si2168.c (946e0f6ffcaa614012d646f4cf84efdd62628c8b) | si2168.c (6ab1e9438a71b642dd94a6a774fa229273d7b759) |
---|---|
1/* 2 * Silicon Labs Si2168 DVB-T/T2/C demodulator driver 3 * 4 * Copyright (C) 2014 Antti Palosaari <crope@iki.fi> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or --- 343 unchanged lines hidden (view full) --- 352} 353 354static int si2168_init(struct dvb_frontend *fe) 355{ 356 struct i2c_client *client = fe->demodulator_priv; 357 struct si2168_dev *dev = i2c_get_clientdata(client); 358 int ret, len, remaining; 359 const struct firmware *fw; | 1/* 2 * Silicon Labs Si2168 DVB-T/T2/C demodulator driver 3 * 4 * Copyright (C) 2014 Antti Palosaari <crope@iki.fi> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or --- 343 unchanged lines hidden (view full) --- 352} 353 354static int si2168_init(struct dvb_frontend *fe) 355{ 356 struct i2c_client *client = fe->demodulator_priv; 357 struct si2168_dev *dev = i2c_get_clientdata(client); 358 int ret, len, remaining; 359 const struct firmware *fw; |
360 const char *fw_name; | |
361 struct si2168_cmd cmd; | 360 struct si2168_cmd cmd; |
362 unsigned int chip_id; | |
363 364 dev_dbg(&client->dev, "\n"); 365 366 /* initialize */ 367 memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13); 368 cmd.wlen = 13; 369 cmd.rlen = 0; 370 ret = si2168_cmd_execute(client, &cmd); 371 if (ret) 372 goto err; 373 | 361 362 dev_dbg(&client->dev, "\n"); 363 364 /* initialize */ 365 memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13); 366 cmd.wlen = 13; 367 cmd.rlen = 0; 368 ret = si2168_cmd_execute(client, &cmd); 369 if (ret) 370 goto err; 371 |
374 if (dev->fw_loaded) { | 372 if (dev->warm) { |
375 /* resume */ 376 memcpy(cmd.args, "\xc0\x06\x08\x0f\x00\x20\x21\x01", 8); 377 cmd.wlen = 8; 378 cmd.rlen = 1; 379 ret = si2168_cmd_execute(client, &cmd); 380 if (ret) 381 goto err; 382 --- 10 unchanged lines hidden (view full) --- 393 /* power up */ 394 memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8); 395 cmd.wlen = 8; 396 cmd.rlen = 1; 397 ret = si2168_cmd_execute(client, &cmd); 398 if (ret) 399 goto err; 400 | 373 /* resume */ 374 memcpy(cmd.args, "\xc0\x06\x08\x0f\x00\x20\x21\x01", 8); 375 cmd.wlen = 8; 376 cmd.rlen = 1; 377 ret = si2168_cmd_execute(client, &cmd); 378 if (ret) 379 goto err; 380 --- 10 unchanged lines hidden (view full) --- 391 /* power up */ 392 memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8); 393 cmd.wlen = 8; 394 cmd.rlen = 1; 395 ret = si2168_cmd_execute(client, &cmd); 396 if (ret) 397 goto err; 398 |
401 /* query chip revision */ 402 memcpy(cmd.args, "\x02", 1); 403 cmd.wlen = 1; 404 cmd.rlen = 13; 405 ret = si2168_cmd_execute(client, &cmd); 406 if (ret) 407 goto err; 408 409 chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 | 410 cmd.args[4] << 0; 411 412 #define SI2168_A20 ('A' << 24 | 68 << 16 | '2' << 8 | '0' << 0) 413 #define SI2168_A30 ('A' << 24 | 68 << 16 | '3' << 8 | '0' << 0) 414 #define SI2168_B40 ('B' << 24 | 68 << 16 | '4' << 8 | '0' << 0) 415 416 switch (chip_id) { 417 case SI2168_A20: 418 fw_name = SI2168_A20_FIRMWARE; 419 break; 420 case SI2168_A30: 421 fw_name = SI2168_A30_FIRMWARE; 422 break; 423 case SI2168_B40: 424 fw_name = SI2168_B40_FIRMWARE; 425 break; 426 default: 427 dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n", 428 cmd.args[2], cmd.args[1], 429 cmd.args[3], cmd.args[4]); 430 ret = -EINVAL; 431 goto err; 432 } 433 434 dev_info(&client->dev, "found a 'Silicon Labs Si21%d-%c%c%c'\n", 435 cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]); 436 | |
437 /* request the firmware, this will block and timeout */ | 399 /* request the firmware, this will block and timeout */ |
438 ret = request_firmware(&fw, fw_name, &client->dev); | 400 ret = request_firmware(&fw, dev->firmware_name, &client->dev); |
439 if (ret) { 440 /* fallback mechanism to handle old name for Si2168 B40 fw */ | 401 if (ret) { 402 /* fallback mechanism to handle old name for Si2168 B40 fw */ |
441 if (chip_id == SI2168_B40) { 442 fw_name = SI2168_B40_FIRMWARE_FALLBACK; 443 ret = request_firmware(&fw, fw_name, &client->dev); | 403 if (dev->chip_id == SI2168_CHIP_ID_B40) { 404 dev->firmware_name = SI2168_B40_FIRMWARE_FALLBACK; 405 ret = request_firmware(&fw, dev->firmware_name, 406 &client->dev); |
444 } 445 446 if (ret == 0) { 447 dev_notice(&client->dev, 448 "please install firmware file '%s'\n", 449 SI2168_B40_FIRMWARE); 450 } else { 451 dev_err(&client->dev, 452 "firmware file '%s' not found\n", | 407 } 408 409 if (ret == 0) { 410 dev_notice(&client->dev, 411 "please install firmware file '%s'\n", 412 SI2168_B40_FIRMWARE); 413 } else { 414 dev_err(&client->dev, 415 "firmware file '%s' not found\n", |
453 fw_name); | 416 dev->firmware_name); |
454 goto err_release_firmware; 455 } 456 } 457 458 dev_info(&client->dev, "downloading firmware from file '%s'\n", | 417 goto err_release_firmware; 418 } 419 } 420 421 dev_info(&client->dev, "downloading firmware from file '%s'\n", |
459 fw_name); | 422 dev->firmware_name); |
460 461 if ((fw->size % 17 == 0) && (fw->data[0] > 5)) { 462 /* firmware is in the new format */ 463 for (remaining = fw->size; remaining > 0; remaining -= 17) { 464 len = fw->data[fw->size - remaining]; 465 if (len > SI2168_ARGLEN) { 466 ret = -EINVAL; 467 break; --- 38 unchanged lines hidden (view full) --- 506 /* query firmware version */ 507 memcpy(cmd.args, "\x11", 1); 508 cmd.wlen = 1; 509 cmd.rlen = 10; 510 ret = si2168_cmd_execute(client, &cmd); 511 if (ret) 512 goto err; 513 | 423 424 if ((fw->size % 17 == 0) && (fw->data[0] > 5)) { 425 /* firmware is in the new format */ 426 for (remaining = fw->size; remaining > 0; remaining -= 17) { 427 len = fw->data[fw->size - remaining]; 428 if (len > SI2168_ARGLEN) { 429 ret = -EINVAL; 430 break; --- 38 unchanged lines hidden (view full) --- 469 /* query firmware version */ 470 memcpy(cmd.args, "\x11", 1); 471 cmd.wlen = 1; 472 cmd.rlen = 10; 473 ret = si2168_cmd_execute(client, &cmd); 474 if (ret) 475 goto err; 476 |
514 dev_info(&client->dev, "firmware version: %c.%c.%d\n", 515 cmd.args[6], cmd.args[7], cmd.args[8]); | 477 dev->version = (cmd.args[9] + '@') << 24 | (cmd.args[6] - '0') << 16 | 478 (cmd.args[7] - '0') << 8 | (cmd.args[8]) << 0; 479 dev_info(&client->dev, "firmware version: %c %d.%d.%d\n", 480 dev->version >> 24 & 0xff, dev->version >> 16 & 0xff, 481 dev->version >> 8 & 0xff, dev->version >> 0 & 0xff); |
516 517 /* set ts mode */ 518 memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6); 519 cmd.args[4] |= dev->ts_mode; 520 if (dev->ts_clock_gapped) 521 cmd.args[4] |= 0x40; 522 cmd.wlen = 6; 523 cmd.rlen = 4; 524 ret = si2168_cmd_execute(client, &cmd); 525 if (ret) 526 goto err; 527 | 482 483 /* set ts mode */ 484 memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6); 485 cmd.args[4] |= dev->ts_mode; 486 if (dev->ts_clock_gapped) 487 cmd.args[4] |= 0x40; 488 cmd.wlen = 6; 489 cmd.rlen = 4; 490 ret = si2168_cmd_execute(client, &cmd); 491 if (ret) 492 goto err; 493 |
528 dev->fw_loaded = true; | 494 dev->warm = true; |
529warm: 530 dev->active = true; 531 532 return 0; 533 534err_release_firmware: 535 release_firmware(fw); 536err: --- 7 unchanged lines hidden (view full) --- 544 struct si2168_dev *dev = i2c_get_clientdata(client); 545 int ret; 546 struct si2168_cmd cmd; 547 548 dev_dbg(&client->dev, "\n"); 549 550 dev->active = false; 551 | 495warm: 496 dev->active = true; 497 498 return 0; 499 500err_release_firmware: 501 release_firmware(fw); 502err: --- 7 unchanged lines hidden (view full) --- 510 struct si2168_dev *dev = i2c_get_clientdata(client); 511 int ret; 512 struct si2168_cmd cmd; 513 514 dev_dbg(&client->dev, "\n"); 515 516 dev->active = false; 517 |
518 /* Firmware B 4.0-11 or later loses warm state during sleep */ 519 if (dev->version > ('B' << 24 | 4 << 16 | 0 << 8 | 11 << 0)) 520 dev->warm = false; 521 |
|
552 memcpy(cmd.args, "\x13", 1); 553 cmd.wlen = 1; 554 cmd.rlen = 0; 555 ret = si2168_cmd_execute(client, &cmd); 556 if (ret) 557 goto err; 558 559 return 0; --- 88 unchanged lines hidden (view full) --- 648}; 649 650static int si2168_probe(struct i2c_client *client, 651 const struct i2c_device_id *id) 652{ 653 struct si2168_config *config = client->dev.platform_data; 654 struct si2168_dev *dev; 655 int ret; | 522 memcpy(cmd.args, "\x13", 1); 523 cmd.wlen = 1; 524 cmd.rlen = 0; 525 ret = si2168_cmd_execute(client, &cmd); 526 if (ret) 527 goto err; 528 529 return 0; --- 88 unchanged lines hidden (view full) --- 618}; 619 620static int si2168_probe(struct i2c_client *client, 621 const struct i2c_device_id *id) 622{ 623 struct si2168_config *config = client->dev.platform_data; 624 struct si2168_dev *dev; 625 int ret; |
626 struct si2168_cmd cmd; |
|
656 657 dev_dbg(&client->dev, "\n"); 658 659 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 660 if (!dev) { 661 ret = -ENOMEM; 662 dev_err(&client->dev, "kzalloc() failed\n"); 663 goto err; 664 } 665 | 627 628 dev_dbg(&client->dev, "\n"); 629 630 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 631 if (!dev) { 632 ret = -ENOMEM; 633 dev_err(&client->dev, "kzalloc() failed\n"); 634 goto err; 635 } 636 |
637 i2c_set_clientdata(client, dev); |
|
666 mutex_init(&dev->i2c_mutex); 667 | 638 mutex_init(&dev->i2c_mutex); 639 |
640 /* Initialize */ 641 memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13); 642 cmd.wlen = 13; 643 cmd.rlen = 0; 644 ret = si2168_cmd_execute(client, &cmd); 645 if (ret) 646 goto err_kfree; 647 648 /* Power up */ 649 memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8); 650 cmd.wlen = 8; 651 cmd.rlen = 1; 652 ret = si2168_cmd_execute(client, &cmd); 653 if (ret) 654 goto err_kfree; 655 656 /* Query chip revision */ 657 memcpy(cmd.args, "\x02", 1); 658 cmd.wlen = 1; 659 cmd.rlen = 13; 660 ret = si2168_cmd_execute(client, &cmd); 661 if (ret) 662 goto err_kfree; 663 664 dev->chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | 665 cmd.args[3] << 8 | cmd.args[4] << 0; 666 667 switch (dev->chip_id) { 668 case SI2168_CHIP_ID_A20: 669 dev->firmware_name = SI2168_A20_FIRMWARE; 670 break; 671 case SI2168_CHIP_ID_A30: 672 dev->firmware_name = SI2168_A30_FIRMWARE; 673 break; 674 case SI2168_CHIP_ID_B40: 675 dev->firmware_name = SI2168_B40_FIRMWARE; 676 break; 677 default: 678 dev_dbg(&client->dev, "unknown chip version Si21%d-%c%c%c\n", 679 cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]); 680 ret = -ENODEV; 681 goto err_kfree; 682 } 683 684 dev->version = (cmd.args[1]) << 24 | (cmd.args[3] - '0') << 16 | 685 (cmd.args[4] - '0') << 8 | (cmd.args[5]) << 0; 686 |
|
668 /* create mux i2c adapter for tuner */ 669 dev->muxc = i2c_mux_alloc(client->adapter, &client->dev, 670 1, 0, I2C_MUX_LOCKED, 671 si2168_select, si2168_deselect); 672 if (!dev->muxc) { 673 ret = -ENOMEM; 674 goto err_kfree; 675 } --- 5 unchanged lines hidden (view full) --- 681 /* create dvb_frontend */ 682 memcpy(&dev->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops)); 683 dev->fe.demodulator_priv = client; 684 *config->i2c_adapter = dev->muxc->adapter[0]; 685 *config->fe = &dev->fe; 686 dev->ts_mode = config->ts_mode; 687 dev->ts_clock_inv = config->ts_clock_inv; 688 dev->ts_clock_gapped = config->ts_clock_gapped; | 687 /* create mux i2c adapter for tuner */ 688 dev->muxc = i2c_mux_alloc(client->adapter, &client->dev, 689 1, 0, I2C_MUX_LOCKED, 690 si2168_select, si2168_deselect); 691 if (!dev->muxc) { 692 ret = -ENOMEM; 693 goto err_kfree; 694 } --- 5 unchanged lines hidden (view full) --- 700 /* create dvb_frontend */ 701 memcpy(&dev->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops)); 702 dev->fe.demodulator_priv = client; 703 *config->i2c_adapter = dev->muxc->adapter[0]; 704 *config->fe = &dev->fe; 705 dev->ts_mode = config->ts_mode; 706 dev->ts_clock_inv = config->ts_clock_inv; 707 dev->ts_clock_gapped = config->ts_clock_gapped; |
689 dev->fw_loaded = false; | |
690 | 708 |
691 i2c_set_clientdata(client, dev); | 709 dev_info(&client->dev, "Silicon Labs Si2168-%c%d%d successfully identified\n", 710 dev->version >> 24 & 0xff, dev->version >> 16 & 0xff, 711 dev->version >> 8 & 0xff); 712 dev_info(&client->dev, "firmware version: %c %d.%d.%d\n", 713 dev->version >> 24 & 0xff, dev->version >> 16 & 0xff, 714 dev->version >> 8 & 0xff, dev->version >> 0 & 0xff); |
692 | 715 |
693 dev_info(&client->dev, "Silicon Labs Si2168 successfully attached\n"); | |
694 return 0; 695err_kfree: 696 kfree(dev); 697err: 698 dev_dbg(&client->dev, "failed=%d\n", ret); 699 return ret; 700} 701 --- 39 unchanged lines hidden --- | 716 return 0; 717err_kfree: 718 kfree(dev); 719err: 720 dev_dbg(&client->dev, "failed=%d\n", ret); 721 return ret; 722} 723 --- 39 unchanged lines hidden --- |