1 /* 2 * Sharp VA3A5JZ921 One Seg Broadcast Module driver 3 * This device is labeled as just S. 921 at the top of the frontend can 4 * 5 * Copyright (C) 2009-2010 Mauro Carvalho Chehab <mchehab@redhat.com> 6 * Copyright (C) 2009-2010 Douglas Landgraf <dougsland@redhat.com> 7 * 8 * Developed for Leadership SBTVD 1seg device sold in Brazil 9 * 10 * Frontend module based on cx24123 driver, getting some info from 11 * the old s921 driver. 12 * 13 * FIXME: Need to port to DVB v5.2 API 14 * 15 * This program is free software; you can redistribute it and/or 16 * modify it under the terms of the GNU General Public License as 17 * published by the Free Software Foundation version 2. 18 * 19 * This program is distributed in the hope that it will be useful, 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 * General Public License for more details. 23 */ 24 25 #include <linux/kernel.h> 26 #include <asm/div64.h> 27 28 #include "dvb_frontend.h" 29 #include "s921.h" 30 31 static int debug = 1; 32 module_param(debug, int, 0644); 33 MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); 34 35 #define rc(args...) do { \ 36 printk(KERN_ERR "s921: " args); \ 37 } while (0) 38 39 #define dprintk(args...) \ 40 do { \ 41 if (debug) { \ 42 printk(KERN_DEBUG "s921: %s: ", __func__); \ 43 printk(args); \ 44 } \ 45 } while (0) 46 47 struct s921_state { 48 struct i2c_adapter *i2c; 49 const struct s921_config *config; 50 51 struct dvb_frontend frontend; 52 53 /* The Demod can't easily provide these, we cache them */ 54 u32 currentfreq; 55 }; 56 57 /* 58 * Various tuner defaults need to be established for a given frequency kHz. 59 * fixme: The bounds on the bands do not match the doc in real life. 60 * fixme: Some of them have been moved, other might need adjustment. 61 */ 62 static struct s921_bandselect_val { 63 u32 freq_low; 64 u8 band_reg; 65 } s921_bandselect[] = { 66 { 0, 0x7b }, 67 { 485140000, 0x5b }, 68 { 515140000, 0x3b }, 69 { 545140000, 0x1b }, 70 { 599140000, 0xfb }, 71 { 623140000, 0xdb }, 72 { 659140000, 0xbb }, 73 { 713140000, 0x9b }, 74 }; 75 76 struct regdata { 77 u8 reg; 78 u8 data; 79 }; 80 81 static struct regdata s921_init[] = { 82 { 0x01, 0x80 }, /* Probably, a reset sequence */ 83 { 0x01, 0x40 }, 84 { 0x01, 0x80 }, 85 { 0x01, 0x40 }, 86 87 { 0x02, 0x00 }, 88 { 0x03, 0x40 }, 89 { 0x04, 0x01 }, 90 { 0x05, 0x00 }, 91 { 0x06, 0x00 }, 92 { 0x07, 0x00 }, 93 { 0x08, 0x00 }, 94 { 0x09, 0x00 }, 95 { 0x0a, 0x00 }, 96 { 0x0b, 0x5a }, 97 { 0x0c, 0x00 }, 98 { 0x0d, 0x00 }, 99 { 0x0f, 0x00 }, 100 { 0x13, 0x1b }, 101 { 0x14, 0x80 }, 102 { 0x15, 0x40 }, 103 { 0x17, 0x70 }, 104 { 0x18, 0x01 }, 105 { 0x19, 0x12 }, 106 { 0x1a, 0x01 }, 107 { 0x1b, 0x12 }, 108 { 0x1c, 0xa0 }, 109 { 0x1d, 0x00 }, 110 { 0x1e, 0x0a }, 111 { 0x1f, 0x08 }, 112 { 0x20, 0x40 }, 113 { 0x21, 0xff }, 114 { 0x22, 0x4c }, 115 { 0x23, 0x4e }, 116 { 0x24, 0x4c }, 117 { 0x25, 0x00 }, 118 { 0x26, 0x00 }, 119 { 0x27, 0xf4 }, 120 { 0x28, 0x60 }, 121 { 0x29, 0x88 }, 122 { 0x2a, 0x40 }, 123 { 0x2b, 0x40 }, 124 { 0x2c, 0xff }, 125 { 0x2d, 0x00 }, 126 { 0x2e, 0xff }, 127 { 0x2f, 0x00 }, 128 { 0x30, 0x20 }, 129 { 0x31, 0x06 }, 130 { 0x32, 0x0c }, 131 { 0x34, 0x0f }, 132 { 0x37, 0xfe }, 133 { 0x38, 0x00 }, 134 { 0x39, 0x63 }, 135 { 0x3a, 0x10 }, 136 { 0x3b, 0x10 }, 137 { 0x47, 0x00 }, 138 { 0x49, 0xe5 }, 139 { 0x4b, 0x00 }, 140 { 0x50, 0xc0 }, 141 { 0x52, 0x20 }, 142 { 0x54, 0x5a }, 143 { 0x55, 0x5b }, 144 { 0x56, 0x40 }, 145 { 0x57, 0x70 }, 146 { 0x5c, 0x50 }, 147 { 0x5d, 0x00 }, 148 { 0x62, 0x17 }, 149 { 0x63, 0x2f }, 150 { 0x64, 0x6f }, 151 { 0x68, 0x00 }, 152 { 0x69, 0x89 }, 153 { 0x6a, 0x00 }, 154 { 0x6b, 0x00 }, 155 { 0x6c, 0x00 }, 156 { 0x6d, 0x00 }, 157 { 0x6e, 0x00 }, 158 { 0x70, 0x10 }, 159 { 0x71, 0x00 }, 160 { 0x75, 0x00 }, 161 { 0x76, 0x30 }, 162 { 0x77, 0x01 }, 163 { 0xaf, 0x00 }, 164 { 0xb0, 0xa0 }, 165 { 0xb2, 0x3d }, 166 { 0xb3, 0x25 }, 167 { 0xb4, 0x8b }, 168 { 0xb5, 0x4b }, 169 { 0xb6, 0x3f }, 170 { 0xb7, 0xff }, 171 { 0xb8, 0xff }, 172 { 0xb9, 0xfc }, 173 { 0xba, 0x00 }, 174 { 0xbb, 0x00 }, 175 { 0xbc, 0x00 }, 176 { 0xd0, 0x30 }, 177 { 0xe4, 0x84 }, 178 { 0xf0, 0x48 }, 179 { 0xf1, 0x19 }, 180 { 0xf2, 0x5a }, 181 { 0xf3, 0x8e }, 182 { 0xf4, 0x2d }, 183 { 0xf5, 0x07 }, 184 { 0xf6, 0x5a }, 185 { 0xf7, 0xba }, 186 { 0xf8, 0xd7 }, 187 }; 188 189 static struct regdata s921_prefreq[] = { 190 { 0x47, 0x60 }, 191 { 0x68, 0x00 }, 192 { 0x69, 0x89 }, 193 { 0xf0, 0x48 }, 194 { 0xf1, 0x19 }, 195 }; 196 197 static struct regdata s921_postfreq[] = { 198 { 0xf5, 0xae }, 199 { 0xf6, 0xb7 }, 200 { 0xf7, 0xba }, 201 { 0xf8, 0xd7 }, 202 { 0x68, 0x0a }, 203 { 0x69, 0x09 }, 204 }; 205 206 static int s921_i2c_writereg(struct s921_state *state, 207 u8 i2c_addr, int reg, int data) 208 { 209 u8 buf[] = { reg, data }; 210 struct i2c_msg msg = { 211 .addr = i2c_addr, .flags = 0, .buf = buf, .len = 2 212 }; 213 int rc; 214 215 rc = i2c_transfer(state->i2c, &msg, 1); 216 if (rc != 1) { 217 printk("%s: writereg rcor(rc == %i, reg == 0x%02x," 218 " data == 0x%02x)\n", __func__, rc, reg, data); 219 return rc; 220 } 221 222 return 0; 223 } 224 225 static int s921_i2c_writeregdata(struct s921_state *state, u8 i2c_addr, 226 struct regdata *rd, int size) 227 { 228 int i, rc; 229 230 for (i = 0; i < size; i++) { 231 rc = s921_i2c_writereg(state, i2c_addr, rd[i].reg, rd[i].data); 232 if (rc < 0) 233 return rc; 234 } 235 return 0; 236 } 237 238 static int s921_i2c_readreg(struct s921_state *state, u8 i2c_addr, u8 reg) 239 { 240 u8 val; 241 int rc; 242 struct i2c_msg msg[] = { 243 { .addr = i2c_addr, .flags = 0, .buf = ®, .len = 1 }, 244 { .addr = i2c_addr, .flags = I2C_M_RD, .buf = &val, .len = 1 } 245 }; 246 247 rc = i2c_transfer(state->i2c, msg, 2); 248 249 if (rc != 2) { 250 rc("%s: reg=0x%x (rcor=%d)\n", __func__, reg, rc); 251 return rc; 252 } 253 254 return val; 255 } 256 257 #define s921_readreg(state, reg) \ 258 s921_i2c_readreg(state, state->config->demod_address, reg) 259 #define s921_writereg(state, reg, val) \ 260 s921_i2c_writereg(state, state->config->demod_address, reg, val) 261 #define s921_writeregdata(state, regdata) \ 262 s921_i2c_writeregdata(state, state->config->demod_address, \ 263 regdata, ARRAY_SIZE(regdata)) 264 265 static int s921_pll_tune(struct dvb_frontend *fe) 266 { 267 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 268 struct s921_state *state = fe->demodulator_priv; 269 int band, rc, i; 270 unsigned long f_offset; 271 u8 f_switch; 272 u64 offset; 273 274 dprintk("frequency=%i\n", p->frequency); 275 276 for (band = 0; band < ARRAY_SIZE(s921_bandselect); band++) 277 if (p->frequency < s921_bandselect[band].freq_low) 278 break; 279 band--; 280 281 if (band < 0) { 282 rc("%s: frequency out of range\n", __func__); 283 return -EINVAL; 284 } 285 286 f_switch = s921_bandselect[band].band_reg; 287 288 offset = ((u64)p->frequency) * 258; 289 do_div(offset, 6000000); 290 f_offset = ((unsigned long)offset) + 2321; 291 292 rc = s921_writeregdata(state, s921_prefreq); 293 if (rc < 0) 294 return rc; 295 296 rc = s921_writereg(state, 0xf2, (f_offset >> 8) & 0xff); 297 if (rc < 0) 298 return rc; 299 300 rc = s921_writereg(state, 0xf3, f_offset & 0xff); 301 if (rc < 0) 302 return rc; 303 304 rc = s921_writereg(state, 0xf4, f_switch); 305 if (rc < 0) 306 return rc; 307 308 rc = s921_writeregdata(state, s921_postfreq); 309 if (rc < 0) 310 return rc; 311 312 for (i = 0 ; i < 6; i++) { 313 rc = s921_readreg(state, 0x80); 314 dprintk("status 0x80: %02x\n", rc); 315 } 316 rc = s921_writereg(state, 0x01, 0x40); 317 if (rc < 0) 318 return rc; 319 320 rc = s921_readreg(state, 0x01); 321 dprintk("status 0x01: %02x\n", rc); 322 323 rc = s921_readreg(state, 0x80); 324 dprintk("status 0x80: %02x\n", rc); 325 326 rc = s921_readreg(state, 0x80); 327 dprintk("status 0x80: %02x\n", rc); 328 329 rc = s921_readreg(state, 0x32); 330 dprintk("status 0x32: %02x\n", rc); 331 332 dprintk("pll tune band=%d, pll=%d\n", f_switch, (int)f_offset); 333 334 return 0; 335 } 336 337 static int s921_initfe(struct dvb_frontend *fe) 338 { 339 struct s921_state *state = fe->demodulator_priv; 340 int rc; 341 342 dprintk("\n"); 343 344 rc = s921_writeregdata(state, s921_init); 345 if (rc < 0) 346 return rc; 347 348 return 0; 349 } 350 351 static int s921_read_status(struct dvb_frontend *fe, fe_status_t *status) 352 { 353 struct s921_state *state = fe->demodulator_priv; 354 int regstatus, rc; 355 356 *status = 0; 357 358 rc = s921_readreg(state, 0x81); 359 if (rc < 0) 360 return rc; 361 362 regstatus = rc << 8; 363 364 rc = s921_readreg(state, 0x82); 365 if (rc < 0) 366 return rc; 367 368 regstatus |= rc; 369 370 dprintk("status = %04x\n", regstatus); 371 372 /* Full Sync - We don't know what each bit means on regs 0x81/0x82 */ 373 if ((regstatus & 0xff) == 0x40) { 374 *status = FE_HAS_SIGNAL | 375 FE_HAS_CARRIER | 376 FE_HAS_VITERBI | 377 FE_HAS_SYNC | 378 FE_HAS_LOCK; 379 } else if (regstatus & 0x40) { 380 /* This is close to Full Sync, but not enough to get useful info */ 381 *status = FE_HAS_SIGNAL | 382 FE_HAS_CARRIER | 383 FE_HAS_VITERBI | 384 FE_HAS_SYNC; 385 } 386 387 return 0; 388 } 389 390 static int s921_read_signal_strength(struct dvb_frontend *fe, u16 *strength) 391 { 392 fe_status_t status; 393 struct s921_state *state = fe->demodulator_priv; 394 int rc; 395 396 /* FIXME: Use the proper register for it... 0x80? */ 397 rc = s921_read_status(fe, &status); 398 if (rc < 0) 399 return rc; 400 401 *strength = (status & FE_HAS_LOCK) ? 0xffff : 0; 402 403 dprintk("strength = 0x%04x\n", *strength); 404 405 rc = s921_readreg(state, 0x01); 406 dprintk("status 0x01: %02x\n", rc); 407 408 rc = s921_readreg(state, 0x80); 409 dprintk("status 0x80: %02x\n", rc); 410 411 rc = s921_readreg(state, 0x32); 412 dprintk("status 0x32: %02x\n", rc); 413 414 return 0; 415 } 416 417 static int s921_set_frontend(struct dvb_frontend *fe) 418 { 419 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 420 struct s921_state *state = fe->demodulator_priv; 421 int rc; 422 423 dprintk("\n"); 424 425 /* FIXME: We don't know how to use non-auto mode */ 426 427 rc = s921_pll_tune(fe); 428 if (rc < 0) 429 return rc; 430 431 state->currentfreq = p->frequency; 432 433 return 0; 434 } 435 436 static int s921_get_frontend(struct dvb_frontend *fe) 437 { 438 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 439 struct s921_state *state = fe->demodulator_priv; 440 441 /* FIXME: Probably it is possible to get it from regs f1 and f2 */ 442 p->frequency = state->currentfreq; 443 p->delivery_system = SYS_ISDBT; 444 445 return 0; 446 } 447 448 static int s921_tune(struct dvb_frontend *fe, 449 bool re_tune, 450 unsigned int mode_flags, 451 unsigned int *delay, 452 fe_status_t *status) 453 { 454 int rc = 0; 455 456 dprintk("\n"); 457 458 if (re_tune) 459 rc = s921_set_frontend(fe); 460 461 if (!(mode_flags & FE_TUNE_MODE_ONESHOT)) 462 s921_read_status(fe, status); 463 464 return rc; 465 } 466 467 static int s921_get_algo(struct dvb_frontend *fe) 468 { 469 return 1; /* FE_ALGO_HW */ 470 } 471 472 static void s921_release(struct dvb_frontend *fe) 473 { 474 struct s921_state *state = fe->demodulator_priv; 475 476 dprintk("\n"); 477 kfree(state); 478 } 479 480 static struct dvb_frontend_ops s921_ops; 481 482 struct dvb_frontend *s921_attach(const struct s921_config *config, 483 struct i2c_adapter *i2c) 484 { 485 /* allocate memory for the internal state */ 486 struct s921_state *state = 487 kzalloc(sizeof(struct s921_state), GFP_KERNEL); 488 489 dprintk("\n"); 490 if (!state) { 491 rc("Unable to kzalloc\n"); 492 return NULL; 493 } 494 495 /* setup the state */ 496 state->config = config; 497 state->i2c = i2c; 498 499 /* create dvb_frontend */ 500 memcpy(&state->frontend.ops, &s921_ops, 501 sizeof(struct dvb_frontend_ops)); 502 state->frontend.demodulator_priv = state; 503 504 return &state->frontend; 505 } 506 EXPORT_SYMBOL(s921_attach); 507 508 static struct dvb_frontend_ops s921_ops = { 509 .delsys = { SYS_ISDBT }, 510 /* Use dib8000 values per default */ 511 .info = { 512 .name = "Sharp S921", 513 .frequency_min = 470000000, 514 /* 515 * Max should be 770MHz instead, according with Sharp docs, 516 * but Leadership doc says it works up to 806 MHz. This is 517 * required to get channel 69, used in Brazil 518 */ 519 .frequency_max = 806000000, 520 .frequency_tolerance = 0, 521 .caps = FE_CAN_INVERSION_AUTO | 522 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 523 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | 524 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | 525 FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | 526 FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | 527 FE_CAN_HIERARCHY_AUTO, 528 }, 529 530 .release = s921_release, 531 532 .init = s921_initfe, 533 .set_frontend = s921_set_frontend, 534 .get_frontend = s921_get_frontend, 535 .read_status = s921_read_status, 536 .read_signal_strength = s921_read_signal_strength, 537 .tune = s921_tune, 538 .get_frontend_algo = s921_get_algo, 539 }; 540 541 MODULE_DESCRIPTION("DVB Frontend module for Sharp S921 hardware"); 542 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); 543 MODULE_AUTHOR("Douglas Landgraf <dougsland@redhat.com>"); 544 MODULE_LICENSE("GPL"); 545