rl6347a.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * rl6347a.c - RL6347A class device shared support
  4. *
  5. * Copyright 2015 Realtek Semiconductor Corp.
  6. *
  7. * Author: Oder Chiou <[email protected]>
  8. */
  9. #include <linux/module.h>
  10. #include <linux/i2c.h>
  11. #include <linux/regmap.h>
  12. #include "rl6347a.h"
  13. int rl6347a_hw_write(void *context, unsigned int reg, unsigned int value)
  14. {
  15. struct i2c_client *client = context;
  16. struct rl6347a_priv *rl6347a = i2c_get_clientdata(client);
  17. u8 data[4];
  18. int ret, i;
  19. /* handle index registers */
  20. if (reg <= 0xff) {
  21. rl6347a_hw_write(client, RL6347A_COEF_INDEX, reg);
  22. for (i = 0; i < rl6347a->index_cache_size; i++) {
  23. if (reg == rl6347a->index_cache[i].reg) {
  24. rl6347a->index_cache[i].def = value;
  25. break;
  26. }
  27. }
  28. reg = RL6347A_PROC_COEF;
  29. }
  30. data[0] = (reg >> 24) & 0xff;
  31. data[1] = (reg >> 16) & 0xff;
  32. /*
  33. * 4 bit VID: reg should be 0
  34. * 12 bit VID: value should be 0
  35. * So we use an OR operator to handle it rather than use if condition.
  36. */
  37. data[2] = ((reg >> 8) & 0xff) | ((value >> 8) & 0xff);
  38. data[3] = value & 0xff;
  39. ret = i2c_master_send(client, data, 4);
  40. if (ret == 4)
  41. return 0;
  42. else
  43. dev_err(&client->dev, "I2C error %d\n", ret);
  44. if (ret < 0)
  45. return ret;
  46. else
  47. return -EIO;
  48. }
  49. EXPORT_SYMBOL_GPL(rl6347a_hw_write);
  50. int rl6347a_hw_read(void *context, unsigned int reg, unsigned int *value)
  51. {
  52. struct i2c_client *client = context;
  53. struct i2c_msg xfer[2];
  54. int ret;
  55. __be32 be_reg, buf = 0x0;
  56. unsigned int index, vid;
  57. /* handle index registers */
  58. if (reg <= 0xff) {
  59. rl6347a_hw_write(client, RL6347A_COEF_INDEX, reg);
  60. reg = RL6347A_PROC_COEF;
  61. }
  62. reg = reg | 0x80000;
  63. vid = (reg >> 8) & 0xfff;
  64. if (AC_VERB_GET_AMP_GAIN_MUTE == (vid & 0xf00)) {
  65. index = (reg >> 8) & 0xf;
  66. reg = (reg & ~0xf0f) | index;
  67. }
  68. be_reg = cpu_to_be32(reg);
  69. /* Write register */
  70. xfer[0].addr = client->addr;
  71. xfer[0].flags = 0;
  72. xfer[0].len = 4;
  73. xfer[0].buf = (u8 *)&be_reg;
  74. /* Read data */
  75. xfer[1].addr = client->addr;
  76. xfer[1].flags = I2C_M_RD;
  77. xfer[1].len = 4;
  78. xfer[1].buf = (u8 *)&buf;
  79. ret = i2c_transfer(client->adapter, xfer, 2);
  80. if (ret < 0)
  81. return ret;
  82. else if (ret != 2)
  83. return -EIO;
  84. *value = be32_to_cpu(buf);
  85. return 0;
  86. }
  87. EXPORT_SYMBOL_GPL(rl6347a_hw_read);
  88. MODULE_DESCRIPTION("RL6347A class device shared support");
  89. MODULE_AUTHOR("Oder Chiou <[email protected]>");
  90. MODULE_LICENSE("GPL v2");