summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/Kconfig8
-rw-r--r--sound/soc/codecs/es8328-i2c.c2
-rw-r--r--sound/soc/codecs/es8328.c20
-rw-r--r--sound/soc/dwc/designware_i2s.c9
-rw-r--r--sound/soc/dwc/designware_pcm.c99
-rw-r--r--sound/soc/dwc/local.h9
-rw-r--r--sound/soc/fsl/efika-audio-fabric.c1
-rw-r--r--sound/soc/fsl/fsl_sai.c4
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.c1
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.h13
-rw-r--r--sound/soc/soc-core.c38
11 files changed, 131 insertions, 73 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 928baa69de91..e00ba806ef86 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -525,14 +525,16 @@ config SND_SOC_HDMI_CODEC
select HDMI
config SND_SOC_ES8328
- tristate "Everest Semi ES8328 CODEC"
+ tristate
config SND_SOC_ES8328_I2C
- tristate
+ tristate "Everest Semi ES8328 CODEC (I2C)"
+ depends on I2C
select SND_SOC_ES8328
config SND_SOC_ES8328_SPI
- tristate
+ tristate "Everest Semi ES8328 CODEC (SPI)"
+ depends on SPI_MASTER
select SND_SOC_ES8328
config SND_SOC_GTM601
diff --git a/sound/soc/codecs/es8328-i2c.c b/sound/soc/codecs/es8328-i2c.c
index 2d05b5d3a6ce..318ab28c5351 100644
--- a/sound/soc/codecs/es8328-i2c.c
+++ b/sound/soc/codecs/es8328-i2c.c
@@ -20,12 +20,14 @@
static const struct i2c_device_id es8328_id[] = {
{ "es8328", 0 },
+ { "es8388", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, es8328_id);
static const struct of_device_id es8328_of_match[] = {
{ .compatible = "everest,es8328", },
+ { .compatible = "everest,es8388", },
{ }
};
MODULE_DEVICE_TABLE(of, es8328_of_match);
diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c
index 37722194b107..3f84fbd071e2 100644
--- a/sound/soc/codecs/es8328.c
+++ b/sound/soc/codecs/es8328.c
@@ -589,9 +589,21 @@ static int es8328_set_dai_fmt(struct snd_soc_dai *codec_dai,
u8 dac_mode = 0;
u8 adc_mode = 0;
- /* set master/slave audio interface */
- if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBM_CFM)
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ /* Master serial port mode, with BCLK generated automatically */
+ snd_soc_update_bits(codec, ES8328_MASTERMODE,
+ ES8328_MASTERMODE_MSC,
+ ES8328_MASTERMODE_MSC);
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ /* Slave serial port mode */
+ snd_soc_update_bits(codec, ES8328_MASTERMODE,
+ ES8328_MASTERMODE_MSC, 0);
+ break;
+ default:
return -EINVAL;
+ }
/* interface format */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -620,10 +632,6 @@ static int es8328_set_dai_fmt(struct snd_soc_dai *codec_dai,
snd_soc_update_bits(codec, ES8328_ADCCONTROL4,
ES8328_ADCCONTROL4_ADCFORMAT_MASK, adc_mode);
- /* Master serial port mode, with BCLK generated automatically */
- snd_soc_update_bits(codec, ES8328_MASTERMODE,
- ES8328_MASTERMODE_MSC, ES8328_MASTERMODE_MSC);
-
return 0;
}
diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c
index bdf8398cbc81..9c46e4112026 100644
--- a/sound/soc/dwc/designware_i2s.c
+++ b/sound/soc/dwc/designware_i2s.c
@@ -121,9 +121,14 @@ static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
irq_valid = true;
}
- /* Data available. Record mode not supported in PIO mode */
- if (isr[i] & ISR_RXDA)
+ /*
+ * Data available. Retrieve samples from FIFO
+ * NOTE: Only two channels supported
+ */
+ if ((isr[i] & ISR_RXDA) && (i == 0) && dev->use_pio) {
+ dw_pcm_pop_rx(dev);
irq_valid = true;
+ }
/* Error Handling: TX */
if (isr[i] & ISR_TXFO) {
diff --git a/sound/soc/dwc/designware_pcm.c b/sound/soc/dwc/designware_pcm.c
index 4a83a22fa3cb..459ec861e6b6 100644
--- a/sound/soc/dwc/designware_pcm.c
+++ b/sound/soc/dwc/designware_pcm.c
@@ -41,10 +41,33 @@ static unsigned int dw_pcm_tx_##sample_bits(struct dw_i2s_dev *dev, \
return tx_ptr; \
}
+#define dw_pcm_rx_fn(sample_bits) \
+static unsigned int dw_pcm_rx_##sample_bits(struct dw_i2s_dev *dev, \
+ struct snd_pcm_runtime *runtime, unsigned int rx_ptr, \
+ bool *period_elapsed) \
+{ \
+ u##sample_bits (*p)[2] = (void *)runtime->dma_area; \
+ unsigned int period_pos = rx_ptr % runtime->period_size; \
+ int i; \
+\
+ for (i = 0; i < dev->fifo_th; i++) { \
+ p[rx_ptr][0] = ioread32(dev->i2s_base + LRBR_LTHR(0)); \
+ p[rx_ptr][1] = ioread32(dev->i2s_base + RRBR_RTHR(0)); \
+ period_pos++; \
+ if (++rx_ptr >= runtime->buffer_size) \
+ rx_ptr = 0; \
+ } \
+ *period_elapsed = period_pos >= runtime->period_size; \
+ return rx_ptr; \
+}
+
dw_pcm_tx_fn(16);
dw_pcm_tx_fn(32);
+dw_pcm_rx_fn(16);
+dw_pcm_rx_fn(32);
#undef dw_pcm_tx_fn
+#undef dw_pcm_rx_fn
static const struct snd_pcm_hardware dw_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
@@ -57,6 +80,7 @@ static const struct snd_pcm_hardware dw_pcm_hardware = {
.rate_min = 32000,
.rate_max = 48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
.channels_min = 2,
.channels_max = 2,
@@ -68,27 +92,51 @@ static const struct snd_pcm_hardware dw_pcm_hardware = {
.fifo_size = 16,
};
-void dw_pcm_push_tx(struct dw_i2s_dev *dev)
+static void dw_pcm_transfer(struct dw_i2s_dev *dev, bool push)
{
- struct snd_pcm_substream *tx_substream;
- bool tx_active, period_elapsed;
+ struct snd_pcm_substream *substream;
+ bool active, period_elapsed;
rcu_read_lock();
- tx_substream = rcu_dereference(dev->tx_substream);
- tx_active = tx_substream && snd_pcm_running(tx_substream);
- if (tx_active) {
- unsigned int tx_ptr = READ_ONCE(dev->tx_ptr);
- unsigned int new_tx_ptr = dev->tx_fn(dev, tx_substream->runtime,
- tx_ptr, &period_elapsed);
- cmpxchg(&dev->tx_ptr, tx_ptr, new_tx_ptr);
+ if (push)
+ substream = rcu_dereference(dev->tx_substream);
+ else
+ substream = rcu_dereference(dev->rx_substream);
+ active = substream && snd_pcm_running(substream);
+ if (active) {
+ unsigned int ptr;
+ unsigned int new_ptr;
+
+ if (push) {
+ ptr = READ_ONCE(dev->tx_ptr);
+ new_ptr = dev->tx_fn(dev, substream->runtime, ptr,
+ &period_elapsed);
+ cmpxchg(&dev->tx_ptr, ptr, new_ptr);
+ } else {
+ ptr = READ_ONCE(dev->rx_ptr);
+ new_ptr = dev->rx_fn(dev, substream->runtime, ptr,
+ &period_elapsed);
+ cmpxchg(&dev->rx_ptr, ptr, new_ptr);
+ }
if (period_elapsed)
- snd_pcm_period_elapsed(tx_substream);
+ snd_pcm_period_elapsed(substream);
}
rcu_read_unlock();
}
+
+void dw_pcm_push_tx(struct dw_i2s_dev *dev)
+{
+ dw_pcm_transfer(dev, true);
+}
EXPORT_SYMBOL_GPL(dw_pcm_push_tx);
+void dw_pcm_pop_rx(struct dw_i2s_dev *dev)
+{
+ dw_pcm_transfer(dev, false);
+}
+EXPORT_SYMBOL_GPL(dw_pcm_pop_rx);
+
static int dw_pcm_open(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -126,20 +174,18 @@ static int dw_pcm_hw_params(struct snd_pcm_substream *substream,
switch (params_format(hw_params)) {
case SNDRV_PCM_FORMAT_S16_LE:
dev->tx_fn = dw_pcm_tx_16;
+ dev->rx_fn = dw_pcm_rx_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S32_LE:
dev->tx_fn = dw_pcm_tx_32;
+ dev->rx_fn = dw_pcm_rx_32;
break;
default:
dev_err(dev->dev, "invalid format\n");
return -EINVAL;
}
- if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) {
- dev_err(dev->dev, "only playback is available\n");
- return -EINVAL;
- }
-
ret = snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
if (ret < 0)
@@ -163,13 +209,21 @@ static int dw_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- WRITE_ONCE(dev->tx_ptr, 0);
- rcu_assign_pointer(dev->tx_substream, substream);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ WRITE_ONCE(dev->tx_ptr, 0);
+ rcu_assign_pointer(dev->tx_substream, substream);
+ } else {
+ WRITE_ONCE(dev->rx_ptr, 0);
+ rcu_assign_pointer(dev->rx_substream, substream);
+ }
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- rcu_assign_pointer(dev->tx_substream, NULL);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ rcu_assign_pointer(dev->tx_substream, NULL);
+ else
+ rcu_assign_pointer(dev->rx_substream, NULL);
break;
default:
ret = -EINVAL;
@@ -183,7 +237,12 @@ static snd_pcm_uframes_t dw_pcm_pointer(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct dw_i2s_dev *dev = runtime->private_data;
- snd_pcm_uframes_t pos = READ_ONCE(dev->tx_ptr);
+ snd_pcm_uframes_t pos;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ pos = READ_ONCE(dev->tx_ptr);
+ else
+ pos = READ_ONCE(dev->rx_ptr);
return pos < runtime->buffer_size ? pos : 0;
}
diff --git a/sound/soc/dwc/local.h b/sound/soc/dwc/local.h
index 68afd7577343..91dc70a826f8 100644
--- a/sound/soc/dwc/local.h
+++ b/sound/soc/dwc/local.h
@@ -105,20 +105,27 @@ struct dw_i2s_dev {
struct i2s_clk_config_data config;
int (*i2s_clk_cfg)(struct i2s_clk_config_data *config);
- /* data related to PIO transfers (TX) */
+ /* data related to PIO transfers */
bool use_pio;
struct snd_pcm_substream __rcu *tx_substream;
+ struct snd_pcm_substream __rcu *rx_substream;
unsigned int (*tx_fn)(struct dw_i2s_dev *dev,
struct snd_pcm_runtime *runtime, unsigned int tx_ptr,
bool *period_elapsed);
+ unsigned int (*rx_fn)(struct dw_i2s_dev *dev,
+ struct snd_pcm_runtime *runtime, unsigned int rx_ptr,
+ bool *period_elapsed);
unsigned int tx_ptr;
+ unsigned int rx_ptr;
};
#if IS_ENABLED(CONFIG_SND_DESIGNWARE_PCM)
void dw_pcm_push_tx(struct dw_i2s_dev *dev);
+void dw_pcm_pop_rx(struct dw_i2s_dev *dev);
int dw_pcm_register(struct platform_device *pdev);
#else
void dw_pcm_push_tx(struct dw_i2s_dev *dev) { }
+void dw_pcm_pop_rx(struct dw_i2s_dev *dev) { }
int dw_pcm_register(struct platform_device *pdev)
{
return -EINVAL;
diff --git a/sound/soc/fsl/efika-audio-fabric.c b/sound/soc/fsl/efika-audio-fabric.c
index f200d1cfc4bd..667f4215dfc0 100644
--- a/sound/soc/fsl/efika-audio-fabric.c
+++ b/sound/soc/fsl/efika-audio-fabric.c
@@ -26,7 +26,6 @@
#include <sound/soc.h>
#include "mpc5200_dma.h"
-#include "mpc5200_psc_ac97.h"
#define DRV_NAME "efika-audio-fabric"
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 9fadf7e31c5f..18e5ce81527d 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -668,7 +668,7 @@ static struct snd_soc_dai_driver fsl_sai_dai = {
.playback = {
.stream_name = "CPU-Playback",
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 192000,
.rates = SNDRV_PCM_RATE_KNOT,
@@ -677,7 +677,7 @@ static struct snd_soc_dai_driver fsl_sai_dai = {
.capture = {
.stream_name = "CPU-Capture",
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 192000,
.rates = SNDRV_PCM_RATE_KNOT,
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
index 243700cc29e6..07ee355ee385 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.c
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -25,7 +25,6 @@
#include <asm/mpc52xx_psc.h>
#include "mpc5200_dma.h"
-#include "mpc5200_psc_ac97.h"
#define DRV_NAME "mpc5200-psc-ac97"
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.h b/sound/soc/fsl/mpc5200_psc_ac97.h
deleted file mode 100644
index e881e784b270..000000000000
--- a/sound/soc/fsl/mpc5200_psc_ac97.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Freescale MPC5200 PSC in AC97 mode
- * ALSA SoC Digital Audio Interface (DAI) driver
- *
- */
-
-#ifndef __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__
-#define __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__
-
-#define MPC5200_AC97_NORMAL 0
-#define MPC5200_AC97_SPDIF 1
-
-#endif /* __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ */
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 175c8227de2c..a110d3987d4a 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3675,10 +3675,10 @@ found:
EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
/* Retrieve a card's name from device tree */
-int snd_soc_of_parse_card_name_from_node(struct snd_soc_card *card,
- struct device_node *np,
- const char *propname)
+int snd_soc_of_parse_card_name(struct snd_soc_card *card,
+ const char *propname)
{
+ struct device_node *np;
int ret;
if (!card->dev) {
@@ -3686,8 +3686,7 @@ int snd_soc_of_parse_card_name_from_node(struct snd_soc_card *card,
return -EINVAL;
}
- if (!np)
- np = card->dev->of_node;
+ np = card->dev->of_node;
ret = of_property_read_string_index(np, propname, 0, &card->name);
/*
@@ -3704,7 +3703,7 @@ int snd_soc_of_parse_card_name_from_node(struct snd_soc_card *card,
return 0;
}
-EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name_from_node);
+EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name);
static const struct snd_soc_dapm_widget simple_widgets[] = {
SND_SOC_DAPM_MIC("Microphone", NULL),
@@ -3713,17 +3712,14 @@ static const struct snd_soc_dapm_widget simple_widgets[] = {
SND_SOC_DAPM_SPK("Speaker", NULL),
};
-int snd_soc_of_parse_audio_simple_widgets_from_node(struct snd_soc_card *card,
- struct device_node *np,
+int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
const char *propname)
{
+ struct device_node *np = card->dev->of_node;
struct snd_soc_dapm_widget *widgets;
const char *template, *wname;
int i, j, num_widgets, ret;
- if (!np)
- np = card->dev->of_node;
-
num_widgets = of_property_count_strings(np, propname);
if (num_widgets < 0) {
dev_err(card->dev,
@@ -3794,7 +3790,7 @@ int snd_soc_of_parse_audio_simple_widgets_from_node(struct snd_soc_card *card,
return 0;
}
-EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets_from_node);
+EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets);
static int snd_soc_of_get_slot_mask(struct device_node *np,
const char *prop_name,
@@ -3850,18 +3846,15 @@ int snd_soc_of_parse_tdm_slot(struct device_node *np,
}
EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot);
-void snd_soc_of_parse_audio_prefix_from_node(struct snd_soc_card *card,
- struct device_node *np,
+void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card,
struct snd_soc_codec_conf *codec_conf,
struct device_node *of_node,
const char *propname)
{
+ struct device_node *np = card->dev->of_node;
const char *str;
int ret;
- if (!np)
- np = card->dev->of_node;
-
ret = of_property_read_string(np, propname, &str);
if (ret < 0) {
/* no prefix is not error */
@@ -3871,19 +3864,16 @@ void snd_soc_of_parse_audio_prefix_from_node(struct snd_soc_card *card,
codec_conf->of_node = of_node;
codec_conf->name_prefix = str;
}
-EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_prefix_from_node);
+EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_prefix);
-int snd_soc_of_parse_audio_routing_from_node(struct snd_soc_card *card,
- struct device_node *np,
+int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
const char *propname)
{
+ struct device_node *np = card->dev->of_node;
int num_routes;
struct snd_soc_dapm_route *routes;
int i, ret;
- if (!np)
- np = card->dev->of_node;
-
num_routes = of_property_count_strings(np, propname);
if (num_routes < 0 || num_routes & 1) {
dev_err(card->dev,
@@ -3930,7 +3920,7 @@ int snd_soc_of_parse_audio_routing_from_node(struct snd_soc_card *card,
return 0;
}
-EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_routing_from_node);
+EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_routing);
unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
const char *prefix,