root/drivers/media/dvb-frontends/cxd2820r_t.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cxd2820r_set_frontend_t
  2. cxd2820r_get_frontend_t
  3. cxd2820r_read_status_t
  4. cxd2820r_init_t
  5. cxd2820r_sleep_t
  6. cxd2820r_get_tune_settings_t

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

/* [<][>][^][v][top][bottom][index][help] */