summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorOla Lilja <ola.o.lilja@stericsson.com>2010-11-25 18:02:05 +0100
committerUlf Hansson <ulf.hansson@stericsson.com>2011-09-19 15:14:42 +0200
commitfe1e8e8b6b8637eda7fb33dc9b98a4d3ec9d7f37 (patch)
tree6891167a081639c7f2d429fa5dae54edc478bb49 /sound
parent0185e37f689cecb899655c4c39bc4797993e0bf7 (diff)
Ux500 ASoC: Multi-component support.
The Ux500 driver is now rewritten to for multi-component support. This includes the Ux500 platform driver, the AV8100 codec-driver, the CG29xx codec-driver and the AB3550 codec-driver. There is now one common machine-driver for all codecs, and all three codecs can be activated indepentantly. Change-Id: I4c942b040306a1d6033ee4d80f9368917cb9b4d3 Signed-off-by: Ola Lilja <ola.o.lilja@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/9767 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/10280
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/Kconfig2
-rw-r--r--sound/soc/codecs/Makefile1
-rw-r--r--sound/soc/codecs/ab3550.c426
-rw-r--r--sound/soc/codecs/ab3550.h3
-rw-r--r--sound/soc/codecs/av8100_audio.c218
-rw-r--r--sound/soc/codecs/av8100_audio.h7
-rw-r--r--sound/soc/codecs/cg29xx.c558
-rw-r--r--sound/soc/codecs/cg29xx.h5
-rw-r--r--sound/soc/ux500/Kconfig35
-rw-r--r--sound/soc/ux500/Makefile30
-rw-r--r--sound/soc/ux500/u8500.c199
-rw-r--r--sound/soc/ux500/ux500_ab3550.c205
-rw-r--r--sound/soc/ux500/ux500_ab3550.h19
-rw-r--r--sound/soc/ux500/ux500_av8100.c127
-rw-r--r--sound/soc/ux500/ux500_av8100.h19
-rw-r--r--sound/soc/ux500/ux500_cg29xx.c161
-rw-r--r--sound/soc/ux500/ux500_cg29xx.h19
-rw-r--r--sound/soc/ux500/ux500_msp_dai.c526
-rw-r--r--sound/soc/ux500/ux500_msp_dai.h8
-rw-r--r--sound/soc/ux500/ux500_pcm.c101
-rw-r--r--sound/soc/ux500/ux500_pcm.h4
21 files changed, 1260 insertions, 1413 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index a2d1f2c52a9..adcbc43276d 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -11,7 +11,7 @@ menuconfig SND_SOC
If you want ASoC support, you should say Y here and also to the
specific driver for your SoC platform below.
-
+
ASoC provides power efficient ALSA support for embedded battery powered
SoC based systems like PDA's, Phones and Personal Media Players.
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 99bbb804537..363acbb047b 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -92,6 +92,7 @@ snd-soc-tpa6130a2-objs := tpa6130a2.o
snd-soc-wm2000-objs := wm2000.o
snd-soc-wm9090-objs := wm9090.o
+obj-$(CONFIG_SND_SOC_AB3550) += snd-soc-ab3550.o
obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o
obj-$(CONFIG_SND_SOC_AB3550) += snd-soc-ab3550.o
obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
diff --git a/sound/soc/codecs/ab3550.c b/sound/soc/codecs/ab3550.c
index e0a4c6d7f06..1b5abd2c4e2 100644
--- a/sound/soc/codecs/ab3550.c
+++ b/sound/soc/codecs/ab3550.c
@@ -2,7 +2,8 @@
* Copyright (C) ST-Ericsson SA 2010
*
* Author: Xie Xiaolei <xie.xiaolei@etericsson.com>,
- * Roger Nilsson <roger.xr.nilsson@stericsson.com>
+ * Roger Nilsson <roger.xr.nilsson@stericsson.com>,
+ * Ola Lilja <ola.o.lilja@stericsson.com>
* for ST-Ericsson.
*
* License terms:
@@ -36,8 +37,11 @@
#define I2C_BANK 0
+/* codec private data */
+struct ab3550_codec_dai_data {
+};
+
static struct device *ab3550_dev;
-static struct snd_soc_codec *ab3550_codec;
static u8 virtual_regs[] = {
0, 0
@@ -620,9 +624,6 @@ enum enum_link {
LINK = 1
};
-static unsigned int ab3550_read_reg(struct snd_soc_codec *codec,
- unsigned int reg);
-
static enum enum_power get_widget_power_status(enum enum_widget widget)
{
u8 val;
@@ -861,105 +862,6 @@ static enum enum_widget adder_sink_translate(u8 reg)
}
}
-/**
- This function is only called by the SOC framework to
- set registers associated to the mixer controls.
-*/
-static int ab3550_write_reg(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- if (reg < MIC_BIAS1 || reg > INTERFACE_SWAP)
- return -EINVAL;
- switch (reg) {
- u8 diff, oldval;
- case ANALOG_LOOP_PGA1:
- case ANALOG_LOOP_PGA2: {
- enum enum_widget apga = reg == ANALOG_LOOP_PGA1 ?
- widget_apga1 : widget_apga2;
-
- oldval = read_reg(reg);
- diff = value ^ oldval;
-
- /* The APGA is to be turned on/off.
- The power bit and the other bits in the
- same register won't be changed at the same time
- since they belong to different controls.
- */
- if (diff & (1 << APGAx_PWR_SHIFT)) {
- power_widget_locked(value >> APGAx_PWR_SHIFT & 1,
- apga);
- } else if (diff & APGAx_MUX_MASK) {
- enum enum_widget old_source =
- apga_source_translate(oldval);
- enum enum_widget new_source =
- apga_source_translate(value);
- update_widgets_link(UNLINK, old_source, apga,
- reg, APGAx_MUX_MASK, 0);
- update_widgets_link(LINK, new_source, apga,
- reg, APGAx_MUX_MASK, value);
- } else {
- set_reg(reg, value);
- }
- break;
- }
-
- case APGA1_ADDER:
- case APGA2_ADDER: {
- int i;
- enum enum_widget apga;
- enum enum_widget apga_dst[] = {
- widget_auxo2, widget_auxo1, widget_ear, widget_spkr,
- widget_line2, widget_line1
- };
-
- apga = adder_sink_translate(reg);
- oldval = read_reg(reg);
- diff = value ^ oldval;
- for (i = 0; diff; i++) {
- if (!(diff & 1 << i))
- continue;
- diff ^= 1 << i;
- update_widgets_link(value >> i & 1, apga, apga_dst[i],
- reg, 1 << i, value);
- }
- break;
- }
-
- case EAR_ADDER:
- case AUXO1_ADDER:
- case AUXO2_ADDER:
- case SPKR_ADDER:
- case LINE1_ADDER:
- case LINE2_ADDER: {
- int i;
- enum enum_widget widgets[] = {
- widget_dac1, widget_dac2, widget_dac3,
- };
- oldval = read_reg(reg);
- diff = value ^ oldval;
- for (i = 0; diff; i++) {
- if (!(diff & 1 << i))
- continue;
- diff ^= 1 << i;
- update_widgets_link(value >> i & 1, widgets[i],
- adder_sink_translate(reg),
- reg, 1 << i, value);
- }
- break;
- }
-
- default:
- set_reg(reg, value);
- }
- return 0;
-}
-
-static unsigned int ab3550_read_reg(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- return read_reg(reg);
-}
-
static int ab3550_add_widgets(struct snd_soc_codec *codec)
{
snd_soc_dapm_new_controls(codec, ab3550_dapm_widgets,
@@ -1011,7 +913,7 @@ static int ab3550_add_controls(struct snd_soc_codec *codec)
pr_debug("%s: %s called.\n", __FILE__, __func__);
for (i = 0; i < n; i++) {
- err = snd_ctl_add(codec->card, snd_ctl_new1(
+ err = snd_ctl_add(codec->card->snd_card, snd_ctl_new1(
&ab3550_snd_controls[i], codec));
if (err < 0) {
pr_err("%s failed to add control No.%d of %d.\n",
@@ -1052,7 +954,7 @@ static int ab3550_pcm_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- !dai->capture.active : !dai->playback.active) {
+ !dai->capture_active : !dai->playback_active) {
mask_set_reg(reg, I2Sx_SR_MASK, val << I2Sx_SR_SHIFT);
if ((read_reg(reg) & I2Sx_MODE_MASK) == 0) {
@@ -1067,7 +969,7 @@ static int ab3550_pcm_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- dai->playback.active : dai->capture.active) {
+ dai->playback_active : dai->capture_active) {
dev_err(ab3550_dev, "%s: A %s stream is already active.\n",
__func__,
@@ -1097,21 +999,20 @@ static int ab3550_pcm_prepare(struct snd_pcm_substream *substream,
}
static void ab3550_pcm_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai* dai)
+ struct snd_soc_dai *dai)
{
u8 iface = dai->id == 0 ? INTERFACE0 : INTERFACE1;
dev_info(ab3550_dev, "%s called.\n", __func__);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
power_for_playback(POWER_OFF, dai->id);
- } else {
+ else
power_for_capture(POWER_OFF, dai->id);
- }
- if (!dai->playback.active && !dai->capture.active &&
+ if (!dai->playback_active && !dai->capture_active &&
(read_reg(iface) & I2Sx_MODE_MASK) == 0)
mask_set_reg(iface, MASTER_GENx_PWR_MASK, 0);
}
-static int ab3550_set_dai_sysclk(struct snd_soc_dai* dai, int clk_id,
+static int ab3550_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
unsigned int freq, int dir)
{
return 0;
@@ -1138,7 +1039,7 @@ static int ab3550_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
"0x%x\n", fmt);
return -EINVAL;
}
- if (codec_dai->playback.active && codec_dai->capture.active) {
+ if (codec_dai->playback_active && codec_dai->capture_active) {
if ((read_reg(iface) & I2Sx_MODE_MASK) == val)
return 0;
else {
@@ -1152,19 +1053,19 @@ static int ab3550_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
return 0;
}
-struct snd_soc_dai ab3550_codec_dai[] = {
+struct snd_soc_dai_driver ab3550_dai_drv[] = {
{
- .name = "ab3550_0",
+ .name = "ab3550-codec-dai.0",
.id = 0,
.playback = {
- .stream_name = "ab3550_0",
+ .stream_name = "AB3550.0 Playback",
.channels_min = 2,
.channels_max = 2,
.rates = AB3550_SUPPORTED_RATE,
.formats = AB3550_SUPPORTED_FMT,
},
.capture = {
- .stream_name = "ab3550_0",
+ .stream_name = "AB3550.0 Capture",
.channels_min = 2,
.channels_max = 2,
.rates = AB3550_SUPPORTED_RATE,
@@ -1181,20 +1082,19 @@ struct snd_soc_dai ab3550_codec_dai[] = {
}
},
.symmetric_rates = 1,
- .private_data = NULL
},
{
- .name = "ab3550_1",
+ .name = "ab3550-codec-dai.1",
.id = 1,
.playback = {
- .stream_name = "ab3550_1",
+ .stream_name = "AB3550.1 Playback",
.channels_min = 2,
.channels_max = 2,
.rates = AB3550_SUPPORTED_RATE,
.formats = AB3550_SUPPORTED_FMT,
},
.capture = {
- .stream_name = "ab3550_1",
+ .stream_name = "AB3550.0 Capture",
.channels_min = 2,
.channels_max = 2,
.rates = AB3550_SUPPORTED_RATE,
@@ -1211,61 +1111,45 @@ struct snd_soc_dai ab3550_codec_dai[] = {
}
},
.symmetric_rates = 1,
- .private_data = NULL
}
};
-EXPORT_SYMBOL_GPL(ab3550_codec_dai);
+EXPORT_SYMBOL_GPL(ab3550_dai_drv);
-static int ab3550_codec_probe(struct platform_device *pdev)
+static int ab3550_codec_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
int ret;
- dev_info(&pdev->dev, "%s called. pdev = %p.\n", __func__, pdev);
- if (!ab3550_codec) {
- dev_err(&pdev->dev, "%s: Codec device not registered.\n",
- __func__);
- return -EAGAIN;
- }
- socdev->card->codec = ab3550_codec;
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(&pdev->dev, "%s: Failed to create a new card "
- "and new PCMs. error %d\n", __func__, ret);
- goto err;
- }
+ pr_info("%s: Enter.\n", __func__);
+
/* Add controls */
- if (ab3550_add_controls(ab3550_codec) < 0)
- goto err;
- ab3550_add_widgets(ab3550_codec);
- return 0;
+ if (ab3550_add_controls(codec) < 0)
+ return ret;
-err:
- snd_soc_free_pcms(socdev);
- return ret;
+ /* Add widgets */
+ ab3550_add_widgets(codec);
+
+ return 0;
}
-static int ab3550_codec_remove(struct platform_device *pdev)
+static int ab3550_codec_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
+ snd_soc_dapm_free(codec);
+
return 0;
}
#ifdef CONFIG_PM
-static int ab3550_codec_suspend(struct platform_device *pdev,
- pm_message_t state)
+static int ab3550_codec_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- dev_dbg(ab3550_dev, "%s : pdev=%p.\n", __func__, pdev);
mask_set_reg(CLOCK, CLOCK_ENABLE_MASK, 0);
+
return 0;
}
-static int ab3550_codec_resume(struct platform_device *pdev)
+static int ab3550_codec_resume(struct snd_soc_codec *codec)
{
- dev_dbg(ab3550_dev, "%s : pdev=%p.\n", __func__, pdev);
mask_set_reg(CLOCK, CLOCK_ENABLE_MASK, 0xff);
+
return 0;
}
#else
@@ -1273,14 +1157,114 @@ static int ab3550_codec_resume(struct platform_device *pdev)
#define ab3550_codec_suspend NULL
#endif
-struct snd_soc_codec_device soc_codec_dev_ab3550 = {
+/*
+ * This function is only called by the SOC framework to
+ * set registers associated to the mixer controls.
+ */
+static int ab3550_codec_write_reg(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
+{
+ if (reg < MIC_BIAS1 || reg > INTERFACE_SWAP)
+ return -EINVAL;
+ switch (reg) {
+ u8 diff, oldval;
+ case ANALOG_LOOP_PGA1:
+ case ANALOG_LOOP_PGA2: {
+ enum enum_widget apga = reg == ANALOG_LOOP_PGA1 ?
+ widget_apga1 : widget_apga2;
+
+ oldval = read_reg(reg);
+ diff = value ^ oldval;
+
+ /* The APGA is to be turned on/off.
+ * The power bit and the other bits in the
+ * same register won't be changed at the same time
+ * since they belong to different controls.
+ */
+ if (diff & (1 << APGAx_PWR_SHIFT)) {
+ power_widget_locked(value >> APGAx_PWR_SHIFT & 1,
+ apga);
+ } else if (diff & APGAx_MUX_MASK) {
+ enum enum_widget old_source =
+ apga_source_translate(oldval);
+ enum enum_widget new_source =
+ apga_source_translate(value);
+ update_widgets_link(UNLINK, old_source, apga,
+ reg, APGAx_MUX_MASK, 0);
+ update_widgets_link(LINK, new_source, apga,
+ reg, APGAx_MUX_MASK, value);
+ } else {
+ set_reg(reg, value);
+ }
+ break;
+ }
+
+ case APGA1_ADDER:
+ case APGA2_ADDER: {
+ int i;
+ enum enum_widget apga;
+ enum enum_widget apga_dst[] = {
+ widget_auxo2, widget_auxo1, widget_ear, widget_spkr,
+ widget_line2, widget_line1
+ };
+
+ apga = adder_sink_translate(reg);
+ oldval = read_reg(reg);
+ diff = value ^ oldval;
+ for (i = 0; diff; i++) {
+ if (!(diff & 1 << i))
+ continue;
+ diff ^= 1 << i;
+ update_widgets_link(value >> i & 1, apga, apga_dst[i],
+ reg, 1 << i, value);
+ }
+ break;
+ }
+
+ case EAR_ADDER:
+ case AUXO1_ADDER:
+ case AUXO2_ADDER:
+ case SPKR_ADDER:
+ case LINE1_ADDER:
+ case LINE2_ADDER: {
+ int i;
+ enum enum_widget widgets[] = {
+ widget_dac1, widget_dac2, widget_dac3,
+ };
+ oldval = read_reg(reg);
+ diff = value ^ oldval;
+ for (i = 0; diff; i++) {
+ if (!(diff & 1 << i))
+ continue;
+ diff ^= 1 << i;
+ update_widgets_link(value >> i & 1, widgets[i],
+ adder_sink_translate(reg),
+ reg, 1 << i, value);
+ }
+ break;
+ }
+
+ default:
+ set_reg(reg, value);
+ }
+ return 0;
+}
+
+static unsigned int ab3550_codec_read_reg(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ return read_reg(reg);
+}
+
+static struct snd_soc_codec_driver ab3550_codec_drv = {
.probe = ab3550_codec_probe,
.remove = ab3550_codec_remove,
.suspend = ab3550_codec_suspend,
- .resume = ab3550_codec_resume
+ .resume = ab3550_codec_resume,
+ .read = ab3550_codec_read_reg,
+ .write = ab3550_codec_write_reg,
};
-
-EXPORT_SYMBOL_GPL(soc_codec_dev_ab3550);
+EXPORT_SYMBOL_GPL(ab3550_codec_drv);
static inline void init_playback_route(void)
{
@@ -1334,13 +1318,34 @@ static inline void init_capture_gain(void)
mask_set_reg(TX_DIGITAL_PGA1, TXDPGAx_MASK, 0x0f << TXDPGAx_SHIFT);
}
-static int __init ab3550_platform_probe(struct platform_device *pdev)
+static __devinit int ab3550_codec_drv_probe(struct platform_device *pdev)
{
+ struct ab3550_codec_dai_data *codec_drvdata;
int ret = 0;
- int i;
u8 reg;
- pr_debug("%s invoked with pdev = %p.\n", __func__, pdev);
+ pr_debug("%s: Enter.\n", __func__);
+
+ pr_info("%s: Init codec private data.\n", __func__);
+ codec_drvdata = kzalloc(sizeof(struct ab3550_codec_dai_data), GFP_KERNEL);
+ if (codec_drvdata == NULL)
+ return -ENOMEM;
+
+ /* TODO: Add private data to codec_drvdata */
+
+ platform_set_drvdata(pdev, codec_drvdata);
+
+ pr_info("%s: Register codec.\n", __func__);
+ ret = snd_soc_register_codec(&pdev->dev, &ab3550_codec_drv, &ab3550_dai_drv[0], 2);
+ if (ret < 0) {
+ pr_debug("%s: Error: Failed to register codec (ret = %d).\n",
+ __func__,
+ ret);
+ snd_soc_unregister_codec(&pdev->dev);
+ kfree(platform_get_drvdata(pdev));
+ return ret;
+ }
+
ab3550_dev = &pdev->dev;
/* Initialize the codec registers */
for (reg = AB3550_FIRST_REG; reg <= AB3550_LAST_REG; reg++)
@@ -1354,102 +1359,69 @@ static int __init ab3550_platform_probe(struct platform_device *pdev)
init_capture_gain();
memset(&pm_stack, 0, sizeof(pm_stack));
- ab3550_codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (ab3550_codec == NULL)
- return -ENOMEM;
- ab3550_codec->name = "AB3550";
- ab3550_codec->owner = THIS_MODULE;
- ab3550_codec->dai = ab3550_codec_dai;
- ab3550_codec->num_dai = 2;
- ab3550_codec->read = ab3550_read_reg;
- ab3550_codec->write = ab3550_write_reg;
- ab3550_codec->reg_cache_size = 0;
- ab3550_codec->reg_cache = NULL;
- INIT_LIST_HEAD(&ab3550_codec->dapm_widgets);
- INIT_LIST_HEAD(&ab3550_codec->dapm_paths);
- mutex_init(&ab3550_codec->mutex);
- ret = snd_soc_register_codec(ab3550_codec);
- if (ret) {
- dev_err(ab3550_dev, "%s: Failed to register codec: %d.\n",
- __func__, ret);
- kfree(ab3550_codec);
- }
-
- for (i = 0; !ret && i < ARRAY_SIZE(ab3550_codec_dai); i++)
- ret = snd_soc_register_dai(ab3550_codec_dai + i);
- if (ret && i == 1) {
- snd_soc_unregister_codec(ab3550_codec);
- kfree(ab3550_codec);
- }
-
- return ret;
+ return 0;
}
-static int ab3550_platform_remove(struct platform_device *pdev)
+static int __devexit ab3550_codec_drv_remove(struct platform_device *pdev)
{
- int i;
-
- pr_debug("%s called.\n", __func__);
mask_set_reg(CLOCK, CLOCK_ENABLE_MASK, 0);
- for (i = 0; i < ARRAY_SIZE(ab3550_codec_dai); i++)
- snd_soc_unregister_dai(ab3550_codec_dai + i);
- snd_soc_unregister_codec(ab3550_codec);
- kfree(ab3550_codec);
+
ab3550_dev = NULL;
+
+ snd_soc_unregister_codec(&pdev->dev);
+ kfree(platform_get_drvdata(pdev));
+
return 0;
}
-static int ab3550_platform_suspend(struct platform_device *pdev,
+static int ab3550_codec_drv_suspend(struct platform_device *pdev,
pm_message_t state)
{
return 0;
}
-static int ab3550_platform_resume(struct platform_device *pdev)
+static int ab3550_codec_drv_resume(struct platform_device *pdev)
{
return 0;
}
-static struct platform_driver ab3550_platform_driver = {
- .driver = {
- .name = "ab3550-codec",
- .owner = THIS_MODULE,
+static struct platform_driver ab3550_codec_platform_drv = {
+ .driver = {
+ .name = "ab3550-codec",
+ .owner = THIS_MODULE,
},
- .probe = ab3550_platform_probe,
- .remove = ab3550_platform_remove,
- .suspend = ab3550_platform_suspend,
- .resume = ab3550_platform_resume,
+ .probe = ab3550_codec_drv_probe,
+ .remove = __devexit_p(ab3550_codec_drv_remove),
+ .suspend = ab3550_codec_drv_suspend,
+ .resume = ab3550_codec_drv_resume,
};
-static int __devinit ab3550_init(void)
+static int __devinit ab3550_codec_platform_drv_init(void)
{
- int ret1;
+ int ret;
- pr_debug("%s called.\n", __func__);
+ pr_debug("%s: Enter.\n", __func__);
ab3550_dev = NULL;
- ab3550_codec = NULL;
- /* Register codec platform driver. */
- ret1 = platform_driver_register(&ab3550_platform_driver);
- if (ret1 < 0) {
- pr_debug("%s: Error %d: Failed to register codec platform "
- "driver.\n", __func__, ret1);
- }
- return ret1;
+
+ ret = platform_driver_register(&ab3550_codec_platform_drv);
+ if (ret != 0)
+ pr_err("Failed to register AB3550 platform driver (%d)!\n", ret);
+
+ return ret;
}
-static void __devexit ab3550_exit(void)
+static void __exit ab3550_codec_platform_drv_exit(void)
{
- pr_debug("u8500_ab3550_init: Enter.\n");
+ pr_debug("%s: Enter.\n", __func__);
- /* Register codec platform driver. */
- pr_debug("%s: Un-register codec platform driver.\n", __func__);
- platform_driver_unregister(&ab3550_platform_driver);
+ platform_driver_unregister(&ab3550_codec_platform_drv);
}
-module_init(ab3550_init);
-module_exit(ab3550_exit);
+
+module_init(ab3550_codec_platform_drv_init);
+module_exit(ab3550_codec_platform_drv_exit);
MODULE_DESCRIPTION("AB3550 Codec driver");
MODULE_AUTHOR("Xie Xiaolei <xie.xiaolei@stericsson.com>");
diff --git a/sound/soc/codecs/ab3550.h b/sound/soc/codecs/ab3550.h
index f553fdce96b..fe9c77b1a62 100644
--- a/sound/soc/codecs/ab3550.h
+++ b/sound/soc/codecs/ab3550.h
@@ -13,9 +13,6 @@
#ifndef AB3550_CODEC_REGISTERS_H
#define AB3550_CODEC_REGISTERS_H
-extern struct snd_soc_dai ab3550_codec_dai[2];
-extern struct snd_soc_codec_device soc_codec_dev_ab3550;
-
#define AB3550_SUPPORTED_RATE (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \
SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
diff --git a/sound/soc/codecs/av8100_audio.c b/sound/soc/codecs/av8100_audio.c
index d85a8ca24e5..6fa6261c9fd 100644
--- a/sound/soc/codecs/av8100_audio.c
+++ b/sound/soc/codecs/av8100_audio.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) ST-Ericsson SA 2010
*
- * Author: Ola Lilja (ola.o.lilja@stericsson.com)
+ * Author: Ola Lilja <ola.o.lilja@stericsson.com>
* for ST-Ericsson.
*
* License terms:
@@ -29,7 +29,7 @@
#include "av8100_audio.h"
/* codec private data */
-struct av8100_codec_private_data {
+struct av8100_codec_dai_data {
struct hdmi_audio_settings as;
};
@@ -178,43 +178,51 @@ static int av8100_codec_send_audio_infoframe(struct hdmi_audio_settings *as)
return 0;
}
-int av8100_codec_change_hdmi_audio_settings(struct snd_pcm_substream *substream,
+static struct av8100_codec_dai_data *get_dai_data_codec(struct snd_soc_codec *codec,
+ int dai_id)
+{
+ struct av8100_codec_dai_data *dai_data = snd_soc_codec_get_drvdata(codec);
+ return &dai_data[dai_id];
+}
+
+static struct av8100_codec_dai_data *get_dai_data(struct snd_soc_dai *codec_dai)
+{
+ return get_dai_data_codec(codec_dai->codec, codec_dai->id);
+}
+
+int av8100_codec_change_hdmi_audio_settings(struct snd_soc_dai *codec_dai,
struct hdmi_audio_settings *as)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->socdev->card->codec;
- struct av8100_codec_private_data *av8100_codec_priv = codec->private_data;
+ struct av8100_codec_dai_data *dai_data = get_dai_data(codec_dai);
pr_debug("%s: Enter.\n", __func__);
- av8100_codec_priv->as.audio_coding_type = as->audio_coding_type;
- av8100_codec_priv->as.audio_channel_count = as->audio_channel_count;
- av8100_codec_priv->as.sampling_frequency = as->sampling_frequency;
- av8100_codec_priv->as.sample_size = as->sample_size;
- av8100_codec_priv->as.channel_allocation = as->channel_allocation;
- av8100_codec_priv->as.level_shift_value = as->level_shift_value;
- av8100_codec_priv->as.downmix_inhibit = as->downmix_inhibit;
+ dai_data->as.audio_coding_type = as->audio_coding_type;
+ dai_data->as.audio_channel_count = as->audio_channel_count;
+ dai_data->as.sampling_frequency = as->sampling_frequency;
+ dai_data->as.sample_size = as->sample_size;
+ dai_data->as.channel_allocation = as->channel_allocation;
+ dai_data->as.level_shift_value = as->level_shift_value;
+ dai_data->as.downmix_inhibit = as->downmix_inhibit;
return 0;
}
static int av8100_codec_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params,
- struct snd_soc_dai *dai)
+ struct snd_soc_dai *codec_dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->socdev->card->codec;
- struct av8100_codec_private_data *av8100_codec_priv = codec->private_data;
+ struct av8100_codec_dai_data *dai_data = get_dai_data(codec_dai);
pr_debug("%s: Enter.\n", __func__);
- av8100_codec_send_audio_infoframe(&av8100_codec_priv->as);
+ av8100_codec_send_audio_infoframe(&dai_data->as);
return 0;
}
static int av8100_codec_pcm_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+ struct snd_soc_dai *codec_dai)
{
int ret;
@@ -234,7 +242,7 @@ static int av8100_codec_pcm_startup(struct snd_pcm_substream *substream,
}
static void av8100_codec_pcm_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+ struct snd_soc_dai *codec_dai)
{
pr_debug("%s: Enter.\n", __func__);
}
@@ -301,11 +309,10 @@ static int av8100_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
return 0;
}
-struct snd_soc_dai av8100_codec_dai[] = {
- {
- .name = "av8100_0",
+struct snd_soc_dai_driver av8100_dai_drv = {
+ .name = "av8100-codec-dai",
.playback = {
- .stream_name = "av8100_0",
+ .stream_name = "AV8100 Playback",
.channels_min = 1,
.channels_max = 8,
.rates = AV8100_SUPPORTED_RATE,
@@ -321,145 +328,124 @@ struct snd_soc_dai av8100_codec_dai[] = {
.set_fmt = av8100_codec_set_dai_fmt,
}
},
- }
};
-EXPORT_SYMBOL_GPL(av8100_codec_dai);
+EXPORT_SYMBOL_GPL(av8100_dai_drv);
-static unsigned int av8100_codec_read(struct snd_soc_codec *codec,
- unsigned int ctl)
+static int av8100_codec_probe(struct snd_soc_codec *codec)
{
- pr_debug("%s: Enter.\n", __func__);
+ pr_debug("%s: Enter (codec->name = %s).\n", __func__, codec->name);
return 0;
}
-static int av8100_codec_write(struct snd_soc_codec *codec,
- unsigned int ctl,
- unsigned int value)
+static int av8100_codec_remove(struct snd_soc_codec *codec)
{
- pr_debug("%s: Enter.\n", __func__);
+ pr_debug("%s: Enter (codec->name = %s).\n", __func__, codec->name);
return 0;
}
-static int av8100_codec_probe(struct platform_device *pdev)
+static int av8100_codec_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- struct av8100_codec_private_data *av8100_codec_priv;
- int ret;
+ pr_debug("%s: Enter (codec->name = %s).\n", __func__, codec->name);
- pr_info("%s: Enter (pdev = %p).\n", __func__, pdev);
+ return 0;
+}
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL)
- return -ENOMEM;
- codec->name = "AV8100";
- codec->owner = THIS_MODULE;
- codec->dai = &av8100_codec_dai[0];
- codec->num_dai = 1;
- codec->read = av8100_codec_read;
- codec->write = av8100_codec_write;
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
+static int av8100_codec_resume(struct snd_soc_codec *codec)
+{
+ pr_debug("%s: Enter (codec->name = %s).\n", __func__, codec->name);
+
+ return 0;
+}
+
+struct snd_soc_codec_driver av8100_codec_drv = {
+ .probe = av8100_codec_probe,
+ .remove = av8100_codec_remove,
+ .suspend = av8100_codec_suspend,
+ .resume = av8100_codec_resume
+};
+
+static __devinit int av8100_codec_drv_probe(struct platform_device *pdev)
+{
+ struct av8100_codec_dai_data *dai_data;
+ int ret;
+
+ pr_debug("%s: Enter.\n", __func__);
pr_info("%s: Init codec private data..\n", __func__);
- av8100_codec_priv = kzalloc(sizeof(struct av8100_codec_private_data), GFP_KERNEL);
- if (av8100_codec_priv == NULL)
+ dai_data = kzalloc(sizeof(struct av8100_codec_dai_data), GFP_KERNEL);
+ if (dai_data == NULL)
return -ENOMEM;
/* Setup hdmi_audio_settings default values */
- av8100_codec_priv->as.audio_coding_type = AV8100_CODEC_CT_IEC60958_PCM;
- av8100_codec_priv->as.audio_channel_count = AV8100_CODEC_CC_2CH;
- av8100_codec_priv->as.sampling_frequency = AV8100_CODEC_SF_48KHZ;
- av8100_codec_priv->as.sample_size = AV8100_CODEC_SS_16BIT;
- av8100_codec_priv->as.channel_allocation = AV8100_CODEC_CA_FL_FR;
- av8100_codec_priv->as.level_shift_value = AV8100_CODEC_LSV_0DB;
- av8100_codec_priv->as.downmix_inhibit = false;
-
- codec->private_data = &av8100_codec_priv;
- mutex_init(&codec->mutex);
- socdev->card->codec = codec;
-
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ dai_data[0].as.audio_coding_type = AV8100_CODEC_CT_IEC60958_PCM;
+ dai_data[0].as.audio_channel_count = AV8100_CODEC_CC_2CH;
+ dai_data[0].as.sampling_frequency = AV8100_CODEC_SF_48KHZ;
+ dai_data[0].as.sample_size = AV8100_CODEC_SS_16BIT;
+ dai_data[0].as.channel_allocation = AV8100_CODEC_CA_FL_FR;
+ dai_data[0].as.level_shift_value = AV8100_CODEC_LSV_0DB;
+ dai_data[0].as.downmix_inhibit = false;
+
+ platform_set_drvdata(pdev, dai_data);
+
+ pr_info("%s: Register codec.\n", __func__);
+ ret = snd_soc_register_codec(&pdev->dev, &av8100_codec_drv, &av8100_dai_drv, 1);
if (ret < 0) {
- pr_err("%s: Error: to create new PCMs. error %d\n",
+ pr_debug("%s: Error: Failed to register codec (ret = %d).\n",
__func__,
ret);
- goto err;
+ return ret;
}
return 0;
-
-err:
- kfree(codec);
- return ret;
-}
-
-static int av8100_codec_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- pr_debug("%s: Enter (pdev = %p).\n", __func__, pdev);
-
- if (!codec)
- return 0;
-
- snd_soc_free_pcms(socdev);
- kfree(socdev->card->codec);
-
- return 0;
-}
-
-static int av8100_codec_suspend(struct platform_device *pdev,
- pm_message_t state)
-{
- pr_debug("%s: Enter (pdev = %p).\n", __func__, pdev);
-
- return 0;
}
-static int av8100_codec_resume(struct platform_device *pdev)
+static int __devexit av8100_codec_drv_remove(struct platform_device *pdev)
{
- pr_debug("%s: Enter (pdev = %p).\n", __func__, pdev);
-
+ snd_soc_unregister_codec(&pdev->dev);
+ kfree(platform_get_drvdata(pdev));
return 0;
}
-struct snd_soc_codec_device soc_codec_dev_av8100 = {
- .probe = av8100_codec_probe,
- .remove = av8100_codec_remove,
- .suspend = av8100_codec_suspend,
- .resume = av8100_codec_resume
+static const struct platform_device_id av8100_codec_platform_id[] = {
+ { "av8100-codec", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(platform, av8100_codec_platform_id);
+
+static struct platform_driver av8100_codec_platform_drv = {
+ .driver = {
+ .name = "av8100-codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = av8100_codec_drv_probe,
+ .remove = __devexit_p(av8100_codec_drv_remove),
+ .id_table = av8100_codec_platform_id,
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_av8100);
-static int __devinit av8100_codec_init(void)
+static int __devinit av8100_codec_platform_drv_init(void)
{
int ret;
pr_debug("%s: Enter.\n", __func__);
- pr_info("%s: Register codec-dai.\n", __func__);
- ret = snd_soc_register_dai(&av8100_codec_dai[0]);
- if (ret < 0) {
- pr_debug("%s: Error: Failed to register codec-dai (ret = %d).\n",
- __func__,
- ret);
+ ret = platform_driver_register(&av8100_codec_platform_drv);
+ if (ret != 0) {
+ pr_err("Failed to register AV8100 platform driver (%d)!\n", ret);
}
return ret;
}
-static void av8100_codec_exit(void)
+static void __exit av8100_codec_platform_drv_exit(void)
{
pr_debug("%s: Enter.\n", __func__);
- snd_soc_unregister_dai(&av8100_codec_dai[0]);
+ platform_driver_unregister(&av8100_codec_platform_drv);
}
-module_init(av8100_codec_init);
-module_exit(av8100_codec_exit);
+module_init(av8100_codec_platform_drv_init);
+module_exit(av8100_codec_platform_drv_exit);
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPLv2");
diff --git a/sound/soc/codecs/av8100_audio.h b/sound/soc/codecs/av8100_audio.h
index bcd2f26ddc8..4c269c14106 100644
--- a/sound/soc/codecs/av8100_audio.h
+++ b/sound/soc/codecs/av8100_audio.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) ST-Ericsson SA 2010
*
- * Author: Ola Lilja ola.o.lilja@stericsson.com,
+ * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
* for ST-Ericsson.
*
* License terms:
@@ -151,10 +151,7 @@ struct hdmi_audio_settings {
bool downmix_inhibit;
};
-extern struct snd_soc_dai av8100_codec_dai[];
-extern struct snd_soc_codec_device soc_codec_dev_av8100;
-
-int av8100_codec_change_hdmi_audio_settings(struct snd_pcm_substream *substream,
+int av8100_codec_change_hdmi_audio_settings(struct snd_soc_dai *dai,
struct hdmi_audio_settings *as);
#endif /* AV8100_CODEC_H */
diff --git a/sound/soc/codecs/cg29xx.c b/sound/soc/codecs/cg29xx.c
index a138f2c211a..bbd3adcfe5b 100644
--- a/sound/soc/codecs/cg29xx.c
+++ b/sound/soc/codecs/cg29xx.c
@@ -1,7 +1,8 @@
/*
* Copyright (C) ST-Ericsson SA 2010
*
- * Author: Roger Nilsson roger.xr.nilsson@stericsson.com
+ * Author: Roger Nilsson <roger.xr.nilsson@stericsson.com>,
+ * Ola Lilja <ola.o.lilja@stericsson.com>
* for ST-Ericsson.
*
* License terms:
@@ -78,108 +79,59 @@ static struct cg29xx_codec codec_private = {
.session = 0,
};
-static struct snd_soc_codec *cg29xx_codec;
-
-static struct cg29xx_dai
- cg29xx_dai_private[CG29XX_NBR_OF_DAI] = {
- {
- .tx_active = 0,
- .rx_active = 0,
- .input_select = 0,
- .output_select = 0,
- .config = {
- .port = PORT_0_I2S,
- .conf.i2s.mode = DAI_MODE_SLAVE,
- .conf.i2s.half_period = HALF_PER_DUR_16,
- .conf.i2s.channel_sel = CHANNEL_SELECTION_BOTH,
- .conf.i2s.sample_rate = SAMPLE_RATE_48,
- .conf.i2s.word_width = WORD_WIDTH_32
- }
- },
- {
- .tx_active = 0,
- .rx_active = 0,
- .input_select = 0,
- .output_select = 0,
- .config = {
- .port = PORT_1_I2S_PCM,
- .conf.i2s_pcm.mode = DAI_MODE_SLAVE,
- .conf.i2s_pcm.slot_0_dir = DAI_DIR_B_RX_A_TX,
- .conf.i2s_pcm.slot_1_dir = DAI_DIR_B_TX_A_RX,
- .conf.i2s_pcm.slot_2_dir = DAI_DIR_B_RX_A_TX,
- .conf.i2s_pcm.slot_3_dir = DAI_DIR_B_RX_A_TX,
- .conf.i2s_pcm.slot_0_used = true,
- .conf.i2s_pcm.slot_1_used = false,
- .conf.i2s_pcm.slot_2_used = false,
- .conf.i2s_pcm.slot_3_used = false,
- .conf.i2s_pcm.slot_0_start = 0,
- .conf.i2s_pcm.slot_1_start = 16,
- .conf.i2s_pcm.slot_2_start = 32,
- .conf.i2s_pcm.slot_3_start = 48,
- .conf.i2s_pcm.protocol = PORT_PROTOCOL_PCM,
- .conf.i2s_pcm.ratio = STREAM_RATIO_FM48_VOICE16,
- .conf.i2s_pcm.duration = SYNC_DURATION_32,
- .conf.i2s_pcm.clk = BIT_CLK_512,
- .conf.i2s_pcm.sample_rate = SAMPLE_RATE_16,
- }
- },
-};
-
-static struct snd_soc_dai_ops cg29xx_dai_ops = {
+static struct snd_soc_dai_ops cg29xx_dai_drv_dai_ops = {
.startup = cg29xx_dai_startup,
.prepare = cg29xx_dai_prepare,
.hw_params = cg29xx_dai_hw_params,
- .shutdown = cg29xx_dai_shutdown,
+ .shutdown = cg29xx_dai_shutdown,
.set_sysclk = cg29xx_set_dai_sysclk,
.set_fmt = cg29xx_set_dai_fmt,
.set_tdm_slot = cg29xx_set_tdm_slot
};
-struct snd_soc_dai cg29xx_codec_dai[] = {
+struct snd_soc_dai_driver cg29xx_dai_drv[] = {
{
- .name = "cg29xx_0",
- .id = 0,
- .playback = {
- .stream_name = "cg29xx_0_pb",
- .channels_min = 2,
- .channels_max = 2,
- .rates = CG29XX_SUPPORTED_RATE,
- .formats = CG29XX_SUPPORTED_FMT,
- },
- .capture = {
- .stream_name = "cg29xx_0_cap",
- .channels_min = 2,
- .channels_max = 2,
- .rates = CG29XX_SUPPORTED_RATE,
- .formats = CG29XX_SUPPORTED_FMT,
- },
- .ops = &cg29xx_dai_ops,
- .symmetric_rates = 1,
- .private_data = &cg29xx_dai_private[0]
+ .name = "cg29xx-codec-dai.0",
+ .id = 0,
+ .playback = {
+ .stream_name = "CG29xx.0 Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = CG29XX_SUPPORTED_RATE,
+ .formats = CG29XX_SUPPORTED_FMT,
+ },
+ .capture = {
+ .stream_name = "CG29xx.0 Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = CG29XX_SUPPORTED_RATE,
+ .formats = CG29XX_SUPPORTED_FMT,
+ },
+ .ops = &cg29xx_dai_drv_dai_ops,
+ .symmetric_rates = 1,
},
{
- .name = "cg29xx_1",
- .id = 1,
- .playback = {
- .stream_name = "cg29xx_1_pb",
- .channels_min = 1,
- .channels_max = 2,
- .rates = CG29XX_SUPPORTED_RATE_PCM,
- .formats = CG29XX_SUPPORTED_FMT,
- },
- .capture = {
- .stream_name = "cg29xx_1_cap",
- .channels_min = 1,
- .channels_max = 2,
- .rates = CG29XX_SUPPORTED_RATE_PCM,
- .formats = CG29XX_SUPPORTED_FMT,
- },
- .ops = &cg29xx_dai_ops,
- .symmetric_rates = 1,
- .private_data = &cg29xx_dai_private[1]
+ .name = "cg29xx-codec-dai.1",
+ .id = 1,
+ .playback = {
+ .stream_name = "CG29xx.1 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = CG29XX_SUPPORTED_RATE_PCM,
+ .formats = CG29XX_SUPPORTED_FMT,
+ },
+ .capture = {
+ .stream_name = "CG29xx.1 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = CG29XX_SUPPORTED_RATE_PCM,
+ .formats = CG29XX_SUPPORTED_FMT,
+ },
+ .ops = &cg29xx_dai_drv_dai_ops,
+ .symmetric_rates = 1,
}
};
-EXPORT_SYMBOL_GPL(cg29xx_codec_dai);
+EXPORT_SYMBOL_GPL(cg29xx_dai_drv);
static const char *enum_ifs_input_select[] = {
"BT_SCO", "FM_RX"
@@ -220,20 +172,30 @@ static struct snd_kcontrol_new cg29xx_snd_controls[] = {
SOC_ENUM("If1 Output Select", if1_output_select),
};
-static int cg29xx_set_dai_sysclk(
- struct snd_soc_dai *codec_dai,
- int clk_id,
- unsigned int freq, int dir)
+
+static struct cg29xx_codec_dai_data *get_dai_data_codec(struct snd_soc_codec *codec,
+ int dai_id)
+{
+ struct cg29xx_codec_dai_data *codec_drvdata = snd_soc_codec_get_drvdata(codec);
+ return &codec_drvdata[dai_id];
+}
+
+static struct cg29xx_codec_dai_data *get_dai_data(struct snd_soc_dai *codec_dai)
+{
+ return get_dai_data_codec(codec_dai->codec, codec_dai->id);
+}
+
+static int cg29xx_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id,
+ unsigned int freq, int dir)
{
return 0;
}
-static int cg29xx_set_dai_fmt(
- struct snd_soc_dai *codec_dai,
- unsigned int fmt)
+static int cg29xx_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
{
- struct cg29xx_dai *private =
- codec_dai->private_data;
+ struct cg29xx_codec_dai_data *dai_data = get_dai_data(codec_dai);
unsigned int prot;
unsigned int msel;
@@ -242,20 +204,20 @@ static int cg29xx_set_dai_fmt(
switch (prot) {
case SND_SOC_DAIFMT_I2S:
- if (private->config.port != PORT_0_I2S) {
+ if (dai_data->config.port != PORT_0_I2S) {
pr_err("cg29xx_dai: unsupported DAI format 0x%x\n",
fmt);
return -EINVAL;
}
if (msel == SND_SOC_DAIFMT_CBM_CFM)
- private->config.conf.i2s.mode = DAI_MODE_MASTER;
+ dai_data->config.conf.i2s.mode = DAI_MODE_MASTER;
else
- private->config.conf.i2s.mode = DAI_MODE_SLAVE;
+ dai_data->config.conf.i2s.mode = DAI_MODE_SLAVE;
break;
case SND_SOC_DAIFMT_DSP_A:
- if (private->config.port != PORT_1_I2S_PCM ||
+ if (dai_data->config.port != PORT_1_I2S_PCM ||
msel == SND_SOC_DAIFMT_CBM_CFM) {
pr_err("cg29xx_dai: unsupported DAI format 0x%x\n",
fmt);
@@ -270,57 +232,54 @@ static int cg29xx_set_dai_fmt(
return 0;
}
-static int cg29xx_set_tdm_slot(
- struct snd_soc_dai *dai,
- unsigned int tx_mask,
- unsigned int rx_mask,
- int slots,
- int slot_width)
+static int cg29xx_set_tdm_slot(struct snd_soc_dai *codec_dai,
+ unsigned int tx_mask,
+ unsigned int rx_mask,
+ int slots,
+ int slot_width)
{
- struct cg29xx_dai *private =
- dai->private_data;
+ struct cg29xx_codec_dai_data *dai_data = get_dai_data(codec_dai);
- if (private->config.port != PORT_1_I2S_PCM)
+ if (dai_data->config.port != PORT_1_I2S_PCM)
return -EINVAL;
- private->config.conf.i2s_pcm.slot_0_used =
+ dai_data->config.conf.i2s_pcm.slot_0_used =
(tx_mask | rx_mask) & (1<<CG29XX_DAI_SLOT0_SHIFT) ?
true : false;
- private->config.conf.i2s_pcm.slot_1_used =
+ dai_data->config.conf.i2s_pcm.slot_1_used =
(tx_mask | rx_mask) & (1<<CG29XX_DAI_SLOT1_SHIFT) ?
true : false;
- private->config.conf.i2s_pcm.slot_2_used =
+ dai_data->config.conf.i2s_pcm.slot_2_used =
(tx_mask | rx_mask) & (1<<CG29XX_DAI_SLOT2_SHIFT) ?
true : false;
- private->config.conf.i2s_pcm.slot_3_used =
+ dai_data->config.conf.i2s_pcm.slot_3_used =
(tx_mask | rx_mask) & (1<<CG29XX_DAI_SLOT3_SHIFT) ?
true : false;
- private->config.conf.i2s_pcm.slot_0_start = 0;
- private->config.conf.i2s_pcm.slot_1_start = slot_width;
- private->config.conf.i2s_pcm.slot_2_start = 2 * slot_width;
- private->config.conf.i2s_pcm.slot_3_start = 3 * slot_width;
+ dai_data->config.conf.i2s_pcm.slot_0_start = 0;
+ dai_data->config.conf.i2s_pcm.slot_1_start = slot_width;
+ dai_data->config.conf.i2s_pcm.slot_2_start = 2 * slot_width;
+ dai_data->config.conf.i2s_pcm.slot_3_start = 3 * slot_width;
return 0;
}
-static int cg29xx_configure_endp(
- struct cg29xx_dai *dai,
- enum cg2900_audio_endpoint_id endpid)
+static int cg29xx_configure_endp(struct cg29xx_codec_dai_data *dai_data,
+ enum cg2900_audio_endpoint_id endpid)
{
struct cg2900_endpoint_config config;
int err;
enum cg2900_dai_sample_rate dai_sr;
enum cg2900_endpoint_sample_rate endp_sr;
- switch (dai->config.port) {
+ switch (dai_data->config.port) {
default:
case PORT_0_I2S:
- dai_sr = dai->config.conf.i2s.sample_rate;
+ dai_sr = dai_data->config.conf.i2s.sample_rate;
break;
case PORT_1_I2S_PCM:
- dai_sr = dai->config.conf.i2s_pcm.sample_rate;
+ dai_sr = dai_data->config.conf.i2s_pcm.sample_rate;
break;
}
@@ -359,17 +318,16 @@ static int cg29xx_configure_endp(
return err;
}
-static int cg29xx_stop_if(
- struct cg29xx_dai *dai,
- enum cg29xx_dai_direction direction)
+static int cg29xx_stop_if(struct cg29xx_codec_dai_data *dai_data,
+ enum cg29xx_dai_direction direction)
{
int err = 0;
unsigned int *stream;
if (direction == CG29XX_DAI_DIRECTION_TX)
- stream = &dai->tx_active;
+ stream = &dai_data->tx_active;
else
- stream = &dai->rx_active;
+ stream = &dai_data->rx_active;
if (*stream) {
err = cg2900_audio_stop_stream(
@@ -380,29 +338,28 @@ static int cg29xx_stop_if(
} else {
pr_err("asoc cg29xx - %s - Failed to stop stream on interface %d.\n",
__func__,
- dai->config.port);
+ dai_data->config.port);
}
}
return err;
}
-static int cg29xx_start_if(
- struct cg29xx_dai *dai,
- enum cg29xx_dai_direction direction)
+static int cg29xx_start_if(struct cg29xx_codec_dai_data *dai_data,
+ enum cg29xx_dai_direction direction)
{
enum cg2900_audio_endpoint_id if_endpid;
enum cg2900_audio_endpoint_id endpid;
unsigned int *stream;
int err;
- if (dai->config.port == PORT_0_I2S)
+ if (dai_data->config.port == PORT_0_I2S)
if_endpid = ENDPOINT_PORT_0_I2S;
else
if_endpid = ENDPOINT_PORT_1_I2S_PCM;
if (direction == CG29XX_DAI_DIRECTION_RX) {
- switch (dai->output_select) {
+ switch (dai_data->output_select) {
default:
case 0:
endpid = ENDPOINT_BT_SCO_INOUT;
@@ -410,9 +367,9 @@ static int cg29xx_start_if(
case 1:
endpid = ENDPOINT_FM_TX;
}
- stream = &dai->rx_active;
+ stream = &dai_data->rx_active;
} else {
- switch (dai->input_select) {
+ switch (dai_data->input_select) {
default:
case 0:
endpid = ENDPOINT_BT_SCO_INOUT;
@@ -421,7 +378,7 @@ static int cg29xx_start_if(
endpid = ENDPOINT_FM_RX;
}
- stream = &dai->tx_active;
+ stream = &dai_data->tx_active;
}
if (*stream) {
@@ -436,7 +393,7 @@ static int cg29xx_start_if(
if_endpid,
endpid);
- err = cg29xx_configure_endp(dai, endpid);
+ err = cg29xx_configure_endp(dai_data, endpid);
if (err) {
pr_err("asoc cg29xx - %s - Configure endpoint id: %d failed.\n",
@@ -446,8 +403,7 @@ static int cg29xx_start_if(
return err;
}
- err = cg2900_audio_start_stream(
- codec_private.session,
+ err = cg2900_audio_start_stream(codec_private.session,
if_endpid,
endpid,
stream);
@@ -455,9 +411,8 @@ static int cg29xx_start_if(
return err;
}
-static int cg29xx_dai_startup(
- struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int cg29xx_dai_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
int err = 0;
@@ -467,10 +422,10 @@ static int cg29xx_dai_startup(
return err;
}
-static int cg29xx_dai_prepare(
- struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int cg29xx_dai_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *codec_dai)
{
+ struct cg29xx_codec_dai_data *dai_data = get_dai_data(codec_dai);
int err = 0;
enum cg29xx_dai_direction direction;
@@ -479,15 +434,15 @@ static int cg29xx_dai_prepare(
else
direction = CG29XX_DAI_DIRECTION_TX;
- err = cg29xx_start_if(dai->private_data, direction);
+ err = cg29xx_start_if(dai_data, direction);
return err;
}
-static void cg29xx_dai_shutdown(
- struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static void cg29xx_dai_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *codec_dai)
{
+ struct cg29xx_codec_dai_data *dai_data = get_dai_data(codec_dai);
enum cg29xx_dai_direction direction;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -495,15 +450,14 @@ static void cg29xx_dai_shutdown(
else
direction = CG29XX_DAI_DIRECTION_TX;
- (void) cg29xx_stop_if(dai->private_data, direction);
+ (void) cg29xx_stop_if(dai_data, direction);
}
-static int cg29xx_dai_hw_params(
- struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params,
- struct snd_soc_dai *dai)
+static int cg29xx_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params,
+ struct snd_soc_dai *codec_dai)
{
- struct cg29xx_dai *private = dai->private_data;
+ struct cg29xx_codec_dai_data *dai_data = get_dai_data(codec_dai);
enum cg2900_dai_fs_duration duration = SYNC_DURATION_32;
enum cg2900_dai_bit_clk bclk = BIT_CLK_512;
int sr;
@@ -512,7 +466,7 @@ static int cg29xx_dai_hw_params(
pr_debug("cg29xx asoc - %s called. Port: %d.\n",
__func__,
- private->config.port);
+ dai_data->config.port);
switch (params_rate(hw_params)) {
case 8000:
@@ -537,47 +491,50 @@ static int cg29xx_dai_hw_params(
return -EINVAL;
}
- if (private->config.port == PORT_0_I2S) {
- private->config.conf.i2s.sample_rate = sr;
+ if (dai_data->config.port == PORT_0_I2S) {
+ dai_data->config.conf.i2s.sample_rate = sr;
} else {
- private->config.conf.i2s_pcm.sample_rate = sr;
- private->config.conf.i2s_pcm.duration = duration;
- private->config.conf.i2s_pcm.clk = bclk;
- private->config.conf.i2s_pcm.ratio = ratio;
+ dai_data->config.conf.i2s_pcm.sample_rate = sr;
+ dai_data->config.conf.i2s_pcm.duration = duration;
+ dai_data->config.conf.i2s_pcm.clk = bclk;
+ dai_data->config.conf.i2s_pcm.ratio = ratio;
}
- if (!(private->tx_active | private->rx_active)) {
+ if (!(dai_data->tx_active | dai_data->rx_active)) {
err = cg2900_audio_set_dai_config(
codec_private.session,
- &private->config);
+ &dai_data->config);
pr_debug("asoc cg29xx: cg2900_audio_set_dai_config"
"on port %d completed with result: %d.\n",
- private->config.port,
+ dai_data->config.port,
err);
}
return err;
}
-static unsigned int cg29xx_codec_read(
- struct snd_soc_codec *codec,
- unsigned int reg)
+static unsigned int cg29xx_codec_read(struct snd_soc_codec *codec,
+ unsigned int reg)
{
+ struct cg29xx_codec_dai_data *dai_data;
switch (reg) {
-
case INTERFACE0_INPUT_SELECT:
- return cg29xx_dai_private[0].input_select;
+ dai_data = get_dai_data_codec(codec, 0);
+ return dai_data->input_select;
case INTERFACE1_INPUT_SELECT:
- return cg29xx_dai_private[1].input_select;
+ dai_data = get_dai_data_codec(codec, 1);
+ return dai_data->input_select;
case INTERFACE0_OUTPUT_SELECT:
- return cg29xx_dai_private[0].output_select;
+ dai_data = get_dai_data_codec(codec, 0);
+ return dai_data->output_select;
case INTERFACE1_OUTPUT_SELECT:
- return cg29xx_dai_private[1].output_select;
+ dai_data = get_dai_data_codec(codec, 1);
+ return dai_data->output_select;
default:
return 0;
@@ -586,59 +543,57 @@ static unsigned int cg29xx_codec_read(
return 0;
}
-static int cg29xx_codec_write(
- struct snd_soc_codec *codec,
- unsigned int reg,
- unsigned int value)
+static int cg29xx_codec_write(struct snd_soc_codec *codec,
+ unsigned int reg,
+ unsigned int value)
{
- int old_value;
- struct cg29xx_dai *dai;
+ struct cg29xx_codec_dai_data *dai_data;
enum cg29xx_dai_direction direction;
bool restart_if = false;
+ int old_value;
switch (reg) {
-
case INTERFACE0_INPUT_SELECT:
- dai = &cg29xx_dai_private[0];
+ dai_data = get_dai_data_codec(codec, 0);
direction = CG29XX_DAI_DIRECTION_TX;
- old_value = dai->input_select;
- dai->input_select = value;
+ old_value = dai_data->input_select;
+ dai_data->input_select = value;
- if ((old_value ^ value) && dai->tx_active)
+ if ((old_value ^ value) && dai_data->tx_active)
restart_if = true;
break;
case INTERFACE1_INPUT_SELECT:
- dai = &cg29xx_dai_private[1];
+ dai_data = get_dai_data_codec(codec, 1);
direction = CG29XX_DAI_DIRECTION_TX;
- old_value = dai->input_select;
- dai->input_select = value;
+ old_value = dai_data->input_select;
+ dai_data->input_select = value;
- if ((old_value ^ value) && dai->tx_active)
+ if ((old_value ^ value) && dai_data->tx_active)
restart_if = true;
break;
case INTERFACE0_OUTPUT_SELECT:
- dai = &cg29xx_dai_private[0];
+ dai_data = get_dai_data_codec(codec, 0);
direction = CG29XX_DAI_DIRECTION_RX;
- old_value = dai->output_select;
- dai->output_select = value;
+ old_value = dai_data->output_select;
+ dai_data->output_select = value;
- if ((old_value ^ value) && dai->rx_active)
+ if ((old_value ^ value) && dai_data->rx_active)
restart_if = true;
break;
case INTERFACE1_OUTPUT_SELECT:
- dai = &cg29xx_dai_private[1];
+ dai_data = get_dai_data_codec(codec, 1);
direction = CG29XX_DAI_DIRECTION_RX;
- old_value = dai->output_select;
- dai->output_select = value;
+ old_value = dai_data->output_select;
+ dai_data->output_select = value;
- if ((old_value ^ value) && dai->rx_active)
+ if ((old_value ^ value) && dai_data->rx_active)
restart_if = true;
break;
@@ -647,132 +602,173 @@ static int cg29xx_codec_write(
}
if (restart_if) {
- (void) cg29xx_stop_if(dai, direction);
- (void) cg29xx_start_if(dai, direction);
+ (void) cg29xx_stop_if(dai_data, direction);
+ (void) cg29xx_start_if(dai_data, direction);
}
return 0;
}
-static int cg29xx_soc_probe(struct platform_device *pdev)
+static int cg29xx_codec_probe(struct snd_soc_codec *codec)
{
- int err;
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- socdev->card->codec = cg29xx_codec;
-
- err = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (err < 0) {
- pr_err("cg29xx asoc - snd_soc_new_pcms failed with error: %d\n",
- err);
- goto err1;
- }
+ pr_debug("%s: Enter (codec->name = %s).\n", __func__, codec->name);
snd_soc_add_controls(
- cg29xx_codec,
+ codec,
cg29xx_snd_controls,
ARRAY_SIZE(cg29xx_snd_controls));
return 0;
-
- snd_soc_free_pcms(socdev);
-err1:
- return err;
}
-static int cg29xx_soc_remove(struct platform_device *pdev)
+static int cg29xx_codec_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
+ pr_debug("%s: Enter (codec->name = %s).\n", __func__, codec->name);
return 0;
}
-static int cg29xx_soc_suspend(struct platform_device *pdev,
- pm_message_t state)
+static int cg29xx_codec_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
+ pr_debug("%s: Enter (codec->name = %s).\n", __func__, codec->name);
+
return 0;
}
-static int cg29xx_soc_resume(struct platform_device *pdev)
+static int cg29xx_codec_resume(struct snd_soc_codec *codec)
{
+ pr_debug("%s: Enter (codec->name = %s).\n", __func__, codec->name);
+
return 0;
}
-struct snd_soc_codec_device soc_codec_dev_cg29xx = {
- .probe = cg29xx_soc_probe,
- .remove = cg29xx_soc_remove,
- .suspend = cg29xx_soc_suspend,
- .resume = cg29xx_soc_resume
+struct snd_soc_codec_driver cg29xx_codec_drv = {
+ .probe = cg29xx_codec_probe,
+ .remove = cg29xx_codec_remove,
+ .suspend = cg29xx_codec_suspend,
+ .resume = cg29xx_codec_resume,
+ .read = cg29xx_codec_read,
+ .write = cg29xx_codec_write,
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_cg29xx);
-static int __init cg29xx_init(void)
+static __devinit int cg29xx_codec_drv_probe(struct platform_device *pdev)
{
- int err;
- int i;
+ int ret;
+ struct cg29xx_codec_dai_data *dai_data;
- cg29xx_codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+ pr_debug("%s: Enter.\n", __func__);
- if (!cg29xx_codec)
+ pr_info("%s: Init codec private data..\n", __func__);
+ dai_data = kzalloc(CG29XX_NBR_OF_DAI * sizeof(struct cg29xx_codec_dai_data),
+ GFP_KERNEL);
+ if (dai_data == NULL)
return -ENOMEM;
- cg29xx_codec->name = "CG29XX";
- cg29xx_codec->owner = THIS_MODULE;
- cg29xx_codec->dai = cg29xx_codec_dai;
- cg29xx_codec->num_dai = CG29XX_NBR_OF_DAI;
- cg29xx_codec->read = cg29xx_codec_read;
- cg29xx_codec->write = cg29xx_codec_write;
- INIT_LIST_HEAD(&cg29xx_codec->dapm_widgets);
- INIT_LIST_HEAD(&cg29xx_codec->dapm_paths);
- mutex_init(&cg29xx_codec->mutex);
-
- err = snd_soc_register_codec(cg29xx_codec);
+ dai_data[0].tx_active = 0;
+ dai_data[0].rx_active = 0;
+ dai_data[0].input_select = 0;
+ dai_data[0].output_select = 0;
+ dai_data[0].config.port = PORT_0_I2S;
+ dai_data[0].config.conf.i2s.mode = DAI_MODE_SLAVE;
+ dai_data[0].config.conf.i2s.half_period = HALF_PER_DUR_16;
+ dai_data[0].config.conf.i2s.channel_sel = CHANNEL_SELECTION_BOTH;
+ dai_data[0].config.conf.i2s.sample_rate = SAMPLE_RATE_48;
+ dai_data[0].config.conf.i2s.word_width = WORD_WIDTH_32;
+ dai_data[1].tx_active = 0;
+ dai_data[1].rx_active = 0;
+ dai_data[1].input_select = 0;
+ dai_data[1].output_select = 0;
+ dai_data[1].config.port = PORT_1_I2S_PCM;
+ dai_data[1].config.conf.i2s_pcm.mode = DAI_MODE_SLAVE;
+ dai_data[1].config.conf.i2s_pcm.slot_0_dir = DAI_DIR_B_RX_A_TX;
+ dai_data[1].config.conf.i2s_pcm.slot_1_dir = DAI_DIR_B_TX_A_RX;
+ dai_data[1].config.conf.i2s_pcm.slot_2_dir = DAI_DIR_B_RX_A_TX;
+ dai_data[1].config.conf.i2s_pcm.slot_3_dir = DAI_DIR_B_RX_A_TX;
+ dai_data[1].config.conf.i2s_pcm.slot_0_used = true;
+ dai_data[1].config.conf.i2s_pcm.slot_1_used = false;
+ dai_data[1].config.conf.i2s_pcm.slot_2_used = false;
+ dai_data[1].config.conf.i2s_pcm.slot_3_used = false;
+ dai_data[1].config.conf.i2s_pcm.slot_0_start = 0;
+ dai_data[1].config.conf.i2s_pcm.slot_1_start = 16;
+ dai_data[1].config.conf.i2s_pcm.slot_2_start = 32;
+ dai_data[1].config.conf.i2s_pcm.slot_3_start = 48;
+ dai_data[1].config.conf.i2s_pcm.protocol = PORT_PROTOCOL_PCM;
+ dai_data[1].config.conf.i2s_pcm.ratio = STREAM_RATIO_FM48_VOICE16;
+ dai_data[1].config.conf.i2s_pcm.duration = SYNC_DURATION_32;
+ dai_data[1].config.conf.i2s_pcm.clk = BIT_CLK_512;
+ dai_data[1].config.conf.i2s_pcm.sample_rate = SAMPLE_RATE_16;
+
+ platform_set_drvdata(pdev, dai_data);
+
+ pr_info("%s: Register codec.\n", __func__);
+ ret = snd_soc_register_codec(&pdev->dev, &cg29xx_codec_drv, &cg29xx_dai_drv[0], 2);
+ if (ret < 0) {
+ pr_debug("%s: Error: Failed to register codec (ret = %d).\n",
+ __func__,
+ ret);
+ snd_soc_unregister_codec(&pdev->dev);
+ kfree(platform_get_drvdata(pdev));
+ return ret;
+ }
- if (err) {
- pr_err(
- "asoc cg29xx - snd_soc_register_codec"
- " failed with error: %d.\n",
- err);
+ return 0;
+}
- return err;
- }
+static int __devexit cg29xx_codec_drv_remove(struct platform_device *pdev)
+{
+ (void)cg2900_audio_close(&codec_private.session);
- for (i = 0; i < CG29XX_NBR_OF_DAI; i++) {
- mutex_init(&cg29xx_dai_private[i].mutex);
+ snd_soc_unregister_codec(&pdev->dev);
+ kfree(platform_get_drvdata(pdev));
- err = snd_soc_register_dai(&cg29xx_codec_dai[i]);
+ return 0;
+}
- if (err) {
- pr_err(
- "asoc cg29xx - snd_soc_register_dai"
- " failed with error: %d.\n",
- err);
- return err;
- }
- }
+static int cg29xx_codec_drv_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ return 0;
+}
- return err;
+static int cg29xx_codec_drv_resume(struct platform_device *pdev)
+{
+ return 0;
}
-module_init(cg29xx_init);
-static void __exit cg29xx_exit(void)
+static struct platform_driver cg29xx_codec_platform_drv = {
+ .driver = {
+ .name = "cg29xx-codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = cg29xx_codec_drv_probe,
+ .remove = __devexit_p(cg29xx_codec_drv_remove),
+ .suspend = cg29xx_codec_drv_suspend,
+ .resume = cg29xx_codec_drv_resume,
+};
+
+
+static int __devinit cg29xx_codec_platform_drv_init(void)
{
- int i;
+ int ret;
- (void) cg2900_audio_close(&codec_private.session);
+ pr_debug("%s: Enter.\n", __func__);
- if (cg29xx_codec) {
- snd_soc_unregister_codec(cg29xx_codec);
- kfree(cg29xx_codec);
- cg29xx_codec = NULL;
- }
+ ret = platform_driver_register(&cg29xx_codec_platform_drv);
+ if (ret != 0)
+ pr_err("Failed to register CG29xx platform driver (%d)!\n", ret);
+
+ return ret;
+}
+
+static void __exit cg29xx_codec_platform_drv_exit(void)
+{
+ pr_debug("%s: Enter.\n", __func__);
- for (i = 0; i < CG29XX_NBR_OF_DAI; i++)
- snd_soc_unregister_dai(&cg29xx_codec_dai[i]);
+ platform_driver_unregister(&cg29xx_codec_platform_drv);
}
-module_exit(cg29xx_exit);
-MODULE_DESCRIPTION("CG29xx codec driver");
-MODULE_LICENSE("GPL v2");
+
+module_init(cg29xx_codec_platform_drv_init);
+module_exit(cg29xx_codec_platform_drv_exit);
+
+MODULE_LICENSE("GPLv2");
diff --git a/sound/soc/codecs/cg29xx.h b/sound/soc/codecs/cg29xx.h
index e7ced7f9e24..5e73bc4b65a 100644
--- a/sound/soc/codecs/cg29xx.h
+++ b/sound/soc/codecs/cg29xx.h
@@ -15,10 +15,7 @@
#include <linux/mfd/cg2900_audio.h>
-extern struct snd_soc_dai cg29xx_codec_dai[];
-extern struct snd_soc_codec_device soc_codec_dev_cg29xx;
-
-struct cg29xx_dai {
+struct cg29xx_codec_dai_data {
struct mutex mutex;
unsigned int rx_active;
unsigned int tx_active;
diff --git a/sound/soc/ux500/Kconfig b/sound/soc/ux500/Kconfig
index 52944f6fa64..2b1327240fe 100644
--- a/sound/soc/ux500/Kconfig
+++ b/sound/soc/ux500/Kconfig
@@ -2,45 +2,40 @@
# Ux500 SoC audio configuration
#
-config SND_SOC_UX500
+menuconfig SND_SOC_UX500
bool "SoC Audio support for Ux500 platform"
depends on SND_SOC && STM_I2S && STM_MSP_I2S
default n
help
- Say Y if you want to add support for the codecs attached to
- the I2S of the Ux500. You will also need
- to select the audio codec to be supported in the driver.
-
-choice
- prompt "Codec to be used in Ux500 ASoC driver"
- depends on SND_SOC_UX500
- default SND_SOC_CG29XX
+ Say Y if you want to add support for the Ux500 platform.
config SND_SOC_UX500_AB3550
- bool "AB3550"
- depends on AB3550_CORE
+ bool "Codec - AB3550"
+ depends on SND_SOC_UX500 && (UX500_SOC_DB8500 || UX500_SOC_DB5500) && AB3550_CORE
select SND_SOC_AB3550
+ default n
help
- Say Y if you want to use AB3550 codec (Petronella MSA).
+ Say Y if you want to include AB3550 codec (Petronella MSA).
config SND_SOC_UX500_CG29XX
- bool "CG29xx"
+ bool "Codec - CG29xx"
+ depends on SND_SOC_UX500 && (UX500_SOC_DB8500 || UX500_SOC_DB5500) && MFD_CG2900_AUDIO
select SND_SOC_CG29XX
+ default n
help
- Say Y if you want to use CG29xx codec (Combo chip).
+ Say Y if you want to include CG29xx codec (Combo chip).
config SND_SOC_UX500_AV8100
- bool "AV8100"
- depends on AV8100
+ bool "Codec - AV8100"
+ depends on SND_SOC_UX500 && (UX500_SOC_DB8500 || UX500_SOC_DB5500) && AV8100
select SND_SOC_AV8100
+ default n
help
- Say Y if you want to use AV8100 codec (HDMI chip).
-
-endchoice
+ Say Y if you want to include AV8100 codec (HDMI chip).
config SND_SOC_UX500_DEBUG
bool "Activate Ux500 platform debug-mode (pr_debug)"
- depends on SND_SOC && STM_I2S && STM_MSP_I2S
+ depends on SND_SOC_UX500
default n
help
Say Y if you want to add debug level prints for Ux500 code-files.
diff --git a/sound/soc/ux500/Makefile b/sound/soc/ux500/Makefile
index 3a9091efd35..e7917509681 100644
--- a/sound/soc/ux500/Makefile
+++ b/sound/soc/ux500/Makefile
@@ -6,12 +6,28 @@ CFLAGS_ux500_msp_dai.o := -DDEBUG
CFLAGS_ux500_av8100.o := -DDEBUG
endif
-snd-soc-ux500-objs := ux500_pcm.o ux500_msp_dai.o
-snd-soc-ux500-ab3550-objs := ux500_ab3550.o
-snd-soc-ux500-cg29xx-objs := ux500_cg29xx.o
+ifdef CONFIG_SND_SOC_UX500_AB3550
+snd-soc-ux500-av8100-objs := ux500_ab3550.o
+obj-$(CONFIG_SND_SOC_UX500_AB3550) += ux500_ab3550.o
+endif
+
+ifdef CONFIG_SND_SOC_UX500_AV8100
snd-soc-ux500-av8100-objs := ux500_av8100.o
+obj-$(CONFIG_SND_SOC_UX500_AV8100) += ux500_av8100.o
+endif
+
+ifdef CONFIG_SND_SOC_UX500_CG29XX
+snd-soc-ux500-av8100-objs := ux500_cg29xx.o
+obj-$(CONFIG_SND_SOC_UX500_CG29XX) += ux500_cg29xx.o
+endif
+
+#ifdef UX500_SOC_DB8500
+snd-soc-u8500-objs := u8500.o
+obj-y += ux500_pcm.o ux500_msp_dai.o snd-soc-u8500.o
+#endif
+
+ifdef UX500_SOC_DB5500
+snd-soc-u8500-objs := u5500.o
+obj-$(UX500_SOC_DB5500) += ux500_pcm.o ux500_msp_dai.o snd-soc-u5500.o
+endif
-obj-$(CONFIG_SND_SOC_UX500) += snd-soc-ux500.o
-obj-$(CONFIG_SND_SOC_UX500_AB3550) += snd-soc-ux500-ab3550.o
-obj-$(CONFIG_SND_SOC_UX500_CG29XX) += snd-soc-ux500-cg29xx.o
-obj-$(CONFIG_SND_SOC_UX500_AV8100) += snd-soc-ux500-av8100.o
diff --git a/sound/soc/ux500/u8500.c b/sound/soc/ux500/u8500.c
new file mode 100644
index 00000000000..54fb9a1584e
--- /dev/null
+++ b/sound/soc/ux500/u8500.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Ola Lilja (ola.o.lilja@stericsson.com)
+ * for ST-Ericsson.
+ *
+ * License terms:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <sound/soc.h>
+
+#include "ux500_pcm.h"
+#include "ux500_msp_dai.h"
+
+#include <linux/spi/spi.h>
+#include <sound/initval.h>
+
+#ifdef CONFIG_SND_SOC_UX500_AB3550
+#include "ux500_ab3550.h"
+#endif
+
+#ifdef CONFIG_SND_SOC_UX500_AV8100
+#include "ux500_av8100.h"
+#endif
+
+#ifdef CONFIG_SND_SOC_UX500_CG29XX
+#include "ux500_cg29xx.h"
+#endif
+
+
+static struct platform_device *u8500_platform_dev;
+
+/* Create dummy devices for platform drivers */
+
+static struct platform_device ux500_pcm = {
+ .name = "ux500-pcm",
+ .id = 0,
+ .dev = {
+ .platform_data = NULL,
+ },
+};
+
+#ifdef CONFIG_SND_SOC_UX500_AV8100
+static struct platform_device av8100_codec = {
+ .name = "av8100-codec",
+ .id = 0,
+ .dev = {
+ .platform_data = NULL,
+ },
+};
+#endif
+
+#ifdef CONFIG_SND_SOC_UX500_CG29XX
+static struct platform_device cg29xx_codec = {
+ .name = "cg29xx-codec",
+ .id = 0,
+ .dev = {
+ .platform_data = NULL,
+ },
+};
+#endif
+
+/* Define the whole U8500 soundcard, linking platform to the codec-drivers */
+struct snd_soc_dai_link u8500_dai_links[] = {
+ #ifdef CONFIG_SND_SOC_UX500_AV8100
+ {
+ .name = "hdmi",
+ .stream_name = "hdmi",
+ .cpu_dai_name = "i2s.2",
+ .codec_dai_name = "av8100-codec-dai",
+ .platform_name = "ux500-pcm.0",
+ .codec_name = "av8100-codec.0",
+ .init = NULL,
+ .ops = ux500_av8100_ops,
+ },
+ #endif
+ #ifdef CONFIG_SND_SOC_UX500_AB3550
+ {
+ .name = "ab3550_0",
+ .stream_name = "ab3550_0",
+ .cpu_dai_name = "i2s.0",
+ .codec_dai_name = "ab3550-codec-dai.0",
+ .platform_name = "ux500-pcm.0",
+ .codec_name = "ab3550-codec.11",
+ .init = NULL,
+ .ops = ux500_ab3550_ops,
+ },
+ {
+ .name = "ab3550_1",
+ .stream_name = "ab3550_1",
+ .cpu_dai_name = "i2s.1",
+ .codec_dai_name = "ab3550-codec-dai.1",
+ .platform_name = "ux500-pcm.0",
+ .codec_name = "ab3550-codec.11",
+ .init = NULL,
+ .ops = ux500_ab3550_ops,
+ },
+ #endif
+ #ifdef CONFIG_SND_SOC_UX500_CG29XX
+ {
+ .name = "cg29xx_0",
+ .stream_name = "cg29xx_0",
+ .cpu_dai_name = "i2s.0",
+ .codec_dai_name = "cg29xx-codec-dai.1",
+ .platform_name = "ux500-pcm.0",
+ .codec_name = "cg29xx-codec.0",
+ .init = NULL,
+ .ops = ux500_cg29xx_ops,
+ },
+ #endif
+};
+
+static struct snd_soc_card u8500_drvdata = {
+ .name = "U8500-card",
+ .probe = NULL,
+ .dai_link = u8500_dai_links,
+ .num_links = ARRAY_SIZE(u8500_dai_links),
+};
+
+static int __init u8500_soc_init(void)
+{
+ int ret = 0;
+
+ pr_debug("%s: Enter.\n", __func__);
+
+ #ifdef CONFIG_SND_SOC_UX500_AV8100
+ pr_debug("%s: Register device to generate a probe for AV8100 codec.\n",
+ __func__);
+ platform_device_register(&av8100_codec);
+ #endif
+
+ #ifdef CONFIG_SND_SOC_UX500_CG29XX
+ pr_debug("%s: Register device to generate a probe for CG29xx codec.\n",
+ __func__);
+ platform_device_register(&cg29xx_codec);
+ #endif
+
+ pr_debug("%s: Register device to generate a probe for Ux500-pcm platform.\n",
+ __func__);
+ platform_device_register(&ux500_pcm);
+
+ pr_debug("%s: Allocate platform device 'soc-audio'.\n",
+ __func__);
+ u8500_platform_dev = platform_device_alloc("soc-audio", -1);
+ if (!u8500_platform_dev)
+ return -ENOMEM;
+
+ pr_debug("%s: Card %s: num_links = %d\n",
+ __func__,
+ u8500_drvdata.name,
+ u8500_drvdata.num_links);
+ pr_debug("%s: Card %s: DAI-link 0: name = %s\n",
+ __func__,
+ u8500_drvdata.name,
+ u8500_drvdata.dai_link[0].name);
+ pr_debug("%s: Card %s: DAI-link 0: stream_name = %s\n",
+ __func__,
+ u8500_drvdata.name,
+ u8500_drvdata.dai_link[0].stream_name);
+
+ pr_debug("%s: Card %s: Set platform drvdata.\n",
+ __func__,
+ u8500_drvdata.name);
+ platform_set_drvdata(u8500_platform_dev, &u8500_drvdata);
+ u8500_drvdata.dev = &u8500_platform_dev->dev;
+
+ pr_debug("%s: Card %s: Add platform device.\n",
+ __func__,
+ u8500_drvdata.name);
+ ret = platform_device_add(u8500_platform_dev);
+ if (ret) {
+ pr_err("%s: Error: Failed to add platform device (%s).\n",
+ __func__,
+ u8500_drvdata.name);
+ platform_device_put(u8500_platform_dev);
+ }
+
+ return ret;
+}
+
+static void __exit u8500_soc_exit(void)
+{
+ pr_debug("%s: Enter.\n", __func__);
+
+ pr_debug("%s: Unregister platform device (%s).\n",
+ __func__,
+ u8500_drvdata.name);
+ platform_device_unregister(u8500_platform_dev);
+}
+
+module_init(u8500_soc_init);
+module_exit(u8500_soc_exit);
+
+MODULE_LICENSE("GPLv2");
diff --git a/sound/soc/ux500/ux500_ab3550.c b/sound/soc/ux500/ux500_ab3550.c
index 103e8b2cfb5..7e144c0e4d2 100644
--- a/sound/soc/ux500/ux500_ab3550.c
+++ b/sound/soc/ux500/ux500_ab3550.c
@@ -12,196 +12,65 @@
* by the Free Software Foundation.
*/
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/io.h>
#include <sound/soc.h>
-
-#include "ux500_pcm.h"
-#include "ux500_msp_dai.h"
-#include "mach/hardware.h"
#include "../codecs/ab3550.h"
-static struct platform_device *ux500_ab3550_platform_device;
-
-#define AB3550_DAI_FMT_I2S_M (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM)
-#define AB3550_DAI_FMT_I2S_S (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS)
-#define AB3550_DAI_FMT AB3550_DAI_FMT_I2S_S
-
static int ux500_ab3550_startup(struct snd_pcm_substream *substream)
{
- dev_dbg(&ux500_ab3550_platform_device->dev,
- "%s: Enter\n",
- __func__);
+ pr_debug("%s: Enter.\n", __func__);
+
return 0;
}
static void ux500_ab3550_shutdown(struct snd_pcm_substream *substream)
{
- dev_dbg(&ux500_ab3550_platform_device->dev,
- "%s: Enter\n",
- __func__);
+ pr_debug("%s: Enter.\n", __func__);
}
-static int ux500_ab3550_hw_params(
- struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+static int ux500_ab3550_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
- int ifid, ret = 0;
-
- dev_dbg(&ux500_ab3550_platform_device->dev,
- "%s: Enter\n",
- __func__);
-
- dev_dbg(&ux500_ab3550_platform_device->dev,
- "%s: substream->pcm->name = %s\n"
- "substream->pcm->id = %s.\n"
- "substream->name = %s.\n"
- "substream->number = %d.\n",
- __func__,
- substream->pcm->name,
- substream->pcm->id,
- substream->name,
- substream->number);
-
- for (ifid = 0; ifid < ARRAY_SIZE(ab3550_codec_dai); ifid++) {
- if (strcmp(codec_dai->name, ab3550_codec_dai[ifid].name) == 0)
- break;
- }
-
- if (codec_dai->ops->set_fmt) {
- ret = snd_soc_dai_set_fmt(codec_dai, AB3550_DAI_FMT);
- if (ret < 0) {
- dev_dbg(&ux500_ab3550_platform_device->dev,
- "%s: snd_soc_dai_set_fmt failed with %d.\n",
- __func__,
- ret);
- return ret;
- }
-
- ret = snd_soc_dai_set_fmt(cpu_dai, AB3550_DAI_FMT);
-
- if (ret < 0) {
- dev_dbg(&ux500_ab3550_platform_device->dev,
- "%s: snd_soc_dai_set_fmt"
- " failed with %d.\n", __func__, ret);
- return ret;
- }
- }
-
- return ret;
-}
-
-static struct snd_soc_ops ux500_ab3550_ops = {
- .startup = ux500_ab3550_startup,
- .shutdown = ux500_ab3550_shutdown,
- .hw_params = ux500_ab3550_hw_params,
-};
-
-struct snd_soc_dai_link ux500_ab3550_dai_links[] = {
- {
- .name = "ab3550_0",
- .stream_name = "ab3550_0",
- .cpu_dai = &ux500_msp_dai[0],
- .codec_dai = &ab3550_codec_dai[0],
- .init = NULL,
- .ops = &ux500_ab3550_ops,
- },
- {
- .name = "ab3550_1",
- .stream_name = "ab3550_1",
- .cpu_dai = &ux500_msp_dai[1],
- .codec_dai = &ab3550_codec_dai[1],
- .init = NULL,
- .ops = &ux500_ab3550_ops,
- },
-};
-
-static struct snd_soc_card ux500_ab3550 = {
- .name = "ab3550",
- .probe = NULL,
- .dai_link = ux500_ab3550_dai_links,
- .num_links = ARRAY_SIZE(ux500_ab3550_dai_links),
- .platform = &ux500_soc_platform,
-};
-
-struct snd_soc_device ux500_ab3550_drvdata = {
- .card = &ux500_ab3550,
- .codec_dev = &soc_codec_dev_ab3550,
-};
-
-static int __init mop500_ab3550_soc_init(void)
-{
- int i;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int ret = 0;
- pr_debug("%s: Enter\n",
- __func__);
- pr_debug("%s: Card name: %s\n",
- __func__,
- ux500_ab3550_drvdata.card->name);
-
- for (i = 0; i < ARRAY_SIZE(ux500_ab3550_dai_links); i++) {
- pr_debug("%s: DAI-link %d, name: %s\n",
+ int channels = params_channels(params);
+
+ pr_debug("%s: Enter.\n", __func__);
+ pr_debug("%s: substream->pcm->name = %s.\n", __func__, substream->pcm->name);
+ pr_debug("%s: substream->pcm->id = %s.\n", __func__, substream->pcm->id);
+ pr_debug("%s: substream->name = %s.\n", __func__, substream->name);
+ pr_debug("%s: substream->number = %d.\n", __func__, substream->number);
+ pr_debug("%s: channels = %d.\n", __func__, channels);
+ pr_debug("%s: DAI-index (Codec): %d\n", __func__, codec_dai->id);
+ pr_debug("%s: DAI-index (Platform): %d\n", __func__, cpu_dai->id);
+
+ ret = snd_soc_dai_set_fmt(codec_dai,
+ SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0) {
+ pr_debug("%s: snd_soc_dai_set_fmt failed with %d.\n",
__func__,
- i,
- ux500_ab3550_drvdata.card->dai_link[i].name);
- pr_debug("%s: DAI-link %d, stream_name: %s\n",
- __func__,
- i,
- ux500_ab3550_drvdata.card->dai_link[i].stream_name);
+ ret);
+ return ret;
}
- pr_debug("%s: Allocate platform device (%s)\n",
- __func__,
- ux500_ab3550_drvdata.card->name);
- ux500_ab3550_platform_device = platform_device_alloc("soc-audio", -1);
- if (!ux500_ab3550_platform_device)
- return -ENOMEM;
-
- dev_dbg(&ux500_ab3550_platform_device->dev,
- "%s: Set platform drvdata (%s)\n",
- __func__,
- ux500_ab3550_drvdata.card->name);
- platform_set_drvdata(
- ux500_ab3550_platform_device,
- &ux500_ab3550_drvdata);
-
- dev_dbg(&ux500_ab3550_platform_device->dev,
- "%s: Add platform device (%s)\n",
- __func__,
- ux500_ab3550_drvdata.card->name);
- ux500_ab3550_drvdata.dev = &ux500_ab3550_platform_device->dev;
-
- ret = platform_device_add(ux500_ab3550_platform_device);
- if (ret) {
- dev_dbg(&ux500_ab3550_platform_device->dev,
- "%s: Error: Failed to add platform device (%s)\n",
+ ret = snd_soc_dai_set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0) {
+ pr_debug("%s: snd_soc_dai_set_fmt failed with %d.\n",
__func__,
- ux500_ab3550_drvdata.card->name);
- platform_device_put(ux500_ab3550_platform_device);
+ ret);
+ return ret;
}
return ret;
}
-module_init(mop500_ab3550_soc_init);
-static void __exit mop500_ab3550_soc_exit(void)
-{
- dev_dbg(&ux500_ab3550_platform_device->dev,
- "%s: Enter.\n",
- __func__);
-
- dev_dbg(&ux500_ab3550_platform_device->dev,
- "%s: Un-register platform device (%s)\n",
- __func__,
- ux500_ab3550_drvdata.card->name);
- platform_device_unregister(ux500_ab3550_platform_device);
-}
-module_exit(mop500_ab3550_soc_exit);
-
-MODULE_LICENSE("GPL");
+struct snd_soc_ops ux500_ab3550_ops[] = {
+ {
+ .startup = ux500_ab3550_startup,
+ .shutdown = ux500_ab3550_shutdown,
+ .hw_params = ux500_ab3550_hw_params,
+ }
+};
diff --git a/sound/soc/ux500/ux500_ab3550.h b/sound/soc/ux500/ux500_ab3550.h
new file mode 100644
index 00000000000..53ea3902d36
--- /dev/null
+++ b/sound/soc/ux500/ux500_ab3550.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Ola Lilja <ola.o.lilja@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#ifndef UX500_AB3550_H
+#define UX500_AB3550_H
+
+extern struct snd_soc_ops ux500_ab3550_ops[];
+
+#endif
diff --git a/sound/soc/ux500/ux500_av8100.c b/sound/soc/ux500/ux500_av8100.c
index 5317670c3b4..25e6a0deb0c 100644
--- a/sound/soc/ux500/ux500_av8100.c
+++ b/sound/soc/ux500/ux500_av8100.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) ST-Ericsson SA 2010
*
- * Author: Ola Lilja (ola.o.lilja@stericsson.com)
+ * Author: Ola Lilja <ola.o.lilja@stericsson.com>
* for ST-Ericsson.
*
* License terms:
@@ -11,42 +11,31 @@
* by the Free Software Foundation.
*/
-#include <linux/io.h>
#include <sound/soc.h>
-
-#include "ux500_pcm.h"
-#include "ux500_msp_dai.h"
-
-#include <linux/spi/spi.h>
-#include <sound/initval.h>
-
#include "../codecs/av8100_audio.h"
-
-static struct platform_device *ux500_av8100_platform_device;
+#include "ux500_av8100.h"
static int ux500_av8100_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
-
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int channels = params_channels(params);
unsigned int tx_mask, fmt;
enum hdmi_channel_allocation hdmi_ca;
enum hdmi_audio_channel_count hdmi_cc;
struct hdmi_audio_settings as;
+ int ret;
- int channels = params_channels(params);
- int ret = 0;
-
- pr_debug("%s: Enter (TDM-mode, channels = %d, name = %s, number = %d).\n",
- __func__,
- channels,
- substream->name,
- substream->number);
-
+ pr_debug("%s: Enter.\n", __func__);
pr_debug("%s: substream->pcm->name = %s.\n", __func__, substream->pcm->name);
pr_debug("%s: substream->pcm->id = %s.\n", __func__, substream->pcm->id);
+ pr_debug("%s: substream->name = %s.\n", __func__, substream->name);
+ pr_debug("%s: substream->number = %d.\n", __func__, substream->number);
+ pr_debug("%s: channels = %d.\n", __func__, channels);
+ pr_debug("%s: DAI-index (Codec): %d\n", __func__, codec_dai->id);
+ pr_debug("%s: DAI-index (Platform): %d\n", __func__, cpu_dai->id);
switch (channels) {
case 1:
@@ -100,7 +89,7 @@ static int ux500_av8100_hw_params(struct snd_pcm_substream *substream,
as.channel_allocation = hdmi_ca;
as.level_shift_value = AV8100_CODEC_LSV_0DB;
as.downmix_inhibit = false;
- ret = av8100_codec_change_hdmi_audio_settings(substream, &as);
+ ret = av8100_codec_change_hdmi_audio_settings(codec_dai, &as);
if (ret < 0) {
pr_err("%s: Unable to change HDMI audio-settings for codec-DAI "
"(av8100_codec_change_hdmi_audio_settings returned %d)!\n",
@@ -155,93 +144,9 @@ static int ux500_av8100_hw_params(struct snd_pcm_substream *substream,
return ret;
}
-
-
-struct snd_soc_dai_link ux500_av8100_dai_links[] = {
+struct snd_soc_ops ux500_av8100_ops[] = {
{
- .name = "hdmi",
- .stream_name = "hdmi",
- .cpu_dai = &ux500_msp_dai[2],
- .codec_dai = &av8100_codec_dai[0],
- .init = NULL,
- .ops = (struct snd_soc_ops[]) {
- {
- .hw_params = ux500_av8100_hw_params,
- }
+ .hw_params = ux500_av8100_hw_params,
}
- },
};
-static struct snd_soc_card ux500_av8100 = {
- .name = "hdmi",
- .probe = NULL,
- .dai_link = ux500_av8100_dai_links,
- .num_links = ARRAY_SIZE(ux500_av8100_dai_links),
- .platform = &ux500_soc_platform,
-};
-
-struct snd_soc_device ux500_av8100_drvdata = {
- .card = &ux500_av8100,
- .codec_dev = &soc_codec_dev_av8100,
-};
-
-static int __init ux500_av8100_soc_init(void)
-{
- int ret = 0;
-
- pr_debug("%s: Enter.\n", __func__);
-
- pr_info("%s: Card name: %s\n",
- __func__,
- ux500_av8100_drvdata.card->name);
-
- pr_debug("%s: DAI-link 0, name: %s\n",
- __func__,
- ux500_av8100_drvdata.card->dai_link[0].name);
- pr_debug("%s: DAI-link 0, stream_name: %s\n",
- __func__,
- ux500_av8100_drvdata.card->dai_link[0].stream_name);
-
- pr_debug("%s: Allocate platform device (%s).\n",
- __func__,
- ux500_av8100_drvdata.card->name);
- ux500_av8100_platform_device = platform_device_alloc("soc-audio", -1);
- if (!ux500_av8100_platform_device)
- return -ENOMEM;
-
- pr_debug("%s: Set platform drvdata (%s).\n",
- __func__,
- ux500_av8100_drvdata.card->name);
- platform_set_drvdata(
- ux500_av8100_platform_device,
- &ux500_av8100_drvdata);
- ux500_av8100_drvdata.dev = &ux500_av8100_platform_device->dev;
-
- pr_debug("%s: Add platform device (%s).\n",
- __func__,
- ux500_av8100_drvdata.card->name);
- ret = platform_device_add(ux500_av8100_platform_device);
- if (ret) {
- pr_err("%s: Error: Failed to add platform device (%s).\n",
- __func__,
- ux500_av8100_drvdata.card->name);
- platform_device_put(ux500_av8100_platform_device);
- }
-
- return ret;
-}
-
-static void __exit ux500_av8100_soc_exit(void)
-{
- pr_debug("%s: Enter.\n", __func__);
-
- pr_debug("%s: Unregister platform device (%s).\n",
- __func__,
- ux500_av8100_drvdata.card->name);
- platform_device_unregister(ux500_av8100_platform_device);
-}
-
-module_init(ux500_av8100_soc_init);
-module_exit(ux500_av8100_soc_exit);
-
-MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/ux500/ux500_av8100.h b/sound/soc/ux500/ux500_av8100.h
new file mode 100644
index 00000000000..b107b2e1be7
--- /dev/null
+++ b/sound/soc/ux500/ux500_av8100.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Ola Lilja <ola.o.lilja@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#ifndef UX500_AV8100_H
+#define UX500_AV8100_H
+
+extern struct snd_soc_ops ux500_av8100_ops[];
+
+#endif
diff --git a/sound/soc/ux500/ux500_cg29xx.c b/sound/soc/ux500/ux500_cg29xx.c
index 0c74bbe4550..6cc77820a62 100644
--- a/sound/soc/ux500/ux500_cg29xx.c
+++ b/sound/soc/ux500/ux500_cg29xx.c
@@ -1,7 +1,8 @@
/*
* Copyright (C) ST-Ericsson SA 2010
*
- * Author: Roger Nilsson roger.xr.nilsson@stericsson.com
+ * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
+ * Roger Nilsson <roger.xr.nilsson@stericsson.com>
* for ST-Ericsson.
*
* License terms:
@@ -11,93 +12,75 @@
* by the Free Software Foundation.
*/
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/io.h>
#include <sound/soc.h>
-
-#include "ux500_pcm.h"
-#include "ux500_msp_dai.h"
#include "../codecs/cg29xx.h"
#define UX500_CG29XX_DAI_SLOT_WIDTH 16
#define UX500_CG29XX_DAI_SLOTS 2
#define UX500_CG29XX_DAI_ACTIVE_SLOTS 0x01
-static struct platform_device *ux500_cg29xx_platform_device;
-
-static int ux500_cg29xx_hw_params(
- struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+int ux500_cg29xx_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
- struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
-
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ int channels = params_channels(params);
int err;
- pr_debug("%s: substream->pcm->name = %s.\n"
- "substream->pcm->id = %s.\n"
- "substream->name = %s.\n"
- "substream->number = %d.\n",
- __func__,
- substream->pcm->name,
- substream->pcm->id,
- substream->name,
- substream->number);
+ pr_debug("%s: Enter.\n", __func__);
+ pr_debug("%s: substream->pcm->name = %s.\n", __func__, substream->pcm->name);
+ pr_debug("%s: substream->pcm->id = %s.\n", __func__, substream->pcm->id);
+ pr_debug("%s: substream->name = %s.\n", __func__, substream->name);
+ pr_debug("%s: substream->number = %d.\n", __func__, substream->number);
+ pr_debug("%s: channels = %d.\n", __func__, channels);
+ pr_debug("%s: DAI-index (Codec): %d\n", __func__, codec_dai->id);
+ pr_debug("%s: DAI-index (Platform): %d\n", __func__, cpu_dai->id);
- err = snd_soc_dai_set_fmt(
- codec_dai,
- SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS);
+ err = snd_soc_dai_set_fmt(codec_dai,
+ SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS);
if (err) {
- pr_err("%s: snd_soc_dai_set_fmt(codec)"
- " failed with %d.\n",
- __func__,
+ pr_err("%s: snd_soc_dai_set_fmt(codec) failed with %d.\n",
+ __func__,
err);
goto out_err;
}
- err = snd_soc_dai_set_tdm_slot(
- codec_dai,
- 1 << CG29XX_DAI_SLOT0_SHIFT,
- 1 << CG29XX_DAI_SLOT0_SHIFT,
- UX500_CG29XX_DAI_SLOTS,
- UX500_CG29XX_DAI_SLOT_WIDTH);
+ err = snd_soc_dai_set_tdm_slot(codec_dai,
+ 1 << CG29XX_DAI_SLOT0_SHIFT,
+ 1 << CG29XX_DAI_SLOT0_SHIFT,
+ UX500_CG29XX_DAI_SLOTS,
+ UX500_CG29XX_DAI_SLOT_WIDTH);
if (err) {
- pr_err("%s: cg29xx_set_tdm_slot(codec)"
- " failed with %d.\n",
+ pr_err("%s: cg29xx_set_tdm_slot(codec_dai) failed with %d.\n",
__func__,
err);
goto out_err;
}
- err = snd_soc_dai_set_fmt(
- cpu_dai,
- SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS |
- SND_SOC_DAIFMT_NB_NF);
+ err = snd_soc_dai_set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS |
+ SND_SOC_DAIFMT_NB_NF);
if (err) {
- pr_err("%s: snd_soc_dai_set_fmt(dai)"
- " failed with %d.\n",
- __func__,
+ pr_err("%s: snd_soc_dai_set_fmt(cpu_dai) failed with %d.\n",
+ __func__,
err);
goto out_err;
}
err = snd_soc_dai_set_tdm_slot(cpu_dai,
- UX500_CG29XX_DAI_ACTIVE_SLOTS,
- UX500_CG29XX_DAI_ACTIVE_SLOTS,
- UX500_CG29XX_DAI_SLOTS,
- UX500_CG29XX_DAI_SLOT_WIDTH);
+ UX500_CG29XX_DAI_ACTIVE_SLOTS,
+ UX500_CG29XX_DAI_ACTIVE_SLOTS,
+ UX500_CG29XX_DAI_SLOTS,
+ UX500_CG29XX_DAI_SLOT_WIDTH);
if (err) {
- pr_err("%s: cg29xx_set_tdm_slot(dai)"
- " failed with %d.\n",
- __func__,
- err);
+ pr_err("%s: cg29xx_set_tdm_slot(cpu_dai) failed with %d.\n",
+ __func__,
+ err);
goto out_err;
}
@@ -105,73 +88,9 @@ out_err:
return err;
}
-static struct snd_soc_ops ux500_cg29xx_ops = {
- .hw_params = ux500_cg29xx_hw_params,
-};
-
-struct snd_soc_dai_link ux500_cg29xx_dai_links[] = {
+struct snd_soc_ops ux500_cg29xx_ops[] = {
{
- .name = "cg29xx_0",
- .stream_name = "cg29xx_0",
- .cpu_dai = &ux500_msp_dai[0],
- .codec_dai = &cg29xx_codec_dai[1],
- .init = NULL,
- .ops = &ux500_cg29xx_ops,
- },
-};
-
-static struct snd_soc_card ux500_cg29xx = {
- .name = "cg29xx",
- .probe = NULL,
- .dai_link = ux500_cg29xx_dai_links,
- .num_links = ARRAY_SIZE(ux500_cg29xx_dai_links),
- .platform = &ux500_soc_platform,
-};
-
-struct snd_soc_device ux500_cg29xx_drvdata = {
- .card = &ux500_cg29xx,
- .codec_dev = &soc_codec_dev_cg29xx,
-};
-
-static int __init ux500_cg29xx_soc_init(void)
-{
- int err;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(ux500_cg29xx_dai_links); i++) {
- pr_debug("%s: DAI-link %d, name: %s\n",
- __func__,
- i,
- ux500_cg29xx_drvdata.card->dai_link[i].name);
- }
-
- ux500_cg29xx_platform_device =
- platform_device_alloc("soc-audio", -1);
- if (!ux500_cg29xx_platform_device)
- return -ENOMEM;
-
- platform_set_drvdata(
- ux500_cg29xx_platform_device,
- &ux500_cg29xx_drvdata);
-
- ux500_cg29xx_drvdata.dev = &ux500_cg29xx_platform_device->dev;
-
- err = platform_device_add(ux500_cg29xx_platform_device);
- if (err) {
- pr_err("%s: Error: Failed to add platform device (%s).\n",
- __func__,
- ux500_cg29xx_drvdata.card->name);
- platform_device_put(ux500_cg29xx_platform_device);
+ .hw_params = ux500_cg29xx_hw_params,
}
+};
- return err;
-}
-module_init(ux500_cg29xx_soc_init);
-
-static void __exit ux500_cg29xx_soc_exit(void)
-{
- platform_device_unregister(ux500_cg29xx_platform_device);
-}
-module_exit(ux500_cg29xx_soc_exit);
-
-MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/ux500/ux500_cg29xx.h b/sound/soc/ux500/ux500_cg29xx.h
new file mode 100644
index 00000000000..49a8c3e0478
--- /dev/null
+++ b/sound/soc/ux500/ux500_cg29xx.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Ola Lilja <ola.o.lilja@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#ifndef UX500_CG29XX_H
+#define UX500_CG29XX_H
+
+extern struct snd_soc_ops ux500_cg29xx_ops[];
+
+#endif
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c
index 432f5646b67..6a4574c0931 100644
--- a/sound/soc/ux500/ux500_msp_dai.c
+++ b/sound/soc/ux500/ux500_msp_dai.c
@@ -1,8 +1,8 @@
/*
* Copyright (C) ST-Ericsson SA 2010
*
- * Author: Ola Lilja (ola.o.lilja@stericsson.com),
- * Roger Nilsson (roger.xr.nilsson@stericsson.com)
+ * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
+ * Roger Nilsson <roger.xr.nilsson@stericsson.com>
* for ST-Ericsson.
*
* License terms:
@@ -11,6 +11,7 @@
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
+
#include <linux/slab.h>
#include <asm/dma.h>
#include <linux/bitops.h>
@@ -23,7 +24,7 @@
#include "ux500_msp_dai.h"
#include "ux500_pcm.h"
-static struct ux500_msp_dai_private ux500_msp_dai_private[UX500_NBR_OF_DAI] = {
+static struct ux500_platform_drvdata platform_drvdata[UX500_NBR_OF_DAI] = {
{
.i2s = NULL,
.fmt = 0,
@@ -31,6 +32,8 @@ static struct ux500_msp_dai_private ux500_msp_dai_private[UX500_NBR_OF_DAI] = {
.tx_mask = 0x01,
.rx_mask = 0x01,
.slot_width = 16,
+ .playback_active = false,
+ .capture_active = false,
},
{
.i2s = NULL,
@@ -39,6 +42,8 @@ static struct ux500_msp_dai_private ux500_msp_dai_private[UX500_NBR_OF_DAI] = {
.tx_mask = 0x01,
.rx_mask = 0x01,
.slot_width = 16,
+ .playback_active = false,
+ .capture_active = false,
},
{
.i2s = NULL,
@@ -47,73 +52,22 @@ static struct ux500_msp_dai_private ux500_msp_dai_private[UX500_NBR_OF_DAI] = {
.tx_mask = 0x01,
.rx_mask = 0x01,
.slot_width = 16,
+ .playback_active = false,
+ .capture_active = false,
},
};
-static int ux500_msp_dai_i2s_probe(struct i2s_device *i2s)
-{
- pr_info("%s: Enter (chip_select = %d, i2s = %d).\n",
- __func__,
- (int)i2s->chip_select, (int)(i2s));
-
- ux500_msp_dai_private[i2s->chip_select].i2s = i2s;
-
- try_module_get(i2s->controller->dev.parent->driver->owner);
- i2s_set_drvdata(
- i2s,
- (void *)&ux500_msp_dai_private[i2s->chip_select]);
-
- return 0;
-}
-
-static int ux500_msp_dai_i2s_remove(struct i2s_device *i2s)
-{
- struct ux500_msp_dai_private *ux500_msp_dai_private =
- i2s_get_drvdata(i2s);
-
- pr_debug("%s: Enter (chip_select = %d).\n",
- __func__,
- (int)i2s->chip_select);
-
- ux500_msp_dai_private->i2s = NULL;
- i2s_set_drvdata(i2s, NULL);
-
- pr_debug("%s: Calling module_put.\n",
- __func__);
- module_put(i2s->controller->dev.parent->driver->owner);
-
- return 0;
-}
-
-static const struct i2s_device_id dev_id_table[] = {
- { "i2s_device.0", 0, 0 },
- { "i2s_device.1", 0, 0 },
- { "i2s_device.2", 0, 0 },
- { },
-};
-MODULE_DEVICE_TABLE(i2s, dev_id_table);
-
-static struct i2s_driver i2sdrv_i2s = {
- .driver = {
- .name = "ux500_asoc_i2s",
- .owner = THIS_MODULE,
- },
- .probe = ux500_msp_dai_i2s_probe,
- .remove = __devexit_p(ux500_msp_dai_i2s_remove),
- .id_table = dev_id_table,
-};
-
bool ux500_msp_dai_i2s_get_underrun_status(int dai_idx)
{
- struct ux500_msp_dai_private *dai_private = &ux500_msp_dai_private[dai_idx];
- int status = i2s_hw_status(dai_private->i2s->controller);
+ struct ux500_platform_drvdata *drvdata = &platform_drvdata[dai_idx];
+ int status = i2s_hw_status(drvdata->i2s->controller);
return (bool)(status & TRANSMIT_UNDERRUN_ERR_INT);
}
dma_addr_t ux500_msp_dai_i2s_get_pointer(int dai_idx, int stream_id)
{
- struct ux500_msp_dai_private *dai_private = &ux500_msp_dai_private[dai_idx];
- return i2s_get_pointer(dai_private->i2s->controller,
+ struct ux500_platform_drvdata *drvdata = &platform_drvdata[dai_idx];
+ return i2s_get_pointer(drvdata->i2s->controller,
(stream_id == SNDRV_PCM_STREAM_PLAYBACK) ?
I2S_DIRECTION_TX :
I2S_DIRECTION_RX);
@@ -125,7 +79,7 @@ int ux500_msp_dai_i2s_configure_sg(dma_addr_t dma_addr,
int dai_idx,
int stream_id)
{
- struct ux500_msp_dai_private *dai_private = &ux500_msp_dai_private[dai_idx];
+ struct ux500_platform_drvdata *drvdata = &platform_drvdata[dai_idx];
struct i2s_message message;
struct i2s_device *i2s_dev;
int i;
@@ -138,7 +92,7 @@ int ux500_msp_dai_i2s_configure_sg(dma_addr_t dma_addr,
sg_len,
sg_size);
- if (!ux500_msp_dai[dai_idx].playback.active) {
+ if (!drvdata->playback_active) {
pr_err("%s: The I2S controller is not available."
"MSP index:%d\n",
__func__,
@@ -146,7 +100,7 @@ int ux500_msp_dai_i2s_configure_sg(dma_addr_t dma_addr,
return ret;
}
- i2s_dev = dai_private->i2s;
+ i2s_dev = drvdata->i2s;
sg = kzalloc(sizeof(struct scatterlist) * sg_len, GFP_ATOMIC);
sg_init_table(sg, sg_len);
@@ -174,161 +128,70 @@ int ux500_msp_dai_i2s_configure_sg(dma_addr_t dma_addr,
return ret;
}
-int ux500_msp_dai_i2s_send_data(void *data,
- size_t bytes,
- int dai_idx)
+static const char *stream_str(struct snd_pcm_substream *substream)
{
- struct ux500_msp_dai_private *dai_private =
- &ux500_msp_dai_private[dai_idx];
- struct i2s_message message;
- struct i2s_device *i2s_dev;
- int ret = 0;
-
- pr_debug("%s: Enter. (MSP-index: %d, bytes = %d).\n",
- __func__,
- dai_idx,
- (int)bytes);
-
- i2s_dev = dai_private->i2s;
-
- if (!ux500_msp_dai[dai_idx].playback.active) {
- pr_err("%s: The I2S controller is not available."
- "MSP index:%d\n",
- __func__,
- dai_idx);
- return ret;
- }
-
- message.i2s_transfer_mode = I2S_TRANSFER_MODE_SINGLE_DMA;
- message.i2s_direction = I2S_DIRECTION_TX;
- message.txbytes = bytes;
- message.txdata = data;
-
- ret = i2s_transfer(i2s_dev->controller, &message);
- if (ret < 0) {
- pr_err("%s: Error: i2s_transfer failed. MSP index: %d\n",
- __func__,
- dai_idx);
- }
-
- return ret;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ return "Playback";
+ else
+ return "Capture";
}
-int ux500_msp_dai_i2s_receive_data(void *data,
- size_t bytes,
- int dai_idx)
+static int ux500_msp_dai_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
- struct ux500_msp_dai_private *dai_private =
- &ux500_msp_dai_private[dai_idx];
- struct i2s_message message;
- struct i2s_device *i2s_dev;
- int ret = 0;
-
- pr_debug("%s: Enter. (MSP-index: %d, Bytes: %d).\n",
- __func__,
- dai_idx,
- (int)bytes);
+ struct ux500_platform_drvdata *drvdata = &platform_drvdata[dai->id];
+ bool mode_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
- i2s_dev = dai_private->i2s;
+ pr_debug("%s: MSP %d (%s): Enter.\n", __func__, dai->id, stream_str(substream));
- if (!ux500_msp_dai[dai_idx].capture.active) {
- pr_err("%s: MSP controller is not available. (MSP-index: %d)\n",
+ if ((mode_playback && drvdata->playback_active) ||
+ (!mode_playback && drvdata->capture_active)) {
+ pr_err("%s: Error: MSP %d (%s): Stream already active.\n",
__func__,
- dai_idx);
- return ret;
+ dai->id,
+ stream_str(substream));
+ return -EBUSY;
}
- message.i2s_transfer_mode = I2S_TRANSFER_MODE_SINGLE_DMA;
- message.i2s_direction = I2S_DIRECTION_RX;
- message.rxbytes = bytes;
- message.rxdata = data;
- message.dma_flag = 1;
-
- ret = i2s_transfer(i2s_dev->controller, &message);
- if (ret < 0) {
- pr_err("%s: i2s_transfer failed (%d)! (MSP-index: %d)\n",
- __func__,
- ret,
- dai_idx);
- }
+ if (mode_playback)
+ drvdata->playback_active = true;
+ else
+ drvdata->capture_active = true;
- return ret;
+ return 0;
}
static void ux500_msp_dai_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *msp_dai)
+ struct snd_soc_dai *dai)
{
- struct ux500_msp_dai_private *dai_private = msp_dai->private_data;
+ struct ux500_platform_drvdata *drvdata = &platform_drvdata[dai->id];
+ bool mode_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
- pr_info("%s: Enter (stream = %s).\n",
- __func__,
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- "SNDRV_PCM_STREAM_PLAYBACK" : "SNDRV_PCM_STREAM_CAPTURE");
- if (dai_private == NULL)
- return;
-
- pr_debug("%s: chip_select = %d.\n",
- __func__,
- (int)dai_private->i2s->chip_select);
-
- if (i2s_cleanup(dai_private->i2s->controller,
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- DISABLE_TRANSMIT : DISABLE_RECEIVE)) {
-
- pr_err("%s: Error closing i2s for %s.\n",
- __func__,
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- "playback" : "capture");
- }
- return;
-}
+ pr_debug("%s: MSP %d (%s): Enter.\n", __func__, dai->id, stream_str(substream));
-static int ux500_msp_dai_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *msp_dai)
-{
- struct ux500_msp_dai_private *dai_private =
- &ux500_msp_dai_private[msp_dai->id];
-
- pr_info("%s: MSP Index: %d.\n",
- __func__,
- msp_dai->id);
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- msp_dai->playback.active : msp_dai->capture.active) {
- pr_err("%s: A %s stream is already active.\n",
- __func__,
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- "PLAYBACK" : "CAPTURE");
- return -EBUSY;
- }
+ if (drvdata == NULL)
+ return;
- msp_dai->private_data = dai_private;
+ if (mode_playback)
+ drvdata->playback_active = false;
+ else
+ drvdata->capture_active = false;
- if (dai_private->i2s == NULL) {
- pr_err("%s: MSP index: %d"
- "i2sdrv.i2s == NULL\n",
- __func__,
- msp_dai->id);
- return -1;
- }
-
- if (dai_private->i2s->controller == NULL) {
- pr_err("%s: MSP index: %d"
- "i2sdrv.i2s->controller == NULL.\n",
- __func__,
- msp_dai->id);
- return -1;
+ if (i2s_cleanup(drvdata->i2s->controller,
+ mode_playback ? DISABLE_TRANSMIT : DISABLE_RECEIVE)) {
+ pr_err("%s: Error: MSP %d (%s): Unable to close i2s.\n",
+ __func__,
+ dai->id,
+ stream_str(substream));
}
- return 0;
+ return;
}
-static void ux500_msp_dai_setup_multichannel(
- struct ux500_msp_dai_private *private,
- struct msp_config *msp_config)
+static void ux500_msp_dai_setup_multichannel(struct ux500_platform_drvdata *private,
+ struct msp_config *msp_config)
{
- struct msp_multichannel_config *multi =
- &msp_config->multichannel_config;
+ struct msp_multichannel_config *multi = &msp_config->multichannel_config;
if (private->slots > 1) {
msp_config->multichannel_configured = 1;
@@ -356,10 +219,9 @@ static void ux500_msp_dai_setup_multichannel(
}
}
-static void ux500_msp_dai_setup_frameper(
- struct ux500_msp_dai_private *private,
- unsigned int rate,
- struct msp_protocol_desc *prot_desc)
+static void ux500_msp_dai_setup_frameper(struct ux500_platform_drvdata *private,
+ unsigned int rate,
+ struct msp_protocol_desc *prot_desc)
{
switch (private->slots) {
default:
@@ -408,10 +270,9 @@ static void ux500_msp_dai_setup_frameper(
prot_desc->total_clocks_for_one_frame);
}
-static void ux500_msp_dai_setup_framing_pcm(
- struct ux500_msp_dai_private *private,
- unsigned int rate,
- struct msp_protocol_desc *prot_desc)
+static void ux500_msp_dai_setup_framing_pcm(struct ux500_platform_drvdata *private,
+ unsigned int rate,
+ struct msp_protocol_desc *prot_desc)
{
u32 frame_length = MSP_FRAME_LENGTH_1;
prot_desc->frame_width = 0;
@@ -448,9 +309,8 @@ static void ux500_msp_dai_setup_framing_pcm(
ux500_msp_dai_setup_frameper(private, rate, prot_desc);
}
-static void ux500_msp_dai_setup_clocking(
- unsigned int fmt,
- struct msp_config *msp_config)
+static void ux500_msp_dai_setup_clocking(unsigned int fmt,
+ struct msp_config *msp_config)
{
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
@@ -491,9 +351,8 @@ static void ux500_msp_dai_setup_clocking(
}
}
-static void ux500_msp_dai_compile_prot_desc_pcm(
- unsigned int fmt,
- struct msp_protocol_desc *prot_desc)
+static void ux500_msp_dai_compile_prot_desc_pcm(unsigned int fmt,
+ struct msp_protocol_desc *prot_desc)
{
prot_desc->rx_phase_mode = MSP_SINGLE_PHASE;
prot_desc->tx_phase_mode = MSP_SINGLE_PHASE;
@@ -525,8 +384,7 @@ static void ux500_msp_dai_compile_prot_desc_pcm(
prot_desc->frame_sync_ignore = MSP_FRAME_SYNC_IGNORE;
}
-static void ux500_msp_dai_compile_prot_desc_i2s(
- struct msp_protocol_desc *prot_desc)
+static void ux500_msp_dai_compile_prot_desc_i2s(struct msp_protocol_desc *prot_desc)
{
prot_desc->rx_phase_mode = MSP_DUAL_PHASE;
prot_desc->tx_phase_mode = MSP_DUAL_PHASE;
@@ -560,11 +418,10 @@ static void ux500_msp_dai_compile_prot_desc_i2s(
prot_desc->frame_sync_ignore = MSP_FRAME_SYNC_IGNORE;
}
-static void ux500_msp_dai_compile_msp_config(
- struct snd_pcm_substream *substream,
- struct ux500_msp_dai_private *private,
- unsigned int rate,
- struct msp_config *msp_config)
+static void ux500_msp_dai_compile_msp_config(struct snd_pcm_substream *substream,
+ struct ux500_platform_drvdata *private,
+ unsigned int rate,
+ struct msp_config *msp_config)
{
struct msp_protocol_desc *prot_desc = &msp_config->protocol_desc;
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -640,31 +497,24 @@ static void ux500_msp_dai_compile_msp_config(
}
static int ux500_msp_dai_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *msp_dai)
+ struct snd_soc_dai *dai)
{
int ret = 0;
- struct ux500_msp_dai_private *dai_private = msp_dai->private_data;
+ struct ux500_platform_drvdata *drvdata = &platform_drvdata[dai->id];
struct snd_pcm_runtime *runtime = substream->runtime;
struct msp_config msp_config;
- pr_debug("%s: Enter (stream = %p - %s, chip_select = %d).\n",
- __func__,
- substream,
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- "SNDRV_PCM_STREAM_PLAYBACK" : "SNDRV_PCM_STREAM_CAPTURE",
- (int)dai_private->i2s->chip_select);
-
- pr_debug("%s: Setting up dai with rate %u.\n",
- __func__,
- runtime->rate);
+ pr_debug("%s: MSP %d (%s): Enter.\n", __func__, dai->id, stream_str(substream));
- ux500_msp_dai_compile_msp_config(substream, dai_private,
- runtime->rate, &msp_config);
+ pr_debug("%s: Setup dai (Rate: %u).\n", __func__, runtime->rate);
+ ux500_msp_dai_compile_msp_config(substream,
+ drvdata,
+ runtime->rate,
+ &msp_config);
- ret = i2s_setup(dai_private->i2s->controller, &msp_config);
+ ret = i2s_setup(drvdata->i2s->controller, &msp_config);
if (ret < 0) {
- pr_err("u8500_msp_dai_prepare: i2s_setup failed! "
- "ret = %d\n", ret);
+ pr_err("%s: Error: i2s_setup failed (ret = %d)!\n", __func__, ret);
goto cleanup;
}
@@ -674,24 +524,21 @@ cleanup:
static int ux500_msp_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
- struct snd_soc_dai *msp_dai)
+ struct snd_soc_dai *dai)
{
unsigned int mask, slots_active;
- struct ux500_msp_dai_private *private = msp_dai->private_data;
+ struct ux500_platform_drvdata *drvdata = &platform_drvdata[dai->id];
- pr_debug("%s: Enter stream: %s, MSP index: %d.\n",
+ pr_debug("%s: MSP %d (%s): Enter.\n",
__func__,
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- "SNDRV_PCM_STREAM_PLAYBACK" :
- "SNDRV_PCM_STREAM_CAPTURE",
- (int)private->i2s->chip_select);
+ dai->id,
+ stream_str(substream));
- switch (private->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ switch (drvdata->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
if (params_channels(params) != 2) {
- pr_err("%s: The I2S requires "
- "that the channel count of the substream "
- "is two. Substream channels: %d.\n",
+ pr_err("%s: Error: I2S requires channels = 2 "
+ "(channels = %d)!\n",
__func__,
params_channels(params));
return -EINVAL;
@@ -701,22 +548,20 @@ static int ux500_msp_dai_hw_params(struct snd_pcm_substream *substream,
case SND_SOC_DAIFMT_DSP_A:
mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- private->tx_mask :
- private->rx_mask;
+ drvdata->tx_mask :
+ drvdata->rx_mask;
slots_active = hweight32(mask);
pr_debug("TDM slots active: %d", slots_active);
if (params_channels(params) != slots_active) {
- pr_err("%s: The PCM format requires "
- "that the channel count of the substream "
- "matches the number of active slots.\n"
- "Number of active slots: %d\n"
- "Substream channels: %d.\n",
+ pr_err("%s: Error: PCM TDM format requires channels "
+ "to match active slots "
+ "(channels = %d, active slots = %d)!\n",
__func__,
- slots_active,
- params_channels(params));
+ params_channels(params),
+ slots_active);
return -EINVAL;
}
break;
@@ -728,18 +573,14 @@ static int ux500_msp_dai_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int ux500_msp_dai_set_dai_fmt(struct snd_soc_dai *msp_dai,
+static int ux500_msp_dai_set_dai_fmt(struct snd_soc_dai *dai,
unsigned int fmt)
{
- struct ux500_msp_dai_private *dai_private =
- msp_dai->private_data;
+ struct ux500_platform_drvdata *drvdata = &platform_drvdata[dai->id];
- pr_debug("%s: MSP index: %d: Enter.\n",
- __func__,
- (int)dai_private->i2s->chip_select);
+ pr_debug("%s: MSP %d: Enter.\n", __func__, dai->id);
- switch (fmt &
- (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
+ switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBS_CFS:
@@ -749,9 +590,7 @@ static int ux500_msp_dai_set_dai_fmt(struct snd_soc_dai *msp_dai,
break;
default:
- pr_err("Unsupported DAI format (0x%x)!\n",
- fmt);
- return -EINVAL;
+ goto unsupported_format;
}
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
@@ -760,40 +599,46 @@ static int ux500_msp_dai_set_dai_fmt(struct snd_soc_dai *msp_dai,
break;
default:
- pr_err("Unsupported DAI format (0x%x)!\n",
- fmt);
- return -EINVAL;
+ goto unsupported_format;
}
- dai_private->fmt = fmt;
+ drvdata->fmt = fmt;
return 0;
+
+unsupported_format:
+ pr_err("%s: MSP %d: Error: Unsupported DAI format (0x%x)!\n",
+ __func__,
+ dai->id,
+ fmt);
+ return -EINVAL;
}
static int ux500_msp_dai_set_tdm_slot(struct snd_soc_dai *dai,
- unsigned int tx_mask,
- unsigned int rx_mask,
- int slots,
- int slot_width)
+ unsigned int tx_mask,
+ unsigned int rx_mask,
+ int slots,
+ int slot_width)
{
- struct ux500_msp_dai_private *private =
- dai->private_data;
+ struct ux500_platform_drvdata *drvdata = &platform_drvdata[dai->id];
unsigned int cap;
if (!(slots == 1 || slots == 2 || slots == 8 || slots == 16)) {
- pr_err("%s - error: slots %d Supported values are 1/2/8/16.\n",
+ pr_err("%s: Error: Unsupported slots (%d)! "
+ "Supported values are 1/2/8/16.\n",
__func__,
slots);
return -EINVAL;
}
- private->slots = slots;
+ drvdata->slots = slots;
if (!(slot_width == 16)) {
- pr_err("%s - error: slot_width %d Supported value is 16.\n",
+ pr_err("%s: Error: Unsupported slots_width (%d)!. "
+ "Supported value is 16.\n",
__func__,
slot_width);
return -EINVAL;
}
- private->slot_width = slot_width;
+ drvdata->slot_width = slot_width;
switch (slots) {
default:
@@ -811,28 +656,24 @@ static int ux500_msp_dai_set_tdm_slot(struct snd_soc_dai *dai,
break;
}
- private->tx_mask = tx_mask & cap;
- private->rx_mask = rx_mask & cap;
+ drvdata->tx_mask = tx_mask & cap;
+ drvdata->rx_mask = rx_mask & cap;
return 0;
}
static int ux500_msp_dai_trigger(struct snd_pcm_substream *substream,
int cmd,
- struct snd_soc_dai *msp_dai)
+ struct snd_soc_dai *dai)
{
int ret = 0;
- struct ux500_msp_dai_private *dai_private =
- msp_dai->private_data;
+ struct ux500_platform_drvdata *drvdata = &platform_drvdata[dai->id];
- pr_debug("%s: Enter (stream = %p - %s,"
- " chip_select = %d, cmd = %d).\n",
+ pr_debug("%s: MSP %d (%s): Enter (chip_select = %d, cmd = %d).\n",
__func__,
- substream,
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- "SNDRV_PCM_STREAM_PLAYBACK" :
- "SNDRV_PCM_STREAM_CAPTURE",
- (int)dai_private->i2s->chip_select,
+ dai->id,
+ stream_str(substream),
+ (int)drvdata->i2s->chip_select,
cmd);
switch (cmd) {
@@ -858,9 +699,9 @@ static int ux500_msp_dai_trigger(struct snd_pcm_substream *substream,
return ret;
}
-struct snd_soc_dai ux500_msp_dai[UX500_NBR_OF_DAI] = {
+static struct snd_soc_dai_driver ux500_msp_dai_drv[UX500_NBR_OF_DAI] = {
{
- .name = "ux500_i2s-0",
+ .name = "ux500-msp.0",
.id = 0,
.suspend = NULL,
.resume = NULL,
@@ -888,10 +729,9 @@ struct snd_soc_dai ux500_msp_dai[UX500_NBR_OF_DAI] = {
.hw_params = ux500_msp_dai_hw_params,
}
},
- .private_data = &ux500_msp_dai_private[0],
},
{
- .name = "ux500_i2s-1",
+ .name = "ux500-msp.1",
.id = 1,
.suspend = NULL,
.resume = NULL,
@@ -919,10 +759,9 @@ struct snd_soc_dai ux500_msp_dai[UX500_NBR_OF_DAI] = {
.hw_params = ux500_msp_dai_hw_params,
}
},
- .private_data = &ux500_msp_dai_private[1],
},
{
- .name = "ux500_i2s-2",
+ .name = "ux500-msp.2",
.id = 2,
.suspend = NULL,
.resume = NULL,
@@ -950,51 +789,92 @@ struct snd_soc_dai ux500_msp_dai[UX500_NBR_OF_DAI] = {
.hw_params = ux500_msp_dai_hw_params,
}
},
- .private_data = &ux500_msp_dai_private[2],
},
};
-EXPORT_SYMBOL(ux500_msp_dai);
+EXPORT_SYMBOL(ux500_msp_dai_drv);
-static int __init ux500_msp_dai_init(void)
+static int __devinit ux500_msp_drv_probe(struct i2s_device *i2s_dev)
{
- int i;
int ret = 0;
+ struct ux500_platform_drvdata *drvdata;
+ int msp_idx = i2s_dev->chip_select;
+
+ pr_debug("%s: Enter (idx: %d, dev-name: %s, drv-name: %s).\n",
+ __func__,
+ msp_idx,
+ dev_name(&i2s_dev->dev),
+ i2s_dev->dev.driver->name);
+
+ drvdata = &platform_drvdata[msp_idx];
+ drvdata->i2s = i2s_dev;
+
+ try_module_get(i2s_dev->controller->dev.parent->driver->owner);
+ i2s_set_drvdata(i2s_dev, drvdata);
- ret = i2s_register_driver(&i2sdrv_i2s);
+ pr_debug("%s: Register MSP %d.\n", __func__, msp_idx);
+ ret = snd_soc_register_dai(&i2s_dev->dev, &ux500_msp_dai_drv[msp_idx]);
if (ret < 0) {
- pr_err("%s: Unable to register as a I2S driver.\n",
- __func__);
+ pr_err("Error: %s: Failed to register MSP %d.\n", __func__, msp_idx);
return ret;
}
- for (i = 0; i < UX500_NBR_OF_DAI; i++) {
- pr_debug("%s: Register MSP dai %d.\n",
- __func__,
- i);
- ret = snd_soc_register_dai(&ux500_msp_dai[i]);
- if (ret < 0) {
- pr_err("Error: Failed to register MSP dai %d.\n",
- i);
- return ret;
- }
- }
-
return ret;
}
-static void __exit ux500_msp_dai_exit(void)
+static int ux500_msp_drv_remove(struct i2s_device *i2s_dev)
{
- int i;
+ struct ux500_platform_drvdata *drvdata = i2s_get_drvdata(i2s_dev);
+ int msp_idx = i2s_dev->chip_select;
+
+ pr_debug("%s: Enter (idx: %d, dev-name: %s, drv-name: %s).\n",
+ __func__,
+ msp_idx,
+ dev_name(&i2s_dev->dev),
+ i2s_dev->dev.driver->name);
+
+ drvdata->i2s = NULL;
+ i2s_set_drvdata(i2s_dev, NULL);
+
+ pr_debug("%s: Calling module_put.\n", __func__);
+ module_put(i2s_dev->controller->dev.parent->driver->owner);
+
+ pr_debug("%s: Unregister ux500-pcm SoC platform driver.\n", __func__);
+ snd_soc_unregister_dais(&i2s_dev->dev, ARRAY_SIZE(ux500_msp_dai_drv));
+
+ return 0;
+}
+static const struct i2s_device_id dev_id_table[] = {
+ { "i2s_device.0", 0, 0 },
+ { "i2s_device.1", 1, 0 },
+ { "i2s_device.2", 2, 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2s, dev_id_table);
+
+static struct i2s_driver i2sdrv_i2s = {
+ .driver = {
+ .name = "i2s",
+ .owner = THIS_MODULE,
+ },
+ .probe = ux500_msp_drv_probe,
+ .remove = __devexit_p(ux500_msp_drv_remove),
+ .id_table = dev_id_table,
+};
+
+static int __init ux500_msp_init(void)
+{
+ return i2s_register_driver(&i2sdrv_i2s);
+}
+
+static void __exit ux500_msp_exit(void)
+{
pr_debug("%s: Enter.\n", __func__);
i2s_unregister_driver(&i2sdrv_i2s);
-
- for (i = 0; i < UX500_NBR_OF_DAI; i++)
- snd_soc_unregister_dai(&ux500_msp_dai[i]);
}
-module_init(ux500_msp_dai_init);
-module_exit(ux500_msp_dai_exit);
+module_init(ux500_msp_init);
+module_exit(ux500_msp_exit);
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPLv2");
diff --git a/sound/soc/ux500/ux500_msp_dai.h b/sound/soc/ux500/ux500_msp_dai.h
index 90bc518fc83..28f06120f58 100644
--- a/sound/soc/ux500/ux500_msp_dai.h
+++ b/sound/soc/ux500/ux500_msp_dai.h
@@ -1,8 +1,8 @@
/*
* Copyright (C) ST-Ericsson SA 2010
*
- * Author: Ola Lilja ola.o.lilja@stericsson.com,
- * Roger Nilsson roger.xr.nilsson@stericsson.com
+ * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
+ * Roger Nilsson <roger.xr.nilsson@stericsson.com>
* for ST-Ericsson.
*
* License terms:
@@ -38,13 +38,15 @@
#define UX500_MSP_MIN_CHANNELS 1
#define UX500_MSP_MAX_CHANNELS 8
-struct ux500_msp_dai_private {
+struct ux500_platform_drvdata {
struct i2s_device *i2s;
unsigned int fmt;
unsigned int tx_mask;
unsigned int rx_mask;
int slots;
int slot_width;
+ bool playback_active;
+ bool capture_active;
};
extern struct snd_soc_dai ux500_msp_dai[UX500_NBR_OF_DAI];
diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c
index c0765f7a839..f8c92b59da2 100644
--- a/sound/soc/ux500/ux500_pcm.c
+++ b/sound/soc/ux500/ux500_pcm.c
@@ -1,8 +1,8 @@
/*
* Copyright (C) ST-Ericsson SA 2010
*
- * Author: Ola Lilja (ola.o.lilja@stericsson.com),
- * Roger Nilsson (roger.xr.nilsson@stericsson.com)
+ * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
+ * Roger Nilsson <roger.xr.nilsson@stericsson.com>
* for ST-Ericsson.
*
* License terms:
@@ -68,6 +68,14 @@ static struct snd_pcm_hardware ux500_pcm_hw_capture = {
.periods_max = UX500_PLATFORM_PERIODS_MAX,
};
+static const char *stream_str(struct snd_pcm_substream *substream)
+{
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ return "Playback";
+ else
+ return "Capture";
+}
+
static void ux500_pcm_dma_hw_free(struct device *dev,
struct snd_pcm_substream *substream)
{
@@ -94,8 +102,10 @@ void ux500_pcm_dma_eot_handler(void *data)
struct snd_pcm_substream *substream = data;
struct snd_pcm_runtime *runtime;
struct ux500_pcm_private *private;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *dai = rtd->cpu_dai;
- pr_debug("%s: Enter\n", __func__);
+ pr_err("%s: MSP %d (%s): Enter.\n", __func__, dai->id, stream_str(substream));
if (substream) {
runtime = substream->runtime;
@@ -115,17 +125,35 @@ static int ux500_pcm_open(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
struct ux500_pcm_private *private;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ int ret;
- pr_info("%s: Enter\n", __func__);
+ pr_debug("%s: MSP %d (%s): Enter.\n", __func__, dai->id, stream_str(substream));
+
+ pr_debug("%s: Set runtime hwparams.\n", __func__);
+ if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
+ snd_soc_set_runtime_hwparams(substream, &ux500_pcm_hw_playback);
+ else
+ snd_soc_set_runtime_hwparams(substream, &ux500_pcm_hw_capture);
+
+ /* ensure that buffer size is a multiple of period size */
+ ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0) {
+ pr_err("%s: Error: snd_pcm_hw_constraints failed (%d)\n",
+ __func__,
+ ret);
+ return ret;
+ }
+
+ pr_debug("%s: Init runtime private data.\n", __func__);
private = kzalloc(sizeof(struct ux500_pcm_private), GFP_KERNEL);
if (private == NULL)
return -ENOMEM;
-
- private->msp_id = rtd->dai->cpu_dai->id;
+ private->msp_id = dai->id;
runtime->private_data = private;
- pr_debug("%s: Setting HW-config\n", __func__);
+ pr_debug("%s: Set hw-struct for %s.\n", __func__, stream_str(substream));
runtime->hw = (stream_id == SNDRV_PCM_STREAM_PLAYBACK) ?
ux500_pcm_hw_playback : ux500_pcm_hw_capture;
@@ -332,35 +360,66 @@ static int ux500_pcm_resume(struct snd_soc_dai *dai)
return 0;
}
-struct snd_soc_platform ux500_soc_platform = {
- .name = "ux500-audio",
- .pcm_ops = &ux500_pcm_ops,
+struct snd_soc_platform_driver ux500_pcm_soc_drv = {
+ .ops = &ux500_pcm_ops,
.pcm_new = ux500_pcm_new,
.pcm_free = ux500_pcm_free,
.suspend = ux500_pcm_suspend,
.resume = ux500_pcm_resume,
};
-EXPORT_SYMBOL(ux500_soc_platform);
+EXPORT_SYMBOL(ux500_pcm_soc_drv);
-static int __init ux500_pcm_init(void)
+static int __devinit ux500_pcm_drv_probe(struct platform_device *pdev)
{
int ret;
- pr_debug("%s: Register platform.\n", __func__);
- ret = snd_soc_register_platform(&ux500_soc_platform);
- if (ret < 0)
- pr_debug("%s: Error: Failed to register platform!\n",
- __func__);
+ pr_debug("%s: Register ux500-pcm SoC platform driver.\n", __func__);
+ ret = snd_soc_register_platform(&pdev->dev, &ux500_pcm_soc_drv);
+ if (ret < 0) {
+ pr_err("%s: Error: Failed to register "
+ "ux500-pcm SoC platform driver (%d)!\n",
+ __func__,
+ ret);
+ return ret;
+ }
return 0;
}
-static void __exit ux500_pcm_exit(void)
+static int __devexit ux500_pcm_drv_remove(struct platform_device *pdev)
{
- snd_soc_unregister_platform(&ux500_soc_platform);
+ pr_debug("%s: Unregister ux500-pcm SoC platform driver.\n", __func__);
+ snd_soc_unregister_platform(&pdev->dev);
+
+ return 0;
+}
+
+static struct platform_driver ux500_pcm_drv = {
+ .driver = {
+ .name = "ux500-pcm",
+ .owner = THIS_MODULE,
+ },
+
+ .probe = ux500_pcm_drv_probe,
+ .remove = __devexit_p(ux500_pcm_drv_remove),
+};
+
+static int __init ux500_pcm_drv_init(void)
+{
+ pr_debug("%s: Register ux500-pcm platform driver.\n", __func__);
+
+ return platform_driver_register(&ux500_pcm_drv);
+}
+
+
+static void __exit ux500_pcm_drv_exit(void)
+{
+ pr_debug("%s: Unregister ux500-pcm platform driver.\n", __func__);
+
+ platform_driver_unregister(&ux500_pcm_drv);
}
-module_init(ux500_pcm_init);
-module_exit(ux500_pcm_exit);
+module_init(ux500_pcm_drv_init);
+module_exit(ux500_pcm_drv_exit);
MODULE_LICENSE("GPL");
diff --git a/sound/soc/ux500/ux500_pcm.h b/sound/soc/ux500/ux500_pcm.h
index 9d8b36d9b6f..de2df94fd97 100644
--- a/sound/soc/ux500/ux500_pcm.h
+++ b/sound/soc/ux500/ux500_pcm.h
@@ -1,8 +1,8 @@
/*
* Copyright (C) ST-Ericsson SA 2010
*
- * Author: Ola Lilja ola.o.lilja@stericsson.com,
- * Roger Nilsson roger.xr.nilsson@stericsson.com
+ * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
+ * Roger Nilsson <roger.xr.nilsson@stericsson.com>
* for ST-Ericsson.
*
* License terms: