]>
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 | ||
20 | #include <linux/bitops.h> | |
21 | #include "mantis_common.h" | |
22 | #include "mantis_core.h" | |
23 | ||
24 | #include "dmxdev.h" | |
25 | #include "dvbdev.h" | |
26 | #include "dvb_demux.h" | |
27 | #include "dvb_frontend.h" | |
28 | #include "mantis_vp1033.h" | |
29 | #include "mantis_vp1034.h" | |
873c8c25 | 30 | #include "mantis_vp1041.h" |
41e840b1 | 31 | #include "mantis_vp2033.h" |
b2eb1312 | 32 | #include "mantis_vp2040.h" |
41e840b1 MA |
33 | #include "mantis_vp3030.h" |
34 | ||
616f75e1 MA |
35 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
36 | ||
41e840b1 MA |
37 | /* Tuner power supply control */ |
38 | void mantis_fe_powerup(struct mantis_pci *mantis) | |
39 | { | |
40 | dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Power ON"); | |
41 | gpio_set_bits(mantis, 0x0c, 1); | |
42 | msleep_interruptible(100); | |
43 | gpio_set_bits(mantis, 0x0c, 1); | |
44 | msleep_interruptible(100); | |
45 | } | |
46 | ||
47 | void mantis_fe_powerdown(struct mantis_pci *mantis) | |
48 | { | |
49 | dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Power OFF"); | |
50 | gpio_set_bits(mantis, 0x0c, 0); | |
51 | } | |
52 | ||
53 | static int mantis_fe_reset(struct dvb_frontend *fe) | |
54 | { | |
55 | struct mantis_pci *mantis = fe->dvb->priv; | |
56 | ||
57 | dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Reset"); | |
58 | gpio_set_bits(mantis, 13, 0); | |
59 | msleep_interruptible(100); | |
60 | gpio_set_bits(mantis, 13, 0); | |
61 | msleep_interruptible(100); | |
62 | gpio_set_bits(mantis, 13, 1); | |
63 | msleep_interruptible(100); | |
64 | gpio_set_bits(mantis, 13, 1); | |
65 | ||
66 | return 0; | |
67 | } | |
68 | ||
69 | static int mantis_frontend_reset(struct mantis_pci *mantis) | |
70 | { | |
71 | dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Reset"); | |
72 | gpio_set_bits(mantis, 13, 0); | |
73 | msleep_interruptible(100); | |
74 | gpio_set_bits(mantis, 13, 0); | |
75 | msleep_interruptible(100); | |
76 | gpio_set_bits(mantis, 13, 1); | |
77 | msleep_interruptible(100); | |
78 | gpio_set_bits(mantis, 13, 1); | |
79 | ||
80 | return 0; | |
81 | } | |
82 | ||
83 | static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) | |
84 | { | |
85 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | |
86 | struct mantis_pci *mantis = dvbdmx->priv; | |
87 | ||
88 | dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB Start feed"); | |
89 | if (!dvbdmx->dmx.frontend) { | |
90 | dprintk(verbose, MANTIS_DEBUG, 1, "no frontend ?"); | |
91 | return -EINVAL; | |
92 | } | |
93 | mantis->feeds++; | |
94 | dprintk(verbose, MANTIS_DEBUG, 1, | |
95 | "mantis start feed, feeds=%d", | |
96 | mantis->feeds); | |
97 | ||
98 | if (mantis->feeds == 1) { | |
99 | dprintk(verbose, MANTIS_DEBUG, 1, "mantis start feed & dma"); | |
100 | printk("mantis start feed & dma\n"); | |
101 | mantis_dma_start(mantis); | |
102 | } | |
103 | ||
104 | return mantis->feeds; | |
105 | } | |
106 | ||
107 | static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | |
108 | { | |
109 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | |
110 | struct mantis_pci *mantis = dvbdmx->priv; | |
111 | ||
112 | dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB Stop feed"); | |
113 | if (!dvbdmx->dmx.frontend) { | |
114 | dprintk(verbose, MANTIS_DEBUG, 1, "no frontend ?"); | |
115 | return -EINVAL; | |
116 | } | |
117 | mantis->feeds--; | |
118 | if (mantis->feeds == 0) { | |
119 | dprintk(verbose, MANTIS_DEBUG, 1, "mantis stop feed and dma"); | |
120 | printk("mantis stop feed and dma\n"); | |
121 | mantis_dma_stop(mantis); | |
122 | } | |
123 | return 0; | |
124 | } | |
125 | ||
126 | int __devinit mantis_dvb_init(struct mantis_pci *mantis) | |
127 | { | |
128 | int result; | |
129 | ||
130 | dprintk(verbose, MANTIS_DEBUG, 1, "dvb_register_adapter"); | |
131 | if (dvb_register_adapter(&mantis->dvb_adapter, | |
132 | "Mantis dvb adapter", THIS_MODULE, | |
616f75e1 MA |
133 | &mantis->pdev->dev, |
134 | adapter_nr) < 0) { | |
41e840b1 MA |
135 | |
136 | dprintk(verbose, MANTIS_ERROR, 1, "Error registering adapter"); | |
137 | return -ENODEV; | |
138 | } | |
139 | mantis->dvb_adapter.priv = mantis; | |
140 | mantis->demux.dmx.capabilities = DMX_TS_FILTERING | | |
141 | DMX_SECTION_FILTERING | | |
142 | DMX_MEMORY_BASED_FILTERING; | |
143 | ||
144 | mantis->demux.priv = mantis; | |
145 | mantis->demux.filternum = 256; | |
146 | mantis->demux.feednum = 256; | |
147 | mantis->demux.start_feed = mantis_dvb_start_feed; | |
148 | mantis->demux.stop_feed = mantis_dvb_stop_feed; | |
149 | mantis->demux.write_to_decoder = NULL; | |
41e840b1 MA |
150 | dprintk(verbose, MANTIS_DEBUG, 1, "dvb_dmx_init"); |
151 | if ((result = dvb_dmx_init(&mantis->demux)) < 0) { | |
152 | dprintk(verbose, MANTIS_ERROR, 1, | |
153 | "dvb_dmx_init failed, ERROR=%d", result); | |
154 | ||
155 | goto err0; | |
156 | } | |
157 | mantis->dmxdev.filternum = 256; | |
158 | mantis->dmxdev.demux = &mantis->demux.dmx; | |
159 | mantis->dmxdev.capabilities = 0; | |
160 | dprintk(verbose, MANTIS_DEBUG, 1, "dvb_dmxdev_init"); | |
161 | if ((result = dvb_dmxdev_init(&mantis->dmxdev, | |
162 | &mantis->dvb_adapter)) < 0) { | |
163 | ||
164 | dprintk(verbose, MANTIS_ERROR, 1, | |
165 | "dvb_dmxdev_init failed, ERROR=%d", result); | |
166 | goto err1; | |
167 | } | |
168 | mantis->fe_hw.source = DMX_FRONTEND_0; | |
169 | if ((result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, | |
170 | &mantis->fe_hw)) < 0) { | |
171 | ||
172 | dprintk(verbose, MANTIS_ERROR, 1, | |
173 | "dvb_dmx_init failed, ERROR=%d", result); | |
174 | ||
175 | goto err2; | |
176 | } | |
177 | mantis->fe_mem.source = DMX_MEMORY_FE; | |
178 | if ((result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, | |
179 | &mantis->fe_mem)) < 0) { | |
180 | dprintk(verbose, MANTIS_ERROR, 1, | |
181 | "dvb_dmx_init failed, ERROR=%d", result); | |
182 | ||
183 | goto err3; | |
184 | } | |
185 | if ((result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, | |
186 | &mantis->fe_hw)) < 0) { | |
187 | ||
188 | dprintk(verbose, MANTIS_ERROR, 1, | |
189 | "dvb_dmx_init failed, ERROR=%d", result); | |
190 | ||
191 | goto err4; | |
192 | } | |
193 | dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx); | |
194 | tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis); | |
195 | mantis_frontend_init(mantis); | |
d9dd5f71 MA |
196 | mantis_ca_init(mantis); |
197 | ||
41e840b1 MA |
198 | return 0; |
199 | ||
200 | /* Error conditions .. */ | |
201 | err4: | |
202 | mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); | |
203 | err3: | |
204 | mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); | |
205 | err2: | |
206 | dvb_dmxdev_release(&mantis->dmxdev); | |
207 | err1: | |
208 | dvb_dmx_release(&mantis->demux); | |
209 | err0: | |
210 | dvb_unregister_adapter(&mantis->dvb_adapter); | |
211 | ||
212 | return result; | |
213 | } | |
214 | ||
41e840b1 MA |
215 | int __devinit mantis_frontend_init(struct mantis_pci *mantis) |
216 | { | |
217 | dprintk(verbose, MANTIS_DEBUG, 1, "Mantis frontend Init"); | |
218 | mantis_fe_powerup(mantis); | |
219 | mantis_frontend_reset(mantis); | |
df0cca17 MA |
220 | dprintk(verbose, MANTIS_DEBUG, 1, "Device ID=%02x", mantis->subsystem_device); |
221 | switch (mantis->subsystem_device) { | |
41e840b1 MA |
222 | case MANTIS_VP_1033_DVB_S: // VP-1033 |
223 | dprintk(verbose, MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)"); | |
224 | mantis->fe = stv0299_attach(&lgtdqcs001f_config, | |
225 | &mantis->adapter); | |
226 | ||
227 | if (mantis->fe) { | |
228 | mantis->fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set; | |
229 | dprintk(verbose, MANTIS_ERROR, 1, | |
230 | "found STV0299 DVB-S frontend @ 0x%02x", | |
231 | lgtdqcs001f_config.demod_address); | |
232 | ||
233 | dprintk(verbose, MANTIS_ERROR, 1, | |
234 | "Mantis DVB-S STV0299 frontend attach success"); | |
235 | } | |
236 | break; | |
237 | case MANTIS_VP_1034_DVB_S: // VP-1034 | |
238 | dprintk(verbose, MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); | |
239 | mantis->fe = mb86a16_attach(&vp1034_config, &mantis->adapter); | |
240 | if (mantis->fe) { | |
241 | dprintk(verbose, MANTIS_ERROR, 1, | |
242 | "found MB86A16 DVB-S/DSS frontend @0x%02x", | |
243 | vp1034_config.demod_address); | |
244 | ||
245 | } | |
246 | break; | |
873c8c25 | 247 | case MANTIS_VP_1041_DVB_S2: |
35afca91 | 248 | case TECHNISAT_SKYSTAR_HD2: |
873c8c25 MA |
249 | mantis->fe = stb0899_attach(&vp1041_config, &mantis->adapter); |
250 | if (mantis->fe) { | |
251 | dprintk(verbose, MANTIS_ERROR, 1, | |
252 | "found STB0899 DVB-S/DVB-S2 frontend @0x%02x", | |
253 | vp1041_config.demod_address); | |
254 | ||
255 | if (stb6100_attach(mantis->fe, &vp1041_stb6100_config, &mantis->adapter)) { | |
256 | if (!lnbp21_attach(mantis->fe, &mantis->adapter, 0, 0)) { | |
257 | printk("%s: No LNBP21 found!\n", __FUNCTION__); | |
258 | mantis->fe = NULL; | |
259 | } | |
260 | } else { | |
261 | mantis->fe = NULL; | |
262 | } | |
263 | } | |
264 | break; | |
41e840b1 | 265 | case MANTIS_VP_2033_DVB_C: // VP-2033 |
ec1b6ff1 NE |
266 | case MANTIS_VP_2040_DVB_C: // VP-2040 |
267 | case TERRATEC_CINERGY_C_PCI: | |
268 | case TECHNISAT_CABLESTAR_HD2: | |
41e840b1 | 269 | dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); |
ec1b6ff1 NE |
270 | mantis->fe = tda10021_attach(&philips_cu1216_config, |
271 | &mantis->adapter, | |
272 | read_pwm(mantis)); | |
273 | ||
41e840b1 | 274 | if (mantis->fe) { |
41e840b1 | 275 | dprintk(verbose, MANTIS_ERROR, 1, |
b2eb1312 | 276 | "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", |
41e840b1 | 277 | philips_cu1216_config.demod_address); |
ec1b6ff1 NE |
278 | } else { |
279 | mantis->fe = tda10023_attach(&tda10023_cu1216_config, | |
280 | &mantis->adapter, | |
281 | read_pwm(mantis)); | |
282 | ||
283 | if (mantis->fe) { | |
284 | dprintk(verbose, MANTIS_ERROR, 1, | |
285 | "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", | |
286 | philips_cu1216_config.demod_address); | |
287 | } | |
41e840b1 | 288 | } |
b2eb1312 MA |
289 | if (mantis->fe) { |
290 | mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; | |
b2eb1312 MA |
291 | dprintk(verbose, MANTIS_ERROR, 1, |
292 | "Mantis DVB-C Philips CU1216 frontend attach success"); | |
293 | } | |
294 | break; | |
41e840b1 MA |
295 | default: |
296 | dprintk(verbose, MANTIS_DEBUG, 1, "Unknown frontend:[0x%02x]", | |
297 | mantis->sub_device_id); | |
298 | ||
299 | return -ENODEV; | |
300 | } | |
301 | if (mantis->fe == NULL) { | |
302 | dprintk(verbose, MANTIS_ERROR, 1, "!!! NO Frontends found !!!"); | |
303 | return -ENODEV; | |
304 | } else { | |
305 | if (dvb_register_frontend(&mantis->dvb_adapter, mantis->fe)) { | |
306 | dprintk(verbose, MANTIS_ERROR, 1, | |
307 | "ERROR: Frontend registration failed"); | |
308 | ||
309 | if (mantis->fe->ops.release) | |
310 | mantis->fe->ops.release(mantis->fe); | |
311 | ||
312 | mantis->fe = NULL; | |
313 | return -ENODEV; | |
314 | } | |
315 | } | |
316 | ||
317 | return 0; | |
318 | } | |
319 | ||
320 | int __devexit mantis_dvb_exit(struct mantis_pci *mantis) | |
321 | { | |
3062b157 | 322 | mantis_ca_exit(mantis); |
41e840b1 MA |
323 | tasklet_kill(&mantis->tasklet); |
324 | dvb_net_release(&mantis->dvbnet); | |
325 | mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); | |
326 | mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); | |
327 | dvb_dmxdev_release(&mantis->dmxdev); | |
328 | dvb_dmx_release(&mantis->demux); | |
329 | ||
330 | if (mantis->fe) | |
331 | dvb_unregister_frontend(mantis->fe); | |
332 | dprintk(verbose, MANTIS_DEBUG, 1, "dvb_unregister_adapter"); | |
333 | dvb_unregister_adapter(&mantis->dvb_adapter); | |
334 | ||
335 | return 0; | |
336 | } |