0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/kernel.h>
0018 #include <asm/div64.h>
0019
0020 #include <media/dvb_frontend.h>
0021 #include "s921.h"
0022
0023 static int debug = 1;
0024 module_param(debug, int, 0644);
0025 MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
0026
0027 #define rc(args...) do { \
0028 printk(KERN_ERR "s921: " args); \
0029 } while (0)
0030
0031 #define dprintk(args...) \
0032 do { \
0033 if (debug) { \
0034 printk(KERN_DEBUG "s921: %s: ", __func__); \
0035 printk(args); \
0036 } \
0037 } while (0)
0038
0039 struct s921_state {
0040 struct i2c_adapter *i2c;
0041 const struct s921_config *config;
0042
0043 struct dvb_frontend frontend;
0044
0045
0046 u32 currentfreq;
0047 };
0048
0049
0050
0051
0052
0053
0054 static struct s921_bandselect_val {
0055 u32 freq_low;
0056 u8 band_reg;
0057 } s921_bandselect[] = {
0058 { 0, 0x7b },
0059 { 485140000, 0x5b },
0060 { 515140000, 0x3b },
0061 { 545140000, 0x1b },
0062 { 599140000, 0xfb },
0063 { 623140000, 0xdb },
0064 { 659140000, 0xbb },
0065 { 713140000, 0x9b },
0066 };
0067
0068 struct regdata {
0069 u8 reg;
0070 u8 data;
0071 };
0072
0073 static struct regdata s921_init[] = {
0074 { 0x01, 0x80 },
0075 { 0x01, 0x40 },
0076 { 0x01, 0x80 },
0077 { 0x01, 0x40 },
0078
0079 { 0x02, 0x00 },
0080 { 0x03, 0x40 },
0081 { 0x04, 0x01 },
0082 { 0x05, 0x00 },
0083 { 0x06, 0x00 },
0084 { 0x07, 0x00 },
0085 { 0x08, 0x00 },
0086 { 0x09, 0x00 },
0087 { 0x0a, 0x00 },
0088 { 0x0b, 0x5a },
0089 { 0x0c, 0x00 },
0090 { 0x0d, 0x00 },
0091 { 0x0f, 0x00 },
0092 { 0x13, 0x1b },
0093 { 0x14, 0x80 },
0094 { 0x15, 0x40 },
0095 { 0x17, 0x70 },
0096 { 0x18, 0x01 },
0097 { 0x19, 0x12 },
0098 { 0x1a, 0x01 },
0099 { 0x1b, 0x12 },
0100 { 0x1c, 0xa0 },
0101 { 0x1d, 0x00 },
0102 { 0x1e, 0x0a },
0103 { 0x1f, 0x08 },
0104 { 0x20, 0x40 },
0105 { 0x21, 0xff },
0106 { 0x22, 0x4c },
0107 { 0x23, 0x4e },
0108 { 0x24, 0x4c },
0109 { 0x25, 0x00 },
0110 { 0x26, 0x00 },
0111 { 0x27, 0xf4 },
0112 { 0x28, 0x60 },
0113 { 0x29, 0x88 },
0114 { 0x2a, 0x40 },
0115 { 0x2b, 0x40 },
0116 { 0x2c, 0xff },
0117 { 0x2d, 0x00 },
0118 { 0x2e, 0xff },
0119 { 0x2f, 0x00 },
0120 { 0x30, 0x20 },
0121 { 0x31, 0x06 },
0122 { 0x32, 0x0c },
0123 { 0x34, 0x0f },
0124 { 0x37, 0xfe },
0125 { 0x38, 0x00 },
0126 { 0x39, 0x63 },
0127 { 0x3a, 0x10 },
0128 { 0x3b, 0x10 },
0129 { 0x47, 0x00 },
0130 { 0x49, 0xe5 },
0131 { 0x4b, 0x00 },
0132 { 0x50, 0xc0 },
0133 { 0x52, 0x20 },
0134 { 0x54, 0x5a },
0135 { 0x55, 0x5b },
0136 { 0x56, 0x40 },
0137 { 0x57, 0x70 },
0138 { 0x5c, 0x50 },
0139 { 0x5d, 0x00 },
0140 { 0x62, 0x17 },
0141 { 0x63, 0x2f },
0142 { 0x64, 0x6f },
0143 { 0x68, 0x00 },
0144 { 0x69, 0x89 },
0145 { 0x6a, 0x00 },
0146 { 0x6b, 0x00 },
0147 { 0x6c, 0x00 },
0148 { 0x6d, 0x00 },
0149 { 0x6e, 0x00 },
0150 { 0x70, 0x10 },
0151 { 0x71, 0x00 },
0152 { 0x75, 0x00 },
0153 { 0x76, 0x30 },
0154 { 0x77, 0x01 },
0155 { 0xaf, 0x00 },
0156 { 0xb0, 0xa0 },
0157 { 0xb2, 0x3d },
0158 { 0xb3, 0x25 },
0159 { 0xb4, 0x8b },
0160 { 0xb5, 0x4b },
0161 { 0xb6, 0x3f },
0162 { 0xb7, 0xff },
0163 { 0xb8, 0xff },
0164 { 0xb9, 0xfc },
0165 { 0xba, 0x00 },
0166 { 0xbb, 0x00 },
0167 { 0xbc, 0x00 },
0168 { 0xd0, 0x30 },
0169 { 0xe4, 0x84 },
0170 { 0xf0, 0x48 },
0171 { 0xf1, 0x19 },
0172 { 0xf2, 0x5a },
0173 { 0xf3, 0x8e },
0174 { 0xf4, 0x2d },
0175 { 0xf5, 0x07 },
0176 { 0xf6, 0x5a },
0177 { 0xf7, 0xba },
0178 { 0xf8, 0xd7 },
0179 };
0180
0181 static struct regdata s921_prefreq[] = {
0182 { 0x47, 0x60 },
0183 { 0x68, 0x00 },
0184 { 0x69, 0x89 },
0185 { 0xf0, 0x48 },
0186 { 0xf1, 0x19 },
0187 };
0188
0189 static struct regdata s921_postfreq[] = {
0190 { 0xf5, 0xae },
0191 { 0xf6, 0xb7 },
0192 { 0xf7, 0xba },
0193 { 0xf8, 0xd7 },
0194 { 0x68, 0x0a },
0195 { 0x69, 0x09 },
0196 };
0197
0198 static int s921_i2c_writereg(struct s921_state *state,
0199 u8 i2c_addr, int reg, int data)
0200 {
0201 u8 buf[] = { reg, data };
0202 struct i2c_msg msg = {
0203 .addr = i2c_addr, .flags = 0, .buf = buf, .len = 2
0204 };
0205 int rc;
0206
0207 rc = i2c_transfer(state->i2c, &msg, 1);
0208 if (rc != 1) {
0209 printk("%s: writereg rcor(rc == %i, reg == 0x%02x, data == 0x%02x)\n",
0210 __func__, rc, reg, data);
0211 return rc;
0212 }
0213
0214 return 0;
0215 }
0216
0217 static int s921_i2c_writeregdata(struct s921_state *state, u8 i2c_addr,
0218 struct regdata *rd, int size)
0219 {
0220 int i, rc;
0221
0222 for (i = 0; i < size; i++) {
0223 rc = s921_i2c_writereg(state, i2c_addr, rd[i].reg, rd[i].data);
0224 if (rc < 0)
0225 return rc;
0226 }
0227 return 0;
0228 }
0229
0230 static int s921_i2c_readreg(struct s921_state *state, u8 i2c_addr, u8 reg)
0231 {
0232 u8 val;
0233 int rc;
0234 struct i2c_msg msg[] = {
0235 { .addr = i2c_addr, .flags = 0, .buf = ®, .len = 1 },
0236 { .addr = i2c_addr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
0237 };
0238
0239 rc = i2c_transfer(state->i2c, msg, 2);
0240
0241 if (rc != 2) {
0242 rc("%s: reg=0x%x (rcor=%d)\n", __func__, reg, rc);
0243 return rc;
0244 }
0245
0246 return val;
0247 }
0248
0249 #define s921_readreg(state, reg) \
0250 s921_i2c_readreg(state, state->config->demod_address, reg)
0251 #define s921_writereg(state, reg, val) \
0252 s921_i2c_writereg(state, state->config->demod_address, reg, val)
0253 #define s921_writeregdata(state, regdata) \
0254 s921_i2c_writeregdata(state, state->config->demod_address, \
0255 regdata, ARRAY_SIZE(regdata))
0256
0257 static int s921_pll_tune(struct dvb_frontend *fe)
0258 {
0259 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
0260 struct s921_state *state = fe->demodulator_priv;
0261 int band, rc, i;
0262 unsigned long f_offset;
0263 u8 f_switch;
0264 u64 offset;
0265
0266 dprintk("frequency=%i\n", p->frequency);
0267
0268 for (band = 0; band < ARRAY_SIZE(s921_bandselect); band++)
0269 if (p->frequency < s921_bandselect[band].freq_low)
0270 break;
0271 band--;
0272
0273 if (band < 0) {
0274 rc("%s: frequency out of range\n", __func__);
0275 return -EINVAL;
0276 }
0277
0278 f_switch = s921_bandselect[band].band_reg;
0279
0280 offset = ((u64)p->frequency) * 258;
0281 do_div(offset, 6000000);
0282 f_offset = ((unsigned long)offset) + 2321;
0283
0284 rc = s921_writeregdata(state, s921_prefreq);
0285 if (rc < 0)
0286 return rc;
0287
0288 rc = s921_writereg(state, 0xf2, (f_offset >> 8) & 0xff);
0289 if (rc < 0)
0290 return rc;
0291
0292 rc = s921_writereg(state, 0xf3, f_offset & 0xff);
0293 if (rc < 0)
0294 return rc;
0295
0296 rc = s921_writereg(state, 0xf4, f_switch);
0297 if (rc < 0)
0298 return rc;
0299
0300 rc = s921_writeregdata(state, s921_postfreq);
0301 if (rc < 0)
0302 return rc;
0303
0304 for (i = 0 ; i < 6; i++) {
0305 rc = s921_readreg(state, 0x80);
0306 dprintk("status 0x80: %02x\n", rc);
0307 }
0308 rc = s921_writereg(state, 0x01, 0x40);
0309 if (rc < 0)
0310 return rc;
0311
0312 rc = s921_readreg(state, 0x01);
0313 dprintk("status 0x01: %02x\n", rc);
0314
0315 rc = s921_readreg(state, 0x80);
0316 dprintk("status 0x80: %02x\n", rc);
0317
0318 rc = s921_readreg(state, 0x80);
0319 dprintk("status 0x80: %02x\n", rc);
0320
0321 rc = s921_readreg(state, 0x32);
0322 dprintk("status 0x32: %02x\n", rc);
0323
0324 dprintk("pll tune band=%d, pll=%d\n", f_switch, (int)f_offset);
0325
0326 return 0;
0327 }
0328
0329 static int s921_initfe(struct dvb_frontend *fe)
0330 {
0331 struct s921_state *state = fe->demodulator_priv;
0332 int rc;
0333
0334 dprintk("\n");
0335
0336 rc = s921_writeregdata(state, s921_init);
0337 if (rc < 0)
0338 return rc;
0339
0340 return 0;
0341 }
0342
0343 static int s921_read_status(struct dvb_frontend *fe, enum fe_status *status)
0344 {
0345 struct s921_state *state = fe->demodulator_priv;
0346 int regstatus, rc;
0347
0348 *status = 0;
0349
0350 rc = s921_readreg(state, 0x81);
0351 if (rc < 0)
0352 return rc;
0353
0354 regstatus = rc << 8;
0355
0356 rc = s921_readreg(state, 0x82);
0357 if (rc < 0)
0358 return rc;
0359
0360 regstatus |= rc;
0361
0362 dprintk("status = %04x\n", regstatus);
0363
0364
0365 if ((regstatus & 0xff) == 0x40) {
0366 *status = FE_HAS_SIGNAL |
0367 FE_HAS_CARRIER |
0368 FE_HAS_VITERBI |
0369 FE_HAS_SYNC |
0370 FE_HAS_LOCK;
0371 } else if (regstatus & 0x40) {
0372
0373 *status = FE_HAS_SIGNAL |
0374 FE_HAS_CARRIER |
0375 FE_HAS_VITERBI |
0376 FE_HAS_SYNC;
0377 }
0378
0379 return 0;
0380 }
0381
0382 static int s921_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
0383 {
0384 enum fe_status status;
0385 struct s921_state *state = fe->demodulator_priv;
0386 int rc;
0387
0388
0389 rc = s921_read_status(fe, &status);
0390 if (rc < 0)
0391 return rc;
0392
0393 *strength = (status & FE_HAS_LOCK) ? 0xffff : 0;
0394
0395 dprintk("strength = 0x%04x\n", *strength);
0396
0397 rc = s921_readreg(state, 0x01);
0398 dprintk("status 0x01: %02x\n", rc);
0399
0400 rc = s921_readreg(state, 0x80);
0401 dprintk("status 0x80: %02x\n", rc);
0402
0403 rc = s921_readreg(state, 0x32);
0404 dprintk("status 0x32: %02x\n", rc);
0405
0406 return 0;
0407 }
0408
0409 static int s921_set_frontend(struct dvb_frontend *fe)
0410 {
0411 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
0412 struct s921_state *state = fe->demodulator_priv;
0413 int rc;
0414
0415 dprintk("\n");
0416
0417
0418
0419 rc = s921_pll_tune(fe);
0420 if (rc < 0)
0421 return rc;
0422
0423 state->currentfreq = p->frequency;
0424
0425 return 0;
0426 }
0427
0428 static int s921_get_frontend(struct dvb_frontend *fe,
0429 struct dtv_frontend_properties *p)
0430 {
0431 struct s921_state *state = fe->demodulator_priv;
0432
0433
0434 p->frequency = state->currentfreq;
0435 p->delivery_system = SYS_ISDBT;
0436
0437 return 0;
0438 }
0439
0440 static int s921_tune(struct dvb_frontend *fe,
0441 bool re_tune,
0442 unsigned int mode_flags,
0443 unsigned int *delay,
0444 enum fe_status *status)
0445 {
0446 int rc = 0;
0447
0448 dprintk("\n");
0449
0450 if (re_tune)
0451 rc = s921_set_frontend(fe);
0452
0453 if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
0454 s921_read_status(fe, status);
0455
0456 return rc;
0457 }
0458
0459 static enum dvbfe_algo s921_get_algo(struct dvb_frontend *fe)
0460 {
0461 return DVBFE_ALGO_HW;
0462 }
0463
0464 static void s921_release(struct dvb_frontend *fe)
0465 {
0466 struct s921_state *state = fe->demodulator_priv;
0467
0468 dprintk("\n");
0469 kfree(state);
0470 }
0471
0472 static const struct dvb_frontend_ops s921_ops;
0473
0474 struct dvb_frontend *s921_attach(const struct s921_config *config,
0475 struct i2c_adapter *i2c)
0476 {
0477
0478 struct s921_state *state =
0479 kzalloc(sizeof(struct s921_state), GFP_KERNEL);
0480
0481 dprintk("\n");
0482 if (!state) {
0483 rc("Unable to kzalloc\n");
0484 return NULL;
0485 }
0486
0487
0488 state->config = config;
0489 state->i2c = i2c;
0490
0491
0492 memcpy(&state->frontend.ops, &s921_ops,
0493 sizeof(struct dvb_frontend_ops));
0494 state->frontend.demodulator_priv = state;
0495
0496 return &state->frontend;
0497 }
0498 EXPORT_SYMBOL(s921_attach);
0499
0500 static const struct dvb_frontend_ops s921_ops = {
0501 .delsys = { SYS_ISDBT },
0502
0503 .info = {
0504 .name = "Sharp S921",
0505 .frequency_min_hz = 470 * MHz,
0506
0507
0508
0509
0510
0511 .frequency_max_hz = 806 * MHz,
0512 .caps = FE_CAN_INVERSION_AUTO |
0513 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
0514 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
0515 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
0516 FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
0517 FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER |
0518 FE_CAN_HIERARCHY_AUTO,
0519 },
0520
0521 .release = s921_release,
0522
0523 .init = s921_initfe,
0524 .set_frontend = s921_set_frontend,
0525 .get_frontend = s921_get_frontend,
0526 .read_status = s921_read_status,
0527 .read_signal_strength = s921_read_signal_strength,
0528 .tune = s921_tune,
0529 .get_frontend_algo = s921_get_algo,
0530 };
0531
0532 MODULE_DESCRIPTION("DVB Frontend module for Sharp S921 hardware");
0533 MODULE_AUTHOR("Mauro Carvalho Chehab");
0534 MODULE_AUTHOR("Douglas Landgraf <dougsland@redhat.com>");
0535 MODULE_LICENSE("GPL");