sigmadsp-i2c.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Load Analog Devices SigmaStudio firmware files
  4. *
  5. * Copyright 2009-2011 Analog Devices Inc.
  6. */
  7. #include <linux/export.h>
  8. #include <linux/i2c.h>
  9. #include <linux/module.h>
  10. #include <linux/slab.h>
  11. #include <asm/unaligned.h>
  12. #include "sigmadsp.h"
  13. static int sigmadsp_write_i2c(void *control_data,
  14. unsigned int addr, const uint8_t data[], size_t len)
  15. {
  16. uint8_t *buf;
  17. int ret;
  18. buf = kzalloc(2 + len, GFP_KERNEL | GFP_DMA);
  19. if (!buf)
  20. return -ENOMEM;
  21. put_unaligned_be16(addr, buf);
  22. memcpy(buf + 2, data, len);
  23. ret = i2c_master_send(control_data, buf, len + 2);
  24. kfree(buf);
  25. if (ret < 0)
  26. return ret;
  27. return 0;
  28. }
  29. static int sigmadsp_read_i2c(void *control_data,
  30. unsigned int addr, uint8_t data[], size_t len)
  31. {
  32. struct i2c_client *client = control_data;
  33. struct i2c_msg msgs[2];
  34. uint8_t buf[2];
  35. int ret;
  36. put_unaligned_be16(addr, buf);
  37. msgs[0].addr = client->addr;
  38. msgs[0].len = sizeof(buf);
  39. msgs[0].buf = buf;
  40. msgs[0].flags = 0;
  41. msgs[1].addr = client->addr;
  42. msgs[1].len = len;
  43. msgs[1].buf = data;
  44. msgs[1].flags = I2C_M_RD;
  45. ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
  46. if (ret < 0)
  47. return ret;
  48. else if (ret != ARRAY_SIZE(msgs))
  49. return -EIO;
  50. return 0;
  51. }
  52. /**
  53. * devm_sigmadsp_init_i2c() - Initialize SigmaDSP instance
  54. * @client: The parent I2C device
  55. * @ops: The sigmadsp_ops to use for this instance
  56. * @firmware_name: Name of the firmware file to load
  57. *
  58. * Allocates a SigmaDSP instance and loads the specified firmware file.
  59. *
  60. * Returns a pointer to a struct sigmadsp on success, or a PTR_ERR() on error.
  61. */
  62. struct sigmadsp *devm_sigmadsp_init_i2c(struct i2c_client *client,
  63. const struct sigmadsp_ops *ops, const char *firmware_name)
  64. {
  65. struct sigmadsp *sigmadsp;
  66. sigmadsp = devm_sigmadsp_init(&client->dev, ops, firmware_name);
  67. if (IS_ERR(sigmadsp))
  68. return sigmadsp;
  69. sigmadsp->control_data = client;
  70. sigmadsp->write = sigmadsp_write_i2c;
  71. sigmadsp->read = sigmadsp_read_i2c;
  72. return sigmadsp;
  73. }
  74. EXPORT_SYMBOL_GPL(devm_sigmadsp_init_i2c);
  75. MODULE_AUTHOR("Lars-Peter Clausen <[email protected]>");
  76. MODULE_DESCRIPTION("SigmaDSP I2C firmware loader");
  77. MODULE_LICENSE("GPL");