cx25840-firmware.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /* cx25840 firmware functions
  3. */
  4. #include <linux/module.h>
  5. #include <linux/i2c.h>
  6. #include <linux/firmware.h>
  7. #include <media/v4l2-common.h>
  8. #include <media/drv-intf/cx25840.h>
  9. #include "cx25840-core.h"
  10. /*
  11. * Mike Isely <[email protected]> - The FWSEND parameter controls the
  12. * size of the firmware chunks sent down the I2C bus to the chip.
  13. * Previously this had been set to 1024 but unfortunately some I2C
  14. * implementations can't transfer data in such big gulps.
  15. * Specifically, the pvrusb2 driver has a hard limit of around 60
  16. * bytes, due to the encapsulation there of I2C traffic into USB
  17. * messages. So we have to significantly reduce this parameter.
  18. */
  19. #define FWSEND 48
  20. #define FWDEV(x) &((x)->dev)
  21. static char *firmware = "";
  22. module_param(firmware, charp, 0444);
  23. MODULE_PARM_DESC(firmware, "Firmware image to load");
  24. static void start_fw_load(struct i2c_client *client)
  25. {
  26. /* DL_ADDR_LB=0 DL_ADDR_HB=0 */
  27. cx25840_write(client, 0x800, 0x00);
  28. cx25840_write(client, 0x801, 0x00);
  29. // DL_MAP=3 DL_AUTO_INC=0 DL_ENABLE=1
  30. cx25840_write(client, 0x803, 0x0b);
  31. /* AUTO_INC_DIS=1 */
  32. cx25840_write(client, 0x000, 0x20);
  33. }
  34. static void end_fw_load(struct i2c_client *client)
  35. {
  36. /* AUTO_INC_DIS=0 */
  37. cx25840_write(client, 0x000, 0x00);
  38. /* DL_ENABLE=0 */
  39. cx25840_write(client, 0x803, 0x03);
  40. }
  41. #define CX2388x_FIRMWARE "v4l-cx23885-avcore-01.fw"
  42. #define CX231xx_FIRMWARE "v4l-cx231xx-avcore-01.fw"
  43. #define CX25840_FIRMWARE "v4l-cx25840.fw"
  44. static const char *get_fw_name(struct i2c_client *client)
  45. {
  46. struct cx25840_state *state = to_state(i2c_get_clientdata(client));
  47. if (firmware[0])
  48. return firmware;
  49. if (is_cx2388x(state))
  50. return CX2388x_FIRMWARE;
  51. if (is_cx231xx(state))
  52. return CX231xx_FIRMWARE;
  53. return CX25840_FIRMWARE;
  54. }
  55. static int check_fw_load(struct i2c_client *client, int size)
  56. {
  57. /* DL_ADDR_HB DL_ADDR_LB */
  58. int s = cx25840_read(client, 0x801) << 8;
  59. s |= cx25840_read(client, 0x800);
  60. if (size != s) {
  61. v4l_err(client, "firmware %s load failed\n",
  62. get_fw_name(client));
  63. return -EINVAL;
  64. }
  65. v4l_info(client, "loaded %s firmware (%d bytes)\n",
  66. get_fw_name(client), size);
  67. return 0;
  68. }
  69. static int fw_write(struct i2c_client *client, const u8 *data, int size)
  70. {
  71. if (i2c_master_send(client, data, size) < size) {
  72. v4l_err(client, "firmware load i2c failure\n");
  73. return -ENOSYS;
  74. }
  75. return 0;
  76. }
  77. int cx25840_loadfw(struct i2c_client *client)
  78. {
  79. struct cx25840_state *state = to_state(i2c_get_clientdata(client));
  80. const struct firmware *fw = NULL;
  81. u8 buffer[FWSEND];
  82. const u8 *ptr;
  83. const char *fwname = get_fw_name(client);
  84. int size, retval;
  85. int max_buf_size = FWSEND;
  86. u32 gpio_oe = 0, gpio_da = 0;
  87. if (is_cx2388x(state)) {
  88. /* Preserve the GPIO OE and output bits */
  89. gpio_oe = cx25840_read(client, 0x160);
  90. gpio_da = cx25840_read(client, 0x164);
  91. }
  92. /* cx231xx cannot accept more than 16 bytes at a time */
  93. if (is_cx231xx(state) && max_buf_size > 16)
  94. max_buf_size = 16;
  95. if (request_firmware(&fw, fwname, FWDEV(client)) != 0) {
  96. v4l_err(client, "unable to open firmware %s\n", fwname);
  97. return -EINVAL;
  98. }
  99. start_fw_load(client);
  100. buffer[0] = 0x08;
  101. buffer[1] = 0x02;
  102. size = fw->size;
  103. ptr = fw->data;
  104. while (size > 0) {
  105. int len = min(max_buf_size - 2, size);
  106. memcpy(buffer + 2, ptr, len);
  107. retval = fw_write(client, buffer, len + 2);
  108. if (retval < 0) {
  109. release_firmware(fw);
  110. return retval;
  111. }
  112. size -= len;
  113. ptr += len;
  114. }
  115. end_fw_load(client);
  116. size = fw->size;
  117. release_firmware(fw);
  118. if (is_cx2388x(state)) {
  119. /* Restore GPIO configuration after f/w load */
  120. cx25840_write(client, 0x160, gpio_oe);
  121. cx25840_write(client, 0x164, gpio_da);
  122. }
  123. return check_fw_load(client, size);
  124. }
  125. MODULE_FIRMWARE(CX2388x_FIRMWARE);
  126. MODULE_FIRMWARE(CX231xx_FIRMWARE);
  127. MODULE_FIRMWARE(CX25840_FIRMWARE);