linux/drivers/media/dvb-frontends/cxd2820r_t2.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_t2(struct dvb_frontend *fe)
  25{
  26        struct cxd2820r_priv *priv = fe->demodulator_priv;
  27        struct i2c_client *client = priv->client[0];
  28        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  29        int ret, bw_i;
  30        unsigned int utmp;
  31        u32 if_frequency;
  32        u8 buf[3], bw_param;
  33        u8 bw_params1[][5] = {
  34                { 0x1c, 0xb3, 0x33, 0x33, 0x33 }, /* 5 MHz */
  35                { 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */
  36                { 0x14, 0x80, 0x00, 0x00, 0x00 }, /* 7 MHz */
  37                { 0x11, 0xf0, 0x00, 0x00, 0x00 }, /* 8 MHz */
  38        };
  39        struct reg_val_mask tab[] = {
  40                { 0x00080, 0x02, 0xff },
  41                { 0x00081, 0x20, 0xff },
  42                { 0x00085, 0x07, 0xff },
  43                { 0x00088, 0x01, 0xff },
  44                { 0x02069, 0x01, 0xff },
  45
  46                { 0x0207f, 0x2a, 0xff },
  47                { 0x02082, 0x0a, 0xff },
  48                { 0x02083, 0x0a, 0xff },
  49                { 0x020cb, priv->if_agc_polarity << 6, 0x40 },
  50                { 0x02070, priv->ts_mode, 0xff },
  51                { 0x02071, !priv->ts_clk_inv << 6, 0x40 },
  52                { 0x020b5, priv->spec_inv << 4, 0x10 },
  53                { 0x02567, 0x07, 0x0f },
  54                { 0x02569, 0x03, 0x03 },
  55                { 0x02595, 0x1a, 0xff },
  56                { 0x02596, 0x50, 0xff },
  57                { 0x02a8c, 0x00, 0xff },
  58                { 0x02a8d, 0x34, 0xff },
  59                { 0x02a45, 0x06, 0x07 },
  60                { 0x03f10, 0x0d, 0xff },
  61                { 0x03f11, 0x02, 0xff },
  62                { 0x03f12, 0x01, 0xff },
  63                { 0x03f23, 0x2c, 0xff },
  64                { 0x03f51, 0x13, 0xff },
  65                { 0x03f52, 0x01, 0xff },
  66                { 0x03f53, 0x00, 0xff },
  67                { 0x027e6, 0x14, 0xff },
  68                { 0x02786, 0x02, 0x07 },
  69                { 0x02787, 0x40, 0xe0 },
  70                { 0x027ef, 0x10, 0x18 },
  71        };
  72
  73        dev_dbg(&client->dev,
  74                "delivery_system=%d modulation=%d frequency=%u bandwidth_hz=%u inversion=%d stream_id=%u\n",
  75                c->delivery_system, c->modulation, c->frequency,
  76                c->bandwidth_hz, c->inversion, c->stream_id);
  77
  78        switch (c->bandwidth_hz) {
  79        case 5000000:
  80                bw_i = 0;
  81                bw_param = 3;
  82                break;
  83        case 6000000:
  84                bw_i = 1;
  85                bw_param = 2;
  86                break;
  87        case 7000000:
  88                bw_i = 2;
  89                bw_param = 1;
  90                break;
  91        case 8000000:
  92                bw_i = 3;
  93                bw_param = 0;
  94                break;
  95        default:
  96                return -EINVAL;
  97        }
  98
  99        /* program tuner */
 100        if (fe->ops.tuner_ops.set_params)
 101                fe->ops.tuner_ops.set_params(fe);
 102
 103        if (priv->delivery_system != SYS_DVBT2) {
 104                ret = cxd2820r_wr_reg_val_mask_tab(priv, tab, ARRAY_SIZE(tab));
 105                if (ret)
 106                        goto error;
 107        }
 108
 109        priv->delivery_system = SYS_DVBT2;
 110
 111        /* program IF frequency */
 112        if (fe->ops.tuner_ops.get_if_frequency) {
 113                ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
 114                if (ret)
 115                        goto error;
 116                dev_dbg(&client->dev, "if_frequency=%u\n", if_frequency);
 117        } else {
 118                ret = -EINVAL;
 119                goto error;
 120        }
 121
 122        utmp = DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x1000000, CXD2820R_CLK);
 123        buf[0] = (utmp >> 16) & 0xff;
 124        buf[1] = (utmp >>  8) & 0xff;
 125        buf[2] = (utmp >>  0) & 0xff;
 126        ret = regmap_bulk_write(priv->regmap[0], 0x20b6, buf, 3);
 127        if (ret)
 128                goto error;
 129
 130        /* PLP filtering */
 131        if (c->stream_id > 255) {
 132                dev_dbg(&client->dev, "disable PLP filtering\n");
 133                ret = regmap_write(priv->regmap[0], 0x23ad, 0x00);
 134                if (ret)
 135                        goto error;
 136        } else {
 137                dev_dbg(&client->dev, "enable PLP filtering\n");
 138                ret = regmap_write(priv->regmap[0], 0x23af, c->stream_id & 0xff);
 139                if (ret)
 140                        goto error;
 141                ret = regmap_write(priv->regmap[0], 0x23ad, 0x01);
 142                if (ret)
 143                        goto error;
 144        }
 145
 146        ret = regmap_bulk_write(priv->regmap[0], 0x209f, bw_params1[bw_i], 5);
 147        if (ret)
 148                goto error;
 149
 150        ret = regmap_update_bits(priv->regmap[0], 0x20d7, 0xc0, bw_param << 6);
 151        if (ret)
 152                goto error;
 153
 154        ret = regmap_write(priv->regmap[0], 0x00ff, 0x08);
 155        if (ret)
 156                goto error;
 157
 158        ret = regmap_write(priv->regmap[0], 0x00fe, 0x01);
 159        if (ret)
 160                goto error;
 161
 162        return ret;
 163error:
 164        dev_dbg(&client->dev, "failed=%d\n", ret);
 165        return ret;
 166
 167}
 168
 169int cxd2820r_get_frontend_t2(struct dvb_frontend *fe,
 170                             struct dtv_frontend_properties *c)
 171{
 172        struct cxd2820r_priv *priv = fe->demodulator_priv;
 173        struct i2c_client *client = priv->client[0];
 174        int ret;
 175        unsigned int utmp;
 176        u8 buf[2];
 177
 178        dev_dbg(&client->dev, "\n");
 179
 180        ret = regmap_bulk_read(priv->regmap[0], 0x205c, buf, 2);
 181        if (ret)
 182                goto error;
 183
 184        switch ((buf[0] >> 0) & 0x07) {
 185        case 0:
 186                c->transmission_mode = TRANSMISSION_MODE_2K;
 187                break;
 188        case 1:
 189                c->transmission_mode = TRANSMISSION_MODE_8K;
 190                break;
 191        case 2:
 192                c->transmission_mode = TRANSMISSION_MODE_4K;
 193                break;
 194        case 3:
 195                c->transmission_mode = TRANSMISSION_MODE_1K;
 196                break;
 197        case 4:
 198                c->transmission_mode = TRANSMISSION_MODE_16K;
 199                break;
 200        case 5:
 201                c->transmission_mode = TRANSMISSION_MODE_32K;
 202                break;
 203        }
 204
 205        switch ((buf[1] >> 4) & 0x07) {
 206        case 0:
 207                c->guard_interval = GUARD_INTERVAL_1_32;
 208                break;
 209        case 1:
 210                c->guard_interval = GUARD_INTERVAL_1_16;
 211                break;
 212        case 2:
 213                c->guard_interval = GUARD_INTERVAL_1_8;
 214                break;
 215        case 3:
 216                c->guard_interval = GUARD_INTERVAL_1_4;
 217                break;
 218        case 4:
 219                c->guard_interval = GUARD_INTERVAL_1_128;
 220                break;
 221        case 5:
 222                c->guard_interval = GUARD_INTERVAL_19_128;
 223                break;
 224        case 6:
 225                c->guard_interval = GUARD_INTERVAL_19_256;
 226                break;
 227        }
 228
 229        ret = regmap_bulk_read(priv->regmap[0], 0x225b, buf, 2);
 230        if (ret)
 231                goto error;
 232
 233        switch ((buf[0] >> 0) & 0x07) {
 234        case 0:
 235                c->fec_inner = FEC_1_2;
 236                break;
 237        case 1:
 238                c->fec_inner = FEC_3_5;
 239                break;
 240        case 2:
 241                c->fec_inner = FEC_2_3;
 242                break;
 243        case 3:
 244                c->fec_inner = FEC_3_4;
 245                break;
 246        case 4:
 247                c->fec_inner = FEC_4_5;
 248                break;
 249        case 5:
 250                c->fec_inner = FEC_5_6;
 251                break;
 252        }
 253
 254        switch ((buf[1] >> 0) & 0x07) {
 255        case 0:
 256                c->modulation = QPSK;
 257                break;
 258        case 1:
 259                c->modulation = QAM_16;
 260                break;
 261        case 2:
 262                c->modulation = QAM_64;
 263                break;
 264        case 3:
 265                c->modulation = QAM_256;
 266                break;
 267        }
 268
 269        ret = regmap_read(priv->regmap[0], 0x20b5, &utmp);
 270        if (ret)
 271                goto error;
 272
 273        switch ((utmp >> 4) & 0x01) {
 274        case 0:
 275                c->inversion = INVERSION_OFF;
 276                break;
 277        case 1:
 278                c->inversion = INVERSION_ON;
 279                break;
 280        }
 281
 282        return ret;
 283error:
 284        dev_dbg(&client->dev, "failed=%d\n", ret);
 285        return ret;
 286}
 287
 288int cxd2820r_read_status_t2(struct dvb_frontend *fe, enum fe_status *status)
 289{
 290        struct cxd2820r_priv *priv = fe->demodulator_priv;
 291        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 292        struct i2c_client *client = priv->client[0];
 293        int ret;
 294        unsigned int utmp, utmp1, utmp2;
 295        u8 buf[4];
 296
 297        /* Lock detection */
 298        ret = regmap_bulk_read(priv->regmap[0], 0x2010, &buf[0], 1);
 299        if (ret)
 300                goto error;
 301
 302        utmp1 = (buf[0] >> 0) & 0x07;
 303        utmp2 = (buf[0] >> 5) & 0x01;
 304
 305        if (utmp1 == 6 && utmp2 == 1) {
 306                *status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
 307                          FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
 308        } else if (utmp1 == 6 || utmp2 == 1) {
 309                *status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
 310                          FE_HAS_VITERBI | FE_HAS_SYNC;
 311        } else {
 312                *status = 0;
 313        }
 314
 315        dev_dbg(&client->dev, "status=%02x raw=%*ph sync=%u ts=%u\n",
 316                *status, 1, buf, utmp1, utmp2);
 317
 318        /* Signal strength */
 319        if (*status & FE_HAS_SIGNAL) {
 320                unsigned int strength;
 321
 322                ret = regmap_bulk_read(priv->regmap[0], 0x2026, buf, 2);
 323                if (ret)
 324                        goto error;
 325
 326                utmp = buf[0] << 8 | buf[1] << 0;
 327                utmp = ~utmp & 0x0fff;
 328                /* Scale value to 0x0000-0xffff */
 329                strength = utmp << 4 | utmp >> 8;
 330
 331                c->strength.len = 1;
 332                c->strength.stat[0].scale = FE_SCALE_RELATIVE;
 333                c->strength.stat[0].uvalue = strength;
 334        } else {
 335                c->strength.len = 1;
 336                c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
 337        }
 338
 339        /* CNR */
 340        if (*status & FE_HAS_VITERBI) {
 341                unsigned int cnr;
 342
 343                ret = regmap_bulk_read(priv->regmap[0], 0x2028, buf, 2);
 344                if (ret)
 345                        goto error;
 346
 347                utmp = buf[0] << 8 | buf[1] << 0;
 348                utmp = utmp & 0x0fff;
 349                #define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */
 350                if (utmp)
 351                        cnr = div_u64((u64)(intlog10(utmp)
 352                                      - CXD2820R_LOG10_8_24) * 10000,
 353                                      (1 << 24));
 354                else
 355                        cnr = 0;
 356
 357                c->cnr.len = 1;
 358                c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
 359                c->cnr.stat[0].svalue = cnr;
 360        } else {
 361                c->cnr.len = 1;
 362                c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
 363        }
 364
 365        /* BER */
 366        if (*status & FE_HAS_SYNC) {
 367                unsigned int post_bit_error;
 368
 369                ret = regmap_bulk_read(priv->regmap[0], 0x2039, buf, 4);
 370                if (ret)
 371                        goto error;
 372
 373                if ((buf[0] >> 4) & 0x01) {
 374                        post_bit_error = buf[0] << 24 | buf[1] << 16 |
 375                                         buf[2] << 8 | buf[3] << 0;
 376                        post_bit_error &= 0x0fffffff;
 377                } else {
 378                        post_bit_error = 0;
 379                }
 380
 381                priv->post_bit_error += post_bit_error;
 382
 383                c->post_bit_error.len = 1;
 384                c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
 385                c->post_bit_error.stat[0].uvalue = priv->post_bit_error;
 386        } else {
 387                c->post_bit_error.len = 1;
 388                c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
 389        }
 390
 391        return ret;
 392error:
 393        dev_dbg(&client->dev, "failed=%d\n", ret);
 394        return ret;
 395}
 396
 397int cxd2820r_sleep_t2(struct dvb_frontend *fe)
 398{
 399        struct cxd2820r_priv *priv = fe->demodulator_priv;
 400        struct i2c_client *client = priv->client[0];
 401        int ret;
 402        struct reg_val_mask tab[] = {
 403                { 0x000ff, 0x1f, 0xff },
 404                { 0x00085, 0x00, 0xff },
 405                { 0x00088, 0x01, 0xff },
 406                { 0x02069, 0x00, 0xff },
 407                { 0x00081, 0x00, 0xff },
 408                { 0x00080, 0x00, 0xff },
 409        };
 410
 411        dev_dbg(&client->dev, "\n");
 412
 413        ret = cxd2820r_wr_reg_val_mask_tab(priv, tab, ARRAY_SIZE(tab));
 414        if (ret)
 415                goto error;
 416
 417        priv->delivery_system = SYS_UNDEFINED;
 418
 419        return ret;
 420error:
 421        dev_dbg(&client->dev, "failed=%d\n", ret);
 422        return ret;
 423}
 424
 425int cxd2820r_get_tune_settings_t2(struct dvb_frontend *fe,
 426        struct dvb_frontend_tune_settings *s)
 427{
 428        s->min_delay_ms = 1500;
 429        s->step_size = fe->ops.info.frequency_stepsize * 2;
 430        s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
 431
 432        return 0;
 433}
 434