From 0939ce9bc0edd7d84550f4bae799e61ce9b61a23 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Sat, 3 Oct 2009 21:42:01 -0500 Subject: [PATCH] sgtl5000 audio: more porting to 2.6.31 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 #include #include -#include #include #include @@ -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.0.4