diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-06-14 15:35:53 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-13 22:08:14 -0400 |
commit | 3d6c2bc08ac4f75bf3597740357c98f2207ca412 (patch) | |
tree | dfe6d7c9e466cef06224ffadd3310d61f41a4678 /drivers/media/dvb-core/dvb_frontend.c | |
parent | 5bc3cb743bbab408792c1b4ef31adf6268aa4b7e (diff) |
[media] dvb: move the dvb core one level up
just like the V4L2 core, move the DVB core to drivers/media, as the
intention is to get rid of both "video" and "dvb" directories.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb-core/dvb_frontend.c')
-rw-r--r-- | drivers/media/dvb-core/dvb_frontend.c | 2553 |
1 files changed, 2553 insertions, 0 deletions
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c new file mode 100644 index 000000000000..12e5eb1fff76 --- /dev/null +++ b/drivers/media/dvb-core/dvb_frontend.c | |||
@@ -0,0 +1,2553 @@ | |||
1 | /* | ||
2 | * dvb_frontend.c: DVB frontend tuning interface/thread | ||
3 | * | ||
4 | * | ||
5 | * Copyright (C) 1999-2001 Ralph Metzler | ||
6 | * Marcus Metzler | ||
7 | * Holger Waechtler | ||
8 | * for convergence integrated media GmbH | ||
9 | * | ||
10 | * Copyright (C) 2004 Andrew de Quincey (tuning thread cleanup) | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
25 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
26 | */ | ||
27 | |||
28 | /* Enables DVBv3 compatibility bits at the headers */ | ||
29 | #define __DVB_CORE__ | ||
30 | |||
31 | #include <linux/string.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/sched.h> | ||
34 | #include <linux/wait.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/poll.h> | ||
37 | #include <linux/semaphore.h> | ||
38 | #include <linux/module.h> | ||
39 | #include <linux/list.h> | ||
40 | #include <linux/freezer.h> | ||
41 | #include <linux/jiffies.h> | ||
42 | #include <linux/kthread.h> | ||
43 | #include <asm/processor.h> | ||
44 | |||
45 | #include "dvb_frontend.h" | ||
46 | #include "dvbdev.h" | ||
47 | #include <linux/dvb/version.h> | ||
48 | |||
49 | static int dvb_frontend_debug; | ||
50 | static int dvb_shutdown_timeout; | ||
51 | static int dvb_force_auto_inversion; | ||
52 | static int dvb_override_tune_delay; | ||
53 | static int dvb_powerdown_on_sleep = 1; | ||
54 | static int dvb_mfe_wait_time = 5; | ||
55 | |||
56 | module_param_named(frontend_debug, dvb_frontend_debug, int, 0644); | ||
57 | MODULE_PARM_DESC(frontend_debug, "Turn on/off frontend core debugging (default:off)."); | ||
58 | module_param(dvb_shutdown_timeout, int, 0644); | ||
59 | MODULE_PARM_DESC(dvb_shutdown_timeout, "wait <shutdown_timeout> seconds after close() before suspending hardware"); | ||
60 | module_param(dvb_force_auto_inversion, int, 0644); | ||
61 | MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always"); | ||
62 | module_param(dvb_override_tune_delay, int, 0644); | ||
63 | MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt"); | ||
64 | module_param(dvb_powerdown_on_sleep, int, 0644); | ||
65 | MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB voltage off on sleep (default)"); | ||
66 | module_param(dvb_mfe_wait_time, int, 0644); | ||
67 | MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open() for multi-frontend to become available (default:5 seconds)"); | ||
68 | |||
69 | #define dprintk if (dvb_frontend_debug) printk | ||
70 | |||
71 | #define FESTATE_IDLE 1 | ||
72 | #define FESTATE_RETUNE 2 | ||
73 | #define FESTATE_TUNING_FAST 4 | ||
74 | #define FESTATE_TUNING_SLOW 8 | ||
75 | #define FESTATE_TUNED 16 | ||
76 | #define FESTATE_ZIGZAG_FAST 32 | ||
77 | #define FESTATE_ZIGZAG_SLOW 64 | ||
78 | #define FESTATE_DISEQC 128 | ||
79 | #define FESTATE_ERROR 256 | ||
80 | #define FESTATE_WAITFORLOCK (FESTATE_TUNING_FAST | FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW | FESTATE_DISEQC) | ||
81 | #define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST) | ||
82 | #define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW) | ||
83 | #define FESTATE_LOSTLOCK (FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW) | ||
84 | |||
85 | #define FE_ALGO_HW 1 | ||
86 | /* | ||
87 | * FESTATE_IDLE. No tuning parameters have been supplied and the loop is idling. | ||
88 | * FESTATE_RETUNE. Parameters have been supplied, but we have not yet performed the first tune. | ||
89 | * FESTATE_TUNING_FAST. Tuning parameters have been supplied and fast zigzag scan is in progress. | ||
90 | * FESTATE_TUNING_SLOW. Tuning parameters have been supplied. Fast zigzag failed, so we're trying again, but slower. | ||
91 | * FESTATE_TUNED. The frontend has successfully locked on. | ||
92 | * FESTATE_ZIGZAG_FAST. The lock has been lost, and a fast zigzag has been initiated to try and regain it. | ||
93 | * FESTATE_ZIGZAG_SLOW. The lock has been lost. Fast zigzag has been failed, so we're trying again, but slower. | ||
94 | * FESTATE_DISEQC. A DISEQC command has just been issued. | ||
95 | * FESTATE_WAITFORLOCK. When we're waiting for a lock. | ||
96 | * FESTATE_SEARCHING_FAST. When we're searching for a signal using a fast zigzag scan. | ||
97 | * FESTATE_SEARCHING_SLOW. When we're searching for a signal using a slow zigzag scan. | ||
98 | * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again. | ||
99 | */ | ||
100 | |||
101 | #define DVB_FE_NO_EXIT 0 | ||
102 | #define DVB_FE_NORMAL_EXIT 1 | ||
103 | #define DVB_FE_DEVICE_REMOVED 2 | ||
104 | |||
105 | static DEFINE_MUTEX(frontend_mutex); | ||
106 | |||
107 | struct dvb_frontend_private { | ||
108 | |||
109 | /* thread/frontend values */ | ||
110 | struct dvb_device *dvbdev; | ||
111 | struct dvb_frontend_parameters parameters_out; | ||
112 | struct dvb_fe_events events; | ||
113 | struct semaphore sem; | ||
114 | struct list_head list_head; | ||
115 | wait_queue_head_t wait_queue; | ||
116 | struct task_struct *thread; | ||
117 | unsigned long release_jiffies; | ||
118 | unsigned int exit; | ||
119 | unsigned int wakeup; | ||
120 | fe_status_t status; | ||
121 | unsigned long tune_mode_flags; | ||
122 | unsigned int delay; | ||
123 | unsigned int reinitialise; | ||
124 | int tone; | ||
125 | int voltage; | ||
126 | |||
127 | /* swzigzag values */ | ||
128 | unsigned int state; | ||
129 | unsigned int bending; | ||
130 | int lnb_drift; | ||
131 | unsigned int inversion; | ||
132 | unsigned int auto_step; | ||
133 | unsigned int auto_sub_step; | ||
134 | unsigned int started_auto_step; | ||
135 | unsigned int min_delay; | ||
136 | unsigned int max_drift; | ||
137 | unsigned int step_size; | ||
138 | int quality; | ||
139 | unsigned int check_wrapped; | ||
140 | enum dvbfe_search algo_status; | ||
141 | }; | ||
142 | |||
143 | static void dvb_frontend_wakeup(struct dvb_frontend *fe); | ||
144 | static int dtv_get_frontend(struct dvb_frontend *fe, | ||
145 | struct dvb_frontend_parameters *p_out); | ||
146 | static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, | ||
147 | struct dvb_frontend_parameters *p); | ||
148 | |||
149 | static bool has_get_frontend(struct dvb_frontend *fe) | ||
150 | { | ||
151 | return fe->ops.get_frontend != NULL; | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | * Due to DVBv3 API calls, a delivery system should be mapped into one of | ||
156 | * the 4 DVBv3 delivery systems (FE_QPSK, FE_QAM, FE_OFDM or FE_ATSC), | ||
157 | * otherwise, a DVBv3 call will fail. | ||
158 | */ | ||
159 | enum dvbv3_emulation_type { | ||
160 | DVBV3_UNKNOWN, | ||
161 | DVBV3_QPSK, | ||
162 | DVBV3_QAM, | ||
163 | DVBV3_OFDM, | ||
164 | DVBV3_ATSC, | ||
165 | }; | ||
166 | |||
167 | static enum dvbv3_emulation_type dvbv3_type(u32 delivery_system) | ||
168 | { | ||
169 | switch (delivery_system) { | ||
170 | case SYS_DVBC_ANNEX_A: | ||
171 | case SYS_DVBC_ANNEX_C: | ||
172 | return DVBV3_QAM; | ||
173 | case SYS_DVBS: | ||
174 | case SYS_DVBS2: | ||
175 | case SYS_TURBO: | ||
176 | case SYS_ISDBS: | ||
177 | case SYS_DSS: | ||
178 | return DVBV3_QPSK; | ||
179 | case SYS_DVBT: | ||
180 | case SYS_DVBT2: | ||
181 | case SYS_ISDBT: | ||
182 | case SYS_DTMB: | ||
183 | return DVBV3_OFDM; | ||
184 | case SYS_ATSC: | ||
185 | case SYS_ATSCMH: | ||
186 | case SYS_DVBC_ANNEX_B: | ||
187 | return DVBV3_ATSC; | ||
188 | case SYS_UNDEFINED: | ||
189 | case SYS_ISDBC: | ||
190 | case SYS_DVBH: | ||
191 | case SYS_DAB: | ||
192 | default: | ||
193 | /* | ||
194 | * Doesn't know how to emulate those types and/or | ||
195 | * there's no frontend driver from this type yet | ||
196 | * with some emulation code, so, we're not sure yet how | ||
197 | * to handle them, or they're not compatible with a DVBv3 call. | ||
198 | */ | ||
199 | return DVBV3_UNKNOWN; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status) | ||
204 | { | ||
205 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
206 | struct dvb_fe_events *events = &fepriv->events; | ||
207 | struct dvb_frontend_event *e; | ||
208 | int wp; | ||
209 | |||
210 | dprintk ("%s\n", __func__); | ||
211 | |||
212 | if ((status & FE_HAS_LOCK) && has_get_frontend(fe)) | ||
213 | dtv_get_frontend(fe, &fepriv->parameters_out); | ||
214 | |||
215 | mutex_lock(&events->mtx); | ||
216 | |||
217 | wp = (events->eventw + 1) % MAX_EVENT; | ||
218 | if (wp == events->eventr) { | ||
219 | events->overflow = 1; | ||
220 | events->eventr = (events->eventr + 1) % MAX_EVENT; | ||
221 | } | ||
222 | |||
223 | e = &events->events[events->eventw]; | ||
224 | e->status = status; | ||
225 | e->parameters = fepriv->parameters_out; | ||
226 | |||
227 | events->eventw = wp; | ||
228 | |||
229 | mutex_unlock(&events->mtx); | ||
230 | |||
231 | wake_up_interruptible (&events->wait_queue); | ||
232 | } | ||
233 | |||
234 | static int dvb_frontend_get_event(struct dvb_frontend *fe, | ||
235 | struct dvb_frontend_event *event, int flags) | ||
236 | { | ||
237 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
238 | struct dvb_fe_events *events = &fepriv->events; | ||
239 | |||
240 | dprintk ("%s\n", __func__); | ||
241 | |||
242 | if (events->overflow) { | ||
243 | events->overflow = 0; | ||
244 | return -EOVERFLOW; | ||
245 | } | ||
246 | |||
247 | if (events->eventw == events->eventr) { | ||
248 | int ret; | ||
249 | |||
250 | if (flags & O_NONBLOCK) | ||
251 | return -EWOULDBLOCK; | ||
252 | |||
253 | up(&fepriv->sem); | ||
254 | |||
255 | ret = wait_event_interruptible (events->wait_queue, | ||
256 | events->eventw != events->eventr); | ||
257 | |||
258 | if (down_interruptible (&fepriv->sem)) | ||
259 | return -ERESTARTSYS; | ||
260 | |||
261 | if (ret < 0) | ||
262 | return ret; | ||
263 | } | ||
264 | |||
265 | mutex_lock(&events->mtx); | ||
266 | *event = events->events[events->eventr]; | ||
267 | events->eventr = (events->eventr + 1) % MAX_EVENT; | ||
268 | mutex_unlock(&events->mtx); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static void dvb_frontend_clear_events(struct dvb_frontend *fe) | ||
274 | { | ||
275 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
276 | struct dvb_fe_events *events = &fepriv->events; | ||
277 | |||
278 | mutex_lock(&events->mtx); | ||
279 | events->eventr = events->eventw; | ||
280 | mutex_unlock(&events->mtx); | ||
281 | } | ||
282 | |||
283 | static void dvb_frontend_init(struct dvb_frontend *fe) | ||
284 | { | ||
285 | dprintk ("DVB: initialising adapter %i frontend %i (%s)...\n", | ||
286 | fe->dvb->num, | ||
287 | fe->id, | ||
288 | fe->ops.info.name); | ||
289 | |||
290 | if (fe->ops.init) | ||
291 | fe->ops.init(fe); | ||
292 | if (fe->ops.tuner_ops.init) { | ||
293 | if (fe->ops.i2c_gate_ctrl) | ||
294 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
295 | fe->ops.tuner_ops.init(fe); | ||
296 | if (fe->ops.i2c_gate_ctrl) | ||
297 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
298 | } | ||
299 | } | ||
300 | |||
301 | void dvb_frontend_reinitialise(struct dvb_frontend *fe) | ||
302 | { | ||
303 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
304 | |||
305 | fepriv->reinitialise = 1; | ||
306 | dvb_frontend_wakeup(fe); | ||
307 | } | ||
308 | EXPORT_SYMBOL(dvb_frontend_reinitialise); | ||
309 | |||
310 | static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked) | ||
311 | { | ||
312 | int q2; | ||
313 | |||
314 | dprintk ("%s\n", __func__); | ||
315 | |||
316 | if (locked) | ||
317 | (fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256; | ||
318 | else | ||
319 | (fepriv->quality) = (fepriv->quality * 220 + 0) / 256; | ||
320 | |||
321 | q2 = fepriv->quality - 128; | ||
322 | q2 *= q2; | ||
323 | |||
324 | fepriv->delay = fepriv->min_delay + q2 * HZ / (128*128); | ||
325 | } | ||
326 | |||
327 | /** | ||
328 | * Performs automatic twiddling of frontend parameters. | ||
329 | * | ||
330 | * @param fe The frontend concerned. | ||
331 | * @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT | ||
332 | * @returns Number of complete iterations that have been performed. | ||
333 | */ | ||
334 | static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wrapped) | ||
335 | { | ||
336 | int autoinversion; | ||
337 | int ready = 0; | ||
338 | int fe_set_err = 0; | ||
339 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
340 | struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp; | ||
341 | int original_inversion = c->inversion; | ||
342 | u32 original_frequency = c->frequency; | ||
343 | |||
344 | /* are we using autoinversion? */ | ||
345 | autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && | ||
346 | (c->inversion == INVERSION_AUTO)); | ||
347 | |||
348 | /* setup parameters correctly */ | ||
349 | while(!ready) { | ||
350 | /* calculate the lnb_drift */ | ||
351 | fepriv->lnb_drift = fepriv->auto_step * fepriv->step_size; | ||
352 | |||
353 | /* wrap the auto_step if we've exceeded the maximum drift */ | ||
354 | if (fepriv->lnb_drift > fepriv->max_drift) { | ||
355 | fepriv->auto_step = 0; | ||
356 | fepriv->auto_sub_step = 0; | ||
357 | fepriv->lnb_drift = 0; | ||
358 | } | ||
359 | |||
360 | /* perform inversion and +/- zigzag */ | ||
361 | switch(fepriv->auto_sub_step) { | ||
362 | case 0: | ||
363 | /* try with the current inversion and current drift setting */ | ||
364 | ready = 1; | ||
365 | break; | ||
366 | |||
367 | case 1: | ||
368 | if (!autoinversion) break; | ||
369 | |||
370 | fepriv->inversion = (fepriv->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF; | ||
371 | ready = 1; | ||
372 | break; | ||
373 | |||
374 | case 2: | ||
375 | if (fepriv->lnb_drift == 0) break; | ||
376 | |||
377 | fepriv->lnb_drift = -fepriv->lnb_drift; | ||
378 | ready = 1; | ||
379 | break; | ||
380 | |||
381 | case 3: | ||
382 | if (fepriv->lnb_drift == 0) break; | ||
383 | if (!autoinversion) break; | ||
384 | |||
385 | fepriv->inversion = (fepriv->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF; | ||
386 | fepriv->lnb_drift = -fepriv->lnb_drift; | ||
387 | ready = 1; | ||
388 | break; | ||
389 | |||
390 | default: | ||
391 | fepriv->auto_step++; | ||
392 | fepriv->auto_sub_step = -1; /* it'll be incremented to 0 in a moment */ | ||
393 | break; | ||
394 | } | ||
395 | |||
396 | if (!ready) fepriv->auto_sub_step++; | ||
397 | } | ||
398 | |||
399 | /* if this attempt would hit where we started, indicate a complete | ||
400 | * iteration has occurred */ | ||
401 | if ((fepriv->auto_step == fepriv->started_auto_step) && | ||
402 | (fepriv->auto_sub_step == 0) && check_wrapped) { | ||
403 | return 1; | ||
404 | } | ||
405 | |||
406 | dprintk("%s: drift:%i inversion:%i auto_step:%i " | ||
407 | "auto_sub_step:%i started_auto_step:%i\n", | ||
408 | __func__, fepriv->lnb_drift, fepriv->inversion, | ||
409 | fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step); | ||
410 | |||
411 | /* set the frontend itself */ | ||
412 | c->frequency += fepriv->lnb_drift; | ||
413 | if (autoinversion) | ||
414 | c->inversion = fepriv->inversion; | ||
415 | tmp = *c; | ||
416 | if (fe->ops.set_frontend) | ||
417 | fe_set_err = fe->ops.set_frontend(fe); | ||
418 | *c = tmp; | ||
419 | if (fe_set_err < 0) { | ||
420 | fepriv->state = FESTATE_ERROR; | ||
421 | return fe_set_err; | ||
422 | } | ||
423 | |||
424 | c->frequency = original_frequency; | ||
425 | c->inversion = original_inversion; | ||
426 | |||
427 | fepriv->auto_sub_step++; | ||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | static void dvb_frontend_swzigzag(struct dvb_frontend *fe) | ||
432 | { | ||
433 | fe_status_t s = 0; | ||
434 | int retval = 0; | ||
435 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
436 | struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp; | ||
437 | |||
438 | /* if we've got no parameters, just keep idling */ | ||
439 | if (fepriv->state & FESTATE_IDLE) { | ||
440 | fepriv->delay = 3*HZ; | ||
441 | fepriv->quality = 0; | ||
442 | return; | ||
443 | } | ||
444 | |||
445 | /* in SCAN mode, we just set the frontend when asked and leave it alone */ | ||
446 | if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) { | ||
447 | if (fepriv->state & FESTATE_RETUNE) { | ||
448 | tmp = *c; | ||
449 | if (fe->ops.set_frontend) | ||
450 | retval = fe->ops.set_frontend(fe); | ||
451 | *c = tmp; | ||
452 | if (retval < 0) | ||
453 | fepriv->state = FESTATE_ERROR; | ||
454 | else | ||
455 | fepriv->state = FESTATE_TUNED; | ||
456 | } | ||
457 | fepriv->delay = 3*HZ; | ||
458 | fepriv->quality = 0; | ||
459 | return; | ||
460 | } | ||
461 | |||
462 | /* get the frontend status */ | ||
463 | if (fepriv->state & FESTATE_RETUNE) { | ||
464 | s = 0; | ||
465 | } else { | ||
466 | if (fe->ops.read_status) | ||
467 | fe->ops.read_status(fe, &s); | ||
468 | if (s != fepriv->status) { | ||
469 | dvb_frontend_add_event(fe, s); | ||
470 | fepriv->status = s; | ||
471 | } | ||
472 | } | ||
473 | |||
474 | /* if we're not tuned, and we have a lock, move to the TUNED state */ | ||
475 | if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) { | ||
476 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
477 | fepriv->state = FESTATE_TUNED; | ||
478 | |||
479 | /* if we're tuned, then we have determined the correct inversion */ | ||
480 | if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && | ||
481 | (c->inversion == INVERSION_AUTO)) { | ||
482 | c->inversion = fepriv->inversion; | ||
483 | } | ||
484 | return; | ||
485 | } | ||
486 | |||
487 | /* if we are tuned already, check we're still locked */ | ||
488 | if (fepriv->state & FESTATE_TUNED) { | ||
489 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
490 | |||
491 | /* we're tuned, and the lock is still good... */ | ||
492 | if (s & FE_HAS_LOCK) { | ||
493 | return; | ||
494 | } else { /* if we _WERE_ tuned, but now don't have a lock */ | ||
495 | fepriv->state = FESTATE_ZIGZAG_FAST; | ||
496 | fepriv->started_auto_step = fepriv->auto_step; | ||
497 | fepriv->check_wrapped = 0; | ||
498 | } | ||
499 | } | ||
500 | |||
501 | /* don't actually do anything if we're in the LOSTLOCK state, | ||
502 | * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */ | ||
503 | if ((fepriv->state & FESTATE_LOSTLOCK) && | ||
504 | (fe->ops.info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) { | ||
505 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
506 | return; | ||
507 | } | ||
508 | |||
509 | /* don't do anything if we're in the DISEQC state, since this | ||
510 | * might be someone with a motorized dish controlled by DISEQC. | ||
511 | * If its actually a re-tune, there will be a SET_FRONTEND soon enough. */ | ||
512 | if (fepriv->state & FESTATE_DISEQC) { | ||
513 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
514 | return; | ||
515 | } | ||
516 | |||
517 | /* if we're in the RETUNE state, set everything up for a brand | ||
518 | * new scan, keeping the current inversion setting, as the next | ||
519 | * tune is _very_ likely to require the same */ | ||
520 | if (fepriv->state & FESTATE_RETUNE) { | ||
521 | fepriv->lnb_drift = 0; | ||
522 | fepriv->auto_step = 0; | ||
523 | fepriv->auto_sub_step = 0; | ||
524 | fepriv->started_auto_step = 0; | ||
525 | fepriv->check_wrapped = 0; | ||
526 | } | ||
527 | |||
528 | /* fast zigzag. */ | ||
529 | if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) { | ||
530 | fepriv->delay = fepriv->min_delay; | ||
531 | |||
532 | /* perform a tune */ | ||
533 | retval = dvb_frontend_swzigzag_autotune(fe, | ||
534 | fepriv->check_wrapped); | ||
535 | if (retval < 0) { | ||
536 | return; | ||
537 | } else if (retval) { | ||
538 | /* OK, if we've run out of trials at the fast speed. | ||
539 | * Drop back to slow for the _next_ attempt */ | ||
540 | fepriv->state = FESTATE_SEARCHING_SLOW; | ||
541 | fepriv->started_auto_step = fepriv->auto_step; | ||
542 | return; | ||
543 | } | ||
544 | fepriv->check_wrapped = 1; | ||
545 | |||
546 | /* if we've just retuned, enter the ZIGZAG_FAST state. | ||
547 | * This ensures we cannot return from an | ||
548 | * FE_SET_FRONTEND ioctl before the first frontend tune | ||
549 | * occurs */ | ||
550 | if (fepriv->state & FESTATE_RETUNE) { | ||
551 | fepriv->state = FESTATE_TUNING_FAST; | ||
552 | } | ||
553 | } | ||
554 | |||
555 | /* slow zigzag */ | ||
556 | if (fepriv->state & FESTATE_SEARCHING_SLOW) { | ||
557 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
558 | |||
559 | /* Note: don't bother checking for wrapping; we stay in this | ||
560 | * state until we get a lock */ | ||
561 | dvb_frontend_swzigzag_autotune(fe, 0); | ||
562 | } | ||
563 | } | ||
564 | |||
565 | static int dvb_frontend_is_exiting(struct dvb_frontend *fe) | ||
566 | { | ||
567 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
568 | |||
569 | if (fepriv->exit != DVB_FE_NO_EXIT) | ||
570 | return 1; | ||
571 | |||
572 | if (fepriv->dvbdev->writers == 1) | ||
573 | if (time_after_eq(jiffies, fepriv->release_jiffies + | ||
574 | dvb_shutdown_timeout * HZ)) | ||
575 | return 1; | ||
576 | |||
577 | return 0; | ||
578 | } | ||
579 | |||
580 | static int dvb_frontend_should_wakeup(struct dvb_frontend *fe) | ||
581 | { | ||
582 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
583 | |||
584 | if (fepriv->wakeup) { | ||
585 | fepriv->wakeup = 0; | ||
586 | return 1; | ||
587 | } | ||
588 | return dvb_frontend_is_exiting(fe); | ||
589 | } | ||
590 | |||
591 | static void dvb_frontend_wakeup(struct dvb_frontend *fe) | ||
592 | { | ||
593 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
594 | |||
595 | fepriv->wakeup = 1; | ||
596 | wake_up_interruptible(&fepriv->wait_queue); | ||
597 | } | ||
598 | |||
599 | static int dvb_frontend_thread(void *data) | ||
600 | { | ||
601 | struct dvb_frontend *fe = data; | ||
602 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
603 | fe_status_t s; | ||
604 | enum dvbfe_algo algo; | ||
605 | |||
606 | bool re_tune = false; | ||
607 | |||
608 | dprintk("%s\n", __func__); | ||
609 | |||
610 | fepriv->check_wrapped = 0; | ||
611 | fepriv->quality = 0; | ||
612 | fepriv->delay = 3*HZ; | ||
613 | fepriv->status = 0; | ||
614 | fepriv->wakeup = 0; | ||
615 | fepriv->reinitialise = 0; | ||
616 | |||
617 | dvb_frontend_init(fe); | ||
618 | |||
619 | set_freezable(); | ||
620 | while (1) { | ||
621 | up(&fepriv->sem); /* is locked when we enter the thread... */ | ||
622 | restart: | ||
623 | wait_event_interruptible_timeout(fepriv->wait_queue, | ||
624 | dvb_frontend_should_wakeup(fe) || kthread_should_stop() | ||
625 | || freezing(current), | ||
626 | fepriv->delay); | ||
627 | |||
628 | if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) { | ||
629 | /* got signal or quitting */ | ||
630 | fepriv->exit = DVB_FE_NORMAL_EXIT; | ||
631 | break; | ||
632 | } | ||
633 | |||
634 | if (try_to_freeze()) | ||
635 | goto restart; | ||
636 | |||
637 | if (down_interruptible(&fepriv->sem)) | ||
638 | break; | ||
639 | |||
640 | if (fepriv->reinitialise) { | ||
641 | dvb_frontend_init(fe); | ||
642 | if (fe->ops.set_tone && fepriv->tone != -1) | ||
643 | fe->ops.set_tone(fe, fepriv->tone); | ||
644 | if (fe->ops.set_voltage && fepriv->voltage != -1) | ||
645 | fe->ops.set_voltage(fe, fepriv->voltage); | ||
646 | fepriv->reinitialise = 0; | ||
647 | } | ||
648 | |||
649 | /* do an iteration of the tuning loop */ | ||
650 | if (fe->ops.get_frontend_algo) { | ||
651 | algo = fe->ops.get_frontend_algo(fe); | ||
652 | switch (algo) { | ||
653 | case DVBFE_ALGO_HW: | ||
654 | dprintk("%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__); | ||
655 | |||
656 | if (fepriv->state & FESTATE_RETUNE) { | ||
657 | dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__); | ||
658 | re_tune = true; | ||
659 | fepriv->state = FESTATE_TUNED; | ||
660 | } else { | ||
661 | re_tune = false; | ||
662 | } | ||
663 | |||
664 | if (fe->ops.tune) | ||
665 | fe->ops.tune(fe, re_tune, fepriv->tune_mode_flags, &fepriv->delay, &s); | ||
666 | |||
667 | if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) { | ||
668 | dprintk("%s: state changed, adding current state\n", __func__); | ||
669 | dvb_frontend_add_event(fe, s); | ||
670 | fepriv->status = s; | ||
671 | } | ||
672 | break; | ||
673 | case DVBFE_ALGO_SW: | ||
674 | dprintk("%s: Frontend ALGO = DVBFE_ALGO_SW\n", __func__); | ||
675 | dvb_frontend_swzigzag(fe); | ||
676 | break; | ||
677 | case DVBFE_ALGO_CUSTOM: | ||
678 | dprintk("%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state); | ||
679 | if (fepriv->state & FESTATE_RETUNE) { | ||
680 | dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__); | ||
681 | fepriv->state = FESTATE_TUNED; | ||
682 | } | ||
683 | /* Case where we are going to search for a carrier | ||
684 | * User asked us to retune again for some reason, possibly | ||
685 | * requesting a search with a new set of parameters | ||
686 | */ | ||
687 | if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) { | ||
688 | if (fe->ops.search) { | ||
689 | fepriv->algo_status = fe->ops.search(fe); | ||
690 | /* We did do a search as was requested, the flags are | ||
691 | * now unset as well and has the flags wrt to search. | ||
692 | */ | ||
693 | } else { | ||
694 | fepriv->algo_status &= ~DVBFE_ALGO_SEARCH_AGAIN; | ||
695 | } | ||
696 | } | ||
697 | /* Track the carrier if the search was successful */ | ||
698 | if (fepriv->algo_status != DVBFE_ALGO_SEARCH_SUCCESS) { | ||
699 | fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; | ||
700 | fepriv->delay = HZ / 2; | ||
701 | } | ||
702 | dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); | ||
703 | fe->ops.read_status(fe, &s); | ||
704 | if (s != fepriv->status) { | ||
705 | dvb_frontend_add_event(fe, s); /* update event list */ | ||
706 | fepriv->status = s; | ||
707 | if (!(s & FE_HAS_LOCK)) { | ||
708 | fepriv->delay = HZ / 10; | ||
709 | fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; | ||
710 | } else { | ||
711 | fepriv->delay = 60 * HZ; | ||
712 | } | ||
713 | } | ||
714 | break; | ||
715 | default: | ||
716 | dprintk("%s: UNDEFINED ALGO !\n", __func__); | ||
717 | break; | ||
718 | } | ||
719 | } else { | ||
720 | dvb_frontend_swzigzag(fe); | ||
721 | } | ||
722 | } | ||
723 | |||
724 | if (dvb_powerdown_on_sleep) { | ||
725 | if (fe->ops.set_voltage) | ||
726 | fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF); | ||
727 | if (fe->ops.tuner_ops.sleep) { | ||
728 | if (fe->ops.i2c_gate_ctrl) | ||
729 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
730 | fe->ops.tuner_ops.sleep(fe); | ||
731 | if (fe->ops.i2c_gate_ctrl) | ||
732 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
733 | } | ||
734 | if (fe->ops.sleep) | ||
735 | fe->ops.sleep(fe); | ||
736 | } | ||
737 | |||
738 | fepriv->thread = NULL; | ||
739 | if (kthread_should_stop()) | ||
740 | fepriv->exit = DVB_FE_DEVICE_REMOVED; | ||
741 | else | ||
742 | fepriv->exit = DVB_FE_NO_EXIT; | ||
743 | mb(); | ||
744 | |||
745 | dvb_frontend_wakeup(fe); | ||
746 | return 0; | ||
747 | } | ||
748 | |||
749 | static void dvb_frontend_stop(struct dvb_frontend *fe) | ||
750 | { | ||
751 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
752 | |||
753 | dprintk ("%s\n", __func__); | ||
754 | |||
755 | fepriv->exit = DVB_FE_NORMAL_EXIT; | ||
756 | mb(); | ||
757 | |||
758 | if (!fepriv->thread) | ||
759 | return; | ||
760 | |||
761 | kthread_stop(fepriv->thread); | ||
762 | |||
763 | sema_init(&fepriv->sem, 1); | ||
764 | fepriv->state = FESTATE_IDLE; | ||
765 | |||
766 | /* paranoia check in case a signal arrived */ | ||
767 | if (fepriv->thread) | ||
768 | printk("dvb_frontend_stop: warning: thread %p won't exit\n", | ||
769 | fepriv->thread); | ||
770 | } | ||
771 | |||
772 | s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime) | ||
773 | { | ||
774 | return ((curtime.tv_usec < lasttime.tv_usec) ? | ||
775 | 1000000 - lasttime.tv_usec + curtime.tv_usec : | ||
776 | curtime.tv_usec - lasttime.tv_usec); | ||
777 | } | ||
778 | EXPORT_SYMBOL(timeval_usec_diff); | ||
779 | |||
780 | static inline void timeval_usec_add(struct timeval *curtime, u32 add_usec) | ||
781 | { | ||
782 | curtime->tv_usec += add_usec; | ||
783 | if (curtime->tv_usec >= 1000000) { | ||
784 | curtime->tv_usec -= 1000000; | ||
785 | curtime->tv_sec++; | ||
786 | } | ||
787 | } | ||
788 | |||
789 | /* | ||
790 | * Sleep until gettimeofday() > waketime + add_usec | ||
791 | * This needs to be as precise as possible, but as the delay is | ||
792 | * usually between 2ms and 32ms, it is done using a scheduled msleep | ||
793 | * followed by usleep (normally a busy-wait loop) for the remainder | ||
794 | */ | ||
795 | void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec) | ||
796 | { | ||
797 | struct timeval lasttime; | ||
798 | s32 delta, newdelta; | ||
799 | |||
800 | timeval_usec_add(waketime, add_usec); | ||
801 | |||
802 | do_gettimeofday(&lasttime); | ||
803 | delta = timeval_usec_diff(lasttime, *waketime); | ||
804 | if (delta > 2500) { | ||
805 | msleep((delta - 1500) / 1000); | ||
806 | do_gettimeofday(&lasttime); | ||
807 | newdelta = timeval_usec_diff(lasttime, *waketime); | ||
808 | delta = (newdelta > delta) ? 0 : newdelta; | ||
809 | } | ||
810 | if (delta > 0) | ||
811 | udelay(delta); | ||
812 | } | ||
813 | EXPORT_SYMBOL(dvb_frontend_sleep_until); | ||
814 | |||
815 | static int dvb_frontend_start(struct dvb_frontend *fe) | ||
816 | { | ||
817 | int ret; | ||
818 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
819 | struct task_struct *fe_thread; | ||
820 | |||
821 | dprintk ("%s\n", __func__); | ||
822 | |||
823 | if (fepriv->thread) { | ||
824 | if (fepriv->exit == DVB_FE_NO_EXIT) | ||
825 | return 0; | ||
826 | else | ||
827 | dvb_frontend_stop (fe); | ||
828 | } | ||
829 | |||
830 | if (signal_pending(current)) | ||
831 | return -EINTR; | ||
832 | if (down_interruptible (&fepriv->sem)) | ||
833 | return -EINTR; | ||
834 | |||
835 | fepriv->state = FESTATE_IDLE; | ||
836 | fepriv->exit = DVB_FE_NO_EXIT; | ||
837 | fepriv->thread = NULL; | ||
838 | mb(); | ||
839 | |||
840 | fe_thread = kthread_run(dvb_frontend_thread, fe, | ||
841 | "kdvb-ad-%i-fe-%i", fe->dvb->num,fe->id); | ||
842 | if (IS_ERR(fe_thread)) { | ||
843 | ret = PTR_ERR(fe_thread); | ||
844 | printk("dvb_frontend_start: failed to start kthread (%d)\n", ret); | ||
845 | up(&fepriv->sem); | ||
846 | return ret; | ||
847 | } | ||
848 | fepriv->thread = fe_thread; | ||
849 | return 0; | ||
850 | } | ||
851 | |||
852 | static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe, | ||
853 | u32 *freq_min, u32 *freq_max) | ||
854 | { | ||
855 | *freq_min = max(fe->ops.info.frequency_min, fe->ops.tuner_ops.info.frequency_min); | ||
856 | |||
857 | if (fe->ops.info.frequency_max == 0) | ||
858 | *freq_max = fe->ops.tuner_ops.info.frequency_max; | ||
859 | else if (fe->ops.tuner_ops.info.frequency_max == 0) | ||
860 | *freq_max = fe->ops.info.frequency_max; | ||
861 | else | ||
862 | *freq_max = min(fe->ops.info.frequency_max, fe->ops.tuner_ops.info.frequency_max); | ||
863 | |||
864 | if (*freq_min == 0 || *freq_max == 0) | ||
865 | printk(KERN_WARNING "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n", | ||
866 | fe->dvb->num,fe->id); | ||
867 | } | ||
868 | |||
869 | static int dvb_frontend_check_parameters(struct dvb_frontend *fe) | ||
870 | { | ||
871 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
872 | u32 freq_min; | ||
873 | u32 freq_max; | ||
874 | |||
875 | /* range check: frequency */ | ||
876 | dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max); | ||
877 | if ((freq_min && c->frequency < freq_min) || | ||
878 | (freq_max && c->frequency > freq_max)) { | ||
879 | printk(KERN_WARNING "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n", | ||
880 | fe->dvb->num, fe->id, c->frequency, freq_min, freq_max); | ||
881 | return -EINVAL; | ||
882 | } | ||
883 | |||
884 | /* range check: symbol rate */ | ||
885 | switch (c->delivery_system) { | ||
886 | case SYS_DVBS: | ||
887 | case SYS_DVBS2: | ||
888 | case SYS_TURBO: | ||
889 | case SYS_DVBC_ANNEX_A: | ||
890 | case SYS_DVBC_ANNEX_C: | ||
891 | if ((fe->ops.info.symbol_rate_min && | ||
892 | c->symbol_rate < fe->ops.info.symbol_rate_min) || | ||
893 | (fe->ops.info.symbol_rate_max && | ||
894 | c->symbol_rate > fe->ops.info.symbol_rate_max)) { | ||
895 | printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n", | ||
896 | fe->dvb->num, fe->id, c->symbol_rate, | ||
897 | fe->ops.info.symbol_rate_min, | ||
898 | fe->ops.info.symbol_rate_max); | ||
899 | return -EINVAL; | ||
900 | } | ||
901 | default: | ||
902 | break; | ||
903 | } | ||
904 | |||
905 | return 0; | ||
906 | } | ||
907 | |||
908 | static int dvb_frontend_clear_cache(struct dvb_frontend *fe) | ||
909 | { | ||
910 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
911 | int i; | ||
912 | u32 delsys; | ||
913 | |||
914 | delsys = c->delivery_system; | ||
915 | memset(c, 0, sizeof(struct dtv_frontend_properties)); | ||
916 | c->delivery_system = delsys; | ||
917 | |||
918 | c->state = DTV_CLEAR; | ||
919 | |||
920 | dprintk("%s() Clearing cache for delivery system %d\n", __func__, | ||
921 | c->delivery_system); | ||
922 | |||
923 | c->transmission_mode = TRANSMISSION_MODE_AUTO; | ||
924 | c->bandwidth_hz = 0; /* AUTO */ | ||
925 | c->guard_interval = GUARD_INTERVAL_AUTO; | ||
926 | c->hierarchy = HIERARCHY_AUTO; | ||
927 | c->symbol_rate = 0; | ||
928 | c->code_rate_HP = FEC_AUTO; | ||
929 | c->code_rate_LP = FEC_AUTO; | ||
930 | c->fec_inner = FEC_AUTO; | ||
931 | c->rolloff = ROLLOFF_AUTO; | ||
932 | c->voltage = SEC_VOLTAGE_OFF; | ||
933 | c->sectone = SEC_TONE_OFF; | ||
934 | c->pilot = PILOT_AUTO; | ||
935 | |||
936 | c->isdbt_partial_reception = 0; | ||
937 | c->isdbt_sb_mode = 0; | ||
938 | c->isdbt_sb_subchannel = 0; | ||
939 | c->isdbt_sb_segment_idx = 0; | ||
940 | c->isdbt_sb_segment_count = 0; | ||
941 | c->isdbt_layer_enabled = 0; | ||
942 | for (i = 0; i < 3; i++) { | ||
943 | c->layer[i].fec = FEC_AUTO; | ||
944 | c->layer[i].modulation = QAM_AUTO; | ||
945 | c->layer[i].interleaving = 0; | ||
946 | c->layer[i].segment_count = 0; | ||
947 | } | ||
948 | |||
949 | c->isdbs_ts_id = 0; | ||
950 | c->dvbt2_plp_id = 0; | ||
951 | |||
952 | switch (c->delivery_system) { | ||
953 | case SYS_DVBS: | ||
954 | case SYS_DVBS2: | ||
955 | case SYS_TURBO: | ||
956 | c->modulation = QPSK; /* implied for DVB-S in legacy API */ | ||
957 | c->rolloff = ROLLOFF_35;/* implied for DVB-S */ | ||
958 | break; | ||
959 | case SYS_ATSC: | ||
960 | c->modulation = VSB_8; | ||
961 | break; | ||
962 | default: | ||
963 | c->modulation = QAM_AUTO; | ||
964 | break; | ||
965 | } | ||
966 | |||
967 | return 0; | ||
968 | } | ||
969 | |||
970 | #define _DTV_CMD(n, s, b) \ | ||
971 | [n] = { \ | ||
972 | .name = #n, \ | ||
973 | .cmd = n, \ | ||
974 | .set = s,\ | ||
975 | .buffer = b \ | ||
976 | } | ||
977 | |||
978 | static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = { | ||
979 | _DTV_CMD(DTV_TUNE, 1, 0), | ||
980 | _DTV_CMD(DTV_CLEAR, 1, 0), | ||
981 | |||
982 | /* Set */ | ||
983 | _DTV_CMD(DTV_FREQUENCY, 1, 0), | ||
984 | _DTV_CMD(DTV_BANDWIDTH_HZ, 1, 0), | ||
985 | _DTV_CMD(DTV_MODULATION, 1, 0), | ||
986 | _DTV_CMD(DTV_INVERSION, 1, 0), | ||
987 | _DTV_CMD(DTV_DISEQC_MASTER, 1, 1), | ||
988 | _DTV_CMD(DTV_SYMBOL_RATE, 1, 0), | ||
989 | _DTV_CMD(DTV_INNER_FEC, 1, 0), | ||
990 | _DTV_CMD(DTV_VOLTAGE, 1, 0), | ||
991 | _DTV_CMD(DTV_TONE, 1, 0), | ||
992 | _DTV_CMD(DTV_PILOT, 1, 0), | ||
993 | _DTV_CMD(DTV_ROLLOFF, 1, 0), | ||
994 | _DTV_CMD(DTV_DELIVERY_SYSTEM, 1, 0), | ||
995 | _DTV_CMD(DTV_HIERARCHY, 1, 0), | ||
996 | _DTV_CMD(DTV_CODE_RATE_HP, 1, 0), | ||
997 | _DTV_CMD(DTV_CODE_RATE_LP, 1, 0), | ||
998 | _DTV_CMD(DTV_GUARD_INTERVAL, 1, 0), | ||
999 | _DTV_CMD(DTV_TRANSMISSION_MODE, 1, 0), | ||
1000 | _DTV_CMD(DTV_INTERLEAVING, 1, 0), | ||
1001 | |||
1002 | _DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 1, 0), | ||
1003 | _DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 1, 0), | ||
1004 | _DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID, 1, 0), | ||
1005 | _DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX, 1, 0), | ||
1006 | _DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT, 1, 0), | ||
1007 | _DTV_CMD(DTV_ISDBT_LAYER_ENABLED, 1, 0), | ||
1008 | _DTV_CMD(DTV_ISDBT_LAYERA_FEC, 1, 0), | ||
1009 | _DTV_CMD(DTV_ISDBT_LAYERA_MODULATION, 1, 0), | ||
1010 | _DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT, 1, 0), | ||
1011 | _DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING, 1, 0), | ||
1012 | _DTV_CMD(DTV_ISDBT_LAYERB_FEC, 1, 0), | ||
1013 | _DTV_CMD(DTV_ISDBT_LAYERB_MODULATION, 1, 0), | ||
1014 | _DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT, 1, 0), | ||
1015 | _DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING, 1, 0), | ||
1016 | _DTV_CMD(DTV_ISDBT_LAYERC_FEC, 1, 0), | ||
1017 | _DTV_CMD(DTV_ISDBT_LAYERC_MODULATION, 1, 0), | ||
1018 | _DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 1, 0), | ||
1019 | _DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 1, 0), | ||
1020 | |||
1021 | _DTV_CMD(DTV_ISDBS_TS_ID, 1, 0), | ||
1022 | _DTV_CMD(DTV_DVBT2_PLP_ID, 1, 0), | ||
1023 | |||
1024 | /* Get */ | ||
1025 | _DTV_CMD(DTV_DISEQC_SLAVE_REPLY, 0, 1), | ||
1026 | _DTV_CMD(DTV_API_VERSION, 0, 0), | ||
1027 | _DTV_CMD(DTV_CODE_RATE_HP, 0, 0), | ||
1028 | _DTV_CMD(DTV_CODE_RATE_LP, 0, 0), | ||
1029 | _DTV_CMD(DTV_GUARD_INTERVAL, 0, 0), | ||
1030 | _DTV_CMD(DTV_TRANSMISSION_MODE, 0, 0), | ||
1031 | _DTV_CMD(DTV_HIERARCHY, 0, 0), | ||
1032 | _DTV_CMD(DTV_INTERLEAVING, 0, 0), | ||
1033 | |||
1034 | _DTV_CMD(DTV_ENUM_DELSYS, 0, 0), | ||
1035 | |||
1036 | _DTV_CMD(DTV_ATSCMH_PARADE_ID, 1, 0), | ||
1037 | _DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE, 1, 0), | ||
1038 | |||
1039 | _DTV_CMD(DTV_ATSCMH_FIC_VER, 0, 0), | ||
1040 | _DTV_CMD(DTV_ATSCMH_PARADE_ID, 0, 0), | ||
1041 | _DTV_CMD(DTV_ATSCMH_NOG, 0, 0), | ||
1042 | _DTV_CMD(DTV_ATSCMH_TNOG, 0, 0), | ||
1043 | _DTV_CMD(DTV_ATSCMH_SGN, 0, 0), | ||
1044 | _DTV_CMD(DTV_ATSCMH_PRC, 0, 0), | ||
1045 | _DTV_CMD(DTV_ATSCMH_RS_FRAME_MODE, 0, 0), | ||
1046 | _DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE, 0, 0), | ||
1047 | _DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_PRI, 0, 0), | ||
1048 | _DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_SEC, 0, 0), | ||
1049 | _DTV_CMD(DTV_ATSCMH_SCCC_BLOCK_MODE, 0, 0), | ||
1050 | _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_A, 0, 0), | ||
1051 | _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_B, 0, 0), | ||
1052 | _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_C, 0, 0), | ||
1053 | _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_D, 0, 0), | ||
1054 | }; | ||
1055 | |||
1056 | static void dtv_property_dump(struct dtv_property *tvp) | ||
1057 | { | ||
1058 | int i; | ||
1059 | |||
1060 | if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) { | ||
1061 | printk(KERN_WARNING "%s: tvp.cmd = 0x%08x undefined\n", | ||
1062 | __func__, tvp->cmd); | ||
1063 | return; | ||
1064 | } | ||
1065 | |||
1066 | dprintk("%s() tvp.cmd = 0x%08x (%s)\n" | ||
1067 | ,__func__ | ||
1068 | ,tvp->cmd | ||
1069 | ,dtv_cmds[ tvp->cmd ].name); | ||
1070 | |||
1071 | if(dtv_cmds[ tvp->cmd ].buffer) { | ||
1072 | |||
1073 | dprintk("%s() tvp.u.buffer.len = 0x%02x\n" | ||
1074 | ,__func__ | ||
1075 | ,tvp->u.buffer.len); | ||
1076 | |||
1077 | for(i = 0; i < tvp->u.buffer.len; i++) | ||
1078 | dprintk("%s() tvp.u.buffer.data[0x%02x] = 0x%02x\n" | ||
1079 | ,__func__ | ||
1080 | ,i | ||
1081 | ,tvp->u.buffer.data[i]); | ||
1082 | |||
1083 | } else | ||
1084 | dprintk("%s() tvp.u.data = 0x%08x\n", __func__, tvp->u.data); | ||
1085 | } | ||
1086 | |||
1087 | /* Synchronise the legacy tuning parameters into the cache, so that demodulator | ||
1088 | * drivers can use a single set_frontend tuning function, regardless of whether | ||
1089 | * it's being used for the legacy or new API, reducing code and complexity. | ||
1090 | */ | ||
1091 | static int dtv_property_cache_sync(struct dvb_frontend *fe, | ||
1092 | struct dtv_frontend_properties *c, | ||
1093 | const struct dvb_frontend_parameters *p) | ||
1094 | { | ||
1095 | c->frequency = p->frequency; | ||
1096 | c->inversion = p->inversion; | ||
1097 | |||
1098 | switch (dvbv3_type(c->delivery_system)) { | ||
1099 | case DVBV3_QPSK: | ||
1100 | dprintk("%s() Preparing QPSK req\n", __func__); | ||
1101 | c->symbol_rate = p->u.qpsk.symbol_rate; | ||
1102 | c->fec_inner = p->u.qpsk.fec_inner; | ||
1103 | break; | ||
1104 | case DVBV3_QAM: | ||
1105 | dprintk("%s() Preparing QAM req\n", __func__); | ||
1106 | c->symbol_rate = p->u.qam.symbol_rate; | ||
1107 | c->fec_inner = p->u.qam.fec_inner; | ||
1108 | c->modulation = p->u.qam.modulation; | ||
1109 | break; | ||
1110 | case DVBV3_OFDM: | ||
1111 | dprintk("%s() Preparing OFDM req\n", __func__); | ||
1112 | switch (p->u.ofdm.bandwidth) { | ||
1113 | case BANDWIDTH_10_MHZ: | ||
1114 | c->bandwidth_hz = 10000000; | ||
1115 | break; | ||
1116 | case BANDWIDTH_8_MHZ: | ||
1117 | c->bandwidth_hz = 8000000; | ||
1118 | break; | ||
1119 | case BANDWIDTH_7_MHZ: | ||
1120 | c->bandwidth_hz = 7000000; | ||
1121 | break; | ||
1122 | case BANDWIDTH_6_MHZ: | ||
1123 | c->bandwidth_hz = 6000000; | ||
1124 | break; | ||
1125 | case BANDWIDTH_5_MHZ: | ||
1126 | c->bandwidth_hz = 5000000; | ||
1127 | break; | ||
1128 | case BANDWIDTH_1_712_MHZ: | ||
1129 | c->bandwidth_hz = 1712000; | ||
1130 | break; | ||
1131 | case BANDWIDTH_AUTO: | ||
1132 | c->bandwidth_hz = 0; | ||
1133 | } | ||
1134 | |||
1135 | c->code_rate_HP = p->u.ofdm.code_rate_HP; | ||
1136 | c->code_rate_LP = p->u.ofdm.code_rate_LP; | ||
1137 | c->modulation = p->u.ofdm.constellation; | ||
1138 | c->transmission_mode = p->u.ofdm.transmission_mode; | ||
1139 | c->guard_interval = p->u.ofdm.guard_interval; | ||
1140 | c->hierarchy = p->u.ofdm.hierarchy_information; | ||
1141 | break; | ||
1142 | case DVBV3_ATSC: | ||
1143 | dprintk("%s() Preparing ATSC req\n", __func__); | ||
1144 | c->modulation = p->u.vsb.modulation; | ||
1145 | if (c->delivery_system == SYS_ATSCMH) | ||
1146 | break; | ||
1147 | if ((c->modulation == VSB_8) || (c->modulation == VSB_16)) | ||
1148 | c->delivery_system = SYS_ATSC; | ||
1149 | else | ||
1150 | c->delivery_system = SYS_DVBC_ANNEX_B; | ||
1151 | break; | ||
1152 | case DVBV3_UNKNOWN: | ||
1153 | printk(KERN_ERR | ||
1154 | "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n", | ||
1155 | __func__, c->delivery_system); | ||
1156 | return -EINVAL; | ||
1157 | } | ||
1158 | |||
1159 | return 0; | ||
1160 | } | ||
1161 | |||
1162 | /* Ensure the cached values are set correctly in the frontend | ||
1163 | * legacy tuning structures, for the advanced tuning API. | ||
1164 | */ | ||
1165 | static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, | ||
1166 | struct dvb_frontend_parameters *p) | ||
1167 | { | ||
1168 | const struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1169 | |||
1170 | p->frequency = c->frequency; | ||
1171 | p->inversion = c->inversion; | ||
1172 | |||
1173 | switch (dvbv3_type(c->delivery_system)) { | ||
1174 | case DVBV3_UNKNOWN: | ||
1175 | printk(KERN_ERR | ||
1176 | "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n", | ||
1177 | __func__, c->delivery_system); | ||
1178 | return -EINVAL; | ||
1179 | case DVBV3_QPSK: | ||
1180 | dprintk("%s() Preparing QPSK req\n", __func__); | ||
1181 | p->u.qpsk.symbol_rate = c->symbol_rate; | ||
1182 | p->u.qpsk.fec_inner = c->fec_inner; | ||
1183 | break; | ||
1184 | case DVBV3_QAM: | ||
1185 | dprintk("%s() Preparing QAM req\n", __func__); | ||
1186 | p->u.qam.symbol_rate = c->symbol_rate; | ||
1187 | p->u.qam.fec_inner = c->fec_inner; | ||
1188 | p->u.qam.modulation = c->modulation; | ||
1189 | break; | ||
1190 | case DVBV3_OFDM: | ||
1191 | dprintk("%s() Preparing OFDM req\n", __func__); | ||
1192 | |||
1193 | switch (c->bandwidth_hz) { | ||
1194 | case 10000000: | ||
1195 | p->u.ofdm.bandwidth = BANDWIDTH_10_MHZ; | ||
1196 | break; | ||
1197 | case 8000000: | ||
1198 | p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; | ||
1199 | break; | ||
1200 | case 7000000: | ||
1201 | p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; | ||
1202 | break; | ||
1203 | case 6000000: | ||
1204 | p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; | ||
1205 | break; | ||
1206 | case 5000000: | ||
1207 | p->u.ofdm.bandwidth = BANDWIDTH_5_MHZ; | ||
1208 | break; | ||
1209 | case 1712000: | ||
1210 | p->u.ofdm.bandwidth = BANDWIDTH_1_712_MHZ; | ||
1211 | break; | ||
1212 | case 0: | ||
1213 | default: | ||
1214 | p->u.ofdm.bandwidth = BANDWIDTH_AUTO; | ||
1215 | } | ||
1216 | p->u.ofdm.code_rate_HP = c->code_rate_HP; | ||
1217 | p->u.ofdm.code_rate_LP = c->code_rate_LP; | ||
1218 | p->u.ofdm.constellation = c->modulation; | ||
1219 | p->u.ofdm.transmission_mode = c->transmission_mode; | ||
1220 | p->u.ofdm.guard_interval = c->guard_interval; | ||
1221 | p->u.ofdm.hierarchy_information = c->hierarchy; | ||
1222 | break; | ||
1223 | case DVBV3_ATSC: | ||
1224 | dprintk("%s() Preparing VSB req\n", __func__); | ||
1225 | p->u.vsb.modulation = c->modulation; | ||
1226 | break; | ||
1227 | } | ||
1228 | return 0; | ||
1229 | } | ||
1230 | |||
1231 | /** | ||
1232 | * dtv_get_frontend - calls a callback for retrieving DTV parameters | ||
1233 | * @fe: struct dvb_frontend pointer | ||
1234 | * @c: struct dtv_frontend_properties pointer (DVBv5 cache) | ||
1235 | * @p_out struct dvb_frontend_parameters pointer (DVBv3 FE struct) | ||
1236 | * | ||
1237 | * This routine calls either the DVBv3 or DVBv5 get_frontend call. | ||
1238 | * If c is not null, it will update the DVBv5 cache struct pointed by it. | ||
1239 | * If p_out is not null, it will update the DVBv3 params pointed by it. | ||
1240 | */ | ||
1241 | static int dtv_get_frontend(struct dvb_frontend *fe, | ||
1242 | struct dvb_frontend_parameters *p_out) | ||
1243 | { | ||
1244 | int r; | ||
1245 | |||
1246 | if (fe->ops.get_frontend) { | ||
1247 | r = fe->ops.get_frontend(fe); | ||
1248 | if (unlikely(r < 0)) | ||
1249 | return r; | ||
1250 | if (p_out) | ||
1251 | dtv_property_legacy_params_sync(fe, p_out); | ||
1252 | return 0; | ||
1253 | } | ||
1254 | |||
1255 | /* As everything is in cache, get_frontend fops are always supported */ | ||
1256 | return 0; | ||
1257 | } | ||
1258 | |||
1259 | static int dvb_frontend_ioctl_legacy(struct file *file, | ||
1260 | unsigned int cmd, void *parg); | ||
1261 | static int dvb_frontend_ioctl_properties(struct file *file, | ||
1262 | unsigned int cmd, void *parg); | ||
1263 | |||
1264 | static int dtv_property_process_get(struct dvb_frontend *fe, | ||
1265 | const struct dtv_frontend_properties *c, | ||
1266 | struct dtv_property *tvp, | ||
1267 | struct file *file) | ||
1268 | { | ||
1269 | int r, ncaps; | ||
1270 | |||
1271 | switch(tvp->cmd) { | ||
1272 | case DTV_ENUM_DELSYS: | ||
1273 | ncaps = 0; | ||
1274 | while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { | ||
1275 | tvp->u.buffer.data[ncaps] = fe->ops.delsys[ncaps]; | ||
1276 | ncaps++; | ||
1277 | } | ||
1278 | tvp->u.buffer.len = ncaps; | ||
1279 | break; | ||
1280 | case DTV_FREQUENCY: | ||
1281 | tvp->u.data = c->frequency; | ||
1282 | break; | ||
1283 | case DTV_MODULATION: | ||
1284 | tvp->u.data = c->modulation; | ||
1285 | break; | ||
1286 | case DTV_BANDWIDTH_HZ: | ||
1287 | tvp->u.data = c->bandwidth_hz; | ||
1288 | break; | ||
1289 | case DTV_INVERSION: | ||
1290 | tvp->u.data = c->inversion; | ||
1291 | break; | ||
1292 | case DTV_SYMBOL_RATE: | ||
1293 | tvp->u.data = c->symbol_rate; | ||
1294 | break; | ||
1295 | case DTV_INNER_FEC: | ||
1296 | tvp->u.data = c->fec_inner; | ||
1297 | break; | ||
1298 | case DTV_PILOT: | ||
1299 | tvp->u.data = c->pilot; | ||
1300 | break; | ||
1301 | case DTV_ROLLOFF: | ||
1302 | tvp->u.data = c->rolloff; | ||
1303 | break; | ||
1304 | case DTV_DELIVERY_SYSTEM: | ||
1305 | tvp->u.data = c->delivery_system; | ||
1306 | break; | ||
1307 | case DTV_VOLTAGE: | ||
1308 | tvp->u.data = c->voltage; | ||
1309 | break; | ||
1310 | case DTV_TONE: | ||
1311 | tvp->u.data = c->sectone; | ||
1312 | break; | ||
1313 | case DTV_API_VERSION: | ||
1314 | tvp->u.data = (DVB_API_VERSION << 8) | DVB_API_VERSION_MINOR; | ||
1315 | break; | ||
1316 | case DTV_CODE_RATE_HP: | ||
1317 | tvp->u.data = c->code_rate_HP; | ||
1318 | break; | ||
1319 | case DTV_CODE_RATE_LP: | ||
1320 | tvp->u.data = c->code_rate_LP; | ||
1321 | break; | ||
1322 | case DTV_GUARD_INTERVAL: | ||
1323 | tvp->u.data = c->guard_interval; | ||
1324 | break; | ||
1325 | case DTV_TRANSMISSION_MODE: | ||
1326 | tvp->u.data = c->transmission_mode; | ||
1327 | break; | ||
1328 | case DTV_HIERARCHY: | ||
1329 | tvp->u.data = c->hierarchy; | ||
1330 | break; | ||
1331 | case DTV_INTERLEAVING: | ||
1332 | tvp->u.data = c->interleaving; | ||
1333 | break; | ||
1334 | |||
1335 | /* ISDB-T Support here */ | ||
1336 | case DTV_ISDBT_PARTIAL_RECEPTION: | ||
1337 | tvp->u.data = c->isdbt_partial_reception; | ||
1338 | break; | ||
1339 | case DTV_ISDBT_SOUND_BROADCASTING: | ||
1340 | tvp->u.data = c->isdbt_sb_mode; | ||
1341 | break; | ||
1342 | case DTV_ISDBT_SB_SUBCHANNEL_ID: | ||
1343 | tvp->u.data = c->isdbt_sb_subchannel; | ||
1344 | break; | ||
1345 | case DTV_ISDBT_SB_SEGMENT_IDX: | ||
1346 | tvp->u.data = c->isdbt_sb_segment_idx; | ||
1347 | break; | ||
1348 | case DTV_ISDBT_SB_SEGMENT_COUNT: | ||
1349 | tvp->u.data = c->isdbt_sb_segment_count; | ||
1350 | break; | ||
1351 | case DTV_ISDBT_LAYER_ENABLED: | ||
1352 | tvp->u.data = c->isdbt_layer_enabled; | ||
1353 | break; | ||
1354 | case DTV_ISDBT_LAYERA_FEC: | ||
1355 | tvp->u.data = c->layer[0].fec; | ||
1356 | break; | ||
1357 | case DTV_ISDBT_LAYERA_MODULATION: | ||
1358 | tvp->u.data = c->layer[0].modulation; | ||
1359 | break; | ||
1360 | case DTV_ISDBT_LAYERA_SEGMENT_COUNT: | ||
1361 | tvp->u.data = c->layer[0].segment_count; | ||
1362 | break; | ||
1363 | case DTV_ISDBT_LAYERA_TIME_INTERLEAVING: | ||
1364 | tvp->u.data = c->layer[0].interleaving; | ||
1365 | break; | ||
1366 | case DTV_ISDBT_LAYERB_FEC: | ||
1367 | tvp->u.data = c->layer[1].fec; | ||
1368 | break; | ||
1369 | case DTV_ISDBT_LAYERB_MODULATION: | ||
1370 | tvp->u.data = c->layer[1].modulation; | ||
1371 | break; | ||
1372 | case DTV_ISDBT_LAYERB_SEGMENT_COUNT: | ||
1373 | tvp->u.data = c->layer[1].segment_count; | ||
1374 | break; | ||
1375 | case DTV_ISDBT_LAYERB_TIME_INTERLEAVING: | ||
1376 | tvp->u.data = c->layer[1].interleaving; | ||
1377 | break; | ||
1378 | case DTV_ISDBT_LAYERC_FEC: | ||
1379 | tvp->u.data = c->layer[2].fec; | ||
1380 | break; | ||
1381 | case DTV_ISDBT_LAYERC_MODULATION: | ||
1382 | tvp->u.data = c->layer[2].modulation; | ||
1383 | break; | ||
1384 | case DTV_ISDBT_LAYERC_SEGMENT_COUNT: | ||
1385 | tvp->u.data = c->layer[2].segment_count; | ||
1386 | break; | ||
1387 | case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: | ||
1388 | tvp->u.data = c->layer[2].interleaving; | ||
1389 | break; | ||
1390 | case DTV_ISDBS_TS_ID: | ||
1391 | tvp->u.data = c->isdbs_ts_id; | ||
1392 | break; | ||
1393 | case DTV_DVBT2_PLP_ID: | ||
1394 | tvp->u.data = c->dvbt2_plp_id; | ||
1395 | break; | ||
1396 | |||
1397 | /* ATSC-MH */ | ||
1398 | case DTV_ATSCMH_FIC_VER: | ||
1399 | tvp->u.data = fe->dtv_property_cache.atscmh_fic_ver; | ||
1400 | break; | ||
1401 | case DTV_ATSCMH_PARADE_ID: | ||
1402 | tvp->u.data = fe->dtv_property_cache.atscmh_parade_id; | ||
1403 | break; | ||
1404 | case DTV_ATSCMH_NOG: | ||
1405 | tvp->u.data = fe->dtv_property_cache.atscmh_nog; | ||
1406 | break; | ||
1407 | case DTV_ATSCMH_TNOG: | ||
1408 | tvp->u.data = fe->dtv_property_cache.atscmh_tnog; | ||
1409 | break; | ||
1410 | case DTV_ATSCMH_SGN: | ||
1411 | tvp->u.data = fe->dtv_property_cache.atscmh_sgn; | ||
1412 | break; | ||
1413 | case DTV_ATSCMH_PRC: | ||
1414 | tvp->u.data = fe->dtv_property_cache.atscmh_prc; | ||
1415 | break; | ||
1416 | case DTV_ATSCMH_RS_FRAME_MODE: | ||
1417 | tvp->u.data = fe->dtv_property_cache.atscmh_rs_frame_mode; | ||
1418 | break; | ||
1419 | case DTV_ATSCMH_RS_FRAME_ENSEMBLE: | ||
1420 | tvp->u.data = fe->dtv_property_cache.atscmh_rs_frame_ensemble; | ||
1421 | break; | ||
1422 | case DTV_ATSCMH_RS_CODE_MODE_PRI: | ||
1423 | tvp->u.data = fe->dtv_property_cache.atscmh_rs_code_mode_pri; | ||
1424 | break; | ||
1425 | case DTV_ATSCMH_RS_CODE_MODE_SEC: | ||
1426 | tvp->u.data = fe->dtv_property_cache.atscmh_rs_code_mode_sec; | ||
1427 | break; | ||
1428 | case DTV_ATSCMH_SCCC_BLOCK_MODE: | ||
1429 | tvp->u.data = fe->dtv_property_cache.atscmh_sccc_block_mode; | ||
1430 | break; | ||
1431 | case DTV_ATSCMH_SCCC_CODE_MODE_A: | ||
1432 | tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_a; | ||
1433 | break; | ||
1434 | case DTV_ATSCMH_SCCC_CODE_MODE_B: | ||
1435 | tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_b; | ||
1436 | break; | ||
1437 | case DTV_ATSCMH_SCCC_CODE_MODE_C: | ||
1438 | tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_c; | ||
1439 | break; | ||
1440 | case DTV_ATSCMH_SCCC_CODE_MODE_D: | ||
1441 | tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_d; | ||
1442 | break; | ||
1443 | |||
1444 | default: | ||
1445 | return -EINVAL; | ||
1446 | } | ||
1447 | |||
1448 | /* Allow the frontend to override outgoing properties */ | ||
1449 | if (fe->ops.get_property) { | ||
1450 | r = fe->ops.get_property(fe, tvp); | ||
1451 | if (r < 0) | ||
1452 | return r; | ||
1453 | } | ||
1454 | |||
1455 | dtv_property_dump(tvp); | ||
1456 | |||
1457 | return 0; | ||
1458 | } | ||
1459 | |||
1460 | static int dtv_set_frontend(struct dvb_frontend *fe); | ||
1461 | |||
1462 | static bool is_dvbv3_delsys(u32 delsys) | ||
1463 | { | ||
1464 | bool status; | ||
1465 | |||
1466 | status = (delsys == SYS_DVBT) || (delsys == SYS_DVBC_ANNEX_A) || | ||
1467 | (delsys == SYS_DVBS) || (delsys == SYS_ATSC); | ||
1468 | |||
1469 | return status; | ||
1470 | } | ||
1471 | |||
1472 | static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) | ||
1473 | { | ||
1474 | int ncaps, i; | ||
1475 | u32 delsys = SYS_UNDEFINED; | ||
1476 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1477 | enum dvbv3_emulation_type type; | ||
1478 | |||
1479 | /* | ||
1480 | * It was reported that some old DVBv5 applications were | ||
1481 | * filling delivery_system with SYS_UNDEFINED. If this happens, | ||
1482 | * assume that the application wants to use the first supported | ||
1483 | * delivery system. | ||
1484 | */ | ||
1485 | if (c->delivery_system == SYS_UNDEFINED) | ||
1486 | c->delivery_system = fe->ops.delsys[0]; | ||
1487 | |||
1488 | if (desired_system == SYS_UNDEFINED) { | ||
1489 | /* | ||
1490 | * A DVBv3 call doesn't know what's the desired system. | ||
1491 | * Also, DVBv3 applications don't know that ops.info->type | ||
1492 | * could be changed, and they simply dies when it doesn't | ||
1493 | * match. | ||
1494 | * So, don't change the current delivery system, as it | ||
1495 | * may be trying to do the wrong thing, like setting an | ||
1496 | * ISDB-T frontend as DVB-T. Instead, find the closest | ||
1497 | * DVBv3 system that matches the delivery system. | ||
1498 | */ | ||
1499 | if (is_dvbv3_delsys(c->delivery_system)) { | ||
1500 | dprintk("%s() Using delivery system to %d\n", | ||
1501 | __func__, c->delivery_system); | ||
1502 | return 0; | ||
1503 | } | ||
1504 | type = dvbv3_type(c->delivery_system); | ||
1505 | switch (type) { | ||
1506 | case DVBV3_QPSK: | ||
1507 | desired_system = SYS_DVBS; | ||
1508 | break; | ||
1509 | case DVBV3_QAM: | ||
1510 | desired_system = SYS_DVBC_ANNEX_A; | ||
1511 | break; | ||
1512 | case DVBV3_ATSC: | ||
1513 | desired_system = SYS_ATSC; | ||
1514 | break; | ||
1515 | case DVBV3_OFDM: | ||
1516 | desired_system = SYS_DVBT; | ||
1517 | break; | ||
1518 | default: | ||
1519 | dprintk("%s(): This frontend doesn't support DVBv3 calls\n", | ||
1520 | __func__); | ||
1521 | return -EINVAL; | ||
1522 | } | ||
1523 | /* | ||
1524 | * Get a delivery system that is compatible with DVBv3 | ||
1525 | * NOTE: in order for this to work with softwares like Kaffeine that | ||
1526 | * uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to | ||
1527 | * DVB-S, drivers that support both should put the SYS_DVBS entry | ||
1528 | * before the SYS_DVBS2, otherwise it won't switch back to DVB-S. | ||
1529 | * The real fix is that userspace applications should not use DVBv3 | ||
1530 | * and not trust on calling FE_SET_FRONTEND to switch the delivery | ||
1531 | * system. | ||
1532 | */ | ||
1533 | ncaps = 0; | ||
1534 | while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { | ||
1535 | if (fe->ops.delsys[ncaps] == desired_system) { | ||
1536 | delsys = desired_system; | ||
1537 | break; | ||
1538 | } | ||
1539 | ncaps++; | ||
1540 | } | ||
1541 | if (delsys == SYS_UNDEFINED) { | ||
1542 | dprintk("%s() Couldn't find a delivery system that matches %d\n", | ||
1543 | __func__, desired_system); | ||
1544 | } | ||
1545 | } else { | ||
1546 | /* | ||
1547 | * This is a DVBv5 call. So, it likely knows the supported | ||
1548 | * delivery systems. | ||
1549 | */ | ||
1550 | |||
1551 | /* Check if the desired delivery system is supported */ | ||
1552 | ncaps = 0; | ||
1553 | while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { | ||
1554 | if (fe->ops.delsys[ncaps] == desired_system) { | ||
1555 | c->delivery_system = desired_system; | ||
1556 | dprintk("%s() Changing delivery system to %d\n", | ||
1557 | __func__, desired_system); | ||
1558 | return 0; | ||
1559 | } | ||
1560 | ncaps++; | ||
1561 | } | ||
1562 | type = dvbv3_type(desired_system); | ||
1563 | |||
1564 | /* | ||
1565 | * The delivery system is not supported. See if it can be | ||
1566 | * emulated. | ||
1567 | * The emulation only works if the desired system is one of the | ||
1568 | * DVBv3 delivery systems | ||
1569 | */ | ||
1570 | if (!is_dvbv3_delsys(desired_system)) { | ||
1571 | dprintk("%s() can't use a DVBv3 FE_SET_FRONTEND call on this frontend\n", | ||
1572 | __func__); | ||
1573 | return -EINVAL; | ||
1574 | } | ||
1575 | |||
1576 | /* | ||
1577 | * Get the last non-DVBv3 delivery system that has the same type | ||
1578 | * of the desired system | ||
1579 | */ | ||
1580 | ncaps = 0; | ||
1581 | while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { | ||
1582 | if ((dvbv3_type(fe->ops.delsys[ncaps]) == type) && | ||
1583 | !is_dvbv3_delsys(fe->ops.delsys[ncaps])) | ||
1584 | delsys = fe->ops.delsys[ncaps]; | ||
1585 | ncaps++; | ||
1586 | } | ||
1587 | /* There's nothing compatible with the desired delivery system */ | ||
1588 | if (delsys == SYS_UNDEFINED) { | ||
1589 | dprintk("%s() Incompatible DVBv3 FE_SET_FRONTEND call for this frontend\n", | ||
1590 | __func__); | ||
1591 | return -EINVAL; | ||
1592 | } | ||
1593 | } | ||
1594 | |||
1595 | c->delivery_system = delsys; | ||
1596 | |||
1597 | /* | ||
1598 | * The DVBv3 or DVBv5 call is requesting a different system. So, | ||
1599 | * emulation is needed. | ||
1600 | * | ||
1601 | * Emulate newer delivery systems like ISDBT, DVBT and DTMB | ||
1602 | * for older DVBv5 applications. The emulation will try to use | ||
1603 | * the auto mode for most things, and will assume that the desired | ||
1604 | * delivery system is the last one at the ops.delsys[] array | ||
1605 | */ | ||
1606 | dprintk("%s() Using delivery system %d emulated as if it were a %d\n", | ||
1607 | __func__, delsys, desired_system); | ||
1608 | |||
1609 | /* | ||
1610 | * For now, handles ISDB-T calls. More code may be needed here for the | ||
1611 | * other emulated stuff | ||
1612 | */ | ||
1613 | if (type == DVBV3_OFDM) { | ||
1614 | if (c->delivery_system == SYS_ISDBT) { | ||
1615 | dprintk("%s() Using defaults for SYS_ISDBT\n", | ||
1616 | __func__); | ||
1617 | if (!c->bandwidth_hz) | ||
1618 | c->bandwidth_hz = 6000000; | ||
1619 | |||
1620 | c->isdbt_partial_reception = 0; | ||
1621 | c->isdbt_sb_mode = 0; | ||
1622 | c->isdbt_sb_subchannel = 0; | ||
1623 | c->isdbt_sb_segment_idx = 0; | ||
1624 | c->isdbt_sb_segment_count = 0; | ||
1625 | c->isdbt_layer_enabled = 0; | ||
1626 | for (i = 0; i < 3; i++) { | ||
1627 | c->layer[i].fec = FEC_AUTO; | ||
1628 | c->layer[i].modulation = QAM_AUTO; | ||
1629 | c->layer[i].interleaving = 0; | ||
1630 | c->layer[i].segment_count = 0; | ||
1631 | } | ||
1632 | } | ||
1633 | } | ||
1634 | dprintk("change delivery system on cache to %d\n", c->delivery_system); | ||
1635 | |||
1636 | return 0; | ||
1637 | } | ||
1638 | |||
1639 | static int dtv_property_process_set(struct dvb_frontend *fe, | ||
1640 | struct dtv_property *tvp, | ||
1641 | struct file *file) | ||
1642 | { | ||
1643 | int r = 0; | ||
1644 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1645 | |||
1646 | /* Allow the frontend to validate incoming properties */ | ||
1647 | if (fe->ops.set_property) { | ||
1648 | r = fe->ops.set_property(fe, tvp); | ||
1649 | if (r < 0) | ||
1650 | return r; | ||
1651 | } | ||
1652 | |||
1653 | switch(tvp->cmd) { | ||
1654 | case DTV_CLEAR: | ||
1655 | /* | ||
1656 | * Reset a cache of data specific to the frontend here. This does | ||
1657 | * not effect hardware. | ||
1658 | */ | ||
1659 | dvb_frontend_clear_cache(fe); | ||
1660 | break; | ||
1661 | case DTV_TUNE: | ||
1662 | /* interpret the cache of data, build either a traditional frontend | ||
1663 | * tunerequest so we can pass validation in the FE_SET_FRONTEND | ||
1664 | * ioctl. | ||
1665 | */ | ||
1666 | c->state = tvp->cmd; | ||
1667 | dprintk("%s() Finalised property cache\n", __func__); | ||
1668 | |||
1669 | r = dtv_set_frontend(fe); | ||
1670 | break; | ||
1671 | case DTV_FREQUENCY: | ||
1672 | c->frequency = tvp->u.data; | ||
1673 | break; | ||
1674 | case DTV_MODULATION: | ||
1675 | c->modulation = tvp->u.data; | ||
1676 | break; | ||
1677 | case DTV_BANDWIDTH_HZ: | ||
1678 | c->bandwidth_hz = tvp->u.data; | ||
1679 | break; | ||
1680 | case DTV_INVERSION: | ||
1681 | c->inversion = tvp->u.data; | ||
1682 | break; | ||
1683 | case DTV_SYMBOL_RATE: | ||
1684 | c->symbol_rate = tvp->u.data; | ||
1685 | break; | ||
1686 | case DTV_INNER_FEC: | ||
1687 | c->fec_inner = tvp->u.data; | ||
1688 | break; | ||
1689 | case DTV_PILOT: | ||
1690 | c->pilot = tvp->u.data; | ||
1691 | break; | ||
1692 | case DTV_ROLLOFF: | ||
1693 | c->rolloff = tvp->u.data; | ||
1694 | break; | ||
1695 | case DTV_DELIVERY_SYSTEM: | ||
1696 | r = set_delivery_system(fe, tvp->u.data); | ||
1697 | break; | ||
1698 | case DTV_VOLTAGE: | ||
1699 | c->voltage = tvp->u.data; | ||
1700 | r = dvb_frontend_ioctl_legacy(file, FE_SET_VOLTAGE, | ||
1701 | (void *)c->voltage); | ||
1702 | break; | ||
1703 | case DTV_TONE: | ||
1704 | c->sectone = tvp->u.data; | ||
1705 | r = dvb_frontend_ioctl_legacy(file, FE_SET_TONE, | ||
1706 | (void *)c->sectone); | ||
1707 | break; | ||
1708 | case DTV_CODE_RATE_HP: | ||
1709 | c->code_rate_HP = tvp->u.data; | ||
1710 | break; | ||
1711 | case DTV_CODE_RATE_LP: | ||
1712 | c->code_rate_LP = tvp->u.data; | ||
1713 | break; | ||
1714 | case DTV_GUARD_INTERVAL: | ||
1715 | c->guard_interval = tvp->u.data; | ||
1716 | break; | ||
1717 | case DTV_TRANSMISSION_MODE: | ||
1718 | c->transmission_mode = tvp->u.data; | ||
1719 | break; | ||
1720 | case DTV_HIERARCHY: | ||
1721 | c->hierarchy = tvp->u.data; | ||
1722 | break; | ||
1723 | case DTV_INTERLEAVING: | ||
1724 | c->interleaving = tvp->u.data; | ||
1725 | break; | ||
1726 | |||
1727 | /* ISDB-T Support here */ | ||
1728 | case DTV_ISDBT_PARTIAL_RECEPTION: | ||
1729 | c->isdbt_partial_reception = tvp->u.data; | ||
1730 | break; | ||
1731 | case DTV_ISDBT_SOUND_BROADCASTING: | ||
1732 | c->isdbt_sb_mode = tvp->u.data; | ||
1733 | break; | ||
1734 | case DTV_ISDBT_SB_SUBCHANNEL_ID: | ||
1735 | c->isdbt_sb_subchannel = tvp->u.data; | ||
1736 | break; | ||
1737 | case DTV_ISDBT_SB_SEGMENT_IDX: | ||
1738 | c->isdbt_sb_segment_idx = tvp->u.data; | ||
1739 | break; | ||
1740 | case DTV_ISDBT_SB_SEGMENT_COUNT: | ||
1741 | c->isdbt_sb_segment_count = tvp->u.data; | ||
1742 | break; | ||
1743 | case DTV_ISDBT_LAYER_ENABLED: | ||
1744 | c->isdbt_layer_enabled = tvp->u.data; | ||
1745 | break; | ||
1746 | case DTV_ISDBT_LAYERA_FEC: | ||
1747 | c->layer[0].fec = tvp->u.data; | ||
1748 | break; | ||
1749 | case DTV_ISDBT_LAYERA_MODULATION: | ||
1750 | c->layer[0].modulation = tvp->u.data; | ||
1751 | break; | ||
1752 | case DTV_ISDBT_LAYERA_SEGMENT_COUNT: | ||
1753 | c->layer[0].segment_count = tvp->u.data; | ||
1754 | break; | ||
1755 | case DTV_ISDBT_LAYERA_TIME_INTERLEAVING: | ||
1756 | c->layer[0].interleaving = tvp->u.data; | ||
1757 | break; | ||
1758 | case DTV_ISDBT_LAYERB_FEC: | ||
1759 | c->layer[1].fec = tvp->u.data; | ||
1760 | break; | ||
1761 | case DTV_ISDBT_LAYERB_MODULATION: | ||
1762 | c->layer[1].modulation = tvp->u.data; | ||
1763 | break; | ||
1764 | case DTV_ISDBT_LAYERB_SEGMENT_COUNT: | ||
1765 | c->layer[1].segment_count = tvp->u.data; | ||
1766 | break; | ||
1767 | case DTV_ISDBT_LAYERB_TIME_INTERLEAVING: | ||
1768 | c->layer[1].interleaving = tvp->u.data; | ||
1769 | break; | ||
1770 | case DTV_ISDBT_LAYERC_FEC: | ||
1771 | c->layer[2].fec = tvp->u.data; | ||
1772 | break; | ||
1773 | case DTV_ISDBT_LAYERC_MODULATION: | ||
1774 | c->layer[2].modulation = tvp->u.data; | ||
1775 | break; | ||
1776 | case DTV_ISDBT_LAYERC_SEGMENT_COUNT: | ||
1777 | c->layer[2].segment_count = tvp->u.data; | ||
1778 | break; | ||
1779 | case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: | ||
1780 | c->layer[2].interleaving = tvp->u.data; | ||
1781 | break; | ||
1782 | case DTV_ISDBS_TS_ID: | ||
1783 | c->isdbs_ts_id = tvp->u.data; | ||
1784 | break; | ||
1785 | case DTV_DVBT2_PLP_ID: | ||
1786 | c->dvbt2_plp_id = tvp->u.data; | ||
1787 | break; | ||
1788 | |||
1789 | /* ATSC-MH */ | ||
1790 | case DTV_ATSCMH_PARADE_ID: | ||
1791 | fe->dtv_property_cache.atscmh_parade_id = tvp->u.data; | ||
1792 | break; | ||
1793 | case DTV_ATSCMH_RS_FRAME_ENSEMBLE: | ||
1794 | fe->dtv_property_cache.atscmh_rs_frame_ensemble = tvp->u.data; | ||
1795 | break; | ||
1796 | |||
1797 | default: | ||
1798 | return -EINVAL; | ||
1799 | } | ||
1800 | |||
1801 | return r; | ||
1802 | } | ||
1803 | |||
1804 | static int dvb_frontend_ioctl(struct file *file, | ||
1805 | unsigned int cmd, void *parg) | ||
1806 | { | ||
1807 | struct dvb_device *dvbdev = file->private_data; | ||
1808 | struct dvb_frontend *fe = dvbdev->priv; | ||
1809 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1810 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
1811 | int err = -EOPNOTSUPP; | ||
1812 | |||
1813 | dprintk("%s (%d)\n", __func__, _IOC_NR(cmd)); | ||
1814 | |||
1815 | if (fepriv->exit != DVB_FE_NO_EXIT) | ||
1816 | return -ENODEV; | ||
1817 | |||
1818 | if ((file->f_flags & O_ACCMODE) == O_RDONLY && | ||
1819 | (_IOC_DIR(cmd) != _IOC_READ || cmd == FE_GET_EVENT || | ||
1820 | cmd == FE_DISEQC_RECV_SLAVE_REPLY)) | ||
1821 | return -EPERM; | ||
1822 | |||
1823 | if (down_interruptible (&fepriv->sem)) | ||
1824 | return -ERESTARTSYS; | ||
1825 | |||
1826 | if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY)) | ||
1827 | err = dvb_frontend_ioctl_properties(file, cmd, parg); | ||
1828 | else { | ||
1829 | c->state = DTV_UNDEFINED; | ||
1830 | err = dvb_frontend_ioctl_legacy(file, cmd, parg); | ||
1831 | } | ||
1832 | |||
1833 | up(&fepriv->sem); | ||
1834 | return err; | ||
1835 | } | ||
1836 | |||
1837 | static int dvb_frontend_ioctl_properties(struct file *file, | ||
1838 | unsigned int cmd, void *parg) | ||
1839 | { | ||
1840 | struct dvb_device *dvbdev = file->private_data; | ||
1841 | struct dvb_frontend *fe = dvbdev->priv; | ||
1842 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
1843 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1844 | int err = 0; | ||
1845 | |||
1846 | struct dtv_properties *tvps = NULL; | ||
1847 | struct dtv_property *tvp = NULL; | ||
1848 | int i; | ||
1849 | |||
1850 | dprintk("%s\n", __func__); | ||
1851 | |||
1852 | if(cmd == FE_SET_PROPERTY) { | ||
1853 | tvps = (struct dtv_properties __user *)parg; | ||
1854 | |||
1855 | dprintk("%s() properties.num = %d\n", __func__, tvps->num); | ||
1856 | dprintk("%s() properties.props = %p\n", __func__, tvps->props); | ||
1857 | |||
1858 | /* Put an arbitrary limit on the number of messages that can | ||
1859 | * be sent at once */ | ||
1860 | if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) | ||
1861 | return -EINVAL; | ||
1862 | |||
1863 | tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL); | ||
1864 | if (!tvp) { | ||
1865 | err = -ENOMEM; | ||
1866 | goto out; | ||
1867 | } | ||
1868 | |||
1869 | if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) { | ||
1870 | err = -EFAULT; | ||
1871 | goto out; | ||
1872 | } | ||
1873 | |||
1874 | for (i = 0; i < tvps->num; i++) { | ||
1875 | err = dtv_property_process_set(fe, tvp + i, file); | ||
1876 | if (err < 0) | ||
1877 | goto out; | ||
1878 | (tvp + i)->result = err; | ||
1879 | } | ||
1880 | |||
1881 | if (c->state == DTV_TUNE) | ||
1882 | dprintk("%s() Property cache is full, tuning\n", __func__); | ||
1883 | |||
1884 | } else | ||
1885 | if(cmd == FE_GET_PROPERTY) { | ||
1886 | tvps = (struct dtv_properties __user *)parg; | ||
1887 | |||
1888 | dprintk("%s() properties.num = %d\n", __func__, tvps->num); | ||
1889 | dprintk("%s() properties.props = %p\n", __func__, tvps->props); | ||
1890 | |||
1891 | /* Put an arbitrary limit on the number of messages that can | ||
1892 | * be sent at once */ | ||
1893 | if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) | ||
1894 | return -EINVAL; | ||
1895 | |||
1896 | tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL); | ||
1897 | if (!tvp) { | ||
1898 | err = -ENOMEM; | ||
1899 | goto out; | ||
1900 | } | ||
1901 | |||
1902 | if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) { | ||
1903 | err = -EFAULT; | ||
1904 | goto out; | ||
1905 | } | ||
1906 | |||
1907 | /* | ||
1908 | * Fills the cache out struct with the cache contents, plus | ||
1909 | * the data retrieved from get_frontend, if the frontend | ||
1910 | * is not idle. Otherwise, returns the cached content | ||
1911 | */ | ||
1912 | if (fepriv->state != FESTATE_IDLE) { | ||
1913 | err = dtv_get_frontend(fe, NULL); | ||
1914 | if (err < 0) | ||
1915 | goto out; | ||
1916 | } | ||
1917 | for (i = 0; i < tvps->num; i++) { | ||
1918 | err = dtv_property_process_get(fe, c, tvp + i, file); | ||
1919 | if (err < 0) | ||
1920 | goto out; | ||
1921 | (tvp + i)->result = err; | ||
1922 | } | ||
1923 | |||
1924 | if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) { | ||
1925 | err = -EFAULT; | ||
1926 | goto out; | ||
1927 | } | ||
1928 | |||
1929 | } else | ||
1930 | err = -EOPNOTSUPP; | ||
1931 | |||
1932 | out: | ||
1933 | kfree(tvp); | ||
1934 | return err; | ||
1935 | } | ||
1936 | |||
1937 | static int dtv_set_frontend(struct dvb_frontend *fe) | ||
1938 | { | ||
1939 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
1940 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1941 | struct dvb_frontend_tune_settings fetunesettings; | ||
1942 | u32 rolloff = 0; | ||
1943 | |||
1944 | if (dvb_frontend_check_parameters(fe) < 0) | ||
1945 | return -EINVAL; | ||
1946 | |||
1947 | /* | ||
1948 | * Initialize output parameters to match the values given by | ||
1949 | * the user. FE_SET_FRONTEND triggers an initial frontend event | ||
1950 | * with status = 0, which copies output parameters to userspace. | ||
1951 | */ | ||
1952 | dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); | ||
1953 | |||
1954 | /* | ||
1955 | * Be sure that the bandwidth will be filled for all | ||
1956 | * non-satellite systems, as tuners need to know what | ||
1957 | * low pass/Nyquist half filter should be applied, in | ||
1958 | * order to avoid inter-channel noise. | ||
1959 | * | ||
1960 | * ISDB-T and DVB-T/T2 already sets bandwidth. | ||
1961 | * ATSC and DVB-C don't set, so, the core should fill it. | ||
1962 | * | ||
1963 | * On DVB-C Annex A and C, the bandwidth is a function of | ||
1964 | * the roll-off and symbol rate. Annex B defines different | ||
1965 | * roll-off factors depending on the modulation. Fortunately, | ||
1966 | * Annex B is only used with 6MHz, so there's no need to | ||
1967 | * calculate it. | ||
1968 | * | ||
1969 | * While not officially supported, a side effect of handling it at | ||
1970 | * the cache level is that a program could retrieve the bandwidth | ||
1971 | * via DTV_BANDWIDTH_HZ, which may be useful for test programs. | ||
1972 | */ | ||
1973 | switch (c->delivery_system) { | ||
1974 | case SYS_ATSC: | ||
1975 | case SYS_DVBC_ANNEX_B: | ||
1976 | c->bandwidth_hz = 6000000; | ||
1977 | break; | ||
1978 | case SYS_DVBC_ANNEX_A: | ||
1979 | rolloff = 115; | ||
1980 | break; | ||
1981 | case SYS_DVBC_ANNEX_C: | ||
1982 | rolloff = 113; | ||
1983 | break; | ||
1984 | default: | ||
1985 | break; | ||
1986 | } | ||
1987 | if (rolloff) | ||
1988 | c->bandwidth_hz = (c->symbol_rate * rolloff) / 100; | ||
1989 | |||
1990 | /* force auto frequency inversion if requested */ | ||
1991 | if (dvb_force_auto_inversion) | ||
1992 | c->inversion = INVERSION_AUTO; | ||
1993 | |||
1994 | /* | ||
1995 | * without hierarchical coding code_rate_LP is irrelevant, | ||
1996 | * so we tolerate the otherwise invalid FEC_NONE setting | ||
1997 | */ | ||
1998 | if (c->hierarchy == HIERARCHY_NONE && c->code_rate_LP == FEC_NONE) | ||
1999 | c->code_rate_LP = FEC_AUTO; | ||
2000 | |||
2001 | /* get frontend-specific tuning settings */ | ||
2002 | memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings)); | ||
2003 | if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) { | ||
2004 | fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000; | ||
2005 | fepriv->max_drift = fetunesettings.max_drift; | ||
2006 | fepriv->step_size = fetunesettings.step_size; | ||
2007 | } else { | ||
2008 | /* default values */ | ||
2009 | switch (c->delivery_system) { | ||
2010 | case SYS_DVBS: | ||
2011 | case SYS_DVBS2: | ||
2012 | case SYS_ISDBS: | ||
2013 | case SYS_TURBO: | ||
2014 | case SYS_DVBC_ANNEX_A: | ||
2015 | case SYS_DVBC_ANNEX_C: | ||
2016 | fepriv->min_delay = HZ / 20; | ||
2017 | fepriv->step_size = c->symbol_rate / 16000; | ||
2018 | fepriv->max_drift = c->symbol_rate / 2000; | ||
2019 | break; | ||
2020 | case SYS_DVBT: | ||
2021 | case SYS_DVBT2: | ||
2022 | case SYS_ISDBT: | ||
2023 | case SYS_DTMB: | ||
2024 | fepriv->min_delay = HZ / 20; | ||
2025 | fepriv->step_size = fe->ops.info.frequency_stepsize * 2; | ||
2026 | fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; | ||
2027 | break; | ||
2028 | default: | ||
2029 | /* | ||
2030 | * FIXME: This sounds wrong! if freqency_stepsize is | ||
2031 | * defined by the frontend, why not use it??? | ||
2032 | */ | ||
2033 | fepriv->min_delay = HZ / 20; | ||
2034 | fepriv->step_size = 0; /* no zigzag */ | ||
2035 | fepriv->max_drift = 0; | ||
2036 | break; | ||
2037 | } | ||
2038 | } | ||
2039 | if (dvb_override_tune_delay > 0) | ||
2040 | fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000; | ||
2041 | |||
2042 | fepriv->state = FESTATE_RETUNE; | ||
2043 | |||
2044 | /* Request the search algorithm to search */ | ||
2045 | fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; | ||
2046 | |||
2047 | dvb_frontend_clear_events(fe); | ||
2048 | dvb_frontend_add_event(fe, 0); | ||
2049 | dvb_frontend_wakeup(fe); | ||
2050 | fepriv->status = 0; | ||
2051 | |||
2052 | return 0; | ||
2053 | } | ||
2054 | |||
2055 | |||
2056 | static int dvb_frontend_ioctl_legacy(struct file *file, | ||
2057 | unsigned int cmd, void *parg) | ||
2058 | { | ||
2059 | struct dvb_device *dvbdev = file->private_data; | ||
2060 | struct dvb_frontend *fe = dvbdev->priv; | ||
2061 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
2062 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
2063 | int err = -EOPNOTSUPP; | ||
2064 | |||
2065 | switch (cmd) { | ||
2066 | case FE_GET_INFO: { | ||
2067 | struct dvb_frontend_info* info = parg; | ||
2068 | |||
2069 | memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info)); | ||
2070 | dvb_frontend_get_frequency_limits(fe, &info->frequency_min, &info->frequency_max); | ||
2071 | |||
2072 | /* | ||
2073 | * Associate the 4 delivery systems supported by DVBv3 | ||
2074 | * API with their DVBv5 counterpart. For the other standards, | ||
2075 | * use the closest type, assuming that it would hopefully | ||
2076 | * work with a DVBv3 application. | ||
2077 | * It should be noticed that, on multi-frontend devices with | ||
2078 | * different types (terrestrial and cable, for example), | ||
2079 | * a pure DVBv3 application won't be able to use all delivery | ||
2080 | * systems. Yet, changing the DVBv5 cache to the other delivery | ||
2081 | * system should be enough for making it work. | ||
2082 | */ | ||
2083 | switch (dvbv3_type(c->delivery_system)) { | ||
2084 | case DVBV3_QPSK: | ||
2085 | info->type = FE_QPSK; | ||
2086 | break; | ||
2087 | case DVBV3_ATSC: | ||
2088 | info->type = FE_ATSC; | ||
2089 | break; | ||
2090 | case DVBV3_QAM: | ||
2091 | info->type = FE_QAM; | ||
2092 | break; | ||
2093 | case DVBV3_OFDM: | ||
2094 | info->type = FE_OFDM; | ||
2095 | break; | ||
2096 | default: | ||
2097 | printk(KERN_ERR | ||
2098 | "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n", | ||
2099 | __func__, c->delivery_system); | ||
2100 | fe->ops.info.type = FE_OFDM; | ||
2101 | } | ||
2102 | dprintk("current delivery system on cache: %d, V3 type: %d\n", | ||
2103 | c->delivery_system, fe->ops.info.type); | ||
2104 | |||
2105 | /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't | ||
2106 | * do it, it is done for it. */ | ||
2107 | info->caps |= FE_CAN_INVERSION_AUTO; | ||
2108 | err = 0; | ||
2109 | break; | ||
2110 | } | ||
2111 | |||
2112 | case FE_READ_STATUS: { | ||
2113 | fe_status_t* status = parg; | ||
2114 | |||
2115 | /* if retune was requested but hasn't occurred yet, prevent | ||
2116 | * that user get signal state from previous tuning */ | ||
2117 | if (fepriv->state == FESTATE_RETUNE || | ||
2118 | fepriv->state == FESTATE_ERROR) { | ||
2119 | err=0; | ||
2120 | *status = 0; | ||
2121 | break; | ||
2122 | } | ||
2123 | |||
2124 | if (fe->ops.read_status) | ||
2125 | err = fe->ops.read_status(fe, status); | ||
2126 | break; | ||
2127 | } | ||
2128 | case FE_READ_BER: | ||
2129 | if (fe->ops.read_ber) | ||
2130 | err = fe->ops.read_ber(fe, (__u32*) parg); | ||
2131 | break; | ||
2132 | |||
2133 | case FE_READ_SIGNAL_STRENGTH: | ||
2134 | if (fe->ops.read_signal_strength) | ||
2135 | err = fe->ops.read_signal_strength(fe, (__u16*) parg); | ||
2136 | break; | ||
2137 | |||
2138 | case FE_READ_SNR: | ||
2139 | if (fe->ops.read_snr) | ||
2140 | err = fe->ops.read_snr(fe, (__u16*) parg); | ||
2141 | break; | ||
2142 | |||
2143 | case FE_READ_UNCORRECTED_BLOCKS: | ||
2144 | if (fe->ops.read_ucblocks) | ||
2145 | err = fe->ops.read_ucblocks(fe, (__u32*) parg); | ||
2146 | break; | ||
2147 | |||
2148 | |||
2149 | case FE_DISEQC_RESET_OVERLOAD: | ||
2150 | if (fe->ops.diseqc_reset_overload) { | ||
2151 | err = fe->ops.diseqc_reset_overload(fe); | ||
2152 | fepriv->state = FESTATE_DISEQC; | ||
2153 | fepriv->status = 0; | ||
2154 | } | ||
2155 | break; | ||
2156 | |||
2157 | case FE_DISEQC_SEND_MASTER_CMD: | ||
2158 | if (fe->ops.diseqc_send_master_cmd) { | ||
2159 | err = fe->ops.diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg); | ||
2160 | fepriv->state = FESTATE_DISEQC; | ||
2161 | fepriv->status = 0; | ||
2162 | } | ||
2163 | break; | ||
2164 | |||
2165 | case FE_DISEQC_SEND_BURST: | ||
2166 | if (fe->ops.diseqc_send_burst) { | ||
2167 | err = fe->ops.diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg); | ||
2168 | fepriv->state = FESTATE_DISEQC; | ||
2169 | fepriv->status = 0; | ||
2170 | } | ||
2171 | break; | ||
2172 | |||
2173 | case FE_SET_TONE: | ||
2174 | if (fe->ops.set_tone) { | ||
2175 | err = fe->ops.set_tone(fe, (fe_sec_tone_mode_t) parg); | ||
2176 | fepriv->tone = (fe_sec_tone_mode_t) parg; | ||
2177 | fepriv->state = FESTATE_DISEQC; | ||
2178 | fepriv->status = 0; | ||
2179 | } | ||
2180 | break; | ||
2181 | |||
2182 | case FE_SET_VOLTAGE: | ||
2183 | if (fe->ops.set_voltage) { | ||
2184 | err = fe->ops.set_voltage(fe, (fe_sec_voltage_t) parg); | ||
2185 | fepriv->voltage = (fe_sec_voltage_t) parg; | ||
2186 | fepriv->state = FESTATE_DISEQC; | ||
2187 | fepriv->status = 0; | ||
2188 | } | ||
2189 | break; | ||
2190 | |||
2191 | case FE_DISHNETWORK_SEND_LEGACY_CMD: | ||
2192 | if (fe->ops.dishnetwork_send_legacy_command) { | ||
2193 | err = fe->ops.dishnetwork_send_legacy_command(fe, (unsigned long) parg); | ||
2194 | fepriv->state = FESTATE_DISEQC; | ||
2195 | fepriv->status = 0; | ||
2196 | } else if (fe->ops.set_voltage) { | ||
2197 | /* | ||
2198 | * NOTE: This is a fallback condition. Some frontends | ||
2199 | * (stv0299 for instance) take longer than 8msec to | ||
2200 | * respond to a set_voltage command. Those switches | ||
2201 | * need custom routines to switch properly. For all | ||
2202 | * other frontends, the following should work ok. | ||
2203 | * Dish network legacy switches (as used by Dish500) | ||
2204 | * are controlled by sending 9-bit command words | ||
2205 | * spaced 8msec apart. | ||
2206 | * the actual command word is switch/port dependent | ||
2207 | * so it is up to the userspace application to send | ||
2208 | * the right command. | ||
2209 | * The command must always start with a '0' after | ||
2210 | * initialization, so parg is 8 bits and does not | ||
2211 | * include the initialization or start bit | ||
2212 | */ | ||
2213 | unsigned long swcmd = ((unsigned long) parg) << 1; | ||
2214 | struct timeval nexttime; | ||
2215 | struct timeval tv[10]; | ||
2216 | int i; | ||
2217 | u8 last = 1; | ||
2218 | if (dvb_frontend_debug) | ||
2219 | printk("%s switch command: 0x%04lx\n", __func__, swcmd); | ||
2220 | do_gettimeofday(&nexttime); | ||
2221 | if (dvb_frontend_debug) | ||
2222 | memcpy(&tv[0], &nexttime, sizeof(struct timeval)); | ||
2223 | /* before sending a command, initialize by sending | ||
2224 | * a 32ms 18V to the switch | ||
2225 | */ | ||
2226 | fe->ops.set_voltage(fe, SEC_VOLTAGE_18); | ||
2227 | dvb_frontend_sleep_until(&nexttime, 32000); | ||
2228 | |||
2229 | for (i = 0; i < 9; i++) { | ||
2230 | if (dvb_frontend_debug) | ||
2231 | do_gettimeofday(&tv[i + 1]); | ||
2232 | if ((swcmd & 0x01) != last) { | ||
2233 | /* set voltage to (last ? 13V : 18V) */ | ||
2234 | fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18); | ||
2235 | last = (last) ? 0 : 1; | ||
2236 | } | ||
2237 | swcmd = swcmd >> 1; | ||
2238 | if (i != 8) | ||
2239 | dvb_frontend_sleep_until(&nexttime, 8000); | ||
2240 | } | ||
2241 | if (dvb_frontend_debug) { | ||
2242 | printk("%s(%d): switch delay (should be 32k followed by all 8k\n", | ||
2243 | __func__, fe->dvb->num); | ||
2244 | for (i = 1; i < 10; i++) | ||
2245 | printk("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i])); | ||
2246 | } | ||
2247 | err = 0; | ||
2248 | fepriv->state = FESTATE_DISEQC; | ||
2249 | fepriv->status = 0; | ||
2250 | } | ||
2251 | break; | ||
2252 | |||
2253 | case FE_DISEQC_RECV_SLAVE_REPLY: | ||
2254 | if (fe->ops.diseqc_recv_slave_reply) | ||
2255 | err = fe->ops.diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg); | ||
2256 | break; | ||
2257 | |||
2258 | case FE_ENABLE_HIGH_LNB_VOLTAGE: | ||
2259 | if (fe->ops.enable_high_lnb_voltage) | ||
2260 | err = fe->ops.enable_high_lnb_voltage(fe, (long) parg); | ||
2261 | break; | ||
2262 | |||
2263 | case FE_SET_FRONTEND: | ||
2264 | err = set_delivery_system(fe, SYS_UNDEFINED); | ||
2265 | if (err) | ||
2266 | break; | ||
2267 | |||
2268 | err = dtv_property_cache_sync(fe, c, parg); | ||
2269 | if (err) | ||
2270 | break; | ||
2271 | err = dtv_set_frontend(fe); | ||
2272 | break; | ||
2273 | case FE_GET_EVENT: | ||
2274 | err = dvb_frontend_get_event (fe, parg, file->f_flags); | ||
2275 | break; | ||
2276 | |||
2277 | case FE_GET_FRONTEND: | ||
2278 | err = dtv_get_frontend(fe, parg); | ||
2279 | break; | ||
2280 | |||
2281 | case FE_SET_FRONTEND_TUNE_MODE: | ||
2282 | fepriv->tune_mode_flags = (unsigned long) parg; | ||
2283 | err = 0; | ||
2284 | break; | ||
2285 | }; | ||
2286 | |||
2287 | return err; | ||
2288 | } | ||
2289 | |||
2290 | |||
2291 | static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struct *wait) | ||
2292 | { | ||
2293 | struct dvb_device *dvbdev = file->private_data; | ||
2294 | struct dvb_frontend *fe = dvbdev->priv; | ||
2295 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
2296 | |||
2297 | dprintk ("%s\n", __func__); | ||
2298 | |||
2299 | poll_wait (file, &fepriv->events.wait_queue, wait); | ||
2300 | |||
2301 | if (fepriv->events.eventw != fepriv->events.eventr) | ||
2302 | return (POLLIN | POLLRDNORM | POLLPRI); | ||
2303 | |||
2304 | return 0; | ||
2305 | } | ||
2306 | |||
2307 | static int dvb_frontend_open(struct inode *inode, struct file *file) | ||
2308 | { | ||
2309 | struct dvb_device *dvbdev = file->private_data; | ||
2310 | struct dvb_frontend *fe = dvbdev->priv; | ||
2311 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
2312 | struct dvb_adapter *adapter = fe->dvb; | ||
2313 | int ret; | ||
2314 | |||
2315 | dprintk ("%s\n", __func__); | ||
2316 | if (fepriv->exit == DVB_FE_DEVICE_REMOVED) | ||
2317 | return -ENODEV; | ||
2318 | |||
2319 | if (adapter->mfe_shared) { | ||
2320 | mutex_lock (&adapter->mfe_lock); | ||
2321 | |||
2322 | if (adapter->mfe_dvbdev == NULL) | ||
2323 | adapter->mfe_dvbdev = dvbdev; | ||
2324 | |||
2325 | else if (adapter->mfe_dvbdev != dvbdev) { | ||
2326 | struct dvb_device | ||
2327 | *mfedev = adapter->mfe_dvbdev; | ||
2328 | struct dvb_frontend | ||
2329 | *mfe = mfedev->priv; | ||
2330 | struct dvb_frontend_private | ||
2331 | *mfepriv = mfe->frontend_priv; | ||
2332 | int mferetry = (dvb_mfe_wait_time << 1); | ||
2333 | |||
2334 | mutex_unlock (&adapter->mfe_lock); | ||
2335 | while (mferetry-- && (mfedev->users != -1 || | ||
2336 | mfepriv->thread != NULL)) { | ||
2337 | if(msleep_interruptible(500)) { | ||
2338 | if(signal_pending(current)) | ||
2339 | return -EINTR; | ||
2340 | } | ||
2341 | } | ||
2342 | |||
2343 | mutex_lock (&adapter->mfe_lock); | ||
2344 | if(adapter->mfe_dvbdev != dvbdev) { | ||
2345 | mfedev = adapter->mfe_dvbdev; | ||
2346 | mfe = mfedev->priv; | ||
2347 | mfepriv = mfe->frontend_priv; | ||
2348 | if (mfedev->users != -1 || | ||
2349 | mfepriv->thread != NULL) { | ||
2350 | mutex_unlock (&adapter->mfe_lock); | ||
2351 | return -EBUSY; | ||
2352 | } | ||
2353 | adapter->mfe_dvbdev = dvbdev; | ||
2354 | } | ||
2355 | } | ||
2356 | } | ||
2357 | |||
2358 | if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) { | ||
2359 | if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0) | ||
2360 | goto err0; | ||
2361 | |||
2362 | /* If we took control of the bus, we need to force | ||
2363 | reinitialization. This is because many ts_bus_ctrl() | ||
2364 | functions strobe the RESET pin on the demod, and if the | ||
2365 | frontend thread already exists then the dvb_init() routine | ||
2366 | won't get called (which is what usually does initial | ||
2367 | register configuration). */ | ||
2368 | fepriv->reinitialise = 1; | ||
2369 | } | ||
2370 | |||
2371 | if ((ret = dvb_generic_open (inode, file)) < 0) | ||
2372 | goto err1; | ||
2373 | |||
2374 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) { | ||
2375 | /* normal tune mode when opened R/W */ | ||
2376 | fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT; | ||
2377 | fepriv->tone = -1; | ||
2378 | fepriv->voltage = -1; | ||
2379 | |||
2380 | ret = dvb_frontend_start (fe); | ||
2381 | if (ret) | ||
2382 | goto err2; | ||
2383 | |||
2384 | /* empty event queue */ | ||
2385 | fepriv->events.eventr = fepriv->events.eventw = 0; | ||
2386 | } | ||
2387 | |||
2388 | if (adapter->mfe_shared) | ||
2389 | mutex_unlock (&adapter->mfe_lock); | ||
2390 | return ret; | ||
2391 | |||
2392 | err2: | ||
2393 | dvb_generic_release(inode, file); | ||
2394 | err1: | ||
2395 | if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) | ||
2396 | fe->ops.ts_bus_ctrl(fe, 0); | ||
2397 | err0: | ||
2398 | if (adapter->mfe_shared) | ||
2399 | mutex_unlock (&adapter->mfe_lock); | ||
2400 | return ret; | ||
2401 | } | ||
2402 | |||
2403 | static int dvb_frontend_release(struct inode *inode, struct file *file) | ||
2404 | { | ||
2405 | struct dvb_device *dvbdev = file->private_data; | ||
2406 | struct dvb_frontend *fe = dvbdev->priv; | ||
2407 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
2408 | int ret; | ||
2409 | |||
2410 | dprintk ("%s\n", __func__); | ||
2411 | |||
2412 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) { | ||
2413 | fepriv->release_jiffies = jiffies; | ||
2414 | mb(); | ||
2415 | } | ||
2416 | |||
2417 | ret = dvb_generic_release (inode, file); | ||
2418 | |||
2419 | if (dvbdev->users == -1) { | ||
2420 | wake_up(&fepriv->wait_queue); | ||
2421 | if (fepriv->exit != DVB_FE_NO_EXIT) { | ||
2422 | fops_put(file->f_op); | ||
2423 | file->f_op = NULL; | ||
2424 | wake_up(&dvbdev->wait_queue); | ||
2425 | } | ||
2426 | if (fe->ops.ts_bus_ctrl) | ||
2427 | fe->ops.ts_bus_ctrl(fe, 0); | ||
2428 | } | ||
2429 | |||
2430 | return ret; | ||
2431 | } | ||
2432 | |||
2433 | static const struct file_operations dvb_frontend_fops = { | ||
2434 | .owner = THIS_MODULE, | ||
2435 | .unlocked_ioctl = dvb_generic_ioctl, | ||
2436 | .poll = dvb_frontend_poll, | ||
2437 | .open = dvb_frontend_open, | ||
2438 | .release = dvb_frontend_release, | ||
2439 | .llseek = noop_llseek, | ||
2440 | }; | ||
2441 | |||
2442 | int dvb_register_frontend(struct dvb_adapter* dvb, | ||
2443 | struct dvb_frontend* fe) | ||
2444 | { | ||
2445 | struct dvb_frontend_private *fepriv; | ||
2446 | static const struct dvb_device dvbdev_template = { | ||
2447 | .users = ~0, | ||
2448 | .writers = 1, | ||
2449 | .readers = (~0)-1, | ||
2450 | .fops = &dvb_frontend_fops, | ||
2451 | .kernel_ioctl = dvb_frontend_ioctl | ||
2452 | }; | ||
2453 | |||
2454 | dprintk ("%s\n", __func__); | ||
2455 | |||
2456 | if (mutex_lock_interruptible(&frontend_mutex)) | ||
2457 | return -ERESTARTSYS; | ||
2458 | |||
2459 | fe->frontend_priv = kzalloc(sizeof(struct dvb_frontend_private), GFP_KERNEL); | ||
2460 | if (fe->frontend_priv == NULL) { | ||
2461 | mutex_unlock(&frontend_mutex); | ||
2462 | return -ENOMEM; | ||
2463 | } | ||
2464 | fepriv = fe->frontend_priv; | ||
2465 | |||
2466 | sema_init(&fepriv->sem, 1); | ||
2467 | init_waitqueue_head (&fepriv->wait_queue); | ||
2468 | init_waitqueue_head (&fepriv->events.wait_queue); | ||
2469 | mutex_init(&fepriv->events.mtx); | ||
2470 | fe->dvb = dvb; | ||
2471 | fepriv->inversion = INVERSION_OFF; | ||
2472 | |||
2473 | printk ("DVB: registering adapter %i frontend %i (%s)...\n", | ||
2474 | fe->dvb->num, | ||
2475 | fe->id, | ||
2476 | fe->ops.info.name); | ||
2477 | |||
2478 | dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template, | ||
2479 | fe, DVB_DEVICE_FRONTEND); | ||
2480 | |||
2481 | /* | ||
2482 | * Initialize the cache to the proper values according with the | ||
2483 | * first supported delivery system (ops->delsys[0]) | ||
2484 | */ | ||
2485 | |||
2486 | fe->dtv_property_cache.delivery_system = fe->ops.delsys[0]; | ||
2487 | dvb_frontend_clear_cache(fe); | ||
2488 | |||
2489 | mutex_unlock(&frontend_mutex); | ||
2490 | return 0; | ||
2491 | } | ||
2492 | EXPORT_SYMBOL(dvb_register_frontend); | ||
2493 | |||
2494 | int dvb_unregister_frontend(struct dvb_frontend* fe) | ||
2495 | { | ||
2496 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
2497 | dprintk ("%s\n", __func__); | ||
2498 | |||
2499 | mutex_lock(&frontend_mutex); | ||
2500 | dvb_frontend_stop (fe); | ||
2501 | mutex_unlock(&frontend_mutex); | ||
2502 | |||
2503 | if (fepriv->dvbdev->users < -1) | ||
2504 | wait_event(fepriv->dvbdev->wait_queue, | ||
2505 | fepriv->dvbdev->users==-1); | ||
2506 | |||
2507 | mutex_lock(&frontend_mutex); | ||
2508 | dvb_unregister_device (fepriv->dvbdev); | ||
2509 | |||
2510 | /* fe is invalid now */ | ||
2511 | kfree(fepriv); | ||
2512 | mutex_unlock(&frontend_mutex); | ||
2513 | return 0; | ||
2514 | } | ||
2515 | EXPORT_SYMBOL(dvb_unregister_frontend); | ||
2516 | |||
2517 | #ifdef CONFIG_MEDIA_ATTACH | ||
2518 | void dvb_frontend_detach(struct dvb_frontend* fe) | ||
2519 | { | ||
2520 | void *ptr; | ||
2521 | |||
2522 | if (fe->ops.release_sec) { | ||
2523 | fe->ops.release_sec(fe); | ||
2524 | symbol_put_addr(fe->ops.release_sec); | ||
2525 | } | ||
2526 | if (fe->ops.tuner_ops.release) { | ||
2527 | fe->ops.tuner_ops.release(fe); | ||
2528 | symbol_put_addr(fe->ops.tuner_ops.release); | ||
2529 | } | ||
2530 | if (fe->ops.analog_ops.release) { | ||
2531 | fe->ops.analog_ops.release(fe); | ||
2532 | symbol_put_addr(fe->ops.analog_ops.release); | ||
2533 | } | ||
2534 | ptr = (void*)fe->ops.release; | ||
2535 | if (ptr) { | ||
2536 | fe->ops.release(fe); | ||
2537 | symbol_put_addr(ptr); | ||
2538 | } | ||
2539 | } | ||
2540 | #else | ||
2541 | void dvb_frontend_detach(struct dvb_frontend* fe) | ||
2542 | { | ||
2543 | if (fe->ops.release_sec) | ||
2544 | fe->ops.release_sec(fe); | ||
2545 | if (fe->ops.tuner_ops.release) | ||
2546 | fe->ops.tuner_ops.release(fe); | ||
2547 | if (fe->ops.analog_ops.release) | ||
2548 | fe->ops.analog_ops.release(fe); | ||
2549 | if (fe->ops.release) | ||
2550 | fe->ops.release(fe); | ||
2551 | } | ||
2552 | #endif | ||
2553 | EXPORT_SYMBOL(dvb_frontend_detach); | ||