Merge remote-tracking branch 'asoc/topic/ux500' into for-3.7
This commit is contained in:
commit
2ef39e606b
39
Documentation/devicetree/bindings/sound/ux500-mop500.txt
Normal file
39
Documentation/devicetree/bindings/sound/ux500-mop500.txt
Normal file
|
@ -0,0 +1,39 @@
|
|||
* MOP500 Audio Machine Driver
|
||||
|
||||
This node is responsible for linking together all ux500 Audio Driver components.
|
||||
|
||||
Required properties:
|
||||
- compatible : "stericsson,snd-soc-mop500"
|
||||
|
||||
Non-standard properties:
|
||||
- stericsson,cpu-dai : Phandle to the CPU-side DAI
|
||||
- stericsson,audio-codec : Phandle to the Audio CODEC
|
||||
- stericsson,card-name : Over-ride default card name
|
||||
|
||||
Example:
|
||||
|
||||
sound {
|
||||
compatible = "stericsson,snd-soc-mop500";
|
||||
|
||||
stericsson,cpu-dai = <&msp1 &msp3>;
|
||||
stericsson,audio-codec = <&codec>;
|
||||
};
|
||||
|
||||
msp1: msp@80124000 {
|
||||
compatible = "stericsson,ux500-msp-i2s";
|
||||
reg = <0x80124000 0x1000>;
|
||||
interrupts = <0 62 0x4>;
|
||||
v-ape-supply = <&db8500_vape_reg>;
|
||||
};
|
||||
|
||||
msp3: msp@80125000 {
|
||||
compatible = "stericsson,ux500-msp-i2s";
|
||||
reg = <0x80125000 0x1000>;
|
||||
interrupts = <0 62 0x4>;
|
||||
v-ape-supply = <&db8500_vape_reg>;
|
||||
};
|
||||
|
||||
codec: ab8500-codec {
|
||||
compatible = "stericsson,ab8500-codec";
|
||||
stericsson,earpeice-cmv = <950>; /* Units in mV. */
|
||||
};
|
43
Documentation/devicetree/bindings/sound/ux500-msp.txt
Normal file
43
Documentation/devicetree/bindings/sound/ux500-msp.txt
Normal file
|
@ -0,0 +1,43 @@
|
|||
* ux500 MSP (CPU-side Digital Audio Interface)
|
||||
|
||||
Required properties:
|
||||
- compatible :"stericsson,ux500-msp-i2s"
|
||||
- reg : Physical base address and length of the device's registers.
|
||||
|
||||
Optional properties:
|
||||
- interrupts : The interrupt output from the device.
|
||||
- interrupt-parent : The parent interrupt controller.
|
||||
- <name>-supply : Phandle to the regulator <name> supply
|
||||
|
||||
Example:
|
||||
|
||||
sound {
|
||||
compatible = "stericsson,snd-soc-mop500";
|
||||
|
||||
stericsson,platform-pcm-dma = <&pcm>;
|
||||
stericsson,cpu-dai = <&msp1 &msp3>;
|
||||
stericsson,audio-codec = <&codec>;
|
||||
};
|
||||
|
||||
pcm: ux500-pcm {
|
||||
compatible = "stericsson,ux500-pcm";
|
||||
};
|
||||
|
||||
msp1: msp@80124000 {
|
||||
compatible = "stericsson,ux500-msp-i2s";
|
||||
reg = <0x80124000 0x1000>;
|
||||
interrupts = <0 62 0x4>;
|
||||
v-ape-supply = <&db8500_vape_reg>;
|
||||
};
|
||||
|
||||
msp3: msp@80125000 {
|
||||
compatible = "stericsson,ux500-msp-i2s";
|
||||
reg = <0x80125000 0x1000>;
|
||||
interrupts = <0 62 0x4>;
|
||||
v-ape-supply = <&db8500_vape_reg>;
|
||||
};
|
||||
|
||||
codec: ab8500-codec {
|
||||
compatible = "stericsson,ab8500-codec";
|
||||
stericsson,earpeice-cmv = <950>; /* Units in mV. */
|
||||
};
|
|
@ -7,7 +7,6 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
#include <plat/gpio-nomadik.h>
|
||||
#include <plat/pincfg.h>
|
||||
|
@ -23,53 +22,6 @@
|
|||
#include "devices-db8500.h"
|
||||
#include "pins-db8500.h"
|
||||
|
||||
/* MSP1/3 Tx/Rx usage protection */
|
||||
static DEFINE_SPINLOCK(msp_rxtx_lock);
|
||||
|
||||
/* Reference Count */
|
||||
static int msp_rxtx_ref;
|
||||
|
||||
/* Pin modes */
|
||||
struct pinctrl *msp1_p;
|
||||
struct pinctrl_state *msp1_def;
|
||||
struct pinctrl_state *msp1_sleep;
|
||||
|
||||
int msp13_i2s_init(void)
|
||||
{
|
||||
int retval = 0;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&msp_rxtx_lock, flags);
|
||||
if (msp_rxtx_ref == 0 && !(IS_ERR(msp1_p) || IS_ERR(msp1_def))) {
|
||||
retval = pinctrl_select_state(msp1_p, msp1_def);
|
||||
if (retval)
|
||||
pr_err("could not set MSP1 defstate\n");
|
||||
}
|
||||
if (!retval)
|
||||
msp_rxtx_ref++;
|
||||
spin_unlock_irqrestore(&msp_rxtx_lock, flags);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int msp13_i2s_exit(void)
|
||||
{
|
||||
int retval = 0;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&msp_rxtx_lock, flags);
|
||||
WARN_ON(!msp_rxtx_ref);
|
||||
msp_rxtx_ref--;
|
||||
if (msp_rxtx_ref == 0 && !(IS_ERR(msp1_p) || IS_ERR(msp1_sleep))) {
|
||||
retval = pinctrl_select_state(msp1_p, msp1_sleep);
|
||||
if (retval)
|
||||
pr_err("could not set MSP1 sleepstate\n");
|
||||
}
|
||||
spin_unlock_irqrestore(&msp_rxtx_lock, flags);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static struct stedma40_chan_cfg msp0_dma_rx = {
|
||||
.high_priority = true,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
|
@ -132,8 +84,6 @@ static struct msp_i2s_platform_data msp1_platform_data = {
|
|||
.id = MSP_I2S_1,
|
||||
.msp_i2s_dma_rx = NULL,
|
||||
.msp_i2s_dma_tx = &msp1_dma_tx,
|
||||
.msp_i2s_init = msp13_i2s_init,
|
||||
.msp_i2s_exit = msp13_i2s_exit,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg msp2_dma_rx = {
|
||||
|
@ -219,49 +169,22 @@ static struct msp_i2s_platform_data msp3_platform_data = {
|
|||
.id = MSP_I2S_3,
|
||||
.msp_i2s_dma_rx = &msp1_dma_rx,
|
||||
.msp_i2s_dma_tx = NULL,
|
||||
.msp_i2s_init = msp13_i2s_init,
|
||||
.msp_i2s_exit = msp13_i2s_exit,
|
||||
};
|
||||
|
||||
int mop500_msp_init(struct device *parent)
|
||||
{
|
||||
struct platform_device *msp1;
|
||||
|
||||
pr_info("%s: Register platform-device 'snd-soc-mop500'.\n", __func__);
|
||||
platform_device_register(&snd_soc_mop500);
|
||||
|
||||
pr_info("Initialize MSP I2S-devices.\n");
|
||||
db8500_add_msp_i2s(parent, 0, U8500_MSP0_BASE, IRQ_DB8500_MSP0,
|
||||
&msp0_platform_data);
|
||||
msp1 = db8500_add_msp_i2s(parent, 1, U8500_MSP1_BASE, IRQ_DB8500_MSP1,
|
||||
db8500_add_msp_i2s(parent, 1, U8500_MSP1_BASE, IRQ_DB8500_MSP1,
|
||||
&msp1_platform_data);
|
||||
db8500_add_msp_i2s(parent, 2, U8500_MSP2_BASE, IRQ_DB8500_MSP2,
|
||||
&msp2_platform_data);
|
||||
db8500_add_msp_i2s(parent, 3, U8500_MSP3_BASE, IRQ_DB8500_MSP1,
|
||||
&msp3_platform_data);
|
||||
|
||||
/* Get the pinctrl handle for MSP1 */
|
||||
if (msp1) {
|
||||
msp1_p = pinctrl_get(&msp1->dev);
|
||||
if (IS_ERR(msp1_p))
|
||||
dev_err(&msp1->dev, "could not get MSP1 pinctrl\n");
|
||||
else {
|
||||
msp1_def = pinctrl_lookup_state(msp1_p,
|
||||
PINCTRL_STATE_DEFAULT);
|
||||
if (IS_ERR(msp1_def)) {
|
||||
dev_err(&msp1->dev,
|
||||
"could not get MSP1 defstate\n");
|
||||
}
|
||||
msp1_sleep = pinctrl_lookup_state(msp1_p,
|
||||
PINCTRL_STATE_SLEEP);
|
||||
if (IS_ERR(msp1_sleep))
|
||||
dev_err(&msp1->dev,
|
||||
"could not get MSP1 idlestate\n");
|
||||
}
|
||||
}
|
||||
|
||||
pr_info("%s: Register platform-device 'ux500-pcm'\n", __func__);
|
||||
platform_device_register(&ux500_pcm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -22,8 +22,6 @@ struct msp_i2s_platform_data {
|
|||
enum msp_i2s_id id;
|
||||
struct stedma40_chan_cfg *msp_i2s_dma_rx;
|
||||
struct stedma40_chan_cfg *msp_i2s_dma_tx;
|
||||
int (*msp_i2s_init) (void);
|
||||
int (*msp_i2s_exit) (void);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,7 +23,8 @@ enum amic_type {
|
|||
/* Mic-biases */
|
||||
enum amic_micbias {
|
||||
AMIC_MICBIAS_VAMIC1,
|
||||
AMIC_MICBIAS_VAMIC2
|
||||
AMIC_MICBIAS_VAMIC2,
|
||||
AMIC_MICBIAS_UNKNOWN
|
||||
};
|
||||
|
||||
/* Bias-voltage */
|
||||
|
@ -31,7 +32,8 @@ enum ear_cm_voltage {
|
|||
EAR_CMV_0_95V,
|
||||
EAR_CMV_1_10V,
|
||||
EAR_CMV_1_27V,
|
||||
EAR_CMV_1_58V
|
||||
EAR_CMV_1_58V,
|
||||
EAR_CMV_UNKNOWN
|
||||
};
|
||||
|
||||
/* Analog microphone settings */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue