linux/drivers/media/dvb-frontends/cxd2820r_t.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_t(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                { 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */
  35                { 0x14, 0x80, 0x00, 0x00, 0x00 }, /* 7 MHz */
  36                { 0x11, 0xf0, 0x00, 0x00, 0x00 }, /* 8 MHz */
  37        };
  38        u8 bw_params2[][2] = {
  39                { 0x1f, 0xdc }, /* 6 MHz */
  40                { 0x12, 0xf8 }, /* 7 MHz */
  41                { 0x01, 0xe0 }, /* 8 MHz */
  42        };
  43        struct reg_val_mask tab[] = {
  44                { 0x00080, 0x00, 0xff },
  45                { 0x00081, 0x03, 0xff },
  46                { 0x00085, 0x07, 0xff },
  47                { 0x00088, 0x01, 0xff },
  48
  49                { 0x00070, priv->ts_mode, 0xff },
  50                { 0x00071, !priv->ts_clk_inv << 4, 0x10 },
  51                { 0x000cb, priv->if_agc_polarity << 6, 0x40 },
  52                { 0x000a5, 0x00, 0x01 },
  53                { 0x00082, 0x20, 0x60 },
  54                { 0x000c2, 0xc3, 0xff },
  55                { 0x0016a, 0x50, 0xff },
  56                { 0x00427, 0x41, 0xff },
  57        };
  58
  59        dev_dbg(&client->dev,
  60                "delivery_system=%d modulation=%d frequency=%u bandwidth_hz=%u inversion=%d\n",
  61                c->delivery_system, c->modulation, c->frequency,
  62                c->bandwidth_hz, c->inversion);
  63
  64        switch (c->bandwidth_hz) {
  65        case 6000000:
  66                bw_i = 0;
  67                bw_param = 2;
  68                break;
  69        case 7000000:
  70                bw_i = 1;
  71                bw_param = 1;
  72                break;
  73        case 8000000:
  74                bw_i = 2;
  75                bw_param = 0;
  76                break;
  77        default:
  78                return -EINVAL;
  79        }
  80
  81        /* program tuner */
  82        if (fe->ops.tuner_ops.set_params)
  83                fe->ops.tuner_ops.set_params(fe);
  84
  85        if (priv->delivery_system != SYS_DVBT) {
  86                ret = cxd2820r_wr_reg_val_mask_tab(priv, tab, ARRAY_SIZE(tab));
  87                if (ret)
  88                        goto error;
  89        }
  90
  91        priv->delivery_system = SYS_DVBT;
  92        priv->ber_running = false; /* tune stops BER counter */
  93
  94        /* program IF frequency */
  95        if (fe->ops.tuner_ops.get_if_frequency) {
  96                ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
  97                if (ret)
  98                        goto error;
  99                dev_dbg(&client->dev, "if_frequency=%u\n", if_frequency);
 100        } else {
 101                ret = -EINVAL;
 102                goto error;
 103        }
 104
 105        utmp = DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x1000000, CXD2820R_CLK);
 106        buf[0] = (utmp >> 16) & 0xff;
 107        buf[1] = (utmp >>  8) & 0xff;
 108        buf[2] = (utmp >>  0) & 0xff;
 109        ret = regmap_bulk_write(priv->regmap[0], 0x00b6, buf, 3);
 110        if (ret)
 111                goto error;
 112
 113        ret = regmap_bulk_write(priv->regmap[0], 0x009f, bw_params1[bw_i], 5);
 114        if (ret)
 115                goto error;
 116
 117        ret = regmap_update_bits(priv->regmap[0], 0x00d7, 0xc0, bw_param << 6);
 118        if (ret)
 119                goto error;
 120
 121        ret = regmap_bulk_write(priv->regmap[0], 0x00d9, bw_params2[bw_i], 2);
 122        if (ret)
 123                goto error;
 124
 125        ret = regmap_write(priv->regmap[0], 0x00ff, 0x08);
 126        if (ret)
 127                goto error;
 128
 129        ret = regmap_write(priv->regmap[0], 0x00fe, 0x01);
 130        if (ret)
 131                goto error;
 132
 133        return ret;
 134error:
 135        dev_dbg(&client->dev, "failed=%d\n", ret);
 136        return ret;
 137}
 138
 139int cxd2820r_get_frontend_t(struct dvb_frontend *fe,
 140                            struct dtv_frontend_properties *c)
 141{
 142        struct cxd2820r_priv *priv = fe->demodulator_priv;
 143        struct i2c_client *client = priv->client[0];
 144        int ret;
 145        unsigned int utmp;
 146        u8 buf[2];
 147
 148        dev_dbg(&client->dev, "\n");
 149
 150        ret = regmap_bulk_read(priv->regmap[0], 0x002f, buf, sizeof(buf));
 151        if (ret)
 152                goto error;
 153
 154        switch ((buf[0] >> 6) & 0x03) {
 155        case 0:
 156                c->modulation = QPSK;
 157                break;
 158        case 1:
 159                c->modulation = QAM_16;
 160                break;
 161        case 2:
 162                c->modulation = QAM_64;
 163                break;
 164        }
 165
 166        switch ((buf[1] >> 1) & 0x03) {
 167        case 0:
 168                c->transmission_mode = TRANSMISSION_MODE_2K;
 169                break;
 170        case 1:
 171                c->transmission_mode = TRANSMISSION_MODE_8K;
 172                break;
 173        }
 174
 175        switch ((buf[1] >> 3) & 0x03) {
 176        case 0:
 177                c->guard_interval = GUARD_INTERVAL_1_32;
 178                break;
 179        case 1:
 180                c->guard_interval = GUARD_INTERVAL_1_16;
 181                break;
 182        case 2:
 183                c->guard_interval = GUARD_INTERVAL_1_8;
 184                break;
 185        case 3:
 186                c->guard_interval = GUARD_INTERVAL_1_4;
 187                break;
 188        }
 189
 190        switch ((buf[0] >> 3) & 0x07) {
 191        case 0:
 192                c->hierarchy = HIERARCHY_NONE;
 193                break;
 194        case 1:
 195                c->hierarchy = HIERARCHY_1;
 196                break;
 197        case 2:
 198                c->hierarchy = HIERARCHY_2;
 199                break;
 200        case 3:
 201                c->hierarchy = HIERARCHY_4;
 202                break;
 203        }
 204
 205        switch ((buf[0] >> 0) & 0x07) {
 206        case 0:
 207                c->code_rate_HP = FEC_1_2;
 208                break;
 209        case 1:
 210                c->code_rate_HP = FEC_2_3;
 211                break;
 212        case 2:
 213                c->code_rate_HP = FEC_3_4;
 214                break;
 215        case 3:
 216                c->code_rate_HP = FEC_5_6;
 217                break;
 218        case 4:
 219                c->code_rate_HP = FEC_7_8;
 220                break;
 221        }
 222
 223        switch ((buf[1] >> 5) & 0x07) {
 224        case 0:
 225                c->code_rate_LP = FEC_1_2;
 226                break;
 227        case 1:
 228                c->code_rate_LP = FEC_2_3;
 229                break;
 230        case 2:
 231                c->code_rate_LP = FEC_3_4;
 232                break;
 233        case 3:
 234                c->code_rate_LP = FEC_5_6;
 235                break;
 236        case 4:
 237                c->code_rate_LP = FEC_7_8;
 238                break;
 239        }
 240
 241        ret = regmap_read(priv->regmap[0], 0x07c6, &utmp);
 242        if (ret)
 243                goto error;
 244
 245        switch ((utmp >> 0) & 0x01) {
 246        case 0:
 247                c->inversion = INVERSION_OFF;
 248                break;
 249        case 1:
 250                c->inversion = INVERSION_ON;
 251                break;
 252        }
 253
 254        return ret;
 255error:
 256        dev_dbg(&client->dev, "failed=%d\n", ret);
 257        return ret;
 258}
 259
 260int cxd2820r_read_status_t(struct dvb_frontend *fe, enum fe_status *status)
 261{
 262        struct cxd2820r_priv *priv = fe->demodulator_priv;
 263        struct i2c_client *client = priv->client[0];
 264        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 265        int ret;
 266        unsigned int utmp, utmp1, utmp2;
 267        u8 buf[3];
 268
 269        /* Lock detection */
 270        ret = regmap_bulk_read(priv->regmap[0], 0x0010, &buf[0], 1);
 271        if (ret)
 272                goto error;
 273        ret = regmap_bulk_read(priv->regmap[0], 0x0073, &buf[1], 1);
 274        if (ret)
 275                goto error;
 276
 277        utmp1 = (buf[0] >> 0) & 0x07;
 278        utmp2 = (buf[1] >> 3) & 0x01;
 279
 280        if (utmp1 == 6 && utmp2 == 1) {
 281                *status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
 282                          FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
 283        } else if (utmp1 == 6 || utmp2 == 1) {
 284                *status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
 285                          FE_HAS_VITERBI | FE_HAS_SYNC;
 286        } else {
 287                *status = 0;
 288        }
 289
 290        dev_dbg(&client->dev, "status=%02x raw=%*ph sync=%u ts=%u\n",
 291                *status, 2, buf, utmp1, utmp2);
 292
 293        /* Signal strength */
 294        if (*status & FE_HAS_SIGNAL) {
 295                unsigned int strength;
 296
 297                ret = regmap_bulk_read(priv->regmap[0], 0x0026, buf, 2);
 298                if (ret)
 299                        goto error;
 300
 301                utmp = buf[0] << 8 | buf[1] << 0;
 302                utmp = ~utmp & 0x0fff;
 303                /* Scale value to 0x0000-0xffff */
 304                strength = utmp << 4 | utmp >> 8;
 305
 306                c->strength.len = 1;
 307                c->strength.stat[0].scale = FE_SCALE_RELATIVE;
 308                c->strength.stat[0].uvalue = strength;
 309        } else {
 310                c->strength.len = 1;
 311                c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
 312        }
 313
 314        /* CNR */
 315        if (*status & FE_HAS_VITERBI) {
 316                unsigned int cnr;
 317
 318                ret = regmap_bulk_read(priv->regmap[0], 0x002c, buf, 2);
 319                if (ret)
 320                        goto error;
 321
 322                utmp = buf[0] << 8 | buf[1] << 0;
 323                if (utmp)
 324                        cnr = div_u64((u64)(intlog10(utmp)
 325                                      - intlog10(32000 - utmp) + 55532585)
 326                                      * 10000, (1 << 24));
 327                else
 328                        cnr = 0;
 329
 330                c->cnr.len = 1;
 331                c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
 332                c->cnr.stat[0].svalue = cnr;
 333        } else {
 334                c->cnr.len = 1;
 335                c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
 336        }
 337
 338        /* BER */
 339        if (*status & FE_HAS_SYNC) {
 340                unsigned int post_bit_error;
 341                bool start_ber;
 342
 343                if (priv->ber_running) {
 344                        ret = regmap_bulk_read(priv->regmap[0], 0x0076, buf, 3);
 345                        if (ret)
 346                                goto error;
 347
 348                        if ((buf[2] >> 7) & 0x01) {
 349                                post_bit_error = buf[2] << 16 | buf[1] << 8 |
 350                                                 buf[0] << 0;
 351                                post_bit_error &= 0x0fffff;
 352                                start_ber = true;
 353                        } else {
 354                                post_bit_error = 0;
 355                                start_ber = false;
 356                        }
 357                } else {
 358                        post_bit_error = 0;
 359                        start_ber = true;
 360                }
 361
 362                if (start_ber) {
 363                        ret = regmap_write(priv->regmap[0], 0x0079, 0x01);
 364                        if (ret)
 365                                goto error;
 366                        priv->ber_running = true;
 367                }
 368
 369                priv->post_bit_error += post_bit_error;
 370
 371                c->post_bit_error.len = 1;
 372                c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
 373                c->post_bit_error.stat[0].uvalue = priv->post_bit_error;
 374        } else {
 375                c->post_bit_error.len = 1;
 376                c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
 377        }
 378
 379        return ret;
 380error:
 381        dev_dbg(&client->dev, "failed=%d\n", ret);
 382        return ret;
 383}
 384
 385int cxd2820r_init_t(struct dvb_frontend *fe)
 386{
 387        struct cxd2820r_priv *priv = fe->demodulator_priv;
 388        struct i2c_client *client = priv->client[0];
 389        int ret;
 390
 391        dev_dbg(&client->dev, "\n");
 392
 393        ret = regmap_write(priv->regmap[0], 0x0085, 0x07);
 394        if (ret)
 395                goto error;
 396
 397        return ret;
 398error:
 399        dev_dbg(&client->dev, "failed=%d\n", ret);
 400        return ret;
 401}
 402
 403int cxd2820r_sleep_t(struct dvb_frontend *fe)
 404{
 405        struct cxd2820r_priv *priv = fe->demodulator_priv;
 406        struct i2c_client *client = priv->client[0];
 407        int ret;
 408        struct reg_val_mask tab[] = {
 409                { 0x000ff, 0x1f, 0xff },
 410                { 0x00085, 0x00, 0xff },
 411                { 0x00088, 0x01, 0xff },
 412                { 0x00081, 0x00, 0xff },
 413                { 0x00080, 0x00, 0xff },
 414        };
 415
 416        dev_dbg(&client->dev, "\n");
 417
 418        priv->delivery_system = SYS_UNDEFINED;
 419
 420        ret = cxd2820r_wr_reg_val_mask_tab(priv, tab, ARRAY_SIZE(tab));
 421        if (ret)
 422                goto error;
 423
 424        return ret;
 425error:
 426        dev_dbg(&client->dev, "failed=%d\n", ret);
 427        return ret;
 428}
 429
 430int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe,
 431        struct dvb_frontend_tune_settings *s)
 432{
 433        s->min_delay_ms = 500;
 434        s->step_size = fe->ops.info.frequency_stepsize_hz * 2;
 435        s->max_drift = (fe->ops.info.frequency_stepsize_hz * 2) + 1;
 436
 437        return 0;
 438}
 439