mantis_dvb.c revision 3037fd14302d635426996fb7f6fcf7cb98dc15b9
1/*
2	Mantis PCI bridge driver
3	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
4
5	This program is free software; you can redistribute it and/or modify
6	it under the terms of the GNU General Public License as published by
7	the Free Software Foundation; either version 2 of the License, or
8	(at your option) any later version.
9
10	This program is distributed in the hope that it will be useful,
11	but WITHOUT ANY WARRANTY; without even the implied warranty of
12	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13	GNU General Public License for more details.
14
15	You should have received a copy of the GNU General Public License
16	along with this program; if not, write to the Free Software
17	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*/
19
20#include <linux/kernel.h>
21#include <linux/bitops.h>
22
23#include <linux/signal.h>
24#include <linux/sched.h>
25#include <linux/interrupt.h>
26#include <linux/pci.h>
27#include <linux/i2c.h>
28
29#include "dmxdev.h"
30#include "dvbdev.h"
31#include "dvb_demux.h"
32#include "dvb_frontend.h"
33#include "dvb_net.h"
34
35#include "mantis_common.h"
36#include "mantis_dma.h"
37#include "mantis_ca.h"
38#include "mantis_ioc.h"
39#include "mantis_dvb.h"
40
41DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
42
43int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power)
44{
45	struct mantis_hwconfig *config = mantis->hwconfig;
46
47	switch (power) {
48	case POWER_ON:
49		dprintk(MANTIS_DEBUG, 1, "Power ON");
50		mantis_gpio_set_bits(mantis, config->power, POWER_ON);
51		msleep(100);
52		mantis_gpio_set_bits(mantis, config->power, POWER_ON);
53		msleep(100);
54		break;
55
56	case POWER_OFF:
57		dprintk(MANTIS_DEBUG, 1, "Power OFF");
58		mantis_gpio_set_bits(mantis, config->power, POWER_OFF);
59		msleep(100);
60		break;
61
62	default:
63		dprintk(MANTIS_DEBUG, 1, "Unknown state <%02x>", power);
64		return -1;
65	}
66
67	return 0;
68}
69EXPORT_SYMBOL_GPL(mantis_frontend_power);
70
71void mantis_frontend_soft_reset(struct mantis_pci *mantis)
72{
73	struct mantis_hwconfig *config = mantis->hwconfig;
74
75	dprintk(MANTIS_DEBUG, 1, "Frontend RESET");
76	mantis_gpio_set_bits(mantis, config->reset, 0);
77	msleep(100);
78	mantis_gpio_set_bits(mantis, config->reset, 0);
79	msleep(100);
80	mantis_gpio_set_bits(mantis, config->reset, 1);
81	msleep(100);
82	mantis_gpio_set_bits(mantis, config->reset, 1);
83	msleep(100);
84
85	return;
86}
87EXPORT_SYMBOL_GPL(mantis_frontend_soft_reset);
88
89static int mantis_frontend_shutdown(struct mantis_pci *mantis)
90{
91	int err;
92
93	mantis_frontend_soft_reset(mantis);
94	err = mantis_frontend_power(mantis, POWER_OFF);
95	if (err != 0) {
96		dprintk(MANTIS_ERROR, 1, "Frontend POWER OFF failed! <%d>", err);
97		return 1;
98	}
99
100	return 0;
101}
102
103static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
104{
105	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
106	struct mantis_pci *mantis = dvbdmx->priv;
107
108	dprintk(MANTIS_DEBUG, 1, "Mantis DVB Start feed");
109	if (!dvbdmx->dmx.frontend) {
110		dprintk(MANTIS_DEBUG, 1, "no frontend ?");
111		return -EINVAL;
112	}
113
114	mantis->feeds++;
115	dprintk(MANTIS_DEBUG, 1, "mantis start feed, feeds=%d",	mantis->feeds);
116
117	if (mantis->feeds == 1)	 {
118		dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma");
119		mantis_dma_start(mantis);
120		tasklet_enable(&mantis->tasklet);
121	}
122
123	return mantis->feeds;
124}
125
126static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
127{
128	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
129	struct mantis_pci *mantis = dvbdmx->priv;
130
131	dprintk(MANTIS_DEBUG, 1, "Mantis DVB Stop feed");
132	if (!dvbdmx->dmx.frontend) {
133		dprintk(MANTIS_DEBUG, 1, "no frontend ?");
134		return -EINVAL;
135	}
136
137	mantis->feeds--;
138	if (mantis->feeds == 0) {
139		dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma");
140		tasklet_disable(&mantis->tasklet);
141		mantis_dma_stop(mantis);
142	}
143
144	return 0;
145}
146
147int __devinit mantis_dvb_init(struct mantis_pci *mantis)
148{
149	struct mantis_hwconfig *config = mantis->hwconfig;
150	int result = -1;
151
152	dprintk(MANTIS_DEBUG, 1, "dvb_register_adapter");
153
154	result = dvb_register_adapter(&mantis->dvb_adapter,
155				      "Mantis DVB adapter",
156				      THIS_MODULE,
157				      &mantis->pdev->dev,
158				      adapter_nr);
159
160	if (result < 0) {
161
162		dprintk(MANTIS_ERROR, 1, "Error registering adapter");
163		return -ENODEV;
164	}
165
166	mantis->dvb_adapter.priv	= mantis;
167	mantis->demux.dmx.capabilities	= DMX_TS_FILTERING	|
168					 DMX_SECTION_FILTERING	|
169					 DMX_MEMORY_BASED_FILTERING;
170
171	mantis->demux.priv		= mantis;
172	mantis->demux.filternum		= 256;
173	mantis->demux.feednum		= 256;
174	mantis->demux.start_feed	= mantis_dvb_start_feed;
175	mantis->demux.stop_feed		= mantis_dvb_stop_feed;
176	mantis->demux.write_to_decoder	= NULL;
177
178	dprintk(MANTIS_DEBUG, 1, "dvb_dmx_init");
179	result = dvb_dmx_init(&mantis->demux);
180	if (result < 0) {
181		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
182
183		goto err0;
184	}
185
186	mantis->dmxdev.filternum	= 256;
187	mantis->dmxdev.demux		= &mantis->demux.dmx;
188	mantis->dmxdev.capabilities	= 0;
189	dprintk(MANTIS_DEBUG, 1, "dvb_dmxdev_init");
190
191	result = dvb_dmxdev_init(&mantis->dmxdev, &mantis->dvb_adapter);
192	if (result < 0) {
193
194		dprintk(MANTIS_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result);
195		goto err1;
196	}
197
198	mantis->fe_hw.source		= DMX_FRONTEND_0;
199	result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_hw);
200	if (result < 0) {
201
202		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
203		goto err2;
204	}
205
206	mantis->fe_mem.source		= DMX_MEMORY_FE;
207	result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_mem);
208	if (result < 0) {
209		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
210		goto err3;
211	}
212
213	result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, &mantis->fe_hw);
214	if (result < 0) {
215		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
216		goto err4;
217	}
218
219	dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx);
220	tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis);
221	tasklet_disable(&mantis->tasklet);
222	if (mantis->hwconfig) {
223		result = config->frontend_init(mantis, mantis->fe);
224		if (result < 0) {
225			dprintk(MANTIS_ERROR, 1, "!!! NO Frontends found !!!");
226			goto err5;
227		} else {
228			if (mantis->fe == NULL) {
229				dprintk(MANTIS_ERROR, 1, "FE <NULL>");
230				goto err5;
231			}
232
233			if (dvb_register_frontend(&mantis->dvb_adapter, mantis->fe)) {
234				dprintk(MANTIS_ERROR, 1, "ERROR: Frontend registration failed");
235
236				if (mantis->fe->ops.release)
237					mantis->fe->ops.release(mantis->fe);
238
239				mantis->fe = NULL;
240				goto err5;
241			}
242		}
243	}
244
245	return 0;
246
247	/* Error conditions ..	*/
248err5:
249	tasklet_kill(&mantis->tasklet);
250	dvb_net_release(&mantis->dvbnet);
251	dvb_unregister_frontend(mantis->fe);
252	dvb_frontend_detach(mantis->fe);
253err4:
254	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
255
256err3:
257	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
258
259err2:
260	dvb_dmxdev_release(&mantis->dmxdev);
261
262err1:
263	dvb_dmx_release(&mantis->demux);
264
265err0:
266	dvb_unregister_adapter(&mantis->dvb_adapter);
267
268	return result;
269}
270EXPORT_SYMBOL_GPL(mantis_dvb_init);
271
272int __devexit mantis_dvb_exit(struct mantis_pci *mantis)
273{
274	int err;
275
276	if (mantis->fe) {
277		/* mantis_ca_exit(mantis); */
278		err = mantis_frontend_shutdown(mantis);
279		if (err != 0)
280			dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err);
281		dvb_unregister_frontend(mantis->fe);
282		dvb_frontend_detach(mantis->fe);
283	}
284
285	tasklet_kill(&mantis->tasklet);
286	dvb_net_release(&mantis->dvbnet);
287
288	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
289	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
290
291	dvb_dmxdev_release(&mantis->dmxdev);
292	dvb_dmx_release(&mantis->demux);
293
294	dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter");
295	dvb_unregister_adapter(&mantis->dvb_adapter);
296
297	return 0;
298}
299EXPORT_SYMBOL_GPL(mantis_dvb_exit);
300