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_c(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; 29 u8 buf[2]; 30 u32 if_freq; 31 u16 if_ctl; 32 u64 num; 33 struct reg_val_mask tab[] = { 34 { 0x00080, 0x01, 0xff }, 35 { 0x00081, 0x05, 0xff }, 36 { 0x00085, 0x07, 0xff }, 37 { 0x00088, 0x01, 0xff }, 38 39 { 0x00082, 0x20, 0x60 }, 40 { 0x1016a, 0x48, 0xff }, 41 { 0x100a5, 0x00, 0x01 }, 42 { 0x10020, 0x06, 0x07 }, 43 { 0x10059, 0x50, 0xff }, 44 { 0x10087, 0x0c, 0x3c }, 45 { 0x1008b, 0x07, 0xff }, 46 { 0x1001f, priv->cfg.if_agc_polarity << 7, 0x80 }, 47 { 0x10070, priv->cfg.ts_mode, 0xff }, 48 }; 49 50 dev_dbg(&priv->i2c->dev, "%s: frequency=%d symbol_rate=%d\n", __func__, 51 c->frequency, c->symbol_rate); 52 53 /* program tuner */ 54 if (fe->ops.tuner_ops.set_params) 55 fe->ops.tuner_ops.set_params(fe); 56 57 if (priv->delivery_system != SYS_DVBC_ANNEX_A) { 58 for (i = 0; i < ARRAY_SIZE(tab); i++) { 59 ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, 60 tab[i].val, tab[i].mask); 61 if (ret) 62 goto error; 63 } 64 } 65 66 priv->delivery_system = SYS_DVBC_ANNEX_A; 67 priv->ber_running = 0; /* tune stops BER counter */ 68 69 /* program IF frequency */ 70 if (fe->ops.tuner_ops.get_if_frequency) { 71 ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq); 72 if (ret) 73 goto error; 74 } else 75 if_freq = 0; 76 77 dev_dbg(&priv->i2c->dev, "%s: if_freq=%d\n", __func__, if_freq); 78 79 num = if_freq / 1000; /* Hz => kHz */ 80 num *= 0x4000; 81 if_ctl = cxd2820r_div_u64_round_closest(num, 41000); 82 buf[0] = (if_ctl >> 8) & 0x3f; 83 buf[1] = (if_ctl >> 0) & 0xff; 84 85 ret = cxd2820r_wr_regs(priv, 0x10042, buf, 2); 86 if (ret) 87 goto error; 88 89 ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08); 90 if (ret) 91 goto error; 92 93 ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01); 94 if (ret) 95 goto error; 96 97 return ret; 98 error: 99 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 100 return ret; 101 } 102 103 int cxd2820r_get_frontend_c(struct dvb_frontend *fe) 104 { 105 struct cxd2820r_priv *priv = fe->demodulator_priv; 106 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 107 int ret; 108 u8 buf[2]; 109 110 ret = cxd2820r_rd_regs(priv, 0x1001a, buf, 2); 111 if (ret) 112 goto error; 113 114 c->symbol_rate = 2500 * ((buf[0] & 0x0f) << 8 | buf[1]); 115 116 ret = cxd2820r_rd_reg(priv, 0x10019, &buf[0]); 117 if (ret) 118 goto error; 119 120 switch ((buf[0] >> 0) & 0x07) { 121 case 0: 122 c->modulation = QAM_16; 123 break; 124 case 1: 125 c->modulation = QAM_32; 126 break; 127 case 2: 128 c->modulation = QAM_64; 129 break; 130 case 3: 131 c->modulation = QAM_128; 132 break; 133 case 4: 134 c->modulation = QAM_256; 135 break; 136 } 137 138 switch ((buf[0] >> 7) & 0x01) { 139 case 0: 140 c->inversion = INVERSION_OFF; 141 break; 142 case 1: 143 c->inversion = INVERSION_ON; 144 break; 145 } 146 147 return ret; 148 error: 149 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 150 return ret; 151 } 152 153 int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber) 154 { 155 struct cxd2820r_priv *priv = fe->demodulator_priv; 156 int ret; 157 u8 buf[3], start_ber = 0; 158 *ber = 0; 159 160 if (priv->ber_running) { 161 ret = cxd2820r_rd_regs(priv, 0x10076, buf, sizeof(buf)); 162 if (ret) 163 goto error; 164 165 if ((buf[2] >> 7) & 0x01 || (buf[2] >> 4) & 0x01) { 166 *ber = (buf[2] & 0x0f) << 16 | buf[1] << 8 | buf[0]; 167 start_ber = 1; 168 } 169 } else { 170 priv->ber_running = 1; 171 start_ber = 1; 172 } 173 174 if (start_ber) { 175 /* (re)start BER */ 176 ret = cxd2820r_wr_reg(priv, 0x10079, 0x01); 177 if (ret) 178 goto error; 179 } 180 181 return ret; 182 error: 183 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 184 return ret; 185 } 186 187 int cxd2820r_read_signal_strength_c(struct dvb_frontend *fe, 188 u16 *strength) 189 { 190 struct cxd2820r_priv *priv = fe->demodulator_priv; 191 int ret; 192 u8 buf[2]; 193 u16 tmp; 194 195 ret = cxd2820r_rd_regs(priv, 0x10049, buf, sizeof(buf)); 196 if (ret) 197 goto error; 198 199 tmp = (buf[0] & 0x03) << 8 | buf[1]; 200 tmp = (~tmp & 0x03ff); 201 202 if (tmp == 512) 203 /* ~no signal */ 204 tmp = 0; 205 else if (tmp > 350) 206 tmp = 350; 207 208 /* scale value to 0x0000-0xffff */ 209 *strength = tmp * 0xffff / (350-0); 210 211 return ret; 212 error: 213 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 214 return ret; 215 } 216 217 int cxd2820r_read_snr_c(struct dvb_frontend *fe, u16 *snr) 218 { 219 struct cxd2820r_priv *priv = fe->demodulator_priv; 220 int ret; 221 u8 tmp; 222 unsigned int A, B; 223 /* report SNR in dB * 10 */ 224 225 ret = cxd2820r_rd_reg(priv, 0x10019, &tmp); 226 if (ret) 227 goto error; 228 229 if (((tmp >> 0) & 0x03) % 2) { 230 A = 875; 231 B = 650; 232 } else { 233 A = 950; 234 B = 760; 235 } 236 237 ret = cxd2820r_rd_reg(priv, 0x1004d, &tmp); 238 if (ret) 239 goto error; 240 241 #define CXD2820R_LOG2_E_24 24204406 /* log2(e) << 24 */ 242 if (tmp) 243 *snr = A * (intlog2(B / tmp) >> 5) / (CXD2820R_LOG2_E_24 >> 5) 244 / 10; 245 else 246 *snr = 0; 247 248 return ret; 249 error: 250 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 251 return ret; 252 } 253 254 int cxd2820r_read_ucblocks_c(struct dvb_frontend *fe, u32 *ucblocks) 255 { 256 *ucblocks = 0; 257 /* no way to read ? */ 258 return 0; 259 } 260 261 int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status) 262 { 263 struct cxd2820r_priv *priv = fe->demodulator_priv; 264 int ret; 265 u8 buf[2]; 266 *status = 0; 267 268 ret = cxd2820r_rd_regs(priv, 0x10088, buf, sizeof(buf)); 269 if (ret) 270 goto error; 271 272 if (((buf[0] >> 0) & 0x01) == 1) { 273 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | 274 FE_HAS_VITERBI | FE_HAS_SYNC; 275 276 if (((buf[1] >> 3) & 0x01) == 1) { 277 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | 278 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; 279 } 280 } 281 282 dev_dbg(&priv->i2c->dev, "%s: lock=%02x %02x\n", __func__, buf[0], 283 buf[1]); 284 285 return ret; 286 error: 287 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 288 return ret; 289 } 290 291 int cxd2820r_init_c(struct dvb_frontend *fe) 292 { 293 struct cxd2820r_priv *priv = fe->demodulator_priv; 294 int ret; 295 296 ret = cxd2820r_wr_reg(priv, 0x00085, 0x07); 297 if (ret) 298 goto error; 299 300 return ret; 301 error: 302 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 303 return ret; 304 } 305 306 int cxd2820r_sleep_c(struct dvb_frontend *fe) 307 { 308 struct cxd2820r_priv *priv = fe->demodulator_priv; 309 int ret, i; 310 struct reg_val_mask tab[] = { 311 { 0x000ff, 0x1f, 0xff }, 312 { 0x00085, 0x00, 0xff }, 313 { 0x00088, 0x01, 0xff }, 314 { 0x00081, 0x00, 0xff }, 315 { 0x00080, 0x00, 0xff }, 316 }; 317 318 dev_dbg(&priv->i2c->dev, "%s\n", __func__); 319 320 priv->delivery_system = SYS_UNDEFINED; 321 322 for (i = 0; i < ARRAY_SIZE(tab); i++) { 323 ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val, 324 tab[i].mask); 325 if (ret) 326 goto error; 327 } 328 329 return ret; 330 error: 331 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 332 return ret; 333 } 334 335 int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe, 336 struct dvb_frontend_tune_settings *s) 337 { 338 s->min_delay_ms = 500; 339 s->step_size = 0; /* no zigzag */ 340 s->max_drift = 0; 341 342 return 0; 343 } 344