diff options
Diffstat (limited to 'sound/soc')
| -rw-r--r-- | sound/soc/codecs/ab8500-codec.c | 81 | ||||
| -rw-r--r-- | sound/soc/ux500/mop500.c | 47 | ||||
| -rw-r--r-- | sound/soc/ux500/ux500_msp_dai.c | 6 | ||||
| -rw-r--r-- | sound/soc/ux500/ux500_msp_i2s.c | 89 | ||||
| -rw-r--r-- | sound/soc/ux500/ux500_msp_i2s.h | 8 | 
5 files changed, 205 insertions, 26 deletions
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 2c1c2524ef8..af547490b4f 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -34,6 +34,7 @@  #include <linux/mfd/abx500/ab8500-sysctrl.h>  #include <linux/mfd/abx500/ab8500-codec.h>  #include <linux/regulator/consumer.h> +#include <linux/of.h>  #include <sound/core.h>  #include <sound/pcm.h> @@ -2394,9 +2395,65 @@ struct snd_soc_dai_driver ab8500_codec_dai[] = {  	}  }; +static void ab8500_codec_of_probe(struct device *dev, struct device_node *np, +				struct ab8500_codec_platform_data *codec) +{ +	u32 value; + +	if (of_get_property(np, "stericsson,amic1-type-single-ended", NULL)) +		codec->amics.mic1_type = AMIC_TYPE_SINGLE_ENDED; +	else +		codec->amics.mic1_type = AMIC_TYPE_DIFFERENTIAL; + +	if (of_get_property(np, "stericsson,amic2-type-single-ended", NULL)) +		codec->amics.mic2_type = AMIC_TYPE_SINGLE_ENDED; +	else +		codec->amics.mic2_type = AMIC_TYPE_DIFFERENTIAL; + +	/* Has a non-standard Vamic been requested? */ +	if (of_get_property(np, "stericsson,amic1a-bias-vamic2", NULL)) +		codec->amics.mic1a_micbias = AMIC_MICBIAS_VAMIC2; +	else +		codec->amics.mic1a_micbias = AMIC_MICBIAS_VAMIC1; + +	if (of_get_property(np, "stericsson,amic1b-bias-vamic2", NULL)) +		codec->amics.mic1b_micbias = AMIC_MICBIAS_VAMIC2; +	else +		codec->amics.mic1b_micbias = AMIC_MICBIAS_VAMIC1; + +	if (of_get_property(np, "stericsson,amic2-bias-vamic1", NULL)) +		codec->amics.mic2_micbias = AMIC_MICBIAS_VAMIC1; +	else +		codec->amics.mic2_micbias = AMIC_MICBIAS_VAMIC2; + +	if (!of_property_read_u32(np, "stericsson,earpeice-cmv", &value)) { +		switch (value) { +		case 950 : +			codec->ear_cmv = EAR_CMV_0_95V; +			break; +		case 1100 : +			codec->ear_cmv = EAR_CMV_1_10V; +			break; +		case 1270 : +			codec->ear_cmv = EAR_CMV_1_27V; +			break; +		case 1580 : +			codec->ear_cmv = EAR_CMV_1_58V; +			break; +		default : +			codec->ear_cmv = EAR_CMV_UNKNOWN; +			dev_err(dev, "Unsuitable earpiece voltage found in DT\n"); +		} +	} else { +		dev_warn(dev, "No earpiece voltage found in DT - using default\n"); +		codec->ear_cmv = EAR_CMV_0_95V; +	} +} +  static int ab8500_codec_probe(struct snd_soc_codec *codec)  {  	struct device *dev = codec->dev; +	struct device_node *np = dev->of_node;  	struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(dev);  	struct ab8500_platform_data *pdata;  	struct filter_control *fc; @@ -2407,6 +2464,30 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec)  	/* Setup AB8500 according to board-settings */  	pdata = dev_get_platdata(dev->parent); +	if (np) { +		if (!pdata) +			pdata = devm_kzalloc(dev, +					sizeof(struct ab8500_platform_data), +					GFP_KERNEL); + +		if (pdata && !pdata->codec) +			pdata->codec +				= devm_kzalloc(dev, +					sizeof(struct ab8500_codec_platform_data), +					GFP_KERNEL); + +		if (!(pdata && pdata->codec)) +			return -ENOMEM; + +		ab8500_codec_of_probe(dev, np, pdata->codec); + +	} else { +		if (!(pdata && pdata->codec)) { +			dev_err(dev, "No codec platform data or DT found\n"); +			return -EINVAL; +		} +	} +  	status = ab8500_audio_setup_mics(codec, &pdata->codec->amics);  	if (status < 0) {  		pr_err("%s: Failed to setup mics (%d)!\n", __func__, status); diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c index 31c4d26d035..356611d9654 100644 --- a/sound/soc/ux500/mop500.c +++ b/sound/soc/ux500/mop500.c @@ -16,6 +16,7 @@  #include <linux/module.h>  #include <linux/io.h>  #include <linux/spi/spi.h> +#include <linux/of.h>  #include <sound/soc.h>  #include <sound/initval.h> @@ -56,16 +57,47 @@ static struct snd_soc_card mop500_card = {  	.num_links = ARRAY_SIZE(mop500_dai_links),  }; +static int __devinit mop500_of_probe(struct platform_device *pdev, +				struct device_node *np) +{ +	struct device_node *codec_np, *msp_np[2]; +	int i; + +	msp_np[0] = of_parse_phandle(np, "stericsson,cpu-dai", 0); +	msp_np[1] = of_parse_phandle(np, "stericsson,cpu-dai", 1); +	codec_np  = of_parse_phandle(np, "stericsson,audio-codec", 0); + +	if (!(msp_np[0] && msp_np[1] && codec_np)) { +		dev_err(&pdev->dev, "Phandle missing or invalid\n"); +		return -EINVAL; +	} + +	for (i = 0; i < 2; i++) { +		mop500_dai_links[i].cpu_of_node = msp_np[i]; +		mop500_dai_links[i].cpu_dai_name = NULL; +		mop500_dai_links[i].codec_of_node = codec_np; +		mop500_dai_links[i].codec_name = NULL; +	} + +	snd_soc_of_parse_card_name(&mop500_card, "stericsson,card-name"); + +	return 0; +}  static int __devinit mop500_probe(struct platform_device *pdev)  { +	struct device_node *np = pdev->dev.of_node;  	int ret; -	pr_debug("%s: Enter.\n", __func__); -  	dev_dbg(&pdev->dev, "%s: Enter.\n", __func__);  	mop500_card.dev = &pdev->dev; +	if (np) { +		ret = mop500_of_probe(pdev, np); +		if (ret) +			return ret; +	} +  	dev_dbg(&pdev->dev, "%s: Card %s: Set platform drvdata.\n",  		__func__, mop500_card.name);  	platform_set_drvdata(pdev, &mop500_card); @@ -83,8 +115,7 @@ static int __devinit mop500_probe(struct platform_device *pdev)  	ret = snd_soc_register_card(&mop500_card);  	if (ret)  		dev_err(&pdev->dev, -			"Error: snd_soc_register_card failed (%d)!\n", -			ret); +			"Error: snd_soc_register_card failed (%d)!\n", ret);  	return ret;  } @@ -97,14 +128,20 @@ static int __devexit mop500_remove(struct platform_device *pdev)  	snd_soc_unregister_card(mop500_card);  	mop500_ab8500_remove(mop500_card); -	 +  	return 0;  } +static const struct of_device_id snd_soc_mop500_match[] = { +	{ .compatible = "stericsson,snd-soc-mop500", }, +	{}, +}; +  static struct platform_driver snd_soc_mop500_driver = {  	.driver = {  		.owner = THIS_MODULE,  		.name = "snd-soc-mop500", +		.of_match_table = snd_soc_mop500_match,  	},  	.probe = mop500_probe,  	.remove = __devexit_p(mop500_remove), diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 772cb19d2fb..be94bf9bf94 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c @@ -833,10 +833,16 @@ static int __devexit ux500_msp_drv_remove(struct platform_device *pdev)  	return 0;  } +static const struct of_device_id ux500_msp_i2s_match[] = { +	{ .compatible = "stericsson,ux500-msp-i2s", }, +	{}, +}; +  static struct platform_driver msp_i2s_driver = {  	.driver = {  		.name = "ux500-msp-i2s",  		.owner = THIS_MODULE, +		.of_match_table = ux500_msp_i2s_match,  	},  	.probe = ux500_msp_drv_probe,  	.remove = ux500_msp_drv_remove, diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index 1b7c2f58ce1..b7c996e7757 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c @@ -15,8 +15,10 @@  #include <linux/module.h>  #include <linux/platform_device.h> +#include <linux/pinctrl/consumer.h>  #include <linux/delay.h>  #include <linux/slab.h> +#include <linux/of.h>  #include <mach/hardware.h>  #include <mach/msp.h> @@ -25,6 +27,9 @@  #include "ux500_msp_i2s.h" +/* MSP1/3 Tx/Rx usage protection */ +static DEFINE_SPINLOCK(msp_rxtx_lock); +   /* Protocol desciptors */  static const struct msp_protdesc prot_descs[] = {  	{ /* I2S */ @@ -352,17 +357,23 @@ static int configure_multichannel(struct ux500_msp *msp,  static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config)  { -	int status = 0; +	int status = 0, retval = 0;  	u32 reg_val_DMACR, reg_val_GCR; +	unsigned long flags;  	/* Check msp state whether in RUN or CONFIGURED Mode */ -	if ((msp->msp_state == MSP_STATE_IDLE) && (msp->plat_init)) { -		status = msp->plat_init(); -		if (status) { -			dev_err(msp->dev, "%s: ERROR: Failed to init MSP (%d)!\n", -				__func__, status); -			return status; +	if (msp->msp_state == MSP_STATE_IDLE) { +		spin_lock_irqsave(&msp_rxtx_lock, flags); +		if (msp->pinctrl_rxtx_ref == 0 && +			!(IS_ERR(msp->pinctrl_p) || IS_ERR(msp->pinctrl_def))) { +			retval = pinctrl_select_state(msp->pinctrl_p, +						msp->pinctrl_def); +			if (retval) +				pr_err("could not set MSP defstate\n");  		} +		if (!retval) +			msp->pinctrl_rxtx_ref++; +		spin_unlock_irqrestore(&msp_rxtx_lock, flags);  	}  	/* Configure msp with protocol dependent settings */ @@ -620,7 +631,8 @@ int ux500_msp_i2s_trigger(struct ux500_msp *msp, int cmd, int direction)  int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir)  { -	int status = 0; +	int status = 0, retval = 0; +	unsigned long flags;  	dev_dbg(msp->dev, "%s: Enter (dir = 0x%01x).\n", __func__, dir); @@ -631,12 +643,19 @@ int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir)  		writel((readl(msp->registers + MSP_GCR) &  			       (~(FRAME_GEN_ENABLE | SRG_ENABLE))),  			      msp->registers + MSP_GCR); -		if (msp->plat_exit) -			status = msp->plat_exit(); -			if (status) -				dev_warn(msp->dev, -					"%s: WARN: ux500_msp_i2s_exit failed (%d)!\n", -					__func__, status); + +		spin_lock_irqsave(&msp_rxtx_lock, flags); +		WARN_ON(!msp->pinctrl_rxtx_ref); +		msp->pinctrl_rxtx_ref--; +		if (msp->pinctrl_rxtx_ref == 0 && +			!(IS_ERR(msp->pinctrl_p) || IS_ERR(msp->pinctrl_sleep))) { +			retval = pinctrl_select_state(msp->pinctrl_p, +						msp->pinctrl_sleep); +			if (retval) +				pr_err("could not set MSP sleepstate\n"); +		} +		spin_unlock_irqrestore(&msp_rxtx_lock, flags); +  		writel(0, msp->registers + MSP_GCR);  		writel(0, msp->registers + MSP_TCF);  		writel(0, msp->registers + MSP_RCF); @@ -665,20 +684,33 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,  {  	struct resource *res = NULL;  	struct i2s_controller *i2s_cont; +	struct device_node *np = pdev->dev.of_node;  	struct ux500_msp *msp; -	dev_dbg(&pdev->dev, "%s: Enter (name: %s, id: %d).\n", __func__, -		pdev->name, platform_data->id); -  	*msp_p = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp), GFP_KERNEL);  	msp = *msp_p;  	if (!msp)  		return -ENOMEM; +	if (np) { +		if (!platform_data) { +			platform_data = devm_kzalloc(&pdev->dev, +				sizeof(struct msp_i2s_platform_data), GFP_KERNEL); +			if (!platform_data) +				ret = -ENOMEM; +		} +	} else +		if (!platform_data) +			ret = -EINVAL; + +	if (ret) +		goto err_res; + +	dev_dbg(&pdev->dev, "%s: Enter (name: %s, id: %d).\n", __func__, +		pdev->name, platform_data->id); +  	msp->id = platform_data->id;  	msp->dev = &pdev->dev; -	msp->plat_init = platform_data->msp_i2s_init; -	msp->plat_exit = platform_data->msp_i2s_exit;  	msp->dma_cfg_rx = platform_data->msp_i2s_dma_rx;  	msp->dma_cfg_tx = platform_data->msp_i2s_dma_tx; @@ -715,6 +747,25 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,  	dev_dbg(&pdev->dev, "I2S device-name: '%s'\n", i2s_cont->name);  	msp->i2s_cont = i2s_cont; +	msp->pinctrl_p = pinctrl_get(msp->dev); +	if (IS_ERR(msp->pinctrl_p)) +		dev_err(&pdev->dev, "could not get MSP pinctrl\n"); +	else { +		msp->pinctrl_def = pinctrl_lookup_state(msp->pinctrl_p, +						PINCTRL_STATE_DEFAULT); +		if (IS_ERR(msp->pinctrl_def)) { +			dev_err(&pdev->dev, +				"could not get MSP defstate (%li)\n", +				PTR_ERR(msp->pinctrl_def)); +		} +		msp->pinctrl_sleep = pinctrl_lookup_state(msp->pinctrl_p, +						PINCTRL_STATE_SLEEP); +		if (IS_ERR(msp->pinctrl_sleep)) +			dev_err(&pdev->dev, +				"could not get MSP idlestate (%li)\n", +				PTR_ERR(msp->pinctrl_def)); +	} +  	return 0;  } diff --git a/sound/soc/ux500/ux500_msp_i2s.h b/sound/soc/ux500/ux500_msp_i2s.h index 2d9136da986..1311c0df762 100644 --- a/sound/soc/ux500/ux500_msp_i2s.h +++ b/sound/soc/ux500/ux500_msp_i2s.h @@ -524,14 +524,18 @@ struct ux500_msp {  	struct dma_chan *rx_pipeid;  	enum msp_state msp_state;  	int (*transfer) (struct ux500_msp *msp, struct i2s_message *message); -	int (*plat_init) (void); -	int (*plat_exit) (void);  	struct timer_list notify_timer;  	int def_elem_len;  	unsigned int dir_busy;  	int loopback_enable;  	u32 backup_regs[MAX_MSP_BACKUP_REGS];  	unsigned int f_bitclk; +	/* Pin modes */ +	struct pinctrl *pinctrl_p; +	struct pinctrl_state *pinctrl_def; +	struct pinctrl_state *pinctrl_sleep; +	/* Reference Count */ +	int pinctrl_rxtx_ref;  };  struct ux500_msp_dma_params {  |