Em 21-11-2011 22:04, Andreas Oberritter escreveu:
> On 21.11.2011 22:06, Manu Abraham wrote:
>>
>> 0004-TDA18271-Allow-frontend-to-set-DELSYS-rather-than-qu.patch
>>
>>
>> From 2ece38602678ae323450d0e35379147e6e086326 Mon Sep 17 00:00:00 2001
>> From: Manu Abraham <abraham.m...@gmail.com>
>> Date: Sat, 19 Nov 2011 19:50:09 +0530
>> Subject: [PATCH 04/13] TDA18271: Allow frontend to set DELSYS, rather than 
>> querying fe->ops.info.type
>>
>> With any tuner that can tune to multiple delivery systems/standards, it does
>> query fe->ops.info.type to determine frontend type and set the delivery
>> system type. fe->ops.info.type can handle only 4 delivery systems, viz 
>> FE_QPSK,
>> FE_QAM, FE_OFDM and FE_ATSC.
>>
>> The change allows the tuner to be set to any delivery system specified in
>> fe_delivery_system_t, thereby simplifying a lot of issues.
>>
>> Signed-off-by: Manu Abraham <abraham.m...@gmail.com>
>> ---
>>  drivers/media/common/tuners/tda18271-fe.c   |   80 
>> +++++++++++++++++++++++++++
>>  drivers/media/common/tuners/tda18271-priv.h |    2 +
>>  2 files changed, 82 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/media/common/tuners/tda18271-fe.c 
>> b/drivers/media/common/tuners/tda18271-fe.c
>> index 3347c5b..6e29faf 100644
>> --- a/drivers/media/common/tuners/tda18271-fe.c
>> +++ b/drivers/media/common/tuners/tda18271-fe.c
>> @@ -928,6 +928,85 @@ fail:
>>  
>>  /* ------------------------------------------------------------------ */
>>  
>> +static int tda18271_set_state(struct dvb_frontend *fe,
>> +                          enum tuner_param param,
>> +                          struct tuner_state *state)
>> +{
>> +    struct tda18271_priv *priv = fe->tuner_priv;
>> +    struct tuner_state *req = &priv->request;
>> +    struct tda18271_std_map *std_map = &priv->std;
>> +    struct tda18271_std_map_item *map;
>> +    int ret;
>> +
>> +    BUG_ON(!priv);
> 
> At this point priv has already been dereferenced.
> 
>> +    if (param & DVBFE_TUNER_DELSYS)
>> +            req->delsys = state->delsys;
>> +    if (param & DVBFE_TUNER_FREQUENCY)
>> +            req->frequency = state->frequency;
>> +    if (param & DVBFE_TUNER_BANDWIDTH)
>> +            req->bandwidth = state->bandwidth;
> 
> What happens if one of these flags is not set, when the function is
> called for the first time? priv->request doesn't seem to get initialized.
> 
> Regards,
> Andreas
> 
>> +
>> +    priv->mode = TDA18271_DIGITAL;
>> +
>> +    switch (req->delsys) {
>> +    case SYS_ATSC:
>> +            map = &std_map->atsc_6;
>> +            req->bandwidth = 6000000;
>> +            break;
>> +    case SYS_DVBC_ANNEX_B:
>> +            map = &std_map->qam_6;
>> +            req->bandwidth = 6000000;
>> +            break;
>> +    case SYS_DVBT:
>> +    case SYS_DVBT2:
>> +            switch (req->bandwidth) {
>> +            case 6000000:
>> +                    map = &std_map->dvbt_6;
>> +                    break;
>> +            case 7000000:
>> +                    map = &std_map->dvbt_7;
>> +                    break;
>> +            case 8000000:
>> +                    map = &std_map->dvbt_8;
>> +                    break;
>> +            default:
>> +                    ret = -EINVAL;
>> +                    goto fail;
>> +            }
>> +            break;
>> +    case SYS_DVBC_ANNEX_AC:
>> +            map = &std_map->qam_8;
>> +            req->bandwidth = 8000000;
>> +            break;

This premise is not correct, and causes tuning failure on places where
channels are spaced with 6MHz.

The bandwidth should be calculated as a function of the rolloff and symbol
rate. I had to fix it on a few places, for devices to work with Net Digital
Cable operator in Brazil (6MHz spaced channels, 5.217 KBauds per carrier,
DVB-C Annex A).

The correct way for doing it is:

        else if (fe->ops.info.type == FE_QAM) {
                /*
                 * Using a higher bandwidth at the tuner filter may
                 * allow inter-carrier interference.
                 * So, determine the minimal channel spacing, in order
                 * to better adjust the tuner filter.
                 * According with ITU-T J.83, the bandwidth is given by:
                 * bw = Simbol Rate * (1 + roll_off), where the roll_off
                 * is equal to 0.15 for Annex A, and 0.13 for annex C
                 */
                if (fe->dtv_property_cache.rolloff == ROLLOFF_13)
                        bw = (params->u.qam.symbol_rate * 13) / 10;
                else
                        bw = (params->u.qam.symbol_rate * 15) / 10;
                if (bw <= 6000000)
                        Standard = HF_DVBC_6MHZ;
                else if (bw <= 7000000)
                        Standard = HF_DVBC_7MHZ;
                else
                        Standard = HF_DVBC_8MHZ;

(from drivers/media/dvb/frontends/tda18271c2dd.c)

Where ROLLOFF_13 is used on Annex C, and ROLLOF_15 on Annex A.

The same fix should be applied to all DVB-C capable tuners. Alternatively, we 
should put some ancillary function at the core, and let the core estimate the 
needed bandwidth for DVB-C.

PS.: While I didn't test, I suspect that places using 7MHz-spaced channels will 
also increase the reception, as less inter-channel noise will be sent to
the demod.

>> +    default:
>> +            tda_warn("Invalid delivery system!\n");
>> +            ret = -EINVAL;
>> +            goto fail;
>> +    }
>> +    tda_dbg("Trying to tune .. delsys=%d modulation=%d frequency=%d 
>> bandwidth=%d",
>> +            req->delsys,
>> +            req->modulation,
>> +            req->frequency,
>> +            req->bandwidth);
>> +
>> +    /* When tuning digital, the analog demod must be tri-stated */
>> +    if (fe->ops.analog_ops.standby)
>> +            fe->ops.analog_ops.standby(fe);
>> +
>> +    ret = tda18271_tune(fe, map, req->frequency, req->bandwidth);
>> +
>> +    if (tda_fail(ret))
>> +            goto fail;
>> +
>> +    priv->if_freq   = map->if_freq;
>> +    priv->frequency = req->frequency;
>> +    priv->bandwidth = (req->delsys == SYS_DVBT || req->delsys == SYS_DVBT2) 
>> ?
>> +                       req->bandwidth : 0;
>> +fail:
>> +    return ret;
>> +}
>> +
>> +
>>  static int tda18271_set_params(struct dvb_frontend *fe,
>>                             struct dvb_frontend_parameters *params)
>>  {
>> @@ -1249,6 +1328,7 @@ static const struct dvb_tuner_ops tda18271_tuner_ops = 
>> {
>>      .init              = tda18271_init,
>>      .sleep             = tda18271_sleep,
>>      .set_params        = tda18271_set_params,
>> +    .set_state         = tda18271_set_state,
>>      .set_analog_params = tda18271_set_analog_params,
>>      .release           = tda18271_release,
>>      .set_config        = tda18271_set_config,
>> diff --git a/drivers/media/common/tuners/tda18271-priv.h 
>> b/drivers/media/common/tuners/tda18271-priv.h
>> index 454c152..bd1bf58 100644
>> --- a/drivers/media/common/tuners/tda18271-priv.h
>> +++ b/drivers/media/common/tuners/tda18271-priv.h
>> @@ -126,6 +126,8 @@ struct tda18271_priv {
>>  
>>      u32 frequency;
>>      u32 bandwidth;
>> +
>> +    struct tuner_state request;
>>  };
>>  
>>  /*---------------------------------------------------------------------*/
>> -- 1.7.1
>>
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to