diff options
Diffstat (limited to 'drivers/media/dvb/dvb-core/dvb_frontend.c')
-rw-r--r-- | drivers/media/dvb/dvb-core/dvb_frontend.c | 885 |
1 files changed, 569 insertions, 316 deletions
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 2c0acdb4d81..b15db4fe347 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c | |||
@@ -25,6 +25,9 @@ | |||
25 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | 25 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html |
26 | */ | 26 | */ |
27 | 27 | ||
28 | /* Enables DVBv3 compatibility bits at the headers */ | ||
29 | #define __DVB_CORE__ | ||
30 | |||
28 | #include <linux/string.h> | 31 | #include <linux/string.h> |
29 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
30 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
@@ -105,7 +108,6 @@ struct dvb_frontend_private { | |||
105 | 108 | ||
106 | /* thread/frontend values */ | 109 | /* thread/frontend values */ |
107 | struct dvb_device *dvbdev; | 110 | struct dvb_device *dvbdev; |
108 | struct dvb_frontend_parameters parameters_in; | ||
109 | struct dvb_frontend_parameters parameters_out; | 111 | struct dvb_frontend_parameters parameters_out; |
110 | struct dvb_fe_events events; | 112 | struct dvb_fe_events events; |
111 | struct semaphore sem; | 113 | struct semaphore sem; |
@@ -139,6 +141,62 @@ struct dvb_frontend_private { | |||
139 | }; | 141 | }; |
140 | 142 | ||
141 | static void dvb_frontend_wakeup(struct dvb_frontend *fe); | 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 | |||
147 | static bool has_get_frontend(struct dvb_frontend *fe) | ||
148 | { | ||
149 | return fe->ops.get_frontend; | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | * Due to DVBv3 API calls, a delivery system should be mapped into one of | ||
154 | * the 4 DVBv3 delivery systems (FE_QPSK, FE_QAM, FE_OFDM or FE_ATSC), | ||
155 | * otherwise, a DVBv3 call will fail. | ||
156 | */ | ||
157 | enum dvbv3_emulation_type { | ||
158 | DVBV3_UNKNOWN, | ||
159 | DVBV3_QPSK, | ||
160 | DVBV3_QAM, | ||
161 | DVBV3_OFDM, | ||
162 | DVBV3_ATSC, | ||
163 | }; | ||
164 | |||
165 | static enum dvbv3_emulation_type dvbv3_type(u32 delivery_system) | ||
166 | { | ||
167 | switch (delivery_system) { | ||
168 | case SYS_DVBC_ANNEX_A: | ||
169 | case SYS_DVBC_ANNEX_C: | ||
170 | return DVBV3_QAM; | ||
171 | case SYS_DVBS: | ||
172 | case SYS_DVBS2: | ||
173 | case SYS_TURBO: | ||
174 | case SYS_ISDBS: | ||
175 | case SYS_DSS: | ||
176 | return DVBV3_QPSK; | ||
177 | case SYS_DVBT: | ||
178 | case SYS_DVBT2: | ||
179 | case SYS_ISDBT: | ||
180 | case SYS_DMBTH: | ||
181 | return DVBV3_OFDM; | ||
182 | case SYS_ATSC: | ||
183 | case SYS_DVBC_ANNEX_B: | ||
184 | return DVBV3_ATSC; | ||
185 | case SYS_UNDEFINED: | ||
186 | case SYS_ISDBC: | ||
187 | case SYS_DVBH: | ||
188 | case SYS_DAB: | ||
189 | case SYS_ATSCMH: | ||
190 | default: | ||
191 | /* | ||
192 | * Doesn't know how to emulate those types and/or | ||
193 | * there's no frontend driver from this type yet | ||
194 | * with some emulation code, so, we're not sure yet how | ||
195 | * to handle them, or they're not compatible with a DVBv3 call. | ||
196 | */ | ||
197 | return DVBV3_UNKNOWN; | ||
198 | } | ||
199 | } | ||
142 | 200 | ||
143 | static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status) | 201 | static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status) |
144 | { | 202 | { |
@@ -149,8 +207,8 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status) | |||
149 | 207 | ||
150 | dprintk ("%s\n", __func__); | 208 | dprintk ("%s\n", __func__); |
151 | 209 | ||
152 | if ((status & FE_HAS_LOCK) && fe->ops.get_frontend) | 210 | if ((status & FE_HAS_LOCK) && has_get_frontend(fe)) |
153 | fe->ops.get_frontend(fe, &fepriv->parameters_out); | 211 | dtv_get_frontend(fe, &fepriv->parameters_out); |
154 | 212 | ||
155 | mutex_lock(&events->mtx); | 213 | mutex_lock(&events->mtx); |
156 | 214 | ||
@@ -277,12 +335,13 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra | |||
277 | int ready = 0; | 335 | int ready = 0; |
278 | int fe_set_err = 0; | 336 | int fe_set_err = 0; |
279 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | 337 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
280 | int original_inversion = fepriv->parameters_in.inversion; | 338 | struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp; |
281 | u32 original_frequency = fepriv->parameters_in.frequency; | 339 | int original_inversion = c->inversion; |
340 | u32 original_frequency = c->frequency; | ||
282 | 341 | ||
283 | /* are we using autoinversion? */ | 342 | /* are we using autoinversion? */ |
284 | autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && | 343 | autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && |
285 | (fepriv->parameters_in.inversion == INVERSION_AUTO)); | 344 | (c->inversion == INVERSION_AUTO)); |
286 | 345 | ||
287 | /* setup parameters correctly */ | 346 | /* setup parameters correctly */ |
288 | while(!ready) { | 347 | while(!ready) { |
@@ -348,19 +407,20 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra | |||
348 | fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step); | 407 | fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step); |
349 | 408 | ||
350 | /* set the frontend itself */ | 409 | /* set the frontend itself */ |
351 | fepriv->parameters_in.frequency += fepriv->lnb_drift; | 410 | c->frequency += fepriv->lnb_drift; |
352 | if (autoinversion) | 411 | if (autoinversion) |
353 | fepriv->parameters_in.inversion = fepriv->inversion; | 412 | c->inversion = fepriv->inversion; |
413 | tmp = *c; | ||
354 | if (fe->ops.set_frontend) | 414 | if (fe->ops.set_frontend) |
355 | fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters_in); | 415 | fe_set_err = fe->ops.set_frontend(fe); |
356 | fepriv->parameters_out = fepriv->parameters_in; | 416 | *c = tmp; |
357 | if (fe_set_err < 0) { | 417 | if (fe_set_err < 0) { |
358 | fepriv->state = FESTATE_ERROR; | 418 | fepriv->state = FESTATE_ERROR; |
359 | return fe_set_err; | 419 | return fe_set_err; |
360 | } | 420 | } |
361 | 421 | ||
362 | fepriv->parameters_in.frequency = original_frequency; | 422 | c->frequency = original_frequency; |
363 | fepriv->parameters_in.inversion = original_inversion; | 423 | c->inversion = original_inversion; |
364 | 424 | ||
365 | fepriv->auto_sub_step++; | 425 | fepriv->auto_sub_step++; |
366 | return 0; | 426 | return 0; |
@@ -371,6 +431,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe) | |||
371 | fe_status_t s = 0; | 431 | fe_status_t s = 0; |
372 | int retval = 0; | 432 | int retval = 0; |
373 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | 433 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
434 | struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp; | ||
374 | 435 | ||
375 | /* if we've got no parameters, just keep idling */ | 436 | /* if we've got no parameters, just keep idling */ |
376 | if (fepriv->state & FESTATE_IDLE) { | 437 | if (fepriv->state & FESTATE_IDLE) { |
@@ -382,10 +443,10 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe) | |||
382 | /* in SCAN mode, we just set the frontend when asked and leave it alone */ | 443 | /* in SCAN mode, we just set the frontend when asked and leave it alone */ |
383 | if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) { | 444 | if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) { |
384 | if (fepriv->state & FESTATE_RETUNE) { | 445 | if (fepriv->state & FESTATE_RETUNE) { |
446 | tmp = *c; | ||
385 | if (fe->ops.set_frontend) | 447 | if (fe->ops.set_frontend) |
386 | retval = fe->ops.set_frontend(fe, | 448 | retval = fe->ops.set_frontend(fe); |
387 | &fepriv->parameters_in); | 449 | *c = tmp; |
388 | fepriv->parameters_out = fepriv->parameters_in; | ||
389 | if (retval < 0) | 450 | if (retval < 0) |
390 | fepriv->state = FESTATE_ERROR; | 451 | fepriv->state = FESTATE_ERROR; |
391 | else | 452 | else |
@@ -415,8 +476,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe) | |||
415 | 476 | ||
416 | /* if we're tuned, then we have determined the correct inversion */ | 477 | /* if we're tuned, then we have determined the correct inversion */ |
417 | if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && | 478 | if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && |
418 | (fepriv->parameters_in.inversion == INVERSION_AUTO)) { | 479 | (c->inversion == INVERSION_AUTO)) { |
419 | fepriv->parameters_in.inversion = fepriv->inversion; | 480 | c->inversion = fepriv->inversion; |
420 | } | 481 | } |
421 | return; | 482 | return; |
422 | } | 483 | } |
@@ -507,7 +568,7 @@ static int dvb_frontend_is_exiting(struct dvb_frontend *fe) | |||
507 | return 1; | 568 | return 1; |
508 | 569 | ||
509 | if (fepriv->dvbdev->writers == 1) | 570 | if (fepriv->dvbdev->writers == 1) |
510 | if (time_after(jiffies, fepriv->release_jiffies + | 571 | if (time_after_eq(jiffies, fepriv->release_jiffies + |
511 | dvb_shutdown_timeout * HZ)) | 572 | dvb_shutdown_timeout * HZ)) |
512 | return 1; | 573 | return 1; |
513 | 574 | ||
@@ -540,7 +601,7 @@ static int dvb_frontend_thread(void *data) | |||
540 | fe_status_t s; | 601 | fe_status_t s; |
541 | enum dvbfe_algo algo; | 602 | enum dvbfe_algo algo; |
542 | 603 | ||
543 | struct dvb_frontend_parameters *params; | 604 | bool re_tune = false; |
544 | 605 | ||
545 | dprintk("%s\n", __func__); | 606 | dprintk("%s\n", __func__); |
546 | 607 | ||
@@ -589,18 +650,15 @@ restart: | |||
589 | switch (algo) { | 650 | switch (algo) { |
590 | case DVBFE_ALGO_HW: | 651 | case DVBFE_ALGO_HW: |
591 | dprintk("%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__); | 652 | dprintk("%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__); |
592 | params = NULL; /* have we been asked to RETUNE ? */ | ||
593 | 653 | ||
594 | if (fepriv->state & FESTATE_RETUNE) { | 654 | if (fepriv->state & FESTATE_RETUNE) { |
595 | dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__); | 655 | dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__); |
596 | params = &fepriv->parameters_in; | 656 | re_tune = true; |
597 | fepriv->state = FESTATE_TUNED; | 657 | fepriv->state = FESTATE_TUNED; |
598 | } | 658 | } |
599 | 659 | ||
600 | if (fe->ops.tune) | 660 | if (fe->ops.tune) |
601 | fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s); | 661 | fe->ops.tune(fe, re_tune, fepriv->tune_mode_flags, &fepriv->delay, &s); |
602 | if (params) | ||
603 | fepriv->parameters_out = *params; | ||
604 | 662 | ||
605 | if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) { | 663 | if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) { |
606 | dprintk("%s: state changed, adding current state\n", __func__); | 664 | dprintk("%s: state changed, adding current state\n", __func__); |
@@ -624,7 +682,7 @@ restart: | |||
624 | */ | 682 | */ |
625 | if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) { | 683 | if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) { |
626 | if (fe->ops.search) { | 684 | if (fe->ops.search) { |
627 | fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters_in); | 685 | fepriv->algo_status = fe->ops.search(fe); |
628 | /* We did do a search as was requested, the flags are | 686 | /* We did do a search as was requested, the flags are |
629 | * now unset as well and has the flags wrt to search. | 687 | * now unset as well and has the flags wrt to search. |
630 | */ | 688 | */ |
@@ -633,14 +691,10 @@ restart: | |||
633 | } | 691 | } |
634 | } | 692 | } |
635 | /* Track the carrier if the search was successful */ | 693 | /* Track the carrier if the search was successful */ |
636 | if (fepriv->algo_status == DVBFE_ALGO_SEARCH_SUCCESS) { | 694 | if (fepriv->algo_status != DVBFE_ALGO_SEARCH_SUCCESS) { |
637 | if (fe->ops.track) | ||
638 | fe->ops.track(fe, &fepriv->parameters_in); | ||
639 | } else { | ||
640 | fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; | 695 | fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; |
641 | fepriv->delay = HZ / 2; | 696 | fepriv->delay = HZ / 2; |
642 | } | 697 | } |
643 | fepriv->parameters_out = fepriv->parameters_in; | ||
644 | fe->ops.read_status(fe, &s); | 698 | fe->ops.read_status(fe, &s); |
645 | if (s != fepriv->status) { | 699 | if (s != fepriv->status) { |
646 | dvb_frontend_add_event(fe, s); /* update event list */ | 700 | dvb_frontend_add_event(fe, s); /* update event list */ |
@@ -807,52 +861,40 @@ static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe, | |||
807 | fe->dvb->num,fe->id); | 861 | fe->dvb->num,fe->id); |
808 | } | 862 | } |
809 | 863 | ||
810 | static int dvb_frontend_check_parameters(struct dvb_frontend *fe, | 864 | static int dvb_frontend_check_parameters(struct dvb_frontend *fe) |
811 | struct dvb_frontend_parameters *parms) | ||
812 | { | 865 | { |
866 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
813 | u32 freq_min; | 867 | u32 freq_min; |
814 | u32 freq_max; | 868 | u32 freq_max; |
815 | 869 | ||
816 | /* range check: frequency */ | 870 | /* range check: frequency */ |
817 | dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max); | 871 | dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max); |
818 | if ((freq_min && parms->frequency < freq_min) || | 872 | if ((freq_min && c->frequency < freq_min) || |
819 | (freq_max && parms->frequency > freq_max)) { | 873 | (freq_max && c->frequency > freq_max)) { |
820 | printk(KERN_WARNING "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n", | 874 | printk(KERN_WARNING "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n", |
821 | fe->dvb->num, fe->id, parms->frequency, freq_min, freq_max); | 875 | fe->dvb->num, fe->id, c->frequency, freq_min, freq_max); |
822 | return -EINVAL; | 876 | return -EINVAL; |
823 | } | 877 | } |
824 | 878 | ||
825 | /* range check: symbol rate */ | 879 | /* range check: symbol rate */ |
826 | if (fe->ops.info.type == FE_QPSK) { | 880 | switch (c->delivery_system) { |
827 | if ((fe->ops.info.symbol_rate_min && | 881 | case SYS_DVBS: |
828 | parms->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min) || | 882 | case SYS_DVBS2: |
829 | (fe->ops.info.symbol_rate_max && | 883 | case SYS_TURBO: |
830 | parms->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max)) { | 884 | case SYS_DVBC_ANNEX_A: |
831 | printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n", | 885 | case SYS_DVBC_ANNEX_C: |
832 | fe->dvb->num, fe->id, parms->u.qpsk.symbol_rate, | ||
833 | fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max); | ||
834 | return -EINVAL; | ||
835 | } | ||
836 | |||
837 | } else if (fe->ops.info.type == FE_QAM) { | ||
838 | if ((fe->ops.info.symbol_rate_min && | 886 | if ((fe->ops.info.symbol_rate_min && |
839 | parms->u.qam.symbol_rate < fe->ops.info.symbol_rate_min) || | 887 | c->symbol_rate < fe->ops.info.symbol_rate_min) || |
840 | (fe->ops.info.symbol_rate_max && | 888 | (fe->ops.info.symbol_rate_max && |
841 | parms->u.qam.symbol_rate > fe->ops.info.symbol_rate_max)) { | 889 | c->symbol_rate > fe->ops.info.symbol_rate_max)) { |
842 | printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n", | 890 | printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n", |
843 | fe->dvb->num, fe->id, parms->u.qam.symbol_rate, | 891 | fe->dvb->num, fe->id, c->symbol_rate, |
844 | fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max); | 892 | fe->ops.info.symbol_rate_min, |
893 | fe->ops.info.symbol_rate_max); | ||
845 | return -EINVAL; | 894 | return -EINVAL; |
846 | } | 895 | } |
847 | } | 896 | default: |
848 | 897 | break; | |
849 | /* check for supported modulation */ | ||
850 | if (fe->ops.info.type == FE_QAM && | ||
851 | (parms->u.qam.modulation > QAM_AUTO || | ||
852 | !((1 << (parms->u.qam.modulation + 10)) & fe->ops.info.caps))) { | ||
853 | printk(KERN_WARNING "DVB: adapter %i frontend %i modulation %u not supported\n", | ||
854 | fe->dvb->num, fe->id, parms->u.qam.modulation); | ||
855 | return -EINVAL; | ||
856 | } | 898 | } |
857 | 899 | ||
858 | return 0; | 900 | return 0; |
@@ -866,28 +908,52 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe) | |||
866 | memset(c, 0, sizeof(struct dtv_frontend_properties)); | 908 | memset(c, 0, sizeof(struct dtv_frontend_properties)); |
867 | 909 | ||
868 | c->state = DTV_CLEAR; | 910 | c->state = DTV_CLEAR; |
869 | c->delivery_system = SYS_UNDEFINED; | 911 | |
870 | c->inversion = INVERSION_AUTO; | 912 | dprintk("%s() Clearing cache for delivery system %d\n", __func__, |
871 | c->fec_inner = FEC_AUTO; | 913 | c->delivery_system); |
914 | |||
872 | c->transmission_mode = TRANSMISSION_MODE_AUTO; | 915 | c->transmission_mode = TRANSMISSION_MODE_AUTO; |
873 | c->bandwidth_hz = BANDWIDTH_AUTO; | 916 | c->bandwidth_hz = 0; /* AUTO */ |
874 | c->guard_interval = GUARD_INTERVAL_AUTO; | 917 | c->guard_interval = GUARD_INTERVAL_AUTO; |
875 | c->hierarchy = HIERARCHY_AUTO; | 918 | c->hierarchy = HIERARCHY_AUTO; |
876 | c->symbol_rate = QAM_AUTO; | 919 | c->symbol_rate = 0; |
877 | c->code_rate_HP = FEC_AUTO; | 920 | c->code_rate_HP = FEC_AUTO; |
878 | c->code_rate_LP = FEC_AUTO; | 921 | c->code_rate_LP = FEC_AUTO; |
879 | 922 | c->fec_inner = FEC_AUTO; | |
880 | c->isdbt_partial_reception = -1; | 923 | c->rolloff = ROLLOFF_AUTO; |
881 | c->isdbt_sb_mode = -1; | 924 | c->voltage = SEC_VOLTAGE_OFF; |
882 | c->isdbt_sb_subchannel = -1; | 925 | c->sectone = SEC_TONE_OFF; |
883 | c->isdbt_sb_segment_idx = -1; | 926 | c->pilot = PILOT_AUTO; |
884 | c->isdbt_sb_segment_count = -1; | 927 | |
885 | c->isdbt_layer_enabled = 0x7; | 928 | c->isdbt_partial_reception = 0; |
929 | c->isdbt_sb_mode = 0; | ||
930 | c->isdbt_sb_subchannel = 0; | ||
931 | c->isdbt_sb_segment_idx = 0; | ||
932 | c->isdbt_sb_segment_count = 0; | ||
933 | c->isdbt_layer_enabled = 0; | ||
886 | for (i = 0; i < 3; i++) { | 934 | for (i = 0; i < 3; i++) { |
887 | c->layer[i].fec = FEC_AUTO; | 935 | c->layer[i].fec = FEC_AUTO; |
888 | c->layer[i].modulation = QAM_AUTO; | 936 | c->layer[i].modulation = QAM_AUTO; |
889 | c->layer[i].interleaving = -1; | 937 | c->layer[i].interleaving = 0; |
890 | c->layer[i].segment_count = -1; | 938 | c->layer[i].segment_count = 0; |
939 | } | ||
940 | |||
941 | c->isdbs_ts_id = 0; | ||
942 | c->dvbt2_plp_id = 0; | ||
943 | |||
944 | switch (c->delivery_system) { | ||
945 | case SYS_DVBS: | ||
946 | case SYS_DVBS2: | ||
947 | case SYS_TURBO: | ||
948 | c->modulation = QPSK; /* implied for DVB-S in legacy API */ | ||
949 | c->rolloff = ROLLOFF_35;/* implied for DVB-S */ | ||
950 | break; | ||
951 | case SYS_ATSC: | ||
952 | c->modulation = VSB_8; | ||
953 | break; | ||
954 | default: | ||
955 | c->modulation = QAM_AUTO; | ||
956 | break; | ||
891 | } | 957 | } |
892 | 958 | ||
893 | return 0; | 959 | return 0; |
@@ -973,6 +1039,8 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = { | |||
973 | _DTV_CMD(DTV_GUARD_INTERVAL, 0, 0), | 1039 | _DTV_CMD(DTV_GUARD_INTERVAL, 0, 0), |
974 | _DTV_CMD(DTV_TRANSMISSION_MODE, 0, 0), | 1040 | _DTV_CMD(DTV_TRANSMISSION_MODE, 0, 0), |
975 | _DTV_CMD(DTV_HIERARCHY, 0, 0), | 1041 | _DTV_CMD(DTV_HIERARCHY, 0, 0), |
1042 | |||
1043 | _DTV_CMD(DTV_ENUM_DELSYS, 0, 0), | ||
976 | }; | 1044 | }; |
977 | 1045 | ||
978 | static void dtv_property_dump(struct dtv_property *tvp) | 1046 | static void dtv_property_dump(struct dtv_property *tvp) |
@@ -1006,70 +1074,54 @@ static void dtv_property_dump(struct dtv_property *tvp) | |||
1006 | dprintk("%s() tvp.u.data = 0x%08x\n", __func__, tvp->u.data); | 1074 | dprintk("%s() tvp.u.data = 0x%08x\n", __func__, tvp->u.data); |
1007 | } | 1075 | } |
1008 | 1076 | ||
1009 | static int is_legacy_delivery_system(fe_delivery_system_t s) | ||
1010 | { | ||
1011 | if((s == SYS_UNDEFINED) || (s == SYS_DVBC_ANNEX_AC) || | ||
1012 | (s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS) || | ||
1013 | (s == SYS_ATSC)) | ||
1014 | return 1; | ||
1015 | |||
1016 | return 0; | ||
1017 | } | ||
1018 | |||
1019 | /* Initialize the cache with some default values derived from the | ||
1020 | * legacy frontend_info structure. | ||
1021 | */ | ||
1022 | static void dtv_property_cache_init(struct dvb_frontend *fe, | ||
1023 | struct dtv_frontend_properties *c) | ||
1024 | { | ||
1025 | switch (fe->ops.info.type) { | ||
1026 | case FE_QPSK: | ||
1027 | c->modulation = QPSK; /* implied for DVB-S in legacy API */ | ||
1028 | c->rolloff = ROLLOFF_35;/* implied for DVB-S */ | ||
1029 | c->delivery_system = SYS_DVBS; | ||
1030 | break; | ||
1031 | case FE_QAM: | ||
1032 | c->delivery_system = SYS_DVBC_ANNEX_AC; | ||
1033 | break; | ||
1034 | case FE_OFDM: | ||
1035 | c->delivery_system = SYS_DVBT; | ||
1036 | break; | ||
1037 | case FE_ATSC: | ||
1038 | break; | ||
1039 | } | ||
1040 | } | ||
1041 | |||
1042 | /* Synchronise the legacy tuning parameters into the cache, so that demodulator | 1077 | /* Synchronise the legacy tuning parameters into the cache, so that demodulator |
1043 | * drivers can use a single set_frontend tuning function, regardless of whether | 1078 | * drivers can use a single set_frontend tuning function, regardless of whether |
1044 | * it's being used for the legacy or new API, reducing code and complexity. | 1079 | * it's being used for the legacy or new API, reducing code and complexity. |
1045 | */ | 1080 | */ |
1046 | static void dtv_property_cache_sync(struct dvb_frontend *fe, | 1081 | static int dtv_property_cache_sync(struct dvb_frontend *fe, |
1047 | struct dtv_frontend_properties *c, | 1082 | struct dtv_frontend_properties *c, |
1048 | const struct dvb_frontend_parameters *p) | 1083 | const struct dvb_frontend_parameters *p) |
1049 | { | 1084 | { |
1050 | c->frequency = p->frequency; | 1085 | c->frequency = p->frequency; |
1051 | c->inversion = p->inversion; | 1086 | c->inversion = p->inversion; |
1052 | 1087 | ||
1053 | switch (fe->ops.info.type) { | 1088 | switch (dvbv3_type(c->delivery_system)) { |
1054 | case FE_QPSK: | 1089 | case DVBV3_QPSK: |
1090 | dprintk("%s() Preparing QPSK req\n", __func__); | ||
1055 | c->symbol_rate = p->u.qpsk.symbol_rate; | 1091 | c->symbol_rate = p->u.qpsk.symbol_rate; |
1056 | c->fec_inner = p->u.qpsk.fec_inner; | 1092 | c->fec_inner = p->u.qpsk.fec_inner; |
1057 | break; | 1093 | break; |
1058 | case FE_QAM: | 1094 | case DVBV3_QAM: |
1095 | dprintk("%s() Preparing QAM req\n", __func__); | ||
1059 | c->symbol_rate = p->u.qam.symbol_rate; | 1096 | c->symbol_rate = p->u.qam.symbol_rate; |
1060 | c->fec_inner = p->u.qam.fec_inner; | 1097 | c->fec_inner = p->u.qam.fec_inner; |
1061 | c->modulation = p->u.qam.modulation; | 1098 | c->modulation = p->u.qam.modulation; |
1062 | break; | 1099 | break; |
1063 | case FE_OFDM: | 1100 | case DVBV3_OFDM: |
1064 | if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ) | 1101 | dprintk("%s() Preparing OFDM req\n", __func__); |
1065 | c->bandwidth_hz = 6000000; | 1102 | switch (p->u.ofdm.bandwidth) { |
1066 | else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ) | 1103 | case BANDWIDTH_10_MHZ: |
1067 | c->bandwidth_hz = 7000000; | 1104 | c->bandwidth_hz = 10000000; |
1068 | else if (p->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) | 1105 | break; |
1106 | case BANDWIDTH_8_MHZ: | ||
1069 | c->bandwidth_hz = 8000000; | 1107 | c->bandwidth_hz = 8000000; |
1070 | else | 1108 | break; |
1071 | /* Including BANDWIDTH_AUTO */ | 1109 | case BANDWIDTH_7_MHZ: |
1110 | c->bandwidth_hz = 7000000; | ||
1111 | break; | ||
1112 | case BANDWIDTH_6_MHZ: | ||
1113 | c->bandwidth_hz = 6000000; | ||
1114 | break; | ||
1115 | case BANDWIDTH_5_MHZ: | ||
1116 | c->bandwidth_hz = 5000000; | ||
1117 | break; | ||
1118 | case BANDWIDTH_1_712_MHZ: | ||
1119 | c->bandwidth_hz = 1712000; | ||
1120 | break; | ||
1121 | case BANDWIDTH_AUTO: | ||
1072 | c->bandwidth_hz = 0; | 1122 | c->bandwidth_hz = 0; |
1123 | } | ||
1124 | |||
1073 | c->code_rate_HP = p->u.ofdm.code_rate_HP; | 1125 | c->code_rate_HP = p->u.ofdm.code_rate_HP; |
1074 | c->code_rate_LP = p->u.ofdm.code_rate_LP; | 1126 | c->code_rate_LP = p->u.ofdm.code_rate_LP; |
1075 | c->modulation = p->u.ofdm.constellation; | 1127 | c->modulation = p->u.ofdm.constellation; |
@@ -1077,50 +1129,78 @@ static void dtv_property_cache_sync(struct dvb_frontend *fe, | |||
1077 | c->guard_interval = p->u.ofdm.guard_interval; | 1129 | c->guard_interval = p->u.ofdm.guard_interval; |
1078 | c->hierarchy = p->u.ofdm.hierarchy_information; | 1130 | c->hierarchy = p->u.ofdm.hierarchy_information; |
1079 | break; | 1131 | break; |
1080 | case FE_ATSC: | 1132 | case DVBV3_ATSC: |
1133 | dprintk("%s() Preparing ATSC req\n", __func__); | ||
1081 | c->modulation = p->u.vsb.modulation; | 1134 | c->modulation = p->u.vsb.modulation; |
1082 | if ((c->modulation == VSB_8) || (c->modulation == VSB_16)) | 1135 | if ((c->modulation == VSB_8) || (c->modulation == VSB_16)) |
1083 | c->delivery_system = SYS_ATSC; | 1136 | c->delivery_system = SYS_ATSC; |
1084 | else | 1137 | else |
1085 | c->delivery_system = SYS_DVBC_ANNEX_B; | 1138 | c->delivery_system = SYS_DVBC_ANNEX_B; |
1086 | break; | 1139 | break; |
1140 | case DVBV3_UNKNOWN: | ||
1141 | printk(KERN_ERR | ||
1142 | "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n", | ||
1143 | __func__, c->delivery_system); | ||
1144 | return -EINVAL; | ||
1087 | } | 1145 | } |
1146 | |||
1147 | return 0; | ||
1088 | } | 1148 | } |
1089 | 1149 | ||
1090 | /* Ensure the cached values are set correctly in the frontend | 1150 | /* Ensure the cached values are set correctly in the frontend |
1091 | * legacy tuning structures, for the advanced tuning API. | 1151 | * legacy tuning structures, for the advanced tuning API. |
1092 | */ | 1152 | */ |
1093 | static void dtv_property_legacy_params_sync(struct dvb_frontend *fe) | 1153 | static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, |
1154 | struct dvb_frontend_parameters *p) | ||
1094 | { | 1155 | { |
1095 | const struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 1156 | const struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
1096 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
1097 | struct dvb_frontend_parameters *p = &fepriv->parameters_in; | ||
1098 | 1157 | ||
1099 | p->frequency = c->frequency; | 1158 | p->frequency = c->frequency; |
1100 | p->inversion = c->inversion; | 1159 | p->inversion = c->inversion; |
1101 | 1160 | ||
1102 | switch (fe->ops.info.type) { | 1161 | switch (dvbv3_type(c->delivery_system)) { |
1103 | case FE_QPSK: | 1162 | case DVBV3_UNKNOWN: |
1163 | printk(KERN_ERR | ||
1164 | "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n", | ||
1165 | __func__, c->delivery_system); | ||
1166 | return -EINVAL; | ||
1167 | case DVBV3_QPSK: | ||
1104 | dprintk("%s() Preparing QPSK req\n", __func__); | 1168 | dprintk("%s() Preparing QPSK req\n", __func__); |
1105 | p->u.qpsk.symbol_rate = c->symbol_rate; | 1169 | p->u.qpsk.symbol_rate = c->symbol_rate; |
1106 | p->u.qpsk.fec_inner = c->fec_inner; | 1170 | p->u.qpsk.fec_inner = c->fec_inner; |
1107 | break; | 1171 | break; |
1108 | case FE_QAM: | 1172 | case DVBV3_QAM: |
1109 | dprintk("%s() Preparing QAM req\n", __func__); | 1173 | dprintk("%s() Preparing QAM req\n", __func__); |
1110 | p->u.qam.symbol_rate = c->symbol_rate; | 1174 | p->u.qam.symbol_rate = c->symbol_rate; |
1111 | p->u.qam.fec_inner = c->fec_inner; | 1175 | p->u.qam.fec_inner = c->fec_inner; |
1112 | p->u.qam.modulation = c->modulation; | 1176 | p->u.qam.modulation = c->modulation; |
1113 | break; | 1177 | break; |
1114 | case FE_OFDM: | 1178 | case DVBV3_OFDM: |
1115 | dprintk("%s() Preparing OFDM req\n", __func__); | 1179 | dprintk("%s() Preparing OFDM req\n", __func__); |
1116 | if (c->bandwidth_hz == 6000000) | 1180 | |
1117 | p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; | 1181 | switch (c->bandwidth_hz) { |
1118 | else if (c->bandwidth_hz == 7000000) | 1182 | case 10000000: |
1119 | p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; | 1183 | p->u.ofdm.bandwidth = BANDWIDTH_10_MHZ; |
1120 | else if (c->bandwidth_hz == 8000000) | 1184 | break; |
1185 | case 8000000: | ||
1121 | p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; | 1186 | p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; |
1122 | else | 1187 | break; |
1188 | case 7000000: | ||
1189 | p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; | ||
1190 | break; | ||
1191 | case 6000000: | ||
1192 | p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; | ||
1193 | break; | ||
1194 | case 5000000: | ||
1195 | p->u.ofdm.bandwidth = BANDWIDTH_5_MHZ; | ||
1196 | break; | ||
1197 | case 1712000: | ||
1198 | p->u.ofdm.bandwidth = BANDWIDTH_1_712_MHZ; | ||
1199 | break; | ||
1200 | case 0: | ||
1201 | default: | ||
1123 | p->u.ofdm.bandwidth = BANDWIDTH_AUTO; | 1202 | p->u.ofdm.bandwidth = BANDWIDTH_AUTO; |
1203 | } | ||
1124 | p->u.ofdm.code_rate_HP = c->code_rate_HP; | 1204 | p->u.ofdm.code_rate_HP = c->code_rate_HP; |
1125 | p->u.ofdm.code_rate_LP = c->code_rate_LP; | 1205 | p->u.ofdm.code_rate_LP = c->code_rate_LP; |
1126 | p->u.ofdm.constellation = c->modulation; | 1206 | p->u.ofdm.constellation = c->modulation; |
@@ -1128,78 +1208,40 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe) | |||
1128 | p->u.ofdm.guard_interval = c->guard_interval; | 1208 | p->u.ofdm.guard_interval = c->guard_interval; |
1129 | p->u.ofdm.hierarchy_information = c->hierarchy; | 1209 | p->u.ofdm.hierarchy_information = c->hierarchy; |
1130 | break; | 1210 | break; |
1131 | case FE_ATSC: | 1211 | case DVBV3_ATSC: |
1132 | dprintk("%s() Preparing VSB req\n", __func__); | 1212 | dprintk("%s() Preparing VSB req\n", __func__); |
1133 | p->u.vsb.modulation = c->modulation; | 1213 | p->u.vsb.modulation = c->modulation; |
1134 | break; | 1214 | break; |
1135 | } | 1215 | } |
1216 | return 0; | ||
1136 | } | 1217 | } |
1137 | 1218 | ||
1138 | /* Ensure the cached values are set correctly in the frontend | 1219 | /** |
1139 | * legacy tuning structures, for the legacy tuning API. | 1220 | * dtv_get_frontend - calls a callback for retrieving DTV parameters |
1221 | * @fe: struct dvb_frontend pointer | ||
1222 | * @c: struct dtv_frontend_properties pointer (DVBv5 cache) | ||
1223 | * @p_out struct dvb_frontend_parameters pointer (DVBv3 FE struct) | ||
1224 | * | ||
1225 | * This routine calls either the DVBv3 or DVBv5 get_frontend call. | ||
1226 | * If c is not null, it will update the DVBv5 cache struct pointed by it. | ||
1227 | * If p_out is not null, it will update the DVBv3 params pointed by it. | ||
1140 | */ | 1228 | */ |
1141 | static void dtv_property_adv_params_sync(struct dvb_frontend *fe) | 1229 | static int dtv_get_frontend(struct dvb_frontend *fe, |
1230 | struct dvb_frontend_parameters *p_out) | ||
1142 | { | 1231 | { |
1143 | const struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 1232 | int r; |
1144 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
1145 | struct dvb_frontend_parameters *p = &fepriv->parameters_in; | ||
1146 | |||
1147 | p->frequency = c->frequency; | ||
1148 | p->inversion = c->inversion; | ||
1149 | |||
1150 | if (c->delivery_system == SYS_DSS || | ||
1151 | c->delivery_system == SYS_DVBS || | ||
1152 | c->delivery_system == SYS_DVBS2 || | ||
1153 | c->delivery_system == SYS_ISDBS || | ||
1154 | c->delivery_system == SYS_TURBO) { | ||
1155 | p->u.qpsk.symbol_rate = c->symbol_rate; | ||
1156 | p->u.qpsk.fec_inner = c->fec_inner; | ||
1157 | } | ||
1158 | 1233 | ||
1159 | /* Fake out a generic DVB-T request so we pass validation in the ioctl */ | 1234 | if (fe->ops.get_frontend) { |
1160 | if ((c->delivery_system == SYS_ISDBT) || | 1235 | r = fe->ops.get_frontend(fe); |
1161 | (c->delivery_system == SYS_DVBT2)) { | 1236 | if (unlikely(r < 0)) |
1162 | p->u.ofdm.constellation = QAM_AUTO; | 1237 | return r; |
1163 | p->u.ofdm.code_rate_HP = FEC_AUTO; | 1238 | if (p_out) |
1164 | p->u.ofdm.code_rate_LP = FEC_AUTO; | 1239 | dtv_property_legacy_params_sync(fe, p_out); |
1165 | p->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; | 1240 | return 0; |
1166 | p->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; | ||
1167 | p->u.ofdm.hierarchy_information = HIERARCHY_AUTO; | ||
1168 | if (c->bandwidth_hz == 8000000) | ||
1169 | p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; | ||
1170 | else if (c->bandwidth_hz == 7000000) | ||
1171 | p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; | ||
1172 | else if (c->bandwidth_hz == 6000000) | ||
1173 | p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; | ||
1174 | else | ||
1175 | p->u.ofdm.bandwidth = BANDWIDTH_AUTO; | ||
1176 | } | 1241 | } |
1177 | } | ||
1178 | |||
1179 | static void dtv_property_cache_submit(struct dvb_frontend *fe) | ||
1180 | { | ||
1181 | const struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1182 | 1242 | ||
1183 | /* For legacy delivery systems we don't need the delivery_system to | 1243 | /* As everything is in cache, get_frontend fops are always supported */ |
1184 | * be specified, but we populate the older structures from the cache | 1244 | return 0; |
1185 | * so we can call set_frontend on older drivers. | ||
1186 | */ | ||
1187 | if(is_legacy_delivery_system(c->delivery_system)) { | ||
1188 | |||
1189 | dprintk("%s() legacy, modulation = %d\n", __func__, c->modulation); | ||
1190 | dtv_property_legacy_params_sync(fe); | ||
1191 | |||
1192 | } else { | ||
1193 | dprintk("%s() adv, modulation = %d\n", __func__, c->modulation); | ||
1194 | |||
1195 | /* For advanced delivery systems / modulation types ... | ||
1196 | * we seed the lecacy dvb_frontend_parameters structure | ||
1197 | * so that the sanity checking code later in the IOCTL processing | ||
1198 | * can validate our basic frequency ranges, symbolrates, modulation | ||
1199 | * etc. | ||
1200 | */ | ||
1201 | dtv_property_adv_params_sync(fe); | ||
1202 | } | ||
1203 | } | 1245 | } |
1204 | 1246 | ||
1205 | static int dvb_frontend_ioctl_legacy(struct file *file, | 1247 | static int dvb_frontend_ioctl_legacy(struct file *file, |
@@ -1208,25 +1250,21 @@ static int dvb_frontend_ioctl_properties(struct file *file, | |||
1208 | unsigned int cmd, void *parg); | 1250 | unsigned int cmd, void *parg); |
1209 | 1251 | ||
1210 | static int dtv_property_process_get(struct dvb_frontend *fe, | 1252 | static int dtv_property_process_get(struct dvb_frontend *fe, |
1253 | const struct dtv_frontend_properties *c, | ||
1211 | struct dtv_property *tvp, | 1254 | struct dtv_property *tvp, |
1212 | struct file *file) | 1255 | struct file *file) |
1213 | { | 1256 | { |
1214 | const struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 1257 | int r, ncaps; |
1215 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
1216 | struct dtv_frontend_properties cdetected; | ||
1217 | int r; | ||
1218 | |||
1219 | /* | ||
1220 | * If the driver implements a get_frontend function, then convert | ||
1221 | * detected parameters to S2API properties. | ||
1222 | */ | ||
1223 | if (fe->ops.get_frontend) { | ||
1224 | cdetected = *c; | ||
1225 | dtv_property_cache_sync(fe, &cdetected, &fepriv->parameters_out); | ||
1226 | c = &cdetected; | ||
1227 | } | ||
1228 | 1258 | ||
1229 | switch(tvp->cmd) { | 1259 | switch(tvp->cmd) { |
1260 | case DTV_ENUM_DELSYS: | ||
1261 | ncaps = 0; | ||
1262 | while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { | ||
1263 | tvp->u.buffer.data[ncaps] = fe->ops.delsys[ncaps]; | ||
1264 | ncaps++; | ||
1265 | } | ||
1266 | tvp->u.buffer.len = ncaps; | ||
1267 | break; | ||
1230 | case DTV_FREQUENCY: | 1268 | case DTV_FREQUENCY: |
1231 | tvp->u.data = c->frequency; | 1269 | tvp->u.data = c->frequency; |
1232 | break; | 1270 | break; |
@@ -1356,14 +1394,159 @@ static int dtv_property_process_get(struct dvb_frontend *fe, | |||
1356 | return 0; | 1394 | return 0; |
1357 | } | 1395 | } |
1358 | 1396 | ||
1397 | static int dtv_set_frontend(struct dvb_frontend *fe); | ||
1398 | |||
1399 | static bool is_dvbv3_delsys(u32 delsys) | ||
1400 | { | ||
1401 | bool status; | ||
1402 | |||
1403 | status = (delsys == SYS_DVBT) || (delsys == SYS_DVBC_ANNEX_A) || | ||
1404 | (delsys == SYS_DVBS) || (delsys == SYS_ATSC); | ||
1405 | |||
1406 | return status; | ||
1407 | } | ||
1408 | |||
1409 | static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) | ||
1410 | { | ||
1411 | int ncaps, i; | ||
1412 | u32 delsys = SYS_UNDEFINED; | ||
1413 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1414 | enum dvbv3_emulation_type type; | ||
1415 | |||
1416 | if (desired_system == SYS_UNDEFINED) { | ||
1417 | /* | ||
1418 | * A DVBv3 call doesn't know what's the desired system. | ||
1419 | * Also, DVBv3 applications don't know that ops.info->type | ||
1420 | * could be changed, and they simply dies when it doesn't | ||
1421 | * match. | ||
1422 | * So, don't change the current delivery system, as it | ||
1423 | * may be trying to do the wrong thing, like setting an | ||
1424 | * ISDB-T frontend as DVB-T. Instead, find the closest | ||
1425 | * DVBv3 system that matches the delivery system. | ||
1426 | */ | ||
1427 | if (is_dvbv3_delsys(c->delivery_system)) { | ||
1428 | dprintk("%s() Using delivery system to %d\n", | ||
1429 | __func__, c->delivery_system); | ||
1430 | return 0; | ||
1431 | } | ||
1432 | type = dvbv3_type(c->delivery_system); | ||
1433 | switch (type) { | ||
1434 | case DVBV3_QPSK: | ||
1435 | desired_system = SYS_DVBS; | ||
1436 | break; | ||
1437 | case DVBV3_QAM: | ||
1438 | desired_system = SYS_DVBC_ANNEX_A; | ||
1439 | break; | ||
1440 | case DVBV3_ATSC: | ||
1441 | desired_system = SYS_ATSC; | ||
1442 | break; | ||
1443 | case DVBV3_OFDM: | ||
1444 | desired_system = SYS_DVBT; | ||
1445 | break; | ||
1446 | default: | ||
1447 | dprintk("%s(): This frontend doesn't support DVBv3 calls\n", | ||
1448 | __func__); | ||
1449 | return -EINVAL; | ||
1450 | } | ||
1451 | } else { | ||
1452 | /* | ||
1453 | * This is a DVBv5 call. So, it likely knows the supported | ||
1454 | * delivery systems. | ||
1455 | */ | ||
1456 | |||
1457 | /* Check if the desired delivery system is supported */ | ||
1458 | ncaps = 0; | ||
1459 | while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { | ||
1460 | if (fe->ops.delsys[ncaps] == desired_system) { | ||
1461 | c->delivery_system = desired_system; | ||
1462 | dprintk("%s() Changing delivery system to %d\n", | ||
1463 | __func__, desired_system); | ||
1464 | return 0; | ||
1465 | } | ||
1466 | ncaps++; | ||
1467 | } | ||
1468 | type = dvbv3_type(desired_system); | ||
1469 | |||
1470 | /* | ||
1471 | * The delivery system is not supported. See if it can be | ||
1472 | * emulated. | ||
1473 | * The emulation only works if the desired system is one of the | ||
1474 | * DVBv3 delivery systems | ||
1475 | */ | ||
1476 | if (!is_dvbv3_delsys(desired_system)) { | ||
1477 | dprintk("%s() can't use a DVBv3 FE_SET_FRONTEND call on this frontend\n", | ||
1478 | __func__); | ||
1479 | return -EINVAL; | ||
1480 | } | ||
1481 | |||
1482 | /* | ||
1483 | * Get the last non-DVBv3 delivery system that has the same type | ||
1484 | * of the desired system | ||
1485 | */ | ||
1486 | ncaps = 0; | ||
1487 | while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { | ||
1488 | if ((dvbv3_type(fe->ops.delsys[ncaps]) == type) && | ||
1489 | !is_dvbv3_delsys(fe->ops.delsys[ncaps])) | ||
1490 | delsys = fe->ops.delsys[ncaps]; | ||
1491 | ncaps++; | ||
1492 | } | ||
1493 | /* There's nothing compatible with the desired delivery system */ | ||
1494 | if (delsys == SYS_UNDEFINED) { | ||
1495 | dprintk("%s() Incompatible DVBv3 FE_SET_FRONTEND call for this frontend\n", | ||
1496 | __func__); | ||
1497 | return -EINVAL; | ||
1498 | } | ||
1499 | c->delivery_system = delsys; | ||
1500 | } | ||
1501 | |||
1502 | /* | ||
1503 | * The DVBv3 or DVBv5 call is requesting a different system. So, | ||
1504 | * emulation is needed. | ||
1505 | * | ||
1506 | * Emulate newer delivery systems like ISDBT, DVBT and DMBTH | ||
1507 | * for older DVBv5 applications. The emulation will try to use | ||
1508 | * the auto mode for most things, and will assume that the desired | ||
1509 | * delivery system is the last one at the ops.delsys[] array | ||
1510 | */ | ||
1511 | dprintk("%s() Using delivery system %d emulated as if it were a %d\n", | ||
1512 | __func__, delsys, desired_system); | ||
1513 | |||
1514 | /* | ||
1515 | * For now, handles ISDB-T calls. More code may be needed here for the | ||
1516 | * other emulated stuff | ||
1517 | */ | ||
1518 | if (type == DVBV3_OFDM) { | ||
1519 | if (c->delivery_system == SYS_ISDBT) { | ||
1520 | dprintk("%s() Using defaults for SYS_ISDBT\n", | ||
1521 | __func__); | ||
1522 | if (!c->bandwidth_hz) | ||
1523 | c->bandwidth_hz = 6000000; | ||
1524 | |||
1525 | c->isdbt_partial_reception = 0; | ||
1526 | c->isdbt_sb_mode = 0; | ||
1527 | c->isdbt_sb_subchannel = 0; | ||
1528 | c->isdbt_sb_segment_idx = 0; | ||
1529 | c->isdbt_sb_segment_count = 0; | ||
1530 | c->isdbt_layer_enabled = 0; | ||
1531 | for (i = 0; i < 3; i++) { | ||
1532 | c->layer[i].fec = FEC_AUTO; | ||
1533 | c->layer[i].modulation = QAM_AUTO; | ||
1534 | c->layer[i].interleaving = 0; | ||
1535 | c->layer[i].segment_count = 0; | ||
1536 | } | ||
1537 | } | ||
1538 | } | ||
1539 | dprintk("change delivery system on cache to %d\n", c->delivery_system); | ||
1540 | |||
1541 | return 0; | ||
1542 | } | ||
1543 | |||
1359 | static int dtv_property_process_set(struct dvb_frontend *fe, | 1544 | static int dtv_property_process_set(struct dvb_frontend *fe, |
1360 | struct dtv_property *tvp, | 1545 | struct dtv_property *tvp, |
1361 | struct file *file) | 1546 | struct file *file) |
1362 | { | 1547 | { |
1363 | int r = 0; | 1548 | int r = 0; |
1364 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 1549 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
1365 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
1366 | dtv_property_dump(tvp); | ||
1367 | 1550 | ||
1368 | /* Allow the frontend to validate incoming properties */ | 1551 | /* Allow the frontend to validate incoming properties */ |
1369 | if (fe->ops.set_property) { | 1552 | if (fe->ops.set_property) { |
@@ -1374,11 +1557,11 @@ static int dtv_property_process_set(struct dvb_frontend *fe, | |||
1374 | 1557 | ||
1375 | switch(tvp->cmd) { | 1558 | switch(tvp->cmd) { |
1376 | case DTV_CLEAR: | 1559 | case DTV_CLEAR: |
1377 | /* Reset a cache of data specific to the frontend here. This does | 1560 | /* |
1561 | * Reset a cache of data specific to the frontend here. This does | ||
1378 | * not effect hardware. | 1562 | * not effect hardware. |
1379 | */ | 1563 | */ |
1380 | dvb_frontend_clear_cache(fe); | 1564 | dvb_frontend_clear_cache(fe); |
1381 | dprintk("%s() Flushing property cache\n", __func__); | ||
1382 | break; | 1565 | break; |
1383 | case DTV_TUNE: | 1566 | case DTV_TUNE: |
1384 | /* interpret the cache of data, build either a traditional frontend | 1567 | /* interpret the cache of data, build either a traditional frontend |
@@ -1387,10 +1570,8 @@ static int dtv_property_process_set(struct dvb_frontend *fe, | |||
1387 | */ | 1570 | */ |
1388 | c->state = tvp->cmd; | 1571 | c->state = tvp->cmd; |
1389 | dprintk("%s() Finalised property cache\n", __func__); | 1572 | dprintk("%s() Finalised property cache\n", __func__); |
1390 | dtv_property_cache_submit(fe); | ||
1391 | 1573 | ||
1392 | r = dvb_frontend_ioctl_legacy(file, FE_SET_FRONTEND, | 1574 | r = dtv_set_frontend(fe); |
1393 | &fepriv->parameters_in); | ||
1394 | break; | 1575 | break; |
1395 | case DTV_FREQUENCY: | 1576 | case DTV_FREQUENCY: |
1396 | c->frequency = tvp->u.data; | 1577 | c->frequency = tvp->u.data; |
@@ -1417,7 +1598,7 @@ static int dtv_property_process_set(struct dvb_frontend *fe, | |||
1417 | c->rolloff = tvp->u.data; | 1598 | c->rolloff = tvp->u.data; |
1418 | break; | 1599 | break; |
1419 | case DTV_DELIVERY_SYSTEM: | 1600 | case DTV_DELIVERY_SYSTEM: |
1420 | c->delivery_system = tvp->u.data; | 1601 | r = set_delivery_system(fe, tvp->u.data); |
1421 | break; | 1602 | break; |
1422 | case DTV_VOLTAGE: | 1603 | case DTV_VOLTAGE: |
1423 | c->voltage = tvp->u.data; | 1604 | c->voltage = tvp->u.data; |
@@ -1594,7 +1775,6 @@ static int dvb_frontend_ioctl_properties(struct file *file, | |||
1594 | 1775 | ||
1595 | } else | 1776 | } else |
1596 | if(cmd == FE_GET_PROPERTY) { | 1777 | if(cmd == FE_GET_PROPERTY) { |
1597 | |||
1598 | tvps = (struct dtv_properties __user *)parg; | 1778 | tvps = (struct dtv_properties __user *)parg; |
1599 | 1779 | ||
1600 | dprintk("%s() properties.num = %d\n", __func__, tvps->num); | 1780 | dprintk("%s() properties.num = %d\n", __func__, tvps->num); |
@@ -1616,8 +1796,13 @@ static int dvb_frontend_ioctl_properties(struct file *file, | |||
1616 | goto out; | 1796 | goto out; |
1617 | } | 1797 | } |
1618 | 1798 | ||
1799 | /* | ||
1800 | * Fills the cache out struct with the cache contents, plus | ||
1801 | * the data retrieved from get_frontend. | ||
1802 | */ | ||
1803 | dtv_get_frontend(fe, NULL); | ||
1619 | for (i = 0; i < tvps->num; i++) { | 1804 | for (i = 0; i < tvps->num; i++) { |
1620 | err = dtv_property_process_get(fe, tvp + i, file); | 1805 | err = dtv_property_process_get(fe, c, tvp + i, file); |
1621 | if (err < 0) | 1806 | if (err < 0) |
1622 | goto out; | 1807 | goto out; |
1623 | (tvp + i)->result = err; | 1808 | (tvp + i)->result = err; |
@@ -1636,12 +1821,121 @@ out: | |||
1636 | return err; | 1821 | return err; |
1637 | } | 1822 | } |
1638 | 1823 | ||
1824 | static int dtv_set_frontend(struct dvb_frontend *fe) | ||
1825 | { | ||
1826 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
1827 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1828 | struct dvb_frontend_tune_settings fetunesettings; | ||
1829 | u32 rolloff = 0; | ||
1830 | |||
1831 | if (dvb_frontend_check_parameters(fe) < 0) | ||
1832 | return -EINVAL; | ||
1833 | |||
1834 | /* | ||
1835 | * Be sure that the bandwidth will be filled for all | ||
1836 | * non-satellite systems, as tuners need to know what | ||
1837 | * low pass/Nyquist half filter should be applied, in | ||
1838 | * order to avoid inter-channel noise. | ||
1839 | * | ||
1840 | * ISDB-T and DVB-T/T2 already sets bandwidth. | ||
1841 | * ATSC and DVB-C don't set, so, the core should fill it. | ||
1842 | * | ||
1843 | * On DVB-C Annex A and C, the bandwidth is a function of | ||
1844 | * the roll-off and symbol rate. Annex B defines different | ||
1845 | * roll-off factors depending on the modulation. Fortunately, | ||
1846 | * Annex B is only used with 6MHz, so there's no need to | ||
1847 | * calculate it. | ||
1848 | * | ||
1849 | * While not officially supported, a side effect of handling it at | ||
1850 | * the cache level is that a program could retrieve the bandwidth | ||
1851 | * via DTV_BANDWIDTH_HZ, which may be useful for test programs. | ||
1852 | */ | ||
1853 | switch (c->delivery_system) { | ||
1854 | case SYS_ATSC: | ||
1855 | case SYS_DVBC_ANNEX_B: | ||
1856 | c->bandwidth_hz = 6000000; | ||
1857 | break; | ||
1858 | case SYS_DVBC_ANNEX_A: | ||
1859 | rolloff = 115; | ||
1860 | break; | ||
1861 | case SYS_DVBC_ANNEX_C: | ||
1862 | rolloff = 113; | ||
1863 | break; | ||
1864 | default: | ||
1865 | break; | ||
1866 | } | ||
1867 | if (rolloff) | ||
1868 | c->bandwidth_hz = (c->symbol_rate * rolloff) / 100; | ||
1869 | |||
1870 | /* force auto frequency inversion if requested */ | ||
1871 | if (dvb_force_auto_inversion) | ||
1872 | c->inversion = INVERSION_AUTO; | ||
1873 | |||
1874 | /* | ||
1875 | * without hierarchical coding code_rate_LP is irrelevant, | ||
1876 | * so we tolerate the otherwise invalid FEC_NONE setting | ||
1877 | */ | ||
1878 | if (c->hierarchy == HIERARCHY_NONE && c->code_rate_LP == FEC_NONE) | ||
1879 | c->code_rate_LP = FEC_AUTO; | ||
1880 | |||
1881 | /* get frontend-specific tuning settings */ | ||
1882 | memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings)); | ||
1883 | if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) { | ||
1884 | fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000; | ||
1885 | fepriv->max_drift = fetunesettings.max_drift; | ||
1886 | fepriv->step_size = fetunesettings.step_size; | ||
1887 | } else { | ||
1888 | /* default values */ | ||
1889 | switch (c->delivery_system) { | ||
1890 | case SYS_DVBC_ANNEX_A: | ||
1891 | case SYS_DVBC_ANNEX_C: | ||
1892 | fepriv->min_delay = HZ / 20; | ||
1893 | fepriv->step_size = c->symbol_rate / 16000; | ||
1894 | fepriv->max_drift = c->symbol_rate / 2000; | ||
1895 | break; | ||
1896 | case SYS_DVBT: | ||
1897 | case SYS_DVBT2: | ||
1898 | case SYS_ISDBT: | ||
1899 | case SYS_DMBTH: | ||
1900 | fepriv->min_delay = HZ / 20; | ||
1901 | fepriv->step_size = fe->ops.info.frequency_stepsize * 2; | ||
1902 | fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; | ||
1903 | break; | ||
1904 | default: | ||
1905 | /* | ||
1906 | * FIXME: This sounds wrong! if freqency_stepsize is | ||
1907 | * defined by the frontend, why not use it??? | ||
1908 | */ | ||
1909 | fepriv->min_delay = HZ / 20; | ||
1910 | fepriv->step_size = 0; /* no zigzag */ | ||
1911 | fepriv->max_drift = 0; | ||
1912 | break; | ||
1913 | } | ||
1914 | } | ||
1915 | if (dvb_override_tune_delay > 0) | ||
1916 | fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000; | ||
1917 | |||
1918 | fepriv->state = FESTATE_RETUNE; | ||
1919 | |||
1920 | /* Request the search algorithm to search */ | ||
1921 | fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; | ||
1922 | |||
1923 | dvb_frontend_clear_events(fe); | ||
1924 | dvb_frontend_add_event(fe, 0); | ||
1925 | dvb_frontend_wakeup(fe); | ||
1926 | fepriv->status = 0; | ||
1927 | |||
1928 | return 0; | ||
1929 | } | ||
1930 | |||
1931 | |||
1639 | static int dvb_frontend_ioctl_legacy(struct file *file, | 1932 | static int dvb_frontend_ioctl_legacy(struct file *file, |
1640 | unsigned int cmd, void *parg) | 1933 | unsigned int cmd, void *parg) |
1641 | { | 1934 | { |
1642 | struct dvb_device *dvbdev = file->private_data; | 1935 | struct dvb_device *dvbdev = file->private_data; |
1643 | struct dvb_frontend *fe = dvbdev->priv; | 1936 | struct dvb_frontend *fe = dvbdev->priv; |
1644 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | 1937 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
1938 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1645 | int cb_err, err = -EOPNOTSUPP; | 1939 | int cb_err, err = -EOPNOTSUPP; |
1646 | 1940 | ||
1647 | if (fe->dvb->fe_ioctl_override) { | 1941 | if (fe->dvb->fe_ioctl_override) { |
@@ -1658,9 +1952,43 @@ static int dvb_frontend_ioctl_legacy(struct file *file, | |||
1658 | switch (cmd) { | 1952 | switch (cmd) { |
1659 | case FE_GET_INFO: { | 1953 | case FE_GET_INFO: { |
1660 | struct dvb_frontend_info* info = parg; | 1954 | struct dvb_frontend_info* info = parg; |
1955 | |||
1661 | memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info)); | 1956 | memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info)); |
1662 | dvb_frontend_get_frequency_limits(fe, &info->frequency_min, &info->frequency_max); | 1957 | dvb_frontend_get_frequency_limits(fe, &info->frequency_min, &info->frequency_max); |
1663 | 1958 | ||
1959 | /* | ||
1960 | * Associate the 4 delivery systems supported by DVBv3 | ||
1961 | * API with their DVBv5 counterpart. For the other standards, | ||
1962 | * use the closest type, assuming that it would hopefully | ||
1963 | * work with a DVBv3 application. | ||
1964 | * It should be noticed that, on multi-frontend devices with | ||
1965 | * different types (terrestrial and cable, for example), | ||
1966 | * a pure DVBv3 application won't be able to use all delivery | ||
1967 | * systems. Yet, changing the DVBv5 cache to the other delivery | ||
1968 | * system should be enough for making it work. | ||
1969 | */ | ||
1970 | switch (dvbv3_type(c->delivery_system)) { | ||
1971 | case DVBV3_QPSK: | ||
1972 | info->type = FE_QPSK; | ||
1973 | break; | ||
1974 | case DVBV3_ATSC: | ||
1975 | info->type = FE_ATSC; | ||
1976 | break; | ||
1977 | case DVBV3_QAM: | ||
1978 | info->type = FE_QAM; | ||
1979 | break; | ||
1980 | case DVBV3_OFDM: | ||
1981 | info->type = FE_OFDM; | ||
1982 | break; | ||
1983 | default: | ||
1984 | printk(KERN_ERR | ||
1985 | "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n", | ||
1986 | __func__, c->delivery_system); | ||
1987 | fe->ops.info.type = FE_OFDM; | ||
1988 | } | ||
1989 | dprintk("current delivery system on cache: %d, V3 type: %d\n", | ||
1990 | c->delivery_system, fe->ops.info.type); | ||
1991 | |||
1664 | /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't | 1992 | /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't |
1665 | * do it, it is done for it. */ | 1993 | * do it, it is done for it. */ |
1666 | info->caps |= FE_CAN_INVERSION_AUTO; | 1994 | info->caps |= FE_CAN_INVERSION_AUTO; |
@@ -1819,108 +2147,22 @@ static int dvb_frontend_ioctl_legacy(struct file *file, | |||
1819 | err = fe->ops.enable_high_lnb_voltage(fe, (long) parg); | 2147 | err = fe->ops.enable_high_lnb_voltage(fe, (long) parg); |
1820 | break; | 2148 | break; |
1821 | 2149 | ||
1822 | case FE_SET_FRONTEND: { | 2150 | case FE_SET_FRONTEND: |
1823 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 2151 | err = set_delivery_system(fe, SYS_UNDEFINED); |
1824 | struct dvb_frontend_tune_settings fetunesettings; | 2152 | if (err) |
1825 | 2153 | break; | |
1826 | if (c->state == DTV_TUNE) { | ||
1827 | if (dvb_frontend_check_parameters(fe, &fepriv->parameters_in) < 0) { | ||
1828 | err = -EINVAL; | ||
1829 | break; | ||
1830 | } | ||
1831 | } else { | ||
1832 | if (dvb_frontend_check_parameters(fe, parg) < 0) { | ||
1833 | err = -EINVAL; | ||
1834 | break; | ||
1835 | } | ||
1836 | |||
1837 | memcpy (&fepriv->parameters_in, parg, | ||
1838 | sizeof (struct dvb_frontend_parameters)); | ||
1839 | dtv_property_cache_init(fe, c); | ||
1840 | dtv_property_cache_sync(fe, c, &fepriv->parameters_in); | ||
1841 | } | ||
1842 | |||
1843 | /* | ||
1844 | * Initialize output parameters to match the values given by | ||
1845 | * the user. FE_SET_FRONTEND triggers an initial frontend event | ||
1846 | * with status = 0, which copies output parameters to userspace. | ||
1847 | */ | ||
1848 | fepriv->parameters_out = fepriv->parameters_in; | ||
1849 | |||
1850 | memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings)); | ||
1851 | memcpy(&fetunesettings.parameters, parg, | ||
1852 | sizeof (struct dvb_frontend_parameters)); | ||
1853 | |||
1854 | /* force auto frequency inversion if requested */ | ||
1855 | if (dvb_force_auto_inversion) { | ||
1856 | fepriv->parameters_in.inversion = INVERSION_AUTO; | ||
1857 | fetunesettings.parameters.inversion = INVERSION_AUTO; | ||
1858 | } | ||
1859 | if (fe->ops.info.type == FE_OFDM) { | ||
1860 | /* without hierarchical coding code_rate_LP is irrelevant, | ||
1861 | * so we tolerate the otherwise invalid FEC_NONE setting */ | ||
1862 | if (fepriv->parameters_in.u.ofdm.hierarchy_information == HIERARCHY_NONE && | ||
1863 | fepriv->parameters_in.u.ofdm.code_rate_LP == FEC_NONE) | ||
1864 | fepriv->parameters_in.u.ofdm.code_rate_LP = FEC_AUTO; | ||
1865 | } | ||
1866 | |||
1867 | /* get frontend-specific tuning settings */ | ||
1868 | if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) { | ||
1869 | fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000; | ||
1870 | fepriv->max_drift = fetunesettings.max_drift; | ||
1871 | fepriv->step_size = fetunesettings.step_size; | ||
1872 | } else { | ||
1873 | /* default values */ | ||
1874 | switch(fe->ops.info.type) { | ||
1875 | case FE_QPSK: | ||
1876 | fepriv->min_delay = HZ/20; | ||
1877 | fepriv->step_size = fepriv->parameters_in.u.qpsk.symbol_rate / 16000; | ||
1878 | fepriv->max_drift = fepriv->parameters_in.u.qpsk.symbol_rate / 2000; | ||
1879 | break; | ||
1880 | |||
1881 | case FE_QAM: | ||
1882 | fepriv->min_delay = HZ/20; | ||
1883 | fepriv->step_size = 0; /* no zigzag */ | ||
1884 | fepriv->max_drift = 0; | ||
1885 | break; | ||
1886 | |||
1887 | case FE_OFDM: | ||
1888 | fepriv->min_delay = HZ/20; | ||
1889 | fepriv->step_size = fe->ops.info.frequency_stepsize * 2; | ||
1890 | fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; | ||
1891 | break; | ||
1892 | case FE_ATSC: | ||
1893 | fepriv->min_delay = HZ/20; | ||
1894 | fepriv->step_size = 0; | ||
1895 | fepriv->max_drift = 0; | ||
1896 | break; | ||
1897 | } | ||
1898 | } | ||
1899 | if (dvb_override_tune_delay > 0) | ||
1900 | fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000; | ||
1901 | |||
1902 | fepriv->state = FESTATE_RETUNE; | ||
1903 | |||
1904 | /* Request the search algorithm to search */ | ||
1905 | fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; | ||
1906 | 2154 | ||
1907 | dvb_frontend_clear_events(fe); | 2155 | err = dtv_property_cache_sync(fe, c, parg); |
1908 | dvb_frontend_add_event(fe, 0); | 2156 | if (err) |
1909 | dvb_frontend_wakeup(fe); | 2157 | break; |
1910 | fepriv->status = 0; | 2158 | err = dtv_set_frontend(fe); |
1911 | err = 0; | ||
1912 | break; | 2159 | break; |
1913 | } | ||
1914 | |||
1915 | case FE_GET_EVENT: | 2160 | case FE_GET_EVENT: |
1916 | err = dvb_frontend_get_event (fe, parg, file->f_flags); | 2161 | err = dvb_frontend_get_event (fe, parg, file->f_flags); |
1917 | break; | 2162 | break; |
1918 | 2163 | ||
1919 | case FE_GET_FRONTEND: | 2164 | case FE_GET_FRONTEND: |
1920 | if (fe->ops.get_frontend) { | 2165 | err = dtv_get_frontend(fe, parg); |
1921 | err = fe->ops.get_frontend(fe, &fepriv->parameters_out); | ||
1922 | memcpy(parg, &fepriv->parameters_out, sizeof(struct dvb_frontend_parameters)); | ||
1923 | } | ||
1924 | break; | 2166 | break; |
1925 | 2167 | ||
1926 | case FE_SET_FRONTEND_TUNE_MODE: | 2168 | case FE_SET_FRONTEND_TUNE_MODE: |
@@ -2061,12 +2303,15 @@ static int dvb_frontend_release(struct inode *inode, struct file *file) | |||
2061 | 2303 | ||
2062 | dprintk ("%s\n", __func__); | 2304 | dprintk ("%s\n", __func__); |
2063 | 2305 | ||
2064 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) | 2306 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) { |
2065 | fepriv->release_jiffies = jiffies; | 2307 | fepriv->release_jiffies = jiffies; |
2308 | mb(); | ||
2309 | } | ||
2066 | 2310 | ||
2067 | ret = dvb_generic_release (inode, file); | 2311 | ret = dvb_generic_release (inode, file); |
2068 | 2312 | ||
2069 | if (dvbdev->users == -1) { | 2313 | if (dvbdev->users == -1) { |
2314 | wake_up(&fepriv->wait_queue); | ||
2070 | if (fepriv->exit != DVB_FE_NO_EXIT) { | 2315 | if (fepriv->exit != DVB_FE_NO_EXIT) { |
2071 | fops_put(file->f_op); | 2316 | fops_put(file->f_op); |
2072 | file->f_op = NULL; | 2317 | file->f_op = NULL; |
@@ -2127,6 +2372,14 @@ int dvb_register_frontend(struct dvb_adapter* dvb, | |||
2127 | dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template, | 2372 | dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template, |
2128 | fe, DVB_DEVICE_FRONTEND); | 2373 | fe, DVB_DEVICE_FRONTEND); |
2129 | 2374 | ||
2375 | /* | ||
2376 | * Initialize the cache to the proper values according with the | ||
2377 | * first supported delivery system (ops->delsys[0]) | ||
2378 | */ | ||
2379 | |||
2380 | fe->dtv_property_cache.delivery_system = fe->ops.delsys[0]; | ||
2381 | dvb_frontend_clear_cache(fe); | ||
2382 | |||
2130 | mutex_unlock(&frontend_mutex); | 2383 | mutex_unlock(&frontend_mutex); |
2131 | return 0; | 2384 | return 0; |
2132 | } | 2385 | } |