blob: e78ca1f26e684dd90d940e623ea27c1151883776 [file] [log] [blame]
Thomas Gleixner74ba9202019-05-20 09:19:02 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Manu Abraham41e840b2009-12-02 21:57:10 -03002/*
3 Mantis PCI bridge driver
Manu Abraham8825a092009-12-15 09:13:49 -03004 Copyright (C) Manu Abraham (abraham.manu@gmail.com)
Manu Abraham41e840b2009-12-02 21:57:10 -03005
Manu Abraham41e840b2009-12-02 21:57:10 -03006*/
7
Manu Abrahamb3b96142009-12-04 05:41:11 -03008#include <linux/kernel.h>
Manu Abraham41e840b2009-12-02 21:57:10 -03009#include <linux/bitops.h>
Manu Abrahamb3b96142009-12-04 05:41:11 -030010
Manu Abrahamb3b96142009-12-04 05:41:11 -030011#include <linux/signal.h>
12#include <linux/sched.h>
13#include <linux/interrupt.h>
14#include <linux/pci.h>
15#include <linux/i2c.h>
Manu Abraham41e840b2009-12-02 21:57:10 -030016
Mauro Carvalho Chehabfada1932017-12-28 13:03:51 -050017#include <media/dmxdev.h>
18#include <media/dvbdev.h>
19#include <media/dvb_demux.h>
20#include <media/dvb_frontend.h>
21#include <media/dvb_net.h>
Manu Abrahamb3b96142009-12-04 05:41:11 -030022
23#include "mantis_common.h"
24#include "mantis_dma.h"
25#include "mantis_ca.h"
26#include "mantis_ioc.h"
27#include "mantis_dvb.h"
Manu Abraham41e840b2009-12-02 21:57:10 -030028
Manu Abraham616f75e2009-12-04 05:33:56 -030029DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
30
Manu Abrahamb3b96142009-12-04 05:41:11 -030031int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power)
Manu Abraham41e840b2009-12-02 21:57:10 -030032{
Manu Abrahamb3b96142009-12-04 05:41:11 -030033 struct mantis_hwconfig *config = mantis->hwconfig;
Manu Abraham41e840b2009-12-02 21:57:10 -030034
Manu Abrahamb3b96142009-12-04 05:41:11 -030035 switch (power) {
36 case POWER_ON:
37 dprintk(MANTIS_DEBUG, 1, "Power ON");
Ben Hutchings3037fd12010-11-14 14:56:00 -030038 mantis_gpio_set_bits(mantis, config->power, POWER_ON);
Manu Abrahamb3b96142009-12-04 05:41:11 -030039 msleep(100);
Ben Hutchings3037fd12010-11-14 14:56:00 -030040 mantis_gpio_set_bits(mantis, config->power, POWER_ON);
Manu Abrahamb3b96142009-12-04 05:41:11 -030041 msleep(100);
42 break;
Manu Abraham41e840b2009-12-02 21:57:10 -030043
Manu Abrahamb3b96142009-12-04 05:41:11 -030044 case POWER_OFF:
45 dprintk(MANTIS_DEBUG, 1, "Power OFF");
Ben Hutchings3037fd12010-11-14 14:56:00 -030046 mantis_gpio_set_bits(mantis, config->power, POWER_OFF);
Manu Abrahamb3b96142009-12-04 05:41:11 -030047 msleep(100);
48 break;
Manu Abraham41e840b2009-12-02 21:57:10 -030049
Manu Abrahamb3b96142009-12-04 05:41:11 -030050 default:
51 dprintk(MANTIS_DEBUG, 1, "Unknown state <%02x>", power);
52 return -1;
53 }
Manu Abraham41e840b2009-12-02 21:57:10 -030054
55 return 0;
56}
Manu Abrahamb3b96142009-12-04 05:41:11 -030057EXPORT_SYMBOL_GPL(mantis_frontend_power);
Manu Abraham41e840b2009-12-02 21:57:10 -030058
Manu Abrahamb3b96142009-12-04 05:41:11 -030059void mantis_frontend_soft_reset(struct mantis_pci *mantis)
Manu Abraham41e840b2009-12-02 21:57:10 -030060{
Manu Abrahamb3b96142009-12-04 05:41:11 -030061 struct mantis_hwconfig *config = mantis->hwconfig;
62
63 dprintk(MANTIS_DEBUG, 1, "Frontend RESET");
Ben Hutchings3037fd12010-11-14 14:56:00 -030064 mantis_gpio_set_bits(mantis, config->reset, 0);
Manu Abrahamb3b96142009-12-04 05:41:11 -030065 msleep(100);
Ben Hutchings3037fd12010-11-14 14:56:00 -030066 mantis_gpio_set_bits(mantis, config->reset, 0);
Manu Abrahamb3b96142009-12-04 05:41:11 -030067 msleep(100);
Ben Hutchings3037fd12010-11-14 14:56:00 -030068 mantis_gpio_set_bits(mantis, config->reset, 1);
Manu Abrahamb3b96142009-12-04 05:41:11 -030069 msleep(100);
Ben Hutchings3037fd12010-11-14 14:56:00 -030070 mantis_gpio_set_bits(mantis, config->reset, 1);
Manu Abrahamb3b96142009-12-04 05:41:11 -030071 msleep(100);
72
73 return;
74}
75EXPORT_SYMBOL_GPL(mantis_frontend_soft_reset);
76
77static int mantis_frontend_shutdown(struct mantis_pci *mantis)
78{
79 int err;
80
81 mantis_frontend_soft_reset(mantis);
82 err = mantis_frontend_power(mantis, POWER_OFF);
83 if (err != 0) {
84 dprintk(MANTIS_ERROR, 1, "Frontend POWER OFF failed! <%d>", err);
85 return 1;
86 }
Manu Abraham41e840b2009-12-02 21:57:10 -030087
88 return 0;
89}
90
91static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
92{
93 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
94 struct mantis_pci *mantis = dvbdmx->priv;
95
Manu Abrahamb3b96142009-12-04 05:41:11 -030096 dprintk(MANTIS_DEBUG, 1, "Mantis DVB Start feed");
Manu Abraham41e840b2009-12-02 21:57:10 -030097 if (!dvbdmx->dmx.frontend) {
Manu Abrahamb3b96142009-12-04 05:41:11 -030098 dprintk(MANTIS_DEBUG, 1, "no frontend ?");
Manu Abraham41e840b2009-12-02 21:57:10 -030099 return -EINVAL;
100 }
Manu Abrahamb3b96142009-12-04 05:41:11 -0300101
Manu Abraham41e840b2009-12-02 21:57:10 -0300102 mantis->feeds++;
Manu Abrahamb3b96142009-12-04 05:41:11 -0300103 dprintk(MANTIS_DEBUG, 1, "mantis start feed, feeds=%d", mantis->feeds);
Manu Abraham41e840b2009-12-02 21:57:10 -0300104
105 if (mantis->feeds == 1) {
Manu Abrahamb3b96142009-12-04 05:41:11 -0300106 dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma");
Manu Abraham41e840b2009-12-02 21:57:10 -0300107 mantis_dma_start(mantis);
Marko Ristola9c814962010-11-14 14:09:04 -0300108 tasklet_enable(&mantis->tasklet);
Manu Abraham41e840b2009-12-02 21:57:10 -0300109 }
110
111 return mantis->feeds;
112}
113
114static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
115{
116 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
117 struct mantis_pci *mantis = dvbdmx->priv;
118
Manu Abrahamb3b96142009-12-04 05:41:11 -0300119 dprintk(MANTIS_DEBUG, 1, "Mantis DVB Stop feed");
Manu Abraham41e840b2009-12-02 21:57:10 -0300120 if (!dvbdmx->dmx.frontend) {
Manu Abrahamb3b96142009-12-04 05:41:11 -0300121 dprintk(MANTIS_DEBUG, 1, "no frontend ?");
Manu Abraham41e840b2009-12-02 21:57:10 -0300122 return -EINVAL;
123 }
Manu Abrahamb3b96142009-12-04 05:41:11 -0300124
Manu Abraham41e840b2009-12-02 21:57:10 -0300125 mantis->feeds--;
126 if (mantis->feeds == 0) {
Manu Abrahamb3b96142009-12-04 05:41:11 -0300127 dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma");
Marko Ristola9c814962010-11-14 14:09:04 -0300128 tasklet_disable(&mantis->tasklet);
Manu Abraham41e840b2009-12-02 21:57:10 -0300129 mantis_dma_stop(mantis);
130 }
Manu Abrahamb3b96142009-12-04 05:41:11 -0300131
Manu Abraham41e840b2009-12-02 21:57:10 -0300132 return 0;
133}
134
Greg Kroah-Hartman4c62e972012-12-21 13:17:53 -0800135int mantis_dvb_init(struct mantis_pci *mantis)
Manu Abraham41e840b2009-12-02 21:57:10 -0300136{
Manu Abrahamb3b96142009-12-04 05:41:11 -0300137 struct mantis_hwconfig *config = mantis->hwconfig;
138 int result = -1;
Manu Abraham41e840b2009-12-02 21:57:10 -0300139
Manu Abrahamb3b96142009-12-04 05:41:11 -0300140 dprintk(MANTIS_DEBUG, 1, "dvb_register_adapter");
Manu Abraham41e840b2009-12-02 21:57:10 -0300141
Manu Abrahamb3b96142009-12-04 05:41:11 -0300142 result = dvb_register_adapter(&mantis->dvb_adapter,
143 "Mantis DVB adapter",
144 THIS_MODULE,
145 &mantis->pdev->dev,
146 adapter_nr);
147
148 if (result < 0) {
149
150 dprintk(MANTIS_ERROR, 1, "Error registering adapter");
Manu Abraham41e840b2009-12-02 21:57:10 -0300151 return -ENODEV;
152 }
Manu Abrahamb3b96142009-12-04 05:41:11 -0300153
154 mantis->dvb_adapter.priv = mantis;
155 mantis->demux.dmx.capabilities = DMX_TS_FILTERING |
Manu Abraham41e840b2009-12-02 21:57:10 -0300156 DMX_SECTION_FILTERING |
157 DMX_MEMORY_BASED_FILTERING;
158
Manu Abrahamb3b96142009-12-04 05:41:11 -0300159 mantis->demux.priv = mantis;
160 mantis->demux.filternum = 256;
161 mantis->demux.feednum = 256;
162 mantis->demux.start_feed = mantis_dvb_start_feed;
163 mantis->demux.stop_feed = mantis_dvb_stop_feed;
164 mantis->demux.write_to_decoder = NULL;
165
166 dprintk(MANTIS_DEBUG, 1, "dvb_dmx_init");
167 result = dvb_dmx_init(&mantis->demux);
168 if (result < 0) {
169 dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
Manu Abraham41e840b2009-12-02 21:57:10 -0300170
171 goto err0;
172 }
Manu Abraham41e840b2009-12-02 21:57:10 -0300173
Manu Abrahamb3b96142009-12-04 05:41:11 -0300174 mantis->dmxdev.filternum = 256;
175 mantis->dmxdev.demux = &mantis->demux.dmx;
176 mantis->dmxdev.capabilities = 0;
177 dprintk(MANTIS_DEBUG, 1, "dvb_dmxdev_init");
178
179 result = dvb_dmxdev_init(&mantis->dmxdev, &mantis->dvb_adapter);
180 if (result < 0) {
181
182 dprintk(MANTIS_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result);
Manu Abraham41e840b2009-12-02 21:57:10 -0300183 goto err1;
184 }
Manu Abraham41e840b2009-12-02 21:57:10 -0300185
Manu Abrahamb3b96142009-12-04 05:41:11 -0300186 mantis->fe_hw.source = DMX_FRONTEND_0;
187 result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_hw);
188 if (result < 0) {
Manu Abraham41e840b2009-12-02 21:57:10 -0300189
Manu Abrahamb3b96142009-12-04 05:41:11 -0300190 dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
Manu Abraham41e840b2009-12-02 21:57:10 -0300191 goto err2;
192 }
Manu Abraham41e840b2009-12-02 21:57:10 -0300193
Manu Abrahamb3b96142009-12-04 05:41:11 -0300194 mantis->fe_mem.source = DMX_MEMORY_FE;
Manu Abrahamf5ae4f62009-12-15 08:47:21 -0300195 result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_mem);
Manu Abrahamb3b96142009-12-04 05:41:11 -0300196 if (result < 0) {
Manu Abrahamf5ae4f62009-12-15 08:47:21 -0300197 dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
Manu Abraham41e840b2009-12-02 21:57:10 -0300198 goto err3;
199 }
Manu Abraham41e840b2009-12-02 21:57:10 -0300200
Manu Abrahamb3b96142009-12-04 05:41:11 -0300201 result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, &mantis->fe_hw);
202 if (result < 0) {
203 dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
Manu Abraham41e840b2009-12-02 21:57:10 -0300204 goto err4;
205 }
Manu Abrahamb3b96142009-12-04 05:41:11 -0300206
Manu Abraham41e840b2009-12-02 21:57:10 -0300207 dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx);
208 tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis);
Marko Ristola9c814962010-11-14 14:09:04 -0300209 tasklet_disable(&mantis->tasklet);
Manu Abrahamb3b96142009-12-04 05:41:11 -0300210 if (mantis->hwconfig) {
211 result = config->frontend_init(mantis, mantis->fe);
212 if (result < 0) {
213 dprintk(MANTIS_ERROR, 1, "!!! NO Frontends found !!!");
214 goto err5;
215 } else {
Manu Abrahamb3b96142009-12-04 05:41:11 -0300216 if (mantis->fe == NULL) {
Dan Carpenter79a2eda2017-01-27 06:06:22 -0200217 result = -ENOMEM;
Manu Abrahamb3b96142009-12-04 05:41:11 -0300218 dprintk(MANTIS_ERROR, 1, "FE <NULL>");
219 goto err5;
220 }
Dan Carpenter79a2eda2017-01-27 06:06:22 -0200221 result = dvb_register_frontend(&mantis->dvb_adapter, mantis->fe);
222 if (result) {
Manu Abrahamb3b96142009-12-04 05:41:11 -0300223 dprintk(MANTIS_ERROR, 1, "ERROR: Frontend registration failed");
224
225 if (mantis->fe->ops.release)
226 mantis->fe->ops.release(mantis->fe);
227
228 mantis->fe = NULL;
229 goto err5;
230 }
231 }
232 }
Manu Abrahamd9dd5f72009-12-04 05:07:41 -0300233
Manu Abraham41e840b2009-12-02 21:57:10 -0300234 return 0;
235
Manu Abrahamb3b96142009-12-04 05:41:11 -0300236 /* Error conditions .. */
237err5:
238 tasklet_kill(&mantis->tasklet);
239 dvb_net_release(&mantis->dvbnet);
Alan Coxe1d45ae2012-08-09 12:33:52 -0300240 if (mantis->fe) {
241 dvb_unregister_frontend(mantis->fe);
242 dvb_frontend_detach(mantis->fe);
243 }
Manu Abraham41e840b2009-12-02 21:57:10 -0300244err4:
245 mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
Manu Abraham3e978a82009-12-04 05:56:35 -0300246
Manu Abraham41e840b2009-12-02 21:57:10 -0300247err3:
248 mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
Manu Abraham3e978a82009-12-04 05:56:35 -0300249
Manu Abraham41e840b2009-12-02 21:57:10 -0300250err2:
251 dvb_dmxdev_release(&mantis->dmxdev);
Manu Abraham3e978a82009-12-04 05:56:35 -0300252
Manu Abraham41e840b2009-12-02 21:57:10 -0300253err1:
254 dvb_dmx_release(&mantis->demux);
Manu Abraham3e978a82009-12-04 05:56:35 -0300255
Manu Abraham41e840b2009-12-02 21:57:10 -0300256err0:
257 dvb_unregister_adapter(&mantis->dvb_adapter);
258
259 return result;
260}
Manu Abrahamb3b96142009-12-04 05:41:11 -0300261EXPORT_SYMBOL_GPL(mantis_dvb_init);
Manu Abraham41e840b2009-12-02 21:57:10 -0300262
Greg Kroah-Hartman4c62e972012-12-21 13:17:53 -0800263int mantis_dvb_exit(struct mantis_pci *mantis)
Manu Abraham41e840b2009-12-02 21:57:10 -0300264{
Manu Abrahamb3b96142009-12-04 05:41:11 -0300265 int err;
266
Manu Abraham3e978a82009-12-04 05:56:35 -0300267 if (mantis->fe) {
Manu Abrahamf5ae4f62009-12-15 08:47:21 -0300268 /* mantis_ca_exit(mantis); */
Manu Abraham3e978a82009-12-04 05:56:35 -0300269 err = mantis_frontend_shutdown(mantis);
270 if (err != 0)
271 dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err);
Manu Abraham3e978a82009-12-04 05:56:35 -0300272 dvb_unregister_frontend(mantis->fe);
Manu Abrahamc5e598a2009-12-09 19:59:26 -0300273 dvb_frontend_detach(mantis->fe);
Manu Abraham3e978a82009-12-04 05:56:35 -0300274 }
275
Manu Abraham41e840b2009-12-02 21:57:10 -0300276 tasklet_kill(&mantis->tasklet);
277 dvb_net_release(&mantis->dvbnet);
Manu Abraham3e978a82009-12-04 05:56:35 -0300278
Manu Abraham41e840b2009-12-02 21:57:10 -0300279 mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
280 mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
Manu Abraham3e978a82009-12-04 05:56:35 -0300281
Manu Abraham41e840b2009-12-02 21:57:10 -0300282 dvb_dmxdev_release(&mantis->dmxdev);
283 dvb_dmx_release(&mantis->demux);
284
Manu Abrahamb3b96142009-12-04 05:41:11 -0300285 dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter");
Manu Abraham41e840b2009-12-02 21:57:10 -0300286 dvb_unregister_adapter(&mantis->dvb_adapter);
287
288 return 0;
289}
Manu Abrahamb3b96142009-12-04 05:41:11 -0300290EXPORT_SYMBOL_GPL(mantis_dvb_exit);