blob: 52069b16fa0b82418117d1b03862b45a1cb0e25e [file] [log] [blame]
Daniel Scheller4771d832018-06-19 14:50:09 -04001// SPDX-License-Identifier: GPL-2.0
Daniel Schellerbb4cec92017-07-09 15:42:44 -04002/*
Daniel Scheller2d8c98b2017-10-15 16:51:54 -04003 * ddbridge-max.c: Digital Devices bridge MAX card support
Daniel Schellerbb4cec92017-07-09 15:42:44 -04004 *
5 * Copyright (C) 2010-2017 Digital Devices GmbH
6 * Ralph Metzler <rjkm@metzlerbros.de>
7 * Marcus Metzler <mocm@metzlerbros.de>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 only, as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 */
19
20#include <linux/module.h>
21#include <linux/init.h>
22#include <linux/interrupt.h>
23#include <linux/delay.h>
24#include <linux/slab.h>
25#include <linux/poll.h>
26#include <linux/io.h>
27#include <linux/pci.h>
28#include <linux/pci_ids.h>
29#include <linux/timer.h>
30#include <linux/i2c.h>
31#include <linux/swab.h>
32#include <linux/vmalloc.h>
33
34#include "ddbridge.h"
35#include "ddbridge-regs.h"
36#include "ddbridge-io.h"
Daniel Schellerb4b5b8d2018-04-09 12:47:49 -040037#include "ddbridge-mci.h"
Daniel Schellerbb4cec92017-07-09 15:42:44 -040038
Daniel Scheller2d8c98b2017-10-15 16:51:54 -040039#include "ddbridge-max.h"
Daniel Schellerbb4cec92017-07-09 15:42:44 -040040#include "mxl5xx.h"
41
42/******************************************************************************/
43
44/* MaxS4/8 related modparams */
45static int fmode;
46module_param(fmode, int, 0444);
47MODULE_PARM_DESC(fmode, "frontend emulation mode");
48
49static int fmode_sat = -1;
50module_param(fmode_sat, int, 0444);
51MODULE_PARM_DESC(fmode_sat, "set frontend emulation mode sat");
52
53static int old_quattro;
54module_param(old_quattro, int, 0444);
55MODULE_PARM_DESC(old_quattro, "old quattro LNB input order ");
56
57/******************************************************************************/
58
59static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd)
60{
61 u32 c, v = 0, tag = DDB_LINK_TAG(link);
62
63 v = LNB_TONE & (dev->link[link].lnb.tone << (15 - lnb));
64 ddbwritel(dev, cmd | v, tag | LNB_CONTROL(lnb));
65 for (c = 0; c < 10; c++) {
66 v = ddbreadl(dev, tag | LNB_CONTROL(lnb));
67 if ((v & LNB_BUSY) == 0)
68 break;
69 msleep(20);
70 }
71 if (c == 10)
72 dev_info(dev->dev, "%s lnb = %08x cmd = %08x\n",
Daniel Scheller757d78d2017-10-15 16:51:51 -040073 __func__, lnb, cmd);
Daniel Schellerbb4cec92017-07-09 15:42:44 -040074 return 0;
75}
76
77static int max_send_master_cmd(struct dvb_frontend *fe,
78 struct dvb_diseqc_master_cmd *cmd)
79{
80 struct ddb_input *input = fe->sec_priv;
81 struct ddb_port *port = input->port;
82 struct ddb *dev = port->dev;
83 struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
84 u32 tag = DDB_LINK_TAG(port->lnr);
85 int i;
86 u32 fmode = dev->link[port->lnr].lnb.fmode;
87
88 if (fmode == 2 || fmode == 1)
89 return 0;
90 if (dvb->diseqc_send_master_cmd)
91 dvb->diseqc_send_master_cmd(fe, cmd);
92
93 mutex_lock(&dev->link[port->lnr].lnb.lock);
94 ddbwritel(dev, 0, tag | LNB_BUF_LEVEL(dvb->input));
95 for (i = 0; i < cmd->msg_len; i++)
96 ddbwritel(dev, cmd->msg[i], tag | LNB_BUF_WRITE(dvb->input));
97 lnb_command(dev, port->lnr, dvb->input, LNB_CMD_DISEQC);
98 mutex_unlock(&dev->link[port->lnr].lnb.lock);
99 return 0;
100}
101
102static int lnb_send_diseqc(struct ddb *dev, u32 link, u32 input,
103 struct dvb_diseqc_master_cmd *cmd)
104{
105 u32 tag = DDB_LINK_TAG(link);
106 int i;
107
108 ddbwritel(dev, 0, tag | LNB_BUF_LEVEL(input));
109 for (i = 0; i < cmd->msg_len; i++)
110 ddbwritel(dev, cmd->msg[i], tag | LNB_BUF_WRITE(input));
111 lnb_command(dev, link, input, LNB_CMD_DISEQC);
112 return 0;
113}
114
115static int lnb_set_sat(struct ddb *dev, u32 link, u32 input, u32 sat, u32 band,
116 u32 hor)
117{
118 struct dvb_diseqc_master_cmd cmd = {
119 .msg = {0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00},
120 .msg_len = 4
121 };
122 cmd.msg[3] = 0xf0 | (((sat << 2) & 0x0c) | (band ? 1 : 0) |
123 (hor ? 2 : 0));
124 return lnb_send_diseqc(dev, link, input, &cmd);
125}
126
127static int lnb_set_tone(struct ddb *dev, u32 link, u32 input,
Daniel Scheller757d78d2017-10-15 16:51:51 -0400128 enum fe_sec_tone_mode tone)
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400129{
130 int s = 0;
131 u32 mask = (1ULL << input);
132
133 switch (tone) {
134 case SEC_TONE_OFF:
135 if (!(dev->link[link].lnb.tone & mask))
136 return 0;
137 dev->link[link].lnb.tone &= ~(1ULL << input);
138 break;
139 case SEC_TONE_ON:
140 if (dev->link[link].lnb.tone & mask)
141 return 0;
142 dev->link[link].lnb.tone |= (1ULL << input);
143 break;
144 default:
145 s = -EINVAL;
146 break;
Fengguang Wu0779b882017-08-20 10:17:15 -0400147 }
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400148 if (!s)
149 s = lnb_command(dev, link, input, LNB_CMD_NOP);
150 return s;
151}
152
153static int lnb_set_voltage(struct ddb *dev, u32 link, u32 input,
Daniel Scheller757d78d2017-10-15 16:51:51 -0400154 enum fe_sec_voltage voltage)
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400155{
156 int s = 0;
157
158 if (dev->link[link].lnb.oldvoltage[input] == voltage)
159 return 0;
160 switch (voltage) {
161 case SEC_VOLTAGE_OFF:
162 if (dev->link[link].lnb.voltage[input])
163 return 0;
164 lnb_command(dev, link, input, LNB_CMD_OFF);
165 break;
166 case SEC_VOLTAGE_13:
167 lnb_command(dev, link, input, LNB_CMD_LOW);
168 break;
169 case SEC_VOLTAGE_18:
170 lnb_command(dev, link, input, LNB_CMD_HIGH);
171 break;
172 default:
173 s = -EINVAL;
174 break;
Fengguang Wu0779b882017-08-20 10:17:15 -0400175 }
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400176 dev->link[link].lnb.oldvoltage[input] = voltage;
177 return s;
178}
179
180static int max_set_input_unlocked(struct dvb_frontend *fe, int in)
181{
182 struct ddb_input *input = fe->sec_priv;
183 struct ddb_port *port = input->port;
184 struct ddb *dev = port->dev;
185 struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
186 int res = 0;
187
188 if (in > 3)
189 return -EINVAL;
190 if (dvb->input != in) {
191 u32 bit = (1ULL << input->nr);
Daniel Schellerb9a92f62017-07-09 15:42:45 -0400192 u32 obit =
193 dev->link[port->lnr].lnb.voltage[dvb->input & 3] & bit;
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400194
Daniel Schellerb9a92f62017-07-09 15:42:45 -0400195 dev->link[port->lnr].lnb.voltage[dvb->input & 3] &= ~bit;
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400196 dvb->input = in;
Daniel Schellerb9a92f62017-07-09 15:42:45 -0400197 dev->link[port->lnr].lnb.voltage[dvb->input & 3] |= obit;
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400198 }
199 res = dvb->set_input(fe, in);
200 return res;
201}
202
203static int max_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
204{
205 struct ddb_input *input = fe->sec_priv;
206 struct ddb_port *port = input->port;
207 struct ddb *dev = port->dev;
208 struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
209 int tuner = 0;
210 int res = 0;
211 u32 fmode = dev->link[port->lnr].lnb.fmode;
212
213 mutex_lock(&dev->link[port->lnr].lnb.lock);
214 dvb->tone = tone;
215 switch (fmode) {
216 default:
217 case 0:
218 case 3:
219 res = lnb_set_tone(dev, port->lnr, dvb->input, tone);
220 break;
221 case 1:
222 case 2:
223 if (old_quattro) {
224 if (dvb->tone == SEC_TONE_ON)
225 tuner |= 2;
226 if (dvb->voltage == SEC_VOLTAGE_18)
227 tuner |= 1;
228 } else {
229 if (dvb->tone == SEC_TONE_ON)
230 tuner |= 1;
231 if (dvb->voltage == SEC_VOLTAGE_18)
232 tuner |= 2;
233 }
234 res = max_set_input_unlocked(fe, tuner);
235 break;
236 }
237 mutex_unlock(&dev->link[port->lnr].lnb.lock);
238 return res;
239}
240
241static int max_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage)
242{
243 struct ddb_input *input = fe->sec_priv;
244 struct ddb_port *port = input->port;
245 struct ddb *dev = port->dev;
246 struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
247 int tuner = 0;
248 u32 nv, ov = dev->link[port->lnr].lnb.voltages;
249 int res = 0;
250 u32 fmode = dev->link[port->lnr].lnb.fmode;
251
252 mutex_lock(&dev->link[port->lnr].lnb.lock);
253 dvb->voltage = voltage;
254
255 switch (fmode) {
256 case 3:
257 default:
258 case 0:
259 if (fmode == 3)
260 max_set_input_unlocked(fe, 0);
261 if (voltage == SEC_VOLTAGE_OFF)
262 dev->link[port->lnr].lnb.voltage[dvb->input] &=
263 ~(1ULL << input->nr);
264 else
265 dev->link[port->lnr].lnb.voltage[dvb->input] |=
266 (1ULL << input->nr);
267
268 res = lnb_set_voltage(dev, port->lnr, dvb->input, voltage);
269 break;
270 case 1:
271 case 2:
272 if (voltage == SEC_VOLTAGE_OFF)
273 dev->link[port->lnr].lnb.voltages &=
274 ~(1ULL << input->nr);
275 else
276 dev->link[port->lnr].lnb.voltages |=
277 (1ULL << input->nr);
278
279 nv = dev->link[port->lnr].lnb.voltages;
280
281 if (old_quattro) {
282 if (dvb->tone == SEC_TONE_ON)
283 tuner |= 2;
284 if (dvb->voltage == SEC_VOLTAGE_18)
285 tuner |= 1;
286 } else {
287 if (dvb->tone == SEC_TONE_ON)
288 tuner |= 1;
289 if (dvb->voltage == SEC_VOLTAGE_18)
290 tuner |= 2;
291 }
292 res = max_set_input_unlocked(fe, tuner);
293
294 if (nv != ov) {
295 if (nv) {
Daniel Scheller757d78d2017-10-15 16:51:51 -0400296 lnb_set_voltage(
297 dev, port->lnr,
298 0, SEC_VOLTAGE_13);
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400299 if (fmode == 1) {
Daniel Scheller757d78d2017-10-15 16:51:51 -0400300 lnb_set_voltage(
301 dev, port->lnr,
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400302 0, SEC_VOLTAGE_13);
303 if (old_quattro) {
Daniel Scheller757d78d2017-10-15 16:51:51 -0400304 lnb_set_voltage(
305 dev, port->lnr,
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400306 1, SEC_VOLTAGE_18);
Daniel Scheller757d78d2017-10-15 16:51:51 -0400307 lnb_set_voltage(
308 dev, port->lnr,
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400309 2, SEC_VOLTAGE_13);
310 } else {
Daniel Scheller757d78d2017-10-15 16:51:51 -0400311 lnb_set_voltage(
312 dev, port->lnr,
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400313 1, SEC_VOLTAGE_13);
Daniel Scheller757d78d2017-10-15 16:51:51 -0400314 lnb_set_voltage(
315 dev, port->lnr,
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400316 2, SEC_VOLTAGE_18);
317 }
Daniel Scheller757d78d2017-10-15 16:51:51 -0400318 lnb_set_voltage(
319 dev, port->lnr,
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400320 3, SEC_VOLTAGE_18);
321 }
322 } else {
Daniel Scheller757d78d2017-10-15 16:51:51 -0400323 lnb_set_voltage(
324 dev, port->lnr,
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400325 0, SEC_VOLTAGE_OFF);
326 if (fmode == 1) {
Daniel Scheller757d78d2017-10-15 16:51:51 -0400327 lnb_set_voltage(
328 dev, port->lnr,
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400329 1, SEC_VOLTAGE_OFF);
Daniel Scheller757d78d2017-10-15 16:51:51 -0400330 lnb_set_voltage(
331 dev, port->lnr,
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400332 2, SEC_VOLTAGE_OFF);
Daniel Scheller757d78d2017-10-15 16:51:51 -0400333 lnb_set_voltage(
334 dev, port->lnr,
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400335 3, SEC_VOLTAGE_OFF);
336 }
337 }
338 }
339 break;
340 }
341 mutex_unlock(&dev->link[port->lnr].lnb.lock);
342 return res;
343}
344
345static int max_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
346{
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400347 return 0;
348}
349
350static int max_send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd burst)
351{
352 return 0;
353}
354
355static int mxl_fw_read(void *priv, u8 *buf, u32 len)
356{
357 struct ddb_link *link = priv;
358 struct ddb *dev = link->dev;
359
360 dev_info(dev->dev, "Read mxl_fw from link %u\n", link->nr);
361
362 return ddbridge_flashread(dev, link->nr, buf, 0xc0000, len);
363}
364
Daniel Scheller1c714502017-10-15 16:51:55 -0400365int ddb_lnb_init_fmode(struct ddb *dev, struct ddb_link *link, u32 fm)
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400366{
367 u32 l = link->nr;
368
369 if (link->lnb.fmode == fm)
370 return 0;
371 dev_info(dev->dev, "Set fmode link %u = %u\n", l, fm);
372 mutex_lock(&link->lnb.lock);
373 if (fm == 2 || fm == 1) {
374 if (fmode_sat >= 0) {
375 lnb_set_sat(dev, l, 0, fmode_sat, 0, 0);
376 if (old_quattro) {
377 lnb_set_sat(dev, l, 1, fmode_sat, 0, 1);
378 lnb_set_sat(dev, l, 2, fmode_sat, 1, 0);
379 } else {
380 lnb_set_sat(dev, l, 1, fmode_sat, 1, 0);
381 lnb_set_sat(dev, l, 2, fmode_sat, 0, 1);
382 }
383 lnb_set_sat(dev, l, 3, fmode_sat, 1, 1);
384 }
385 lnb_set_tone(dev, l, 0, SEC_TONE_OFF);
386 if (old_quattro) {
387 lnb_set_tone(dev, l, 1, SEC_TONE_OFF);
388 lnb_set_tone(dev, l, 2, SEC_TONE_ON);
389 } else {
390 lnb_set_tone(dev, l, 1, SEC_TONE_ON);
391 lnb_set_tone(dev, l, 2, SEC_TONE_OFF);
392 }
393 lnb_set_tone(dev, l, 3, SEC_TONE_ON);
394 }
395 link->lnb.fmode = fm;
396 mutex_unlock(&link->lnb.lock);
397 return 0;
398}
399
400static struct mxl5xx_cfg mxl5xx = {
401 .adr = 0x60,
402 .type = 0x01,
403 .clk = 27000000,
404 .ts_clk = 139,
405 .cap = 12,
406 .fw_read = mxl_fw_read,
407};
408
Daniel Scheller1c714502017-10-15 16:51:55 -0400409int ddb_fe_attach_mxl5xx(struct ddb_input *input)
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400410{
411 struct ddb *dev = input->port->dev;
412 struct i2c_adapter *i2c = &input->port->i2c->adap;
413 struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
414 struct ddb_port *port = input->port;
415 struct ddb_link *link = &dev->link[port->lnr];
416 struct mxl5xx_cfg cfg;
417 int demod, tuner;
418
419 cfg = mxl5xx;
420 cfg.fw_priv = link;
421 dvb->set_input = NULL;
422
423 demod = input->nr;
424 tuner = demod & 3;
425 if (fmode == 3)
426 tuner = 0;
427
428 dvb->fe = dvb_attach(mxl5xx_attach, i2c, &cfg,
Daniel Scheller757d78d2017-10-15 16:51:51 -0400429 demod, tuner, &dvb->set_input);
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400430
431 if (!dvb->fe) {
432 dev_err(dev->dev, "No MXL5XX found!\n");
433 return -ENODEV;
434 }
435
436 if (!dvb->set_input) {
437 dev_err(dev->dev, "No mxl5xx_set_input function pointer!\n");
438 return -ENODEV;
439 }
440
441 if (input->nr < 4) {
442 lnb_command(dev, port->lnr, input->nr, LNB_CMD_INIT);
443 lnb_set_voltage(dev, port->lnr, input->nr, SEC_VOLTAGE_OFF);
444 }
Daniel Scheller1c714502017-10-15 16:51:55 -0400445 ddb_lnb_init_fmode(dev, link, fmode);
Daniel Schellerbb4cec92017-07-09 15:42:44 -0400446
447 dvb->fe->ops.set_voltage = max_set_voltage;
448 dvb->fe->ops.enable_high_lnb_voltage = max_enable_high_lnb_voltage;
449 dvb->fe->ops.set_tone = max_set_tone;
450 dvb->diseqc_send_master_cmd = dvb->fe->ops.diseqc_send_master_cmd;
451 dvb->fe->ops.diseqc_send_master_cmd = max_send_master_cmd;
452 dvb->fe->ops.diseqc_send_burst = max_send_burst;
453 dvb->fe->sec_priv = input;
454 dvb->input = tuner;
455 return 0;
456}
Daniel Schellerb4b5b8d2018-04-09 12:47:49 -0400457
458/******************************************************************************/
459/* MAX MCI related functions */
460
Daniel Schellere5526842018-06-23 11:36:11 -0400461int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
Daniel Schellerb4b5b8d2018-04-09 12:47:49 -0400462{
463 struct ddb *dev = input->port->dev;
464 struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
465 struct ddb_port *port = input->port;
466 struct ddb_link *link = &dev->link[port->lnr];
467 int demod, tuner;
Daniel Schellere5526842018-06-23 11:36:11 -0400468 struct mci_cfg cfg;
Daniel Schellerb4b5b8d2018-04-09 12:47:49 -0400469
470 demod = input->nr;
471 tuner = demod & 3;
Daniel Schellere5526842018-06-23 11:36:11 -0400472 switch (type) {
473 case DDB_TUNER_MCI_SX8:
474 cfg = ddb_max_sx8_cfg;
475 if (fmode == 3)
476 tuner = 0;
477 break;
478 default:
479 return -EINVAL;
480 }
481 dvb->fe = ddb_mci_attach(input, &cfg, demod, &dvb->set_input);
Daniel Schellerb4b5b8d2018-04-09 12:47:49 -0400482 if (!dvb->fe) {
Daniel Schellere5526842018-06-23 11:36:11 -0400483 dev_err(dev->dev, "No MCI card found!\n");
Daniel Schellerb4b5b8d2018-04-09 12:47:49 -0400484 return -ENODEV;
485 }
486 if (!dvb->set_input) {
487 dev_err(dev->dev, "No MCI set_input function pointer!\n");
488 return -ENODEV;
489 }
490 if (input->nr < 4) {
491 lnb_command(dev, port->lnr, input->nr, LNB_CMD_INIT);
492 lnb_set_voltage(dev, port->lnr, input->nr, SEC_VOLTAGE_OFF);
493 }
494 ddb_lnb_init_fmode(dev, link, fmode);
495
496 dvb->fe->ops.set_voltage = max_set_voltage;
497 dvb->fe->ops.enable_high_lnb_voltage = max_enable_high_lnb_voltage;
498 dvb->fe->ops.set_tone = max_set_tone;
499 dvb->diseqc_send_master_cmd = dvb->fe->ops.diseqc_send_master_cmd;
500 dvb->fe->ops.diseqc_send_master_cmd = max_send_master_cmd;
501 dvb->fe->ops.diseqc_send_burst = max_send_burst;
502 dvb->fe->sec_priv = input;
503 dvb->input = tuner;
504 return 0;
505}