diff options
author | Andrew de Quincey <adq_dvb@lidskialf.net> | 2006-01-09 12:25:07 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@brturbo.com.br> | 2006-01-09 12:25:07 -0500 |
commit | 36cb557a2f64513e2fdc1a542167e5e8a6c1c67e (patch) | |
tree | 02822705dd0bafb191f4fe26fb3f28ef876b1429 | |
parent | 47f3692096eef208d8cb455bfa2b3308cdfc40de (diff) |
DVB (2444): Implement frontend-specific tuning and the ability to disable zigzag
- Implement frontend-specific tuning and the ability to disable zigzag
Signed-off-by: Andrew de Quincey <adq_dvb@lidskialf.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
-rw-r--r-- | drivers/media/dvb/bt8xx/dst.c | 52 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-core/dvb_frontend.c | 307 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-core/dvb_frontend.h | 11 | ||||
-rw-r--r-- | include/linux/dvb/frontend.h | 10 |
4 files changed, 228 insertions, 152 deletions
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 8977c7a313df..3a2ff1cc24b7 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c | |||
@@ -1341,30 +1341,40 @@ static int dst_read_snr(struct dvb_frontend *fe, u16 *snr) | |||
1341 | return 0; | 1341 | return 0; |
1342 | } | 1342 | } |
1343 | 1343 | ||
1344 | static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) | 1344 | static int dst_set_frontend(struct dvb_frontend* fe, |
1345 | struct dvb_frontend_parameters* p, | ||
1346 | unsigned int mode_flags, | ||
1347 | int *delay, | ||
1348 | fe_status_t *status) | ||
1345 | { | 1349 | { |
1346 | struct dst_state *state = fe->demodulator_priv; | 1350 | struct dst_state *state = fe->demodulator_priv; |
1347 | 1351 | ||
1348 | dst_set_freq(state, p->frequency); | 1352 | if (p != NULL) { |
1349 | dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency); | 1353 | dst_set_freq(state, p->frequency); |
1354 | dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency); | ||
1350 | 1355 | ||
1351 | if (state->dst_type == DST_TYPE_IS_SAT) { | 1356 | if (state->dst_type == DST_TYPE_IS_SAT) { |
1352 | if (state->type_flags & DST_TYPE_HAS_OBS_REGS) | 1357 | if (state->type_flags & DST_TYPE_HAS_OBS_REGS) |
1353 | dst_set_inversion(state, p->inversion); | 1358 | dst_set_inversion(state, p->inversion); |
1354 | dst_set_fec(state, p->u.qpsk.fec_inner); | 1359 | dst_set_fec(state, p->u.qpsk.fec_inner); |
1355 | dst_set_symbolrate(state, p->u.qpsk.symbol_rate); | 1360 | dst_set_symbolrate(state, p->u.qpsk.symbol_rate); |
1356 | dst_set_polarization(state); | 1361 | dst_set_polarization(state); |
1357 | dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate); | 1362 | dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate); |
1358 | 1363 | ||
1359 | } else if (state->dst_type == DST_TYPE_IS_TERR) | 1364 | } else if (state->dst_type == DST_TYPE_IS_TERR) |
1360 | dst_set_bandwidth(state, p->u.ofdm.bandwidth); | 1365 | dst_set_bandwidth(state, p->u.ofdm.bandwidth); |
1361 | else if (state->dst_type == DST_TYPE_IS_CABLE) { | 1366 | else if (state->dst_type == DST_TYPE_IS_CABLE) { |
1362 | dst_set_fec(state, p->u.qam.fec_inner); | 1367 | dst_set_fec(state, p->u.qam.fec_inner); |
1363 | dst_set_symbolrate(state, p->u.qam.symbol_rate); | 1368 | dst_set_symbolrate(state, p->u.qam.symbol_rate); |
1364 | dst_set_modulation(state, p->u.qam.modulation); | 1369 | dst_set_modulation(state, p->u.qam.modulation); |
1370 | } | ||
1371 | dst_write_tuna(fe); | ||
1365 | } | 1372 | } |
1366 | dst_write_tuna(fe); | ||
1367 | 1373 | ||
1374 | if (!(mode_flags & FE_TUNE_MODE_ONESHOT)) | ||
1375 | dst_read_status(fe, status); | ||
1376 | |||
1377 | *delay = HZ/10; | ||
1368 | return 0; | 1378 | return 0; |
1369 | } | 1379 | } |
1370 | 1380 | ||
@@ -1445,7 +1455,7 @@ static struct dvb_frontend_ops dst_dvbt_ops = { | |||
1445 | 1455 | ||
1446 | .release = dst_release, | 1456 | .release = dst_release, |
1447 | .init = dst_init, | 1457 | .init = dst_init, |
1448 | .set_frontend = dst_set_frontend, | 1458 | .tune = dst_set_frontend, |
1449 | .get_frontend = dst_get_frontend, | 1459 | .get_frontend = dst_get_frontend, |
1450 | .read_status = dst_read_status, | 1460 | .read_status = dst_read_status, |
1451 | .read_signal_strength = dst_read_signal_strength, | 1461 | .read_signal_strength = dst_read_signal_strength, |
@@ -1469,7 +1479,7 @@ static struct dvb_frontend_ops dst_dvbs_ops = { | |||
1469 | 1479 | ||
1470 | .release = dst_release, | 1480 | .release = dst_release, |
1471 | .init = dst_init, | 1481 | .init = dst_init, |
1472 | .set_frontend = dst_set_frontend, | 1482 | .tune = dst_set_frontend, |
1473 | .get_frontend = dst_get_frontend, | 1483 | .get_frontend = dst_get_frontend, |
1474 | .read_status = dst_read_status, | 1484 | .read_status = dst_read_status, |
1475 | .read_signal_strength = dst_read_signal_strength, | 1485 | .read_signal_strength = dst_read_signal_strength, |
@@ -1496,7 +1506,7 @@ static struct dvb_frontend_ops dst_dvbc_ops = { | |||
1496 | 1506 | ||
1497 | .release = dst_release, | 1507 | .release = dst_release, |
1498 | .init = dst_init, | 1508 | .init = dst_init, |
1499 | .set_frontend = dst_set_frontend, | 1509 | .tune = dst_set_frontend, |
1500 | .get_frontend = dst_get_frontend, | 1510 | .get_frontend = dst_get_frontend, |
1501 | .read_status = dst_read_status, | 1511 | .read_status = dst_read_status, |
1502 | .read_signal_strength = dst_read_signal_strength, | 1512 | .read_signal_strength = dst_read_signal_strength, |
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 95ea5095e07e..9b5fa540e1e7 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c | |||
@@ -92,6 +92,7 @@ static DECLARE_MUTEX(frontend_mutex); | |||
92 | 92 | ||
93 | struct dvb_frontend_private { | 93 | struct dvb_frontend_private { |
94 | 94 | ||
95 | /* thread/frontend values */ | ||
95 | struct dvb_device *dvbdev; | 96 | struct dvb_device *dvbdev; |
96 | struct dvb_frontend_parameters parameters; | 97 | struct dvb_frontend_parameters parameters; |
97 | struct dvb_fe_events events; | 98 | struct dvb_fe_events events; |
@@ -100,20 +101,25 @@ struct dvb_frontend_private { | |||
100 | wait_queue_head_t wait_queue; | 101 | wait_queue_head_t wait_queue; |
101 | pid_t thread_pid; | 102 | pid_t thread_pid; |
102 | unsigned long release_jiffies; | 103 | unsigned long release_jiffies; |
103 | int state; | 104 | unsigned int exit; |
104 | int bending; | 105 | unsigned int wakeup; |
105 | int lnb_drift; | ||
106 | int inversion; | ||
107 | int auto_step; | ||
108 | int auto_sub_step; | ||
109 | int started_auto_step; | ||
110 | int min_delay; | ||
111 | int max_drift; | ||
112 | int step_size; | ||
113 | int exit; | ||
114 | int wakeup; | ||
115 | fe_status_t status; | 106 | fe_status_t status; |
116 | fe_sec_tone_mode_t tone; | 107 | unsigned int tune_mode_flags; |
108 | unsigned int delay; | ||
109 | |||
110 | /* swzigzag values */ | ||
111 | unsigned int state; | ||
112 | unsigned int bending; | ||
113 | int lnb_drift; | ||
114 | unsigned int inversion; | ||
115 | unsigned int auto_step; | ||
116 | unsigned int auto_sub_step; | ||
117 | unsigned int started_auto_step; | ||
118 | unsigned int min_delay; | ||
119 | unsigned int max_drift; | ||
120 | unsigned int step_size; | ||
121 | int quality; | ||
122 | unsigned int check_wrapped; | ||
117 | }; | 123 | }; |
118 | 124 | ||
119 | 125 | ||
@@ -208,21 +214,21 @@ static void dvb_frontend_init(struct dvb_frontend *fe) | |||
208 | fe->ops->init(fe); | 214 | fe->ops->init(fe); |
209 | } | 215 | } |
210 | 216 | ||
211 | static void update_delay(int *quality, int *delay, int min_delay, int locked) | 217 | static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked) |
212 | { | 218 | { |
213 | int q2; | 219 | int q2; |
214 | 220 | ||
215 | dprintk ("%s\n", __FUNCTION__); | 221 | dprintk ("%s\n", __FUNCTION__); |
216 | 222 | ||
217 | if (locked) | 223 | if (locked) |
218 | (*quality) = (*quality * 220 + 36*256) / 256; | 224 | (fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256; |
219 | else | 225 | else |
220 | (*quality) = (*quality * 220 + 0) / 256; | 226 | (fepriv->quality) = (fepriv->quality * 220 + 0) / 256; |
221 | 227 | ||
222 | q2 = *quality - 128; | 228 | q2 = fepriv->quality - 128; |
223 | q2 *= q2; | 229 | q2 *= q2; |
224 | 230 | ||
225 | *delay = min_delay + q2 * HZ / (128*128); | 231 | fepriv->delay = fepriv->min_delay + q2 * HZ / (128*128); |
226 | } | 232 | } |
227 | 233 | ||
228 | /** | 234 | /** |
@@ -232,7 +238,7 @@ static void update_delay(int *quality, int *delay, int min_delay, int locked) | |||
232 | * @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT | 238 | * @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT |
233 | * @returns Number of complete iterations that have been performed. | 239 | * @returns Number of complete iterations that have been performed. |
234 | */ | 240 | */ |
235 | static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped) | 241 | static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wrapped) |
236 | { | 242 | { |
237 | int autoinversion; | 243 | int autoinversion; |
238 | int ready = 0; | 244 | int ready = 0; |
@@ -321,6 +327,129 @@ static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped) | |||
321 | return 0; | 327 | return 0; |
322 | } | 328 | } |
323 | 329 | ||
330 | static void dvb_frontend_swzigzag(struct dvb_frontend *fe) | ||
331 | { | ||
332 | fe_status_t s; | ||
333 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
334 | |||
335 | /* if we've got no parameters, just keep idling */ | ||
336 | if (fepriv->state & FESTATE_IDLE) { | ||
337 | fepriv->delay = 3*HZ; | ||
338 | fepriv->quality = 0; | ||
339 | return; | ||
340 | } | ||
341 | |||
342 | /* in SCAN mode, we just set the frontend when asked and leave it alone */ | ||
343 | if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) { | ||
344 | if (fepriv->state & FESTATE_RETUNE) { | ||
345 | if (fe->ops->set_frontend) | ||
346 | fe->ops->set_frontend(fe, &fepriv->parameters); | ||
347 | fepriv->state = FESTATE_TUNED; | ||
348 | } | ||
349 | fepriv->delay = 3*HZ; | ||
350 | fepriv->quality = 0; | ||
351 | return; | ||
352 | } | ||
353 | |||
354 | /* get the frontend status */ | ||
355 | if (fepriv->state & FESTATE_RETUNE) { | ||
356 | s = 0; | ||
357 | } else { | ||
358 | if (fe->ops->read_status) | ||
359 | fe->ops->read_status(fe, &s); | ||
360 | if (s != fepriv->status) { | ||
361 | dvb_frontend_add_event(fe, s); | ||
362 | fepriv->status = s; | ||
363 | } | ||
364 | } | ||
365 | |||
366 | /* if we're not tuned, and we have a lock, move to the TUNED state */ | ||
367 | if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) { | ||
368 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
369 | fepriv->state = FESTATE_TUNED; | ||
370 | |||
371 | /* if we're tuned, then we have determined the correct inversion */ | ||
372 | if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) && | ||
373 | (fepriv->parameters.inversion == INVERSION_AUTO)) { | ||
374 | fepriv->parameters.inversion = fepriv->inversion; | ||
375 | } | ||
376 | return; | ||
377 | } | ||
378 | |||
379 | /* if we are tuned already, check we're still locked */ | ||
380 | if (fepriv->state & FESTATE_TUNED) { | ||
381 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
382 | |||
383 | /* we're tuned, and the lock is still good... */ | ||
384 | if (s & FE_HAS_LOCK) { | ||
385 | return; | ||
386 | } else { /* if we _WERE_ tuned, but now don't have a lock */ | ||
387 | fepriv->state = FESTATE_ZIGZAG_FAST; | ||
388 | fepriv->started_auto_step = fepriv->auto_step; | ||
389 | fepriv->check_wrapped = 0; | ||
390 | } | ||
391 | } | ||
392 | |||
393 | /* don't actually do anything if we're in the LOSTLOCK state, | ||
394 | * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */ | ||
395 | if ((fepriv->state & FESTATE_LOSTLOCK) && | ||
396 | (fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) { | ||
397 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
398 | return; | ||
399 | } | ||
400 | |||
401 | /* don't do anything if we're in the DISEQC state, since this | ||
402 | * might be someone with a motorized dish controlled by DISEQC. | ||
403 | * If its actually a re-tune, there will be a SET_FRONTEND soon enough. */ | ||
404 | if (fepriv->state & FESTATE_DISEQC) { | ||
405 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
406 | return; | ||
407 | } | ||
408 | |||
409 | /* if we're in the RETUNE state, set everything up for a brand | ||
410 | * new scan, keeping the current inversion setting, as the next | ||
411 | * tune is _very_ likely to require the same */ | ||
412 | if (fepriv->state & FESTATE_RETUNE) { | ||
413 | fepriv->lnb_drift = 0; | ||
414 | fepriv->auto_step = 0; | ||
415 | fepriv->auto_sub_step = 0; | ||
416 | fepriv->started_auto_step = 0; | ||
417 | fepriv->check_wrapped = 0; | ||
418 | } | ||
419 | |||
420 | /* fast zigzag. */ | ||
421 | if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) { | ||
422 | fepriv->delay = fepriv->min_delay; | ||
423 | |||
424 | /* peform a tune */ | ||
425 | if (dvb_frontend_swzigzag_autotune(fe, fepriv->check_wrapped)) { | ||
426 | /* OK, if we've run out of trials at the fast speed. | ||
427 | * Drop back to slow for the _next_ attempt */ | ||
428 | fepriv->state = FESTATE_SEARCHING_SLOW; | ||
429 | fepriv->started_auto_step = fepriv->auto_step; | ||
430 | return; | ||
431 | } | ||
432 | fepriv->check_wrapped = 1; | ||
433 | |||
434 | /* if we've just retuned, enter the ZIGZAG_FAST state. | ||
435 | * This ensures we cannot return from an | ||
436 | * FE_SET_FRONTEND ioctl before the first frontend tune | ||
437 | * occurs */ | ||
438 | if (fepriv->state & FESTATE_RETUNE) { | ||
439 | fepriv->state = FESTATE_TUNING_FAST; | ||
440 | } | ||
441 | } | ||
442 | |||
443 | /* slow zigzag */ | ||
444 | if (fepriv->state & FESTATE_SEARCHING_SLOW) { | ||
445 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
446 | |||
447 | /* Note: don't bother checking for wrapping; we stay in this | ||
448 | * state until we get a lock */ | ||
449 | dvb_frontend_swzigzag_autotune(fe, 0); | ||
450 | } | ||
451 | } | ||
452 | |||
324 | static int dvb_frontend_is_exiting(struct dvb_frontend *fe) | 453 | static int dvb_frontend_is_exiting(struct dvb_frontend *fe) |
325 | { | 454 | { |
326 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | 455 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
@@ -330,7 +459,7 @@ static int dvb_frontend_is_exiting(struct dvb_frontend *fe) | |||
330 | 459 | ||
331 | if (fepriv->dvbdev->writers == 1) | 460 | if (fepriv->dvbdev->writers == 1) |
332 | if (time_after(jiffies, fepriv->release_jiffies + | 461 | if (time_after(jiffies, fepriv->release_jiffies + |
333 | dvb_shutdown_timeout * HZ)) | 462 | dvb_shutdown_timeout * HZ)) |
334 | return 1; | 463 | return 1; |
335 | 464 | ||
336 | return 0; | 465 | return 0; |
@@ -355,18 +484,14 @@ static void dvb_frontend_wakeup(struct dvb_frontend *fe) | |||
355 | wake_up_interruptible(&fepriv->wait_queue); | 484 | wake_up_interruptible(&fepriv->wait_queue); |
356 | } | 485 | } |
357 | 486 | ||
358 | /* | ||
359 | * FIXME: use linux/kthread.h | ||
360 | */ | ||
361 | static int dvb_frontend_thread(void *data) | 487 | static int dvb_frontend_thread(void *data) |
362 | { | 488 | { |
363 | struct dvb_frontend *fe = data; | 489 | struct dvb_frontend *fe = data; |
364 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | 490 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
365 | unsigned long timeout; | 491 | unsigned long timeout; |
366 | char name [15]; | 492 | char name [15]; |
367 | int quality = 0, delay = 3*HZ; | ||
368 | fe_status_t s; | 493 | fe_status_t s; |
369 | int check_wrapped = 0; | 494 | struct dvb_frontend_parameters *params; |
370 | 495 | ||
371 | dprintk("%s\n", __FUNCTION__); | 496 | dprintk("%s\n", __FUNCTION__); |
372 | 497 | ||
@@ -377,6 +502,9 @@ static int dvb_frontend_thread(void *data) | |||
377 | sigfillset(¤t->blocked); | 502 | sigfillset(¤t->blocked); |
378 | unlock_kernel(); | 503 | unlock_kernel(); |
379 | 504 | ||
505 | fepriv->check_wrapped = 0; | ||
506 | fepriv->quality = 0; | ||
507 | fepriv->delay = 3*HZ; | ||
380 | fepriv->status = 0; | 508 | fepriv->status = 0; |
381 | dvb_frontend_init(fe); | 509 | dvb_frontend_init(fe); |
382 | fepriv->wakeup = 0; | 510 | fepriv->wakeup = 0; |
@@ -386,7 +514,7 @@ static int dvb_frontend_thread(void *data) | |||
386 | 514 | ||
387 | timeout = wait_event_interruptible_timeout(fepriv->wait_queue, | 515 | timeout = wait_event_interruptible_timeout(fepriv->wait_queue, |
388 | dvb_frontend_should_wakeup(fe), | 516 | dvb_frontend_should_wakeup(fe), |
389 | delay); | 517 | fepriv->delay); |
390 | if (0 != dvb_frontend_is_exiting(fe)) { | 518 | if (0 != dvb_frontend_is_exiting(fe)) { |
391 | /* got signal or quitting */ | 519 | /* got signal or quitting */ |
392 | break; | 520 | break; |
@@ -397,108 +525,22 @@ static int dvb_frontend_thread(void *data) | |||
397 | if (down_interruptible(&fepriv->sem)) | 525 | if (down_interruptible(&fepriv->sem)) |
398 | break; | 526 | break; |
399 | 527 | ||
400 | /* if we've got no parameters, just keep idling */ | 528 | /* do an iteration of the tuning loop */ |
401 | if (fepriv->state & FESTATE_IDLE) { | 529 | if (fe->ops->tune) { |
402 | delay = 3*HZ; | 530 | /* have we been asked to retune? */ |
403 | quality = 0; | 531 | params = NULL; |
404 | continue; | 532 | if (fepriv->state & FESTATE_RETUNE) { |
405 | } | 533 | params = &fepriv->parameters; |
534 | fepriv->state = FESTATE_TUNED; | ||
535 | } | ||
406 | 536 | ||
407 | /* get the frontend status */ | 537 | fe->ops->tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s); |
408 | if (fepriv->state & FESTATE_RETUNE) { | ||
409 | s = 0; | ||
410 | } else { | ||
411 | if (fe->ops->read_status) | ||
412 | fe->ops->read_status(fe, &s); | ||
413 | if (s != fepriv->status) { | 538 | if (s != fepriv->status) { |
414 | dvb_frontend_add_event(fe, s); | 539 | dvb_frontend_add_event(fe, s); |
415 | fepriv->status = s; | 540 | fepriv->status = s; |
416 | } | 541 | } |
417 | } | 542 | } else { |
418 | /* if we're not tuned, and we have a lock, move to the TUNED state */ | 543 | dvb_frontend_swzigzag(fe); |
419 | if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) { | ||
420 | update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); | ||
421 | fepriv->state = FESTATE_TUNED; | ||
422 | |||
423 | /* if we're tuned, then we have determined the correct inversion */ | ||
424 | if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) && | ||
425 | (fepriv->parameters.inversion == INVERSION_AUTO)) { | ||
426 | fepriv->parameters.inversion = fepriv->inversion; | ||
427 | } | ||
428 | continue; | ||
429 | } | ||
430 | |||
431 | /* if we are tuned already, check we're still locked */ | ||
432 | if (fepriv->state & FESTATE_TUNED) { | ||
433 | update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); | ||
434 | |||
435 | /* we're tuned, and the lock is still good... */ | ||
436 | if (s & FE_HAS_LOCK) | ||
437 | continue; | ||
438 | else { /* if we _WERE_ tuned, but now don't have a lock */ | ||
439 | fepriv->state = FESTATE_ZIGZAG_FAST; | ||
440 | fepriv->started_auto_step = fepriv->auto_step; | ||
441 | check_wrapped = 0; | ||
442 | } | ||
443 | } | ||
444 | |||
445 | /* don't actually do anything if we're in the LOSTLOCK state, | ||
446 | * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */ | ||
447 | if ((fepriv->state & FESTATE_LOSTLOCK) && | ||
448 | (fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) { | ||
449 | update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); | ||
450 | continue; | ||
451 | } | ||
452 | |||
453 | /* don't do anything if we're in the DISEQC state, since this | ||
454 | * might be someone with a motorized dish controlled by DISEQC. | ||
455 | * If its actually a re-tune, there will be a SET_FRONTEND soon enough. */ | ||
456 | if (fepriv->state & FESTATE_DISEQC) { | ||
457 | update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); | ||
458 | continue; | ||
459 | } | ||
460 | |||
461 | /* if we're in the RETUNE state, set everything up for a brand | ||
462 | * new scan, keeping the current inversion setting, as the next | ||
463 | * tune is _very_ likely to require the same */ | ||
464 | if (fepriv->state & FESTATE_RETUNE) { | ||
465 | fepriv->lnb_drift = 0; | ||
466 | fepriv->auto_step = 0; | ||
467 | fepriv->auto_sub_step = 0; | ||
468 | fepriv->started_auto_step = 0; | ||
469 | check_wrapped = 0; | ||
470 | } | ||
471 | |||
472 | /* fast zigzag. */ | ||
473 | if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) { | ||
474 | delay = fepriv->min_delay; | ||
475 | |||
476 | /* peform a tune */ | ||
477 | if (dvb_frontend_autotune(fe, check_wrapped)) { | ||
478 | /* OK, if we've run out of trials at the fast speed. | ||
479 | * Drop back to slow for the _next_ attempt */ | ||
480 | fepriv->state = FESTATE_SEARCHING_SLOW; | ||
481 | fepriv->started_auto_step = fepriv->auto_step; | ||
482 | continue; | ||
483 | } | ||
484 | check_wrapped = 1; | ||
485 | |||
486 | /* if we've just retuned, enter the ZIGZAG_FAST state. | ||
487 | * This ensures we cannot return from an | ||
488 | * FE_SET_FRONTEND ioctl before the first frontend tune | ||
489 | * occurs */ | ||
490 | if (fepriv->state & FESTATE_RETUNE) { | ||
491 | fepriv->state = FESTATE_TUNING_FAST; | ||
492 | } | ||
493 | } | ||
494 | |||
495 | /* slow zigzag */ | ||
496 | if (fepriv->state & FESTATE_SEARCHING_SLOW) { | ||
497 | update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); | ||
498 | |||
499 | /* Note: don't bother checking for wrapping; we stay in this | ||
500 | * state until we get a lock */ | ||
501 | dvb_frontend_autotune(fe, 0); | ||
502 | } | 544 | } |
503 | } | 545 | } |
504 | 546 | ||
@@ -733,7 +775,6 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, | |||
733 | err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg); | 775 | err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg); |
734 | fepriv->state = FESTATE_DISEQC; | 776 | fepriv->state = FESTATE_DISEQC; |
735 | fepriv->status = 0; | 777 | fepriv->status = 0; |
736 | fepriv->tone = (fe_sec_tone_mode_t) parg; | ||
737 | } | 778 | } |
738 | break; | 779 | break; |
739 | 780 | ||
@@ -891,6 +932,10 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, | |||
891 | err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg); | 932 | err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg); |
892 | } | 933 | } |
893 | break; | 934 | break; |
935 | |||
936 | case FE_SET_FRONTEND_TUNE_MODE: | ||
937 | fepriv->tune_mode_flags = (unsigned int) parg; | ||
938 | break; | ||
894 | }; | 939 | }; |
895 | 940 | ||
896 | up (&fepriv->sem); | 941 | up (&fepriv->sem); |
@@ -932,6 +977,9 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) | |||
932 | 977 | ||
933 | /* empty event queue */ | 978 | /* empty event queue */ |
934 | fepriv->events.eventr = fepriv->events.eventw = 0; | 979 | fepriv->events.eventr = fepriv->events.eventw = 0; |
980 | |||
981 | /* normal tune mode when opened R/W */ | ||
982 | fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT; | ||
935 | } | 983 | } |
936 | 984 | ||
937 | return ret; | 985 | return ret; |
@@ -990,7 +1038,6 @@ int dvb_register_frontend(struct dvb_adapter* dvb, | |||
990 | init_MUTEX (&fepriv->events.sem); | 1038 | init_MUTEX (&fepriv->events.sem); |
991 | fe->dvb = dvb; | 1039 | fe->dvb = dvb; |
992 | fepriv->inversion = INVERSION_OFF; | 1040 | fepriv->inversion = INVERSION_OFF; |
993 | fepriv->tone = SEC_TONE_OFF; | ||
994 | 1041 | ||
995 | printk ("DVB: registering frontend %i (%s)...\n", | 1042 | printk ("DVB: registering frontend %i (%s)...\n", |
996 | fe->dvb->num, | 1043 | fe->dvb->num, |
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index 1e0840d02f1f..48c3f81be912 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h | |||
@@ -58,10 +58,19 @@ struct dvb_frontend_ops { | |||
58 | int (*init)(struct dvb_frontend* fe); | 58 | int (*init)(struct dvb_frontend* fe); |
59 | int (*sleep)(struct dvb_frontend* fe); | 59 | int (*sleep)(struct dvb_frontend* fe); |
60 | 60 | ||
61 | /* if this is set, it overrides the default swzigzag */ | ||
62 | int (*tune)(struct dvb_frontend* fe, | ||
63 | struct dvb_frontend_parameters* params, | ||
64 | unsigned int mode_flags, | ||
65 | int *delay, | ||
66 | fe_status_t *status); | ||
67 | |||
68 | /* these two are only used for the swzigzag code */ | ||
61 | int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); | 69 | int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); |
62 | int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); | ||
63 | int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings); | 70 | int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings); |
64 | 71 | ||
72 | int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); | ||
73 | |||
65 | int (*read_status)(struct dvb_frontend* fe, fe_status_t* status); | 74 | int (*read_status)(struct dvb_frontend* fe, fe_status_t* status); |
66 | int (*read_ber)(struct dvb_frontend* fe, u32* ber); | 75 | int (*read_ber)(struct dvb_frontend* fe, u32* ber); |
67 | int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength); | 76 | int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength); |
diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index d41df7047ed7..c8cbd90ba375 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h | |||
@@ -240,6 +240,15 @@ struct dvb_frontend_event { | |||
240 | }; | 240 | }; |
241 | 241 | ||
242 | 242 | ||
243 | /** | ||
244 | * When set, this flag will disable any zigzagging or other "normal" tuning | ||
245 | * behaviour. Additionally, there will be no automatic monitoring of the lock | ||
246 | * status, and hence no frontend events will be generated. If a frontend device | ||
247 | * is closed, this flag will be automatically turned off when the device is | ||
248 | * reopened read-write. | ||
249 | */ | ||
250 | #define FE_TUNE_MODE_ONESHOT 0x01 | ||
251 | |||
243 | 252 | ||
244 | #define FE_GET_INFO _IOR('o', 61, struct dvb_frontend_info) | 253 | #define FE_GET_INFO _IOR('o', 61, struct dvb_frontend_info) |
245 | 254 | ||
@@ -260,6 +269,7 @@ struct dvb_frontend_event { | |||
260 | 269 | ||
261 | #define FE_SET_FRONTEND _IOW('o', 76, struct dvb_frontend_parameters) | 270 | #define FE_SET_FRONTEND _IOW('o', 76, struct dvb_frontend_parameters) |
262 | #define FE_GET_FRONTEND _IOR('o', 77, struct dvb_frontend_parameters) | 271 | #define FE_GET_FRONTEND _IOR('o', 77, struct dvb_frontend_parameters) |
272 | #define FE_SET_FRONTEND_TUNE_MODE _IO('o', 81) /* unsigned int */ | ||
263 | #define FE_GET_EVENT _IOR('o', 78, struct dvb_frontend_event) | 273 | #define FE_GET_EVENT _IOR('o', 78, struct dvb_frontend_event) |
264 | 274 | ||
265 | #define FE_DISHNETWORK_SEND_LEGACY_CMD _IO('o', 80) /* unsigned int */ | 275 | #define FE_DISHNETWORK_SEND_LEGACY_CMD _IO('o', 80) /* unsigned int */ |