summaryrefslogtreecommitdiff
path: root/sound/soc/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs')
-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
7 files changed, 582 insertions, 636 deletions
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;