Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mantis_dvb.c
Go to the documentation of this file.
1 /*
2  Mantis PCI bridge driver
3  Copyright (C) Manu Abraham ([email protected])
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 
42 
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 }
70 
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 }
88 
89 static int mantis_frontend_shutdown(struct mantis_pci *mantis)
90 {
91  int err;
92 
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 
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 
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 
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 
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 
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 |
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 .. */
248 err5:
249  tasklet_kill(&mantis->tasklet);
250  dvb_net_release(&mantis->dvbnet);
251  if (mantis->fe) {
252  dvb_unregister_frontend(mantis->fe);
253  dvb_frontend_detach(mantis->fe);
254  }
255 err4:
256  mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
257 
258 err3:
259  mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
260 
261 err2:
262  dvb_dmxdev_release(&mantis->dmxdev);
263 
264 err1:
265  dvb_dmx_release(&mantis->demux);
266 
267 err0:
268  dvb_unregister_adapter(&mantis->dvb_adapter);
269 
270  return result;
271 }
273 
275 {
276  int err;
277 
278  if (mantis->fe) {
279  /* mantis_ca_exit(mantis); */
280  err = mantis_frontend_shutdown(mantis);
281  if (err != 0)
282  dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err);
283  dvb_unregister_frontend(mantis->fe);
284  dvb_frontend_detach(mantis->fe);
285  }
286 
287  tasklet_kill(&mantis->tasklet);
288  dvb_net_release(&mantis->dvbnet);
289 
290  mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
291  mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
292 
293  dvb_dmxdev_release(&mantis->dmxdev);
294  dvb_dmx_release(&mantis->demux);
295 
296  dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter");
298 
299  return 0;
300 }