0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/delay.h>
0010 #include <linux/errno.h>
0011 #include <linux/init.h>
0012 #include <linux/kernel.h>
0013 #include <linux/module.h>
0014 #include <linux/string.h>
0015 #include <linux/slab.h>
0016 #include <asm/div64.h>
0017
0018 #include <media/dvb_frontend.h>
0019 #include "ves1820.h"
0020
0021
0022
0023 struct ves1820_state {
0024 struct i2c_adapter* i2c;
0025
0026 const struct ves1820_config* config;
0027 struct dvb_frontend frontend;
0028
0029
0030 u8 reg0;
0031 u8 pwm;
0032 };
0033
0034
0035 static int verbose;
0036
0037 static u8 ves1820_inittab[] = {
0038 0x69, 0x6A, 0x93, 0x1A, 0x12, 0x46, 0x26, 0x1A,
0039 0x43, 0x6A, 0xAA, 0xAA, 0x1E, 0x85, 0x43, 0x20,
0040 0xE0, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00,
0041 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0042 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0043 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0044 0x00, 0x00, 0x00, 0x00, 0x40
0045 };
0046
0047 static int ves1820_writereg(struct ves1820_state *state, u8 reg, u8 data)
0048 {
0049 u8 buf[] = { 0x00, reg, data };
0050 struct i2c_msg msg = {.addr = state->config->demod_address,.flags = 0,.buf = buf,.len = 3 };
0051 int ret;
0052
0053 ret = i2c_transfer(state->i2c, &msg, 1);
0054
0055 if (ret != 1)
0056 printk("ves1820: %s(): writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
0057 __func__, reg, data, ret);
0058
0059 return (ret != 1) ? -EREMOTEIO : 0;
0060 }
0061
0062 static u8 ves1820_readreg(struct ves1820_state *state, u8 reg)
0063 {
0064 u8 b0[] = { 0x00, reg };
0065 u8 b1[] = { 0 };
0066 struct i2c_msg msg[] = {
0067 {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = 2},
0068 {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1}
0069 };
0070 int ret;
0071
0072 ret = i2c_transfer(state->i2c, msg, 2);
0073
0074 if (ret != 2)
0075 printk("ves1820: %s(): readreg error (reg == 0x%02x, ret == %i)\n",
0076 __func__, reg, ret);
0077
0078 return b1[0];
0079 }
0080
0081 static int ves1820_setup_reg0(struct ves1820_state *state,
0082 u8 reg0, enum fe_spectral_inversion inversion)
0083 {
0084 reg0 |= state->reg0 & 0x62;
0085
0086 if (INVERSION_ON == inversion) {
0087 if (!state->config->invert) reg0 |= 0x20;
0088 else reg0 &= ~0x20;
0089 } else if (INVERSION_OFF == inversion) {
0090 if (!state->config->invert) reg0 &= ~0x20;
0091 else reg0 |= 0x20;
0092 }
0093
0094 ves1820_writereg(state, 0x00, reg0 & 0xfe);
0095 ves1820_writereg(state, 0x00, reg0 | 0x01);
0096
0097 state->reg0 = reg0;
0098
0099 return 0;
0100 }
0101
0102 static int ves1820_set_symbolrate(struct ves1820_state *state, u32 symbolrate)
0103 {
0104 s32 BDR;
0105 s32 BDRI;
0106 s16 SFIL = 0;
0107 u16 NDEC = 0;
0108 u32 ratio;
0109 u32 fin;
0110 u32 tmp;
0111 u64 fptmp;
0112 u64 fpxin;
0113
0114 if (symbolrate > state->config->xin / 2)
0115 symbolrate = state->config->xin / 2;
0116
0117 if (symbolrate < 500000)
0118 symbolrate = 500000;
0119
0120 if (symbolrate < state->config->xin / 16)
0121 NDEC = 1;
0122 if (symbolrate < state->config->xin / 32)
0123 NDEC = 2;
0124 if (symbolrate < state->config->xin / 64)
0125 NDEC = 3;
0126
0127
0128 fpxin = state->config->xin * 10ULL;
0129 fptmp = fpxin; do_div(fptmp, 123);
0130 if (symbolrate < fptmp)
0131 SFIL = 1;
0132 fptmp = fpxin; do_div(fptmp, 160);
0133 if (symbolrate < fptmp)
0134 SFIL = 0;
0135 fptmp = fpxin; do_div(fptmp, 246);
0136 if (symbolrate < fptmp)
0137 SFIL = 1;
0138 fptmp = fpxin; do_div(fptmp, 320);
0139 if (symbolrate < fptmp)
0140 SFIL = 0;
0141 fptmp = fpxin; do_div(fptmp, 492);
0142 if (symbolrate < fptmp)
0143 SFIL = 1;
0144 fptmp = fpxin; do_div(fptmp, 640);
0145 if (symbolrate < fptmp)
0146 SFIL = 0;
0147 fptmp = fpxin; do_div(fptmp, 984);
0148 if (symbolrate < fptmp)
0149 SFIL = 1;
0150
0151 fin = state->config->xin >> 4;
0152 symbolrate <<= NDEC;
0153 ratio = (symbolrate << 4) / fin;
0154 tmp = ((symbolrate << 4) % fin) << 8;
0155 ratio = (ratio << 8) + tmp / fin;
0156 tmp = (tmp % fin) << 8;
0157 ratio = (ratio << 8) + DIV_ROUND_CLOSEST(tmp, fin);
0158
0159 BDR = ratio;
0160 BDRI = (((state->config->xin << 5) / symbolrate) + 1) / 2;
0161
0162 if (BDRI > 0xFF)
0163 BDRI = 0xFF;
0164
0165 SFIL = (SFIL << 4) | ves1820_inittab[0x0E];
0166
0167 NDEC = (NDEC << 6) | ves1820_inittab[0x03];
0168
0169 ves1820_writereg(state, 0x03, NDEC);
0170 ves1820_writereg(state, 0x0a, BDR & 0xff);
0171 ves1820_writereg(state, 0x0b, (BDR >> 8) & 0xff);
0172 ves1820_writereg(state, 0x0c, (BDR >> 16) & 0x3f);
0173
0174 ves1820_writereg(state, 0x0d, BDRI);
0175 ves1820_writereg(state, 0x0e, SFIL);
0176
0177 return 0;
0178 }
0179
0180 static int ves1820_init(struct dvb_frontend* fe)
0181 {
0182 struct ves1820_state* state = fe->demodulator_priv;
0183 int i;
0184
0185 ves1820_writereg(state, 0, 0);
0186
0187 for (i = 0; i < sizeof(ves1820_inittab); i++)
0188 ves1820_writereg(state, i, ves1820_inittab[i]);
0189 if (state->config->selagc)
0190 ves1820_writereg(state, 2, ves1820_inittab[2] | 0x08);
0191
0192 ves1820_writereg(state, 0x34, state->pwm);
0193
0194 return 0;
0195 }
0196
0197 static int ves1820_set_parameters(struct dvb_frontend *fe)
0198 {
0199 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
0200 struct ves1820_state* state = fe->demodulator_priv;
0201 static const u8 reg0x00[] = { 0x00, 0x04, 0x08, 0x0c, 0x10 };
0202 static const u8 reg0x01[] = { 140, 140, 106, 100, 92 };
0203 static const u8 reg0x05[] = { 135, 100, 70, 54, 38 };
0204 static const u8 reg0x08[] = { 162, 116, 67, 52, 35 };
0205 static const u8 reg0x09[] = { 145, 150, 106, 126, 107 };
0206 int real_qam = p->modulation - QAM_16;
0207
0208 if (real_qam < 0 || real_qam > 4)
0209 return -EINVAL;
0210
0211 if (fe->ops.tuner_ops.set_params) {
0212 fe->ops.tuner_ops.set_params(fe);
0213 if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
0214 }
0215
0216 ves1820_set_symbolrate(state, p->symbol_rate);
0217 ves1820_writereg(state, 0x34, state->pwm);
0218
0219 ves1820_writereg(state, 0x01, reg0x01[real_qam]);
0220 ves1820_writereg(state, 0x05, reg0x05[real_qam]);
0221 ves1820_writereg(state, 0x08, reg0x08[real_qam]);
0222 ves1820_writereg(state, 0x09, reg0x09[real_qam]);
0223
0224 ves1820_setup_reg0(state, reg0x00[real_qam], p->inversion);
0225 ves1820_writereg(state, 2, ves1820_inittab[2] | (state->config->selagc ? 0x08 : 0));
0226 return 0;
0227 }
0228
0229 static int ves1820_read_status(struct dvb_frontend *fe,
0230 enum fe_status *status)
0231 {
0232 struct ves1820_state* state = fe->demodulator_priv;
0233 int sync;
0234
0235 *status = 0;
0236 sync = ves1820_readreg(state, 0x11);
0237
0238 if (sync & 1)
0239 *status |= FE_HAS_SIGNAL;
0240
0241 if (sync & 2)
0242 *status |= FE_HAS_CARRIER;
0243
0244 if (sync & 2)
0245 *status |= FE_HAS_VITERBI;
0246
0247 if (sync & 4)
0248 *status |= FE_HAS_SYNC;
0249
0250 if (sync & 8)
0251 *status |= FE_HAS_LOCK;
0252
0253 return 0;
0254 }
0255
0256 static int ves1820_read_ber(struct dvb_frontend* fe, u32* ber)
0257 {
0258 struct ves1820_state* state = fe->demodulator_priv;
0259
0260 u32 _ber = ves1820_readreg(state, 0x14) |
0261 (ves1820_readreg(state, 0x15) << 8) |
0262 ((ves1820_readreg(state, 0x16) & 0x0f) << 16);
0263 *ber = 10 * _ber;
0264
0265 return 0;
0266 }
0267
0268 static int ves1820_read_signal_strength(struct dvb_frontend* fe, u16* strength)
0269 {
0270 struct ves1820_state* state = fe->demodulator_priv;
0271
0272 u8 gain = ves1820_readreg(state, 0x17);
0273 *strength = (gain << 8) | gain;
0274
0275 return 0;
0276 }
0277
0278 static int ves1820_read_snr(struct dvb_frontend* fe, u16* snr)
0279 {
0280 struct ves1820_state* state = fe->demodulator_priv;
0281
0282 u8 quality = ~ves1820_readreg(state, 0x18);
0283 *snr = (quality << 8) | quality;
0284
0285 return 0;
0286 }
0287
0288 static int ves1820_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
0289 {
0290 struct ves1820_state* state = fe->demodulator_priv;
0291
0292 *ucblocks = ves1820_readreg(state, 0x13) & 0x7f;
0293 if (*ucblocks == 0x7f)
0294 *ucblocks = 0xffffffff;
0295
0296
0297 ves1820_writereg(state, 0x10, ves1820_inittab[0x10] & 0xdf);
0298 ves1820_writereg(state, 0x10, ves1820_inittab[0x10]);
0299
0300 return 0;
0301 }
0302
0303 static int ves1820_get_frontend(struct dvb_frontend *fe,
0304 struct dtv_frontend_properties *p)
0305 {
0306 struct ves1820_state* state = fe->demodulator_priv;
0307 int sync;
0308 s8 afc = 0;
0309
0310 sync = ves1820_readreg(state, 0x11);
0311 afc = ves1820_readreg(state, 0x19);
0312 if (verbose) {
0313
0314 printk(sync & 2 ? "ves1820: AFC (%d) %dHz\n" :
0315 "ves1820: [AFC (%d) %dHz]\n", afc, -((s32) p->symbol_rate * afc) >> 10);
0316 }
0317
0318 if (!state->config->invert) {
0319 p->inversion = (state->reg0 & 0x20) ? INVERSION_ON : INVERSION_OFF;
0320 } else {
0321 p->inversion = (!(state->reg0 & 0x20)) ? INVERSION_ON : INVERSION_OFF;
0322 }
0323
0324 p->modulation = ((state->reg0 >> 2) & 7) + QAM_16;
0325
0326 p->fec_inner = FEC_NONE;
0327
0328 p->frequency = ((p->frequency + 31250) / 62500) * 62500;
0329 if (sync & 2)
0330 p->frequency -= ((s32) p->symbol_rate * afc) >> 10;
0331
0332 return 0;
0333 }
0334
0335 static int ves1820_sleep(struct dvb_frontend* fe)
0336 {
0337 struct ves1820_state* state = fe->demodulator_priv;
0338
0339 ves1820_writereg(state, 0x1b, 0x02);
0340 ves1820_writereg(state, 0x00, 0x80);
0341
0342 return 0;
0343 }
0344
0345 static int ves1820_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
0346 {
0347
0348 fesettings->min_delay_ms = 200;
0349 fesettings->step_size = 0;
0350 fesettings->max_drift = 0;
0351 return 0;
0352 }
0353
0354 static void ves1820_release(struct dvb_frontend* fe)
0355 {
0356 struct ves1820_state* state = fe->demodulator_priv;
0357 kfree(state);
0358 }
0359
0360 static const struct dvb_frontend_ops ves1820_ops;
0361
0362 struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
0363 struct i2c_adapter* i2c,
0364 u8 pwm)
0365 {
0366 struct ves1820_state* state = NULL;
0367
0368
0369 state = kzalloc(sizeof(struct ves1820_state), GFP_KERNEL);
0370 if (state == NULL)
0371 goto error;
0372
0373
0374 state->reg0 = ves1820_inittab[0];
0375 state->config = config;
0376 state->i2c = i2c;
0377 state->pwm = pwm;
0378
0379
0380 if ((ves1820_readreg(state, 0x1a) & 0xf0) != 0x70)
0381 goto error;
0382
0383 if (verbose)
0384 printk("ves1820: pwm=0x%02x\n", state->pwm);
0385
0386
0387 memcpy(&state->frontend.ops, &ves1820_ops, sizeof(struct dvb_frontend_ops));
0388 state->frontend.ops.info.symbol_rate_min = (state->config->xin / 2) / 64;
0389 state->frontend.ops.info.symbol_rate_max = (state->config->xin / 2) / 4;
0390 state->frontend.demodulator_priv = state;
0391
0392 return &state->frontend;
0393
0394 error:
0395 kfree(state);
0396 return NULL;
0397 }
0398
0399 static const struct dvb_frontend_ops ves1820_ops = {
0400 .delsys = { SYS_DVBC_ANNEX_A },
0401 .info = {
0402 .name = "VLSI VES1820 DVB-C",
0403 .frequency_min_hz = 47 * MHz,
0404 .frequency_max_hz = 862 * MHz,
0405 .frequency_stepsize_hz = 62500,
0406 .caps = FE_CAN_QAM_16 |
0407 FE_CAN_QAM_32 |
0408 FE_CAN_QAM_64 |
0409 FE_CAN_QAM_128 |
0410 FE_CAN_QAM_256 |
0411 FE_CAN_FEC_AUTO
0412 },
0413
0414 .release = ves1820_release,
0415
0416 .init = ves1820_init,
0417 .sleep = ves1820_sleep,
0418
0419 .set_frontend = ves1820_set_parameters,
0420 .get_frontend = ves1820_get_frontend,
0421 .get_tune_settings = ves1820_get_tune_settings,
0422
0423 .read_status = ves1820_read_status,
0424 .read_ber = ves1820_read_ber,
0425 .read_signal_strength = ves1820_read_signal_strength,
0426 .read_snr = ves1820_read_snr,
0427 .read_ucblocks = ves1820_read_ucblocks,
0428 };
0429
0430 module_param(verbose, int, 0644);
0431 MODULE_PARM_DESC(verbose, "print AFC offset after tuning for debugging the PWM setting");
0432
0433 MODULE_DESCRIPTION("VLSI VES1820 DVB-C Demodulator driver");
0434 MODULE_AUTHOR("Ralph Metzler, Holger Waechtler");
0435 MODULE_LICENSE("GPL");
0436
0437 EXPORT_SYMBOL(ves1820_attach);