mantis_dvb.c revision f5ae4f6f482191c531ea9e50ac91d9bd2ffca171
1/*
2	Mantis PCI bridge driver
3	Copyright (C) 2005, 2006 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		gpio_set_bits(mantis, config->power, POWER_ON);
51		msleep(100);
52		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		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	gpio_set_bits(mantis, config->reset, 0);
77	msleep(100);
78	gpio_set_bits(mantis, config->reset, 0);
79	msleep(100);
80	gpio_set_bits(mantis, config->reset, 1);
81	msleep(100);
82	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	}
121
122	return mantis->feeds;
123}
124
125static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
126{
127	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
128	struct mantis_pci *mantis = dvbdmx->priv;
129
130	dprintk(MANTIS_DEBUG, 1, "Mantis DVB Stop feed");
131	if (!dvbdmx->dmx.frontend) {
132		dprintk(MANTIS_DEBUG, 1, "no frontend ?");
133		return -EINVAL;
134	}
135
136	mantis->feeds--;
137	if (mantis->feeds == 0) {
138		dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma");
139		mantis_dma_stop(mantis);
140	}
141
142	return 0;
143}
144
145int __devinit mantis_dvb_init(struct mantis_pci *mantis)
146{
147	struct mantis_hwconfig *config = mantis->hwconfig;
148	int result = -1;
149
150	dprintk(MANTIS_DEBUG, 1, "dvb_register_adapter");
151
152	result = dvb_register_adapter(&mantis->dvb_adapter,
153				      "Mantis DVB adapter",
154				      THIS_MODULE,
155				      &mantis->pdev->dev,
156				      adapter_nr);
157
158	if (result < 0) {
159
160		dprintk(MANTIS_ERROR, 1, "Error registering adapter");
161		return -ENODEV;
162	}
163
164	mantis->dvb_adapter.priv	= mantis;
165	mantis->demux.dmx.capabilities	= DMX_TS_FILTERING	|
166					 DMX_SECTION_FILTERING	|
167					 DMX_MEMORY_BASED_FILTERING;
168
169	mantis->demux.priv		= mantis;
170	mantis->demux.filternum		= 256;
171	mantis->demux.feednum		= 256;
172	mantis->demux.start_feed	= mantis_dvb_start_feed;
173	mantis->demux.stop_feed		= mantis_dvb_stop_feed;
174	mantis->demux.write_to_decoder	= NULL;
175
176	dprintk(MANTIS_DEBUG, 1, "dvb_dmx_init");
177	result = dvb_dmx_init(&mantis->demux);
178	if (result < 0) {
179		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
180
181		goto err0;
182	}
183
184	mantis->dmxdev.filternum	= 256;
185	mantis->dmxdev.demux		= &mantis->demux.dmx;
186	mantis->dmxdev.capabilities	= 0;
187	dprintk(MANTIS_DEBUG, 1, "dvb_dmxdev_init");
188
189	result = dvb_dmxdev_init(&mantis->dmxdev, &mantis->dvb_adapter);
190	if (result < 0) {
191
192		dprintk(MANTIS_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result);
193		goto err1;
194	}
195
196	mantis->fe_hw.source		= DMX_FRONTEND_0;
197	result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_hw);
198	if (result < 0) {
199
200		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
201		goto err2;
202	}
203
204	mantis->fe_mem.source		= DMX_MEMORY_FE;
205	result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_mem);
206	if (result < 0) {
207		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
208		goto err3;
209	}
210
211	result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, &mantis->fe_hw);
212	if (result < 0) {
213		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
214		goto err4;
215	}
216
217	dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx);
218	tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis);
219	if (mantis->hwconfig) {
220		result = config->frontend_init(mantis, mantis->fe);
221		if (result < 0) {
222			dprintk(MANTIS_ERROR, 1, "!!! NO Frontends found !!!");
223			goto err5;
224		} else {
225			if (mantis->fe == NULL) {
226				dprintk(MANTIS_ERROR, 1, "FE <NULL>");
227				goto err5;
228			}
229
230			if (dvb_register_frontend(&mantis->dvb_adapter, mantis->fe)) {
231				dprintk(MANTIS_ERROR, 1, "ERROR: Frontend registration failed");
232
233				if (mantis->fe->ops.release)
234					mantis->fe->ops.release(mantis->fe);
235
236				mantis->fe = NULL;
237				goto err5;
238			}
239		}
240	}
241
242	return 0;
243
244	/* Error conditions ..	*/
245err5:
246	tasklet_kill(&mantis->tasklet);
247	dvb_net_release(&mantis->dvbnet);
248	dvb_unregister_frontend(mantis->fe);
249	dvb_frontend_detach(mantis->fe);
250err4:
251	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
252
253err3:
254	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
255
256err2:
257	dvb_dmxdev_release(&mantis->dmxdev);
258
259err1:
260	dvb_dmx_release(&mantis->demux);
261
262err0:
263	dvb_unregister_adapter(&mantis->dvb_adapter);
264
265	return result;
266}
267EXPORT_SYMBOL_GPL(mantis_dvb_init);
268
269int __devexit mantis_dvb_exit(struct mantis_pci *mantis)
270{
271	int err;
272
273	if (mantis->fe) {
274		/* mantis_ca_exit(mantis); */
275		err = mantis_frontend_shutdown(mantis);
276		if (err != 0)
277			dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err);
278		dvb_unregister_frontend(mantis->fe);
279		dvb_frontend_detach(mantis->fe);
280	}
281
282	tasklet_kill(&mantis->tasklet);
283	dvb_net_release(&mantis->dvbnet);
284
285	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
286	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
287
288	dvb_dmxdev_release(&mantis->dmxdev);
289	dvb_dmx_release(&mantis->demux);
290
291	dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter");
292	dvb_unregister_adapter(&mantis->dvb_adapter);
293
294	return 0;
295}
296EXPORT_SYMBOL_GPL(mantis_dvb_exit);
297