soc-io.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  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 <sound/soc.h>
  17. #include <trace/events/asoc.h>
  18. static int hw_write(struct snd_soc_codec *codec, unsigned int reg,
  19. unsigned int value)
  20. {
  21. int ret;
  22. if (!snd_soc_codec_volatile_register(codec, reg) &&
  23. reg < codec->driver->reg_cache_size &&
  24. !codec->cache_bypass) {
  25. ret = snd_soc_cache_write(codec, reg, value);
  26. if (ret < 0)
  27. return -1;
  28. }
  29. if (codec->cache_only) {
  30. codec->cache_sync = 1;
  31. return 0;
  32. }
  33. return regmap_write(codec->control_data, reg, value);
  34. }
  35. static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
  36. {
  37. int ret;
  38. unsigned int val;
  39. if (reg >= codec->driver->reg_cache_size ||
  40. snd_soc_codec_volatile_register(codec, reg) ||
  41. codec->cache_bypass) {
  42. if (codec->cache_only)
  43. return -1;
  44. ret = regmap_read(codec->control_data, reg, &val);
  45. if (ret == 0)
  46. return val;
  47. else
  48. return ret;
  49. }
  50. ret = snd_soc_cache_read(codec, reg, &val);
  51. if (ret < 0)
  52. return -1;
  53. return val;
  54. }
  55. /* Primitive bulk write support for soc-cache. The data pointed to by
  56. * `data' needs to already be in the form the hardware expects. Any
  57. * data written through this function will not go through the cache as
  58. * it only handles writing to volatile or out of bounds registers.
  59. *
  60. * This is currently only supported for devices using the regmap API
  61. * wrappers.
  62. */
  63. static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec,
  64. unsigned int reg,
  65. const void *data, size_t len)
  66. {
  67. /* To ensure that we don't get out of sync with the cache, check
  68. * whether the base register is volatile or if we've directly asked
  69. * to bypass the cache. Out of bounds registers are considered
  70. * volatile.
  71. */
  72. if (!codec->cache_bypass
  73. && !snd_soc_codec_volatile_register(codec, reg)
  74. && reg < codec->driver->reg_cache_size)
  75. return -EINVAL;
  76. return regmap_raw_write(codec->control_data, reg, data, len);
  77. }
  78. /**
  79. * snd_soc_codec_set_cache_io: Set up standard I/O functions.
  80. *
  81. * @codec: CODEC to configure.
  82. * @addr_bits: Number of bits of register address data.
  83. * @data_bits: Number of bits of data per register.
  84. * @control: Control bus used.
  85. *
  86. * Register formats are frequently shared between many I2C and SPI
  87. * devices. In order to promote code reuse the ASoC core provides
  88. * some standard implementations of CODEC read and write operations
  89. * which can be set up using this function.
  90. *
  91. * The caller is responsible for allocating and initialising the
  92. * actual cache.
  93. *
  94. * Note that at present this code cannot be used by CODECs with
  95. * volatile registers.
  96. */
  97. int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
  98. int addr_bits, int data_bits,
  99. enum snd_soc_control_type control)
  100. {
  101. struct regmap_config config;
  102. memset(&config, 0, sizeof(config));
  103. codec->write = hw_write;
  104. codec->read = hw_read;
  105. codec->bulk_write_raw = snd_soc_hw_bulk_write_raw;
  106. config.reg_bits = addr_bits;
  107. config.val_bits = data_bits;
  108. switch (control) {
  109. case SND_SOC_I2C:
  110. codec->control_data = regmap_init_i2c(to_i2c_client(codec->dev),
  111. &config);
  112. break;
  113. case SND_SOC_SPI:
  114. codec->control_data = regmap_init_spi(to_spi_device(codec->dev),
  115. &config);
  116. break;
  117. case SND_SOC_REGMAP:
  118. /* Device has made its own regmap arrangements */
  119. break;
  120. default:
  121. return -EINVAL;
  122. }
  123. if (IS_ERR(codec->control_data))
  124. return PTR_ERR(codec->control_data);
  125. return 0;
  126. }
  127. EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);