Commit a77bf70978a42e94790a8bc81941edc1026939ce

Authored by Simon Glass
1 parent 7d95f2a329

sound: Move Samsung-specific code into its own file

The i2s code is in fact Samsung-specific, but there might be other
implementation. Move this code into its own file. This makes it slightly
more obviously how to adjust the code to support another SoC, when someone
takes this task on.

Also drop non-FDT support, since it isn't used on Exynos 5.

Tested-by: Che-Liang Chiou <clchiou@chromium.org>
Signed-off-by: Simon Glass <sjg@chromium.org>

Showing 5 changed files with 220 additions and 221 deletions Side-by-side Diff

drivers/sound/Makefile
... ... @@ -6,7 +6,7 @@
6 6 #
7 7  
8 8 obj-$(CONFIG_SOUND) += sound.o
9   -obj-$(CONFIG_I2S) += samsung-i2s.o
  9 +obj-$(CONFIG_I2S) += sound-i2s.o
10 10 obj-$(CONFIG_I2S_SAMSUNG) += samsung-i2s.o
11 11 obj-$(CONFIG_SOUND_SANDBOX) += sandbox.o
12 12 obj-$(CONFIG_SOUND_WM8994) += wm8994.o
drivers/sound/sound-i2s.c
  1 +/*
  2 + * Copyright (C) 2012 Samsung Electronics
  3 + * R. Chandrasekar <rcsekar@samsung.com>
  4 + *
  5 + * SPDX-License-Identifier: GPL-2.0+
  6 + */
  7 +
  8 +#include <malloc.h>
  9 +#include <common.h>
  10 +#include <asm/io.h>
  11 +#include <libfdt.h>
  12 +#include <fdtdec.h>
  13 +#include <i2c.h>
  14 +#include <i2s.h>
  15 +#include <sound.h>
  16 +#include <asm/arch/sound.h>
  17 +#include "wm8994.h"
  18 +#include "max98095.h"
  19 +
  20 +/* defines */
  21 +#define SOUND_400_HZ 400
  22 +#define SOUND_BITS_IN_BYTE 8
  23 +
  24 +static struct i2stx_info g_i2stx_pri;
  25 +
  26 +/*
  27 + * get_sound_i2s_values gets values for i2s parameters
  28 + *
  29 + * @param i2stx_info i2s transmitter transfer param structure
  30 + * @param blob FDT blob if enabled else NULL
  31 + */
  32 +static int get_sound_i2s_values(struct i2stx_info *i2s, const void *blob)
  33 +{
  34 + int node;
  35 + int error = 0;
  36 + int base;
  37 +
  38 + node = fdt_path_offset(blob, "i2s");
  39 + if (node <= 0) {
  40 + debug("EXYNOS_SOUND: No node for sound in device tree\n");
  41 + return -1;
  42 + }
  43 +
  44 + /*
  45 + * Get the pre-defined sound specific values from FDT.
  46 + * All of these are expected to be correct otherwise
  47 + * wrong register values in i2s setup parameters
  48 + * may result in no sound play.
  49 + */
  50 + base = fdtdec_get_addr(blob, node, "reg");
  51 + if (base == FDT_ADDR_T_NONE) {
  52 + debug("%s: Missing i2s base\n", __func__);
  53 + return -1;
  54 + }
  55 + i2s->base_address = base;
  56 +
  57 + i2s->audio_pll_clk = fdtdec_get_int(blob,
  58 + node, "samsung,i2s-epll-clock-frequency", -1);
  59 + error |= i2s->audio_pll_clk;
  60 + debug("audio_pll_clk = %d\n", i2s->audio_pll_clk);
  61 + i2s->samplingrate = fdtdec_get_int(blob,
  62 + node, "samsung,i2s-sampling-rate", -1);
  63 + error |= i2s->samplingrate;
  64 + debug("samplingrate = %d\n", i2s->samplingrate);
  65 + i2s->bitspersample = fdtdec_get_int(blob,
  66 + node, "samsung,i2s-bits-per-sample", -1);
  67 + error |= i2s->bitspersample;
  68 + debug("bitspersample = %d\n", i2s->bitspersample);
  69 + i2s->channels = fdtdec_get_int(blob,
  70 + node, "samsung,i2s-channels", -1);
  71 + error |= i2s->channels;
  72 + debug("channels = %d\n", i2s->channels);
  73 + i2s->rfs = fdtdec_get_int(blob,
  74 + node, "samsung,i2s-lr-clk-framesize", -1);
  75 + error |= i2s->rfs;
  76 + debug("rfs = %d\n", i2s->rfs);
  77 + i2s->bfs = fdtdec_get_int(blob,
  78 + node, "samsung,i2s-bit-clk-framesize", -1);
  79 + error |= i2s->bfs;
  80 + debug("bfs = %d\n", i2s->bfs);
  81 +
  82 + i2s->id = fdtdec_get_int(blob, node, "samsung,i2s-id", -1);
  83 + error |= i2s->id;
  84 + debug("id = %d\n", i2s->id);
  85 +
  86 + if (error == -1) {
  87 + debug("fail to get sound i2s node properties\n");
  88 + return -1;
  89 + }
  90 +
  91 + return 0;
  92 +}
  93 +
  94 +/*
  95 + * Init codec
  96 + *
  97 + * @param blob FDT blob
  98 + * @param pi2s_tx i2s parameters required by codec
  99 + * @return int value, 0 for success
  100 + */
  101 +static int codec_init(const void *blob, struct i2stx_info *pi2s_tx)
  102 +{
  103 + int ret;
  104 + const char *codectype;
  105 + int node;
  106 +
  107 + /* Get the node from FDT for sound */
  108 + node = fdt_path_offset(blob, "i2s");
  109 + if (node <= 0) {
  110 + debug("EXYNOS_SOUND: No node for sound in device tree\n");
  111 + debug("node = %d\n", node);
  112 + return -1;
  113 + }
  114 +
  115 + /*
  116 + * Get the pre-defined sound codec specific values from FDT.
  117 + * All of these are expected to be correct otherwise sound
  118 + * can not be played
  119 + */
  120 + codectype = fdt_getprop(blob, node, "samsung,codec-type", NULL);
  121 + debug("device = %s\n", codectype);
  122 + if (!strcmp(codectype, "wm8994")) {
  123 + /* Check the codec type and initialise the same */
  124 + ret = wm8994_init(blob, pi2s_tx->id + 1,
  125 + pi2s_tx->samplingrate,
  126 + (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
  127 + pi2s_tx->bitspersample, pi2s_tx->channels);
  128 + } else if (!strcmp(codectype, "max98095")) {
  129 + ret = max98095_init(blob, pi2s_tx->id + 1,
  130 + pi2s_tx->samplingrate,
  131 + (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
  132 + pi2s_tx->bitspersample);
  133 + } else {
  134 + debug("%s: Unknown codec type %s\n", __func__, codectype);
  135 + return -1;
  136 + }
  137 +
  138 + if (ret) {
  139 + debug("%s: Codec init failed\n", __func__);
  140 + return -1;
  141 + }
  142 +
  143 + return 0;
  144 +}
  145 +
  146 +int sound_init(const void *blob)
  147 +{
  148 + int ret;
  149 + struct i2stx_info *pi2s_tx = &g_i2stx_pri;
  150 +
  151 + /* Get the I2S Values */
  152 + if (get_sound_i2s_values(pi2s_tx, blob) < 0) {
  153 + debug(" FDT I2S values failed\n");
  154 + return -1;
  155 + }
  156 +
  157 + if (codec_init(blob, pi2s_tx) < 0) {
  158 + debug(" Codec init failed\n");
  159 + return -1;
  160 + }
  161 +
  162 + ret = i2s_tx_init(pi2s_tx);
  163 + if (ret) {
  164 + debug("%s: Failed to init i2c transmit: ret=%d\n", __func__,
  165 + ret);
  166 + return ret;
  167 + }
  168 +
  169 +
  170 + return ret;
  171 +}
  172 +
  173 +int sound_play(uint32_t msec, uint32_t frequency)
  174 +{
  175 + unsigned int *data;
  176 + unsigned long data_size;
  177 + unsigned int ret = 0;
  178 +
  179 + /*Buffer length computation */
  180 + data_size = g_i2stx_pri.samplingrate * g_i2stx_pri.channels;
  181 + data_size *= (g_i2stx_pri.bitspersample / SOUND_BITS_IN_BYTE);
  182 + data = malloc(data_size);
  183 +
  184 + if (data == NULL) {
  185 + debug("%s: malloc failed\n", __func__);
  186 + return -1;
  187 + }
  188 +
  189 + sound_create_square_wave((unsigned short *)data,
  190 + data_size / sizeof(unsigned short),
  191 + frequency);
  192 +
  193 + while (msec >= 1000) {
  194 + ret = i2s_transfer_tx_data(&g_i2stx_pri, data,
  195 + (data_size / sizeof(int)));
  196 + msec -= 1000;
  197 + }
  198 + if (msec) {
  199 + unsigned long size =
  200 + (data_size * msec) / (sizeof(int) * 1000);
  201 +
  202 + ret = i2s_transfer_tx_data(&g_i2stx_pri, data, size);
  203 + }
  204 +
  205 + free(data);
  206 +
  207 + return ret;
  208 +}
drivers/sound/sound.c
... ... @@ -5,194 +5,11 @@
5 5 * SPDX-License-Identifier: GPL-2.0+
6 6 */
7 7  
8   -#include <malloc.h>
9 8 #include <common.h>
10   -#include <asm/io.h>
11   -#include <libfdt.h>
12   -#include <fdtdec.h>
13   -#include <i2c.h>
14   -#include <i2s.h>
15 9 #include <sound.h>
16   -#include <asm/arch/sound.h>
17   -#include "wm8994.h"
18   -#include "max98095.h"
19 10  
20   -/* defines */
21   -#define SOUND_400_HZ 400
22   -#define SOUND_BITS_IN_BYTE 8
23   -
24   -static struct i2stx_info g_i2stx_pri;
25   -
26   -/*
27   - * get_sound_i2s_values gets values for i2s parameters
28   - *
29   - * @param i2stx_info i2s transmitter transfer param structure
30   - * @param blob FDT blob if enabled else NULL
31   - */
32   -static int get_sound_i2s_values(struct i2stx_info *i2s, const void *blob)
  11 +void sound_create_square_wave(unsigned short *data, int size, uint32_t freq)
33 12 {
34   -#ifdef CONFIG_OF_CONTROL
35   - int node;
36   - int error = 0;
37   - int base;
38   -
39   - node = fdt_path_offset(blob, "i2s");
40   - if (node <= 0) {
41   - debug("EXYNOS_SOUND: No node for sound in device tree\n");
42   - return -1;
43   - }
44   -
45   - /*
46   - * Get the pre-defined sound specific values from FDT.
47   - * All of these are expected to be correct otherwise
48   - * wrong register values in i2s setup parameters
49   - * may result in no sound play.
50   - */
51   - base = fdtdec_get_addr(blob, node, "reg");
52   - if (base == FDT_ADDR_T_NONE) {
53   - debug("%s: Missing i2s base\n", __func__);
54   - return -1;
55   - }
56   - i2s->base_address = base;
57   -
58   - i2s->audio_pll_clk = fdtdec_get_int(blob,
59   - node, "samsung,i2s-epll-clock-frequency", -1);
60   - error |= i2s->audio_pll_clk;
61   - debug("audio_pll_clk = %d\n", i2s->audio_pll_clk);
62   - i2s->samplingrate = fdtdec_get_int(blob,
63   - node, "samsung,i2s-sampling-rate", -1);
64   - error |= i2s->samplingrate;
65   - debug("samplingrate = %d\n", i2s->samplingrate);
66   - i2s->bitspersample = fdtdec_get_int(blob,
67   - node, "samsung,i2s-bits-per-sample", -1);
68   - error |= i2s->bitspersample;
69   - debug("bitspersample = %d\n", i2s->bitspersample);
70   - i2s->channels = fdtdec_get_int(blob,
71   - node, "samsung,i2s-channels", -1);
72   - error |= i2s->channels;
73   - debug("channels = %d\n", i2s->channels);
74   - i2s->rfs = fdtdec_get_int(blob,
75   - node, "samsung,i2s-lr-clk-framesize", -1);
76   - error |= i2s->rfs;
77   - debug("rfs = %d\n", i2s->rfs);
78   - i2s->bfs = fdtdec_get_int(blob,
79   - node, "samsung,i2s-bit-clk-framesize", -1);
80   - error |= i2s->bfs;
81   - debug("bfs = %d\n", i2s->bfs);
82   -
83   - i2s->id = fdtdec_get_int(blob, node, "samsung,i2s-id", -1);
84   - error |= i2s->id;
85   - debug("id = %d\n", i2s->id);
86   -
87   - if (error == -1) {
88   - debug("fail to get sound i2s node properties\n");
89   - return -1;
90   - }
91   -#else
92   - i2s->base_address = samsung_get_base_i2s();
93   - i2s->audio_pll_clk = I2S_PLL_CLK;
94   - i2s->samplingrate = I2S_SAMPLING_RATE;
95   - i2s->bitspersample = I2S_BITS_PER_SAMPLE;
96   - i2s->channels = I2S_CHANNELS;
97   - i2s->rfs = I2S_RFS;
98   - i2s->bfs = I2S_BFS;
99   - i2s->id = 0;
100   -#endif
101   - return 0;
102   -}
103   -
104   -/*
105   - * Init codec
106   - *
107   - * @param blob FDT blob
108   - * @param pi2s_tx i2s parameters required by codec
109   - * @return int value, 0 for success
110   - */
111   -static int codec_init(const void *blob, struct i2stx_info *pi2s_tx)
112   -{
113   - int ret;
114   - const char *codectype;
115   -#ifdef CONFIG_OF_CONTROL
116   - int node;
117   -
118   - /* Get the node from FDT for sound */
119   - node = fdt_path_offset(blob, "i2s");
120   - if (node <= 0) {
121   - debug("EXYNOS_SOUND: No node for sound in device tree\n");
122   - debug("node = %d\n", node);
123   - return -1;
124   - }
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, pi2s_tx->id + 1,
139   - pi2s_tx->samplingrate,
140   - (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
141   - pi2s_tx->bitspersample, pi2s_tx->channels);
142   - } else if (!strcmp(codectype, "max98095")) {
143   - ret = max98095_init(blob, pi2s_tx->id + 1,
144   - pi2s_tx->samplingrate,
145   - (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
146   - pi2s_tx->bitspersample);
147   - } else {
148   - debug("%s: Unknown codec type %s\n", __func__, codectype);
149   - return -1;
150   - }
151   -
152   - if (ret) {
153   - debug("%s: Codec init failed\n", __func__);
154   - return -1;
155   - }
156   -
157   - return 0;
158   -}
159   -
160   -int sound_init(const void *blob)
161   -{
162   - int ret;
163   - struct i2stx_info *pi2s_tx = &g_i2stx_pri;
164   -
165   - /* Get the I2S Values */
166   - if (get_sound_i2s_values(pi2s_tx, blob) < 0) {
167   - debug(" FDT I2S values failed\n");
168   - return -1;
169   - }
170   -
171   - if (codec_init(blob, pi2s_tx) < 0) {
172   - debug(" Codec init failed\n");
173   - return -1;
174   - }
175   -
176   - ret = i2s_tx_init(pi2s_tx);
177   - if (ret) {
178   - debug("%s: Failed to init i2c transmit: ret=%d\n", __func__,
179   - ret);
180   - return ret;
181   - }
182   -
183   -
184   - return ret;
185   -}
186   -
187   -/*
188   - * Generates square wave sound data for 1 second
189   - *
190   - * @param data data buffer pointer
191   - * @param size size of the buffer
192   - * @param freq frequency of the wave
193   - */
194   -static void sound_prepare_buffer(unsigned short *data, int size, uint32_t freq)
195   -{
196 13 const int sample = 48000;
197 14 const unsigned short amplitude = 16000; /* between 1 and 32767 */
198 15 const int period = freq ? sample / freq : 0;
... ... @@ -217,41 +34,5 @@
217 34 *data++ = -amplitude;
218 35 }
219 36 }
220   -}
221   -
222   -int sound_play(uint32_t msec, uint32_t frequency)
223   -{
224   - unsigned int *data;
225   - unsigned long data_size;
226   - unsigned int ret = 0;
227   -
228   - /*Buffer length computation */
229   - data_size = g_i2stx_pri.samplingrate * g_i2stx_pri.channels;
230   - data_size *= (g_i2stx_pri.bitspersample / SOUND_BITS_IN_BYTE);
231   - data = malloc(data_size);
232   -
233   - if (data == NULL) {
234   - debug("%s: malloc failed\n", __func__);
235   - return -1;
236   - }
237   -
238   - sound_prepare_buffer((unsigned short *)data,
239   - data_size / sizeof(unsigned short), frequency);
240   -
241   - while (msec >= 1000) {
242   - ret = i2s_transfer_tx_data(&g_i2stx_pri, data,
243   - (data_size / sizeof(int)));
244   - msec -= 1000;
245   - }
246   - if (msec) {
247   - unsigned long size =
248   - (data_size * msec) / (sizeof(int) * 1000);
249   -
250   - ret = i2s_transfer_tx_data(&g_i2stx_pri, data, size);
251   - }
252   -
253   - free(data);
254   -
255   - return ret;
256 37 }
include/configs/exynos5250-dt.h
... ... @@ -51,6 +51,7 @@
51 51 #define CONFIG_CMD_SOUND
52 52 #ifdef CONFIG_CMD_SOUND
53 53 #define CONFIG_SOUND
  54 +#define CONFIG_I2S_SAMSUNG
54 55 #define CONFIG_I2S
55 56 #define CONFIG_SOUND_MAX98095
56 57 #define CONFIG_SOUND_WM8994
... ... @@ -30,6 +30,15 @@
30 30 };
31 31  
32 32 /*
  33 + * Generates square wave sound data for 1 second
  34 + *
  35 + * @param data data buffer pointer
  36 + * @param size size of the buffer
  37 + * @param freq frequency of the wave
  38 + */
  39 +void sound_create_square_wave(unsigned short *data, int size, uint32_t freq);
  40 +
  41 +/*
33 42 * Initialises audio sub system
34 43 * @param blob Pointer of device tree node or NULL if none.
35 44 * @return int value 0 for success, -1 for error