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 24 int 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, i, 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 for (i = 0; i < ARRAY_SIZE(tab); i++) { 105 ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, 106 tab[i].val, tab[i].mask); 107 if (ret) 108 goto error; 109 } 110 } 111 112 priv->delivery_system = SYS_DVBT2; 113 114 /* program IF frequency */ 115 if (fe->ops.tuner_ops.get_if_frequency) { 116 ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency); 117 if (ret) 118 goto error; 119 dev_dbg(&client->dev, "if_frequency=%u\n", if_frequency); 120 } else { 121 ret = -EINVAL; 122 goto error; 123 } 124 125 utmp = DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x1000000, CXD2820R_CLK); 126 buf[0] = (utmp >> 16) & 0xff; 127 buf[1] = (utmp >> 8) & 0xff; 128 buf[2] = (utmp >> 0) & 0xff; 129 ret = cxd2820r_wr_regs(priv, 0x020b6, buf, 3); 130 if (ret) 131 goto error; 132 133 /* PLP filtering */ 134 if (c->stream_id > 255) { 135 dev_dbg(&client->dev, "disable PLP filtering\n"); 136 ret = cxd2820r_wr_reg(priv, 0x023ad , 0); 137 if (ret) 138 goto error; 139 } else { 140 dev_dbg(&client->dev, "enable PLP filtering\n"); 141 ret = cxd2820r_wr_reg(priv, 0x023af , c->stream_id & 0xFF); 142 if (ret) 143 goto error; 144 ret = cxd2820r_wr_reg(priv, 0x023ad , 1); 145 if (ret) 146 goto error; 147 } 148 149 ret = cxd2820r_wr_regs(priv, 0x0209f, bw_params1[bw_i], 5); 150 if (ret) 151 goto error; 152 153 ret = cxd2820r_wr_reg_mask(priv, 0x020d7, bw_param << 6, 0xc0); 154 if (ret) 155 goto error; 156 157 ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08); 158 if (ret) 159 goto error; 160 161 ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01); 162 if (ret) 163 goto error; 164 165 return ret; 166 error: 167 dev_dbg(&client->dev, "failed=%d\n", ret); 168 return ret; 169 170 } 171 172 int cxd2820r_get_frontend_t2(struct dvb_frontend *fe, 173 struct dtv_frontend_properties *c) 174 { 175 struct cxd2820r_priv *priv = fe->demodulator_priv; 176 struct i2c_client *client = priv->client[0]; 177 int ret; 178 u8 buf[2]; 179 180 dev_dbg(&client->dev, "\n"); 181 182 ret = cxd2820r_rd_regs(priv, 0x0205c, buf, 2); 183 if (ret) 184 goto error; 185 186 switch ((buf[0] >> 0) & 0x07) { 187 case 0: 188 c->transmission_mode = TRANSMISSION_MODE_2K; 189 break; 190 case 1: 191 c->transmission_mode = TRANSMISSION_MODE_8K; 192 break; 193 case 2: 194 c->transmission_mode = TRANSMISSION_MODE_4K; 195 break; 196 case 3: 197 c->transmission_mode = TRANSMISSION_MODE_1K; 198 break; 199 case 4: 200 c->transmission_mode = TRANSMISSION_MODE_16K; 201 break; 202 case 5: 203 c->transmission_mode = TRANSMISSION_MODE_32K; 204 break; 205 } 206 207 switch ((buf[1] >> 4) & 0x07) { 208 case 0: 209 c->guard_interval = GUARD_INTERVAL_1_32; 210 break; 211 case 1: 212 c->guard_interval = GUARD_INTERVAL_1_16; 213 break; 214 case 2: 215 c->guard_interval = GUARD_INTERVAL_1_8; 216 break; 217 case 3: 218 c->guard_interval = GUARD_INTERVAL_1_4; 219 break; 220 case 4: 221 c->guard_interval = GUARD_INTERVAL_1_128; 222 break; 223 case 5: 224 c->guard_interval = GUARD_INTERVAL_19_128; 225 break; 226 case 6: 227 c->guard_interval = GUARD_INTERVAL_19_256; 228 break; 229 } 230 231 ret = cxd2820r_rd_regs(priv, 0x0225b, buf, 2); 232 if (ret) 233 goto error; 234 235 switch ((buf[0] >> 0) & 0x07) { 236 case 0: 237 c->fec_inner = FEC_1_2; 238 break; 239 case 1: 240 c->fec_inner = FEC_3_5; 241 break; 242 case 2: 243 c->fec_inner = FEC_2_3; 244 break; 245 case 3: 246 c->fec_inner = FEC_3_4; 247 break; 248 case 4: 249 c->fec_inner = FEC_4_5; 250 break; 251 case 5: 252 c->fec_inner = FEC_5_6; 253 break; 254 } 255 256 switch ((buf[1] >> 0) & 0x07) { 257 case 0: 258 c->modulation = QPSK; 259 break; 260 case 1: 261 c->modulation = QAM_16; 262 break; 263 case 2: 264 c->modulation = QAM_64; 265 break; 266 case 3: 267 c->modulation = QAM_256; 268 break; 269 } 270 271 ret = cxd2820r_rd_reg(priv, 0x020b5, &buf[0]); 272 if (ret) 273 goto error; 274 275 switch ((buf[0] >> 4) & 0x01) { 276 case 0: 277 c->inversion = INVERSION_OFF; 278 break; 279 case 1: 280 c->inversion = INVERSION_ON; 281 break; 282 } 283 284 return ret; 285 error: 286 dev_dbg(&client->dev, "failed=%d\n", ret); 287 return ret; 288 } 289 290 int cxd2820r_read_status_t2(struct dvb_frontend *fe, enum fe_status *status) 291 { 292 struct cxd2820r_priv *priv = fe->demodulator_priv; 293 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 294 struct i2c_client *client = priv->client[0]; 295 int ret; 296 unsigned int utmp, utmp1, utmp2; 297 u8 buf[4]; 298 299 /* Lock detection */ 300 ret = cxd2820r_rd_reg(priv, 0x02010 , &buf[0]); 301 if (ret) 302 goto error; 303 304 utmp1 = (buf[0] >> 0) & 0x07; 305 utmp2 = (buf[0] >> 5) & 0x01; 306 307 if (utmp1 == 6 && utmp2 == 1) { 308 *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | 309 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; 310 } else if (utmp1 == 6 || utmp2 == 1) { 311 *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | 312 FE_HAS_VITERBI | FE_HAS_SYNC; 313 } else { 314 *status = 0; 315 } 316 317 dev_dbg(&client->dev, "status=%02x raw=%*ph sync=%u ts=%u\n", 318 *status, 1, buf, utmp1, utmp2); 319 320 /* Signal strength */ 321 if (*status & FE_HAS_SIGNAL) { 322 unsigned int strength; 323 324 ret = cxd2820r_rd_regs(priv, 0x02026, buf, 2); 325 if (ret) 326 goto error; 327 328 utmp = buf[0] << 8 | buf[1] << 0; 329 utmp = ~utmp & 0x0fff; 330 /* Scale value to 0x0000-0xffff */ 331 strength = utmp << 4 | utmp >> 8; 332 333 c->strength.len = 1; 334 c->strength.stat[0].scale = FE_SCALE_RELATIVE; 335 c->strength.stat[0].uvalue = strength; 336 } else { 337 c->strength.len = 1; 338 c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 339 } 340 341 /* CNR */ 342 if (*status & FE_HAS_VITERBI) { 343 unsigned int cnr; 344 345 ret = cxd2820r_rd_regs(priv, 0x02028, buf, 2); 346 if (ret) 347 goto error; 348 349 utmp = buf[0] << 8 | buf[1] << 0; 350 utmp = utmp & 0x0fff; 351 #define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */ 352 if (utmp) 353 cnr = div_u64((u64)(intlog10(utmp) 354 - CXD2820R_LOG10_8_24) * 10000, 355 (1 << 24)); 356 else 357 cnr = 0; 358 359 c->cnr.len = 1; 360 c->cnr.stat[0].scale = FE_SCALE_DECIBEL; 361 c->cnr.stat[0].svalue = cnr; 362 } else { 363 c->cnr.len = 1; 364 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 365 } 366 367 /* BER */ 368 if (*status & FE_HAS_SYNC) { 369 unsigned int post_bit_error; 370 371 ret = cxd2820r_rd_regs(priv, 0x02039, buf, 4); 372 if (ret) 373 goto error; 374 375 if ((buf[0] >> 4) & 0x01) { 376 post_bit_error = buf[0] << 24 | buf[1] << 16 | 377 buf[2] << 8 | buf[3] << 0; 378 post_bit_error &= 0x0fffffff; 379 } else { 380 post_bit_error = 0; 381 } 382 383 priv->post_bit_error += post_bit_error; 384 385 c->post_bit_error.len = 1; 386 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 387 c->post_bit_error.stat[0].uvalue = priv->post_bit_error; 388 } else { 389 c->post_bit_error.len = 1; 390 c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 391 } 392 393 return ret; 394 error: 395 dev_dbg(&client->dev, "failed=%d\n", ret); 396 return ret; 397 } 398 399 int cxd2820r_sleep_t2(struct dvb_frontend *fe) 400 { 401 struct cxd2820r_priv *priv = fe->demodulator_priv; 402 struct i2c_client *client = priv->client[0]; 403 int ret, i; 404 struct reg_val_mask tab[] = { 405 { 0x000ff, 0x1f, 0xff }, 406 { 0x00085, 0x00, 0xff }, 407 { 0x00088, 0x01, 0xff }, 408 { 0x02069, 0x00, 0xff }, 409 { 0x00081, 0x00, 0xff }, 410 { 0x00080, 0x00, 0xff }, 411 }; 412 413 dev_dbg(&client->dev, "\n"); 414 415 for (i = 0; i < ARRAY_SIZE(tab); i++) { 416 ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val, 417 tab[i].mask); 418 if (ret) 419 goto error; 420 } 421 422 priv->delivery_system = SYS_UNDEFINED; 423 424 return ret; 425 error: 426 dev_dbg(&client->dev, "failed=%d\n", ret); 427 return ret; 428 } 429 430 int cxd2820r_get_tune_settings_t2(struct dvb_frontend *fe, 431 struct dvb_frontend_tune_settings *s) 432 { 433 s->min_delay_ms = 1500; 434 s->step_size = fe->ops.info.frequency_stepsize * 2; 435 s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; 436 437 return 0; 438 } 439