linux/drivers/media/dvb/frontends/cxd2820r_c.c
<<
>>
Prefs
   1/*
   2 * Sony CXD2820R demodulator driver
   3 *
   4 * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
   5 *
   6 *    This program is free software; you can redistribute it and/or modify
   7 *    it under the terms of the GNU General Public License as published by
   8 *    the Free Software Foundation; either version 2 of the License, or
   9 *    (at your option) any later version.
  10 *
  11 *    This program is distributed in the hope that it will be useful,
  12 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *    GNU General Public License for more details.
  15 *
  16 *    You should have received a copy of the GNU General Public License along
  17 *    with this program; if not, write to the Free Software Foundation, Inc.,
  18 *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19 */
  20
  21
  22#include "cxd2820r_priv.h"
  23
  24int cxd2820r_set_frontend_c(struct dvb_frontend *fe,
  25        struct dvb_frontend_parameters *params)
  26{
  27        struct cxd2820r_priv *priv = fe->demodulator_priv;
  28        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  29        int ret, i;
  30        u8 buf[2];
  31        u16 if_ctl;
  32        u64 num;
  33        struct reg_val_mask tab[] = {
  34                { 0x00080, 0x01, 0xff },
  35                { 0x00081, 0x05, 0xff },
  36                { 0x00085, 0x07, 0xff },
  37                { 0x00088, 0x01, 0xff },
  38
  39                { 0x00082, 0x20, 0x60 },
  40                { 0x1016a, 0x48, 0xff },
  41                { 0x100a5, 0x00, 0x01 },
  42                { 0x10020, 0x06, 0x07 },
  43                { 0x10059, 0x50, 0xff },
  44                { 0x10087, 0x0c, 0x3c },
  45                { 0x1008b, 0x07, 0xff },
  46                { 0x1001f, priv->cfg.if_agc_polarity << 7, 0x80 },
  47                { 0x10070, priv->cfg.ts_mode, 0xff },
  48        };
  49
  50        dbg("%s: RF=%d SR=%d", __func__, c->frequency, c->symbol_rate);
  51
  52        /* update GPIOs */
  53        ret = cxd2820r_gpio(fe);
  54        if (ret)
  55                goto error;
  56
  57        /* program tuner */
  58        if (fe->ops.tuner_ops.set_params)
  59                fe->ops.tuner_ops.set_params(fe, params);
  60
  61        if (priv->delivery_system !=  SYS_DVBC_ANNEX_AC) {
  62                for (i = 0; i < ARRAY_SIZE(tab); i++) {
  63                        ret = cxd2820r_wr_reg_mask(priv, tab[i].reg,
  64                                tab[i].val, tab[i].mask);
  65                        if (ret)
  66                                goto error;
  67                }
  68        }
  69
  70        priv->delivery_system = SYS_DVBC_ANNEX_AC;
  71        priv->ber_running = 0; /* tune stops BER counter */
  72
  73        num = priv->cfg.if_dvbc;
  74        num *= 0x4000;
  75        if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
  76        buf[0] = (if_ctl >> 8) & 0x3f;
  77        buf[1] = (if_ctl >> 0) & 0xff;
  78
  79        ret = cxd2820r_wr_regs(priv, 0x10042, buf, 2);
  80        if (ret)
  81                goto error;
  82
  83        ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08);
  84        if (ret)
  85                goto error;
  86
  87        ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01);
  88        if (ret)
  89                goto error;
  90
  91        return ret;
  92error:
  93        dbg("%s: failed:%d", __func__, ret);
  94        return ret;
  95}
  96
  97int cxd2820r_get_frontend_c(struct dvb_frontend *fe,
  98        struct dvb_frontend_parameters *p)
  99{
 100        struct cxd2820r_priv *priv = fe->demodulator_priv;
 101        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 102        int ret;
 103        u8 buf[2];
 104
 105        ret = cxd2820r_rd_regs(priv, 0x1001a, buf, 2);
 106        if (ret)
 107                goto error;
 108
 109        c->symbol_rate = 2500 * ((buf[0] & 0x0f) << 8 | buf[1]);
 110
 111        ret = cxd2820r_rd_reg(priv, 0x10019, &buf[0]);
 112        if (ret)
 113                goto error;
 114
 115        switch ((buf[0] >> 0) & 0x03) {
 116        case 0:
 117                c->modulation = QAM_16;
 118                break;
 119        case 1:
 120                c->modulation = QAM_32;
 121                break;
 122        case 2:
 123                c->modulation = QAM_64;
 124                break;
 125        case 3:
 126                c->modulation = QAM_128;
 127                break;
 128        case 4:
 129                c->modulation = QAM_256;
 130                break;
 131        }
 132
 133        switch ((buf[0] >> 7) & 0x01) {
 134        case 0:
 135                c->inversion = INVERSION_OFF;
 136                break;
 137        case 1:
 138                c->inversion = INVERSION_ON;
 139                break;
 140        }
 141
 142        return ret;
 143error:
 144        dbg("%s: failed:%d", __func__, ret);
 145        return ret;
 146}
 147
 148int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber)
 149{
 150        struct cxd2820r_priv *priv = fe->demodulator_priv;
 151        int ret;
 152        u8 buf[3], start_ber = 0;
 153        *ber = 0;
 154
 155        if (priv->ber_running) {
 156                ret = cxd2820r_rd_regs(priv, 0x10076, buf, sizeof(buf));
 157                if (ret)
 158                        goto error;
 159
 160                if ((buf[2] >> 7) & 0x01 || (buf[2] >> 4) & 0x01) {
 161                        *ber = (buf[2] & 0x0f) << 16 | buf[1] << 8 | buf[0];
 162                        start_ber = 1;
 163                }
 164        } else {
 165                priv->ber_running = 1;
 166                start_ber = 1;
 167        }
 168
 169        if (start_ber) {
 170                /* (re)start BER */
 171                ret = cxd2820r_wr_reg(priv, 0x10079, 0x01);
 172                if (ret)
 173                        goto error;
 174        }
 175
 176        return ret;
 177error:
 178        dbg("%s: failed:%d", __func__, ret);
 179        return ret;
 180}
 181
 182int cxd2820r_read_signal_strength_c(struct dvb_frontend *fe,
 183        u16 *strength)
 184{
 185        struct cxd2820r_priv *priv = fe->demodulator_priv;
 186        int ret;
 187        u8 buf[2];
 188        u16 tmp;
 189
 190        ret = cxd2820r_rd_regs(priv, 0x10049, buf, sizeof(buf));
 191        if (ret)
 192                goto error;
 193
 194        tmp = (buf[0] & 0x03) << 8 | buf[1];
 195        tmp = (~tmp & 0x03ff);
 196
 197        if (tmp == 512)
 198                /* ~no signal */
 199                tmp = 0;
 200        else if (tmp > 350)
 201                tmp = 350;
 202
 203        /* scale value to 0x0000-0xffff */
 204        *strength = tmp * 0xffff / (350-0);
 205
 206        return ret;
 207error:
 208        dbg("%s: failed:%d", __func__, ret);
 209        return ret;
 210}
 211
 212int cxd2820r_read_snr_c(struct dvb_frontend *fe, u16 *snr)
 213{
 214        struct cxd2820r_priv *priv = fe->demodulator_priv;
 215        int ret;
 216        u8 tmp;
 217        unsigned int A, B;
 218        /* report SNR in dB * 10 */
 219
 220        ret = cxd2820r_rd_reg(priv, 0x10019, &tmp);
 221        if (ret)
 222                goto error;
 223
 224        if (((tmp >> 0) & 0x03) % 2) {
 225                A = 875;
 226                B = 650;
 227        } else {
 228                A = 950;
 229                B = 760;
 230        }
 231
 232        ret = cxd2820r_rd_reg(priv, 0x1004d, &tmp);
 233        if (ret)
 234                goto error;
 235
 236        #define CXD2820R_LOG2_E_24 24204406 /* log2(e) << 24 */
 237        if (tmp)
 238                *snr = A * (intlog2(B / tmp) >> 5) / (CXD2820R_LOG2_E_24 >> 5)
 239                        / 10;
 240        else
 241                *snr = 0;
 242
 243        return ret;
 244error:
 245        dbg("%s: failed:%d", __func__, ret);
 246        return ret;
 247}
 248
 249int cxd2820r_read_ucblocks_c(struct dvb_frontend *fe, u32 *ucblocks)
 250{
 251        *ucblocks = 0;
 252        /* no way to read ? */
 253        return 0;
 254}
 255
 256int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status)
 257{
 258        struct cxd2820r_priv *priv = fe->demodulator_priv;
 259        int ret;
 260        u8 buf[2];
 261        *status = 0;
 262
 263        ret = cxd2820r_rd_regs(priv, 0x10088, buf, sizeof(buf));
 264        if (ret)
 265                goto error;
 266
 267        if (((buf[0] >> 0) & 0x01) == 1) {
 268                *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
 269                        FE_HAS_VITERBI | FE_HAS_SYNC;
 270
 271                if (((buf[1] >> 3) & 0x01) == 1) {
 272                        *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
 273                                FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
 274                }
 275        }
 276
 277        dbg("%s: lock=%02x %02x", __func__, buf[0], buf[1]);
 278
 279        return ret;
 280error:
 281        dbg("%s: failed:%d", __func__, ret);
 282        return ret;
 283}
 284
 285int cxd2820r_init_c(struct dvb_frontend *fe)
 286{
 287        struct cxd2820r_priv *priv = fe->demodulator_priv;
 288        int ret;
 289
 290        ret = cxd2820r_wr_reg(priv, 0x00085, 0x07);
 291        if (ret)
 292                goto error;
 293
 294        return ret;
 295error:
 296        dbg("%s: failed:%d", __func__, ret);
 297        return ret;
 298}
 299
 300int cxd2820r_sleep_c(struct dvb_frontend *fe)
 301{
 302        struct cxd2820r_priv *priv = fe->demodulator_priv;
 303        int ret, i;
 304        struct reg_val_mask tab[] = {
 305                { 0x000ff, 0x1f, 0xff },
 306                { 0x00085, 0x00, 0xff },
 307                { 0x00088, 0x01, 0xff },
 308                { 0x00081, 0x00, 0xff },
 309                { 0x00080, 0x00, 0xff },
 310        };
 311
 312        dbg("%s", __func__);
 313
 314        priv->delivery_system = SYS_UNDEFINED;
 315
 316        for (i = 0; i < ARRAY_SIZE(tab); i++) {
 317                ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val,
 318                        tab[i].mask);
 319                if (ret)
 320                        goto error;
 321        }
 322
 323        return ret;
 324error:
 325        dbg("%s: failed:%d", __func__, ret);
 326        return ret;
 327}
 328
 329int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe,
 330        struct dvb_frontend_tune_settings *s)
 331{
 332        s->min_delay_ms = 500;
 333        s->step_size = 0; /* no zigzag */
 334        s->max_drift = 0;
 335
 336        return 0;
 337}
 338
 339