diff options
24 files changed, 502 insertions, 303 deletions
diff --git a/arch/arm/mach-mx25/mx25_3stack.c b/arch/arm/mach-mx25/mx25_3stack.c index fd0d30121f57..a956950913f8 100644 --- a/arch/arm/mach-mx25/mx25_3stack.c +++ b/arch/arm/mach-mx25/mx25_3stack.c @@ -333,9 +333,6 @@ static struct mxc_audio_platform_data sgtl5000_data = { .ext_port = 4, .hp_irq = IOMUX_TO_IRQ(MX25_PIN_A10), .hp_status = headphone_det_status, - .vddio = 1800000, - .vdda = 3300000, - .vddd = 0, .sysclk = 8300000, }; diff --git a/arch/arm/mach-mx25/mx25_3stack_pmic_mc34704.c b/arch/arm/mach-mx25/mx25_3stack_pmic_mc34704.c index 95fbf66fe564..fdb91131143d 100644 --- a/arch/arm/mach-mx25/mx25_3stack_pmic_mc34704.c +++ b/arch/arm/mach-mx25/mx25_3stack_pmic_mc34704.c @@ -35,6 +35,27 @@ struct mc34704; +static struct regulator_consumer_supply rcpu_consumers[] = { + { + /* sgtl5000 */ + .supply = "VDDA", + .dev_name = "0-000a", + }, + { + /* sgtl5000 */ + .supply = "VDDD", + .dev_name = "0-000a", + }, +}; + +static struct regulator_consumer_supply rddr_consumers[] = { + { + /* sgtl5000 */ + .supply = "VDDIO", + .dev_name = "0-000a", + }, +}; + static struct regulator_init_data rbklt_init = { .constraints = { .name = "REG1_BKLT", @@ -58,7 +79,9 @@ static struct regulator_init_data rcpu_init = { mV_to_uV(REG2_V_MV * (1000 + REG2_DVS_MAX_PCT * 10) / 1000), .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, - } + }, + .num_consumer_supplies = ARRAY_SIZE(rcpu_consumers), + .consumer_supplies = rcpu_consumers, }; static struct regulator_init_data rcore_init = { @@ -84,7 +107,9 @@ static struct regulator_init_data rddr_init = { mV_to_uV(REG4_V_MV * (1000 + REG4_DVS_MAX_PCT * 10) / 1000), .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, - } + }, + .num_consumer_supplies = ARRAY_SIZE(rddr_consumers), + .consumer_supplies = rddr_consumers, }; static struct regulator_init_data rpers_init = { diff --git a/arch/arm/mach-mx35/mx35_3stack.c b/arch/arm/mach-mx35/mx35_3stack.c index 02fed337d772..1231d5e59e2f 100644 --- a/arch/arm/mach-mx35/mx35_3stack.c +++ b/arch/arm/mach-mx35/mx35_3stack.c @@ -865,12 +865,7 @@ static struct mxc_audio_platform_data sgtl5000_data = { .ext_port = 4, .hp_irq = MXC_PSEUDO_IRQ_HEADPHONE, .hp_status = sgtl5000_headphone_det_status, - .vddio_reg = NULL, - .vdda_reg = "VCAM", .amp_enable = mxc_sgtl5000_amp_enable, - .vddio = 0, - .vdda = 3000000, - .vddd = 0, .sysclk = 12000000, .init = mxc_sgtl5000_plat_init, .finit = mxc_sgtl5000_plat_finit, diff --git a/arch/arm/mach-mx35/mx35_3stack_pmic_mc13892.c b/arch/arm/mach-mx35/mx35_3stack_pmic_mc13892.c index 44cccc564c2e..b20be8208483 100644 --- a/arch/arm/mach-mx35/mx35_3stack_pmic_mc13892.c +++ b/arch/arm/mach-mx35/mx35_3stack_pmic_mc13892.c @@ -44,6 +44,14 @@ static struct regulator_consumer_supply sw1_consumers[] = { } }; +static struct regulator_consumer_supply vcam_consumers[] = { + { + /* sgtl5000 */ + .supply = "VDDA", + .dev_name = "0-000a", + }, +}; + struct mc13892; static struct regulator_init_data sw1_init = { @@ -195,7 +203,9 @@ static struct regulator_init_data vcam_init = { .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE, .valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL, - } + }, + .num_consumer_supplies = ARRAY_SIZE(vcam_consumers), + .consumer_supplies = vcam_consumers, }; static struct regulator_init_data vgen1_init = { diff --git a/arch/arm/mach-mx37/mx37_3stack.c b/arch/arm/mach-mx37/mx37_3stack.c index b62b2b8f179c..acd36bc2cd9e 100644 --- a/arch/arm/mach-mx37/mx37_3stack.c +++ b/arch/arm/mach-mx37/mx37_3stack.c @@ -755,12 +755,7 @@ static struct mxc_audio_platform_data sgtl5000_data = { .ext_port = 5, .hp_irq = IOMUX_TO_IRQ(MX37_PIN_AUD5_RXFS), .hp_status = headphone_det_status, - .vddio_reg = "SW3", - .vdda_reg = "VAUDIO", .amp_enable = mxc_sgtl5000_amp_enable, - .vddio = 1850000, - .vdda = 2775000, - .vddd = 0, .init = mxc_sgtl5000_plat_init, .finit = mxc_sgtl5000_plat_finit, }; diff --git a/arch/arm/mach-mx37/mx37_3stack_pmic_wm8350.c b/arch/arm/mach-mx37/mx37_3stack_pmic_wm8350.c index 0ab86ff29a3f..f80a61cf00e1 100644 --- a/arch/arm/mach-mx37/mx37_3stack_pmic_wm8350.c +++ b/arch/arm/mach-mx37/mx37_3stack_pmic_wm8350.c @@ -20,6 +20,7 @@ #include <linux/i2c.h> #include <linux/err.h> #include <linux/regulator/machine.h> +#include <linux/mfd/wm8350/audio.h> #include <linux/mfd/wm8350/core.h> #include <linux/mfd/wm8350/pmic.h> #include <linux/mfd/wm8350/gpio.h> @@ -35,6 +36,17 @@ static struct regulator_consumer_supply dcdc1_consumers[] = { } }; +static struct regulator_consumer_supply dcdc3_consumers[] = { + { + .supply = "AVDD", + .dev_name = "1-001a", + }, + { + .supply = "HPVDD", + .dev_name = "1-001a", + }, +}; + static struct regulator_init_data dcdc1_data = { .constraints = { .name = "DCDC1", @@ -107,6 +119,8 @@ static struct regulator_init_data dcdc3_data = { .valid_modes_mask = REGULATOR_MODE_NORMAL, .apply_uV = 1, }, + .num_consumer_supplies = ARRAY_SIZE(dcdc3_consumers), + .consumer_supplies = dcdc3_consumers, }; static struct regulator_init_data ldo1_data = { @@ -217,12 +231,30 @@ static struct platform_device mxc_wm8350_devices[] = { }, }; +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, +}; + struct mxc_audio_platform_data imx_3stack_audio_platform_data = { .ssi_num = 2, .src_port = 2, .ext_port = 5, - .regulator1 = "DCDC6", - .regulator2 = "DCDC3", }; static struct platform_device *imx_snd_device; @@ -271,6 +303,8 @@ static int mx37_wm8350_init(struct wm8350 *wm8350) /* register sound */ pr_info("Registering imx37_snd_device"); + wm8350->codec.platform_data = &imx_3stack_wm8350_setup; + imx_snd_device = platform_device_alloc("wm8350-imx-3stack-audio", -1); if (!imx_snd_device) { ret = -ENOMEM; @@ -334,10 +368,10 @@ static __init int wm8350_regulator_init(void) wm8350_global_regulator [i])))) { regulator_enable(regulator); - if (wm8350_global_regulator[i] == "DCDC4") + if (strcmp(wm8350_global_regulator[i], "DCDC4") == 0) ret = regulator_set_voltage(regulator, 1250000, 1250000); - else if (wm8350_global_regulator[i] == "DCDC1") { + else if (strcmp(wm8350_global_regulator[i], "DCDC1") == 0) { ret = regulator_set_voltage(regulator, 1050000, 1050000); regulator_set_mode(regulator, REGULATOR_MODE_FAST); diff --git a/arch/arm/mach-mx51/mx51_3stack.c b/arch/arm/mach-mx51/mx51_3stack.c index 0ff08e977f0c..39ddfbb6d0a4 100644 --- a/arch/arm/mach-mx51/mx51_3stack.c +++ b/arch/arm/mach-mx51/mx51_3stack.c @@ -1049,9 +1049,6 @@ static struct mxc_audio_platform_data sgtl5000_data = { .hp_irq = IOMUX_TO_IRQ(MX51_PIN_EIM_A26), .hp_status = headphone_det_status, .amp_enable = mxc_sgtl5000_amp_enable, - .vddio = 1800000, - .vdda = 1800000, - .vddd = 1200000, .sysclk = 12000000, .init = mxc_sgtl5000_plat_init, .finit = mxc_sgtl5000_plat_finit, diff --git a/arch/arm/mach-mx51/mx51_babbage.c b/arch/arm/mach-mx51/mx51_babbage.c index 860e687a8cc2..11955f80ce39 100644 --- a/arch/arm/mach-mx51/mx51_babbage.c +++ b/arch/arm/mach-mx51/mx51_babbage.c @@ -812,13 +812,7 @@ static struct mxc_audio_platform_data sgtl5000_data = { .ext_port = 3, .hp_irq = IOMUX_TO_IRQ(MX51_PIN_NANDF_CS0), .hp_status = headphone_det_status, - .vddio_reg = "VVIDEO", - .vdda_reg = "VDIG", - .vddd_reg = "VGEN1", .amp_enable = mxc_sgtl5000_amp_enable, - .vddio = 2775000, - .vdda = 1650000, - .vddd = 1200000, .sysclk = 12288000, }; @@ -840,8 +834,6 @@ static void mxc_init_sgtl5000(void) { if (cpu_is_mx51_rev(CHIP_REV_1_1) == 2) { sgtl5000_data.sysclk = 26000000; - sgtl5000_data.vddd_reg = NULL; - sgtl5000_data.vddd = 0; } gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_A23), "eim_a23"); diff --git a/arch/arm/mach-mx51/mx51_babbage_pmic_mc13892.c b/arch/arm/mach-mx51/mx51_babbage_pmic_mc13892.c index 2b1efe1a2e4a..8165e12d1356 100644 --- a/arch/arm/mach-mx51/mx51_babbage_pmic_mc13892.c +++ b/arch/arm/mach-mx51/mx51_babbage_pmic_mc13892.c @@ -85,6 +85,27 @@ static struct regulator_consumer_supply sw1_consumers[] = { } }; +static struct regulator_consumer_supply vdig_consumers[] = { + { + /* sgtl5000 */ + .supply = "VDDA", + .dev_name = "1-000a", + }, + { + /* sgtl5000 */ + .supply = "VDDD", + .dev_name = "1-000a", + }, +}; + +static struct regulator_consumer_supply vvideo_consumers[] = { + { + /* sgtl5000 */ + .supply = "VDDIO", + .dev_name = "1-000a", + }, +}; + struct mc13892; static struct regulator_init_data sw1_init = { @@ -169,11 +190,13 @@ static struct regulator_init_data swbst_init = { static struct regulator_init_data vdig_init = { .constraints = { .name = "VDIG", - .min_uV = mV_to_uV(1050), - .max_uV = mV_to_uV(1800), + .min_uV = mV_to_uV(1650), + .max_uV = mV_to_uV(1650), .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, .boot_on = 1, - } + }, + .num_consumer_supplies = ARRAY_SIZE(vdig_consumers), + .consumer_supplies = vdig_consumers, }; static struct regulator_init_data vpll_init = { @@ -204,7 +227,9 @@ static struct regulator_init_data vvideo_init = { .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, .always_on = 1, .apply_uV =1, - } + }, + .num_consumer_supplies = ARRAY_SIZE(vvideo_consumers), + .consumer_supplies = vvideo_consumers, }; static struct regulator_init_data vaudio_init = { @@ -240,7 +265,7 @@ static struct regulator_init_data vgen1_init = { .constraints = { .name = "VGEN1", .min_uV = mV_to_uV(1200), - .max_uV = mV_to_uV(3150), + .max_uV = mV_to_uV(1200), .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, } }; diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h index f1cbce461cac..a15d63ce4112 100644 --- a/arch/arm/plat-mxc/include/mach/mxc.h +++ b/arch/arm/plat-mxc/include/mach/mxc.h @@ -236,18 +236,10 @@ struct mxc_audio_platform_data { int intr_id_hp; int ext_ram; struct clk *ssi_clk[2]; - char *regulator1; - char *regulator2; int hp_irq; int (*hp_status) (void); - char *vddio_reg; - char *vdda_reg; - char *vddd_reg; - int vddio; /* voltage of VDDIO (uv) */ - int vdda; /* voltage of vdda (uv) */ - int vddd; /* voltage of vddd (uv), 0 if not connected */ int sysclk; int (*init) (void); /* board specific init */ 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 |