FILE
sp8870.c
File preview with syntax highlighting.
linux-6.19.14/drivers/staging/media/av7110/sp8870.c
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Driver for Spase SP8870 demodulator 4.* 5 * Copyright (C) 1999 Juergen Peitz 6 */ 7 8/* 9 * This driver needs external firmware. Please use the command 10 * "<kerneldir>/scripts/get_dvb_firmware alps_tdlb7" to 11 * download/extract it, and then copy it to /usr/lib/hotplug/firmware 12 * or /lib/firmware (depending on configuration of firmware hotplug). 13 */ 14 15#ifdef pr_fmt 16#undef pr_fmt 17#endif 18#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 19 20#define SP8870_DEFAULT_FIRMWARE "dvb-fe-sp8870.fw" 21 22#include <linux/init.h> 23#include <linux/module.h> 24#include <linux/device.h> 25#include <linux/firmware.h> 26#include <linux/delay.h> 27#include <linux/string.h> 28#include <linux/slab.h> 29 30#include <media/dvb_frontend.h> 31#include "sp8870.h" 32 33struct sp8870_state { 34 struct i2c_adapter *i2c; 35 36 const struct sp8870_config *config; 37 38 struct dvb_frontend frontend; 39 40 /* demodulator private data */ 41 u8 initialised:1; 42}; 43 44static int debug; 45#define dprintk(fmt, arg...) \ 46 do { \ 47 if (debug) \ 48 pr_info("%s(): " fmt, __func__, ##arg); \ 49 } while (0) 50 51/* firmware size for sp8870 */ 52#define SP8870_FIRMWARE_SIZE 16382 53 54/* starting point for firmware in file 'Sc_main.mc' */ 55#define SP8870_FIRMWARE_OFFSET 0x0A 56 57static int sp8870_writereg(struct sp8870_state *state, u16 reg, u16 data) 58{ 59 u8 buf[] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff }; 60 struct i2c_msg msg = { 61 .addr = state->config->demod_address, 62 .flags = 0, 63 .buf = buf, 64 .len = 4 65 }; 66 67 int err; 68 69 err = i2c_transfer(state->i2c, &msg, 1); 70 if (err != 1) { 71 dprintk("writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", err, reg, data); 72 return -EREMOTEIO; 73 } 74 75 return 0; 76} 77 78static int sp8870_readreg(struct sp8870_state *state, u16 reg) 79{ 80 int ret; 81 u8 b0[] = { reg >> 8, reg & 0xff }; 82 u8 b1[] = { 0, 0 }; 83 struct i2c_msg msg[] = { 84 { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 2 }, 85 { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 } 86 }; 87 88 ret = i2c_transfer(state->i2c, msg, 2); 89 90 if (ret != 2) { 91 dprintk("readreg error (ret == %i)\n", ret); 92 return -1; 93 } 94 95 return (b1[0] << 8 | b1[1]); 96} 97 98static int sp8870_firmware_upload(struct sp8870_state *state, const struct firmware *fw) 99{ 100 struct i2c_msg msg; 101 const char *fw_buf = fw->data; 102 int fw_pos; 103 u8 tx_buf[255]; 104 int tx_len; 105 int err = 0; 106 107 dprintk("start firmware upload...\n"); 108 109 if (fw->size < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET) 110 return -EINVAL; 111 112 // system controller stop 113 sp8870_writereg(state, 0x0F00, 0x0000); 114 115 // instruction RAM register hiword 116 sp8870_writereg(state, 0x8F08, ((SP8870_FIRMWARE_SIZE / 2) & 0xFFFF)); 117 118 // instruction RAM MWR 119 sp8870_writereg(state, 0x8F0A, ((SP8870_FIRMWARE_SIZE / 2) >> 16)); 120 121 // do firmware upload 122 fw_pos = SP8870_FIRMWARE_OFFSET; 123 while (fw_pos < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET) { 124 tx_len = (fw_pos <= SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET - 252) ? 252 : 125 SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET - fw_pos; 126 // write register 0xCF0A 127 tx_buf[0] = 0xCF; 128 tx_buf[1] = 0x0A; 129 memcpy(&tx_buf[2], fw_buf + fw_pos, tx_len); 130 msg.addr = state->config->demod_address; 131 msg.flags = 0; 132 msg.buf = tx_buf; 133 msg.len = tx_len + 2; 134 err = i2c_transfer(state->i2c, &msg, 1); 135 if (err != 1) { 136 pr_err("%s(): firmware upload failed!\n", __func__); 137 pr_err("%s(): i2c error (err == %i)\n", __func__, err); 138 return err; 139 } 140 fw_pos += tx_len; 141 } 142 143 dprintk("firmware upload successful!\n"); 144 return 0; 145}; 146 147static void sp8870_microcontroller_stop(struct sp8870_state *state) 148{ 149 sp8870_writereg(state, 0x0F08, 0x000); 150 sp8870_writereg(state, 0x0F09, 0x000); 151 152 // microcontroller STOP 153 sp8870_writereg(state, 0x0F00, 0x000); 154} 155 156static void sp8870_microcontroller_start(struct sp8870_state *state) 157{ 158 sp8870_writereg(state, 0x0F08, 0x000); 159 sp8870_writereg(state, 0x0F09, 0x000); 160 161 // microcontroller START 162 sp8870_writereg(state, 0x0F00, 0x001); 163 // not documented but if we don't read 0x0D01 out here 164 // we don't get a correct data valid signal 165 sp8870_readreg(state, 0x0D01); 166} 167 168static int sp8870_read_data_valid_signal(struct sp8870_state *state) 169{ 170 return (sp8870_readreg(state, 0x0D02) > 0); 171} 172 173static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05) 174{ 175 int known_parameters = 1; 176 177 *reg0xc05 = 0x000; 178 179 switch (p->modulation) { 180 case QPSK: 181 break; 182 case QAM_16: 183 *reg0xc05 |= (1 << 10); 184 break; 185 case QAM_64: 186 *reg0xc05 |= (2 << 10); 187 break; 188 case QAM_AUTO: 189 known_parameters = 0; 190 break; 191 default: 192 return -EINVAL; 193 } 194 195 switch (p->hierarchy) { 196 case HIERARCHY_NONE: 197 break; 198 case HIERARCHY_1: 199 *reg0xc05 |= (1 << 7); 200 break; 201 case HIERARCHY_2: 202 *reg0xc05 |= (2 << 7); 203 break; 204 case HIERARCHY_4: 205 *reg0xc05 |= (3 << 7); 206 break; 207 case HIERARCHY_AUTO: 208 known_parameters = 0; 209 break; 210 default: 211 return -EINVAL; 212 } 213 214 switch (p->code_rate_HP) { 215 case FEC_1_2: 216 break; 217 case FEC_2_3: 218 *reg0xc05 |= (1 << 3); 219 break; 220 case FEC_3_4: 221 *reg0xc05 |= (2 << 3); 222 break; 223 case FEC_5_6: 224 *reg0xc05 |= (3 << 3); 225 break; 226 case FEC_7_8: 227 *reg0xc05 |= (4 << 3); 228 break; 229 case FEC_AUTO: 230 known_parameters = 0; 231 break; 232 default: 233 return -EINVAL; 234 } 235 236 if (known_parameters) 237 *reg0xc05 |= (2 << 1); /* use specified parameters */ 238 else 239 *reg0xc05 |= (1 << 1); /* enable autoprobing */ 240 241 return 0; 242} 243 244static int sp8870_wake_up(struct sp8870_state *state) 245{ 246 // enable TS output and interface pins 247 return sp8870_writereg(state, 0xC18, 0x00D); 248} 249 250static int sp8870_set_frontend_parameters(struct dvb_frontend *fe) 251{ 252 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 253 struct sp8870_state *state = fe->demodulator_priv; 254 int err; 255 u16 reg0xc05; 256 257 err = configure_reg0xc05(p, ®0xc05); 258 if (err) 259 return err; 260 261 // system controller stop 262 sp8870_microcontroller_stop(state); 263 264 // set tuner parameters 265 if (fe->ops.tuner_ops.set_params) { 266 fe->ops.tuner_ops.set_params(fe); 267 if (fe->ops.i2c_gate_ctrl) 268 fe->ops.i2c_gate_ctrl(fe, 0); 269 } 270 271 // sample rate correction bit [23..17] 272 sp8870_writereg(state, 0x0319, 0x000A); 273 274 // sample rate correction bit [16..0] 275 sp8870_writereg(state, 0x031A, 0x0AAB); 276 277 // integer carrier offset 278 sp8870_writereg(state, 0x0309, 0x0400); 279 280 // fractional carrier offset 281 sp8870_writereg(state, 0x030A, 0x0000); 282 283 // filter for 6/7/8 Mhz channel 284 if (p->bandwidth_hz == 6000000) 285 sp8870_writereg(state, 0x0311, 0x0002); 286 else if (p->bandwidth_hz == 7000000) 287 sp8870_writereg(state, 0x0311, 0x0001); 288 else 289 sp8870_writereg(state, 0x0311, 0x0000); 290 291 // scan order: 2k first = 0x0000, 8k first = 0x0001 292 if (p->transmission_mode == TRANSMISSION_MODE_2K) 293 sp8870_writereg(state, 0x0338, 0x0000); 294 else 295 sp8870_writereg(state, 0x0338, 0x0001); 296 297 sp8870_writereg(state, 0xc05, reg0xc05); 298 299 // read status reg in order to clear pending irqs 300 err = sp8870_readreg(state, 0x200); 301 if (err < 0) 302 return err; 303 304 // system controller start 305 sp8870_microcontroller_start(state); 306 307 return 0; 308} 309 310static int sp8870_init(struct dvb_frontend *fe) 311{ 312 struct sp8870_state *state = fe->demodulator_priv; 313 const struct firmware *fw = NULL; 314 315 sp8870_wake_up(state); 316 if (state->initialised) 317 return 0; 318 state->initialised = 1; 319 320 dprintk("initialising frontend...\n"); 321 322 /* request the firmware, this will block until someone uploads it */ 323 pr_info("waiting for firmware upload (%s)...\n", SP8870_DEFAULT_FIRMWARE); 324 if (state->config->request_firmware(fe, &fw, SP8870_DEFAULT_FIRMWARE)) { 325 pr_err("no firmware upload (timeout or file not found?)\n"); 326 return -EIO; 327 } 328 329 if (sp8870_firmware_upload(state, fw)) { 330 pr_err("writing firmware to device failed\n"); 331 release_firmware(fw); 332 return -EIO; 333 } 334 release_firmware(fw); 335 pr_info("firmware upload complete\n"); 336 337 /* enable TS output and interface pins */ 338 sp8870_writereg(state, 0xc18, 0x00d); 339 340 // system controller stop 341 sp8870_microcontroller_stop(state); 342 343 // ADC mode 344 sp8870_writereg(state, 0x0301, 0x0003); 345 346 // Reed Solomon parity bytes passed to output 347 sp8870_writereg(state, 0x0C13, 0x0001); 348 349 // MPEG clock is suppressed if no valid data 350 sp8870_writereg(state, 0x0C14, 0x0001); 351 352 /* bit 0x010: enable data valid signal */ 353 sp8870_writereg(state, 0x0D00, 0x010); 354 sp8870_writereg(state, 0x0D01, 0x000); 355 356 return 0; 357} 358 359static int sp8870_read_status(struct dvb_frontend *fe, 360 enum fe_status *fe_status) 361{ 362 struct sp8870_state *state = fe->demodulator_priv; 363 int status; 364 int signal; 365 366 *fe_status = 0; 367 368 status = sp8870_readreg(state, 0x0200); 369 if (status < 0) 370 return -EIO; 371 372 signal = sp8870_readreg(state, 0x0303); 373 if (signal < 0) 374 return -EIO; 375 376 if (signal > 0x0F) 377 *fe_status |= FE_HAS_SIGNAL; 378 if (status & 0x08) 379 *fe_status |= FE_HAS_SYNC; 380 if (status & 0x04) 381 *fe_status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_VITERBI; 382 383 return 0; 384} 385 386static int sp8870_read_ber(struct dvb_frontend *fe, u32 *ber) 387{ 388 struct sp8870_state *state = fe->demodulator_priv; 389 int ret; 390 u32 tmp; 391 392 *ber = 0; 393 394 ret = sp8870_readreg(state, 0xC08); 395 if (ret < 0) 396 return -EIO; 397 398 tmp = ret & 0x3F; 399 400 ret = sp8870_readreg(state, 0xC07); 401 if (ret < 0) 402 return -EIO; 403 404 tmp = ret << 6; 405 if (tmp >= 0x3FFF0) 406 tmp = ~0; 407 408 *ber = tmp; 409 410 return 0; 411} 412 413static int sp8870_read_signal_strength(struct dvb_frontend *fe, u16 *signal) 414{ 415 struct sp8870_state *state = fe->demodulator_priv; 416 int ret; 417 u16 tmp; 418 419 *signal = 0; 420 421 ret = sp8870_readreg(state, 0x306); 422 if (ret < 0) 423 return -EIO; 424 425 tmp = ret << 8; 426 427 ret = sp8870_readreg(state, 0x303); 428 if (ret < 0) 429 return -EIO; 430 431 tmp |= ret; 432 433 if (tmp) 434 *signal = 0xFFFF - tmp; 435 436 return 0; 437} 438 439static int sp8870_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ublocks) 440{ 441 struct sp8870_state *state = fe->demodulator_priv; 442 int ret; 443 444 *ublocks = 0; 445 446 ret = sp8870_readreg(state, 0xC0C); 447 if (ret < 0) 448 return -EIO; 449 450 if (ret == 0xFFFF) 451 ret = ~0; 452 453 *ublocks = ret; 454 455 return 0; 456} 457 458/* number of trials to recover from lockup */ 459#define MAXTRIALS 5 460/* maximum checks for data valid signal */ 461#define MAXCHECKS 100 462 463/* only for debugging: counter for detected lockups */ 464static int lockups; 465/* only for debugging: counter for channel switches */ 466static int switches; 467 468static int sp8870_set_frontend(struct dvb_frontend *fe) 469{ 470 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 471 struct sp8870_state *state = fe->demodulator_priv; 472 473 /* 474 * The firmware of the sp8870 sometimes locks up after setting frontend parameters. 475 * We try to detect this by checking the data valid signal. 476 * If it is not set after MAXCHECKS we try to recover the lockup by setting 477 * the frontend parameters again. 478 */ 479 480 int err = 0; 481 int valid = 0; 482 int trials = 0; 483 int check_count = 0; 484 485 dprintk("frequency = %i\n", p->frequency); 486 487 for (trials = 1; trials <= MAXTRIALS; trials++) { 488 err = sp8870_set_frontend_parameters(fe); 489 if (err) 490 return err; 491 492 for (check_count = 0; check_count < MAXCHECKS; check_count++) { 493// valid = ((sp8870_readreg(i2c, 0x0200) & 4) == 0); 494 valid = sp8870_read_data_valid_signal(state); 495 if (valid) { 496 dprintk("delay = %i usec\n", check_count * 10); 497 break; 498 } 499 udelay(10); 500 } 501 if (valid) 502 break; 503 } 504 505 if (!valid) { 506 pr_err("%s(): firmware crash!!!!!!\n", __func__); 507 return -EIO; 508 } 509 510 if (debug) { 511 if (valid) { 512 if (trials > 1) { 513 pr_info("%s(): firmware lockup!!!\n", __func__); 514 pr_info("%s(): recovered after %i trial(s))\n", __func__, trials - 1); 515 lockups++; 516 } 517 } 518 switches++; 519 pr_info("%s(): switches = %i lockups = %i\n", __func__, switches, lockups); 520 } 521 522 return 0; 523} 524 525static int sp8870_sleep(struct dvb_frontend *fe) 526{ 527 struct sp8870_state *state = fe->demodulator_priv; 528 529 // tristate TS output and disable interface pins 530 return sp8870_writereg(state, 0xC18, 0x000); 531} 532 533static int sp8870_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *fesettings) 534{ 535 fesettings->min_delay_ms = 350; 536 fesettings->step_size = 0; 537 fesettings->max_drift = 0; 538 return 0; 539} 540 541static int sp8870_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) 542{ 543 struct sp8870_state *state = fe->demodulator_priv; 544 545 if (enable) 546 return sp8870_writereg(state, 0x206, 0x001); 547 else 548 return sp8870_writereg(state, 0x206, 0x000); 549} 550 551static void sp8870_release(struct dvb_frontend *fe) 552{ 553 struct sp8870_state *state = fe->demodulator_priv; 554 555 kfree(state); 556} 557 558static const struct dvb_frontend_ops sp8870_ops; 559 560struct dvb_frontend *sp8870_attach(const struct sp8870_config *config, 561 struct i2c_adapter *i2c) 562{ 563 struct sp8870_state *state = NULL; 564 565 /* allocate memory for the internal state */ 566 state = kzalloc(sizeof(*state), GFP_KERNEL); 567 if (!state) 568 goto error; 569 570 /* setup the state */ 571 state->config = config; 572 state->i2c = i2c; 573 state->initialised = 0; 574 575 /* check if the demod is there */ 576 if (sp8870_readreg(state, 0x0200) < 0) 577 goto error; 578 579 /* create dvb_frontend */ 580 memcpy(&state->frontend.ops, &sp8870_ops, sizeof(sp8870_ops)); 581 state->frontend.demodulator_priv = state; 582 return &state->frontend; 583 584error: 585 kfree(state); 586 return NULL; 587} 588EXPORT_SYMBOL_GPL(sp8870_attach); 589 590static const struct dvb_frontend_ops sp8870_ops = { 591 .delsys = { SYS_DVBT }, 592 .info = { 593 .name = "Spase SP8870 DVB-T", 594 .frequency_min_hz = 470 * MHz, 595 .frequency_max_hz = 860 * MHz, 596 .frequency_stepsize_hz = 166666, 597 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | 598 FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | 599 FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | 600 FE_CAN_QPSK | FE_CAN_QAM_16 | 601 FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | 602 FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER 603 }, 604 605 .release = sp8870_release, 606 607 .init = sp8870_init, 608 .sleep = sp8870_sleep, 609 .i2c_gate_ctrl = sp8870_i2c_gate_ctrl, 610 611 .set_frontend = sp8870_set_frontend, 612 .get_tune_settings = sp8870_get_tune_settings, 613 614 .read_status = sp8870_read_status, 615 .read_ber = sp8870_read_ber, 616 .read_signal_strength = sp8870_read_signal_strength, 617 .read_ucblocks = sp8870_read_uncorrected_blocks, 618}; 619 620module_param(debug, int, 0644); 621MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); 622 623MODULE_DESCRIPTION("Spase SP8870 DVB-T Demodulator driver"); 624MODULE_AUTHOR("Juergen Peitz"); 625MODULE_LICENSE("GPL");
~/
Read-only file preview.