summaryrefslogtreecommitdiffstats
path: root/drivers/sound
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2014-02-27 13:26:20 -0700
committerSimon Glass <sjg@chromium.org>2014-03-17 20:05:49 -0600
commita77bf70978a42e94790a8bc81941edc1026939ce (patch)
tree9481c2ad1393db98a271fde6557c227eb0fbe1a3 /drivers/sound
parent7d95f2a329c964b54cf505503a61e8fd4f12e2a3 (diff)
downloadblackbird-obmc-uboot-a77bf70978a42e94790a8bc81941edc1026939ce.tar.gz
blackbird-obmc-uboot-a77bf70978a42e94790a8bc81941edc1026939ce.zip
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>
Diffstat (limited to 'drivers/sound')
-rw-r--r--drivers/sound/Makefile2
-rw-r--r--drivers/sound/sound-i2s.c208
-rw-r--r--drivers/sound/sound.c221
3 files changed, 210 insertions, 221 deletions
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index 3793f8af9b..981ed614b1 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -6,7 +6,7 @@
#
obj-$(CONFIG_SOUND) += sound.o
-obj-$(CONFIG_I2S) += samsung-i2s.o
+obj-$(CONFIG_I2S) += sound-i2s.o
obj-$(CONFIG_I2S_SAMSUNG) += samsung-i2s.o
obj-$(CONFIG_SOUND_SANDBOX) += sandbox.o
obj-$(CONFIG_SOUND_WM8994) += wm8994.o
diff --git a/drivers/sound/sound-i2s.c b/drivers/sound/sound-i2s.c
new file mode 100644
index 0000000000..749bbbd031
--- /dev/null
+++ b/drivers/sound/sound-i2s.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * R. Chandrasekar <rcsekar@samsung.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <malloc.h>
+#include <common.h>
+#include <asm/io.h>
+#include <libfdt.h>
+#include <fdtdec.h>
+#include <i2c.h>
+#include <i2s.h>
+#include <sound.h>
+#include <asm/arch/sound.h>
+#include "wm8994.h"
+#include "max98095.h"
+
+/* defines */
+#define SOUND_400_HZ 400
+#define SOUND_BITS_IN_BYTE 8
+
+static struct i2stx_info g_i2stx_pri;
+
+/*
+ * get_sound_i2s_values gets values for i2s parameters
+ *
+ * @param i2stx_info i2s transmitter transfer param structure
+ * @param blob FDT blob if enabled else NULL
+ */
+static int get_sound_i2s_values(struct i2stx_info *i2s, const void *blob)
+{
+ int node;
+ int error = 0;
+ int base;
+
+ node = fdt_path_offset(blob, "i2s");
+ if (node <= 0) {
+ debug("EXYNOS_SOUND: No node for sound in device tree\n");
+ return -1;
+ }
+
+ /*
+ * Get the pre-defined sound specific values from FDT.
+ * All of these are expected to be correct otherwise
+ * wrong register values in i2s setup parameters
+ * may result in no sound play.
+ */
+ base = fdtdec_get_addr(blob, node, "reg");
+ if (base == FDT_ADDR_T_NONE) {
+ debug("%s: Missing i2s base\n", __func__);
+ return -1;
+ }
+ i2s->base_address = base;
+
+ i2s->audio_pll_clk = fdtdec_get_int(blob,
+ node, "samsung,i2s-epll-clock-frequency", -1);
+ error |= i2s->audio_pll_clk;
+ debug("audio_pll_clk = %d\n", i2s->audio_pll_clk);
+ i2s->samplingrate = fdtdec_get_int(blob,
+ node, "samsung,i2s-sampling-rate", -1);
+ error |= i2s->samplingrate;
+ debug("samplingrate = %d\n", i2s->samplingrate);
+ i2s->bitspersample = fdtdec_get_int(blob,
+ node, "samsung,i2s-bits-per-sample", -1);
+ error |= i2s->bitspersample;
+ debug("bitspersample = %d\n", i2s->bitspersample);
+ i2s->channels = fdtdec_get_int(blob,
+ node, "samsung,i2s-channels", -1);
+ error |= i2s->channels;
+ debug("channels = %d\n", i2s->channels);
+ i2s->rfs = fdtdec_get_int(blob,
+ node, "samsung,i2s-lr-clk-framesize", -1);
+ error |= i2s->rfs;
+ debug("rfs = %d\n", i2s->rfs);
+ i2s->bfs = fdtdec_get_int(blob,
+ node, "samsung,i2s-bit-clk-framesize", -1);
+ error |= i2s->bfs;
+ debug("bfs = %d\n", i2s->bfs);
+
+ i2s->id = fdtdec_get_int(blob, node, "samsung,i2s-id", -1);
+ error |= i2s->id;
+ debug("id = %d\n", i2s->id);
+
+ if (error == -1) {
+ debug("fail to get sound i2s node properties\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Init codec
+ *
+ * @param blob FDT blob
+ * @param pi2s_tx i2s parameters required by codec
+ * @return int value, 0 for success
+ */
+static int codec_init(const void *blob, struct i2stx_info *pi2s_tx)
+{
+ int ret;
+ const char *codectype;
+ int node;
+
+ /* Get the node from FDT for sound */
+ node = fdt_path_offset(blob, "i2s");
+ if (node <= 0) {
+ debug("EXYNOS_SOUND: No node for sound in device tree\n");
+ debug("node = %d\n", node);
+ return -1;
+ }
+
+ /*
+ * Get the pre-defined sound codec specific values from FDT.
+ * All of these are expected to be correct otherwise sound
+ * can not be played
+ */
+ codectype = fdt_getprop(blob, node, "samsung,codec-type", NULL);
+ debug("device = %s\n", codectype);
+ if (!strcmp(codectype, "wm8994")) {
+ /* Check the codec type and initialise the same */
+ ret = wm8994_init(blob, pi2s_tx->id + 1,
+ pi2s_tx->samplingrate,
+ (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
+ pi2s_tx->bitspersample, pi2s_tx->channels);
+ } else if (!strcmp(codectype, "max98095")) {
+ ret = max98095_init(blob, pi2s_tx->id + 1,
+ pi2s_tx->samplingrate,
+ (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
+ pi2s_tx->bitspersample);
+ } else {
+ debug("%s: Unknown codec type %s\n", __func__, codectype);
+ return -1;
+ }
+
+ if (ret) {
+ debug("%s: Codec init failed\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int sound_init(const void *blob)
+{
+ int ret;
+ struct i2stx_info *pi2s_tx = &g_i2stx_pri;
+
+ /* Get the I2S Values */
+ if (get_sound_i2s_values(pi2s_tx, blob) < 0) {
+ debug(" FDT I2S values failed\n");
+ return -1;
+ }
+
+ if (codec_init(blob, pi2s_tx) < 0) {
+ debug(" Codec init failed\n");
+ return -1;
+ }
+
+ ret = i2s_tx_init(pi2s_tx);
+ if (ret) {
+ debug("%s: Failed to init i2c transmit: ret=%d\n", __func__,
+ ret);
+ return ret;
+ }
+
+
+ return ret;
+}
+
+int sound_play(uint32_t msec, uint32_t frequency)
+{
+ unsigned int *data;
+ unsigned long data_size;
+ unsigned int ret = 0;
+
+ /*Buffer length computation */
+ data_size = g_i2stx_pri.samplingrate * g_i2stx_pri.channels;
+ data_size *= (g_i2stx_pri.bitspersample / SOUND_BITS_IN_BYTE);
+ data = malloc(data_size);
+
+ if (data == NULL) {
+ debug("%s: malloc failed\n", __func__);
+ return -1;
+ }
+
+ sound_create_square_wave((unsigned short *)data,
+ data_size / sizeof(unsigned short),
+ frequency);
+
+ while (msec >= 1000) {
+ ret = i2s_transfer_tx_data(&g_i2stx_pri, data,
+ (data_size / sizeof(int)));
+ msec -= 1000;
+ }
+ if (msec) {
+ unsigned long size =
+ (data_size * msec) / (sizeof(int) * 1000);
+
+ ret = i2s_transfer_tx_data(&g_i2stx_pri, data, size);
+ }
+
+ free(data);
+
+ return ret;
+}
diff --git a/drivers/sound/sound.c b/drivers/sound/sound.c
index 9b8ce5a9ef..9dda2dba82 100644
--- a/drivers/sound/sound.c
+++ b/drivers/sound/sound.c
@@ -5,193 +5,10 @@
* SPDX-License-Identifier: GPL-2.0+
*/
-#include <malloc.h>
#include <common.h>
-#include <asm/io.h>
-#include <libfdt.h>
-#include <fdtdec.h>
-#include <i2c.h>
-#include <i2s.h>
#include <sound.h>
-#include <asm/arch/sound.h>
-#include "wm8994.h"
-#include "max98095.h"
-/* defines */
-#define SOUND_400_HZ 400
-#define SOUND_BITS_IN_BYTE 8
-
-static struct i2stx_info g_i2stx_pri;
-
-/*
- * get_sound_i2s_values gets values for i2s parameters
- *
- * @param i2stx_info i2s transmitter transfer param structure
- * @param blob FDT blob if enabled else NULL
- */
-static int get_sound_i2s_values(struct i2stx_info *i2s, const void *blob)
-{
-#ifdef CONFIG_OF_CONTROL
- int node;
- int error = 0;
- int base;
-
- node = fdt_path_offset(blob, "i2s");
- if (node <= 0) {
- debug("EXYNOS_SOUND: No node for sound in device tree\n");
- return -1;
- }
-
- /*
- * Get the pre-defined sound specific values from FDT.
- * All of these are expected to be correct otherwise
- * wrong register values in i2s setup parameters
- * may result in no sound play.
- */
- base = fdtdec_get_addr(blob, node, "reg");
- if (base == FDT_ADDR_T_NONE) {
- debug("%s: Missing i2s base\n", __func__);
- return -1;
- }
- i2s->base_address = base;
-
- i2s->audio_pll_clk = fdtdec_get_int(blob,
- node, "samsung,i2s-epll-clock-frequency", -1);
- error |= i2s->audio_pll_clk;
- debug("audio_pll_clk = %d\n", i2s->audio_pll_clk);
- i2s->samplingrate = fdtdec_get_int(blob,
- node, "samsung,i2s-sampling-rate", -1);
- error |= i2s->samplingrate;
- debug("samplingrate = %d\n", i2s->samplingrate);
- i2s->bitspersample = fdtdec_get_int(blob,
- node, "samsung,i2s-bits-per-sample", -1);
- error |= i2s->bitspersample;
- debug("bitspersample = %d\n", i2s->bitspersample);
- i2s->channels = fdtdec_get_int(blob,
- node, "samsung,i2s-channels", -1);
- error |= i2s->channels;
- debug("channels = %d\n", i2s->channels);
- i2s->rfs = fdtdec_get_int(blob,
- node, "samsung,i2s-lr-clk-framesize", -1);
- error |= i2s->rfs;
- debug("rfs = %d\n", i2s->rfs);
- i2s->bfs = fdtdec_get_int(blob,
- node, "samsung,i2s-bit-clk-framesize", -1);
- error |= i2s->bfs;
- debug("bfs = %d\n", i2s->bfs);
-
- i2s->id = fdtdec_get_int(blob, node, "samsung,i2s-id", -1);
- error |= i2s->id;
- debug("id = %d\n", i2s->id);
-
- if (error == -1) {
- debug("fail to get sound i2s node properties\n");
- return -1;
- }
-#else
- i2s->base_address = samsung_get_base_i2s();
- i2s->audio_pll_clk = I2S_PLL_CLK;
- i2s->samplingrate = I2S_SAMPLING_RATE;
- i2s->bitspersample = I2S_BITS_PER_SAMPLE;
- i2s->channels = I2S_CHANNELS;
- i2s->rfs = I2S_RFS;
- i2s->bfs = I2S_BFS;
- i2s->id = 0;
-#endif
- return 0;
-}
-
-/*
- * Init codec
- *
- * @param blob FDT blob
- * @param pi2s_tx i2s parameters required by codec
- * @return int value, 0 for success
- */
-static int codec_init(const void *blob, struct i2stx_info *pi2s_tx)
-{
- int ret;
- const char *codectype;
-#ifdef CONFIG_OF_CONTROL
- int node;
-
- /* Get the node from FDT for sound */
- node = fdt_path_offset(blob, "i2s");
- if (node <= 0) {
- debug("EXYNOS_SOUND: No node for sound in device tree\n");
- debug("node = %d\n", node);
- return -1;
- }
-
- /*
- * Get the pre-defined sound codec specific values from FDT.
- * All of these are expected to be correct otherwise sound
- * can not be played
- */
- codectype = fdt_getprop(blob, node, "samsung,codec-type", NULL);
- debug("device = %s\n", codectype);
-#else
- codectype = AUDIO_CODEC;
-#endif
- if (!strcmp(codectype, "wm8994")) {
- /* Check the codec type and initialise the same */
- ret = wm8994_init(blob, pi2s_tx->id + 1,
- pi2s_tx->samplingrate,
- (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
- pi2s_tx->bitspersample, pi2s_tx->channels);
- } else if (!strcmp(codectype, "max98095")) {
- ret = max98095_init(blob, pi2s_tx->id + 1,
- pi2s_tx->samplingrate,
- (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
- pi2s_tx->bitspersample);
- } else {
- debug("%s: Unknown codec type %s\n", __func__, codectype);
- return -1;
- }
-
- if (ret) {
- debug("%s: Codec init failed\n", __func__);
- return -1;
- }
-
- return 0;
-}
-
-int sound_init(const void *blob)
-{
- int ret;
- struct i2stx_info *pi2s_tx = &g_i2stx_pri;
-
- /* Get the I2S Values */
- if (get_sound_i2s_values(pi2s_tx, blob) < 0) {
- debug(" FDT I2S values failed\n");
- return -1;
- }
-
- if (codec_init(blob, pi2s_tx) < 0) {
- debug(" Codec init failed\n");
- return -1;
- }
-
- ret = i2s_tx_init(pi2s_tx);
- if (ret) {
- debug("%s: Failed to init i2c transmit: ret=%d\n", __func__,
- ret);
- return ret;
- }
-
-
- return ret;
-}
-
-/*
- * Generates square wave sound data for 1 second
- *
- * @param data data buffer pointer
- * @param size size of the buffer
- * @param freq frequency of the wave
- */
-static void sound_prepare_buffer(unsigned short *data, int size, uint32_t freq)
+void sound_create_square_wave(unsigned short *data, int size, uint32_t freq)
{
const int sample = 48000;
const unsigned short amplitude = 16000; /* between 1 and 32767 */
@@ -218,39 +35,3 @@ static void sound_prepare_buffer(unsigned short *data, int size, uint32_t freq)
}
}
}
-
-int sound_play(uint32_t msec, uint32_t frequency)
-{
- unsigned int *data;
- unsigned long data_size;
- unsigned int ret = 0;
-
- /*Buffer length computation */
- data_size = g_i2stx_pri.samplingrate * g_i2stx_pri.channels;
- data_size *= (g_i2stx_pri.bitspersample / SOUND_BITS_IN_BYTE);
- data = malloc(data_size);
-
- if (data == NULL) {
- debug("%s: malloc failed\n", __func__);
- return -1;
- }
-
- sound_prepare_buffer((unsigned short *)data,
- data_size / sizeof(unsigned short), frequency);
-
- while (msec >= 1000) {
- ret = i2s_transfer_tx_data(&g_i2stx_pri, data,
- (data_size / sizeof(int)));
- msec -= 1000;
- }
- if (msec) {
- unsigned long size =
- (data_size * msec) / (sizeof(int) * 1000);
-
- ret = i2s_transfer_tx_data(&g_i2stx_pri, data, size);
- }
-
- free(data);
-
- return ret;
-}
OpenPOWER on IntegriCloud