Commit | Line | Data |
---|---|---|
41e840b1 MA |
1 | /* |
2 | Mantis PCI bridge driver | |
8825a097 | 3 | Copyright (C) Manu Abraham (abraham.manu@gmail.com) |
41e840b1 MA |
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 | 22 | |
b3b96144 MA |
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> | |
41e840b1 MA |
28 | |
29 | #include "dmxdev.h" | |
30 | #include "dvbdev.h" | |
31 | #include "dvb_demux.h" | |
32 | #include "dvb_frontend.h" | |
b3b96144 | 33 | #include "dvb_net.h" |
41e840b1 | 34 | |
b3b96144 MA |
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" | |
616f75e1 | 40 | |
b3b96144 | 41 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
41e840b1 | 42 | |
b3b96144 | 43 | int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power) |
41e840b1 | 44 | { |
b3b96144 MA |
45 | struct mantis_hwconfig *config = mantis->hwconfig; |
46 | ||
47 | switch (power) { | |
48 | case POWER_ON: | |
49 | dprintk(MANTIS_DEBUG, 1, "Power ON"); | |
3037fd14 | 50 | mantis_gpio_set_bits(mantis, config->power, POWER_ON); |
b3b96144 | 51 | msleep(100); |
3037fd14 | 52 | mantis_gpio_set_bits(mantis, config->power, POWER_ON); |
b3b96144 MA |
53 | msleep(100); |
54 | break; | |
41e840b1 | 55 | |
b3b96144 MA |
56 | case POWER_OFF: |
57 | dprintk(MANTIS_DEBUG, 1, "Power OFF"); | |
3037fd14 | 58 | mantis_gpio_set_bits(mantis, config->power, POWER_OFF); |
b3b96144 MA |
59 | msleep(100); |
60 | break; | |
41e840b1 | 61 | |
b3b96144 MA |
62 | default: |
63 | dprintk(MANTIS_DEBUG, 1, "Unknown state <%02x>", power); | |
64 | return -1; | |
65 | } | |
41e840b1 MA |
66 | |
67 | return 0; | |
68 | } | |
b3b96144 | 69 | EXPORT_SYMBOL_GPL(mantis_frontend_power); |
41e840b1 | 70 | |
b3b96144 | 71 | void mantis_frontend_soft_reset(struct mantis_pci *mantis) |
41e840b1 | 72 | { |
b3b96144 MA |
73 | struct mantis_hwconfig *config = mantis->hwconfig; |
74 | ||
75 | dprintk(MANTIS_DEBUG, 1, "Frontend RESET"); | |
3037fd14 | 76 | mantis_gpio_set_bits(mantis, config->reset, 0); |
b3b96144 | 77 | msleep(100); |
3037fd14 | 78 | mantis_gpio_set_bits(mantis, config->reset, 0); |
b3b96144 | 79 | msleep(100); |
3037fd14 | 80 | mantis_gpio_set_bits(mantis, config->reset, 1); |
b3b96144 | 81 | msleep(100); |
3037fd14 | 82 | mantis_gpio_set_bits(mantis, config->reset, 1); |
b3b96144 MA |
83 | msleep(100); |
84 | ||
85 | return; | |
86 | } | |
87 | EXPORT_SYMBOL_GPL(mantis_frontend_soft_reset); | |
88 | ||
89 | static 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 | } | |
41e840b1 MA |
99 | |
100 | return 0; | |
101 | } | |
102 | ||
103 | static 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 | ||
b3b96144 | 108 | dprintk(MANTIS_DEBUG, 1, "Mantis DVB Start feed"); |
41e840b1 | 109 | if (!dvbdmx->dmx.frontend) { |
b3b96144 | 110 | dprintk(MANTIS_DEBUG, 1, "no frontend ?"); |
41e840b1 MA |
111 | return -EINVAL; |
112 | } | |
b3b96144 | 113 | |
41e840b1 | 114 | mantis->feeds++; |
b3b96144 | 115 | dprintk(MANTIS_DEBUG, 1, "mantis start feed, feeds=%d", mantis->feeds); |
41e840b1 MA |
116 | |
117 | if (mantis->feeds == 1) { | |
b3b96144 | 118 | dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma"); |
41e840b1 | 119 | mantis_dma_start(mantis); |
9c81496a | 120 | tasklet_enable(&mantis->tasklet); |
41e840b1 MA |
121 | } |
122 | ||
123 | return mantis->feeds; | |
124 | } | |
125 | ||
126 | static 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 | ||
b3b96144 | 131 | dprintk(MANTIS_DEBUG, 1, "Mantis DVB Stop feed"); |
41e840b1 | 132 | if (!dvbdmx->dmx.frontend) { |
b3b96144 | 133 | dprintk(MANTIS_DEBUG, 1, "no frontend ?"); |
41e840b1 MA |
134 | return -EINVAL; |
135 | } | |
b3b96144 | 136 | |
41e840b1 MA |
137 | mantis->feeds--; |
138 | if (mantis->feeds == 0) { | |
b3b96144 | 139 | dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma"); |
9c81496a | 140 | tasklet_disable(&mantis->tasklet); |
41e840b1 MA |
141 | mantis_dma_stop(mantis); |
142 | } | |
b3b96144 | 143 | |
41e840b1 MA |
144 | return 0; |
145 | } | |
146 | ||
147 | int __devinit mantis_dvb_init(struct mantis_pci *mantis) | |
148 | { | |
b3b96144 MA |
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); | |
41e840b1 | 159 | |
b3b96144 | 160 | if (result < 0) { |
41e840b1 | 161 | |
b3b96144 | 162 | dprintk(MANTIS_ERROR, 1, "Error registering adapter"); |
41e840b1 MA |
163 | return -ENODEV; |
164 | } | |
b3b96144 MA |
165 | |
166 | mantis->dvb_adapter.priv = mantis; | |
167 | mantis->demux.dmx.capabilities = DMX_TS_FILTERING | | |
41e840b1 MA |
168 | DMX_SECTION_FILTERING | |
169 | DMX_MEMORY_BASED_FILTERING; | |
170 | ||
b3b96144 MA |
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); | |
41e840b1 MA |
182 | |
183 | goto err0; | |
184 | } | |
b3b96144 MA |
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); | |
41e840b1 MA |
195 | goto err1; |
196 | } | |
41e840b1 | 197 | |
b3b96144 MA |
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) { | |
41e840b1 | 201 | |
b3b96144 | 202 | dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); |
41e840b1 MA |
203 | goto err2; |
204 | } | |
41e840b1 | 205 | |
b3b96144 | 206 | mantis->fe_mem.source = DMX_MEMORY_FE; |
f5ae4f6f | 207 | result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_mem); |
b3b96144 | 208 | if (result < 0) { |
f5ae4f6f | 209 | dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); |
41e840b1 MA |
210 | goto err3; |
211 | } | |
41e840b1 | 212 | |
b3b96144 MA |
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); | |
41e840b1 MA |
216 | goto err4; |
217 | } | |
b3b96144 | 218 | |
41e840b1 MA |
219 | dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx); |
220 | tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis); | |
9c81496a | 221 | tasklet_disable(&mantis->tasklet); |
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 { | |
b3b96144 MA |
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 | } | |
d9dd5f71 | 244 | |
41e840b1 MA |
245 | return 0; |
246 | ||
b3b96144 MA |
247 | /* Error conditions .. */ |
248 | err5: | |
249 | tasklet_kill(&mantis->tasklet); | |
250 | dvb_net_release(&mantis->dvbnet); | |
68fe255c MA |
251 | dvb_unregister_frontend(mantis->fe); |
252 | dvb_frontend_detach(mantis->fe); | |
41e840b1 MA |
253 | err4: |
254 | mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); | |
3e978a82 | 255 | |
41e840b1 MA |
256 | err3: |
257 | mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); | |
3e978a82 | 258 | |
41e840b1 MA |
259 | err2: |
260 | dvb_dmxdev_release(&mantis->dmxdev); | |
3e978a82 | 261 | |
41e840b1 MA |
262 | err1: |
263 | dvb_dmx_release(&mantis->demux); | |
3e978a82 | 264 | |
41e840b1 MA |
265 | err0: |
266 | dvb_unregister_adapter(&mantis->dvb_adapter); | |
267 | ||
268 | return result; | |
269 | } | |
b3b96144 | 270 | EXPORT_SYMBOL_GPL(mantis_dvb_init); |
41e840b1 | 271 | |
b3b96144 | 272 | int __devexit mantis_dvb_exit(struct mantis_pci *mantis) |
41e840b1 | 273 | { |
b3b96144 | 274 | int err; |
41e840b1 | 275 | |
3e978a82 | 276 | if (mantis->fe) { |
f5ae4f6f | 277 | /* mantis_ca_exit(mantis); */ |
3e978a82 MA |
278 | err = mantis_frontend_shutdown(mantis); |
279 | if (err != 0) | |
280 | dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err); | |
3e978a82 | 281 | dvb_unregister_frontend(mantis->fe); |
c5e598a6 | 282 | dvb_frontend_detach(mantis->fe); |
3e978a82 | 283 | } |
41e840b1 | 284 | |
41e840b1 MA |
285 | tasklet_kill(&mantis->tasklet); |
286 | dvb_net_release(&mantis->dvbnet); | |
3e978a82 | 287 | |
41e840b1 MA |
288 | mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); |
289 | mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); | |
3e978a82 | 290 | |
41e840b1 MA |
291 | dvb_dmxdev_release(&mantis->dmxdev); |
292 | dvb_dmx_release(&mantis->demux); | |
293 | ||
b3b96144 | 294 | dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter"); |
41e840b1 MA |
295 | dvb_unregister_adapter(&mantis->dvb_adapter); |
296 | ||
297 | return 0; | |
298 | } | |
b3b96144 | 299 | EXPORT_SYMBOL_GPL(mantis_dvb_exit); |