aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAkihiro Tsukada <tskd08@gmail.com>2014-09-08 13:20:43 -0400
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2014-09-23 16:04:01 -0400
commitf5a98f37a535a43b3a27c6a63b07f23d248e4b31 (patch)
tree5fd5737f9d556ec7134f866997ecef5812f5f251
parentf5d82a75e666a6cc66453285cb3ce28c5d02397a (diff)
[media] pt3: add support for Earthsoft PT3 ISDB-S/T receiver card
This patch adds support for PT3 PCIe cards. PT3 has an FPGA PCIe bridge chip, a TC90522 demod chip and a VA4M6JC2103 tuner module which contains two QM1D1C0042 chips for ISDB-S and two MxL301RF's for ISDB-T. It can receive and deliver 4 (2x ISDB-S, 2x ISDB-T) streams simultaneously, and a kthread is used per stream to poll incoming data, because PT3 does not have interrupts. As an antenna input for each delivery system is split in the tuner module and shared between the corresponding two tuner chips, LNB/LNA controls that the FPGA chip provides are (naturally) shared as well. The tuner chips also share the power line in the tuner module, which is controlled on/off by a GPIO pin of the demod chip. As with the demod chip and the ISDB-T tuner chip, the init sequences/register settings for those chips are not disclosed and stored in a private memory of the FPGA, PT3 driver executes the init of those chips on behalf of their drivers. Signed-off-by: Akihiro Tsukada <tskd08@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
-rw-r--r--drivers/media/pci/Kconfig1
-rw-r--r--drivers/media/pci/Makefile1
-rw-r--r--drivers/media/pci/pt3/Kconfig10
-rw-r--r--drivers/media/pci/pt3/Makefile8
-rw-r--r--drivers/media/pci/pt3/pt3.c877
-rw-r--r--drivers/media/pci/pt3/pt3.h186
-rw-r--r--drivers/media/pci/pt3/pt3_dma.c225
-rw-r--r--drivers/media/pci/pt3/pt3_i2c.c240
8 files changed, 1548 insertions, 0 deletions
diff --git a/drivers/media/pci/Kconfig b/drivers/media/pci/Kconfig
index 933280740176..f8cec8e8cf82 100644
--- a/drivers/media/pci/Kconfig
+++ b/drivers/media/pci/Kconfig
@@ -42,6 +42,7 @@ source "drivers/media/pci/b2c2/Kconfig"
42source "drivers/media/pci/pluto2/Kconfig" 42source "drivers/media/pci/pluto2/Kconfig"
43source "drivers/media/pci/dm1105/Kconfig" 43source "drivers/media/pci/dm1105/Kconfig"
44source "drivers/media/pci/pt1/Kconfig" 44source "drivers/media/pci/pt1/Kconfig"
45source "drivers/media/pci/pt3/Kconfig"
45source "drivers/media/pci/mantis/Kconfig" 46source "drivers/media/pci/mantis/Kconfig"
46source "drivers/media/pci/ngene/Kconfig" 47source "drivers/media/pci/ngene/Kconfig"
47source "drivers/media/pci/ddbridge/Kconfig" 48source "drivers/media/pci/ddbridge/Kconfig"
diff --git a/drivers/media/pci/Makefile b/drivers/media/pci/Makefile
index 73d9c0f11127..a12926e4b51f 100644
--- a/drivers/media/pci/Makefile
+++ b/drivers/media/pci/Makefile
@@ -7,6 +7,7 @@ obj-y += ttpci/ \
7 pluto2/ \ 7 pluto2/ \
8 dm1105/ \ 8 dm1105/ \
9 pt1/ \ 9 pt1/ \
10 pt3/ \
10 mantis/ \ 11 mantis/ \
11 ngene/ \ 12 ngene/ \
12 ddbridge/ \ 13 ddbridge/ \
diff --git a/drivers/media/pci/pt3/Kconfig b/drivers/media/pci/pt3/Kconfig
new file mode 100644
index 000000000000..16c208ae0079
--- /dev/null
+++ b/drivers/media/pci/pt3/Kconfig
@@ -0,0 +1,10 @@
1config DVB_PT3
2 tristate "Earthsoft PT3 cards"
3 depends on DVB_CORE && PCI && I2C
4 select DVB_TC90522 if MEDIA_SUBDRV_AUTOSELECT
5 select MEDIA_TUNER_QM1D1C0042 if MEDIA_SUBDRV_AUTOSELECT
6 select MEDIA_TUNER_MXL301RF if MEDIA_SUBDRV_AUTOSELECT
7 help
8 Support for Earthsoft PT3 PCIe cards.
9
10 Say Y or M if you own such a device and want to use it.
diff --git a/drivers/media/pci/pt3/Makefile b/drivers/media/pci/pt3/Makefile
new file mode 100644
index 000000000000..396f146b1c18
--- /dev/null
+++ b/drivers/media/pci/pt3/Makefile
@@ -0,0 +1,8 @@
1
2earth-pt3-objs += pt3.o pt3_i2c.o pt3_dma.o
3
4obj-$(CONFIG_DVB_PT3) += earth-pt3.o
5
6ccflags-y += -Idrivers/media/dvb-core
7ccflags-y += -Idrivers/media/dvb-frontends
8ccflags-y += -Idrivers/media/tuners
diff --git a/drivers/media/pci/pt3/pt3.c b/drivers/media/pci/pt3/pt3.c
new file mode 100644
index 000000000000..206ede0719b0
--- /dev/null
+++ b/drivers/media/pci/pt3/pt3.c
@@ -0,0 +1,877 @@
1/*
2 * Earthsoft PT3 driver
3 *
4 * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation version 2.
9 *
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/freezer.h>
18#include <linux/kernel.h>
19#include <linux/kthread.h>
20#include <linux/mutex.h>
21#include <linux/module.h>
22#include <linux/pci.h>
23#include <linux/string.h>
24
25#include "dmxdev.h"
26#include "dvbdev.h"
27#include "dvb_demux.h"
28#include "dvb_frontend.h"
29
30#include "pt3.h"
31
32DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
33
34static bool one_adapter;
35module_param(one_adapter, bool, 0444);
36MODULE_PARM_DESC(one_adapter, "Place FE's together under one adapter.");
37
38static int num_bufs = 4;
39module_param(num_bufs, int, 0444);
40MODULE_PARM_DESC(num_bufs, "Number of DMA buffer (188KiB) per FE.");
41
42
43static const struct i2c_algorithm pt3_i2c_algo = {
44 .master_xfer = &pt3_i2c_master_xfer,
45 .functionality = &pt3_i2c_functionality,
46};
47
48static const struct pt3_adap_config adap_conf[PT3_NUM_FE] = {
49 {
50 .demod_info = {
51 I2C_BOARD_INFO(TC90522_I2C_DEV_SAT, 0x11),
52 },
53 .tuner_info = {
54 I2C_BOARD_INFO("qm1d1c0042", 0x63),
55 },
56 .tuner_cfg.qm1d1c0042 = {
57 .lpf = 1,
58 },
59 .init_freq = 1049480 - 300,
60 },
61 {
62 .demod_info = {
63 I2C_BOARD_INFO(TC90522_I2C_DEV_TER, 0x10),
64 },
65 .tuner_info = {
66 I2C_BOARD_INFO("mxl301rf", 0x62),
67 },
68 .init_freq = 515142857,
69 },
70 {
71 .demod_info = {
72 I2C_BOARD_INFO(TC90522_I2C_DEV_SAT, 0x13),
73 },
74 .tuner_info = {
75 I2C_BOARD_INFO("qm1d1c0042", 0x60),
76 },
77 .tuner_cfg.qm1d1c0042 = {
78 .lpf = 1,
79 },
80 .init_freq = 1049480 + 300,
81 },
82 {
83 .demod_info = {
84 I2C_BOARD_INFO(TC90522_I2C_DEV_TER, 0x12),
85 },
86 .tuner_info = {
87 I2C_BOARD_INFO("mxl301rf", 0x61),
88 },
89 .init_freq = 521142857,
90 },
91};
92
93
94struct reg_val {
95 u8 reg;
96 u8 val;
97};
98
99static int
100pt3_demod_write(struct pt3_adapter *adap, const struct reg_val *data, int num)
101{
102 struct i2c_msg msg;
103 int i, ret;
104
105 ret = 0;
106 msg.addr = adap->i2c_demod->addr;
107 msg.flags = 0;
108 msg.len = 2;
109 for (i = 0; i < num; i++) {
110 msg.buf = (u8 *)&data[i];
111 ret = i2c_transfer(adap->i2c_demod->adapter, &msg, 1);
112 if (ret == 0)
113 ret = -EREMOTE;
114 if (ret < 0)
115 return ret;
116 }
117 return 0;
118}
119
120static inline void pt3_lnb_ctrl(struct pt3_board *pt3, bool on)
121{
122 iowrite32((on ? 0x0f : 0x0c), pt3->regs[0] + REG_SYSTEM_W);
123}
124
125static inline struct pt3_adapter *pt3_find_adapter(struct dvb_frontend *fe)
126{
127 struct pt3_board *pt3;
128 int i;
129
130 if (one_adapter) {
131 pt3 = fe->dvb->priv;
132 for (i = 0; i < PT3_NUM_FE; i++)
133 if (pt3->adaps[i]->fe == fe)
134 return pt3->adaps[i];
135 }
136 return container_of(fe->dvb, struct pt3_adapter, dvb_adap);
137}
138
139/*
140 * all 4 tuners in PT3 are packaged in a can module (Sharp VA4M6JC2103).
141 * it seems that they share the power lines and Amp power line and
142 * adaps[3] controls those powers.
143 */
144static int
145pt3_set_tuner_power(struct pt3_board *pt3, bool tuner_on, bool amp_on)
146{
147 struct reg_val rv = { 0x1e, 0x99 };
148
149 if (tuner_on)
150 rv.val |= 0x40;
151 if (amp_on)
152 rv.val |= 0x04;
153 return pt3_demod_write(pt3->adaps[PT3_NUM_FE - 1], &rv, 1);
154}
155
156static int pt3_set_lna(struct dvb_frontend *fe)
157{
158 struct pt3_adapter *adap;
159 struct pt3_board *pt3;
160 u32 val;
161 int ret;
162
163 /* LNA is shared btw. 2 TERR-tuners */
164
165 adap = pt3_find_adapter(fe);
166 val = fe->dtv_property_cache.lna;
167 if (val == LNA_AUTO || val == adap->cur_lna)
168 return 0;
169
170 pt3 = adap->dvb_adap.priv;
171 if (mutex_lock_interruptible(&pt3->lock))
172 return -ERESTARTSYS;
173 if (val)
174 pt3->lna_on_cnt++;
175 else
176 pt3->lna_on_cnt--;
177
178 if (val && pt3->lna_on_cnt <= 1) {
179 pt3->lna_on_cnt = 1;
180 ret = pt3_set_tuner_power(pt3, true, true);
181 } else if (!val && pt3->lna_on_cnt <= 0) {
182 pt3->lna_on_cnt = 0;
183 ret = pt3_set_tuner_power(pt3, true, false);
184 } else
185 ret = 0;
186 mutex_unlock(&pt3->lock);
187 adap->cur_lna = (val != 0);
188 return ret;
189}
190
191static int pt3_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
192{
193 struct pt3_adapter *adap;
194 struct pt3_board *pt3;
195 bool on;
196
197 /* LNB power is shared btw. 2 SAT-tuners */
198
199 adap = pt3_find_adapter(fe);
200 on = (volt != SEC_VOLTAGE_OFF);
201 if (on == adap->cur_lnb)
202 return 0;
203 adap->cur_lnb = on;
204 pt3 = adap->dvb_adap.priv;
205 if (mutex_lock_interruptible(&pt3->lock))
206 return -ERESTARTSYS;
207 if (on)
208 pt3->lnb_on_cnt++;
209 else
210 pt3->lnb_on_cnt--;
211
212 if (on && pt3->lnb_on_cnt <= 1) {
213 pt3->lnb_on_cnt = 1;
214 pt3_lnb_ctrl(pt3, true);
215 } else if (!on && pt3->lnb_on_cnt <= 0) {
216 pt3->lnb_on_cnt = 0;
217 pt3_lnb_ctrl(pt3, false);
218 }
219 mutex_unlock(&pt3->lock);
220 return 0;
221}
222
223/* register values used in pt3_fe_init() */
224
225static const struct reg_val init0_sat[] = {
226 { 0x03, 0x01 },
227 { 0x1e, 0x10 },
228};
229static const struct reg_val init0_ter[] = {
230 { 0x01, 0x40 },
231 { 0x1c, 0x10 },
232};
233static const struct reg_val cfg_sat[] = {
234 { 0x1c, 0x15 },
235 { 0x1f, 0x04 },
236};
237static const struct reg_val cfg_ter[] = {
238 { 0x1d, 0x01 },
239};
240
241/*
242 * pt3_fe_init: initialize demod sub modules and ISDB-T tuners all at once.
243 *
244 * As for demod IC (TC90522) and ISDB-T tuners (MxL301RF),
245 * the i2c sequences for init'ing them are not public and hidden in a ROM,
246 * and include the board specific configurations as well.
247 * They are stored in a lump and cannot be taken out / accessed separately,
248 * thus cannot be moved to the FE/tuner driver.
249 */
250static int pt3_fe_init(struct pt3_board *pt3)
251{
252 int i, ret;
253 struct dvb_frontend *fe;
254
255 pt3_i2c_reset(pt3);
256 ret = pt3_init_all_demods(pt3);
257 if (ret < 0) {
258 dev_warn(&pt3->pdev->dev, "Failed to init demod chips.");
259 return ret;
260 }
261
262 /* additional config? */
263 for (i = 0; i < PT3_NUM_FE; i++) {
264 fe = pt3->adaps[i]->fe;
265
266 if (fe->ops.delsys[0] == SYS_ISDBS)
267 ret = pt3_demod_write(pt3->adaps[i],
268 init0_sat, ARRAY_SIZE(init0_sat));
269 else
270 ret = pt3_demod_write(pt3->adaps[i],
271 init0_ter, ARRAY_SIZE(init0_ter));
272 if (ret < 0) {
273 dev_warn(&pt3->pdev->dev,
274 "demod[%d] faild in init sequence0.", i);
275 return ret;
276 }
277 ret = fe->ops.init(fe);
278 if (ret < 0)
279 return ret;
280 }
281
282 usleep_range(2000, 4000);
283 ret = pt3_set_tuner_power(pt3, true, false);
284 if (ret < 0) {
285 dev_warn(&pt3->pdev->dev, "Failed to control tuner module.");
286 return ret;
287 }
288
289 /* output pin configuration */
290 for (i = 0; i < PT3_NUM_FE; i++) {
291 fe = pt3->adaps[i]->fe;
292 if (fe->ops.delsys[0] == SYS_ISDBS)
293 ret = pt3_demod_write(pt3->adaps[i],
294 cfg_sat, ARRAY_SIZE(cfg_sat));
295 else
296 ret = pt3_demod_write(pt3->adaps[i],
297 cfg_ter, ARRAY_SIZE(cfg_ter));
298 if (ret < 0) {
299 dev_warn(&pt3->pdev->dev,
300 "demod[%d] faild in init sequence1.", i);
301 return ret;
302 }
303 }
304 usleep_range(4000, 6000);
305
306 for (i = 0; i < PT3_NUM_FE; i++) {
307 fe = pt3->adaps[i]->fe;
308 if (fe->ops.delsys[0] != SYS_ISDBS)
309 continue;
310 /* init and wake-up ISDB-S tuners */
311 ret = fe->ops.tuner_ops.init(fe);
312 if (ret < 0) {
313 dev_warn(&pt3->pdev->dev,
314 "Failed to init SAT-tuner[%d].", i);
315 return ret;
316 }
317 }
318 ret = pt3_init_all_mxl301rf(pt3);
319 if (ret < 0) {
320 dev_warn(&pt3->pdev->dev, "Failed to init TERR-tuners.");
321 return ret;
322 }
323
324 ret = pt3_set_tuner_power(pt3, true, true);
325 if (ret < 0) {
326 dev_warn(&pt3->pdev->dev, "Failed to control tuner module.");
327 return ret;
328 }
329
330 /* Wake up all tuners and make an initial tuning,
331 * in order to avoid interference among the tuners in the module,
332 * according to the doc from the manufacturer.
333 */
334 for (i = 0; i < PT3_NUM_FE; i++) {
335 fe = pt3->adaps[i]->fe;
336 ret = 0;
337 if (fe->ops.delsys[0] == SYS_ISDBT)
338 ret = fe->ops.tuner_ops.init(fe);
339 /* set only when called from pt3_probe(), not resume() */
340 if (ret == 0 && fe->dtv_property_cache.frequency == 0) {
341 fe->dtv_property_cache.frequency =
342 adap_conf[i].init_freq;
343 ret = fe->ops.tuner_ops.set_params(fe);
344 }
345 if (ret < 0) {
346 dev_warn(&pt3->pdev->dev,
347 "Failed in initial tuning of tuner[%d].", i);
348 return ret;
349 }
350 }
351
352 /* and sleep again, waiting to be opened by users. */
353 for (i = 0; i < PT3_NUM_FE; i++) {
354 fe = pt3->adaps[i]->fe;
355 if (fe->ops.tuner_ops.sleep)
356 ret = fe->ops.tuner_ops.sleep(fe);
357 if (ret < 0)
358 break;
359 if (fe->ops.sleep)
360 ret = fe->ops.sleep(fe);
361 if (ret < 0)
362 break;
363 if (fe->ops.delsys[0] == SYS_ISDBS)
364 fe->ops.set_voltage = &pt3_set_voltage;
365 else
366 fe->ops.set_lna = &pt3_set_lna;
367 }
368 if (i < PT3_NUM_FE) {
369 dev_warn(&pt3->pdev->dev, "FE[%d] failed to standby.", i);
370 return ret;
371 }
372 return 0;
373}
374
375
376static int pt3_attach_fe(struct pt3_board *pt3, int i)
377{
378 struct i2c_board_info info;
379 struct tc90522_config cfg;
380 struct i2c_client *cl;
381 struct dvb_adapter *dvb_adap;
382 int ret;
383
384 info = adap_conf[i].demod_info;
385 cfg = adap_conf[i].demod_cfg;
386 cfg.tuner_i2c = NULL;
387 info.platform_data = &cfg;
388
389 ret = -ENODEV;
390 request_module("tc90522");
391 cl = i2c_new_device(&pt3->i2c_adap, &info);
392 if (!cl || !cl->dev.driver)
393 return -ENODEV;
394 pt3->adaps[i]->i2c_demod = cl;
395 if (!try_module_get(cl->dev.driver->owner))
396 goto err_demod;
397
398 if (!strncmp(cl->name, TC90522_I2C_DEV_SAT, sizeof(cl->name))) {
399 struct qm1d1c0042_config tcfg;
400
401 tcfg = adap_conf[i].tuner_cfg.qm1d1c0042;
402 tcfg.fe = cfg.fe;
403 info = adap_conf[i].tuner_info;
404 info.platform_data = &tcfg;
405 request_module("qm1d1c0042");
406 cl = i2c_new_device(cfg.tuner_i2c, &info);
407 } else {
408 struct mxl301rf_config tcfg;
409
410 tcfg = adap_conf[i].tuner_cfg.mxl301rf;
411 tcfg.fe = cfg.fe;
412 info = adap_conf[i].tuner_info;
413 info.platform_data = &tcfg;
414 request_module("mxl301rf");
415 cl = i2c_new_device(cfg.tuner_i2c, &info);
416 }
417 if (!cl || !cl->dev.driver)
418 goto err_demod;
419 pt3->adaps[i]->i2c_tuner = cl;
420 if (!try_module_get(cl->dev.driver->owner))
421 goto err_tuner;
422
423 dvb_adap = &pt3->adaps[one_adapter ? 0 : i]->dvb_adap;
424 ret = dvb_register_frontend(dvb_adap, cfg.fe);
425 if (ret < 0)
426 goto err_tuner;
427 pt3->adaps[i]->fe = cfg.fe;
428 return 0;
429
430err_tuner:
431 i2c_unregister_device(pt3->adaps[i]->i2c_tuner);
432 if (pt3->adaps[i]->i2c_tuner->dev.driver->owner &&
433 module_is_live(pt3->adaps[i]->i2c_tuner->dev.driver->owner))
434 module_put(pt3->adaps[i]->i2c_tuner->dev.driver->owner);
435err_demod:
436 i2c_unregister_device(pt3->adaps[i]->i2c_demod);
437 if (pt3->adaps[i]->i2c_demod->dev.driver->owner &&
438 module_is_live(pt3->adaps[i]->i2c_demod->dev.driver->owner))
439 module_put(pt3->adaps[i]->i2c_demod->dev.driver->owner);
440 return ret;
441}
442
443
444static int pt3_fetch_thread(void *data)
445{
446 struct pt3_adapter *adap = data;
447 ktime_t delay;
448 bool was_frozen;
449
450#define PT3_INITIAL_BUF_DROPS 4
451#define PT3_FETCH_DELAY 10
452#define PT3_FETCH_DELAY_DELTA 2
453
454 pt3_init_dmabuf(adap);
455 adap->num_discard = PT3_INITIAL_BUF_DROPS;
456
457 dev_dbg(adap->dvb_adap.device,
458 "PT3: [%s] started.\n", adap->thread->comm);
459 set_freezable();
460 while (!kthread_freezable_should_stop(&was_frozen)) {
461 if (was_frozen)
462 adap->num_discard = PT3_INITIAL_BUF_DROPS;
463
464 pt3_proc_dma(adap);
465
466 delay = ktime_set(0, PT3_FETCH_DELAY * NSEC_PER_MSEC);
467 set_current_state(TASK_UNINTERRUPTIBLE);
468 freezable_schedule_hrtimeout_range(&delay,
469 PT3_FETCH_DELAY_DELTA * NSEC_PER_MSEC,
470 HRTIMER_MODE_REL);
471 }
472 dev_dbg(adap->dvb_adap.device,
473 "PT3: [%s] exited.\n", adap->thread->comm);
474 adap->thread = NULL;
475 return 0;
476}
477
478static int pt3_start_streaming(struct pt3_adapter *adap)
479{
480 struct task_struct *thread;
481
482 /* start fetching thread */
483 thread = kthread_run(pt3_fetch_thread, adap, "pt3-ad%i-dmx%i",
484 adap->dvb_adap.num, adap->dmxdev.dvbdev->id);
485 if (IS_ERR(thread)) {
486 int ret = PTR_ERR(thread);
487
488 dev_warn(adap->dvb_adap.device,
489 "PT3 (adap:%d, dmx:%d): failed to start kthread.\n",
490 adap->dvb_adap.num, adap->dmxdev.dvbdev->id);
491 return ret;
492 }
493 adap->thread = thread;
494
495 return pt3_start_dma(adap);
496}
497
498static int pt3_stop_streaming(struct pt3_adapter *adap)
499{
500 int ret;
501
502 ret = pt3_stop_dma(adap);
503 if (ret)
504 dev_warn(adap->dvb_adap.device,
505 "PT3: failed to stop streaming of adap:%d/FE:%d\n",
506 adap->dvb_adap.num, adap->fe->id);
507
508 /* kill the fetching thread */
509 ret = kthread_stop(adap->thread);
510 return ret;
511}
512
513static int pt3_start_feed(struct dvb_demux_feed *feed)
514{
515 struct pt3_adapter *adap;
516
517 if (signal_pending(current))
518 return -EINTR;
519
520 adap = container_of(feed->demux, struct pt3_adapter, demux);
521 adap->num_feeds++;
522 if (adap->thread)
523 return 0;
524 if (adap->num_feeds != 1) {
525 dev_warn(adap->dvb_adap.device,
526 "%s: unmatched start/stop_feed in adap:%i/dmx:%i.\n",
527 __func__, adap->dvb_adap.num, adap->dmxdev.dvbdev->id);
528 adap->num_feeds = 1;
529 }
530
531 return pt3_start_streaming(adap);
532
533}
534
535static int pt3_stop_feed(struct dvb_demux_feed *feed)
536{
537 struct pt3_adapter *adap;
538
539 adap = container_of(feed->demux, struct pt3_adapter, demux);
540
541 adap->num_feeds--;
542 if (adap->num_feeds > 0 || !adap->thread)
543 return 0;
544 adap->num_feeds = 0;
545
546 return pt3_stop_streaming(adap);
547}
548
549
550static int pt3_alloc_adapter(struct pt3_board *pt3, int index)
551{
552 int ret;
553 struct pt3_adapter *adap;
554 struct dvb_adapter *da;
555
556 adap = kzalloc(sizeof(*adap), GFP_KERNEL);
557 if (!adap) {
558 dev_err(&pt3->pdev->dev, "failed to alloc mem for adapter.\n");
559 return -ENOMEM;
560 }
561 pt3->adaps[index] = adap;
562 adap->adap_idx = index;
563
564 if (index == 0 || !one_adapter) {
565 ret = dvb_register_adapter(&adap->dvb_adap, "PT3 DVB",
566 THIS_MODULE, &pt3->pdev->dev, adapter_nr);
567 if (ret < 0) {
568 dev_err(&pt3->pdev->dev,
569 "failed to register adapter dev.\n");
570 goto err_mem;
571 }
572 da = &adap->dvb_adap;
573 } else
574 da = &pt3->adaps[0]->dvb_adap;
575
576 adap->dvb_adap.priv = pt3;
577 adap->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
578 adap->demux.priv = adap;
579 adap->demux.feednum = 256;
580 adap->demux.filternum = 256;
581 adap->demux.start_feed = pt3_start_feed;
582 adap->demux.stop_feed = pt3_stop_feed;
583 ret = dvb_dmx_init(&adap->demux);
584 if (ret < 0) {
585 dev_err(&pt3->pdev->dev, "failed to init dmx dev.\n");
586 goto err_adap;
587 }
588
589 adap->dmxdev.filternum = 256;
590 adap->dmxdev.demux = &adap->demux.dmx;
591 ret = dvb_dmxdev_init(&adap->dmxdev, da);
592 if (ret < 0) {
593 dev_err(&pt3->pdev->dev, "failed to init dmxdev.\n");
594 goto err_demux;
595 }
596
597 ret = pt3_alloc_dmabuf(adap);
598 if (ret) {
599 dev_err(&pt3->pdev->dev, "failed to alloc DMA buffers.\n");
600 goto err_dmabuf;
601 }
602
603 return 0;
604
605err_dmabuf:
606 pt3_free_dmabuf(adap);
607 dvb_dmxdev_release(&adap->dmxdev);
608err_demux:
609 dvb_dmx_release(&adap->demux);
610err_adap:
611 if (index == 0 || !one_adapter)
612 dvb_unregister_adapter(da);
613err_mem:
614 kfree(adap);
615 pt3->adaps[index] = NULL;
616 return ret;
617}
618
619static void pt3_cleanup_adapter(struct pt3_board *pt3, int index)
620{
621 struct pt3_adapter *adap;
622 struct dmx_demux *dmx;
623
624 adap = pt3->adaps[index];
625 if (adap == NULL)
626 return;
627
628 /* stop demux kthread */
629 if (adap->thread)
630 pt3_stop_streaming(adap);
631
632 dmx = &adap->demux.dmx;
633 dmx->close(dmx);
634 if (adap->fe) {
635 adap->fe->callback = NULL;
636 if (adap->fe->frontend_priv)
637 dvb_unregister_frontend(adap->fe);
638 if (adap->i2c_tuner) {
639 module_put(adap->i2c_tuner->dev.driver->owner);
640 i2c_unregister_device(adap->i2c_tuner);
641 }
642 if (adap->i2c_demod) {
643 module_put(adap->i2c_demod->dev.driver->owner);
644 i2c_unregister_device(adap->i2c_demod);
645 }
646 }
647 pt3_free_dmabuf(adap);
648 dvb_dmxdev_release(&adap->dmxdev);
649 dvb_dmx_release(&adap->demux);
650 if (index == 0 || !one_adapter)
651 dvb_unregister_adapter(&adap->dvb_adap);
652 kfree(adap);
653 pt3->adaps[index] = NULL;
654}
655
656#ifdef CONFIG_PM_SLEEP
657
658static int pt3_suspend(struct device *dev)
659{
660 struct pci_dev *pdev = to_pci_dev(dev);
661 struct pt3_board *pt3 = pci_get_drvdata(pdev);
662 int i;
663 struct pt3_adapter *adap;
664
665 for (i = 0; i < PT3_NUM_FE; i++) {
666 adap = pt3->adaps[i];
667 if (adap->num_feeds > 0)
668 pt3_stop_dma(adap);
669 dvb_frontend_suspend(adap->fe);
670 pt3_free_dmabuf(adap);
671 }
672
673 pt3_lnb_ctrl(pt3, false);
674 pt3_set_tuner_power(pt3, false, false);
675 return 0;
676}
677
678static int pt3_resume(struct device *dev)
679{
680 struct pci_dev *pdev = to_pci_dev(dev);
681 struct pt3_board *pt3 = pci_get_drvdata(pdev);
682 int i, ret;
683 struct pt3_adapter *adap;
684
685 ret = pt3_fe_init(pt3);
686 if (ret)
687 return ret;
688
689 if (pt3->lna_on_cnt > 0)
690 pt3_set_tuner_power(pt3, true, true);
691 if (pt3->lnb_on_cnt > 0)
692 pt3_lnb_ctrl(pt3, true);
693
694 for (i = 0; i < PT3_NUM_FE; i++) {
695 adap = pt3->adaps[i];
696 dvb_frontend_resume(adap->fe);
697 ret = pt3_alloc_dmabuf(adap);
698 if (ret) {
699 dev_err(&pt3->pdev->dev, "failed to alloc DMA bufs.\n");
700 continue;
701 }
702 if (adap->num_feeds > 0)
703 pt3_start_dma(adap);
704 }
705
706 return 0;
707}
708
709#endif /* CONFIG_PM_SLEEP */
710
711
712static void pt3_remove(struct pci_dev *pdev)
713{
714 struct pt3_board *pt3;
715 int i;
716
717 pt3 = pci_get_drvdata(pdev);
718 for (i = PT3_NUM_FE - 1; i >= 0; i--)
719 pt3_cleanup_adapter(pt3, i);
720 i2c_del_adapter(&pt3->i2c_adap);
721 kfree(pt3->i2c_buf);
722 pci_iounmap(pt3->pdev, pt3->regs[0]);
723 pci_iounmap(pt3->pdev, pt3->regs[1]);
724 pci_release_regions(pdev);
725 pci_disable_device(pdev);
726 kfree(pt3);
727}
728
729static int pt3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
730{
731 u8 rev;
732 u32 ver;
733 int i, ret;
734 struct pt3_board *pt3;
735 struct i2c_adapter *i2c;
736
737 if (pci_read_config_byte(pdev, PCI_REVISION_ID, &rev) || rev != 1)
738 return -ENODEV;
739
740 ret = pci_enable_device(pdev);
741 if (ret < 0)
742 return -ENODEV;
743 pci_set_master(pdev);
744
745 ret = pci_request_regions(pdev, DRV_NAME);
746 if (ret < 0)
747 goto err_disable_device;
748
749 ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
750 if (ret == 0)
751 dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
752 else {
753 ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
754 if (ret == 0)
755 dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
756 else {
757 dev_err(&pdev->dev, "Failed to set DMA mask.\n");
758 goto err_release_regions;
759 }
760 dev_info(&pdev->dev, "Use 32bit DMA.\n");
761 }
762
763 pt3 = kzalloc(sizeof(*pt3), GFP_KERNEL);
764 if (!pt3) {
765 dev_err(&pdev->dev, "Failed to alloc mem for this dev.\n");
766 ret = -ENOMEM;
767 goto err_release_regions;
768 }
769 pci_set_drvdata(pdev, pt3);
770 pt3->pdev = pdev;
771 mutex_init(&pt3->lock);
772 pt3->regs[0] = pci_ioremap_bar(pdev, 0);
773 pt3->regs[1] = pci_ioremap_bar(pdev, 2);
774 if (pt3->regs[0] == NULL || pt3->regs[1] == NULL) {
775 dev_err(&pdev->dev, "Failed to ioremap.\n");
776 ret = -ENOMEM;
777 goto err_kfree;
778 }
779
780 ver = ioread32(pt3->regs[0] + REG_VERSION);
781 if ((ver >> 16) != 0x0301) {
782 dev_warn(&pdev->dev, "PT%d, I/F-ver.:%d not supported",
783 ver >> 24, (ver & 0x00ff0000) >> 16);
784 ret = -ENODEV;
785 goto err_iounmap;
786 }
787
788 pt3->num_bufs = clamp_val(num_bufs, MIN_DATA_BUFS, MAX_DATA_BUFS);
789
790 pt3->i2c_buf = kmalloc(sizeof(*pt3->i2c_buf), GFP_KERNEL);
791 if (pt3->i2c_buf == NULL) {
792 dev_err(&pdev->dev, "Failed to alloc mem for i2c.\n");
793 ret = -ENOMEM;
794 goto err_iounmap;
795 }
796 i2c = &pt3->i2c_adap;
797 i2c->owner = THIS_MODULE;
798 i2c->algo = &pt3_i2c_algo;
799 i2c->algo_data = NULL;
800 i2c->dev.parent = &pdev->dev;
801 strlcpy(i2c->name, DRV_NAME, sizeof(i2c->name));
802 i2c_set_adapdata(i2c, pt3);
803 ret = i2c_add_adapter(i2c);
804 if (ret < 0) {
805 dev_err(&pdev->dev, "Failed to add i2c adapter.\n");
806 goto err_i2cbuf;
807 }
808
809 for (i = 0; i < PT3_NUM_FE; i++) {
810 ret = pt3_alloc_adapter(pt3, i);
811 if (ret < 0)
812 break;
813
814 ret = pt3_attach_fe(pt3, i);
815 if (ret < 0)
816 break;
817 }
818 if (i < PT3_NUM_FE) {
819 dev_err(&pdev->dev, "Failed to create FE%d.\n", i);
820 goto err_cleanup_adapters;
821 }
822
823 ret = pt3_fe_init(pt3);
824 if (ret < 0) {
825 dev_err(&pdev->dev, "Failed to init frontends.\n");
826 i = PT3_NUM_FE - 1;
827 goto err_cleanup_adapters;
828 }
829
830 dev_info(&pdev->dev,
831 "successfully init'ed PT%d (fw:0x%02x, I/F:0x%02x).\n",
832 ver >> 24, (ver >> 8) & 0xff, (ver >> 16) & 0xff);
833 return 0;
834
835err_cleanup_adapters:
836 while (i >= 0)
837 pt3_cleanup_adapter(pt3, i--);
838 i2c_del_adapter(i2c);
839err_i2cbuf:
840 kfree(pt3->i2c_buf);
841err_iounmap:
842 if (pt3->regs[0])
843 pci_iounmap(pdev, pt3->regs[0]);
844 if (pt3->regs[1])
845 pci_iounmap(pdev, pt3->regs[1]);
846err_kfree:
847 kfree(pt3);
848err_release_regions:
849 pci_release_regions(pdev);
850err_disable_device:
851 pci_disable_device(pdev);
852 return ret;
853
854}
855
856static const struct pci_device_id pt3_id_table[] = {
857 { PCI_DEVICE_SUB(0x1172, 0x4c15, 0xee8d, 0x0368) },
858 { },
859};
860MODULE_DEVICE_TABLE(pci, pt3_id_table);
861
862SIMPLE_DEV_PM_OPS(pt3_pm_ops, pt3_suspend, pt3_resume);
863
864static struct pci_driver pt3_driver = {
865 .name = DRV_NAME,
866 .probe = pt3_probe,
867 .remove = pt3_remove,
868 .id_table = pt3_id_table,
869
870 .driver.pm = &pt3_pm_ops,
871};
872
873module_pci_driver(pt3_driver);
874
875MODULE_DESCRIPTION("Earthsoft PT3 Driver");
876MODULE_AUTHOR("Akihiro TSUKADA");
877MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/pt3/pt3.h b/drivers/media/pci/pt3/pt3.h
new file mode 100644
index 000000000000..1b3f2ad25db3
--- /dev/null
+++ b/drivers/media/pci/pt3/pt3.h
@@ -0,0 +1,186 @@
1/*
2 * Earthsoft PT3 driver
3 *
4 * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation version 2.
9 *
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#ifndef PT3_H
18#define PT3_H
19
20#include <linux/atomic.h>
21#include <linux/types.h>
22
23#include "dvb_demux.h"
24#include "dvb_frontend.h"
25#include "dmxdev.h"
26
27#include "tc90522.h"
28#include "mxl301rf.h"
29#include "qm1d1c0042.h"
30
31#define DRV_NAME KBUILD_MODNAME
32
33#define PT3_NUM_FE 4
34
35/*
36 * register index of the FPGA chip
37 */
38#define REG_VERSION 0x00
39#define REG_BUS 0x04
40#define REG_SYSTEM_W 0x08
41#define REG_SYSTEM_R 0x0c
42#define REG_I2C_W 0x10
43#define REG_I2C_R 0x14
44#define REG_RAM_W 0x18
45#define REG_RAM_R 0x1c
46#define REG_DMA_BASE 0x40 /* regs for FE[i] = REG_DMA_BASE + 0x18 * i */
47#define OFST_DMA_DESC_L 0x00
48#define OFST_DMA_DESC_H 0x04
49#define OFST_DMA_CTL 0x08
50#define OFST_TS_CTL 0x0c
51#define OFST_STATUS 0x10
52#define OFST_TS_ERR 0x14
53
54/*
55 * internal buffer for I2C
56 */
57#define PT3_I2C_MAX 4091
58struct pt3_i2cbuf {
59 u8 data[PT3_I2C_MAX];
60 u8 tmp;
61 u32 num_cmds;
62};
63
64/*
65 * DMA things
66 */
67#define TS_PACKET_SZ 188
68/* DMA transfers must not cross 4GiB, so use one page / transfer */
69#define DATA_XFER_SZ 4096
70#define DATA_BUF_XFERS 47
71/* (num_bufs * DATA_BUF_SZ) % TS_PACKET_SZ must be 0 */
72#define DATA_BUF_SZ (DATA_BUF_XFERS * DATA_XFER_SZ)
73#define MAX_DATA_BUFS 16
74#define MIN_DATA_BUFS 2
75
76#define DESCS_IN_PAGE (PAGE_SIZE / sizeof(struct xfer_desc))
77#define MAX_NUM_XFERS (MAX_DATA_BUFS * DATA_BUF_XFERS)
78#define MAX_DESC_BUFS DIV_ROUND_UP(MAX_NUM_XFERS, DESCS_IN_PAGE)
79
80/* DMA transfer description.
81 * device is passed a pointer to this struct, dma-reads it,
82 * and gets the DMA buffer ring for storing TS data.
83 */
84struct xfer_desc {
85 u32 addr_l; /* bus address of target data buffer */
86 u32 addr_h;
87 u32 size;
88 u32 next_l; /* bus adddress of the next xfer_desc */
89 u32 next_h;
90};
91
92/* A DMA mapping of a page containing xfer_desc's */
93struct xfer_desc_buffer {
94 dma_addr_t b_addr;
95 struct xfer_desc *descs; /* PAGE_SIZE (xfer_desc[DESCS_IN_PAGE]) */
96};
97
98/* A DMA mapping of a data buffer */
99struct dma_data_buffer {
100 dma_addr_t b_addr;
101 u8 *data; /* size: u8[PAGE_SIZE] */
102};
103
104/*
105 * device things
106 */
107struct pt3_adap_config {
108 struct i2c_board_info demod_info;
109 struct tc90522_config demod_cfg;
110
111 struct i2c_board_info tuner_info;
112 union tuner_config {
113 struct qm1d1c0042_config qm1d1c0042;
114 struct mxl301rf_config mxl301rf;
115 } tuner_cfg;
116 u32 init_freq;
117};
118
119struct pt3_adapter {
120 struct dvb_adapter dvb_adap; /* dvb_adap.priv => struct pt3_board */
121 int adap_idx;
122
123 struct dvb_demux demux;
124 struct dmxdev dmxdev;
125 struct dvb_frontend *fe;
126 struct i2c_client *i2c_demod;
127 struct i2c_client *i2c_tuner;
128
129 /* data fetch thread */
130 struct task_struct *thread;
131 int num_feeds;
132
133 bool cur_lna;
134 bool cur_lnb; /* current LNB power status (on/off) */
135
136 /* items below are for DMA */
137 struct dma_data_buffer buffer[MAX_DATA_BUFS];
138 int buf_idx;
139 int buf_ofs;
140 int num_bufs; /* == pt3_board->num_bufs */
141 int num_discard; /* how many access units to discard initially */
142
143 struct xfer_desc_buffer desc_buf[MAX_DESC_BUFS];
144 int num_desc_bufs; /* == num_bufs * DATA_BUF_XFERS / DESCS_IN_PAGE */
145};
146
147
148struct pt3_board {
149 struct pci_dev *pdev;
150 void __iomem *regs[2];
151 /* regs[0]: registers, regs[1]: internal memory, used for I2C */
152
153 struct mutex lock;
154
155 /* LNB power shared among sat-FEs */
156 int lnb_on_cnt; /* LNB power on count */
157
158 /* LNA shared among terr-FEs */
159 int lna_on_cnt; /* booster enabled count */
160
161 int num_bufs; /* number of DMA buffers allocated/mapped per FE */
162
163 struct i2c_adapter i2c_adap;
164 struct pt3_i2cbuf *i2c_buf;
165
166 struct pt3_adapter *adaps[PT3_NUM_FE];
167};
168
169
170/*
171 * prototypes
172 */
173extern int pt3_alloc_dmabuf(struct pt3_adapter *adap);
174extern void pt3_init_dmabuf(struct pt3_adapter *adap);
175extern void pt3_free_dmabuf(struct pt3_adapter *adap);
176extern int pt3_start_dma(struct pt3_adapter *adap);
177extern int pt3_stop_dma(struct pt3_adapter *adap);
178extern int pt3_proc_dma(struct pt3_adapter *adap);
179
180extern int pt3_i2c_master_xfer(struct i2c_adapter *adap,
181 struct i2c_msg *msgs, int num);
182extern u32 pt3_i2c_functionality(struct i2c_adapter *adap);
183extern void pt3_i2c_reset(struct pt3_board *pt3);
184extern int pt3_init_all_demods(struct pt3_board *pt3);
185extern int pt3_init_all_mxl301rf(struct pt3_board *pt3);
186#endif /* PT3_H */
diff --git a/drivers/media/pci/pt3/pt3_dma.c b/drivers/media/pci/pt3/pt3_dma.c
new file mode 100644
index 000000000000..f0ce90437fac
--- /dev/null
+++ b/drivers/media/pci/pt3/pt3_dma.c
@@ -0,0 +1,225 @@
1/*
2 * Earthsoft PT3 driver
3 *
4 * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation version 2.
9 *
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16#include <linux/dma-mapping.h>
17#include <linux/kernel.h>
18#include <linux/pci.h>
19
20#include "pt3.h"
21
22#define PT3_ACCESS_UNIT (TS_PACKET_SZ * 128)
23#define PT3_BUF_CANARY (0x74)
24
25static u32 get_dma_base(int idx)
26{
27 int i;
28
29 i = (idx == 1 || idx == 2) ? 3 - idx : idx;
30 return REG_DMA_BASE + 0x18 * i;
31}
32
33int pt3_stop_dma(struct pt3_adapter *adap)
34{
35 struct pt3_board *pt3 = adap->dvb_adap.priv;
36 u32 base;
37 u32 stat;
38 int retry;
39
40 base = get_dma_base(adap->adap_idx);
41 stat = ioread32(pt3->regs[0] + base + OFST_STATUS);
42 if (!(stat & 0x01))
43 return 0;
44
45 iowrite32(0x02, pt3->regs[0] + base + OFST_DMA_CTL);
46 for (retry = 0; retry < 5; retry++) {
47 stat = ioread32(pt3->regs[0] + base + OFST_STATUS);
48 if (!(stat & 0x01))
49 return 0;
50 msleep(50);
51 }
52 return -EIO;
53}
54
55int pt3_start_dma(struct pt3_adapter *adap)
56{
57 struct pt3_board *pt3 = adap->dvb_adap.priv;
58 u32 base = get_dma_base(adap->adap_idx);
59
60 iowrite32(0x02, pt3->regs[0] + base + OFST_DMA_CTL);
61 iowrite32(lower_32_bits(adap->desc_buf[0].b_addr),
62 pt3->regs[0] + base + OFST_DMA_DESC_L);
63 iowrite32(upper_32_bits(adap->desc_buf[0].b_addr),
64 pt3->regs[0] + base + OFST_DMA_DESC_H);
65 iowrite32(0x01, pt3->regs[0] + base + OFST_DMA_CTL);
66 return 0;
67}
68
69
70static u8 *next_unit(struct pt3_adapter *adap, int *idx, int *ofs)
71{
72 *ofs += PT3_ACCESS_UNIT;
73 if (*ofs >= DATA_BUF_SZ) {
74 *ofs -= DATA_BUF_SZ;
75 (*idx)++;
76 if (*idx == adap->num_bufs)
77 *idx = 0;
78 }
79 return &adap->buffer[*idx].data[*ofs];
80}
81
82int pt3_proc_dma(struct pt3_adapter *adap)
83{
84 int idx, ofs;
85
86 idx = adap->buf_idx;
87 ofs = adap->buf_ofs;
88
89 if (adap->buffer[idx].data[ofs] == PT3_BUF_CANARY)
90 return 0;
91
92 while (*next_unit(adap, &idx, &ofs) != PT3_BUF_CANARY) {
93 u8 *p;
94
95 p = &adap->buffer[adap->buf_idx].data[adap->buf_ofs];
96 if (adap->num_discard > 0)
97 adap->num_discard--;
98 else if (adap->buf_ofs + PT3_ACCESS_UNIT > DATA_BUF_SZ) {
99 dvb_dmx_swfilter_packets(&adap->demux, p,
100 (DATA_BUF_SZ - adap->buf_ofs) / TS_PACKET_SZ);
101 dvb_dmx_swfilter_packets(&adap->demux,
102 adap->buffer[idx].data, ofs / TS_PACKET_SZ);
103 } else
104 dvb_dmx_swfilter_packets(&adap->demux, p,
105 PT3_ACCESS_UNIT / TS_PACKET_SZ);
106
107 *p = PT3_BUF_CANARY;
108 adap->buf_idx = idx;
109 adap->buf_ofs = ofs;
110 }
111 return 0;
112}
113
114void pt3_init_dmabuf(struct pt3_adapter *adap)
115{
116 int idx, ofs;
117 u8 *p;
118
119 idx = 0;
120 ofs = 0;
121 p = adap->buffer[0].data;
122 /* mark the whole buffers as "not written yet" */
123 while (idx < adap->num_bufs) {
124 p[ofs] = PT3_BUF_CANARY;
125 ofs += PT3_ACCESS_UNIT;
126 if (ofs >= DATA_BUF_SZ) {
127 ofs -= DATA_BUF_SZ;
128 idx++;
129 p = adap->buffer[idx].data;
130 }
131 }
132 adap->buf_idx = 0;
133 adap->buf_ofs = 0;
134}
135
136void pt3_free_dmabuf(struct pt3_adapter *adap)
137{
138 struct pt3_board *pt3;
139 int i;
140
141 pt3 = adap->dvb_adap.priv;
142 for (i = 0; i < adap->num_bufs; i++)
143 dma_free_coherent(&pt3->pdev->dev, DATA_BUF_SZ,
144 adap->buffer[i].data, adap->buffer[i].b_addr);
145 adap->num_bufs = 0;
146
147 for (i = 0; i < adap->num_desc_bufs; i++)
148 dma_free_coherent(&pt3->pdev->dev, PAGE_SIZE,
149 adap->desc_buf[i].descs, adap->desc_buf[i].b_addr);
150 adap->num_desc_bufs = 0;
151}
152
153
154int pt3_alloc_dmabuf(struct pt3_adapter *adap)
155{
156 struct pt3_board *pt3;
157 void *p;
158 int i, j;
159 int idx, ofs;
160 int num_desc_bufs;
161 dma_addr_t data_addr, desc_addr;
162 struct xfer_desc *d;
163
164 pt3 = adap->dvb_adap.priv;
165 adap->num_bufs = 0;
166 adap->num_desc_bufs = 0;
167 for (i = 0; i < pt3->num_bufs; i++) {
168 p = dma_alloc_coherent(&pt3->pdev->dev, DATA_BUF_SZ,
169 &adap->buffer[i].b_addr, GFP_KERNEL);
170 if (p == NULL)
171 goto failed;
172 adap->buffer[i].data = p;
173 adap->num_bufs++;
174 }
175 pt3_init_dmabuf(adap);
176
177 /* build circular-linked pointers (xfer_desc) to the data buffers*/
178 idx = 0;
179 ofs = 0;
180 num_desc_bufs =
181 DIV_ROUND_UP(adap->num_bufs * DATA_BUF_XFERS, DESCS_IN_PAGE);
182 for (i = 0; i < num_desc_bufs; i++) {
183 p = dma_alloc_coherent(&pt3->pdev->dev, PAGE_SIZE,
184 &desc_addr, GFP_KERNEL);
185 if (p == NULL)
186 goto failed;
187 adap->num_desc_bufs++;
188 adap->desc_buf[i].descs = p;
189 adap->desc_buf[i].b_addr = desc_addr;
190
191 if (i > 0) {
192 d = &adap->desc_buf[i - 1].descs[DESCS_IN_PAGE - 1];
193 d->next_l = lower_32_bits(desc_addr);
194 d->next_h = upper_32_bits(desc_addr);
195 }
196 for (j = 0; j < DESCS_IN_PAGE; j++) {
197 data_addr = adap->buffer[idx].b_addr + ofs;
198 d = &adap->desc_buf[i].descs[j];
199 d->addr_l = lower_32_bits(data_addr);
200 d->addr_h = upper_32_bits(data_addr);
201 d->size = DATA_XFER_SZ;
202
203 desc_addr += sizeof(struct xfer_desc);
204 d->next_l = lower_32_bits(desc_addr);
205 d->next_h = upper_32_bits(desc_addr);
206
207 ofs += DATA_XFER_SZ;
208 if (ofs >= DATA_BUF_SZ) {
209 ofs -= DATA_BUF_SZ;
210 idx++;
211 if (idx >= adap->num_bufs) {
212 desc_addr = adap->desc_buf[0].b_addr;
213 d->next_l = lower_32_bits(desc_addr);
214 d->next_h = upper_32_bits(desc_addr);
215 return 0;
216 }
217 }
218 }
219 }
220 return 0;
221
222failed:
223 pt3_free_dmabuf(adap);
224 return -ENOMEM;
225}
diff --git a/drivers/media/pci/pt3/pt3_i2c.c b/drivers/media/pci/pt3/pt3_i2c.c
new file mode 100644
index 000000000000..ec6a8a2e4744
--- /dev/null
+++ b/drivers/media/pci/pt3/pt3_i2c.c
@@ -0,0 +1,240 @@
1/*
2 * Earthsoft PT3 driver
3 *
4 * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation version 2.
9 *
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16#include <linux/delay.h>
17#include <linux/device.h>
18#include <linux/i2c.h>
19#include <linux/io.h>
20#include <linux/pci.h>
21
22#include "pt3.h"
23
24#define PT3_I2C_BASE 2048
25#define PT3_CMD_ADDR_NORMAL 0
26#define PT3_CMD_ADDR_INIT_DEMOD 4096
27#define PT3_CMD_ADDR_INIT_TUNER (4096 + 2042)
28
29/* masks for I2C status register */
30#define STAT_SEQ_RUNNING 0x1
31#define STAT_SEQ_ERROR 0x6
32#define STAT_NO_SEQ 0x8
33
34#define PT3_I2C_RUN (1 << 16)
35#define PT3_I2C_RESET (1 << 17)
36
37enum ctl_cmd {
38 I_END,
39 I_ADDRESS,
40 I_CLOCK_L,
41 I_CLOCK_H,
42 I_DATA_L,
43 I_DATA_H,
44 I_RESET,
45 I_SLEEP,
46 I_DATA_L_NOP = 0x08,
47 I_DATA_H_NOP = 0x0c,
48 I_DATA_H_READ = 0x0d,
49 I_DATA_H_ACK0 = 0x0e,
50 I_DATA_H_ACK1 = 0x0f,
51};
52
53
54static void cmdbuf_add(struct pt3_i2cbuf *cbuf, enum ctl_cmd cmd)
55{
56 int buf_idx;
57
58 if ((cbuf->num_cmds % 2) == 0)
59 cbuf->tmp = cmd;
60 else {
61 cbuf->tmp |= cmd << 4;
62 buf_idx = cbuf->num_cmds / 2;
63 if (buf_idx < ARRAY_SIZE(cbuf->data))
64 cbuf->data[buf_idx] = cbuf->tmp;
65 }
66 cbuf->num_cmds++;
67}
68
69static void put_end(struct pt3_i2cbuf *cbuf)
70{
71 cmdbuf_add(cbuf, I_END);
72 if (cbuf->num_cmds % 2)
73 cmdbuf_add(cbuf, I_END);
74}
75
76static void put_start(struct pt3_i2cbuf *cbuf)
77{
78 cmdbuf_add(cbuf, I_DATA_H);
79 cmdbuf_add(cbuf, I_CLOCK_H);
80 cmdbuf_add(cbuf, I_DATA_L);
81 cmdbuf_add(cbuf, I_CLOCK_L);
82}
83
84static void put_byte_write(struct pt3_i2cbuf *cbuf, u8 val)
85{
86 u8 mask;
87
88 mask = 0x80;
89 for (mask = 0x80; mask > 0; mask >>= 1)
90 cmdbuf_add(cbuf, (val & mask) ? I_DATA_H_NOP : I_DATA_L_NOP);
91 cmdbuf_add(cbuf, I_DATA_H_ACK0);
92}
93
94static void put_byte_read(struct pt3_i2cbuf *cbuf, u32 size)
95{
96 int i, j;
97
98 for (i = 0; i < size; i++) {
99 for (j = 0; j < 8; j++)
100 cmdbuf_add(cbuf, I_DATA_H_READ);
101 cmdbuf_add(cbuf, (i == size - 1) ? I_DATA_H_NOP : I_DATA_L_NOP);
102 }
103}
104
105static void put_stop(struct pt3_i2cbuf *cbuf)
106{
107 cmdbuf_add(cbuf, I_DATA_L);
108 cmdbuf_add(cbuf, I_CLOCK_H);
109 cmdbuf_add(cbuf, I_DATA_H);
110}
111
112
113/* translates msgs to internal commands for bit-banging */
114static void translate(struct pt3_i2cbuf *cbuf, struct i2c_msg *msgs, int num)
115{
116 int i, j;
117 bool rd;
118
119 cbuf->num_cmds = 0;
120 for (i = 0; i < num; i++) {
121 rd = !!(msgs[i].flags & I2C_M_RD);
122 put_start(cbuf);
123 put_byte_write(cbuf, msgs[i].addr << 1 | rd);
124 if (rd)
125 put_byte_read(cbuf, msgs[i].len);
126 else
127 for (j = 0; j < msgs[i].len; j++)
128 put_byte_write(cbuf, msgs[i].buf[j]);
129 }
130 if (num > 0) {
131 put_stop(cbuf);
132 put_end(cbuf);
133 }
134}
135
136static int wait_i2c_result(struct pt3_board *pt3, u32 *result, int max_wait)
137{
138 int i;
139 u32 v;
140
141 for (i = 0; i < max_wait; i++) {
142 v = ioread32(pt3->regs[0] + REG_I2C_R);
143 if (!(v & STAT_SEQ_RUNNING))
144 break;
145 usleep_range(500, 750);
146 }
147 if (i >= max_wait)
148 return -EIO;
149 if (result)
150 *result = v;
151 return 0;
152}
153
154/* send [pre-]translated i2c msgs stored at addr */
155static int send_i2c_cmd(struct pt3_board *pt3, u32 addr)
156{
157 u32 ret;
158
159 /* make sure that previous transactions had finished */
160 if (wait_i2c_result(pt3, NULL, 50)) {
161 dev_warn(&pt3->pdev->dev, "(%s) prev. transaction stalled\n",
162 __func__);
163 return -EIO;
164 }
165
166 iowrite32(PT3_I2C_RUN | addr, pt3->regs[0] + REG_I2C_W);
167 usleep_range(200, 300);
168 /* wait for the current transaction to finish */
169 if (wait_i2c_result(pt3, &ret, 500) || (ret & STAT_SEQ_ERROR)) {
170 dev_warn(&pt3->pdev->dev, "(%s) failed.\n", __func__);
171 return -EIO;
172 }
173 return 0;
174}
175
176
177/* init commands for each demod are combined into one transaction
178 * and hidden in ROM with the address PT3_CMD_ADDR_INIT_DEMOD.
179 */
180int pt3_init_all_demods(struct pt3_board *pt3)
181{
182 ioread32(pt3->regs[0] + REG_I2C_R);
183 return send_i2c_cmd(pt3, PT3_CMD_ADDR_INIT_DEMOD);
184}
185
186/* init commands for two ISDB-T tuners are hidden in ROM. */
187int pt3_init_all_mxl301rf(struct pt3_board *pt3)
188{
189 usleep_range(1000, 2000);
190 return send_i2c_cmd(pt3, PT3_CMD_ADDR_INIT_TUNER);
191}
192
193void pt3_i2c_reset(struct pt3_board *pt3)
194{
195 iowrite32(PT3_I2C_RESET, pt3->regs[0] + REG_I2C_W);
196}
197
198/*
199 * I2C algorithm
200 */
201int
202pt3_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
203{
204 struct pt3_board *pt3;
205 struct pt3_i2cbuf *cbuf;
206 int i;
207 void __iomem *p;
208
209 pt3 = i2c_get_adapdata(adap);
210 cbuf = pt3->i2c_buf;
211
212 for (i = 0; i < num; i++)
213 if (msgs[i].flags & I2C_M_RECV_LEN) {
214 dev_warn(&pt3->pdev->dev,
215 "(%s) I2C_M_RECV_LEN not supported.\n",
216 __func__);
217 return -EINVAL;
218 }
219
220 translate(cbuf, msgs, num);
221 memcpy_toio(pt3->regs[1] + PT3_I2C_BASE + PT3_CMD_ADDR_NORMAL / 2,
222 cbuf->data, cbuf->num_cmds);
223
224 if (send_i2c_cmd(pt3, PT3_CMD_ADDR_NORMAL) < 0)
225 return -EIO;
226
227 p = pt3->regs[1] + PT3_I2C_BASE;
228 for (i = 0; i < num; i++)
229 if ((msgs[i].flags & I2C_M_RD) && msgs[i].len > 0) {
230 memcpy_fromio(msgs[i].buf, p, msgs[i].len);
231 p += msgs[i].len;
232 }
233
234 return num;
235}
236
237u32 pt3_i2c_functionality(struct i2c_adapter *adap)
238{
239 return I2C_FUNC_I2C;
240}