si2157.c (e955f959ac52e145f27ff2be9078b646d0352af0) | si2157.c (7e80a8d14d9ffa5fbd10652da9a2d93c1cefd6f9) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver 4 * 5 * Copyright (C) 2014 Antti Palosaari <crope@iki.fi> 6 */ 7 8#include "si2157_priv.h" --- 357 unchanged lines hidden (view full) --- 366 memcpy(cmd.args, "\x14\x00\x02\x07\x00\x00", 6); 367 cmd.args[4] = dev->if_port; 368 cmd.wlen = 6; 369 cmd.rlen = 4; 370 ret = si2157_cmd_execute(client, &cmd); 371 if (ret) 372 goto err; 373 | 1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver 4 * 5 * Copyright (C) 2014 Antti Palosaari <crope@iki.fi> 6 */ 7 8#include "si2157_priv.h" --- 357 unchanged lines hidden (view full) --- 366 memcpy(cmd.args, "\x14\x00\x02\x07\x00\x00", 6); 367 cmd.args[4] = dev->if_port; 368 cmd.wlen = 6; 369 cmd.rlen = 4; 370 ret = si2157_cmd_execute(client, &cmd); 371 if (ret) 372 goto err; 373 |
374 /* set if frequency if needed */ | 374 /* set digital if frequency if needed */ |
375 if (if_frequency != dev->if_frequency) { 376 memcpy(cmd.args, "\x14\x00\x06\x07", 4); 377 cmd.args[4] = (if_frequency / 1000) & 0xff; 378 cmd.args[5] = ((if_frequency / 1000) >> 8) & 0xff; 379 cmd.wlen = 6; 380 cmd.rlen = 4; 381 ret = si2157_cmd_execute(client, &cmd); 382 if (ret) 383 goto err; 384 385 dev->if_frequency = if_frequency; 386 } 387 | 375 if (if_frequency != dev->if_frequency) { 376 memcpy(cmd.args, "\x14\x00\x06\x07", 4); 377 cmd.args[4] = (if_frequency / 1000) & 0xff; 378 cmd.args[5] = ((if_frequency / 1000) >> 8) & 0xff; 379 cmd.wlen = 6; 380 cmd.rlen = 4; 381 ret = si2157_cmd_execute(client, &cmd); 382 if (ret) 383 goto err; 384 385 dev->if_frequency = if_frequency; 386 } 387 |
388 /* set frequency */ | 388 /* set digital frequency */ |
389 memcpy(cmd.args, "\x41\x00\x00\x00\x00\x00\x00\x00", 8); 390 cmd.args[4] = (c->frequency >> 0) & 0xff; 391 cmd.args[5] = (c->frequency >> 8) & 0xff; 392 cmd.args[6] = (c->frequency >> 16) & 0xff; 393 cmd.args[7] = (c->frequency >> 24) & 0xff; 394 cmd.wlen = 8; 395 cmd.rlen = 1; 396 ret = si2157_cmd_execute(client, &cmd); 397 if (ret) 398 goto err; 399 | 389 memcpy(cmd.args, "\x41\x00\x00\x00\x00\x00\x00\x00", 8); 390 cmd.args[4] = (c->frequency >> 0) & 0xff; 391 cmd.args[5] = (c->frequency >> 8) & 0xff; 392 cmd.args[6] = (c->frequency >> 16) & 0xff; 393 cmd.args[7] = (c->frequency >> 24) & 0xff; 394 cmd.wlen = 8; 395 cmd.rlen = 1; 396 ret = si2157_cmd_execute(client, &cmd); 397 if (ret) 398 goto err; 399 |
400 dev->bandwidth = bandwidth; 401 dev->frequency = c->frequency; 402 |
|
400 return 0; 401err: | 403 return 0; 404err: |
405 dev->bandwidth = 0; 406 dev->frequency = 0; 407 dev->if_frequency = 0; |
|
402 dev_dbg(&client->dev, "failed=%d\n", ret); 403 return ret; 404} 405 | 408 dev_dbg(&client->dev, "failed=%d\n", ret); 409 return ret; 410} 411 |
412static int si2157_set_analog_params(struct dvb_frontend *fe, 413 struct analog_parameters *params) 414{ 415 struct i2c_client *client = fe->tuner_priv; 416 struct si2157_dev *dev = i2c_get_clientdata(client); 417 char *std; /* for debugging */ 418 int ret; 419 struct si2157_cmd cmd; 420 u32 bandwidth = 0; 421 u32 if_frequency = 0; 422 u32 freq = 0; 423 u64 tmp_lval = 0; 424 u8 system = 0; 425 u8 color = 0; /* 0=NTSC/PAL, 0x10=SECAM */ 426 u8 invert_analog = 1; /* analog tuner spectrum; 0=normal, 1=inverted */ 427 428 if (dev->chiptype != SI2157_CHIPTYPE_SI2157) { 429 dev_info(&client->dev, "Analog tuning not supported for chiptype=%u\n", 430 dev->chiptype); 431 ret = -EINVAL; 432 goto err; 433 } 434 435 if (!dev->active) 436 si2157_init(fe); 437 438 if (!dev->active) { 439 ret = -EAGAIN; 440 goto err; 441 } 442 if (params->mode == V4L2_TUNER_RADIO) { 443 /* 444 * std = "fm"; 445 * bandwidth = 1700000; //best can do for FM, AGC will be a mess though 446 * if_frequency = 1250000; //HVR-225x(saa7164), HVR-12xx(cx23885) 447 * if_frequency = 6600000; //HVR-9xx(cx231xx) 448 * if_frequency = 5500000; //HVR-19xx(pvrusb2) 449 */ 450 dev_err(&client->dev, "si2157 does not currently support FM radio\n"); 451 ret = -EINVAL; 452 goto err; 453 } 454 tmp_lval = params->frequency * 625LL; 455 do_div(tmp_lval, 10); /* convert to HZ */ 456 freq = (u32)tmp_lval; 457 458 if (freq < 1000000) /* is freq in KHz */ 459 freq = freq * 1000; 460 dev->frequency = freq; 461 462 /* if_frequency values based on tda187271C2 */ 463 if (params->std & (V4L2_STD_B | V4L2_STD_GH)) { 464 if (freq >= 470000000) { 465 std = "palGH"; 466 bandwidth = 8000000; 467 if_frequency = 6000000; 468 system = 1; 469 if (params->std & 470 (V4L2_STD_SECAM_G | V4L2_STD_SECAM_H)) { 471 std = "secamGH"; 472 color = 0x10; 473 } 474 } else { 475 std = "palB"; 476 bandwidth = 7000000; 477 if_frequency = 6000000; 478 system = 0; 479 if (params->std & V4L2_STD_SECAM_B) { 480 std = "secamB"; 481 color = 0x10; 482 } 483 } 484 } else if (params->std & V4L2_STD_MN) { 485 std = "MN"; 486 bandwidth = 6000000; 487 if_frequency = 5400000; 488 system = 2; 489 } else if (params->std & V4L2_STD_PAL_I) { 490 std = "palI"; 491 bandwidth = 8000000; 492 if_frequency = 7250000; /* TODO: does not work yet */ 493 system = 4; 494 } else if (params->std & V4L2_STD_DK) { 495 std = "palDK"; 496 bandwidth = 8000000; 497 if_frequency = 6900000; /* TODO: does not work yet */ 498 system = 5; 499 if (params->std & V4L2_STD_SECAM_DK) { 500 std = "secamDK"; 501 color = 0x10; 502 } 503 } else if (params->std & V4L2_STD_SECAM_L) { 504 std = "secamL"; 505 bandwidth = 8000000; 506 if_frequency = 6750000; /* TODO: untested */ 507 system = 6; 508 color = 0x10; 509 } else if (params->std & V4L2_STD_SECAM_LC) { 510 std = "secamL'"; 511 bandwidth = 7000000; 512 if_frequency = 1250000; /* TODO: untested */ 513 system = 7; 514 color = 0x10; 515 } else { 516 std = "unknown"; 517 } 518 /* calc channel center freq */ 519 freq = freq - 1250000 + (bandwidth / 2); 520 521 dev_dbg(&client->dev, 522 "mode=%d system=%u std='%s' params->frequency=%u center freq=%u if=%u bandwidth=%u\n", 523 params->mode, system, std, params->frequency, 524 freq, if_frequency, bandwidth); 525 526 /* set analog IF port */ 527 memcpy(cmd.args, "\x14\x00\x03\x06\x08\x02", 6); 528 /* in using dev->if_port, we assume analog and digital IF's */ 529 /* are always on different ports */ 530 /* assumes if_port definition is 0 or 1 for digital out */ 531 cmd.args[4] = (dev->if_port == 1) ? 8 : 10; 532 /* Analog AGC assumed external */ 533 cmd.args[5] = (dev->if_port == 1) ? 2 : 1; 534 cmd.wlen = 6; 535 cmd.rlen = 4; 536 ret = si2157_cmd_execute(client, &cmd); 537 if (ret) 538 goto err; 539 540 /* set analog IF output config */ 541 memcpy(cmd.args, "\x14\x00\x0d\x06\x94\x64", 6); 542 cmd.wlen = 6; 543 cmd.rlen = 4; 544 ret = si2157_cmd_execute(client, &cmd); 545 if (ret) 546 goto err; 547 548 /* make this distinct from a digital IF */ 549 dev->if_frequency = if_frequency | 1; 550 551 /* calc and set tuner analog if center frequency */ 552 if_frequency = if_frequency + 1250000 - (bandwidth / 2); 553 dev_dbg(&client->dev, "IF Ctr freq=%d\n", if_frequency); 554 555 memcpy(cmd.args, "\x14\x00\x0C\x06", 4); 556 cmd.args[4] = (if_frequency / 1000) & 0xff; 557 cmd.args[5] = ((if_frequency / 1000) >> 8) & 0xff; 558 cmd.wlen = 6; 559 cmd.rlen = 4; 560 ret = si2157_cmd_execute(client, &cmd); 561 if (ret) 562 goto err; 563 564 /* set analog AGC config */ 565 memcpy(cmd.args, "\x14\x00\x07\x06\x32\xc8", 6); 566 cmd.wlen = 6; 567 cmd.rlen = 4; 568 ret = si2157_cmd_execute(client, &cmd); 569 if (ret) 570 goto err; 571 572 /* set analog video mode */ 573 memcpy(cmd.args, "\x14\x00\x04\x06\x00\x00", 6); 574 cmd.args[4] = system | color; 575 /* can use dev->inversion if assumed applies to both digital/analog */ 576 if (invert_analog) 577 cmd.args[5] |= 0x02; 578 cmd.wlen = 6; 579 cmd.rlen = 1; 580 ret = si2157_cmd_execute(client, &cmd); 581 if (ret) 582 goto err; 583 584 /* set analog frequency */ 585 memcpy(cmd.args, "\x41\x01\x00\x00\x00\x00\x00\x00", 8); 586 cmd.args[4] = (freq >> 0) & 0xff; 587 cmd.args[5] = (freq >> 8) & 0xff; 588 cmd.args[6] = (freq >> 16) & 0xff; 589 cmd.args[7] = (freq >> 24) & 0xff; 590 cmd.wlen = 8; 591 cmd.rlen = 1; 592 ret = si2157_cmd_execute(client, &cmd); 593 if (ret) 594 goto err; 595 596 dev->bandwidth = bandwidth; 597 598 return 0; 599err: 600 dev->bandwidth = 0; 601 dev->frequency = 0; 602 dev->if_frequency = 0; 603 dev_dbg(&client->dev, "failed=%d\n", ret); 604 return ret; 605} 606 607static int si2157_get_frequency(struct dvb_frontend *fe, u32 *frequency) 608{ 609 struct i2c_client *client = fe->tuner_priv; 610 struct si2157_dev *dev = i2c_get_clientdata(client); 611 612 *frequency = dev->frequency; 613 dev_dbg(&client->dev, "freq=%u\n", dev->frequency); 614 return 0; 615} 616 617static int si2157_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) 618{ 619 struct i2c_client *client = fe->tuner_priv; 620 struct si2157_dev *dev = i2c_get_clientdata(client); 621 622 *bandwidth = dev->bandwidth; 623 dev_dbg(&client->dev, "bandwidth=%u\n", dev->bandwidth); 624 return 0; 625} 626 |
|
406static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) 407{ 408 struct i2c_client *client = fe->tuner_priv; 409 struct si2157_dev *dev = i2c_get_clientdata(client); 410 | 627static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) 628{ 629 struct i2c_client *client = fe->tuner_priv; 630 struct si2157_dev *dev = i2c_get_clientdata(client); 631 |
411 *frequency = dev->if_frequency; | 632 *frequency = dev->if_frequency & ~1; /* strip analog IF indicator bit */ 633 dev_dbg(&client->dev, "if_frequency=%u\n", *frequency); |
412 return 0; 413} 414 415static const struct dvb_tuner_ops si2157_ops = { 416 .info = { 417 .name = "Silicon Labs Si2141/Si2146/2147/2148/2157/2158", 418 .frequency_min_hz = 42 * MHz, 419 .frequency_max_hz = 870 * MHz, 420 }, 421 422 .init = si2157_init, 423 .sleep = si2157_sleep, 424 .set_params = si2157_set_params, | 634 return 0; 635} 636 637static const struct dvb_tuner_ops si2157_ops = { 638 .info = { 639 .name = "Silicon Labs Si2141/Si2146/2147/2148/2157/2158", 640 .frequency_min_hz = 42 * MHz, 641 .frequency_max_hz = 870 * MHz, 642 }, 643 644 .init = si2157_init, 645 .sleep = si2157_sleep, 646 .set_params = si2157_set_params, |
647 .set_analog_params = si2157_set_analog_params, 648 .get_frequency = si2157_get_frequency, 649 .get_bandwidth = si2157_get_bandwidth, |
|
425 .get_if_frequency = si2157_get_if_frequency, 426}; 427 428static void si2157_stat_work(struct work_struct *work) 429{ 430 struct si2157_dev *dev = container_of(work, struct si2157_dev, stat_work.work); 431 struct dvb_frontend *fe = dev->fe; 432 struct i2c_client *client = fe->tuner_priv; --- 150 unchanged lines hidden --- | 650 .get_if_frequency = si2157_get_if_frequency, 651}; 652 653static void si2157_stat_work(struct work_struct *work) 654{ 655 struct si2157_dev *dev = container_of(work, struct si2157_dev, stat_work.work); 656 struct dvb_frontend *fe = dev->fe; 657 struct i2c_client *client = fe->tuner_priv; --- 150 unchanged lines hidden --- |