summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/Kconfig1
-rw-r--r--arch/arm/dts/exynos5250-smdk5250.dts21
-rw-r--r--arch/arm/dts/exynos5250-snow.dts25
-rw-r--r--arch/arm/dts/exynos5250-spring.dts24
-rw-r--r--arch/arm/dts/exynos5250.dtsi15
-rw-r--r--arch/arm/dts/exynos5420-peach-pit.dts24
-rw-r--r--arch/arm/dts/exynos5420-smdk5420.dts21
-rw-r--r--arch/arm/dts/exynos54xx.dtsi14
-rw-r--r--arch/arm/dts/exynos5800-peach-pi.dts24
-rw-r--r--arch/arm/mach-exynos/clock.c31
-rw-r--r--arch/arm/mach-exynos/clock_init_exynos5.c2
-rw-r--r--arch/arm/mach-exynos/common_setup.h4
-rw-r--r--arch/arm/mach-exynos/include/mach/clock.h3
-rw-r--r--arch/arm/mach-exynos/include/mach/cpu.h4
-rw-r--r--arch/arm/mach-exynos/include/mach/gpio.h4
-rw-r--r--arch/arm/mach-exynos/pinmux.c19
-rw-r--r--arch/arm/mach-exynos/power.c2
-rw-r--r--arch/sandbox/cpu/sdl.c124
-rw-r--r--arch/sandbox/dts/sandbox.dts21
-rw-r--r--arch/sandbox/dts/test.dts23
-rw-r--r--arch/sandbox/include/asm/sdl.h19
-rw-r--r--arch/sandbox/include/asm/sound.h13
-rw-r--r--arch/sandbox/include/asm/test.h40
23 files changed, 378 insertions, 100 deletions
diff --git a/arch/Kconfig b/arch/Kconfig
index 947070fdd35..35e2712fce9 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -116,6 +116,7 @@ config SANDBOX
imply VIRTIO_SANDBOX
imply VIRTIO_BLK
imply VIRTIO_NET
+ imply DM_SOUND
config SH
bool "SuperH architecture"
diff --git a/arch/arm/dts/exynos5250-smdk5250.dts b/arch/arm/dts/exynos5250-smdk5250.dts
index 8b695442b1a..e542a790761 100644
--- a/arch/arm/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/dts/exynos5250-smdk5250.dts
@@ -60,9 +60,26 @@
};
i2c@12C70000 {
- soundcodec@1a {
+ wm8994: soundcodec@1a {
reg = <0x1a>;
- compatible = "wolfson,wm8994-codec";
+ u-boot,i2c-offset-len = <2>;
+ compatible = "wolfson,wm8994";
+ #sound-dai-cells = <1>;
+ };
+ };
+
+ sound {
+ compatible = "google,smdk5250-audio-wm8994";
+
+ samsung,model = "SMDK5250-I2S-WM8994";
+ samsung,audio-codec = <&wm8994>;
+
+ cpu {
+ sound-dai = <&i2s0 0>;
+ };
+
+ codec {
+ sound-dai = <&wm8994 0>;
};
};
diff --git a/arch/arm/dts/exynos5250-snow.dts b/arch/arm/dts/exynos5250-snow.dts
index 29c13c1257e..7587dc0ff24 100644
--- a/arch/arm/dts/exynos5250-snow.dts
+++ b/arch/arm/dts/exynos5250-snow.dts
@@ -40,7 +40,6 @@
mmc3 = "/mmc@12230000";
serial0 = "/serial@12C30000";
console = "/serial@12C30000";
- i2s = "/sound@3830000";
};
memory {
@@ -88,7 +87,7 @@
ro-boot {
label = "u-boot";
- reg = <0x6000 0x9a000>;
+ reg = <0x6000 0xb0000>;
read-only;
type = "blob boot,dtb";
required;
@@ -214,9 +213,10 @@
};
};
- soundcodec@22 {
- reg = <0x22>;
- compatible = "maxim,max98095-codec";
+ max98095: codec@11 {
+ compatible = "maxim,max98095";
+ reg = <0x11>;
+ #sound-dai-cells = <1>;
};
};
@@ -273,9 +273,20 @@
};
};
- sound@3830000 {
- samsung,codec-type = "max98095";
+ sound {
+ compatible = "google,snow-audio-max98095";
+
+ samsung,model = "Snow-I2S-MAX98095";
+ samsung,audio-codec = <&max98095>;
codec-enable-gpio = <&gpx1 7 GPIO_ACTIVE_HIGH>;
+
+ cpu {
+ sound-dai = <&i2s0 0>;
+ };
+
+ codec {
+ sound-dai = <&max98095 0>;
+ };
};
sound@12d60000 {
diff --git a/arch/arm/dts/exynos5250-spring.dts b/arch/arm/dts/exynos5250-spring.dts
index 7633d36874f..191e12af6a1 100644
--- a/arch/arm/dts/exynos5250-spring.dts
+++ b/arch/arm/dts/exynos5250-spring.dts
@@ -34,7 +34,6 @@
mmc0 = "/mmc@12200000";
serial0 = "/serial@12C30000";
console = "/serial@12C30000";
- i2s = "/sound@3830000";
};
memory {
@@ -639,10 +638,27 @@
};
};
- soundcodec@20 {
- reg = <0x20>;
- compatible = "maxim,max98088-codec";
+ max98095: soundcodec@10 {
+ reg = <0x10>;
+ compatible = "maxim,max98095";
+ #sound-dai-cells = <1>;
};
+
+ sound {
+ compatible = "google,spring-audio-max98095";
+
+ samsung,model = "Spring-I2S-MAX98095";
+ samsung,audio-codec = <&max98095>;
+
+ cpu {
+ sound-dai = <&i2s0 0>;
+ };
+
+ codec {
+ sound-dai = <&max98095 0>;
+ };
+ };
+
};
#include "cros-ec-keyboard.dtsi"
diff --git a/arch/arm/dts/exynos5250.dtsi b/arch/arm/dts/exynos5250.dtsi
index 502c687802e..66c5b6dca95 100644
--- a/arch/arm/dts/exynos5250.dtsi
+++ b/arch/arm/dts/exynos5250.dtsi
@@ -78,9 +78,12 @@
#size-cells = <0>;
};
- sound@3830000 {
- compatible = "samsung,exynos-sound";
- reg = <0x3830000 0x50>;
+ i2s0: i2s@3830000 {
+ compatible = "samsung,s5pv210-i2s";
+ reg = <0x03830000 0x100>;
+ samsung,idma-addr = <0x03000000>;
+ #clock-cells = <1>;
+ #sound-dai-cells = <1>;
samsung,i2s-epll-clock-frequency = <192000000>;
samsung,i2s-sampling-rate = <48000>;
samsung,i2s-bits-per-sample = <16>;
@@ -90,9 +93,11 @@
samsung,i2s-id = <0>;
};
- sound@12d60000 {
- compatible = "samsung,exynos-sound";
+ i2s1: i2s@12d60000 {
+ compatible = "samsung,s5pv210-i2s";
reg = <0x12d60000 0x20>;
+ #clock-cells = <1>;
+ #sound-dai-cells = <1>;
samsung,i2s-epll-clock-frequency = <192000000>;
samsung,i2s-sampling-rate = <48000>;
samsung,i2s-bits-per-sample = <16>;
diff --git a/arch/arm/dts/exynos5420-peach-pit.dts b/arch/arm/dts/exynos5420-peach-pit.dts
index c86f9d9035d..4a96a18110a 100644
--- a/arch/arm/dts/exynos5420-peach-pit.dts
+++ b/arch/arm/dts/exynos5420-peach-pit.dts
@@ -67,12 +67,28 @@
};
};
+ sound {
+ compatible = "google,peach-audio-max98090";
+
+ samsung,model = "PEACH-I2S-MAX98090";
+ samsung,audio-codec = <&max98090>;
+
+ cpu {
+ sound-dai = <&i2s0 0>;
+ };
+
+ codec {
+ sound-dai = <&max98090 0>;
+ };
+ };
+
i2c@12CD0000 { /* i2c7 */
clock-frequency = <100000>;
- soundcodec@20 {
- reg = <0x20>;
- compatible = "maxim,max98090-codec";
- };
+ max98090: soundcodec@10 {
+ reg = <0x10>;
+ compatible = "maxim,max98090";
+ #sound-dai-cells = <1>;
+ };
edp-lvds-bridge@48 {
compatible = "parade,ps8625";
diff --git a/arch/arm/dts/exynos5420-smdk5420.dts b/arch/arm/dts/exynos5420-smdk5420.dts
index cab5ddb61fa..7a5da674fbe 100644
--- a/arch/arm/dts/exynos5420-smdk5420.dts
+++ b/arch/arm/dts/exynos5420-smdk5420.dts
@@ -82,9 +82,26 @@
};
i2c@12C70000 {
- soundcodec@1a {
+ wm8994: soundcodec@1a {
reg = <0x1a>;
- compatible = "wolfson,wm8994-codec";
+ u-boot,i2c-offset-len = <2>;
+ compatible = "wolfson,wm8994";
+ #sound-dai-cells = <1>;
+ };
+ };
+
+ sound {
+ compatible = "samsung,smdk5420-audio-wm8994";
+
+ samsung,model = "Snow-I2S-MAX98095";
+ samsung,audio-codec = <&wm8994>;
+
+ cpu {
+ sound-dai = <&i2s0 0>;
+ };
+
+ codec {
+ sound-dai = <&wm8994 0>;
};
};
diff --git a/arch/arm/dts/exynos54xx.dtsi b/arch/arm/dts/exynos54xx.dtsi
index 09bef56e6c2..221da8b4850 100644
--- a/arch/arm/dts/exynos54xx.dtsi
+++ b/arch/arm/dts/exynos54xx.dtsi
@@ -104,6 +104,20 @@
interrupts = <0 203 0>;
};
+ i2s0: i2s@3830000 {
+ compatible = "samsung,s5pv210-i2s";
+ reg = <0x03830000 0x100>;
+ #sound-dai-cells = <1>;
+ samsung,idma-addr = <0x03000000>;
+ samsung,i2s-epll-clock-frequency = <192000000>;
+ samsung,i2s-sampling-rate = <48000>;
+ samsung,i2s-bits-per-sample = <16>;
+ samsung,i2s-channels = <2>;
+ samsung,i2s-lr-clk-framesize = <256>;
+ samsung,i2s-bit-clk-framesize = <32>;
+ samsung,i2s-id = <0>;
+ };
+
mmc@12200000 {
samsung,bus-width = <8>;
samsung,timing = <1 3 3>;
diff --git a/arch/arm/dts/exynos5800-peach-pi.dts b/arch/arm/dts/exynos5800-peach-pi.dts
index 7498519d6c6..63c0b186e42 100644
--- a/arch/arm/dts/exynos5800-peach-pi.dts
+++ b/arch/arm/dts/exynos5800-peach-pi.dts
@@ -79,12 +79,28 @@
};
};
+ sound {
+ compatible = "google,peach-audio-max98090";
+
+ samsung,model = "PEACH-I2S-MAX98090";
+ samsung,audio-codec = <&max98090>;
+
+ cpu {
+ sound-dai = <&i2s0 0>;
+ };
+
+ codec {
+ sound-dai = <&max98090 0>;
+ };
+ };
+
i2c@12CD0000 { /* i2c7 */
clock-frequency = <100000>;
- soundcodec@20 {
- reg = <0x20>;
- compatible = "maxim,max98090-codec";
- };
+ max98090: soundcodec@10 {
+ reg = <0x10>;
+ compatible = "maxim,max98090";
+ #sound-dai-cells = <1>;
+ };
};
sound@3830000 {
diff --git a/arch/arm/mach-exynos/clock.c b/arch/arm/mach-exynos/clock.c
index 6a3cd44b5d3..73aa4cdad32 100644
--- a/arch/arm/mach-exynos/clock.c
+++ b/arch/arm/mach-exynos/clock.c
@@ -345,7 +345,7 @@ static struct clk_bit_info *get_clk_bit_info(int peripheral)
int i;
struct clk_bit_info *info;
- if (proid_is_exynos5420() || proid_is_exynos5422())
+ if (proid_is_exynos542x())
info = exynos542x_bit_info;
else
info = exynos5_bit_info;
@@ -557,7 +557,7 @@ static unsigned long exynos542x_get_periph_rate(int peripheral)
unsigned long clock_get_periph_rate(int peripheral)
{
if (cpu_is_exynos5()) {
- if (proid_is_exynos5420() || proid_is_exynos5422())
+ if (proid_is_exynos542x())
return exynos542x_get_periph_rate(peripheral);
return exynos5_get_periph_rate(peripheral);
} else {
@@ -1317,6 +1317,19 @@ int exynos5_set_epll_clk(unsigned long rate)
return 0;
}
+static int exynos5420_set_i2s_clk_source(void)
+{
+ struct exynos5420_clock *clk =
+ (struct exynos5420_clock *)samsung_get_base_clock();
+
+ setbits_le32(&clk->src_top6, EXYNOS5420_CLK_SRC_MOUT_EPLL);
+ clrsetbits_le32(&clk->src_mau, EXYNOS5420_AUDIO0_SEL_MASK,
+ (EXYNOS5420_CLK_SRC_SCLK_EPLL));
+ setbits_le32(EXYNOS5_AUDIOSS_BASE, 1 << 0);
+
+ return 0;
+}
+
int exynos5_set_i2s_clk_source(unsigned int i2s_id)
{
struct exynos5_clock *clk =
@@ -1575,7 +1588,7 @@ static unsigned long exynos4_get_i2c_clk(void)
unsigned long get_pll_clk(int pllreg)
{
if (cpu_is_exynos5()) {
- if (proid_is_exynos5420() || proid_is_exynos5422())
+ if (proid_is_exynos542x())
return exynos542x_get_pll_clk(pllreg);
return exynos5_get_pll_clk(pllreg);
} else if (cpu_is_exynos4()) {
@@ -1691,7 +1704,7 @@ void set_mmc_clk(int dev_index, unsigned int div)
div -= 1;
if (cpu_is_exynos5()) {
- if (proid_is_exynos5420() || proid_is_exynos5422())
+ if (proid_is_exynos542x())
exynos5420_set_mmc_clk(dev_index, div);
else
exynos5_set_mmc_clk(dev_index, div);
@@ -1739,7 +1752,7 @@ void set_mipi_clk(void)
int set_spi_clk(int periph_id, unsigned int rate)
{
if (cpu_is_exynos5()) {
- if (proid_is_exynos5420() || proid_is_exynos5422())
+ if (proid_is_exynos542x())
return exynos5420_set_spi_clk(periph_id, rate);
return exynos5_set_spi_clk(periph_id, rate);
}
@@ -1758,8 +1771,12 @@ int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq,
int set_i2s_clk_source(unsigned int i2s_id)
{
- if (cpu_is_exynos5())
- return exynos5_set_i2s_clk_source(i2s_id);
+ if (cpu_is_exynos5()) {
+ if (proid_is_exynos542x())
+ return exynos5420_set_i2s_clk_source();
+ else
+ return exynos5_set_i2s_clk_source(i2s_id);
+ }
return 0;
}
diff --git a/arch/arm/mach-exynos/clock_init_exynos5.c b/arch/arm/mach-exynos/clock_init_exynos5.c
index e63ef645239..1cb8d391e7c 100644
--- a/arch/arm/mach-exynos/clock_init_exynos5.c
+++ b/arch/arm/mach-exynos/clock_init_exynos5.c
@@ -968,7 +968,7 @@ static void exynos5420_system_clock_init(void)
void system_clock_init(void)
{
- if (proid_is_exynos5420() || proid_is_exynos5422())
+ if (proid_is_exynos542x())
exynos5420_system_clock_init();
else
exynos5250_system_clock_init();
diff --git a/arch/arm/mach-exynos/common_setup.h b/arch/arm/mach-exynos/common_setup.h
index 2829fb269ed..4e3702b9285 100644
--- a/arch/arm/mach-exynos/common_setup.h
+++ b/arch/arm/mach-exynos/common_setup.h
@@ -78,7 +78,7 @@ static inline void configure_l2_ctlr(void)
CACHE_TAG_RAM_LATENCY_2_CYCLES |
CACHE_DATA_RAM_LATENCY_2_CYCLES;
- if (proid_is_exynos5420() || proid_is_exynos5422()) {
+ if (proid_is_exynos542x()) {
val |= CACHE_ECC_AND_PARITY |
CACHE_TAG_RAM_LATENCY_3_CYCLES |
CACHE_DATA_RAM_LATENCY_3_CYCLES;
@@ -97,7 +97,7 @@ static inline void configure_l2_actlr(void)
{
uint32_t val;
- if (proid_is_exynos5420() || proid_is_exynos5422()) {
+ if (proid_is_exynos542x()) {
mrc_l2_aux_ctlr(val);
val |= CACHE_ENABLE_FORCE_L2_LOGIC |
CACHE_DISABLE_CLEAN_EVICT;
diff --git a/arch/arm/mach-exynos/include/mach/clock.h b/arch/arm/mach-exynos/include/mach/clock.h
index edf62bdf853..e4c706adeac 100644
--- a/arch/arm/mach-exynos/include/mach/clock.h
+++ b/arch/arm/mach-exynos/include/mach/clock.h
@@ -1370,10 +1370,13 @@ struct set_epll_con_val {
#define AUDIO_1_RATIO_MASK 0x0f
#define AUDIO0_SEL_MASK 0xf
+#define EXYNOS5420_AUDIO0_SEL_MASK (0x3 << 28)
#define AUDIO1_SEL_MASK 0xf
#define CLK_SRC_SCLK_EPLL 0x7
+#define EXYNOS5420_CLK_SRC_SCLK_EPLL (0x6 << 28)
#define CLK_SRC_MOUT_EPLL (1<<12)
+#define EXYNOS5420_CLK_SRC_MOUT_EPLL BIT(20)
#define AUDIO_CLKMUX_ASS (1<<0)
/* CON0 bit-fields */
diff --git a/arch/arm/mach-exynos/include/mach/cpu.h b/arch/arm/mach-exynos/include/mach/cpu.h
index aeb3755fe6b..766edeeb298 100644
--- a/arch/arm/mach-exynos/include/mach/cpu.h
+++ b/arch/arm/mach-exynos/include/mach/cpu.h
@@ -268,6 +268,8 @@ IS_EXYNOS_TYPE(exynos5250, 0x5250)
IS_EXYNOS_TYPE(exynos5420, 0x5420)
IS_EXYNOS_TYPE(exynos5422, 0x5422)
+#define proid_is_exynos542x() (proid_is_exynos5420() || proid_is_exynos5422())
+
#define SAMSUNG_BASE(device, base) \
static inline unsigned long __attribute__((no_instrument_function)) \
samsung_get_base_##device(void) \
@@ -277,7 +279,7 @@ static inline unsigned long __attribute__((no_instrument_function)) \
return EXYNOS4X12_##base; \
return EXYNOS4_##base; \
} else if (cpu_is_exynos5()) { \
- if (proid_is_exynos5420() || proid_is_exynos5422()) \
+ if (proid_is_exynos542x()) \
return EXYNOS5420_##base; \
return EXYNOS5_##base; \
} \
diff --git a/arch/arm/mach-exynos/include/mach/gpio.h b/arch/arm/mach-exynos/include/mach/gpio.h
index 272e00bae8f..f9975d7919f 100644
--- a/arch/arm/mach-exynos/include/mach/gpio.h
+++ b/arch/arm/mach-exynos/include/mach/gpio.h
@@ -1397,7 +1397,7 @@ static struct gpio_info exynos5420_gpio_data[EXYNOS5420_GPIO_NUM_PARTS] = {
static inline struct gpio_info *get_gpio_data(void)
{
if (cpu_is_exynos5()) {
- if (proid_is_exynos5420() || proid_is_exynos5422())
+ if (proid_is_exynos542x())
return exynos5420_gpio_data;
else
return exynos5_gpio_data;
@@ -1414,7 +1414,7 @@ static inline struct gpio_info *get_gpio_data(void)
static inline unsigned int get_bank_num(void)
{
if (cpu_is_exynos5()) {
- if (proid_is_exynos5420() || proid_is_exynos5422())
+ if (proid_is_exynos542x())
return EXYNOS5420_GPIO_NUM_PARTS;
else
return EXYNOS5_GPIO_NUM_PARTS;
diff --git a/arch/arm/mach-exynos/pinmux.c b/arch/arm/mach-exynos/pinmux.c
index f6743ca0f6e..b24f1bb8f4f 100644
--- a/arch/arm/mach-exynos/pinmux.c
+++ b/arch/arm/mach-exynos/pinmux.c
@@ -378,6 +378,20 @@ static void exynos5_i2s_config(int peripheral)
}
}
+static void exynos5420_i2s_config(int peripheral)
+{
+ int i;
+
+ switch (peripheral) {
+ case PERIPH_ID_I2S0:
+ for (i = 0; i < 5; i++)
+ gpio_cfg_pin(EXYNOS5420_GPIO_Z0 + i,
+ S5P_GPIO_FUNC(0x02));
+ break;
+ }
+}
+
+
void exynos5_spi_config(int peripheral)
{
int cfg = 0, pin = 0, i;
@@ -550,6 +564,9 @@ static int exynos5420_pinmux_config(int peripheral, int flags)
case PERIPH_ID_I2C10:
exynos5420_i2c_config(peripheral);
break;
+ case PERIPH_ID_I2S0:
+ exynos5420_i2s_config(peripheral);
+ break;
case PERIPH_ID_PWM0:
gpio_cfg_pin(EXYNOS5420_GPIO_B20, S5P_GPIO_FUNC(2));
break;
@@ -863,7 +880,7 @@ static int exynos4x12_pinmux_config(int peripheral, int flags)
int exynos_pinmux_config(int peripheral, int flags)
{
if (cpu_is_exynos5()) {
- if (proid_is_exynos5420() || proid_is_exynos5422())
+ if (proid_is_exynos542x())
return exynos5420_pinmux_config(peripheral, flags);
else if (proid_is_exynos5250())
return exynos5_pinmux_config(peripheral, flags);
diff --git a/arch/arm/mach-exynos/power.c b/arch/arm/mach-exynos/power.c
index 63c410aceff..f2a6c00dd62 100644
--- a/arch/arm/mach-exynos/power.c
+++ b/arch/arm/mach-exynos/power.c
@@ -124,7 +124,7 @@ static void exynos5420_set_usbdev_phy_ctrl(unsigned int enable)
void set_usbdrd_phy_ctrl(unsigned int enable)
{
if (cpu_is_exynos5()) {
- if (proid_is_exynos5420() || proid_is_exynos5422())
+ if (proid_is_exynos542x())
exynos5420_set_usbdev_phy_ctrl(enable);
else
exynos5_set_usbdrd_phy_ctrl(enable);
diff --git a/arch/sandbox/cpu/sdl.c b/arch/sandbox/cpu/sdl.c
index c7a8d945492..f668f5379a4 100644
--- a/arch/sandbox/cpu/sdl.c
+++ b/arch/sandbox/cpu/sdl.c
@@ -4,13 +4,24 @@
*/
#include <errno.h>
+#include <unistd.h>
#include <linux/input.h>
#include <SDL/SDL.h>
-#include <sound.h>
#include <asm/state.h>
-enum {
- SAMPLE_RATE = 22050,
+/**
+ * struct buf_info - a data buffer holding audio data
+ *
+ * @pos: Current position playing in audio buffer
+ * @size: Size of data in audio buffer (0=empty)
+ * @alloced: Allocated size of audio buffer (max size it can hold)
+ * @data: Audio data
+ */
+struct buf_info {
+ uint pos;
+ uint size;
+ uint alloced;
+ uint8_t *data;
};
static struct sdl_info {
@@ -20,12 +31,12 @@ static struct sdl_info {
int depth;
int pitch;
uint frequency;
- uint audio_pos;
- uint audio_size;
uint sample_rate;
- uint8_t *audio_data;
bool audio_active;
bool inited;
+ int cur_buf;
+ struct buf_info buf[2];
+ bool running;
} sdl;
static void sandbox_sdl_poll_events(void)
@@ -243,24 +254,37 @@ int sandbox_sdl_key_pressed(int keycode)
void sandbox_sdl_fill_audio(void *udata, Uint8 *stream, int len)
{
+ struct buf_info *buf;
int avail;
+ int i;
- avail = sdl.audio_size - sdl.audio_pos;
- if (avail < len)
- len = avail;
-
- SDL_MixAudio(stream, sdl.audio_data + sdl.audio_pos, len,
- SDL_MIX_MAXVOLUME);
- sdl.audio_pos += len;
-
- /* Loop if we are at the end */
- if (sdl.audio_pos == sdl.audio_size)
- sdl.audio_pos = 0;
+ for (i = 0; i < 2; i++) {
+ buf = &sdl.buf[sdl.cur_buf];
+ avail = buf->size - buf->pos;
+ if (avail <= 0) {
+ sdl.cur_buf = 1 - sdl.cur_buf;
+ continue;
+ }
+ if (avail > len)
+ avail = len;
+
+ SDL_MixAudio(stream, buf->data + buf->pos, avail,
+ SDL_MIX_MAXVOLUME);
+ buf->pos += avail;
+ len -= avail;
+
+ /* Move to next buffer if we are at the end */
+ if (buf->pos == buf->size)
+ buf->size = 0;
+ else
+ break;
+ }
}
-int sandbox_sdl_sound_init(void)
+int sandbox_sdl_sound_init(int rate, int channels)
{
SDL_AudioSpec wanted;
+ int i;
if (sandbox_sdl_ensure_init())
return -1;
@@ -269,20 +293,27 @@ int sandbox_sdl_sound_init(void)
return 0;
/* Set the audio format */
- wanted.freq = SAMPLE_RATE;
+ wanted.freq = rate;
wanted.format = AUDIO_S16;
- wanted.channels = 1; /* 1 = mono, 2 = stereo */
+ wanted.channels = channels;
wanted.samples = 1024; /* Good low-latency value for callback */
wanted.callback = sandbox_sdl_fill_audio;
wanted.userdata = NULL;
- sdl.audio_size = sizeof(uint16_t) * wanted.freq;
- sdl.audio_data = malloc(sdl.audio_size);
- if (!sdl.audio_data) {
- printf("%s: Out of memory\n", __func__);
- return -1;
+ for (i = 0; i < 2; i++) {
+ struct buf_info *buf = &sdl.buf[i];
+
+ buf->alloced = sizeof(uint16_t) * wanted.freq * wanted.channels;
+ buf->data = malloc(buf->alloced);
+ if (!buf->data) {
+ printf("%s: Out of memory\n", __func__);
+ if (i == 1)
+ free(sdl.buf[0].data);
+ return -1;
+ }
+ buf->pos = 0;
+ buf->size = 0;
}
- sdl.audio_pos = 0;
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
printf("Unable to initialize SDL audio: %s\n", SDL_GetError());
@@ -296,33 +327,50 @@ int sandbox_sdl_sound_init(void)
}
sdl.audio_active = true;
sdl.sample_rate = wanted.freq;
+ sdl.cur_buf = 0;
+ sdl.running = 0;
return 0;
err:
- free(sdl.audio_data);
+ for (i = 0; i < 2; i++)
+ free(sdl.buf[i].data);
return -1;
}
-int sandbox_sdl_sound_start(uint frequency)
+int sandbox_sdl_sound_play(const void *data, uint size)
{
+ struct buf_info *buf;
+
if (!sdl.audio_active)
- return -1;
- sdl.frequency = frequency;
- sound_create_square_wave(sdl.sample_rate,
- (unsigned short *)sdl.audio_data,
- sdl.audio_size, frequency);
- sdl.audio_pos = 0;
- SDL_PauseAudio(0);
+ return 0;
+
+ buf = &sdl.buf[0];
+ if (buf->size)
+ buf = &sdl.buf[1];
+ while (buf->size)
+ usleep(1000);
+
+ if (size > buf->alloced)
+ return -E2BIG;
+
+ memcpy(buf->data, data, size);
+ buf->size = size;
+ buf->pos = 0;
+ if (!sdl.running) {
+ SDL_PauseAudio(0);
+ sdl.running = 1;
+ }
return 0;
}
int sandbox_sdl_sound_stop(void)
{
- if (!sdl.audio_active)
- return -1;
- SDL_PauseAudio(1);
+ if (sdl.running) {
+ SDL_PauseAudio(1);
+ sdl.running = 0;
+ }
return 0;
}
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index ce3c88c221d..ae3189ec8cf 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -18,6 +18,11 @@
stdout-path = "/serial";
};
+ audio: audio-codec {
+ compatible = "sandbox,audio-codec";
+ #sound-dai-cells = <1>;
+ };
+
cros_ec: cros-ec {
reg = <0 0>;
u-boot,dm-pre-reloc;
@@ -127,6 +132,11 @@
};
};
+ i2s: i2s {
+ compatible = "sandbox,i2s";
+ #sound-dai-cells = <1>;
+ };
+
lcd {
u-boot,dm-pre-reloc;
compatible = "sandbox,lcd-sdl";
@@ -190,6 +200,17 @@
compatible = "sandbox,reset";
};
+ sound {
+ compatible = "sandbox,sound";
+ cpu {
+ sound-dai = <&i2s 0>;
+ };
+
+ codec {
+ sound-dai = <&audio 0>;
+ };
+ };
+
spi@0 {
u-boot,dm-pre-reloc;
#address-cells = <1>;
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 6b1c2692baa..3790b4c5208 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -42,6 +42,11 @@
osd0 = "/osd";
};
+ audio: audio-codec {
+ compatible = "sandbox,audio-codec";
+ #sound-dai-cells = <1>;
+ };
+
cros_ec: cros-ec {
reg = <0 0>;
compatible = "google,cros-ec-sandbox";
@@ -82,6 +87,8 @@
test2-gpios = <&gpio_a 1>, <&gpio_a 4>, <&gpio_b 6 1 3 2 1>,
<&gpio_b 7 2 3 2 1>, <&gpio_b 8 4 3 2 1>,
<&gpio_b 9 0xc 3 2 1>;
+ int-value = <1234>;
+ uint-value = <(-1234)>;
};
junk {
@@ -373,6 +380,11 @@
u-boot,dm-pre-reloc;
};
+ i2s: i2s {
+ compatible = "sandbox,i2s";
+ #sound-dai-cells = <1>;
+ };
+
misc-test {
compatible = "sandbox,misc_sandbox";
};
@@ -528,6 +540,17 @@
compatible = "sandbox,smem";
};
+ sound {
+ compatible = "sandbox,sound";
+ cpu {
+ sound-dai = <&i2s 0>;
+ };
+
+ codec {
+ sound-dai = <&audio 0>;
+ };
+ };
+
spi@0 {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/sandbox/include/asm/sdl.h b/arch/sandbox/include/asm/sdl.h
index 1c4380c592a..1027b59e732 100644
--- a/arch/sandbox/include/asm/sdl.h
+++ b/arch/sandbox/include/asm/sdl.h
@@ -54,12 +54,12 @@ int sandbox_sdl_scan_keys(int key[], int max_keys);
int sandbox_sdl_key_pressed(int keycode);
/**
- * sandbox_sdl_sound_start() - start playing a sound
+ * sandbox_sdl_sound_play() - Play a sound
*
- * @frequency: Frequency of sounds in Hertz
- * @return 0 if OK, -ENODEV if no sound is available
+ * @data: Data to play (typically 16-bit)
+ * @count: Number of bytes in data
*/
-int sandbox_sdl_sound_start(uint frequency);
+int sandbox_sdl_sound_play(const void *data, uint count);
/**
* sandbox_sdl_sound_stop() - stop playing a sound
@@ -71,9 +71,11 @@ int sandbox_sdl_sound_stop(void);
/**
* sandbox_sdl_sound_init() - set up the sound system
*
+ * @rate: Sample rate to use
+ * @channels: Number of channels to use (1=mono, 2=stereo)
* @return 0 if OK, -ENODEV if no sound is available
*/
-int sandbox_sdl_sound_init(void);
+int sandbox_sdl_sound_init(int rate, int channels);
#else
static inline int sandbox_sdl_init_display(int width, int height,
@@ -102,12 +104,17 @@ static inline int sandbox_sdl_sound_start(uint frequency)
return -ENODEV;
}
+int sandbox_sdl_sound_play(const void *data, uint count)
+{
+ return -ENODEV;
+}
+
static inline int sandbox_sdl_sound_stop(void)
{
return -ENODEV;
}
-static inline int sandbox_sdl_sound_init(void)
+int sandbox_sdl_sound_init(int rate, int channels)
{
return -ENODEV;
}
diff --git a/arch/sandbox/include/asm/sound.h b/arch/sandbox/include/asm/sound.h
deleted file mode 100644
index a6015b0f60f..00000000000
--- a/arch/sandbox/include/asm/sound.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 2013 Google, Inc
- */
-
-#ifndef __SANDBOX_SOUND_H
-#define __SANDBOX_SOUND_H
-
-int sound_play(unsigned int msec, unsigned int frequency);
-
-int sound_init(const void *blob);
-
-#endif
diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h
index 5e818392959..74f96188220 100644
--- a/arch/sandbox/include/asm/test.h
+++ b/arch/sandbox/include/asm/test.h
@@ -121,4 +121,44 @@ int sandbox_pwm_get_config(struct udevice *dev, uint channel, uint *period_nsp,
*/
void sandbox_sf_set_block_protect(struct udevice *dev, int bp_mask);
+/**
+ * sandbox_get_codec_params() - Read back codec parameters
+ *
+ * This reads back the parameters set by audio_codec_set_params() for the
+ * sandbox audio driver. Arguments are as for that function.
+ */
+void sandbox_get_codec_params(struct udevice *dev, int *interfacep, int *ratep,
+ int *mclk_freqp, int *bits_per_samplep,
+ uint *channelsp);
+
+/**
+ * sandbox_get_i2s_sum() - Read back the sum of the audio data so far
+ *
+ * This data is provided to the sandbox driver by the I2S tx_data() method.
+ *
+ * @dev: Device to check
+ * @return sum of audio data
+ */
+int sandbox_get_i2s_sum(struct udevice *dev);
+
+/**
+ * sandbox_get_setup_called() - Returns the number of times setup(*) was called
+ *
+ * This is used in the sound test
+ *
+ * @dev: Device to check
+ * @return call count for the setup() method
+ */
+int sandbox_get_setup_called(struct udevice *dev);
+
+/**
+ * sandbox_get_sound_sum() - Read back the sum of the sound data so far
+ *
+ * This data is provided to the sandbox driver by the sound play() method.
+ *
+ * @dev: Device to check
+ * @return sum of audio data
+ */
+int sandbox_get_sound_sum(struct udevice *dev);
+
#endif