diff options
author | Alan Tull <r80115@freescale.com> | 2009-11-02 19:44:22 -0600 |
---|---|---|
committer | Justin Waters <justin.waters@timesys.com> | 2010-03-25 14:00:36 -0400 |
commit | 1c53f69ce6c7f55be73c2ba24124444c1b3ab975 (patch) | |
tree | 29f2ef3da1bb4122f76e0a05ab68ca831564dfa3 /sound | |
parent | c138b856371156516cd0b742ae40f34dc18b5154 (diff) |
ENGR00118016-1 ASoC : upgrade audio support to 2.6.31
Move regulator control into codec drivers.
Move codec platform data to machine layer.
Remove unused fields from mxc_audio_platform_data.
soc multiple audio cards support:
dai_list is a list for all registered codec/cpu dais.
One codec/cpu dais can't be registered twice, so move the
cpu dai registering into imx-ssi.c/imx-esai.c
Fix ak4647_read_reg error.
Put ssi/esai mode in the cpu_dai private_data.
sgtl5000: Fix the power for MX35
1. MX35 vddio and vddd are directly connected to
external 3V3. It has no regulator control.
2. sgtl5000 needs some time to be ready after vdda
is switched on so msleep(1) is added before regiter
read/write.
3. On MX35 platform, vdda is from VCAM.
Signed-off-by: Alan Tull <r80115@freescale.com>
Signed-off-by: Wallace Wang <r59996@freescale.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/ak4647.c | 4 | ||||
-rw-r--r-- | sound/soc/codecs/bluetooth.c | 14 | ||||
-rw-r--r-- | sound/soc/codecs/sgtl5000.c | 93 | ||||
-rw-r--r-- | sound/soc/codecs/sgtl5000.h | 6 | ||||
-rw-r--r-- | sound/soc/imx/imx-3stack-ak4647.c | 17 | ||||
-rw-r--r-- | sound/soc/imx/imx-3stack-ak5702.c | 7 | ||||
-rw-r--r-- | sound/soc/imx/imx-3stack-bt.c | 19 | ||||
-rw-r--r-- | sound/soc/imx/imx-3stack-sgtl5000.c | 98 | ||||
-rw-r--r-- | sound/soc/imx/imx-3stack-wm8350.c | 77 | ||||
-rw-r--r-- | sound/soc/imx/imx-3stack-wm8580.c | 7 | ||||
-rw-r--r-- | sound/soc/imx/imx-esai.c | 131 | ||||
-rw-r--r-- | sound/soc/imx/imx-esai.h | 7 | ||||
-rw-r--r-- | sound/soc/imx/imx-ssi.c | 167 | ||||
-rw-r--r-- | sound/soc/imx/imx-ssi.h | 8 |
14 files changed, 396 insertions, 259 deletions
diff --git a/sound/soc/codecs/ak4647.c b/sound/soc/codecs/ak4647.c index 46e2e8cbcacc..c3d14e99be0e 100644 --- a/sound/soc/codecs/ak4647.c +++ b/sound/soc/codecs/ak4647.c @@ -45,9 +45,9 @@ int ak4647_read_reg(unsigned int reg, u8 *value) { s32 retval; retval = i2c_smbus_read_byte_data(ak4647_i2c_client, reg); - if (-1 == retval) { + if (retval < 0) { pr_err("%s:read reg errorr:reg=%x,val=%x\n", - __func__, reg, *value); + __func__, reg, retval); return -1; } else { *value = (u8) retval; diff --git a/sound/soc/codecs/bluetooth.c b/sound/soc/codecs/bluetooth.c index ee6c49f67280..2d4c13b4f0af 100644 --- a/sound/soc/codecs/bluetooth.c +++ b/sound/soc/codecs/bluetooth.c @@ -142,6 +142,20 @@ struct snd_soc_codec_device soc_codec_dev_bt = { }; EXPORT_SYMBOL_GPL(soc_codec_dev_bt); +static int __init bluetooth_modinit(void) +{ + return snd_soc_register_dai(&bt_dai); +} + +module_init(bluetooth_modinit); + +static void __exit bluetooth_exit(void) +{ + snd_soc_unregister_dai(&bt_dai); +} + +module_exit(bluetooth_exit); + MODULE_DESCRIPTION("ASoC bluetooth codec driver"); MODULE_AUTHOR("Freescale Semiconductor, Inc."); MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 3d754dea05ba..9cc8756ccccd 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -15,13 +15,14 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/platform_device.h> -#include <mach/hardware.h> +#include <linux/regulator/consumer.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h> #include <sound/soc-dapm.h> #include <sound/initval.h> +#include <mach/hardware.h> #include "sgtl5000.h" @@ -34,6 +35,12 @@ struct sgtl5000_priv { int capture_channels; int playback_active; int capture_active; + struct regulator *reg_vddio; + struct regulator *reg_vdda; + struct regulator *reg_vddd; + int vddio; /* voltage of VDDIO (mv) */ + int vdda; /* voltage of vdda (mv) */ + int vddd; /* voltage of vddd (mv), 0 if not connected */ struct snd_pcm_substream *master_substream; struct snd_pcm_substream *slave_substream; }; @@ -933,7 +940,6 @@ static struct snd_soc_codec *sgtl5000_codec; 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 = sgtl5000_codec; struct sgtl5000_priv *sgtl5000 = codec->private_data; u16 reg, ana_pwr, lreg_ctrl, ref_ctrl, lo_ctrl, short_ctrl, sss; @@ -961,7 +967,7 @@ static int sgtl5000_probe(struct platform_device *pdev) sss = SGTL5000_DAC_SEL_I2S_IN << SGTL5000_DAC_SEL_SHIFT; /* workaround for rev 0x11: use vddd linear regulator */ - if (!plat->vddd || (sgtl5000->rev >= 0x11)) { + if (!sgtl5000->vddd || (sgtl5000->rev >= 0x11)) { /* set VDDD to 1.2v */ lreg_ctrl |= 0x8 << SGTL5000_LINREG_VDDD_SHIFT; /* power internal linear regulator */ @@ -971,14 +977,14 @@ static int sgtl5000_probe(struct platform_device *pdev) ana_pwr &= ~SGTL5000_STARTUP_POWERUP; ana_pwr &= ~SGTL5000_LINREG_SIMPLE_POWERUP; } - if (plat->vddio < 3100 && plat->vdda < 3100) { + if (sgtl5000->vddio < 3100 && sgtl5000->vdda < 3100) { /* Enable VDDC charge pump */ ana_pwr |= SGTL5000_VDDC_CHRGPMP_POWERUP; } - if (plat->vddio >= 3100 && plat->vdda >= 3100) { + if (sgtl5000->vddio >= 3100 && sgtl5000->vdda >= 3100) { /* VDDC use VDDIO rail */ lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD; - if (plat->vddio >= 3100) + if (sgtl5000->vddio >= 3100) lreg_ctrl |= SGTL5000_VDDC_MAN_ASSN_VDDIO << SGTL5000_VDDC_MAN_ASSN_SHIFT; } @@ -987,7 +993,7 @@ static int sgtl5000_probe(struct platform_device *pdev) ana_pwr |= reg & (SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP); /* set ADC/DAC ref voltage to vdda/2 */ - vag = plat->vdda / 2; + vag = sgtl5000->vdda / 2; if (vag <= SGTL5000_ANA_GND_BASE) vag = 0; else if (vag >= SGTL5000_ANA_GND_BASE + SGTL5000_ANA_GND_STP * @@ -998,7 +1004,7 @@ static int sgtl5000_probe(struct platform_device *pdev) ref_ctrl |= vag << SGTL5000_ANA_GND_SHIFT; /* set line out ref voltage to vddio/2 */ - vag = plat->vddio / 2; + vag = sgtl5000->vddio / 2; if (vag <= SGTL5000_LINE_OUT_GND_BASE) vag = 0; else if (vag >= SGTL5000_LINE_OUT_GND_BASE + SGTL5000_LINE_OUT_GND_STP * @@ -1110,6 +1116,7 @@ static __devinit int sgtl5000_i2c_probe(struct i2c_client *client, { struct sgtl5000_priv *sgtl5000; struct snd_soc_codec *codec; + struct regulator *reg; int ret = 0; u32 val; @@ -1137,11 +1144,44 @@ static __devinit int sgtl5000_i2c_probe(struct i2c_client *client, i2c_set_clientdata(client, codec); codec->control_data = client; + reg = regulator_get(&client->dev, "VDDIO"); + if (!IS_ERR(reg)) + sgtl5000->reg_vddio = reg; + + reg = regulator_get(&client->dev, "VDDA"); + if (!IS_ERR(reg)) + sgtl5000->reg_vdda = reg; + + reg = regulator_get(&client->dev, "VDDD"); + if (!IS_ERR(reg)) + sgtl5000->reg_vddd = reg; + + if (sgtl5000->reg_vdda) { + sgtl5000->vdda = + regulator_get_voltage(sgtl5000->reg_vdda) / 1000; + regulator_enable(sgtl5000->reg_vdda); + } + if (sgtl5000->reg_vddio) { + sgtl5000->vddio = + regulator_get_voltage(sgtl5000->reg_vddio) / 1000; + regulator_enable(sgtl5000->reg_vddio); + } + if (sgtl5000->reg_vddd) { + sgtl5000->vddd = + regulator_get_voltage(sgtl5000->reg_vddd) / 1000; + regulator_enable(sgtl5000->reg_vddd); + } else { + sgtl5000->vddd = 0; /* use internal regulator */ + } + + msleep(1); + 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; + ret = -ENODEV; + goto err_codec_reg; } sgtl5000->rev = (val & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT; @@ -1168,15 +1208,32 @@ static __devinit int sgtl5000_i2c_probe(struct i2c_client *client, ret = snd_soc_register_codec(codec); if (ret != 0) { dev_err(codec->dev, "Failed to register codec: %d\n", ret); - return ret; + goto err_codec_reg; } ret = snd_soc_register_dai(&sgtl5000_dai); if (ret != 0) { dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); - return ret; + goto err_codec_reg; } + return 0; + +err_codec_reg: + if (sgtl5000->reg_vddd) + regulator_disable(sgtl5000->reg_vddd); + if (sgtl5000->reg_vdda) + regulator_disable(sgtl5000->reg_vdda); + if (sgtl5000->reg_vddio) + regulator_disable(sgtl5000->reg_vddio); + if (sgtl5000->reg_vddd) + regulator_put(sgtl5000->reg_vddd); + if (sgtl5000->reg_vdda) + regulator_put(sgtl5000->reg_vdda); + if (sgtl5000->reg_vddio) + regulator_put(sgtl5000->reg_vddio); + kfree(sgtl5000); + kfree(codec); return ret; } @@ -1187,6 +1244,20 @@ static __devexit int sgtl5000_i2c_remove(struct i2c_client *client) snd_soc_unregister_dai(&sgtl5000_dai); snd_soc_unregister_codec(codec); + + if (sgtl5000->reg_vddio) { + regulator_disable(sgtl5000->reg_vddio); + regulator_put(sgtl5000->reg_vddio); + } + if (sgtl5000->reg_vddd) { + regulator_disable(sgtl5000->reg_vddd); + regulator_put(sgtl5000->reg_vddd); + } + if (sgtl5000->reg_vdda) { + regulator_disable(sgtl5000->reg_vdda); + regulator_put(sgtl5000->reg_vdda); + } + kfree(codec); kfree(sgtl5000); sgtl5000_codec = NULL; diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h index 177be05b486c..e37b124f67dd 100644 --- a/sound/soc/codecs/sgtl5000.h +++ b/sound/soc/codecs/sgtl5000.h @@ -396,10 +396,4 @@ extern struct snd_soc_codec_device soc_codec_dev_sgtl5000; #define SGTL5000_SYSCLK 0x00 #define SGTL5000_LRCLK 0x01 -struct sgtl5000_platform_data { - int vddio; /* voltage of VDDIO (mv) */ - int vdda; /* voltage of vdda (mv) */ - int vddd; /* voltage of vddd (mv), 0 if not connected */ -}; - #endif diff --git a/sound/soc/imx/imx-3stack-ak4647.c b/sound/soc/imx/imx-3stack-ak4647.c index ed97f8130ec6..bb3606c57fd4 100644 --- a/sound/soc/imx/imx-3stack-ak4647.c +++ b/sound/soc/imx/imx-3stack-ak4647.c @@ -106,6 +106,7 @@ static int imx_3stack_hifi_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai = pcm_link->codec_dai; unsigned int channels = params_channels(params); unsigned int rate = params_rate(params); + struct imx_ssi *ssi_mode = (struct imx_ssi *)cpu_dai->private_data; int ret = 0; u32 dai_format; @@ -117,6 +118,12 @@ static int imx_3stack_hifi_hw_params(struct snd_pcm_substream *substream, SND_SOC_DAIFMT_CBS_CFS; #endif + ssi_mode->sync_mode = 1; + if (channels == 1) + ssi_mode->network_mode = 0; + else + ssi_mode->network_mode = 1; + /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, dai_format); if (ret < 0) @@ -318,7 +325,6 @@ static int imx_3stack_ak4647_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link imx_3stack_dai = { .name = "ak4647", .stream_name = "ak4647", - .cpu_dai = &imx_ssi_dai, .codec_dai = &ak4647_hifi_dai, .init = imx_3stack_ak4647_init, .ops = &imx_3stack_hifi_ops, @@ -345,18 +351,17 @@ static int __init imx_3stack_ak4647_probe(struct platform_device *pdev) { struct mxc_audio_platform_data *dev_data = pdev->dev.platform_data; struct imx_3stack_priv *priv = &card_priv; + struct snd_soc_dai *ak4647_cpu_dai; int ret = 0; dev_data->init(); if (dev_data->src_port == 1) - imx_ssi_dai.name = "imx-ssi-1"; + ak4647_cpu_dai = &imx_ssi_dai[0]; else - imx_ssi_dai.name = "imx-ssi-3"; + ak4647_cpu_dai = &imx_ssi_dai[2]; - imx_ssi_dai.dev = &pdev->dev; - imx_ssi_dai.symmetric_rates = 1; - snd_soc_register_dai(&imx_ssi_dai); + imx_3stack_dai.cpu_dai = ak4647_cpu_dai; /* Configure audio port 3 */ gpio_activate_audio_ports(); diff --git a/sound/soc/imx/imx-3stack-ak5702.c b/sound/soc/imx/imx-3stack-ak5702.c index a13a57ab671a..7603c0f0ae19 100644 --- a/sound/soc/imx/imx-3stack-ak5702.c +++ b/sound/soc/imx/imx-3stack-ak5702.c @@ -65,6 +65,7 @@ static int imx_3stack_surround_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai = pcm_link->cpu_dai; struct snd_soc_dai *codec_dai = pcm_link->codec_dai; unsigned int rate = params_rate(params); + struct imx_esai *esai_mode = (struct imx_esai *)cpu_dai->private_data; u32 dai_format; if (clk_state.lr_clk_active > 1) @@ -73,6 +74,9 @@ static int imx_3stack_surround_hw_params(struct snd_pcm_substream *substream, dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; + esai_mode->sync_mode = 0; + esai_mode->network_mode = 1; + /* set codec DAI configuration */ snd_soc_dai_set_fmt(codec_dai, dai_format); @@ -130,7 +134,6 @@ static int imx_3stack_ak5702_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link imx_3stack_dai = { .name = "ak5702", .stream_name = "ak5702", - .cpu_dai = &imx_esai_dai, .codec_dai = &ak5702_dai, .init = imx_3stack_ak5702_init, .ops = &imx_3stack_surround_ops, @@ -161,7 +164,7 @@ static int __devinit imx_3stack_ak5702_probe(struct platform_device *pdev) { struct ak5702_setup_data *setup; - imx_esai_dai.name = "imx-esai-txrx"; + imx_3stack_dai.cpu_dai = &imx_esai_dai[2]; setup = kzalloc(sizeof(struct ak5702_setup_data), GFP_KERNEL); setup->i2c_bus = 1; diff --git a/sound/soc/imx/imx-3stack-bt.c b/sound/soc/imx/imx-3stack-bt.c index ca0679797df8..28d47eeba62d 100644 --- a/sound/soc/imx/imx-3stack-bt.c +++ b/sound/soc/imx/imx-3stack-bt.c @@ -105,6 +105,7 @@ static int imx_3stack_bt_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai_link *pcm_link = rtd->dai; struct snd_soc_dai *cpu_dai = pcm_link->cpu_dai; unsigned int channels = params_channels(params); + struct imx_ssi *ssi_mode = (struct imx_ssi *)cpu_dai->private_data; int ret = 0; u32 dai_format; @@ -116,6 +117,12 @@ static int imx_3stack_bt_hw_params(struct snd_pcm_substream *substream, SND_SOC_DAIFMT_CBS_CFS; #endif + ssi_mode->sync_mode = 1; + if (channels == 1) + ssi_mode->network_mode = 0; + else + ssi_mode->network_mode = 1; + /* set i.MX active slot mask */ snd_soc_dai_set_tdm_slot(cpu_dai, channels == 1 ? 0xfffffffe : 0xfffffffc, 2); @@ -152,7 +159,6 @@ static struct snd_soc_ops imx_3stack_bt_ops = { static struct snd_soc_dai_link imx_3stack_dai = { .name = "bluetooth", .stream_name = "bluetooth", - .cpu_dai = &imx_ssi_dai, .codec_dai = &bt_dai, .ops = &imx_3stack_bt_ops, }; @@ -178,17 +184,14 @@ static int __init imx_3stack_bt_probe(struct platform_device *pdev) { struct mxc_audio_platform_data *dev_data = pdev->dev.platform_data; struct imx_3stack_priv *priv = &card_priv; - - /* imx_3stack bt interface */ - imx_ssi_dai.private_data = dev_data; - imx_ssi_dai.dev = &pdev->dev; + struct snd_soc_dai *bt_cpu_dai; if (dev_data->src_port == 1) - imx_ssi_dai.name = "imx-ssi-1"; + bt_cpu_dai = &imx_ssi_dai[0]; else - imx_ssi_dai.name = "imx-ssi-3"; + bt_cpu_dai = &imx_ssi_dai[2]; - snd_soc_register_dai(&imx_ssi_dai); + imx_3stack_dai.cpu_dai = bt_cpu_dai; /* Configure audio port */ imx_3stack_init_dam(dev_data->src_port, dev_data->ext_port); diff --git a/sound/soc/imx/imx-3stack-sgtl5000.c b/sound/soc/imx/imx-3stack-sgtl5000.c index 9dc060b52301..fed97f9c2655 100644 --- a/sound/soc/imx/imx-3stack-sgtl5000.c +++ b/sound/soc/imx/imx-3stack-sgtl5000.c @@ -20,7 +20,6 @@ #include <linux/pm.h> #include <linux/bitops.h> #include <linux/platform_device.h> -#include <linux/regulator/consumer.h> #include <linux/i2c.h> #include <linux/err.h> #include <linux/irq.h> @@ -68,9 +67,6 @@ struct imx_3stack_priv { int sysclk; int hw; struct platform_device *pdev; - struct regulator *reg_vddio; - struct regulator *reg_vdda; - struct regulator *reg_vddd; }; static struct imx_3stack_priv card_priv; @@ -84,6 +80,7 @@ static int imx_3stack_audio_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai = machine->codec_dai; struct imx_3stack_priv *priv = &card_priv; unsigned int rate = params_rate(params); + struct imx_ssi *ssi_mode = (struct imx_ssi *)cpu_dai->private_data; int ret = 0; unsigned int channels = params_channels(params); @@ -144,6 +141,12 @@ static int imx_3stack_audio_hw_params(struct snd_pcm_substream *substream, SND_SOC_DAIFMT_CBS_CFS; #endif + ssi_mode->sync_mode = 1; + if (channels == 1) + ssi_mode->network_mode = 0; + else + ssi_mode->network_mode = 1; + /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, dai_format); if (ret < 0) @@ -532,29 +535,15 @@ static int imx_3stack_sgtl5000_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link imx_3stack_dai = { .name = "SGTL5000", .stream_name = "SGTL5000", - .cpu_dai = &imx_ssi_dai, .codec_dai = &sgtl5000_dai, .init = imx_3stack_sgtl5000_init, .ops = &imx_3stack_ops, - .symmetric_rates = 1, }; static int imx_3stack_card_remove(struct platform_device *pdev) { struct imx_3stack_priv *priv = &card_priv; struct mxc_audio_platform_data *plat; - if (priv->reg_vddio) - regulator_disable(priv->reg_vddio); - if (priv->reg_vddd) - regulator_disable(priv->reg_vddd); - if (priv->reg_vdda) - regulator_disable(priv->reg_vdda); - if (priv->reg_vdda) - regulator_put(priv->reg_vdda); - if (priv->reg_vddio) - regulator_put(priv->reg_vddio); - if (priv->reg_vddd) - regulator_put(priv->reg_vddd); if (priv->pdev) { plat = priv->pdev->dev.platform_data; if (plat->finit) @@ -581,36 +570,21 @@ static int __devinit imx_3stack_sgtl5000_probe(struct platform_device *pdev) { struct mxc_audio_platform_data *plat = pdev->dev.platform_data; struct imx_3stack_priv *priv = &card_priv; - struct sgtl5000_platform_data *codec_data; - struct regulator *reg; + struct snd_soc_dai *sgtl5000_cpu_dai; 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) { - ret = -ENOMEM; - goto err_codec_data; - } - codec_data->vddio = plat->vddio / 1000; /* uV to mV */ - codec_data->vdda = plat->vdda / 1000; - codec_data->vddd = plat->vddd / 1000; - imx_3stack_snd_devdata.codec_data = codec_data; - gpio_activate_audio_ports(); imx_3stack_init_dam(plat->src_port, plat->ext_port); if (plat->src_port == 2) - imx_ssi_dai.name = "imx-ssi-3"; + sgtl5000_cpu_dai = &imx_ssi_dai[2]; else - imx_ssi_dai.name = "imx-ssi-1"; + sgtl5000_cpu_dai = &imx_ssi_dai[0]; - imx_ssi_dai.symmetric_rates = 1; - snd_soc_register_dai(&imx_ssi_dai); + imx_3stack_dai.cpu_dai = sgtl5000_cpu_dai; ret = driver_create_file(pdev->dev.driver, &driver_attr_headphone); if (ret < 0) { @@ -621,44 +595,10 @@ static int __devinit imx_3stack_sgtl5000_probe(struct platform_device *pdev) ret = -EINVAL; if (plat->init && plat->init()) goto err_plat_init; - if (plat->vddio_reg) { - reg = regulator_get(&pdev->dev, plat->vddio_reg); - if (IS_ERR(reg)) - goto err_reg_vddio; - priv->reg_vddio = reg; - } - if (plat->vdda_reg) { - reg = regulator_get(&pdev->dev, plat->vdda_reg); - if (IS_ERR(reg)) - goto err_reg_vdda; - priv->reg_vdda = reg; - } - if (plat->vddd_reg) { - reg = regulator_get(&pdev->dev, plat->vddd_reg); - if (IS_ERR(reg)) - goto err_reg_vddd; - priv->reg_vddd = reg; - } - - if (priv->reg_vdda) { - ret = regulator_set_voltage(priv->reg_vdda, - plat->vdda, plat->vdda); - regulator_enable(priv->reg_vdda); - } - if (priv->reg_vddio) { - regulator_set_voltage(priv->reg_vddio, - plat->vddio, plat->vddio); - regulator_enable(priv->reg_vddio); - } - if (priv->reg_vddd) { - regulator_set_voltage(priv->reg_vddd, plat->vddd, plat->vddd); - regulator_enable(priv->reg_vddd); - } /* The SGTL5000 has an internal reset that is deasserted 8 SYS_MCLK cycles after all power rails have been brought up. After this time communication can start */ - msleep(1); if (plat->hp_status()) ret = request_irq(plat->hp_irq, @@ -680,22 +620,11 @@ static int __devinit imx_3stack_sgtl5000_probe(struct platform_device *pdev) return 0; err_card_reg: - if (priv->reg_vddd) - regulator_put(priv->reg_vddd); -err_reg_vddd: - if (priv->reg_vdda) - regulator_put(priv->reg_vdda); -err_reg_vdda: - if (priv->reg_vddio) - regulator_put(priv->reg_vddio); -err_reg_vddio: if (plat->finit) plat->finit(); err_plat_init: driver_remove_file(pdev->dev.driver, &driver_attr_headphone); sysfs_err: - kfree(codec_data); -err_codec_data: return ret; } @@ -706,9 +635,10 @@ static int imx_3stack_sgtl5000_remove(struct platform_device *pdev) free_irq(plat->hp_irq, priv); - driver_remove_file(pdev->dev.driver, &driver_attr_headphone); + if (plat->finit) + plat->finit(); - kfree(imx_3stack_snd_devdata.codec_data); + driver_remove_file(pdev->dev.driver, &driver_attr_headphone); return 0; } diff --git a/sound/soc/imx/imx-3stack-wm8350.c b/sound/soc/imx/imx-3stack-wm8350.c index e51cd907563b..fb1c0191f4ab 100644 --- a/sound/soc/imx/imx-3stack-wm8350.c +++ b/sound/soc/imx/imx-3stack-wm8350.c @@ -169,8 +169,8 @@ static int imx_3stack_audio_hw_params(struct snd_pcm_substream *substream, snd_pcm_format_t format = params_format(params); unsigned int rate = params_rate(params); unsigned int channels = params_channels(params); + struct imx_ssi *ssi_mode = (struct imx_ssi *)cpu_dai->private_data; u32 dai_format; - int clk_id; /* only need to do this once as capture and playback are sync */ if (priv->lr_clk_active > 1) @@ -193,10 +193,26 @@ static int imx_3stack_audio_hw_params(struct snd_pcm_substream *substream, #if WM8350_SSI_MASTER /* codec FLL input is 32768 kHz from MCLK */ snd_soc_dai_set_pll(codec_dai, 0, 32768, wm8350_audio[i].sysclk); +#else + /* codec FLL input is rate from DAC LRC */ + snd_soc_dai_set_pll(codec_dai, 0, rate, wm8350_audio[i].sysclk); +#endif +#if WM8350_SSI_MASTER dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; + ssi_mode->sync_mode = 1; + if (channels == 1) + ssi_mode->network_mode = 0; + else + ssi_mode->network_mode = 1; + + /* set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, dai_format); + if (ret < 0) + return ret; + /* set cpu DAI configuration */ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { dai_format &= ~SND_SOC_DAIFMT_INV_MASK; @@ -204,19 +220,22 @@ static int imx_3stack_audio_hw_params(struct snd_pcm_substream *substream, dai_format |= SND_SOC_DAIFMT_NB_IF; } + /* set i.MX active slot mask */ + snd_soc_dai_set_tdm_slot(cpu_dai, + channels == 1 ? 0xfffffffe : 0xfffffffc, + channels); + + ret = snd_soc_dai_set_fmt(cpu_dai, dai_format); + if (ret < 0) + return ret; + /* set 32KHZ as the codec system clock for DAC and ADC */ - clk_id = WM8350_MCLK_SEL_PLL_32K; + snd_soc_dai_set_sysclk(codec_dai, WM8350_MCLK_SEL_PLL_32K, + wm8350_audio[i].sysclk, SND_SOC_CLOCK_IN); #else - /* codec FLL input is rate from DAC LRC */ - snd_soc_dai_set_pll(codec_dai, 0, rate, wm8350_audio[i].sysclk); - dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; - /* set DAC LRC as the codec system clock for DAC and ADC */ - clk_id = WM8350_MCLK_SEL_PLL_DAC; -#endif - /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, dai_format); if (ret < 0) @@ -232,8 +251,10 @@ static int imx_3stack_audio_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - snd_soc_dai_set_sysclk(codec_dai, clk_id, + /* set DAC LRC as the codec system clock for DAC and ADC */ + snd_soc_dai_set_sysclk(codec_dai, WM8350_MCLK_SEL_PLL_DAC, wm8350_audio[i].sysclk, SND_SOC_CLOCK_IN); +#endif /* set the SSI system clock as input (unused) */ snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, SND_SOC_CLOCK_IN); @@ -301,27 +322,6 @@ static struct snd_soc_ops imx_3stack_ops = { .hw_params = imx_3stack_audio_hw_params, }; -/* need to refine these */ -static struct wm8350_audio_platform_data imx_3stack_wm8350_setup = { - .vmid_discharge_msecs = 1000, - .drain_msecs = 30, - .cap_discharge_msecs = 700, - .vmid_charge_msecs = 700, - .vmid_s_curve = WM8350_S_CURVE_SLOW, - .dis_out4 = WM8350_DISCHARGE_SLOW, - .dis_out3 = WM8350_DISCHARGE_SLOW, - .dis_out2 = WM8350_DISCHARGE_SLOW, - .dis_out1 = WM8350_DISCHARGE_SLOW, - .vroi_out4 = WM8350_TIE_OFF_500R, - .vroi_out3 = WM8350_TIE_OFF_500R, - .vroi_out2 = WM8350_TIE_OFF_500R, - .vroi_out1 = WM8350_TIE_OFF_500R, - .vroi_enable = 0, - .codec_current_on = WM8350_CODEC_ISEL_1_0, - .codec_current_standby = WM8350_CODEC_ISEL_0_5, - .codec_current_charge = WM8350_CODEC_ISEL_1_5, -}; - static void imx_3stack_init_dam(int ssi_port, int dai_port) { unsigned int ssi_ptcr = 0; @@ -567,7 +567,6 @@ static int imx_3stack_wm8350_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link imx_3stack_dai = { .name = "WM8350", .stream_name = "WM8350", - .cpu_dai = &imx_ssi_dai, .codec_dai = &wm8350_dai, .init = imx_3stack_wm8350_init, .ops = &imx_3stack_ops, @@ -580,7 +579,6 @@ static int imx_3stack_machine_probe(struct platform_device *pdev) struct wm8350 *wm8350 = priv->wm8350; socdev->codec_data = wm8350; - wm8350->codec.platform_data = &imx_3stack_wm8350_setup; return 0; } @@ -603,27 +601,22 @@ static int __devinit imx_3stack_wm8350_probe(struct platform_device *pdev) struct mxc_audio_platform_data *plat = pdev->dev.platform_data; struct imx_3stack_priv *priv = &machine_priv; struct wm8350 *wm8350 = plat->priv; + struct snd_soc_dai *wm8350_cpu_dai; int ret = 0; u16 reg; priv->pdev = pdev; priv->wm8350 = wm8350; - imx_ssi_dai.private_data = plat; - imx_ssi_dai.dev = &pdev->dev; - - imx_3stack_wm8350_setup.regulator1 = plat->regulator1; - imx_3stack_wm8350_setup.regulator2 = plat->regulator2; - gpio_activate_audio_ports(); imx_3stack_init_dam(plat->src_port, plat->ext_port); if (plat->src_port == 2) - imx_ssi_dai.name = "imx-ssi-3"; + wm8350_cpu_dai = &imx_ssi_dai[2]; else - imx_ssi_dai.name = "imx-ssi-1"; + wm8350_cpu_dai = &imx_ssi_dai[0]; - snd_soc_register_dai(&imx_ssi_dai); + imx_3stack_dai.cpu_dai = wm8350_cpu_dai; ret = driver_create_file(pdev->dev.driver, &driver_attr_headphone); if (ret < 0) { diff --git a/sound/soc/imx/imx-3stack-wm8580.c b/sound/soc/imx/imx-3stack-wm8580.c index 0dc7b88d1441..4e468132f406 100644 --- a/sound/soc/imx/imx-3stack-wm8580.c +++ b/sound/soc/imx/imx-3stack-wm8580.c @@ -127,6 +127,7 @@ static int imx_3stack_surround_hw_params(struct snd_pcm_substream *substream, u32 dai_format; unsigned int pll_out = 0, lrclk_ratio = 0; unsigned int channel = params_channels(params); + struct imx_esai *esai_mode = (struct imx_esai *)cpu_dai->private_data; if (clk_state.lr_clk_active > 1) return 0; @@ -225,6 +226,9 @@ static int imx_3stack_surround_hw_params(struct snd_pcm_substream *substream, dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; + esai_mode->sync_mode = 0; + esai_mode->network_mode = 1; + /* set codec DAI configuration */ snd_soc_dai_set_fmt(codec_dai, dai_format); @@ -337,7 +341,6 @@ static int imx_3stack_wm8580_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link imx_3stack_dai = { .name = "wm8580", .stream_name = "wm8580", - .cpu_dai = &imx_esai_dai, .codec_dai = wm8580_dai, .init = imx_3stack_wm8580_init, .ops = &imx_3stack_surround_ops, @@ -370,7 +373,7 @@ static int __devinit imx_3stack_wm8580_probe(struct platform_device *pdev) { struct wm8580_setup_data *setup; - imx_esai_dai.name = "imx-esai-txrx"; + imx_3stack_dai.cpu_dai = &imx_esai_dai[2]; setup = kzalloc(sizeof(struct wm8580_setup_data), GFP_KERNEL); setup->spi = 1; diff --git a/sound/soc/imx/imx-esai.c b/sound/soc/imx/imx-esai.c index 795e3d4bc704..71dd62cff509 100644 --- a/sound/soc/imx/imx-esai.c +++ b/sound/soc/imx/imx-esai.c @@ -320,6 +320,7 @@ #define ESAI_RX_DIV_FP 5 static int imx_esai_txrx_state; +static struct imx_esai imx_esai_priv[3]; static int imx_esai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) @@ -422,35 +423,25 @@ static int imx_esai_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, static int imx_esai_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, unsigned int mask, int slots) { - u32 tcr, rcr, tccr, rccr; + u32 tccr, rccr; if (cpu_dai->id & IMX_DAI_ESAI_TX) { - tcr = __raw_readl(ESAI_TCR); tccr = __raw_readl(ESAI_TCCR); - tcr &= ESAI_TCR_TMOD_MASK; - tcr |= ESAI_TCR_TMOD_NETWORK; - tccr &= ESAI_TCCR_TDC_MASK; tccr |= ESAI_TCCR_TDC(slots - 1); - __raw_writel(tcr, ESAI_TCR); __raw_writel(tccr, ESAI_TCCR); __raw_writel((mask & 0xffff), ESAI_TSMA); __raw_writel(((mask >> 16) & 0xffff), ESAI_TSMB); } if (cpu_dai->id & IMX_DAI_ESAI_RX) { - rcr = __raw_readl(ESAI_RCR); rccr = __raw_readl(ESAI_RCCR); - rcr &= ESAI_RCR_RMOD_MASK; - rcr |= ESAI_RCR_RMOD_NETWORK; - rccr &= ESAI_RCCR_RDC_MASK; rccr |= ESAI_RCCR_RDC(slots - 1); - __raw_writel(rcr, ESAI_RCR); __raw_writel(rccr, ESAI_RCCR); __raw_writel((mask & 0xffff), ESAI_RSMA); __raw_writel(((mask >> 16) & 0xffff), ESAI_RSMB); @@ -466,7 +457,7 @@ static int imx_esai_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, */ static int imx_esai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { - bool sync_mode = cpu_dai->symmetric_rates; + struct imx_esai *esai_mode = (struct imx_esai *)cpu_dai->private_data; u32 tcr, tccr, rcr, rccr, saicr; tcr = __raw_readl(ESAI_TCR); @@ -549,11 +540,21 @@ static int imx_esai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) } /* sync */ - if (sync_mode) + if (esai_mode->sync_mode) saicr |= ESAI_SAICR_SYNC; else saicr &= ~ESAI_SAICR_SYNC; + tcr &= ESAI_TCR_TMOD_MASK; + rcr &= ESAI_RCR_RMOD_MASK; + if (esai_mode->network_mode) { + tcr |= ESAI_TCR_TMOD_NETWORK; + rcr |= ESAI_RCR_RMOD_NETWORK; + } else { + tcr |= ESAI_TCR_TMOD_NORMAL; + rcr |= ESAI_RCR_RMOD_NORMAL; + } + if (cpu_dai->id & IMX_DAI_ESAI_TX) { __raw_writel(tcr, ESAI_TCR); __raw_writel(tccr, ESAI_TCCR); @@ -828,17 +829,6 @@ static int imx_esai_resume(struct snd_soc_dai *dai) static int imx_esai_probe(struct platform_device *pdev, struct snd_soc_dai *dai) { - if (!strcmp("imx-esai-tx", dai->name)) - dai->id = IMX_DAI_ESAI_TX; - else if (!strcmp("imx-esai-rx", dai->name)) - dai->id = IMX_DAI_ESAI_RX; - else if (!strcmp("imx-esai-txrx", dai->name)) - dai->id = IMX_DAI_ESAI_TXRX; - else { - pr_err("%s: invalid device %s\n", __func__, dai->name); - return -ENODEV; - } - imx_esai_txrx_state = 0; esai_clk = clk_get(NULL, "esai_clk"); @@ -870,30 +860,91 @@ static struct snd_soc_dai_ops imx_esai_dai_ops = { .set_tdm_slot = imx_esai_set_dai_tdm_slot, }; -struct snd_soc_dai imx_esai_dai = { - .name = "imx-esai", - .id = 0, - .probe = imx_esai_probe, - .remove = imx_esai_remove, - .suspend = imx_esai_suspend, - .resume = imx_esai_resume, - .playback = { +struct snd_soc_dai imx_esai_dai[] = { + { + .name = "imx-esai-tx", + .id = IMX_DAI_ESAI_TX, + .probe = imx_esai_probe, + .remove = imx_esai_remove, + .suspend = imx_esai_suspend, + .resume = imx_esai_resume, + .playback = { + .channels_min = 1, + .channels_max = 6, + .rates = IMX_ESAI_RATES, + .formats = IMX_ESAI_FORMATS, + }, + .capture = { + .channels_min = 1, + .channels_max = 4, + .rates = IMX_ESAI_RATES, + .formats = IMX_ESAI_FORMATS, + }, + .ops = &imx_esai_dai_ops, + .private_data = &imx_esai_priv[0], + }, + { + .name = "imx-esai-rx", + .id = IMX_DAI_ESAI_RX, + .probe = imx_esai_probe, + .remove = imx_esai_remove, + .suspend = imx_esai_suspend, + .resume = imx_esai_resume, + .playback = { + .channels_min = 1, + .channels_max = 6, + .rates = IMX_ESAI_RATES, + .formats = IMX_ESAI_FORMATS, + }, + .capture = { + .channels_min = 1, + .channels_max = 4, + .rates = IMX_ESAI_RATES, + .formats = IMX_ESAI_FORMATS, + }, + .ops = &imx_esai_dai_ops, + .private_data = &imx_esai_priv[1], + }, + { + .name = "imx-esai-txrx", + .id = IMX_DAI_ESAI_TXRX, + .probe = imx_esai_probe, + .remove = imx_esai_remove, + .suspend = imx_esai_suspend, + .resume = imx_esai_resume, + .playback = { + .channels_min = 1, + .channels_max = 6, + .rates = IMX_ESAI_RATES, + .formats = IMX_ESAI_FORMATS, + }, + .capture = { .channels_min = 1, - .channels_max = 6, + .channels_max = 4, .rates = IMX_ESAI_RATES, .formats = IMX_ESAI_FORMATS, }, - .capture = { - .channels_min = 1, - .channels_max = 4, - .rates = IMX_ESAI_RATES, - .formats = IMX_ESAI_FORMATS, - }, - .ops = &imx_esai_dai_ops, + .ops = &imx_esai_dai_ops, + .private_data = &imx_esai_priv[2], + }, + }; EXPORT_SYMBOL_GPL(imx_esai_dai); +static int __init imx_esai_init(void) +{ + return snd_soc_register_dais(imx_esai_dai, ARRAY_SIZE(imx_esai_dai)); +} + +static void __exit imx_esai_exit(void) +{ + snd_soc_unregister_dais(imx_esai_dai, ARRAY_SIZE(imx_esai_dai)); +} + +module_init(imx_esai_init); +module_exit(imx_esai_exit); + MODULE_AUTHOR("Freescale Semiconductor, Inc."); MODULE_DESCRIPTION("i.MX ASoC ESAI driver"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/imx/imx-esai.h b/sound/soc/imx/imx-esai.h index 8ac2e3fbe6d3..58ad601c119f 100644 --- a/sound/soc/imx/imx-esai.h +++ b/sound/soc/imx/imx-esai.h @@ -20,6 +20,11 @@ #define IMX_DAI_ESAI_RX 0x08 #define IMX_DAI_ESAI_TXRX (IMX_DAI_ESAI_TX | IMX_DAI_ESAI_RX) -extern struct snd_soc_dai imx_esai_dai; +struct imx_esai { + bool network_mode; + bool sync_mode; +}; + +extern struct snd_soc_dai imx_esai_dai[]; #endif diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index 2dba33b8c270..14cc967695dc 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c @@ -39,12 +39,7 @@ #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]; +static struct imx_ssi imx_ssi_data[4]; /* debug */ #define IMX_SSI_DEBUG 0 @@ -194,11 +189,8 @@ 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; @@ -236,12 +228,9 @@ 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; + struct imx_ssi *ssi_mode = (struct imx_ssi *)cpu_dai->private_data; 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 @@ -303,7 +292,7 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) case SND_SOC_DAIFMT_CBS_CFS: stcr |= SSI_STCR_TFDIR | SSI_STCR_TXDIR; if (((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S) - && network_mode) { + && ssi_mode->network_mode) { scr &= ~SSI_SCR_I2S_MODE_MASK; scr |= SSI_SCR_I2S_MODE_MSTR; } @@ -318,7 +307,7 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) break; case SND_SOC_DAIFMT_CBM_CFM: if (((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S) - && network_mode) { + && ssi_mode->network_mode) { scr &= ~SSI_SCR_I2S_MODE_MASK; scr |= SSI_SCR_I2S_MODE_SLAVE; } @@ -326,11 +315,11 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) } /* sync */ - if (sync_mode) + if (ssi_mode->sync_mode) scr |= SSI_SCR_SYN; /* tdm - only for stereo atm */ - if (network_mode) + if (ssi_mode->network_mode) scr |= SSI_SCR_NET; if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI1) { @@ -451,8 +440,9 @@ static int imx_ssi_hw_rx_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { - bool sync_mode = cpu_dai->symmetric_rates; u32 srccr, srcr, sier; + struct imx_ssi *ssi_mode = (struct imx_ssi *)cpu_dai->private_data; + bool sync_mode = ssi_mode->sync_mode; if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI1) { srccr = @@ -690,29 +680,16 @@ static irqreturn_t ssi2_irq(int irq, void *dev_id) static int imx_ssi_probe(struct platform_device *pdev, struct snd_soc_dai *dai) { - if (!strcmp(dai->name, "imx-ssi-1")) - dai->id = IMX_DAI_SSI0; - else if (!strcmp(dai->name, "imx-ssi-2")) - dai->id = IMX_DAI_SSI1; - else if (!strcmp(dai->name, "imx-ssi-3")) - dai->id = IMX_DAI_SSI2; - else if (!strcmp(dai->name, "imx-ssi-4")) - dai->id = IMX_DAI_SSI3; - else { - printk(KERN_ERR "%s: invalid device %s\n", __func__, dai->name); - return -ENODEV; - } - - if ((!strcmp(dai->name, "imx-ssi-1")) || - (!strcmp(dai->name, "imx-ssi-2"))) + if ((!strcmp(dai->name, "imx-ssi-1-0")) || + (!strcmp(dai->name, "imx-ssi-1-1"))) if (request_irq(MXC_INT_SSI1, ssi1_irq, 0, "ssi1", dai)) { printk(KERN_ERR "%s: failure requesting irq %s\n", __func__, "ssi1"); return -EBUSY; } - if ((!strcmp(dai->name, "imx-ssi-3")) || - (!strcmp(dai->name, "imx-ssi-4"))) + if ((!strcmp(dai->name, "imx-ssi-2-0")) || + (!strcmp(dai->name, "imx-ssi-2-1"))) if (request_irq(MXC_INT_SSI2, ssi2_irq, 0, "ssi2", dai)) { printk(KERN_ERR "%s: failure requesting irq %s\n", __func__, "ssi2"); @@ -725,12 +702,12 @@ static int imx_ssi_probe(struct platform_device *pdev, struct snd_soc_dai *dai) static void imx_ssi_remove(struct platform_device *pdev, struct snd_soc_dai *dai) { - if ((!strcmp(dai->name, "imx-ssi-1")) || - (!strcmp(dai->name, "imx-ssi-2"))) + if ((!strcmp(dai->name, "imx-ssi-1-0")) || + (!strcmp(dai->name, "imx-ssi-1-1"))) free_irq(MXC_INT_SSI1, dai); - if ((!strcmp(dai->name, "imx-ssi-3")) || - (!strcmp(dai->name, "imx-ssi-4"))) + if ((!strcmp(dai->name, "imx-ssi-2-0")) || + (!strcmp(dai->name, "imx-ssi-2-1"))) free_irq(MXC_INT_SSI2, dai); } @@ -757,29 +734,111 @@ static struct snd_soc_dai_ops imx_ssi_dai_ops = { .set_tdm_slot = imx_ssi_set_dai_tdm_slot, }; -struct snd_soc_dai imx_ssi_dai = { - .name = "imx-ssi", - .id = 0, - .probe = imx_ssi_probe, - .suspend = imx_ssi_suspend, - .remove = imx_ssi_remove, - .resume = imx_ssi_resume, - .playback = { +struct snd_soc_dai imx_ssi_dai[] = { + { + .name = "imx-ssi-1-0", + .id = IMX_DAI_SSI0, + .probe = imx_ssi_probe, + .suspend = imx_ssi_suspend, + .remove = imx_ssi_remove, + .resume = imx_ssi_resume, + .playback = { + .channels_min = 1, + .channels_max = 2, + .rates = IMX_SSI_RATES, + .formats = IMX_SSI_FORMATS, + }, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rates = IMX_SSI_RATES, + .formats = IMX_SSI_FORMATS, + }, + .ops = &imx_ssi_dai_ops, + .private_data = &imx_ssi_data[IMX_DAI_SSI0], + }, + { + .name = "imx-ssi-1-1", + .id = IMX_DAI_SSI1, + .probe = imx_ssi_probe, + .suspend = imx_ssi_suspend, + .remove = imx_ssi_remove, + .resume = imx_ssi_resume, + .playback = { + .channels_min = 1, + .channels_max = 2, + .rates = IMX_SSI_RATES, + .formats = IMX_SSI_FORMATS, + }, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rates = IMX_SSI_RATES, + .formats = IMX_SSI_FORMATS, + }, + .ops = &imx_ssi_dai_ops, + .private_data = &imx_ssi_data[IMX_DAI_SSI1], + }, + { + .name = "imx-ssi-2-0", + .id = IMX_DAI_SSI2, + .probe = imx_ssi_probe, + .suspend = imx_ssi_suspend, + .remove = imx_ssi_remove, + .resume = imx_ssi_resume, + .playback = { + .channels_min = 1, + .channels_max = 2, + .rates = IMX_SSI_RATES, + .formats = IMX_SSI_FORMATS, + }, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rates = IMX_SSI_RATES, + .formats = IMX_SSI_FORMATS, + }, + .ops = &imx_ssi_dai_ops, + .private_data = &imx_ssi_data[IMX_DAI_SSI2], + }, + { + .name = "imx-ssi-2-1", + .id = IMX_DAI_SSI3, + .probe = imx_ssi_probe, + .suspend = imx_ssi_suspend, + .remove = imx_ssi_remove, + .resume = imx_ssi_resume, + .playback = { + .channels_min = 1, + .channels_max = 2, + .rates = IMX_SSI_RATES, + .formats = IMX_SSI_FORMATS, + }, + .capture = { .channels_min = 1, .channels_max = 2, .rates = IMX_SSI_RATES, .formats = IMX_SSI_FORMATS, }, - .capture = { - .channels_min = 1, - .channels_max = 2, - .rates = IMX_SSI_RATES, - .formats = IMX_SSI_FORMATS, - }, - .ops = &imx_ssi_dai_ops, + .ops = &imx_ssi_dai_ops, + .private_data = &imx_ssi_data[IMX_DAI_SSI3], + }, }; + EXPORT_SYMBOL_GPL(imx_ssi_dai); +static int __init imx_ssi_init(void) +{ + return snd_soc_register_dais(imx_ssi_dai, ARRAY_SIZE(imx_ssi_dai)); +} + +static void __exit imx_ssi_exit(void) +{ + snd_soc_unregister_dais(imx_ssi_dai, ARRAY_SIZE(imx_ssi_dai)); +} + +module_init(imx_ssi_init); +module_exit(imx_ssi_exit); MODULE_AUTHOR ("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com"); MODULE_DESCRIPTION("i.MX ASoC I2S driver"); diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h index ffb27e9d2aea..387e992b397f 100644 --- a/sound/soc/imx/imx-ssi.h +++ b/sound/soc/imx/imx-ssi.h @@ -213,6 +213,12 @@ #define IMX_SSI_DIV_2_OFF (~SSI_STCCR_DIV2) #define IMX_SSI_DIV_2_ON SSI_STCCR_DIV2 -extern struct snd_soc_dai imx_ssi_dai; +/* private info */ +struct imx_ssi { + bool network_mode; + bool sync_mode; +}; + +extern struct snd_soc_dai imx_ssi_dai[]; #endif |