[PATCH 2/5] sgtl5000 audio: more porting to 2.6.31
Brad Figg
brad.figg at canonical.com
Thu Oct 8 16:39:10 UTC 2009
From: Alan Tull <r80115 at freescale.com>
With this patch record and playback work at various sample rates
---
sound/soc/codecs/sgtl5000.c | 244 ++++++++++++++++++-----------------
sound/soc/imx/imx-3stack-sgtl5000.c | 62 ++++-----
sound/soc/imx/imx-pcm.c | 15 ++-
sound/soc/imx/imx-ssi.c | 87 ++++++-------
4 files changed, 205 insertions(+), 203 deletions(-)
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 27e83b6..3d754de 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -379,21 +379,6 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = {
1),
};
-static int sgtl5000_add_controls(struct snd_soc_codec *codec)
-{
- int err, i;
-
- for (i = 0; i < ARRAY_SIZE(sgtl5000_snd_controls); i++) {
- err = snd_ctl_add(codec->card,
- snd_soc_cnew(&sgtl5000_snd_controls[i],
- codec, NULL));
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-
static int sgtl5000_digital_mute(struct snd_soc_dai *codec_dai, int mute)
{
struct snd_soc_codec *codec = codec_dai->codec;
@@ -497,8 +482,8 @@ static int sgtl5000_set_dai_sysclk(struct snd_soc_dai *codec_dai,
return 0;
}
-static void sgtl5000_pcm_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dia)
+static int sgtl5000_pcm_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -526,11 +511,12 @@ static void sgtl5000_pcm_shutdown(struct snd_pcm_substream *substream,
return 0;
}
-static int sgtl5000_pcm_startup(struct snd_pcm_substream *substream)
+static int sgtl5000_pcm_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->codec;
+ struct snd_soc_codec *codec = socdev->card->codec;
struct sgtl5000_priv *sgtl5000 = codec->private_data;
struct snd_pcm_runtime *master_runtime;
@@ -545,13 +531,8 @@ static int sgtl5000_pcm_startup(struct snd_pcm_substream *substream)
if (sgtl5000->master_substream) {
master_runtime = sgtl5000->master_substream->runtime;
- pr_debug("Constraining to %d bits at %dHz\n",
- master_runtime->sample_bits, master_runtime->rate);
-
- snd_pcm_hw_constraint_minmax(substream->runtime,
- SNDRV_PCM_HW_PARAM_RATE,
- master_runtime->rate,
- master_runtime->rate);
+ pr_debug("Constraining to %d bits\n",
+ master_runtime->sample_bits);
snd_pcm_hw_constraint_minmax(substream->runtime,
SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
@@ -565,11 +546,12 @@ static int sgtl5000_pcm_startup(struct snd_pcm_substream *substream)
return 0;
}
-static void sgtl5000_pcm_shutdown(struct snd_pcm_substream *substream)
+static void sgtl5000_pcm_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->codec;
+ struct snd_soc_codec *codec = socdev->card->codec;
struct sgtl5000_priv *sgtl5000 = codec->private_data;
int reg, dig_pwr, ana_pwr;
@@ -609,7 +591,7 @@ static void sgtl5000_pcm_shutdown(struct snd_pcm_substream *substream)
*/
static int sgtl5000_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dia)
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -874,10 +856,10 @@ static int sgtl5000_set_bias_level(struct snd_soc_codec *codec,
SNDRV_PCM_FMTBIT_S24_LE)
struct snd_soc_dai_ops sgtl5000_ops = {
- .shutdown = sgtl5000_pcm_shutdown,
- .hw_params = sgtl5000_pcm_hw_params,
.prepare = sgtl5000_pcm_prepare,
.startup = sgtl5000_pcm_startup,
+ .shutdown = sgtl5000_pcm_shutdown,
+ .hw_params = sgtl5000_pcm_hw_params,
.digital_mute = sgtl5000_digital_mute,
.set_fmt = sgtl5000_set_dai_fmt,
.set_sysclk = sgtl5000_set_dai_sysclk
@@ -899,7 +881,8 @@ struct snd_soc_dai sgtl5000_dai = {
.rates = SGTL5000_RATES,
.formats = SGTL5000_FORMATS,
},
- .ops = &sgtl5000_ops
+ .ops = &sgtl5000_ops,
+ .symmetric_rates = 1,
};
EXPORT_SYMBOL_GPL(sgtl5000_dai);
@@ -917,7 +900,6 @@ static int sgtl5000_resume(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = socdev->card->codec;
-
unsigned int i;
/* Restore refs first in same order as in sgtl5000_init */
@@ -942,56 +924,31 @@ static int sgtl5000_resume(struct platform_device *pdev)
return 0;
}
+static struct snd_soc_codec *sgtl5000_codec;
+
/*
* initialise the SGTL5000 driver
* register the mixer and dsp interfaces with the kernel
*/
-static int sgtl5000_init(struct snd_soc_device *socdev)
+static int sgtl5000_probe(struct platform_device *pdev)
{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct sgtl5000_platform_data *plat = socdev->codec_data;
- struct snd_soc_codec *codec = socdev->card->codec;
- struct i2c_client *client = codec->control_data;
+ struct snd_soc_codec *codec = sgtl5000_codec;
struct sgtl5000_priv *sgtl5000 = codec->private_data;
u16 reg, ana_pwr, lreg_ctrl, ref_ctrl, lo_ctrl, short_ctrl, sss;
int vag;
- unsigned int val;
int ret = 0;
- val = sgtl5000_read(codec, SGTL5000_CHIP_ID);
- if (((val & SGTL5000_PARTID_MASK) >> SGTL5000_PARTID_SHIFT) !=
- SGTL5000_PARTID_PART_ID) {
- pr_err("Device with ID register %x is not a SGTL5000\n", val);
- return -ENODEV;
- }
-
- sgtl5000->rev = (val & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT;
- dev_info(&client->dev, "SGTL5000 revision %d\n", sgtl5000->rev);
-
- codec->name = "SGTL5000";
- codec->owner = THIS_MODULE;
- codec->read = sgtl5000_read_reg_cache;
- codec->write = sgtl5000_write;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = sgtl5000_set_bias_level;
- codec->dai = &sgtl5000_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = sizeof(sgtl5000_regs);
- codec->reg_cache_step = 2;
- codec->reg_cache = (void *)&sgtl5000_regs;
- if (codec->reg_cache == NULL) {
- dev_err(&client->dev, "Failed to allocate register cache\n");
- return -ENOMEM;
- }
+ socdev->card->codec = sgtl5000_codec;
/* register pcms */
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
if (ret < 0) {
- dev_err(&client->dev, "failed to create pcms\n");
+ dev_err(codec->dev, "failed to create pcms\n");
return ret;
}
- sgtl5000_sync_reg_cache(codec);
-
/* reset value */
ana_pwr = SGTL5000_DAC_STEREO |
SGTL5000_LINREG_SIMPLE_POWERUP |
@@ -1056,7 +1013,8 @@ static int sgtl5000_init(struct snd_soc_device *socdev)
ref_ctrl |= SGTL5000_SMALL_POP;
/* Controls the output bias current for the lineout */
- lo_ctrl |= (SGTL5000_LINE_OUT_CURRENT_360u << SGTL5000_LINE_OUT_CURRENT_SHIFT);
+ lo_ctrl |=
+ (SGTL5000_LINE_OUT_CURRENT_360u << SGTL5000_LINE_OUT_CURRENT_SHIFT);
/* set short detect */
/* keep default */
@@ -1108,7 +1066,8 @@ static int sgtl5000_init(struct snd_soc_device *socdev)
sgtl5000_write(codec, SGTL5000_DAP_CTRL, 0);
/* TODO: initialize DAP */
- sgtl5000_add_controls(codec);
+ snd_soc_add_controls(codec, sgtl5000_snd_controls,
+ ARRAY_SIZE(sgtl5000_snd_controls));
sgtl5000_add_widgets(codec);
sgtl5000_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1124,47 +1083,41 @@ static int sgtl5000_init(struct snd_soc_device *socdev)
return 0;
}
-static struct snd_soc_device *sgtl5000_socdev;
-
-static int sgtl5000_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+/* power down chip */
+static int sgtl5000_remove(struct platform_device *pdev)
{
- struct snd_soc_device *socdev = sgtl5000_socdev;
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = socdev->card->codec;
- int ret;
-
- i2c_set_clientdata(i2c, codec);
- codec->control_data = i2c;
- ret = sgtl5000_init(socdev);
- if (ret < 0)
- dev_err(&i2c->dev, "Device initialisation failed\n");
+ if (codec->control_data)
+ sgtl5000_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
- return ret;
+ return 0;
}
-static const struct i2c_device_id sgtl5000_id[] = {
- {"sgtl5000-i2c", 0},
- {},
-};
-
-MODULE_DEVICE_TABLE(i2c, sgtl5000_id);
-
-static struct i2c_driver sgtl5000_i2c_driver = {
- .driver = {
- .name = "sgtl5000-i2c",
- .owner = THIS_MODULE,
- },
- .probe = sgtl5000_i2c_probe,
- .id_table = sgtl5000_id,
+struct snd_soc_codec_device soc_codec_dev_sgtl5000 = {
+ .probe = sgtl5000_probe,
+ .remove = sgtl5000_remove,
+ .suspend = sgtl5000_suspend,
+ .resume = sgtl5000_resume,
};
+EXPORT_SYMBOL_GPL(soc_codec_dev_sgtl5000);
-static int sgtl5000_probe(struct platform_device *pdev)
+static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
struct sgtl5000_priv *sgtl5000;
+ struct snd_soc_codec *codec;
int ret = 0;
+ u32 val;
+
+ if (sgtl5000_codec) {
+ dev_err(&client->dev,
+ "Multiple SGTL5000 devices not supported\n");
+ return -ENOMEM;
+ }
codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
if (codec == NULL)
@@ -1177,46 +1130,97 @@ static int sgtl5000_probe(struct platform_device *pdev)
}
codec->private_data = sgtl5000;
- socdev->card->codec = codec;
mutex_init(&codec->mutex);
INIT_LIST_HEAD(&codec->dapm_widgets);
INIT_LIST_HEAD(&codec->dapm_paths);
- sgtl5000_socdev = socdev;
- ret = i2c_add_driver(&sgtl5000_i2c_driver);
+ i2c_set_clientdata(client, codec);
+ codec->control_data = client;
+
+ val = sgtl5000_read(codec, SGTL5000_CHIP_ID);
+ if (((val & SGTL5000_PARTID_MASK) >> SGTL5000_PARTID_SHIFT) !=
+ SGTL5000_PARTID_PART_ID) {
+ pr_err("Device with ID register %x is not a SGTL5000\n", val);
+ return -ENODEV;
+ }
+
+ sgtl5000->rev = (val & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT;
+ dev_info(&client->dev, "SGTL5000 revision %d\n", sgtl5000->rev);
+
+ codec->dev = &client->dev;
+ codec->name = "SGTL5000";
+ codec->owner = THIS_MODULE;
+ codec->read = sgtl5000_read_reg_cache;
+ codec->write = sgtl5000_write;
+ codec->bias_level = SND_SOC_BIAS_OFF;
+ codec->set_bias_level = sgtl5000_set_bias_level;
+ codec->dai = &sgtl5000_dai;
+ codec->num_dai = 1;
+ codec->reg_cache_size = sizeof(sgtl5000_regs);
+ codec->reg_cache_step = 2;
+ codec->reg_cache = (void *)&sgtl5000_regs;
+
+ sgtl5000_sync_reg_cache(codec);
+
+ sgtl5000_codec = codec;
+ sgtl5000_dai.dev = &client->dev;
+
+ ret = snd_soc_register_codec(codec);
if (ret != 0) {
- dev_err(&pdev->dev, "can't add i2c driver\n");
- kfree(codec->private_data);
- kfree(codec);
+ dev_err(codec->dev, "Failed to register codec: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_register_dai(&sgtl5000_dai);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
+ return ret;
}
return ret;
}
-/* power down chip */
-static int sgtl5000_remove(struct platform_device *pdev)
+static __devexit int sgtl5000_i2c_remove(struct i2c_client *client)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = i2c_get_clientdata(client);
+ struct sgtl5000_priv *sgtl5000 = codec->private_data;
- if (codec->control_data)
- sgtl5000_set_bias_level(codec, SND_SOC_BIAS_OFF);
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
- i2c_del_driver(&sgtl5000_i2c_driver);
- kfree(codec->private_data);
+ snd_soc_unregister_dai(&sgtl5000_dai);
+ snd_soc_unregister_codec(codec);
kfree(codec);
-
+ kfree(sgtl5000);
+ sgtl5000_codec = NULL;
return 0;
}
-struct snd_soc_codec_device soc_codec_dev_sgtl5000 = {
- .probe = sgtl5000_probe,
- .remove = sgtl5000_remove,
- .suspend = sgtl5000_suspend,
- .resume = sgtl5000_resume,
+static const struct i2c_device_id sgtl5000_id[] = {
+ {"sgtl5000-i2c", 0},
+ {},
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_sgtl5000);
+
+MODULE_DEVICE_TABLE(i2c, sgtl5000_id);
+
+static struct i2c_driver sgtl5000_i2c_driver = {
+ .driver = {
+ .name = "sgtl5000-i2c",
+ .owner = THIS_MODULE,
+ },
+ .probe = sgtl5000_i2c_probe,
+ .remove = __devexit_p(sgtl5000_i2c_remove),
+ .id_table = sgtl5000_id,
+};
+
+static int __init sgtl5000_modinit(void)
+{
+ return i2c_add_driver(&sgtl5000_i2c_driver);
+}
+module_init(sgtl5000_modinit);
+
+static void __exit sgtl5000_exit(void)
+{
+ i2c_del_driver(&sgtl5000_i2c_driver);
+}
+module_exit(sgtl5000_exit);
MODULE_DESCRIPTION("ASoC SGTL5000 driver");
MODULE_AUTHOR("Freescale Semiconductor, Inc.");
diff --git a/sound/soc/imx/imx-3stack-sgtl5000.c b/sound/soc/imx/imx-3stack-sgtl5000.c
index 9d44125..5ff90db 100644
--- a/sound/soc/imx/imx-3stack-sgtl5000.c
+++ b/sound/soc/imx/imx-3stack-sgtl5000.c
@@ -29,7 +29,6 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
-#include <sound/soc-dai.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
@@ -75,7 +74,7 @@ struct imx_3stack_priv {
struct regulator *reg_vddd;
};
-static struct imx_3stack_priv machine_priv;
+static struct imx_3stack_priv card_priv;
static int imx_3stack_audio_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
@@ -84,7 +83,7 @@ static int imx_3stack_audio_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai_link *machine = rtd->dai;
struct snd_soc_dai *cpu_dai = machine->cpu_dai;
struct snd_soc_dai *codec_dai = machine->codec_dai;
- struct imx_3stack_priv *priv = &machine_priv;
+ struct imx_3stack_priv *priv = &card_priv;
unsigned int rate = params_rate(params);
int ret = 0;
@@ -105,7 +104,7 @@ static int imx_3stack_audio_hw_params(struct snd_pcm_substream *substream,
substream->runtime->private_data;
struct asrc_config config;
struct mxc_audio_platform_data *plat;
- struct imx_3stack_priv *priv = &machine_priv;
+ struct imx_3stack_priv *priv = &card_priv;
int retVal = 0;
retVal = asrc_req_pair(channel, &asrc_ssi_data.asrc_index);
if (retVal < 0) {
@@ -141,38 +140,24 @@ static int imx_3stack_audio_hw_params(struct snd_pcm_substream *substream,
#if SGTL5000_SSI_MASTER
dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM;
-// if (channels == 2)
-// dai_format |= SND_SOC_DAIFMT_TDM;
-
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, dai_format);
- if (ret < 0)
- return ret;
-
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, dai_format);
- if (ret < 0)
- return ret;
#else
dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS;
-// if (channels == 2)
-// dai_format |= SND_SOC_DAIFMT_TDM;
+#endif
/* set codec DAI configuration */
ret = snd_soc_dai_set_fmt(codec_dai, dai_format);
if (ret < 0)
return ret;
+ /* set i.MX active slot mask */
+ snd_soc_dai_set_tdm_slot(cpu_dai,
+ channels == 1 ? 0xfffffffe : 0xfffffffc, 2);
+
/* set cpu DAI configuration */
ret = snd_soc_dai_set_fmt(cpu_dai, dai_format);
if (ret < 0)
return ret;
-#endif
-
- /* set i.MX active slot mask */
- snd_soc_dai_set_tdm_slot(cpu_dai,
- channels == 1 ? 0xfffffffe : 0xfffffffc, 2);
/* set the SSI system clock as input (unused) */
snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, SND_SOC_CLOCK_IN);
@@ -205,7 +190,7 @@ static int imx_3stack_startup(struct snd_pcm_substream *substream)
static void imx_3stack_shutdown(struct snd_pcm_substream *substream)
{
- struct imx_3stack_priv *priv = &machine_priv;
+ struct imx_3stack_priv *priv = &card_priv;
#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE)
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -306,7 +291,7 @@ static int sgtl5000_spk_func;
static void headphone_detect_handler(struct work_struct *work)
{
- struct imx_3stack_priv *priv = &machine_priv;
+ struct imx_3stack_priv *priv = &card_priv;
struct platform_device *pdev = priv->pdev;
struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
int hp_status;
@@ -331,7 +316,7 @@ static irqreturn_t imx_headphone_detect_handler(int irq, void *data)
static ssize_t show_headphone(struct device_driver *dev, char *buf)
{
- struct imx_3stack_priv *priv = &machine_priv;
+ struct imx_3stack_priv *priv = &card_priv;
struct platform_device *pdev = priv->pdev;
struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
u16 hp_status;
@@ -412,7 +397,7 @@ static int sgtl5000_set_spk(struct snd_kcontrol *kcontrol,
static int spk_amp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
- struct imx_3stack_priv *priv = &machine_priv;
+ struct imx_3stack_priv *priv = &card_priv;
struct platform_device *pdev = priv->pdev;
struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
@@ -427,7 +412,7 @@ static int spk_amp_event(struct snd_soc_dapm_widget *w,
return 0;
}
-/* imx_3stack machine dapm widgets */
+/* imx_3stack card dapm widgets */
static const struct snd_soc_dapm_widget imx_3stack_dapm_widgets[] = {
SND_SOC_DAPM_MIC("Mic Jack", NULL),
SND_SOC_DAPM_LINE("Line In Jack", NULL),
@@ -521,11 +506,12 @@ static struct snd_soc_dai_link imx_3stack_dai = {
.codec_dai = &sgtl5000_dai,
.init = imx_3stack_sgtl5000_init,
.ops = &imx_3stack_ops,
+ .symmetric_rates = 1,
};
-static int imx_3stack_machine_remove(struct platform_device *pdev)
+static int imx_3stack_card_remove(struct platform_device *pdev)
{
- struct imx_3stack_priv *priv = &machine_priv;
+ struct imx_3stack_priv *priv = &card_priv;
struct mxc_audio_platform_data *plat;
if (priv->reg_vddio)
regulator_disable(priv->reg_vddio);
@@ -548,17 +534,16 @@ static int imx_3stack_machine_remove(struct platform_device *pdev)
return 0;
}
-/* imx_3stack audio machine driver */
-static struct snd_soc_card snd_soc_machine_imx_3stack = {
+static struct snd_soc_card snd_soc_card_imx_3stack = {
.name = "imx-3stack",
.platform = &imx_soc_platform,
.dai_link = &imx_3stack_dai,
.num_links = 1,
- .remove = imx_3stack_machine_remove,
+ .remove = imx_3stack_card_remove,
};
static struct snd_soc_device imx_3stack_snd_devdata = {
- .card = &snd_soc_machine_imx_3stack,
+ .card = &snd_soc_card_imx_3stack,
.codec_dev = &soc_codec_dev_sgtl5000,
};
@@ -566,13 +551,15 @@ static int __devinit imx_3stack_sgtl5000_probe(struct platform_device *pdev)
{
struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
struct regulator *reg;
- struct imx_3stack_priv *priv = &machine_priv;
+ struct imx_3stack_priv *priv = &card_priv;
struct sgtl5000_platform_data *codec_data;
int ret = 0;
priv->sysclk = plat->sysclk;
priv->pdev = pdev;
+
imx_ssi_dai.private_data = plat;
+ imx_ssi_dai.dev = &pdev->dev;
codec_data = kzalloc(sizeof(struct sgtl5000_platform_data), GFP_KERNEL);
if (!codec_data) {
@@ -592,6 +579,9 @@ static int __devinit imx_3stack_sgtl5000_probe(struct platform_device *pdev)
else
imx_ssi_dai.name = "imx-ssi-1";
+ imx_ssi_dai.symmetric_rates = 1;
+ snd_soc_register_dai(&imx_ssi_dai);
+
ret = driver_create_file(pdev->dev.driver, &driver_attr_headphone);
if (ret < 0) {
pr_err("%s:failed to create driver_attr_headphone\n", __func__);
@@ -681,7 +671,7 @@ err_codec_data:
static int imx_3stack_sgtl5000_remove(struct platform_device *pdev)
{
struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
- struct imx_3stack_priv *priv = &machine_priv;
+ struct imx_3stack_priv *priv = &card_priv;
free_irq(plat->hp_irq, priv);
diff --git a/sound/soc/imx/imx-pcm.c b/sound/soc/imx/imx-pcm.c
index a173367..bcfc59a 100644
--- a/sound/soc/imx/imx-pcm.c
+++ b/sound/soc/imx/imx-pcm.c
@@ -102,7 +102,7 @@ static int imx_iram_audio_playback_mmap(struct snd_pcm_substream *substream,
if (off + size > SND_RAM_SIZE)
return -EINVAL;
- area->vm_page_prot = pgprot_nonshareddev(area->vm_page_prot);
+ area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
area->vm_flags |= VM_IO;
ret =
remap_pfn_range(area, area->vm_start, phys >> PAGE_SHIFT,
@@ -681,9 +681,20 @@ struct snd_soc_platform imx_soc_platform = {
.pcm_new = imx_pcm_new,
.pcm_free = imx_pcm_free_dma_buffers,
};
-
EXPORT_SYMBOL_GPL(imx_soc_platform);
+static int __init imx_pcm_init(void)
+{
+ return snd_soc_register_platform(&imx_soc_platform);
+}
+module_init(imx_pcm_init);
+
+static void __exit imx_pcm_exit(void)
+{
+ snd_soc_unregister_platform(&imx_soc_platform);
+}
+module_exit(imx_pcm_exit);
+
MODULE_AUTHOR("Liam Girdwood");
MODULE_DESCRIPTION("Freescale i.MX3x PCM DMA module");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c
index 91b5019..2dba33b 100644
--- a/sound/soc/imx/imx-ssi.c
+++ b/sound/soc/imx/imx-ssi.c
@@ -39,6 +39,13 @@
#include "imx-ssi.h"
#include "imx-pcm.h"
+/* private info */
+struct imx_ssi {
+ bool network_mode;
+};
+
+static struct imx_ssi imx_ssi_data[IMX_DAI_SSI3];
+
/* debug */
#define IMX_SSI_DEBUG 0
#if IMX_SSI_DEBUG
@@ -187,8 +194,11 @@ static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
unsigned int mask, int slots)
{
+ bool network_mode = (!(mask & 0x2));
u32 stmsk, srmsk, stccr;
+ imx_ssi_data[cpu_dai->id].network_mode = network_mode;
+
if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI1) {
if (__raw_readl(SSI1_SCR) & SSI_SCR_SSIEN)
return 0;
@@ -226,8 +236,12 @@ static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
*/
static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
{
+ bool sync_mode = cpu_dai->symmetric_rates;
+ bool network_mode;
u32 stcr = 0, srcr = 0, scr;
+ network_mode = imx_ssi_data[cpu_dai->id].network_mode;
+
if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI1)
scr = __raw_readl(SSI1_SCR) & ~(SSI_SCR_SYN | SSI_SCR_NET);
else
@@ -288,11 +302,11 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
stcr |= SSI_STCR_TFDIR | SSI_STCR_TXDIR;
-// if (((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S)
-// && (fmt & SND_SOC_DAIFMT_TDM)) {
-// scr &= ~SSI_SCR_I2S_MODE_MASK;
-// scr |= SSI_SCR_I2S_MODE_MSTR;
-// }
+ if (((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S)
+ && network_mode) {
+ scr &= ~SSI_SCR_I2S_MODE_MASK;
+ scr |= SSI_SCR_I2S_MODE_MSTR;
+ }
break;
case SND_SOC_DAIFMT_CBM_CFS:
stcr |= SSI_STCR_TFDIR;
@@ -303,21 +317,21 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
srcr |= SSI_SRCR_RXDIR;
break;
case SND_SOC_DAIFMT_CBM_CFM:
-// if (((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S)
-// && (fmt & SND_SOC_DAIFMT_TDM)) {
-// scr &= ~SSI_SCR_I2S_MODE_MASK;
-// scr |= SSI_SCR_I2S_MODE_SLAVE;
-// }
+ if (((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S)
+ && network_mode) {
+ scr &= ~SSI_SCR_I2S_MODE_MASK;
+ scr |= SSI_SCR_I2S_MODE_SLAVE;
+ }
break;
}
/* sync */
-// if (!(fmt & SND_SOC_DAIFMT_ASYNC))
-// scr |= SSI_SCR_SYN;
+ if (sync_mode)
+ scr |= SSI_SCR_SYN;
/* tdm - only for stereo atm */
-// if (fmt & SND_SOC_DAIFMT_TDM)
-// scr |= SSI_SCR_NET;
+ if (network_mode)
+ scr |= SSI_SCR_NET;
if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI1) {
__raw_writel(stcr, SSI1_STCR);
@@ -336,11 +350,8 @@ static struct clk *ssi1_clk;
static struct clk *ssi2_clk;
static int imx_ssi_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+ struct snd_soc_dai *cpu_dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
-
/* we cant really change any SSI values after SSI is enabled
* need to fix in software for max flexibility - lrg */
if (cpu_dai->playback.active || cpu_dai->capture.active)
@@ -388,10 +399,9 @@ static int imx_ssi_startup(struct snd_pcm_substream *substream,
}
static int imx_ssi_hw_tx_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *cpu_dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
u32 stccr, stcr, sier;
if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI1) {
@@ -438,24 +448,19 @@ static int imx_ssi_hw_tx_params(struct snd_pcm_substream *substream,
}
static int imx_ssi_hw_rx_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *cpu_dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ bool sync_mode = cpu_dai->symmetric_rates;
u32 srccr, srcr, sier;
- bool sync_mode;
if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI1) {
- sync_mode =
- (__raw_readl(SSI1_SCR) & SSI_SCR_SYN) ? true : false;
srccr =
sync_mode ? __raw_readl(SSI1_STCCR) :
__raw_readl(SSI1_SRCCR);
srcr = __raw_readl(SSI1_SRCR);
sier = __raw_readl(SSI1_SIER);
} else {
- sync_mode =
- (__raw_readl(SSI2_SCR) & SSI_SCR_SYN) ? true : false;
srccr =
sync_mode ? __raw_readl(SSI2_STCCR) :
__raw_readl(SSI2_SRCCR);
@@ -507,11 +512,9 @@ static int imx_ssi_hw_rx_params(struct snd_pcm_substream *substream,
* although can be called multiple times by upper layers.
*/
static int imx_ssi_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *da)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *cpu_dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
int id;
id = cpu_dai->id;
@@ -528,7 +531,7 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream,
(__raw_readl(SSI2_SCR) & SSI_SCR_TE))
return 0;
}
- return imx_ssi_hw_tx_params(substream, params);
+ return imx_ssi_hw_tx_params(substream, params, cpu_dai);
} else {
/* cant change any parameters when SSI is running */
if (id == IMX_DAI_SSI0 || id == IMX_DAI_SSI1) {
@@ -540,15 +543,13 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream,
(__raw_readl(SSI2_SCR) & SSI_SCR_RE))
return 0;
}
- return imx_ssi_hw_rx_params(substream, params);
+ return imx_ssi_hw_rx_params(substream, params, cpu_dai);
}
}
static int imx_ssi_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *da)
+ struct snd_soc_dai *cpu_dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
u32 scr;
/* enable the SSI port, note that no other port config
@@ -565,10 +566,8 @@ static int imx_ssi_prepare(struct snd_pcm_substream *substream,
}
static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *da)
+ struct snd_soc_dai *cpu_dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
u32 scr;
if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI1)
@@ -613,10 +612,8 @@ static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
}
static void imx_ssi_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *da)
+ struct snd_soc_dai *cpu_dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
int id;
id = cpu_dai->id;
@@ -748,7 +745,7 @@ static void imx_ssi_remove(struct platform_device *pdev,
(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE)
-struct snd_soc_dai_ops imx_ssi_dai_ops = {
+static struct snd_soc_dai_ops imx_ssi_dai_ops = {
.startup = imx_ssi_startup,
.shutdown = imx_ssi_shutdown,
.trigger = imx_ssi_trigger,
--
1.6.3.3
More information about the kernel-team
mailing list