cxd2820r_c.c (7410B)
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 11int cxd2820r_set_frontend_c(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; 17 unsigned int utmp; 18 u8 buf[2]; 19 u32 if_frequency; 20 struct reg_val_mask tab[] = { 21 { 0x00080, 0x01, 0xff }, 22 { 0x00081, 0x05, 0xff }, 23 { 0x00085, 0x07, 0xff }, 24 { 0x00088, 0x01, 0xff }, 25 26 { 0x00082, 0x20, 0x60 }, 27 { 0x1016a, 0x48, 0xff }, 28 { 0x100a5, 0x00, 0x01 }, 29 { 0x10020, 0x06, 0x07 }, 30 { 0x10059, 0x50, 0xff }, 31 { 0x10087, 0x0c, 0x3c }, 32 { 0x1008b, 0x07, 0xff }, 33 { 0x1001f, priv->if_agc_polarity << 7, 0x80 }, 34 { 0x10070, priv->ts_mode, 0xff }, 35 { 0x10071, !priv->ts_clk_inv << 4, 0x10 }, 36 }; 37 38 dev_dbg(&client->dev, 39 "delivery_system=%d modulation=%d frequency=%u symbol_rate=%u inversion=%d\n", 40 c->delivery_system, c->modulation, c->frequency, 41 c->symbol_rate, c->inversion); 42 43 /* program tuner */ 44 if (fe->ops.tuner_ops.set_params) 45 fe->ops.tuner_ops.set_params(fe); 46 47 if (priv->delivery_system != SYS_DVBC_ANNEX_A) { 48 ret = cxd2820r_wr_reg_val_mask_tab(priv, tab, ARRAY_SIZE(tab)); 49 if (ret) 50 goto error; 51 } 52 53 priv->delivery_system = SYS_DVBC_ANNEX_A; 54 priv->ber_running = false; /* tune stops BER counter */ 55 56 /* program IF frequency */ 57 if (fe->ops.tuner_ops.get_if_frequency) { 58 ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency); 59 if (ret) 60 goto error; 61 dev_dbg(&client->dev, "if_frequency=%u\n", if_frequency); 62 } else { 63 ret = -EINVAL; 64 goto error; 65 } 66 67 utmp = 0x4000 - DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x4000, CXD2820R_CLK); 68 buf[0] = (utmp >> 8) & 0xff; 69 buf[1] = (utmp >> 0) & 0xff; 70 ret = regmap_bulk_write(priv->regmap[1], 0x0042, buf, 2); 71 if (ret) 72 goto error; 73 74 ret = regmap_write(priv->regmap[0], 0x00ff, 0x08); 75 if (ret) 76 goto error; 77 78 ret = regmap_write(priv->regmap[0], 0x00fe, 0x01); 79 if (ret) 80 goto error; 81 82 return ret; 83error: 84 dev_dbg(&client->dev, "failed=%d\n", ret); 85 return ret; 86} 87 88int cxd2820r_get_frontend_c(struct dvb_frontend *fe, 89 struct dtv_frontend_properties *c) 90{ 91 struct cxd2820r_priv *priv = fe->demodulator_priv; 92 struct i2c_client *client = priv->client[0]; 93 int ret; 94 unsigned int utmp; 95 u8 buf[2]; 96 97 dev_dbg(&client->dev, "\n"); 98 99 ret = regmap_bulk_read(priv->regmap[1], 0x001a, buf, 2); 100 if (ret) 101 goto error; 102 103 c->symbol_rate = 2500 * ((buf[0] & 0x0f) << 8 | buf[1]); 104 105 ret = regmap_read(priv->regmap[1], 0x0019, &utmp); 106 if (ret) 107 goto error; 108 109 switch ((utmp >> 0) & 0x07) { 110 case 0: 111 c->modulation = QAM_16; 112 break; 113 case 1: 114 c->modulation = QAM_32; 115 break; 116 case 2: 117 c->modulation = QAM_64; 118 break; 119 case 3: 120 c->modulation = QAM_128; 121 break; 122 case 4: 123 c->modulation = QAM_256; 124 break; 125 } 126 127 switch ((utmp >> 7) & 0x01) { 128 case 0: 129 c->inversion = INVERSION_OFF; 130 break; 131 case 1: 132 c->inversion = INVERSION_ON; 133 break; 134 } 135 136 return ret; 137error: 138 dev_dbg(&client->dev, "failed=%d\n", ret); 139 return ret; 140} 141 142int cxd2820r_read_status_c(struct dvb_frontend *fe, enum fe_status *status) 143{ 144 struct cxd2820r_priv *priv = fe->demodulator_priv; 145 struct i2c_client *client = priv->client[0]; 146 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 147 int ret; 148 unsigned int utmp, utmp1, utmp2; 149 u8 buf[3]; 150 151 /* Lock detection */ 152 ret = regmap_bulk_read(priv->regmap[1], 0x0088, &buf[0], 1); 153 if (ret) 154 goto error; 155 ret = regmap_bulk_read(priv->regmap[1], 0x0073, &buf[1], 1); 156 if (ret) 157 goto error; 158 159 utmp1 = (buf[0] >> 0) & 0x01; 160 utmp2 = (buf[1] >> 3) & 0x01; 161 162 if (utmp1 == 1 && utmp2 == 1) { 163 *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | 164 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; 165 } else if (utmp1 == 1 || utmp2 == 1) { 166 *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | 167 FE_HAS_VITERBI | FE_HAS_SYNC; 168 } else { 169 *status = 0; 170 } 171 172 dev_dbg(&client->dev, "status=%02x raw=%*ph sync=%u ts=%u\n", 173 *status, 2, buf, utmp1, utmp2); 174 175 /* Signal strength */ 176 if (*status & FE_HAS_SIGNAL) { 177 unsigned int strength; 178 179 ret = regmap_bulk_read(priv->regmap[1], 0x0049, buf, 2); 180 if (ret) 181 goto error; 182 183 utmp = buf[0] << 8 | buf[1] << 0; 184 utmp = 511 - sign_extend32(utmp, 9); 185 /* Scale value to 0x0000-0xffff */ 186 strength = utmp << 6 | utmp >> 4; 187 188 c->strength.len = 1; 189 c->strength.stat[0].scale = FE_SCALE_RELATIVE; 190 c->strength.stat[0].uvalue = strength; 191 } else { 192 c->strength.len = 1; 193 c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 194 } 195 196 /* CNR */ 197 if (*status & FE_HAS_VITERBI) { 198 unsigned int cnr, const_a, const_b; 199 200 ret = regmap_read(priv->regmap[1], 0x0019, &utmp); 201 if (ret) 202 goto error; 203 204 if (((utmp >> 0) & 0x03) % 2) { 205 const_a = 8750; 206 const_b = 650; 207 } else { 208 const_a = 9500; 209 const_b = 760; 210 } 211 212 ret = regmap_read(priv->regmap[1], 0x004d, &utmp); 213 if (ret) 214 goto error; 215 216 #define CXD2820R_LOG2_E_24 24204406 /* log2(e) << 24 */ 217 if (utmp) 218 cnr = div_u64((u64)(intlog2(const_b) - intlog2(utmp)) 219 * const_a, CXD2820R_LOG2_E_24); 220 else 221 cnr = 0; 222 223 c->cnr.len = 1; 224 c->cnr.stat[0].scale = FE_SCALE_DECIBEL; 225 c->cnr.stat[0].svalue = cnr; 226 } else { 227 c->cnr.len = 1; 228 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 229 } 230 231 /* BER */ 232 if (*status & FE_HAS_SYNC) { 233 unsigned int post_bit_error; 234 bool start_ber; 235 236 if (priv->ber_running) { 237 ret = regmap_bulk_read(priv->regmap[1], 0x0076, buf, 3); 238 if (ret) 239 goto error; 240 241 if ((buf[2] >> 7) & 0x01) { 242 post_bit_error = buf[2] << 16 | buf[1] << 8 | 243 buf[0] << 0; 244 post_bit_error &= 0x0fffff; 245 start_ber = true; 246 } else { 247 post_bit_error = 0; 248 start_ber = false; 249 } 250 } else { 251 post_bit_error = 0; 252 start_ber = true; 253 } 254 255 if (start_ber) { 256 ret = regmap_write(priv->regmap[1], 0x0079, 0x01); 257 if (ret) 258 goto error; 259 priv->ber_running = true; 260 } 261 262 priv->post_bit_error += post_bit_error; 263 264 c->post_bit_error.len = 1; 265 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 266 c->post_bit_error.stat[0].uvalue = priv->post_bit_error; 267 } else { 268 c->post_bit_error.len = 1; 269 c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 270 } 271 272 return ret; 273error: 274 dev_dbg(&client->dev, "failed=%d\n", ret); 275 return ret; 276} 277 278int cxd2820r_init_c(struct dvb_frontend *fe) 279{ 280 struct cxd2820r_priv *priv = fe->demodulator_priv; 281 struct i2c_client *client = priv->client[0]; 282 int ret; 283 284 dev_dbg(&client->dev, "\n"); 285 286 ret = regmap_write(priv->regmap[0], 0x0085, 0x07); 287 if (ret) 288 goto error; 289 290 return ret; 291error: 292 dev_dbg(&client->dev, "failed=%d\n", ret); 293 return ret; 294} 295 296int cxd2820r_sleep_c(struct dvb_frontend *fe) 297{ 298 struct cxd2820r_priv *priv = fe->demodulator_priv; 299 struct i2c_client *client = priv->client[0]; 300 int ret; 301 static const struct reg_val_mask tab[] = { 302 { 0x000ff, 0x1f, 0xff }, 303 { 0x00085, 0x00, 0xff }, 304 { 0x00088, 0x01, 0xff }, 305 { 0x00081, 0x00, 0xff }, 306 { 0x00080, 0x00, 0xff }, 307 }; 308 309 dev_dbg(&client->dev, "\n"); 310 311 priv->delivery_system = SYS_UNDEFINED; 312 313 ret = cxd2820r_wr_reg_val_mask_tab(priv, tab, ARRAY_SIZE(tab)); 314 if (ret) 315 goto error; 316 317 return ret; 318error: 319 dev_dbg(&client->dev, "failed=%d\n", ret); 320 return ret; 321} 322 323int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe, 324 struct dvb_frontend_tune_settings *s) 325{ 326 s->min_delay_ms = 500; 327 s->step_size = 0; /* no zigzag */ 328 s->max_drift = 0; 329 330 return 0; 331}