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 */ |
