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 dtv_frontend_properties *c = &fe->dtv_property_cache; 28 int ret, i, bw_i; 29 u32 if_freq, if_ctl; 30 u64 num; 31 u8 buf[3], bw_param; 32 u8 bw_params1[][5] = { 33 { 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */ 34 { 0x14, 0x80, 0x00, 0x00, 0x00 }, /* 7 MHz */ 35 { 0x11, 0xf0, 0x00, 0x00, 0x00 }, /* 8 MHz */ 36 }; 37 u8 bw_params2[][2] = { 38 { 0x1f, 0xdc }, /* 6 MHz */ 39 { 0x12, 0xf8 }, /* 7 MHz */ 40 { 0x01, 0xe0 }, /* 8 MHz */ 41 }; 42 struct reg_val_mask tab[] = { 43 { 0x00080, 0x00, 0xff }, 44 { 0x00081, 0x03, 0xff }, 45 { 0x00085, 0x07, 0xff }, 46 { 0x00088, 0x01, 0xff }, 47 48 { 0x00070, priv->cfg.ts_mode, 0xff }, 49 { 0x000cb, priv->cfg.if_agc_polarity << 6, 0x40 }, 50 { 0x000a5, 0x00, 0x01 }, 51 { 0x00082, 0x20, 0x60 }, 52 { 0x000c2, 0xc3, 0xff }, 53 { 0x0016a, 0x50, 0xff }, 54 { 0x00427, 0x41, 0xff }, 55 }; 56 57 dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz); 58 59 switch (c->bandwidth_hz) { 60 case 6000000: 61 bw_i = 0; 62 bw_param = 2; 63 break; 64 case 7000000: 65 bw_i = 1; 66 bw_param = 1; 67 break; 68 case 8000000: 69 bw_i = 2; 70 bw_param = 0; 71 break; 72 default: 73 return -EINVAL; 74 } 75 76 /* update GPIOs */ 77 ret = cxd2820r_gpio(fe); 78 if (ret) 79 goto error; 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 for (i = 0; i < ARRAY_SIZE(tab); i++) { 87 ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, 88 tab[i].val, tab[i].mask); 89 if (ret) 90 goto error; 91 } 92 } 93 94 priv->delivery_system = SYS_DVBT; 95 priv->ber_running = 0; /* tune stops BER counter */ 96 97 /* program IF frequency */ 98 if (fe->ops.tuner_ops.get_if_frequency) { 99 ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq); 100 if (ret) 101 goto error; 102 } else 103 if_freq = 0; 104 105 dbg("%s: if_freq=%d", __func__, if_freq); 106 107 num = if_freq / 1000; /* Hz => kHz */ 108 num *= 0x1000000; 109 if_ctl = cxd2820r_div_u64_round_closest(num, 41000); 110 buf[0] = ((if_ctl >> 16) & 0xff); 111 buf[1] = ((if_ctl >> 8) & 0xff); 112 buf[2] = ((if_ctl >> 0) & 0xff); 113 114 ret = cxd2820r_wr_regs(priv, 0x000b6, buf, 3); 115 if (ret) 116 goto error; 117 118 ret = cxd2820r_wr_regs(priv, 0x0009f, bw_params1[bw_i], 5); 119 if (ret) 120 goto error; 121 122 ret = cxd2820r_wr_reg_mask(priv, 0x000d7, bw_param << 6, 0xc0); 123 if (ret) 124 goto error; 125 126 ret = cxd2820r_wr_regs(priv, 0x000d9, bw_params2[bw_i], 2); 127 if (ret) 128 goto error; 129 130 ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08); 131 if (ret) 132 goto error; 133 134 ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01); 135 if (ret) 136 goto error; 137 138 return ret; 139error: 140 dbg("%s: failed:%d", __func__, ret); 141 return ret; 142} 143 144int cxd2820r_get_frontend_t(struct dvb_frontend *fe) 145{ 146 struct cxd2820r_priv *priv = fe->demodulator_priv; 147 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 148 int ret; 149 u8 buf[2]; 150 151 ret = cxd2820r_rd_regs(priv, 0x0002f, buf, sizeof(buf)); 152 if (ret) 153 goto error; 154 155 switch ((buf[0] >> 6) & 0x03) { 156 case 0: 157 c->modulation = QPSK; 158 break; 159 case 1: 160 c->modulation = QAM_16; 161 break; 162 case 2: 163 c->modulation = QAM_64; 164 break; 165 } 166 167 switch ((buf[1] >> 1) & 0x03) { 168 case 0: 169 c->transmission_mode = TRANSMISSION_MODE_2K; 170 break; 171 case 1: 172 c->transmission_mode = TRANSMISSION_MODE_8K; 173 break; 174 } 175 176 switch ((buf[1] >> 3) & 0x03) { 177 case 0: 178 c->guard_interval = GUARD_INTERVAL_1_32; 179 break; 180 case 1: 181 c->guard_interval = GUARD_INTERVAL_1_16; 182 break; 183 case 2: 184 c->guard_interval = GUARD_INTERVAL_1_8; 185 break; 186 case 3: 187 c->guard_interval = GUARD_INTERVAL_1_4; 188 break; 189 } 190 191 switch ((buf[0] >> 3) & 0x07) { 192 case 0: 193 c->hierarchy = HIERARCHY_NONE; 194 break; 195 case 1: 196 c->hierarchy = HIERARCHY_1; 197 break; 198 case 2: 199 c->hierarchy = HIERARCHY_2; 200 break; 201 case 3: 202 c->hierarchy = HIERARCHY_4; 203 break; 204 } 205 206 switch ((buf[0] >> 0) & 0x07) { 207 case 0: 208 c->code_rate_HP = FEC_1_2; 209 break; 210 case 1: 211 c->code_rate_HP = FEC_2_3; 212 break; 213 case 2: 214 c->code_rate_HP = FEC_3_4; 215 break; 216 case 3: 217 c->code_rate_HP = FEC_5_6; 218 break; 219 case 4: 220 c->code_rate_HP = FEC_7_8; 221 break; 222 } 223 224 switch ((buf[1] >> 5) & 0x07) { 225 case 0: 226 c->code_rate_LP = FEC_1_2; 227 break; 228 case 1: 229 c->code_rate_LP = FEC_2_3; 230 break; 231 case 2: 232 c->code_rate_LP = FEC_3_4; 233 break; 234 case 3: 235 c->code_rate_LP = FEC_5_6; 236 break; 237 case 4: 238 c->code_rate_LP = FEC_7_8; 239 break; 240 } 241 242 ret = cxd2820r_rd_reg(priv, 0x007c6, &buf[0]); 243 if (ret) 244 goto error; 245 246 switch ((buf[0] >> 0) & 0x01) { 247 case 0: 248 c->inversion = INVERSION_OFF; 249 break; 250 case 1: 251 c->inversion = INVERSION_ON; 252 break; 253 } 254 255 return ret; 256error: 257 dbg("%s: failed:%d", __func__, ret); 258 return ret; 259} 260 261int cxd2820r_read_ber_t(struct dvb_frontend *fe, u32 *ber) 262{ 263 struct cxd2820r_priv *priv = fe->demodulator_priv; 264 int ret; 265 u8 buf[3], start_ber = 0; 266 *ber = 0; 267 268 if (priv->ber_running) { 269 ret = cxd2820r_rd_regs(priv, 0x00076, buf, sizeof(buf)); 270 if (ret) 271 goto error; 272 273 if ((buf[2] >> 7) & 0x01 || (buf[2] >> 4) & 0x01) { 274 *ber = (buf[2] & 0x0f) << 16 | buf[1] << 8 | buf[0]; 275 start_ber = 1; 276 } 277 } else { 278 priv->ber_running = 1; 279 start_ber = 1; 280 } 281 282 if (start_ber) { 283 /* (re)start BER */ 284 ret = cxd2820r_wr_reg(priv, 0x00079, 0x01); 285 if (ret) 286 goto error; 287 } 288 289 return ret; 290error: 291 dbg("%s: failed:%d", __func__, ret); 292 return ret; 293} 294 295int cxd2820r_read_signal_strength_t(struct dvb_frontend *fe, 296 u16 *strength) 297{ 298 struct cxd2820r_priv *priv = fe->demodulator_priv; 299 int ret; 300 u8 buf[2]; 301 u16 tmp; 302 303 ret = cxd2820r_rd_regs(priv, 0x00026, buf, sizeof(buf)); 304 if (ret) 305 goto error; 306 307 tmp = (buf[0] & 0x0f) << 8 | buf[1]; 308 tmp = ~tmp & 0x0fff; 309 310 /* scale value to 0x0000-0xffff from 0x0000-0x0fff */ 311 *strength = tmp * 0xffff / 0x0fff; 312 313 return ret; 314error: 315 dbg("%s: failed:%d", __func__, ret); 316 return ret; 317} 318 319int cxd2820r_read_snr_t(struct dvb_frontend *fe, u16 *snr) 320{ 321 struct cxd2820r_priv *priv = fe->demodulator_priv; 322 int ret; 323 u8 buf[2]; 324 u16 tmp; 325 /* report SNR in dB * 10 */ 326 327 ret = cxd2820r_rd_regs(priv, 0x00028, buf, sizeof(buf)); 328 if (ret) 329 goto error; 330 331 tmp = (buf[0] & 0x1f) << 8 | buf[1]; 332 #define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */ 333 if (tmp) 334 *snr = (intlog10(tmp) - CXD2820R_LOG10_8_24) / ((1 << 24) 335 / 100); 336 else 337 *snr = 0; 338 339 dbg("%s: dBx10=%d val=%04x", __func__, *snr, tmp); 340 341 return ret; 342error: 343 dbg("%s: failed:%d", __func__, ret); 344 return ret; 345} 346 347int cxd2820r_read_ucblocks_t(struct dvb_frontend *fe, u32 *ucblocks) 348{ 349 *ucblocks = 0; 350 /* no way to read ? */ 351 return 0; 352} 353 354int cxd2820r_read_status_t(struct dvb_frontend *fe, fe_status_t *status) 355{ 356 struct cxd2820r_priv *priv = fe->demodulator_priv; 357 int ret; 358 u8 buf[4]; 359 *status = 0; 360 361 ret = cxd2820r_rd_reg(priv, 0x00010, &buf[0]); 362 if (ret) 363 goto error; 364 365 if ((buf[0] & 0x07) == 6) { 366 ret = cxd2820r_rd_reg(priv, 0x00073, &buf[1]); 367 if (ret) 368 goto error; 369 370 if (((buf[1] >> 3) & 0x01) == 1) { 371 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | 372 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; 373 } else { 374 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | 375 FE_HAS_VITERBI | FE_HAS_SYNC; 376 } 377 } else { 378 ret = cxd2820r_rd_reg(priv, 0x00014, &buf[2]); 379 if (ret) 380 goto error; 381 382 if ((buf[2] & 0x0f) >= 4) { 383 ret = cxd2820r_rd_reg(priv, 0x00a14, &buf[3]); 384 if (ret) 385 goto error; 386 387 if (((buf[3] >> 4) & 0x01) == 1) 388 *status |= FE_HAS_SIGNAL; 389 } 390 } 391 392 dbg("%s: lock=%02x %02x %02x %02x", __func__, 393 buf[0], buf[1], buf[2], buf[3]); 394 395 return ret; 396error: 397 dbg("%s: failed:%d", __func__, ret); 398 return ret; 399} 400 401int cxd2820r_init_t(struct dvb_frontend *fe) 402{ 403 struct cxd2820r_priv *priv = fe->demodulator_priv; 404 int ret; 405 406 ret = cxd2820r_wr_reg(priv, 0x00085, 0x07); 407 if (ret) 408 goto error; 409 410 return ret; 411error: 412 dbg("%s: failed:%d", __func__, ret); 413 return ret; 414} 415 416int cxd2820r_sleep_t(struct dvb_frontend *fe) 417{ 418 struct cxd2820r_priv *priv = fe->demodulator_priv; 419 int ret, i; 420 struct reg_val_mask tab[] = { 421 { 0x000ff, 0x1f, 0xff }, 422 { 0x00085, 0x00, 0xff }, 423 { 0x00088, 0x01, 0xff }, 424 { 0x00081, 0x00, 0xff }, 425 { 0x00080, 0x00, 0xff }, 426 }; 427 428 dbg("%s", __func__); 429 430 priv->delivery_system = SYS_UNDEFINED; 431 432 for (i = 0; i < ARRAY_SIZE(tab); i++) { 433 ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val, 434 tab[i].mask); 435 if (ret) 436 goto error; 437 } 438 439 return ret; 440error: 441 dbg("%s: failed:%d", __func__, ret); 442 return ret; 443} 444 445int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe, 446 struct dvb_frontend_tune_settings *s) 447{ 448 s->min_delay_ms = 500; 449 s->step_size = fe->ops.info.frequency_stepsize * 2; 450 s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; 451 452 return 0; 453} 454