Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.15-rc9 341 lines 7.3 kB view raw
1/* 2 * E3C EC100 demodulator driver 3 * 4 * Copyright (C) 2009 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 */ 17 18#include "dvb_frontend.h" 19#include "ec100.h" 20 21struct ec100_state { 22 struct i2c_adapter *i2c; 23 struct dvb_frontend frontend; 24 struct ec100_config config; 25 26 u16 ber; 27}; 28 29/* write single register */ 30static int ec100_write_reg(struct ec100_state *state, u8 reg, u8 val) 31{ 32 int ret; 33 u8 buf[2] = {reg, val}; 34 struct i2c_msg msg[1] = { 35 { 36 .addr = state->config.demod_address, 37 .flags = 0, 38 .len = sizeof(buf), 39 .buf = buf, 40 } 41 }; 42 43 ret = i2c_transfer(state->i2c, msg, 1); 44 if (ret == 1) { 45 ret = 0; 46 } else { 47 dev_warn(&state->i2c->dev, "%s: i2c wr failed=%d reg=%02x\n", 48 KBUILD_MODNAME, ret, reg); 49 ret = -EREMOTEIO; 50 } 51 52 return ret; 53} 54 55/* read single register */ 56static int ec100_read_reg(struct ec100_state *state, u8 reg, u8 *val) 57{ 58 int ret; 59 struct i2c_msg msg[2] = { 60 { 61 .addr = state->config.demod_address, 62 .flags = 0, 63 .len = 1, 64 .buf = &reg 65 }, { 66 .addr = state->config.demod_address, 67 .flags = I2C_M_RD, 68 .len = 1, 69 .buf = val 70 } 71 }; 72 73 ret = i2c_transfer(state->i2c, msg, 2); 74 if (ret == 2) { 75 ret = 0; 76 } else { 77 dev_warn(&state->i2c->dev, "%s: i2c rd failed=%d reg=%02x\n", 78 KBUILD_MODNAME, ret, reg); 79 ret = -EREMOTEIO; 80 } 81 82 return ret; 83} 84 85static int ec100_set_frontend(struct dvb_frontend *fe) 86{ 87 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 88 struct ec100_state *state = fe->demodulator_priv; 89 int ret; 90 u8 tmp, tmp2; 91 92 dev_dbg(&state->i2c->dev, "%s: frequency=%d bandwidth_hz=%d\n", 93 __func__, c->frequency, c->bandwidth_hz); 94 95 /* program tuner */ 96 if (fe->ops.tuner_ops.set_params) 97 fe->ops.tuner_ops.set_params(fe); 98 99 ret = ec100_write_reg(state, 0x04, 0x06); 100 if (ret) 101 goto error; 102 ret = ec100_write_reg(state, 0x67, 0x58); 103 if (ret) 104 goto error; 105 ret = ec100_write_reg(state, 0x05, 0x18); 106 if (ret) 107 goto error; 108 109 /* reg/bw | 6 | 7 | 8 110 -------+------+------+------ 111 A 0x1b | 0xa1 | 0xe7 | 0x2c 112 A 0x1c | 0x55 | 0x63 | 0x72 113 -------+------+------+------ 114 B 0x1b | 0xb7 | 0x00 | 0x49 115 B 0x1c | 0x55 | 0x64 | 0x72 */ 116 117 switch (c->bandwidth_hz) { 118 case 6000000: 119 tmp = 0xb7; 120 tmp2 = 0x55; 121 break; 122 case 7000000: 123 tmp = 0x00; 124 tmp2 = 0x64; 125 break; 126 case 8000000: 127 default: 128 tmp = 0x49; 129 tmp2 = 0x72; 130 } 131 132 ret = ec100_write_reg(state, 0x1b, tmp); 133 if (ret) 134 goto error; 135 ret = ec100_write_reg(state, 0x1c, tmp2); 136 if (ret) 137 goto error; 138 139 ret = ec100_write_reg(state, 0x0c, 0xbb); /* if freq */ 140 if (ret) 141 goto error; 142 ret = ec100_write_reg(state, 0x0d, 0x31); /* if freq */ 143 if (ret) 144 goto error; 145 146 ret = ec100_write_reg(state, 0x08, 0x24); 147 if (ret) 148 goto error; 149 150 ret = ec100_write_reg(state, 0x00, 0x00); /* go */ 151 if (ret) 152 goto error; 153 ret = ec100_write_reg(state, 0x00, 0x20); /* go */ 154 if (ret) 155 goto error; 156 157 return ret; 158error: 159 dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); 160 return ret; 161} 162 163static int ec100_get_tune_settings(struct dvb_frontend *fe, 164 struct dvb_frontend_tune_settings *fesettings) 165{ 166 fesettings->min_delay_ms = 300; 167 fesettings->step_size = 0; 168 fesettings->max_drift = 0; 169 170 return 0; 171} 172 173static int ec100_read_status(struct dvb_frontend *fe, enum fe_status *status) 174{ 175 struct ec100_state *state = fe->demodulator_priv; 176 int ret; 177 u8 tmp; 178 *status = 0; 179 180 ret = ec100_read_reg(state, 0x42, &tmp); 181 if (ret) 182 goto error; 183 184 if (tmp & 0x80) { 185 /* bit7 set - have lock */ 186 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | 187 FE_HAS_SYNC | FE_HAS_LOCK; 188 } else { 189 ret = ec100_read_reg(state, 0x01, &tmp); 190 if (ret) 191 goto error; 192 193 if (tmp & 0x10) { 194 /* bit4 set - have signal */ 195 *status |= FE_HAS_SIGNAL; 196 if (!(tmp & 0x01)) { 197 /* bit0 clear - have ~valid signal */ 198 *status |= FE_HAS_CARRIER | FE_HAS_VITERBI; 199 } 200 } 201 } 202 203 return ret; 204error: 205 dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); 206 return ret; 207} 208 209static int ec100_read_ber(struct dvb_frontend *fe, u32 *ber) 210{ 211 struct ec100_state *state = fe->demodulator_priv; 212 int ret; 213 u8 tmp, tmp2; 214 u16 ber2; 215 216 *ber = 0; 217 218 ret = ec100_read_reg(state, 0x65, &tmp); 219 if (ret) 220 goto error; 221 ret = ec100_read_reg(state, 0x66, &tmp2); 222 if (ret) 223 goto error; 224 225 ber2 = (tmp2 << 8) | tmp; 226 227 /* if counter overflow or clear */ 228 if (ber2 < state->ber) 229 *ber = ber2; 230 else 231 *ber = ber2 - state->ber; 232 233 state->ber = ber2; 234 235 return ret; 236error: 237 dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); 238 return ret; 239} 240 241static int ec100_read_signal_strength(struct dvb_frontend *fe, u16 *strength) 242{ 243 struct ec100_state *state = fe->demodulator_priv; 244 int ret; 245 u8 tmp; 246 247 ret = ec100_read_reg(state, 0x24, &tmp); 248 if (ret) { 249 *strength = 0; 250 goto error; 251 } 252 253 *strength = ((tmp << 8) | tmp); 254 255 return ret; 256error: 257 dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); 258 return ret; 259} 260 261static int ec100_read_snr(struct dvb_frontend *fe, u16 *snr) 262{ 263 *snr = 0; 264 return 0; 265} 266 267static int ec100_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 268{ 269 *ucblocks = 0; 270 return 0; 271} 272 273static void ec100_release(struct dvb_frontend *fe) 274{ 275 struct ec100_state *state = fe->demodulator_priv; 276 kfree(state); 277} 278 279static const struct dvb_frontend_ops ec100_ops; 280 281struct dvb_frontend *ec100_attach(const struct ec100_config *config, 282 struct i2c_adapter *i2c) 283{ 284 int ret; 285 struct ec100_state *state = NULL; 286 u8 tmp; 287 288 /* allocate memory for the internal state */ 289 state = kzalloc(sizeof(struct ec100_state), GFP_KERNEL); 290 if (state == NULL) 291 goto error; 292 293 /* setup the state */ 294 state->i2c = i2c; 295 memcpy(&state->config, config, sizeof(struct ec100_config)); 296 297 /* check if the demod is there */ 298 ret = ec100_read_reg(state, 0x33, &tmp); 299 if (ret || tmp != 0x0b) 300 goto error; 301 302 /* create dvb_frontend */ 303 memcpy(&state->frontend.ops, &ec100_ops, 304 sizeof(struct dvb_frontend_ops)); 305 state->frontend.demodulator_priv = state; 306 307 return &state->frontend; 308error: 309 kfree(state); 310 return NULL; 311} 312EXPORT_SYMBOL(ec100_attach); 313 314static const struct dvb_frontend_ops ec100_ops = { 315 .delsys = { SYS_DVBT }, 316 .info = { 317 .name = "E3C EC100 DVB-T", 318 .caps = 319 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 320 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | 321 FE_CAN_QPSK | FE_CAN_QAM_16 | 322 FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | 323 FE_CAN_TRANSMISSION_MODE_AUTO | 324 FE_CAN_GUARD_INTERVAL_AUTO | 325 FE_CAN_HIERARCHY_AUTO | 326 FE_CAN_MUTE_TS 327 }, 328 329 .release = ec100_release, 330 .set_frontend = ec100_set_frontend, 331 .get_tune_settings = ec100_get_tune_settings, 332 .read_status = ec100_read_status, 333 .read_ber = ec100_read_ber, 334 .read_signal_strength = ec100_read_signal_strength, 335 .read_snr = ec100_read_snr, 336 .read_ucblocks = ec100_read_ucblocks, 337}; 338 339MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 340MODULE_DESCRIPTION("E3C EC100 DVB-T demodulator driver"); 341MODULE_LICENSE("GPL");