soc-io.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * soc-io.c -- ASoC register I/O helpers
  3. *
  4. * Copyright 2009-2011 Wolfson Microelectronics PLC.
  5. *
  6. * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the
  10. * Free Software Foundation; either version 2 of the License, or (at your
  11. * option) any later version.
  12. */
  13. #include <linux/i2c.h>
  14. #include <linux/spi/spi.h>
  15. #include <linux/regmap.h>
  16. #include <linux/export.h>
  17. #include <sound/soc.h>
  18. #include <trace/events/asoc.h>
  19. #ifdef CONFIG_REGMAP
  20. static int hw_write(struct snd_soc_codec *codec, unsigned int reg,
  21. unsigned int value)
  22. {
  23. int ret;
  24. if (!snd_soc_codec_volatile_register(codec, reg) &&
  25. reg < codec->driver->reg_cache_size &&
  26. !codec->cache_bypass) {
  27. ret = snd_soc_cache_write(codec, reg, value);
  28. if (ret < 0)
  29. return -1;
  30. }
  31. if (codec->cache_only) {
  32. codec->cache_sync = 1;
  33. return 0;
  34. }
  35. return regmap_write(codec->control_data, reg, value);
  36. }
  37. static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
  38. {
  39. int ret;
  40. unsigned int val;
  41. if (reg >= codec->driver->reg_cache_size ||
  42. snd_soc_codec_volatile_register(codec, reg) ||
  43. codec->cache_bypass) {
  44. if (codec->cache_only)
  45. return -1;
  46. ret = regmap_read(codec->control_data, reg, &val);
  47. if (ret == 0)
  48. return val;
  49. else
  50. return -1;
  51. }
  52. ret = snd_soc_cache_read(codec, reg, &val);
  53. if (ret < 0)
  54. return -1;
  55. return val;
  56. }
  57. /**
  58. * snd_soc_codec_set_cache_io: Set up standard I/O functions.
  59. *
  60. * @codec: CODEC to configure.
  61. * @addr_bits: Number of bits of register address data.
  62. * @data_bits: Number of bits of data per register.
  63. * @control: Control bus used.
  64. *
  65. * Register formats are frequently shared between many I2C and SPI
  66. * devices. In order to promote code reuse the ASoC core provides
  67. * some standard implementations of CODEC read and write operations
  68. * which can be set up using this function.
  69. *
  70. * The caller is responsible for allocating and initialising the
  71. * actual cache.
  72. *
  73. * Note that at present this code cannot be used by CODECs with
  74. * volatile registers.
  75. */
  76. int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
  77. int addr_bits, int data_bits,
  78. enum snd_soc_control_type control)
  79. {
  80. struct regmap_config config;
  81. int ret;
  82. memset(&config, 0, sizeof(config));
  83. codec->write = hw_write;
  84. codec->read = hw_read;
  85. config.reg_bits = addr_bits;
  86. config.val_bits = data_bits;
  87. switch (control) {
  88. #if defined(CONFIG_REGMAP_I2C) || defined(CONFIG_REGMAP_I2C_MODULE)
  89. case SND_SOC_I2C:
  90. codec->control_data = regmap_init_i2c(to_i2c_client(codec->dev),
  91. &config);
  92. break;
  93. #endif
  94. #if defined(CONFIG_REGMAP_SPI) || defined(CONFIG_REGMAP_SPI_MODULE)
  95. case SND_SOC_SPI:
  96. codec->control_data = regmap_init_spi(to_spi_device(codec->dev),
  97. &config);
  98. break;
  99. #endif
  100. case SND_SOC_REGMAP:
  101. /* Device has made its own regmap arrangements */
  102. codec->using_regmap = true;
  103. if (!codec->control_data)
  104. codec->control_data = dev_get_regmap(codec->dev, NULL);
  105. if (codec->control_data) {
  106. ret = regmap_get_val_bytes(codec->control_data);
  107. /* Errors are legitimate for non-integer byte
  108. * multiples */
  109. if (ret > 0)
  110. codec->val_bytes = ret;
  111. }
  112. break;
  113. default:
  114. return -EINVAL;
  115. }
  116. return PTR_ERR_OR_ZERO(codec->control_data);
  117. }
  118. EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
  119. #else
  120. int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
  121. int addr_bits, int data_bits,
  122. enum snd_soc_control_type control)
  123. {
  124. return -ENOTSUPP;
  125. }
  126. EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
  127. #endif