sound.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /*
  2. * Copyright (C) 2012 Samsung Electronics
  3. * R. Chandrasekar <rcsekar@samsung.com>
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. */
  23. #include <malloc.h>
  24. #include <common.h>
  25. #include <asm/io.h>
  26. #include <libfdt.h>
  27. #include <fdtdec.h>
  28. #include <i2c.h>
  29. #include <i2s.h>
  30. #include <sound.h>
  31. #include <asm/arch/sound.h>
  32. #include "wm8994.h"
  33. /* defines */
  34. #define SOUND_400_HZ 400
  35. #define SOUND_BITS_IN_BYTE 8
  36. static struct i2stx_info g_i2stx_pri;
  37. /*
  38. * get_sound_i2s_values gets values for i2s parameters
  39. *
  40. * @param i2stx_info i2s transmitter transfer param structure
  41. * @param blob FDT blob if enabled else NULL
  42. */
  43. static int get_sound_i2s_values(struct i2stx_info *i2s, const void *blob)
  44. {
  45. #ifdef CONFIG_OF_CONTROL
  46. int node;
  47. int error = 0;
  48. int base;
  49. node = fdtdec_next_compatible(blob, 0,
  50. COMPAT_SAMSUNG_EXYNOS5_SOUND);
  51. if (node <= 0) {
  52. debug("EXYNOS_SOUND: No node for sound in device tree\n");
  53. return -1;
  54. }
  55. /*
  56. * Get the pre-defined sound specific values from FDT.
  57. * All of these are expected to be correct otherwise
  58. * wrong register values in i2s setup parameters
  59. * may result in no sound play.
  60. */
  61. base = fdtdec_get_addr(blob, node, "reg");
  62. if (base == FDT_ADDR_T_NONE) {
  63. debug("%s: Missing i2s base\n", __func__);
  64. return -1;
  65. }
  66. i2s->base_address = base;
  67. i2s->audio_pll_clk = fdtdec_get_int(blob,
  68. node, "samsung,i2s-epll-clock-frequency", -1);
  69. error |= i2s->audio_pll_clk;
  70. debug("audio_pll_clk = %d\n", i2s->audio_pll_clk);
  71. i2s->samplingrate = fdtdec_get_int(blob,
  72. node, "samsung,i2s-sampling-rate", -1);
  73. error |= i2s->samplingrate;
  74. debug("samplingrate = %d\n", i2s->samplingrate);
  75. i2s->bitspersample = fdtdec_get_int(blob,
  76. node, "samsung,i2s-bits-per-sample", -1);
  77. error |= i2s->bitspersample;
  78. debug("bitspersample = %d\n", i2s->bitspersample);
  79. i2s->channels = fdtdec_get_int(blob,
  80. node, "samsung,i2s-channels", -1);
  81. error |= i2s->channels;
  82. debug("channels = %d\n", i2s->channels);
  83. i2s->rfs = fdtdec_get_int(blob,
  84. node, "samsung,i2s-lr-clk-framesize", -1);
  85. error |= i2s->rfs;
  86. debug("rfs = %d\n", i2s->rfs);
  87. i2s->bfs = fdtdec_get_int(blob,
  88. node, "samsung,i2s-bit-clk-framesize", -1);
  89. error |= i2s->bfs;
  90. debug("bfs = %d\n", i2s->bfs);
  91. if (error == -1) {
  92. debug("fail to get sound i2s node properties\n");
  93. return -1;
  94. }
  95. #else
  96. i2s->base_address = samsung_get_base_i2s();
  97. i2s->audio_pll_clk = I2S_PLL_CLK;
  98. i2s->samplingrate = I2S_SAMPLING_RATE;
  99. i2s->bitspersample = I2S_BITS_PER_SAMPLE;
  100. i2s->channels = I2S_CHANNELS;
  101. i2s->rfs = I2S_RFS;
  102. i2s->bfs = I2S_BFS;
  103. #endif
  104. return 0;
  105. }
  106. /*
  107. * Init codec
  108. *
  109. * @param blob FDT blob
  110. * @param pi2s_tx i2s parameters required by codec
  111. * @return int value, 0 for success
  112. */
  113. static int codec_init(const void *blob, struct i2stx_info *pi2s_tx)
  114. {
  115. int ret;
  116. const char *codectype;
  117. #ifdef CONFIG_OF_CONTROL
  118. int node;
  119. /* Get the node from FDT for sound */
  120. node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_SOUND);
  121. if (node <= 0) {
  122. debug("EXYNOS_SOUND: No node for sound in device tree\n");
  123. debug("node = %d\n", node);
  124. return -1;
  125. }
  126. /*
  127. * Get the pre-defined sound codec specific values from FDT.
  128. * All of these are expected to be correct otherwise sound
  129. * can not be played
  130. */
  131. codectype = fdt_getprop(blob, node, "samsung,codec-type", NULL);
  132. debug("device = %s\n", codectype);
  133. #else
  134. codectype = AUDIO_CODEC;
  135. #endif
  136. if (!strcmp(codectype, "wm8994")) {
  137. /* Check the codec type and initialise the same */
  138. ret = wm8994_init(blob, WM8994_AIF2,
  139. pi2s_tx->samplingrate,
  140. (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
  141. pi2s_tx->bitspersample, pi2s_tx->channels);
  142. } else {
  143. debug("%s: Unknown code type %s\n", __func__,
  144. codectype);
  145. return -1;
  146. }
  147. if (ret) {
  148. debug("%s: Codec init failed\n", __func__);
  149. return -1;
  150. }
  151. return 0;
  152. }
  153. int sound_init(const void *blob)
  154. {
  155. int ret;
  156. struct i2stx_info *pi2s_tx = &g_i2stx_pri;
  157. /* Get the I2S Values */
  158. if (get_sound_i2s_values(pi2s_tx, blob) < 0) {
  159. debug(" FDT I2S values failed\n");
  160. return -1;
  161. }
  162. if (codec_init(blob, pi2s_tx) < 0) {
  163. debug(" Codec init failed\n");
  164. return -1;
  165. }
  166. ret = i2s_tx_init(pi2s_tx);
  167. if (ret) {
  168. debug("%s: Failed to init i2c transmit: ret=%d\n", __func__,
  169. ret);
  170. return ret;
  171. }
  172. return ret;
  173. }
  174. /*
  175. * Generates square wave sound data for 1 second
  176. *
  177. * @param data data buffer pointer
  178. * @param size size of the buffer
  179. * @param freq frequency of the wave
  180. */
  181. static void sound_prepare_buffer(unsigned short *data, int size, uint32_t freq)
  182. {
  183. const int sample = 48000;
  184. const unsigned short amplitude = 16000; /* between 1 and 32767 */
  185. const int period = freq ? sample / freq : 0;
  186. const int half = period / 2;
  187. assert(freq);
  188. /* Make sure we don't overflow our buffer */
  189. if (size % 2)
  190. size--;
  191. while (size) {
  192. int i;
  193. for (i = 0; size && i < half; i++) {
  194. size -= 2;
  195. *data++ = amplitude;
  196. *data++ = amplitude;
  197. }
  198. for (i = 0; size && i < period - half; i++) {
  199. size -= 2;
  200. *data++ = -amplitude;
  201. *data++ = -amplitude;
  202. }
  203. }
  204. }
  205. int sound_play(uint32_t msec, uint32_t frequency)
  206. {
  207. unsigned int *data;
  208. unsigned long data_size;
  209. unsigned int ret = 0;
  210. /*Buffer length computation */
  211. data_size = g_i2stx_pri.samplingrate * g_i2stx_pri.channels;
  212. data_size *= (g_i2stx_pri.bitspersample / SOUND_BITS_IN_BYTE);
  213. data = malloc(data_size);
  214. if (data == NULL) {
  215. debug("%s: malloc failed\n", __func__);
  216. return -1;
  217. }
  218. sound_prepare_buffer((unsigned short *)data,
  219. data_size / sizeof(unsigned short), frequency);
  220. while (msec >= 1000) {
  221. ret = i2s_transfer_tx_data(&g_i2stx_pri, data,
  222. (data_size / sizeof(int)));
  223. msec -= 1000;
  224. }
  225. if (msec) {
  226. unsigned long size =
  227. (data_size * msec) / (sizeof(int) * 1000);
  228. ret = i2s_transfer_tx_data(&g_i2stx_pri, data, size);
  229. }
  230. free(data);
  231. return ret;
  232. }