Commit | Line | Data |
---|---|---|
41e840b1 MA |
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 | ||
b3b96144 | 20 | #include <linux/kernel.h> |
41e840b1 | 21 | #include <linux/bitops.h> |
b3b96144 MA |
22 | |
23 | #include <asm/irq.h> | |
24 | #include <linux/signal.h> | |
25 | #include <linux/sched.h> | |
26 | #include <linux/interrupt.h> | |
27 | #include <linux/pci.h> | |
28 | #include <linux/i2c.h> | |
41e840b1 MA |
29 | |
30 | #include "dmxdev.h" | |
31 | #include "dvbdev.h" | |
32 | #include "dvb_demux.h" | |
33 | #include "dvb_frontend.h" | |
b3b96144 | 34 | #include "dvb_net.h" |
41e840b1 | 35 | |
b3b96144 MA |
36 | #include "mantis_common.h" |
37 | #include "mantis_dma.h" | |
38 | #include "mantis_ca.h" | |
39 | #include "mantis_ioc.h" | |
40 | #include "mantis_dvb.h" | |
616f75e1 | 41 | |
b3b96144 | 42 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
41e840b1 | 43 | |
b3b96144 | 44 | int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power) |
41e840b1 | 45 | { |
b3b96144 MA |
46 | struct mantis_hwconfig *config = mantis->hwconfig; |
47 | ||
48 | switch (power) { | |
49 | case POWER_ON: | |
50 | dprintk(MANTIS_DEBUG, 1, "Power ON"); | |
51 | gpio_set_bits(mantis, config->power, POWER_ON); | |
52 | msleep(100); | |
53 | gpio_set_bits(mantis, config->power, POWER_ON); | |
54 | msleep(100); | |
55 | break; | |
41e840b1 | 56 | |
b3b96144 MA |
57 | case POWER_OFF: |
58 | dprintk(MANTIS_DEBUG, 1, "Power OFF"); | |
59 | gpio_set_bits(mantis, config->power, POWER_OFF); | |
60 | msleep(100); | |
61 | break; | |
41e840b1 | 62 | |
b3b96144 MA |
63 | default: |
64 | dprintk(MANTIS_DEBUG, 1, "Unknown state <%02x>", power); | |
65 | return -1; | |
66 | } | |
41e840b1 MA |
67 | |
68 | return 0; | |
69 | } | |
b3b96144 | 70 | EXPORT_SYMBOL_GPL(mantis_frontend_power); |
41e840b1 | 71 | |
b3b96144 | 72 | void mantis_frontend_soft_reset(struct mantis_pci *mantis) |
41e840b1 | 73 | { |
b3b96144 MA |
74 | struct mantis_hwconfig *config = mantis->hwconfig; |
75 | ||
76 | dprintk(MANTIS_DEBUG, 1, "Frontend RESET"); | |
77 | gpio_set_bits(mantis, config->reset, 0); | |
78 | msleep(100); | |
79 | gpio_set_bits(mantis, config->reset, 0); | |
80 | msleep(100); | |
81 | gpio_set_bits(mantis, config->reset, 1); | |
82 | msleep(100); | |
83 | gpio_set_bits(mantis, config->reset, 1); | |
84 | msleep(100); | |
85 | ||
86 | return; | |
87 | } | |
88 | EXPORT_SYMBOL_GPL(mantis_frontend_soft_reset); | |
89 | ||
90 | static int mantis_frontend_shutdown(struct mantis_pci *mantis) | |
91 | { | |
92 | int err; | |
93 | ||
94 | mantis_frontend_soft_reset(mantis); | |
95 | err = mantis_frontend_power(mantis, POWER_OFF); | |
96 | if (err != 0) { | |
97 | dprintk(MANTIS_ERROR, 1, "Frontend POWER OFF failed! <%d>", err); | |
98 | return 1; | |
99 | } | |
41e840b1 MA |
100 | |
101 | return 0; | |
102 | } | |
103 | ||
104 | static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) | |
105 | { | |
106 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | |
107 | struct mantis_pci *mantis = dvbdmx->priv; | |
108 | ||
b3b96144 | 109 | dprintk(MANTIS_DEBUG, 1, "Mantis DVB Start feed"); |
41e840b1 | 110 | if (!dvbdmx->dmx.frontend) { |
b3b96144 | 111 | dprintk(MANTIS_DEBUG, 1, "no frontend ?"); |
41e840b1 MA |
112 | return -EINVAL; |
113 | } | |
b3b96144 | 114 | |
41e840b1 | 115 | mantis->feeds++; |
b3b96144 | 116 | dprintk(MANTIS_DEBUG, 1, "mantis start feed, feeds=%d", mantis->feeds); |
41e840b1 MA |
117 | |
118 | if (mantis->feeds == 1) { | |
b3b96144 | 119 | dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma"); |
41e840b1 MA |
120 | printk("mantis start feed & dma\n"); |
121 | mantis_dma_start(mantis); | |
122 | } | |
123 | ||
124 | return mantis->feeds; | |
125 | } | |
126 | ||
127 | static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | |
128 | { | |
129 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | |
130 | struct mantis_pci *mantis = dvbdmx->priv; | |
131 | ||
b3b96144 | 132 | dprintk(MANTIS_DEBUG, 1, "Mantis DVB Stop feed"); |
41e840b1 | 133 | if (!dvbdmx->dmx.frontend) { |
b3b96144 | 134 | dprintk(MANTIS_DEBUG, 1, "no frontend ?"); |
41e840b1 MA |
135 | return -EINVAL; |
136 | } | |
b3b96144 | 137 | |
41e840b1 MA |
138 | mantis->feeds--; |
139 | if (mantis->feeds == 0) { | |
b3b96144 | 140 | dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma"); |
41e840b1 MA |
141 | printk("mantis stop feed and dma\n"); |
142 | mantis_dma_stop(mantis); | |
143 | } | |
b3b96144 | 144 | |
41e840b1 MA |
145 | return 0; |
146 | } | |
147 | ||
148 | int __devinit mantis_dvb_init(struct mantis_pci *mantis) | |
149 | { | |
b3b96144 MA |
150 | struct mantis_hwconfig *config = mantis->hwconfig; |
151 | int result = -1; | |
152 | ||
153 | dprintk(MANTIS_DEBUG, 1, "dvb_register_adapter"); | |
154 | ||
155 | result = dvb_register_adapter(&mantis->dvb_adapter, | |
156 | "Mantis DVB adapter", | |
157 | THIS_MODULE, | |
158 | &mantis->pdev->dev, | |
159 | adapter_nr); | |
41e840b1 | 160 | |
b3b96144 | 161 | if (result < 0) { |
41e840b1 | 162 | |
b3b96144 | 163 | dprintk(MANTIS_ERROR, 1, "Error registering adapter"); |
41e840b1 MA |
164 | return -ENODEV; |
165 | } | |
b3b96144 MA |
166 | |
167 | mantis->dvb_adapter.priv = mantis; | |
168 | mantis->demux.dmx.capabilities = DMX_TS_FILTERING | | |
41e840b1 MA |
169 | DMX_SECTION_FILTERING | |
170 | DMX_MEMORY_BASED_FILTERING; | |
171 | ||
b3b96144 MA |
172 | mantis->demux.priv = mantis; |
173 | mantis->demux.filternum = 256; | |
174 | mantis->demux.feednum = 256; | |
175 | mantis->demux.start_feed = mantis_dvb_start_feed; | |
176 | mantis->demux.stop_feed = mantis_dvb_stop_feed; | |
177 | mantis->demux.write_to_decoder = NULL; | |
178 | ||
179 | dprintk(MANTIS_DEBUG, 1, "dvb_dmx_init"); | |
180 | result = dvb_dmx_init(&mantis->demux); | |
181 | if (result < 0) { | |
182 | dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); | |
41e840b1 MA |
183 | |
184 | goto err0; | |
185 | } | |
b3b96144 MA |
186 | |
187 | mantis->dmxdev.filternum = 256; | |
188 | mantis->dmxdev.demux = &mantis->demux.dmx; | |
189 | mantis->dmxdev.capabilities = 0; | |
190 | dprintk(MANTIS_DEBUG, 1, "dvb_dmxdev_init"); | |
191 | ||
192 | result = dvb_dmxdev_init(&mantis->dmxdev, &mantis->dvb_adapter); | |
193 | if (result < 0) { | |
194 | ||
195 | dprintk(MANTIS_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result); | |
41e840b1 MA |
196 | goto err1; |
197 | } | |
41e840b1 | 198 | |
b3b96144 MA |
199 | mantis->fe_hw.source = DMX_FRONTEND_0; |
200 | result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_hw); | |
201 | if (result < 0) { | |
41e840b1 | 202 | |
b3b96144 | 203 | dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); |
41e840b1 MA |
204 | goto err2; |
205 | } | |
41e840b1 | 206 | |
b3b96144 MA |
207 | mantis->fe_mem.source = DMX_MEMORY_FE; |
208 | result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx,&mantis->fe_mem); | |
209 | if (result < 0) { | |
210 | dprintk(MANTIS_ERROR, 1,"dvb_dmx_init failed, ERROR=%d", result); | |
41e840b1 MA |
211 | goto err3; |
212 | } | |
41e840b1 | 213 | |
b3b96144 MA |
214 | result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, &mantis->fe_hw); |
215 | if (result < 0) { | |
216 | dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); | |
41e840b1 MA |
217 | goto err4; |
218 | } | |
b3b96144 | 219 | |
41e840b1 MA |
220 | dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx); |
221 | tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis); | |
b3b96144 MA |
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->dvb_adapter == NULL) { | |
229 | // dprintk(MANTIS_ERROR, 1, "DVB adapter <NULL>"); | |
230 | // goto err5; | |
231 | // } | |
232 | if (mantis->fe == NULL) { | |
233 | dprintk(MANTIS_ERROR, 1, "FE <NULL>"); | |
234 | goto err5; | |
235 | } | |
236 | ||
237 | if (dvb_register_frontend(&mantis->dvb_adapter, mantis->fe)) { | |
238 | dprintk(MANTIS_ERROR, 1, "ERROR: Frontend registration failed"); | |
239 | ||
240 | if (mantis->fe->ops.release) | |
241 | mantis->fe->ops.release(mantis->fe); | |
242 | ||
243 | mantis->fe = NULL; | |
244 | goto err5; | |
245 | } | |
246 | } | |
247 | } | |
d9dd5f71 | 248 | |
41e840b1 MA |
249 | return 0; |
250 | ||
b3b96144 MA |
251 | /* Error conditions .. */ |
252 | err5: | |
253 | tasklet_kill(&mantis->tasklet); | |
254 | dvb_net_release(&mantis->dvbnet); | |
3e978a82 | 255 | |
41e840b1 MA |
256 | err4: |
257 | mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); | |
3e978a82 | 258 | |
41e840b1 MA |
259 | err3: |
260 | mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); | |
3e978a82 | 261 | |
41e840b1 MA |
262 | err2: |
263 | dvb_dmxdev_release(&mantis->dmxdev); | |
3e978a82 | 264 | |
41e840b1 MA |
265 | err1: |
266 | dvb_dmx_release(&mantis->demux); | |
3e978a82 | 267 | |
41e840b1 MA |
268 | err0: |
269 | dvb_unregister_adapter(&mantis->dvb_adapter); | |
270 | ||
271 | return result; | |
272 | } | |
b3b96144 | 273 | EXPORT_SYMBOL_GPL(mantis_dvb_init); |
41e840b1 | 274 | |
b3b96144 | 275 | int __devexit mantis_dvb_exit(struct mantis_pci *mantis) |
41e840b1 | 276 | { |
b3b96144 | 277 | int err; |
41e840b1 | 278 | |
3e978a82 MA |
279 | if (mantis->fe) { |
280 | // mantis_ca_exit(mantis); | |
281 | err = mantis_frontend_shutdown(mantis); | |
282 | if (err != 0) | |
283 | dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err); | |
284 | ||
285 | dvb_unregister_frontend(mantis->fe); | |
286 | } | |
41e840b1 | 287 | |
41e840b1 MA |
288 | tasklet_kill(&mantis->tasklet); |
289 | dvb_net_release(&mantis->dvbnet); | |
3e978a82 | 290 | |
41e840b1 MA |
291 | mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); |
292 | mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); | |
3e978a82 | 293 | |
41e840b1 MA |
294 | dvb_dmxdev_release(&mantis->dmxdev); |
295 | dvb_dmx_release(&mantis->demux); | |
296 | ||
b3b96144 | 297 | dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter"); |
41e840b1 MA |
298 | dvb_unregister_adapter(&mantis->dvb_adapter); |
299 | ||
300 | return 0; | |
301 | } | |
b3b96144 | 302 | EXPORT_SYMBOL_GPL(mantis_dvb_exit); |