[alsa-devel] [PATCH 00/18] Configure ux500 Audio Drivers for Device Tree
This patch-set sees many of the ux500 related Audio drivers gain Device Tree enablement. There are also some fixes to issues which where encountered along the way.
Documentation/devicetree/bindings/sound/ux500.txt | 62 +++++ arch/arm/boot/dts/db8500.dtsi | 48 ++++ arch/arm/mach-ux500/Kconfig | 1 + arch/arm/mach-ux500/Makefile | 2 +- arch/arm/mach-ux500/board-mop500-audio.c | 194 +++++++++++++++ arch/arm/mach-ux500/board-mop500-msp.c | 267 --------------------- arch/arm/mach-ux500/board-mop500-msp.h | 14 -- arch/arm/mach-ux500/board-mop500.c | 22 +- arch/arm/mach-ux500/board-mop500.h | 6 + arch/arm/mach-ux500/include/mach/msp.h | 3 +- include/linux/mfd/abx500/ab8500-codec.h | 6 +- sound/soc/codecs/ab8500-codec.c | 81 +++++++ sound/soc/ux500/mop500.c | 41 ++++ sound/soc/ux500/ux500_msp_dai.c | 6 + sound/soc/ux500/ux500_msp_i2s.c | 114 +++++++-- sound/soc/ux500/ux500_msp_i2s.h | 3 +- sound/soc/ux500/ux500_pcm.c | 6 + 17 files changed, 561 insertions(+), 315 deletions(-)
Also explains the related AB8500 CODEC configuration properties.
Signed-off-by: Lee Jones lee.jones@linaro.org --- Documentation/devicetree/bindings/sound/ux500.txt | 62 +++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/ux500.txt
diff --git a/Documentation/devicetree/bindings/sound/ux500.txt b/Documentation/devicetree/bindings/sound/ux500.txt new file mode 100644 index 0000000..af1c902 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ux500.txt @@ -0,0 +1,62 @@ +* ux500 Audio Driver and ab8500 Audio CODEC + +Required properties: + - compatible: + - Machine Driver : "stericsson,snd-soc-mop500" + - CPU-side DAI : "stericsson,ux500-msp-i2s" + - DMA (platform) : "stericsson,ux500-pcm" + - Audio CODEC : "stericsson,ab8500-codec" + +Optional properties: + - reg : Physical base address and length of the device's registers. + - interrupts : The interrupt outputs from the device. + - interrupt-parent : The parent interrupt controller. + - <name>-supply : Phandle to the regulator <name> supply + +Non-standard properties: + - Machine Driver: + - stericsson,platform-pcm-dma : Phandle to the DMA (platform) node + - stericsson,cpu-dai : Phandle to the CPU-side DAI + - stericsson,audio-codec : Phandle to the Audio CODEC + - CPU-side DAI: + - stericcson,use-pinctrl : Indicates whether an MSP port has pinctrl support + - Audio CODEC: + - stericsson,amic[1|2]-type-single-ended : Single-ended Analoge Mic (default: differential) + - stericsson,amic1a-bias-vamic2 : Analoge Mic wishes to use a non-standard Vamic + - stericsson,amic1b-bias-vamic2 : Analoge Mic wishes to use a non-standard Vamic + - stericsson,amic2-bias-vamic1 : Analoge Mic wishes to use a non-standard Vamic + - stericsson,earpeice-cmv : Earpeice voltage (only: 950 | 1100 | 1270 | 1580) + +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>; + stericcson,use-pinctrl; + }; + + 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. */ + };
On Fri, Jul 27, 2012 at 01:45:45PM +0100, Lee Jones wrote:
+++ b/Documentation/devicetree/bindings/sound/ux500.txt @@ -0,0 +1,62 @@ +* ux500 Audio Driver and ab8500 Audio CODEC
+Required properties:
- compatible:
- Machine Driver : "stericsson,snd-soc-mop500"
- CPU-side DAI : "stericsson,ux500-msp-i2s"
- DMA (platform) : "stericsson,ux500-pcm"
- Audio CODEC : "stericsson,ab8500-codec"
What is this a binding document for? It looks like the binding for a machine driver...
+Optional properties:
- reg : Physical base address and length of the device's registers.
- interrupts : The interrupt outputs from the device.
- interrupt-parent : The parent interrupt controller.
- <name>-supply : Phandle to the regulator <name> supply
...but these don't look anything like machine driver properties.
On 29/07/12 21:31, Mark Brown wrote:
On Fri, Jul 27, 2012 at 01:45:45PM +0100, Lee Jones wrote:
+++ b/Documentation/devicetree/bindings/sound/ux500.txt @@ -0,0 +1,62 @@ +* ux500 Audio Driver and ab8500 Audio CODEC
+Required properties:
- compatible:
- Machine Driver : "stericsson,snd-soc-mop500"
- CPU-side DAI : "stericsson,ux500-msp-i2s"
- DMA (platform) : "stericsson,ux500-pcm"
- Audio CODEC : "stericsson,ab8500-codec"
What is this a binding document for? It looks like the binding for a machine driver...
No, it's a binding document for all of the ux500 driver and CODEC blocks. Do you really want me to split it all up? I think the only component which could be sanely split-out is the ab8500-codec, which could (should?) live in [1].
+Optional properties:
- reg : Physical base address and length of the device's registers.
- interrupts : The interrupt outputs from the device.
- interrupt-parent : The parent interrupt controller.
- <name>-supply : Phandle to the regulator <name> supply
...but these don't look anything like machine driver properties.
These properties are relevant for some, but not all of the components above, hence why the are listed at 'optional properties'.
[1] Documentation/devicetree/bindings/mfd/ab8500.
On Mon, Jul 30, 2012 at 08:38:49AM +0100, Lee Jones wrote:
On 29/07/12 21:31, Mark Brown wrote:
On Fri, Jul 27, 2012 at 01:45:45PM +0100, Lee Jones wrote:
- Machine Driver : "stericsson,snd-soc-mop500"
- CPU-side DAI : "stericsson,ux500-msp-i2s"
- DMA (platform) : "stericsson,ux500-pcm"
- Audio CODEC : "stericsson,ab8500-codec"
What is this a binding document for? It looks like the binding for a machine driver...
No, it's a binding document for all of the ux500 driver and CODEC blocks. Do you really want me to split it all up? I think the only component which could be sanely split-out is the ab8500-codec, which could (should?) live in [1].
Yes, of course! Each device will have a separate binding with different requirements.
These properties are relevant for some, but not all of the components above, hence why the are listed at 'optional properties'.
Which is part of the problem here, it makes it much harder to tell what you need to do for the individual devices.
On 30/07/12 14:48, Mark Brown wrote:
On Mon, Jul 30, 2012 at 08:38:49AM +0100, Lee Jones wrote:
On 29/07/12 21:31, Mark Brown wrote:
On Fri, Jul 27, 2012 at 01:45:45PM +0100, Lee Jones wrote:
- Machine Driver : "stericsson,snd-soc-mop500"
- CPU-side DAI : "stericsson,ux500-msp-i2s"
- DMA (platform) : "stericsson,ux500-pcm"
- Audio CODEC : "stericsson,ab8500-codec"
What is this a binding document for? It looks like the binding for a machine driver...
No, it's a binding document for all of the ux500 driver and CODEC blocks. Do you really want me to split it all up? I think the only component which could be sanely split-out is the ab8500-codec, which could (should?) live in [1].
Yes, of course! Each device will have a separate binding with different requirements.
These properties are relevant for some, but not all of the components above, hence why the are listed at 'optional properties'.
Which is part of the problem here, it makes it much harder to tell what you need to do for the individual devices.
Once again, I'll split them out, but I think there are people talking about documentation consolidation, as it's going to become very messy, very quickly if we keep adding new files for each device. Soon the Documentation directory will be as large as the driver base. :)
On Mon, Jul 30, 2012 at 03:32:08PM +0100, Lee Jones wrote:
On 30/07/12 14:48, Mark Brown wrote:
Which is part of the problem here, it makes it much harder to tell what you need to do for the individual devices.
Once again, I'll split them out, but I think there are people talking about documentation consolidation, as it's going to become very messy, very quickly if we keep adding new files for each device. Soon the Documentation directory will be as large as the driver base. :)
Well, that's device tree for you. You can probably get away with a single document if there's no differences but as soon as you get into anything where you've got custom properties and no overlap you need to start splitting things out.
In the initial submission of the MSP driver msp1 and msp3's associated pinctrl mechanism was passed back to platform code using a plat_init() call-back routine, but it has no place in platform code. The MSP driver should set this up for the appropriate ports. Instead we use a use_pinctrl identifier which is passed from platform_data/Device Tree which indicates which ports should use pinctrl.
Signed-off-by: Lee Jones lee.jones@linaro.org --- arch/arm/mach-ux500/board-mop500-msp.c | 77 ++---------------------------- arch/arm/mach-ux500/include/mach/msp.h | 3 +- sound/soc/ux500/ux500_msp_i2s.c | 81 +++++++++++++++++++++++++------- sound/soc/ux500/ux500_msp_i2s.h | 3 +- 4 files changed, 70 insertions(+), 94 deletions(-)
diff --git a/arch/arm/mach-ux500/board-mop500-msp.c b/arch/arm/mach-ux500/board-mop500-msp.c index 1b6a193..a740e8a 100644 --- a/arch/arm/mach-ux500/board-mop500-msp.c +++ b/arch/arm/mach-ux500/board-mop500-msp.c @@ -23,53 +23,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 +85,7 @@ 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, + .use_pinctrl = true, };
static struct stedma40_chan_cfg msp2_dma_rx = { @@ -219,47 +171,24 @@ 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, + .use_pinctrl = true, };
int mop500_msp_init(struct device *parent) { - struct platform_device *msp1; - pr_info("%s: Register platform-device 'snd-soc-u8500'.\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);
diff --git a/arch/arm/mach-ux500/include/mach/msp.h b/arch/arm/mach-ux500/include/mach/msp.h index 798be19..95b7deb 100644 --- a/arch/arm/mach-ux500/include/mach/msp.h +++ b/arch/arm/mach-ux500/include/mach/msp.h @@ -22,8 +22,7 @@ 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); + bool use_pinctrl; };
#endif diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index 36be11e..72ad6e8 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c @@ -15,6 +15,7 @@
#include <linux/module.h> #include <linux/platform_device.h> +#include <linux/pinctrl/consumer.h> #include <linux/delay.h> #include <linux/slab.h>
@@ -25,6 +26,17 @@
#include "ux500_msp_i2s.h"
+/* MSP1/3 Tx/Rx usage protection */ +static DEFINE_SPINLOCK(msp_rxtx_lock); + +/* Pin modes */ +struct pinctrl *pinctrl_p; +struct pinctrl_state *pinctrl_def; +struct pinctrl_state *pinctrl_sleep; + +/* Reference Count */ +int pinctrl_rxtx_ref; + /* Protocol desciptors */ static const struct msp_protdesc prot_descs[] = { { /* I2S */ @@ -352,17 +364,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 && msp->use_pinctrl) { + spin_lock_irqsave(&msp_rxtx_lock, flags); + if (pinctrl_rxtx_ref == 0 && + !(IS_ERR(pinctrl_p) || IS_ERR(pinctrl_def))) { + retval = pinctrl_select_state(pinctrl_p, + pinctrl_def); + if (retval) + pr_err("could not set MSP defstate\n"); } + if (!retval) + pinctrl_rxtx_ref++; + spin_unlock_irqrestore(&msp_rxtx_lock, flags); }
/* Configure msp with protocol dependent settings */ @@ -620,7 +638,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 +650,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(!pinctrl_rxtx_ref); + pinctrl_rxtx_ref--; + if (msp->use_pinctrl && pinctrl_rxtx_ref == 0 && + !(IS_ERR(pinctrl_p) || IS_ERR(pinctrl_sleep))) { + retval = pinctrl_select_state(pinctrl_p, + 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); @@ -667,6 +693,7 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, struct resource *res = NULL; struct i2s_controller *i2s_cont; struct ux500_msp *msp; + static int initialised = false;
dev_dbg(&pdev->dev, "%s: Enter (name: %s, id: %d).\n", __func__, pdev->name, platform_data->id); @@ -678,8 +705,7 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
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->use_pinctrl = platform_data->use_pinctrl; msp->dma_cfg_rx = platform_data->msp_i2s_dma_rx; msp->dma_cfg_tx = platform_data->msp_i2s_dma_tx;
@@ -717,6 +743,29 @@ 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;
+ /* MSP1 and MSP3 share pins, so we only need to initialise pinctrl once. */ + if (msp->use_pinctrl && !initialised) { + pinctrl_p = pinctrl_get(msp->dev); + if (IS_ERR(pinctrl_p)) + dev_err(&pdev->dev, "could not get MSP pinctrl\n"); + else { + pinctrl_def = pinctrl_lookup_state(pinctrl_p, + PINCTRL_STATE_DEFAULT); + if (IS_ERR(pinctrl_def)) { + dev_err(&pdev->dev, + "could not get MSP defstate (%li)\n", + PTR_ERR(pinctrl_def)); + } + pinctrl_sleep = pinctrl_lookup_state(pinctrl_p, + PINCTRL_STATE_SLEEP); + if (IS_ERR(pinctrl_sleep)) + dev_err(&pdev->dev, + "could not get MSP idlestate (%li)\n", + PTR_ERR(pinctrl_def)); + } + initialised = true; + } + return 0;
err_i2s_cont: diff --git a/sound/soc/ux500/ux500_msp_i2s.h b/sound/soc/ux500/ux500_msp_i2s.h index 2d9136d..aec02b5 100644 --- a/sound/soc/ux500/ux500_msp_i2s.h +++ b/sound/soc/ux500/ux500_msp_i2s.h @@ -524,14 +524,13 @@ 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; + bool use_pinctrl; };
struct ux500_msp_dma_params {
Here we ensure that the MOP500 audio driver will be probed during a Device Tree boot. We also parse the sound node to link together the codec, dma and the CPU-side Digital Audio Interface.
Signed-off-by: Lee Jones lee.jones@linaro.org --- sound/soc/ux500/mop500.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+)
diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c index 31c4d26..d84a073 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,14 +57,48 @@ 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, *platform_np, *msp_np[2]; + int i; + + platform_np = of_parse_phandle(np, "platform-pcm-dma", 0); + msp_np[0] = of_parse_phandle(np, "cpu-dai", 0); + msp_np[1] = of_parse_phandle(np, "cpu-dai", 1); + codec_np = of_parse_phandle(np, "audio-codec", 0); + + if (!(platform_np && 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].platform_of_node = platform_np; + mop500_dai_links[i].platform_name = NULL; + 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; + } + + 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__);
+ if (np) { + ret = mop500_of_probe(pdev, np); + if (ret) + return ret; + } + mop500_card.dev = &pdev->dev;
dev_dbg(&pdev->dev, "%s: Card %s: Set platform drvdata.\n", @@ -101,10 +136,16 @@ static int __devexit mop500_remove(struct platform_device *pdev) 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),
This simple patch ensures the PCM driver will be probed during boot-up when Device Tree is enabled.
Signed-off-by: Lee Jones lee.jones@linaro.org --- sound/soc/ux500/ux500_pcm.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c index 1a04e24..557da2d 100644 --- a/sound/soc/ux500/ux500_pcm.c +++ b/sound/soc/ux500/ux500_pcm.c @@ -304,10 +304,16 @@ static int __devinit ux500_pcm_drv_remove(struct platform_device *pdev) return 0; }
+static const struct of_device_id ux500_pcm_match[] = { + { .compatible = "stericsson,ux500-pcm", }, + {}, +}; + static struct platform_driver ux500_pcm_driver = { .driver = { .name = "ux500-pcm", .owner = THIS_MODULE, + .of_match_table = ux500_pcm_match, },
.probe = ux500_pcm_drv_probe,
Register both parts of the MSP driver from Device Tree so that they are probed when Device Tree is enabled. Also, as there is platform data involved, we ensure that there is allocated memory to place the configuration into and that the correct information is extracted from the DT binary.
Signed-off-by: Lee Jones lee.jones@linaro.org --- sound/soc/ux500/ux500_msp_dai.c | 6 ++++++ sound/soc/ux500/ux500_msp_i2s.c | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 772cb19..0f7dd49 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_i2c_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_i2c_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 72ad6e8..1ecdec0 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c @@ -18,6 +18,7 @@ #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> @@ -685,6 +686,16 @@ int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir)
}
+void ux500_msp_i2s_of_init_msp(struct platform_device *pdev, + struct ux500_msp *msp, + struct device_node *np) +{ + if (of_get_property(np, "stericsson,use-pinctrl", NULL)) + msp->use_pinctrl = true; + else + msp->use_pinctrl = false; +} + int ux500_msp_i2s_init_msp(struct platform_device *pdev, struct ux500_msp **msp_p, struct msp_i2s_platform_data *platform_data) @@ -692,17 +703,33 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, int ret = 0; struct resource *res = NULL; struct i2s_controller *i2s_cont; + struct device_node *np = pdev->dev.of_node; struct ux500_msp *msp; static int initialised = false;
- 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; + } + ux500_msp_i2s_of_init_msp(pdev, msp, np); + } 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->use_pinctrl = platform_data->use_pinctrl;
On Fri, Jul 27, 2012 at 01:45:49PM +0100, Lee Jones wrote:
- if (of_get_property(np, "stericsson,use-pinctrl", NULL))
msp->use_pinctrl = true;
- else
msp->use_pinctrl = false;
I don't recall seeing any response to my query about this on the first iteration. Please don't just ignore review comments.
On 29/07/12 21:42, Mark Brown wrote:
On Fri, Jul 27, 2012 at 01:45:49PM +0100, Lee Jones wrote:
- if (of_get_property(np, "stericsson,use-pinctrl", NULL))
msp->use_pinctrl = true;
- else
msp->use_pinctrl = false;
I don't recall seeing any response to my query about this on the first iteration. Please don't just ignore review comments.
It wasn't intentional. I must have missed it before.
This doesn't seem particularly sane... why is this conditional?
It's conditional because only MSP1 and MSP3 have pinctrl support.
On Mon, Jul 30, 2012 at 07:53:36AM +0100, Lee Jones wrote:
On 29/07/12 21:42, Mark Brown wrote:
- if (of_get_property(np, "stericsson,use-pinctrl", NULL))
This doesn't seem particularly sane... why is this conditional?
It's conditional because only MSP1 and MSP3 have pinctrl support.
Why does the driver care - doesn't the pinctrl abstraction and/or bindings handle this sensibly?
On 30/07/12 14:39, Mark Brown wrote:
On Mon, Jul 30, 2012 at 07:53:36AM +0100, Lee Jones wrote:
On 29/07/12 21:42, Mark Brown wrote:
- if (of_get_property(np, "stericsson,use-pinctrl", NULL))
This doesn't seem particularly sane... why is this conditional?
It's conditional because only MSP1 and MSP3 have pinctrl support.
Why does the driver care - doesn't the pinctrl abstraction and/or bindings handle this sensibly?
Not when I tested it. pinctrl_get() came back !IS_ERR() for MSP0, MSP2 & MSP3, then when it went on to pinctrl_lookup_state(), only then did it fail. Would it be more sane to retract the error messages and just let it fail silently? It's either that or have lots of "could not get MSP defstate" clogging up the log.
On Mon, Jul 30, 2012 at 02:57:12PM +0100, Lee Jones wrote:
On 30/07/12 14:39, Mark Brown wrote:
Why does the driver care - doesn't the pinctrl abstraction and/or bindings handle this sensibly?
Not when I tested it. pinctrl_get() came back !IS_ERR() for MSP0, MSP2 & MSP3, then when it went on to pinctrl_lookup_state(), only then did it fail. Would it be more sane to retract the error messages and just let it fail silently? It's either that or have lots of "could not get MSP defstate" clogging up the log.
This sounds to me like we should be ensuring that there's a single fixed state available for these MSPs (representing the fact that the pins are always in the right mode) in the pinctrl bindings.
As with several of other changes for this platform it seems like we need to think carefully about the abstraction level we're working at.
We continue to allow the AB8500 CODEC to be registered via the AB8500 Multi Functional Device API, only this time we extract its configuration from the Device Tree binary.
Signed-off-by: Lee Jones lee.jones@linaro.org --- include/linux/mfd/abx500/ab8500-codec.h | 6 ++- sound/soc/codecs/ab8500-codec.c | 81 +++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-)
diff --git a/include/linux/mfd/abx500/ab8500-codec.h b/include/linux/mfd/abx500/ab8500-codec.h index dc65292..d707941 100644 --- a/include/linux/mfd/abx500/ab8500-codec.h +++ b/include/linux/mfd/abx500/ab8500-codec.h @@ -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 */ diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 23b4018..fa80961 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 = (struct ab8500_platform_data *)dev_get_platdata(dev->parent);
+ if (np) { + if (!pdata) + pdata = devm_kzalloc(dev, + sizeof(struct ab8500_platform_data), + GFP_KERNEL); + + if (!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; + } + } + /* Inform SoC Core that we have our own I/O arrangements. */ codec->control_data = (void *)true;
This patch contains a couple of general MSP clean-ups pertaining to layout changes and changing functions to be void instead of int instead of regardlessly returning '0'.
Signed-off-by: Lee Jones lee.jones@linaro.org --- arch/arm/mach-ux500/board-mop500-msp.c | 26 ++++++++++++-------------- arch/arm/mach-ux500/board-mop500-msp.h | 14 -------------- arch/arm/mach-ux500/board-mop500.c | 1 - arch/arm/mach-ux500/board-mop500.h | 3 +++ 4 files changed, 15 insertions(+), 29 deletions(-) delete mode 100644 arch/arm/mach-ux500/board-mop500-msp.h
diff --git a/arch/arm/mach-ux500/board-mop500-msp.c b/arch/arm/mach-ux500/board-mop500-msp.c index a740e8a..719db15 100644 --- a/arch/arm/mach-ux500/board-mop500-msp.c +++ b/arch/arm/mach-ux500/board-mop500-msp.c @@ -144,21 +144,21 @@ static struct platform_device *db8500_add_msp_i2s(struct device *parent, }
/* Platform device for ASoC U8500 machine */ -static struct platform_device snd_soc_u8500 = { - .name = "snd-soc-u8500", - .id = 0, - .dev = { - .platform_data = NULL, - }, +static struct platform_device snd_soc_mop500 = { + .name = "snd-soc-mop500", + .id = 0, + .dev = { + .platform_data = NULL, + }, };
/* Platform device for Ux500-PCM */ static struct platform_device ux500_pcm = { - .name = "ux500-pcm", - .id = 0, - .dev = { - .platform_data = NULL, - }, + .name = "ux500-pcm", + .id = 0, + .dev = { + .platform_data = NULL, + }, };
static struct msp_i2s_platform_data msp2_platform_data = { @@ -174,7 +174,7 @@ static struct msp_i2s_platform_data msp3_platform_data = { .use_pinctrl = true, };
-int mop500_msp_init(struct device *parent) +void mop500_msp_init(struct device *parent) { pr_info("%s: Register platform-device 'snd-soc-u8500'.\n", __func__); platform_device_register(&snd_soc_mop500); @@ -191,6 +191,4 @@ int mop500_msp_init(struct device *parent)
pr_info("%s: Register platform-device 'ux500-pcm'\n", __func__); platform_device_register(&ux500_pcm); - - return 0; } diff --git a/arch/arm/mach-ux500/board-mop500-msp.h b/arch/arm/mach-ux500/board-mop500-msp.h deleted file mode 100644 index 6fcfb5e..0000000 --- a/arch/arm/mach-ux500/board-mop500-msp.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2012 - * - * Author: Ola Lilja ola.o.lilja@stericsson.com, - * for ST-Ericsson. - * - * License terms: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - */ - -void mop500_msp_init(struct device *parent); diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 87a5cd7..6f53a6f 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -54,7 +54,6 @@ #include "devices-db8500.h" #include "board-mop500.h" #include "board-mop500-regulators.h" -#include "board-mop500-msp.h"
static struct gpio_led snowball_led_array[] = { { diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h index d04a8e6..1d7316b 100644 --- a/arch/arm/mach-ux500/board-mop500.h +++ b/arch/arm/mach-ux500/board-mop500.h @@ -92,6 +92,9 @@ void __init mop500_stuib_init(void); void __init mop500_pinmaps_init(void); void __init snowball_pinmaps_init(void); void __init hrefv60_pinmaps_init(void); +void mop500_msp_init(struct device *parent); +/* Due for removal once the MSP driver has been fully DT:ed. */ +void mop500_of_msp_init(struct device *parent);
int __init mop500_uib_init(void); void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
Ensure correct probing and pass though important configuration options to the AB8500 CODEC driver when DT is enabled
Signed-off-by: Lee Jones lee.jones@linaro.org --- arch/arm/boot/dts/db8500.dtsi | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/arch/arm/boot/dts/db8500.dtsi b/arch/arm/boot/dts/db8500.dtsi index 7279165..a3bee0a 100644 --- a/arch/arm/boot/dts/db8500.dtsi +++ b/arch/arm/boot/dts/db8500.dtsi @@ -370,6 +370,12 @@ compatible = "stericsson,ab8500-debug"; };
+ codec: ab8500-codec { + compatible = "stericsson,ab8500-codec"; + + stericsson,earpeice-cmv = <950>; /* Units in mV. */ + }; + ab8500-regulators { compatible = "stericsson,ab8500-regulator";
We've done this before and it worked well last time. Here we're duplicating a complex registration function to ease the process of enabling it for Device Tree. As there are quite a few steps taken during the registration process, it makes sense to break them up into more manageable chunks. This patch will aid us.
Signed-off-by: Lee Jones lee.jones@linaro.org --- arch/arm/mach-ux500/board-mop500-msp.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
diff --git a/arch/arm/mach-ux500/board-mop500-msp.c b/arch/arm/mach-ux500/board-mop500-msp.c index 719db15..ec5857b 100644 --- a/arch/arm/mach-ux500/board-mop500-msp.c +++ b/arch/arm/mach-ux500/board-mop500-msp.c @@ -174,6 +174,26 @@ static struct msp_i2s_platform_data msp3_platform_data = { .use_pinctrl = true, };
+/* Due for removal once the MSP driver has been fully DT:ed. */ +void mop500_of_msp_init(struct device *parent) +{ + pr_info("%s: Register platform-device 'snd-soc-u8500'.\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); + 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); + + pr_info("%s: Register platform-device 'ux500-pcm'\n", __func__); + platform_device_register(&ux500_pcm); +} + void mop500_msp_init(struct device *parent) { pr_info("%s: Register platform-device 'snd-soc-u8500'.\n", __func__);
The current kernel commandline for ux500 based devices includes hard-coded allocations for things like mali and hwmem, which actually run over lowmem. Here we enable highmem in order to avoid memory corruption errors.
Signed-off-by: Lee Jones lee.jones@linaro.org --- arch/arm/mach-ux500/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index c013bbf..f51c351 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -28,6 +28,7 @@ config MACH_MOP500 select I2C select I2C_NOMADIK select SOC_BUS + select HIGHMEM help Include support for the MOP500 development platform.
On Fri, Jul 27, 2012 at 01:45:54PM +0100, Lee Jones wrote:
The current kernel commandline for ux500 based devices includes hard-coded allocations for things like mali and hwmem, which actually run over lowmem. Here we enable highmem in order to avoid memory corruption errors.
This appears to be at best tangentially related to the rest of the series, are you sure it shouldn't be being sent separately as a bugfix?
On 29/07/12 21:45, Mark Brown wrote:
On Fri, Jul 27, 2012 at 01:45:54PM +0100, Lee Jones wrote:
The current kernel commandline for ux500 based devices includes hard-coded allocations for things like mali and hwmem, which actually run over lowmem. Here we enable highmem in order to avoid memory corruption errors.
This appears to be at best tangentially related to the rest of the series, are you sure it shouldn't be being sent separately as a bugfix?
Yes, it should. I'll shift it.
It isn't currently possible to pass all platform specific configuration though Device Tree. Thinks like device names used in the clock infrastructure, call-backs and DMA information have to be passed in via AUXDATA structures and the MSP is no exception. Here we're passing DMA settings.
Signed-off-by: Lee Jones lee.jones@linaro.org --- arch/arm/mach-ux500/board-mop500-msp.c | 8 ++++---- arch/arm/mach-ux500/board-mop500.c | 9 +++++++++ arch/arm/mach-ux500/board-mop500.h | 5 +++++ 3 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-ux500/board-mop500-msp.c b/arch/arm/mach-ux500/board-mop500-msp.c index ec5857b..7691f71 100644 --- a/arch/arm/mach-ux500/board-mop500-msp.c +++ b/arch/arm/mach-ux500/board-mop500-msp.c @@ -49,7 +49,7 @@ static struct stedma40_chan_cfg msp0_dma_tx = { /* data_width is set during configuration */ };
-static struct msp_i2s_platform_data msp0_platform_data = { +struct msp_i2s_platform_data msp0_platform_data = { .id = MSP_I2S_0, .msp_i2s_dma_rx = &msp0_dma_rx, .msp_i2s_dma_tx = &msp0_dma_tx, @@ -81,7 +81,7 @@ static struct stedma40_chan_cfg msp1_dma_tx = { /* data_width is set during configuration */ };
-static struct msp_i2s_platform_data msp1_platform_data = { +struct msp_i2s_platform_data msp1_platform_data = { .id = MSP_I2S_1, .msp_i2s_dma_rx = NULL, .msp_i2s_dma_tx = &msp1_dma_tx, @@ -161,13 +161,13 @@ static struct platform_device ux500_pcm = { }, };
-static struct msp_i2s_platform_data msp2_platform_data = { +struct msp_i2s_platform_data msp2_platform_data = { .id = MSP_I2S_2, .msp_i2s_dma_rx = &msp2_dma_rx, .msp_i2s_dma_tx = &msp2_dma_tx, };
-static struct msp_i2s_platform_data msp3_platform_data = { +struct msp_i2s_platform_data msp3_platform_data = { .id = MSP_I2S_3, .msp_i2s_dma_rx = &msp1_dma_rx, .msp_i2s_dma_tx = NULL, diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 6f53a6f..d455a61 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -753,6 +753,15 @@ struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = { OF_DEV_AUXDATA("st,nomadik-i2c", 0x8012a000, "nmk-i2c.4", NULL), /* Requires device name bindings. */ OF_DEV_AUXDATA("stericsson,nmk_pinctrl", 0, "pinctrl-db8500", NULL), + /* Requires clock name and DMA bindings. */ + OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80123000, + "ux500-msp-i2s.0", &msp0_platform_data), + OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80124000, + "ux500-msp-i2s.1", &msp1_platform_data), + OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80117000, + "ux500-msp-i2s.2", &msp2_platform_data), + OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80125000, + "ux500-msp-i2s.3", &msp3_platform_data), {}, };
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h index 1d7316b..3fbf48f 100644 --- a/arch/arm/mach-ux500/board-mop500.h +++ b/arch/arm/mach-ux500/board-mop500.h @@ -9,6 +9,7 @@
/* For NOMADIK_NR_GPIO */ #include <mach/irqs.h> +#include <mach/msp.h> #include <linux/amba/mmci.h>
/* Snowball specific GPIO assignments, this board has no GPIO expander */ @@ -81,6 +82,10 @@ struct device; struct i2c_board_info; extern struct mmci_platform_data mop500_sdi0_data; extern struct mmci_platform_data mop500_sdi4_data; +extern struct msp_i2s_platform_data msp0_platform_data; +extern struct msp_i2s_platform_data msp1_platform_data; +extern struct msp_i2s_platform_data msp2_platform_data; +extern struct msp_i2s_platform_data msp3_platform_data; extern struct arm_pmu_platdata db8500_pmu_platdata;
extern void mop500_sdi_init(struct device *parent);
In this patch we prevent MOP500 driver registration from platform code and rely solely on Device Tree to do the probing for us.
Signed-off-by: Lee Jones lee.jones@linaro.org --- arch/arm/mach-ux500/board-mop500-msp.c | 3 --- 1 file changed, 3 deletions(-)
diff --git a/arch/arm/mach-ux500/board-mop500-msp.c b/arch/arm/mach-ux500/board-mop500-msp.c index 7691f71..1a83fa5 100644 --- a/arch/arm/mach-ux500/board-mop500-msp.c +++ b/arch/arm/mach-ux500/board-mop500-msp.c @@ -177,9 +177,6 @@ struct msp_i2s_platform_data msp3_platform_data = { /* Due for removal once the MSP driver has been fully DT:ed. */ void mop500_of_msp_init(struct device *parent) { - pr_info("%s: Register platform-device 'snd-soc-u8500'.\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);
Nothing special here. We're only providing a compatible string to ensure the driver is probed using a Device Tree boot.
Signed-off-by: Lee Jones lee.jones@linaro.org --- arch/arm/boot/dts/db8500.dtsi | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/arch/arm/boot/dts/db8500.dtsi b/arch/arm/boot/dts/db8500.dtsi index a3bee0a..a3fb05f 100644 --- a/arch/arm/boot/dts/db8500.dtsi +++ b/arch/arm/boot/dts/db8500.dtsi @@ -591,6 +591,10 @@ status = "disabled"; };
+ pcm: ux500-pcm { + compatible = "stericsson,ux500-pcm"; + }; + external-bus@50000000 { compatible = "simple-bus"; reg = <0x50000000 0x4000000>;
On Fri, Jul 27, 2012 at 01:45:57PM +0100, Lee Jones wrote:
Nothing special here. We're only providing a compatible string to ensure the driver is probed using a Device Tree boot.
pcm: ux500-pcm {
compatible = "stericsson,ux500-pcm";
};
One of two things is wrong here. Either you've not provided any information about the hardware so the driver won't be able to work out what to talk to or you've not provided any data so you're registering a purely virtual Linux-internal device via the device tree.
Once more, the idea here is to describe the hardware not to dump Linux's internal data structures into the device tree.
On 29/07/12 21:50, Mark Brown wrote:
On Fri, Jul 27, 2012 at 01:45:57PM +0100, Lee Jones wrote:
Nothing special here. We're only providing a compatible string to ensure the driver is probed using a Device Tree boot.
pcm: ux500-pcm {
compatible = "stericsson,ux500-pcm";
};
One of two things is wrong here. Either you've not provided any information about the hardware so the driver won't be able to work out what to talk to or you've not provided any data so you're registering a purely virtual Linux-internal device via the device tree.
Once more, the idea here is to describe the hardware not to dump Linux's internal data structures into the device tree.
We use it register the driver for probe()ing. In the same way we do for the PMU and Regulators. All three of which actually belong to a different hardware block. Do you know of a better way to register those devices?
On Mon, Jul 30, 2012 at 08:32:43AM +0100, Lee Jones wrote:
On 29/07/12 21:50, Mark Brown wrote:
On Fri, Jul 27, 2012 at 01:45:57PM +0100, Lee Jones wrote:
pcm: ux500-pcm {
compatible = "stericsson,ux500-pcm";
};
One of two things is wrong here. Either you've not provided any information about the hardware so the driver won't be able to work out what to talk to or you've not provided any data so you're registering a purely virtual Linux-internal device via the device tree.
Once more, the idea here is to describe the hardware not to dump Linux's internal data structures into the device tree.
We use it register the driver for probe()ing. In the same way we do for the PMU and Regulators. All three of which actually belong to a different hardware block. Do you know of a better way to register those devices?
You've not identified which of the two cases above we're in... assuming it's a virtal device look at how the DT bindings for the other platforms are doing things.
On 30/07/12 14:40, Mark Brown wrote:
On Mon, Jul 30, 2012 at 08:32:43AM +0100, Lee Jones wrote:
On 29/07/12 21:50, Mark Brown wrote:
On Fri, Jul 27, 2012 at 01:45:57PM +0100, Lee Jones wrote:
pcm: ux500-pcm {
compatible = "stericsson,ux500-pcm";
};
One of two things is wrong here. Either you've not provided any information about the hardware so the driver won't be able to work out what to talk to or you've not provided any data so you're registering a purely virtual Linux-internal device via the device tree.
Once more, the idea here is to describe the hardware not to dump Linux's internal data structures into the device tree.
We use it register the driver for probe()ing. In the same way we do for the PMU and Regulators. All three of which actually belong to a different hardware block. Do you know of a better way to register those devices?
You've not identified which of the two cases above we're in... assuming it's a virtal device look at how the DT bindings for the other platforms are doing things.
I thought it would have been obvious by my response. The PMU seems to be a virtual device with no registers or IRQs.
I've found a DT which seems to do it in the same way as I do 'arch/powerpc/boot/dts/p1022ds.dts', but some others call PCM registration from the CPU-side DAI probe(). Would that be your preference?
On Mon, Jul 30, 2012 at 03:26:58PM +0100, Lee Jones wrote:
On 30/07/12 14:40, Mark Brown wrote:
We use it register the driver for probe()ing. In the same way we do for the PMU and Regulators. All three of which actually belong to a different hardware block. Do you know of a better way to register those devices?
You've not identified which of the two cases above we're in... assuming it's a virtal device look at how the DT bindings for the other platforms are doing things.
I thought it would have been obvious by my response. The PMU seems to be a virtual device with no registers or IRQs.
That's not at all obvious, no.
I've found a DT which seems to do it in the same way as I do 'arch/powerpc/boot/dts/p1022ds.dts', but some others call PCM registration from the CPU-side DAI probe(). Would that be your preference?
Yes, do what the other drivers are doing
In this patch we prevent PCM driver registration from platform code and rely solely on Device Tree to do the probing for us.
Signed-off-by: Lee Jones lee.jones@linaro.org --- arch/arm/mach-ux500/board-mop500-msp.c | 3 --- 1 file changed, 3 deletions(-)
diff --git a/arch/arm/mach-ux500/board-mop500-msp.c b/arch/arm/mach-ux500/board-mop500-msp.c index 1a83fa5..391c129 100644 --- a/arch/arm/mach-ux500/board-mop500-msp.c +++ b/arch/arm/mach-ux500/board-mop500-msp.c @@ -186,9 +186,6 @@ void mop500_of_msp_init(struct device *parent) &msp2_platform_data); db8500_add_msp_i2s(parent, 3, U8500_MSP3_BASE, IRQ_DB8500_MSP1, &msp3_platform_data); - - pr_info("%s: Register platform-device 'ux500-pcm'\n", __func__); - platform_device_register(&ux500_pcm); }
void mop500_msp_init(struct device *parent)
List all four MSP devices which exist on all DB8500 based platforms, to ensure correct device probing and configuration passing when booting with DT.
Signed-off-by: Lee Jones lee.jones@linaro.org --- arch/arm/boot/dts/db8500.dtsi | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
diff --git a/arch/arm/boot/dts/db8500.dtsi b/arch/arm/boot/dts/db8500.dtsi index a3fb05f..b9d4405 100644 --- a/arch/arm/boot/dts/db8500.dtsi +++ b/arch/arm/boot/dts/db8500.dtsi @@ -595,6 +595,36 @@ compatible = "stericsson,ux500-pcm"; };
+ msp0: msp@80123000 { + compatible = "stericsson,ux500-msp-i2s"; + reg = <0x80123000 0x1000>; + interrupts = <0 31 0x4>; + v-ape-supply = <&db8500_vape_reg>; + }; + + msp1: msp@80124000 { + compatible = "stericsson,ux500-msp-i2s"; + reg = <0x80124000 0x1000>; + interrupts = <0 62 0x4>; + v-ape-supply = <&db8500_vape_reg>; + stericcson,use-pinctrl; + }; + + // HDMI sound + msp2: msp@80117000 { + compatible = "stericsson,ux500-msp-i2s"; + reg = <0x80117000 0x1000>; + interrupts = <0 98 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>; + }; + external-bus@50000000 { compatible = "simple-bus"; reg = <0x50000000 0x4000000>;
This patch removes platform device registration of all 4 MSP devices. It also takes care of all redundant infrastructure now that each of the ux500 audio components have been Device Tree enabled.
Signed-off-by: Lee Jones lee.jones@linaro.org --- arch/arm/mach-ux500/board-mop500-msp.c | 14 -------------- arch/arm/mach-ux500/board-mop500.c | 2 -- arch/arm/mach-ux500/board-mop500.h | 2 -- 3 files changed, 18 deletions(-)
diff --git a/arch/arm/mach-ux500/board-mop500-msp.c b/arch/arm/mach-ux500/board-mop500-msp.c index 391c129..c20d5d2 100644 --- a/arch/arm/mach-ux500/board-mop500-msp.c +++ b/arch/arm/mach-ux500/board-mop500-msp.c @@ -174,20 +174,6 @@ struct msp_i2s_platform_data msp3_platform_data = { .use_pinctrl = true, };
-/* Due for removal once the MSP driver has been fully DT:ed. */ -void mop500_of_msp_init(struct device *parent) -{ - pr_info("Initialize MSP I2S-devices.\n"); - db8500_add_msp_i2s(parent, 0, U8500_MSP0_BASE, IRQ_DB8500_MSP0, - &msp0_platform_data); - 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); -} - void mop500_msp_init(struct device *parent) { pr_info("%s: Register platform-device 'snd-soc-u8500'.\n", __func__); diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index d455a61..2ef26c8 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -810,8 +810,6 @@ static void __init u8500_init_machine(void)
mop500_uib_init();
- } else if (of_machine_is_compatible("calaosystems,snowball-a9500")) { - mop500_of_msp_init(parent); } else if (of_machine_is_compatible("st-ericsson,hrefv60+")) { /* * The HREFv60 board removed a GPIO expander and routed diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h index 3fbf48f..e56c983 100644 --- a/arch/arm/mach-ux500/board-mop500.h +++ b/arch/arm/mach-ux500/board-mop500.h @@ -98,8 +98,6 @@ void __init mop500_pinmaps_init(void); void __init snowball_pinmaps_init(void); void __init hrefv60_pinmaps_init(void); void mop500_msp_init(struct device *parent); -/* Due for removal once the MSP driver has been fully DT:ed. */ -void mop500_of_msp_init(struct device *parent);
int __init mop500_uib_init(void); void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
This is the node which links together the platform (PCM), codec (AB8500) and the CPU side Digital Audio Interface (MCP) with the machine driver.
Signed-off-by: Lee Jones lee.jones@linaro.org --- arch/arm/boot/dts/db8500.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/arch/arm/boot/dts/db8500.dtsi b/arch/arm/boot/dts/db8500.dtsi index b9d4405..9d0fba6 100644 --- a/arch/arm/boot/dts/db8500.dtsi +++ b/arch/arm/boot/dts/db8500.dtsi @@ -595,6 +595,14 @@ compatible = "stericsson,ux500-pcm"; };
+ sound { + compatible = "stericsson,snd-soc-mop500"; + + stericsson,platform-pcm-dma = <&pcm>; + stericsson,cpu-dai = <&msp1 &msp3>; + stericsson,audio-codec = <&codec>; + }; + msp0: msp@80123000 { compatible = "stericsson,ux500-msp-i2s"; reg = <0x80123000 0x1000>;
On Fri, Jul 27, 2012 at 01:46:01PM +0100, Lee Jones wrote:
arch/arm/boot/dts/db8500.dtsi | 8 ++++++++
This is a generic DT include file but...
sound {
compatible = "stericsson,snd-soc-mop500";
stericsson,platform-pcm-dma = <&pcm>;
stericsson,cpu-dai = <&msp1 &msp3>;
stericsson,audio-codec = <&codec>;
};
...this is clearly the board-specific setup for the system, showing how the CPU and CODEC are hooked up. This should therefore be in the DT for whatever board this is you're working on.
On 29/07/12 21:52, Mark Brown wrote:
On Fri, Jul 27, 2012 at 01:46:01PM +0100, Lee Jones wrote:
arch/arm/boot/dts/db8500.dtsi | 8 ++++++++
This is a generic DT include file but...
sound {
compatible = "stericsson,snd-soc-mop500";
stericsson,platform-pcm-dma = <&pcm>;
stericsson,cpu-dai = <&msp1 &msp3>;
stericsson,audio-codec = <&codec>;
};
...this is clearly the board-specific setup for the system, showing how the CPU and CODEC are hooked up. This should therefore be in the DT for whatever board this is you're working on.
I don't think it's board specific. I believe this is the setup on all db8500 platforms. I'm happy to be told I'm wrong here, in which case I can move it to the board specific files.
On Mon, Jul 30, 2012 at 08:35:18AM +0100, Lee Jones wrote:
On 29/07/12 21:52, Mark Brown wrote:
...this is clearly the board-specific setup for the system, showing how the CPU and CODEC are hooked up. This should therefore be in the DT for whatever board this is you're working on.
I don't think it's board specific. I believe this is the setup on all db8500 platforms. I'm happy to be told I'm wrong here, in which case I can move it to the board specific files.
I think that's more a sign that all the platforms you've seen are just cut'n'pasted from the reference design than anything else. If the thing you're describing is on the PCB it's generally board specific...
On 30/07/12 14:42, Mark Brown wrote:
On Mon, Jul 30, 2012 at 08:35:18AM +0100, Lee Jones wrote:
On 29/07/12 21:52, Mark Brown wrote:
...this is clearly the board-specific setup for the system, showing how the CPU and CODEC are hooked up. This should therefore be in the DT for whatever board this is you're working on.
I don't think it's board specific. I believe this is the setup on all db8500 platforms. I'm happy to be told I'm wrong here, in which case I can move it to the board specific files.
I think that's more a sign that all the platforms you've seen are just cut'n'pasted from the reference design than anything else. If the thing you're describing is on the PCB it's generally board specific...
I'll split it out into the board file(s) if it makes you happy. I'd rather just get it in and move on to something more productive. We can change it retrospectively if I'm told by someone more knowledgeable that it's 100% common across all platforms.
The 'msp' board file does more than just register MSP devices. It also registers some other components necessary to get audio working on ux500 based platforms; such as the PCM and Machine Drivers. For that reason we're changing the filename to be more encompassing - 'audio'.
Signed-off-by: Lee Jones lee.jones@linaro.org --- arch/arm/mach-ux500/Makefile | 2 +- arch/arm/mach-ux500/board-mop500-audio.c | 194 ++++++++++++++++++++++++++++++ arch/arm/mach-ux500/board-mop500-msp.c | 194 ------------------------------ arch/arm/mach-ux500/board-mop500.c | 10 +- arch/arm/mach-ux500/board-mop500.h | 2 +- 5 files changed, 201 insertions(+), 201 deletions(-) create mode 100644 arch/arm/mach-ux500/board-mop500-audio.c delete mode 100644 arch/arm/mach-ux500/board-mop500-msp.c
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 026086f..1dc2cfa 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -12,6 +12,6 @@ obj-$(CONFIG_MACH_MOP500) += board-mop500.o board-mop500-sdi.o \ board-mop500-uib.o board-mop500-stuib.o \ board-mop500-u8500uib.o \ board-mop500-pins.o \ - board-mop500-msp.o + board-mop500-audio.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/arch/arm/mach-ux500/board-mop500-audio.c b/arch/arm/mach-ux500/board-mop500-audio.c new file mode 100644 index 0000000..4583846 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-audio.c @@ -0,0 +1,194 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: GNU General Public License (GPL), version 2 + */ + +#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> +#include <plat/ste_dma40.h> + +#include <mach/devices.h> +#include <mach/hardware.h> +#include <mach/irqs.h> +#include <mach/msp.h> + +#include "ste-dma40-db8500.h" +#include "board-mop500.h" +#include "devices-db8500.h" +#include "pins-db8500.h" + +static struct stedma40_chan_cfg msp0_dma_rx = { + .high_priority = true, + .dir = STEDMA40_PERIPH_TO_MEM, + + .src_dev_type = DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + /* data_width is set during configuration */ +}; + +static struct stedma40_chan_cfg msp0_dma_tx = { + .high_priority = true, + .dir = STEDMA40_MEM_TO_PERIPH, + + .src_dev_type = STEDMA40_DEV_DST_MEMORY, + .dst_dev_type = DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + /* data_width is set during configuration */ +}; + +struct msp_i2s_platform_data msp0_platform_data = { + .id = MSP_I2S_0, + .msp_i2s_dma_rx = &msp0_dma_rx, + .msp_i2s_dma_tx = &msp0_dma_tx, +}; + +static struct stedma40_chan_cfg msp1_dma_rx = { + .high_priority = true, + .dir = STEDMA40_PERIPH_TO_MEM, + + .src_dev_type = DB8500_DMA_DEV30_MSP3_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + /* data_width is set during configuration */ +}; + +static struct stedma40_chan_cfg msp1_dma_tx = { + .high_priority = true, + .dir = STEDMA40_MEM_TO_PERIPH, + + .src_dev_type = STEDMA40_DEV_DST_MEMORY, + .dst_dev_type = DB8500_DMA_DEV30_MSP1_TX, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + /* data_width is set during configuration */ +}; + +struct msp_i2s_platform_data msp1_platform_data = { + .id = MSP_I2S_1, + .msp_i2s_dma_rx = NULL, + .msp_i2s_dma_tx = &msp1_dma_tx, + .use_pinctrl = true, +}; + +static struct stedma40_chan_cfg msp2_dma_rx = { + .high_priority = true, + .dir = STEDMA40_PERIPH_TO_MEM, + + .src_dev_type = DB8500_DMA_DEV14_MSP2_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + + /* MSP2 DMA doesn't work with PSIZE == 4 on DB8500v2 */ + .src_info.psize = STEDMA40_PSIZE_LOG_1, + .dst_info.psize = STEDMA40_PSIZE_LOG_1, + + /* data_width is set during configuration */ +}; + +static struct stedma40_chan_cfg msp2_dma_tx = { + .high_priority = true, + .dir = STEDMA40_MEM_TO_PERIPH, + + .src_dev_type = STEDMA40_DEV_DST_MEMORY, + .dst_dev_type = DB8500_DMA_DEV14_MSP2_TX, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + .use_fixed_channel = true, + .phy_channel = 1, + + /* data_width is set during configuration */ +}; + +static struct platform_device *db8500_add_msp_i2s(struct device *parent, + int id, + resource_size_t base, int irq, + struct msp_i2s_platform_data *pdata) +{ + struct platform_device *pdev; + struct resource res[] = { + DEFINE_RES_MEM(base, SZ_4K), + DEFINE_RES_IRQ(irq), + }; + + pr_info("Register platform-device 'ux500-msp-i2s', id %d, irq %d\n", + id, irq); + pdev = platform_device_register_resndata(parent, "ux500-msp-i2s", id, + res, ARRAY_SIZE(res), + pdata, sizeof(*pdata)); + if (!pdev) { + pr_err("Failed to register platform-device 'ux500-msp-i2s.%d'!\n", + id); + return NULL; + } + + return pdev; +} + +/* Platform device for ASoC U8500 machine */ +static struct platform_device snd_soc_mop500 = { + .name = "snd-soc-mop500", + .id = 0, + .dev = { + .platform_data = NULL, + }, +}; + +/* Platform device for Ux500-PCM */ +static struct platform_device ux500_pcm = { + .name = "ux500-pcm", + .id = 0, + .dev = { + .platform_data = NULL, + }, +}; + +struct msp_i2s_platform_data msp2_platform_data = { + .id = MSP_I2S_2, + .msp_i2s_dma_rx = &msp2_dma_rx, + .msp_i2s_dma_tx = &msp2_dma_tx, +}; + +struct msp_i2s_platform_data msp3_platform_data = { + .id = MSP_I2S_3, + .msp_i2s_dma_rx = &msp1_dma_rx, + .msp_i2s_dma_tx = NULL, + .use_pinctrl = true, +}; + +void mop500_audio_init(struct device *parent) +{ + pr_info("%s: Register platform-device 'snd-soc-u8500'.\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); + 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); + + pr_info("%s: Register platform-device 'ux500-pcm'\n", __func__); + platform_device_register(&ux500_pcm); +} diff --git a/arch/arm/mach-ux500/board-mop500-msp.c b/arch/arm/mach-ux500/board-mop500-msp.c deleted file mode 100644 index c20d5d2..0000000 --- a/arch/arm/mach-ux500/board-mop500-msp.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * License terms: GNU General Public License (GPL), version 2 - */ - -#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> -#include <plat/ste_dma40.h> - -#include <mach/devices.h> -#include <mach/hardware.h> -#include <mach/irqs.h> -#include <mach/msp.h> - -#include "ste-dma40-db8500.h" -#include "board-mop500.h" -#include "devices-db8500.h" -#include "pins-db8500.h" - -static struct stedma40_chan_cfg msp0_dma_rx = { - .high_priority = true, - .dir = STEDMA40_PERIPH_TO_MEM, - - .src_dev_type = DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX, - .dst_dev_type = STEDMA40_DEV_DST_MEMORY, - - .src_info.psize = STEDMA40_PSIZE_LOG_4, - .dst_info.psize = STEDMA40_PSIZE_LOG_4, - - /* data_width is set during configuration */ -}; - -static struct stedma40_chan_cfg msp0_dma_tx = { - .high_priority = true, - .dir = STEDMA40_MEM_TO_PERIPH, - - .src_dev_type = STEDMA40_DEV_DST_MEMORY, - .dst_dev_type = DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX, - - .src_info.psize = STEDMA40_PSIZE_LOG_4, - .dst_info.psize = STEDMA40_PSIZE_LOG_4, - - /* data_width is set during configuration */ -}; - -struct msp_i2s_platform_data msp0_platform_data = { - .id = MSP_I2S_0, - .msp_i2s_dma_rx = &msp0_dma_rx, - .msp_i2s_dma_tx = &msp0_dma_tx, -}; - -static struct stedma40_chan_cfg msp1_dma_rx = { - .high_priority = true, - .dir = STEDMA40_PERIPH_TO_MEM, - - .src_dev_type = DB8500_DMA_DEV30_MSP3_RX, - .dst_dev_type = STEDMA40_DEV_DST_MEMORY, - - .src_info.psize = STEDMA40_PSIZE_LOG_4, - .dst_info.psize = STEDMA40_PSIZE_LOG_4, - - /* data_width is set during configuration */ -}; - -static struct stedma40_chan_cfg msp1_dma_tx = { - .high_priority = true, - .dir = STEDMA40_MEM_TO_PERIPH, - - .src_dev_type = STEDMA40_DEV_DST_MEMORY, - .dst_dev_type = DB8500_DMA_DEV30_MSP1_TX, - - .src_info.psize = STEDMA40_PSIZE_LOG_4, - .dst_info.psize = STEDMA40_PSIZE_LOG_4, - - /* data_width is set during configuration */ -}; - -struct msp_i2s_platform_data msp1_platform_data = { - .id = MSP_I2S_1, - .msp_i2s_dma_rx = NULL, - .msp_i2s_dma_tx = &msp1_dma_tx, - .use_pinctrl = true, -}; - -static struct stedma40_chan_cfg msp2_dma_rx = { - .high_priority = true, - .dir = STEDMA40_PERIPH_TO_MEM, - - .src_dev_type = DB8500_DMA_DEV14_MSP2_RX, - .dst_dev_type = STEDMA40_DEV_DST_MEMORY, - - /* MSP2 DMA doesn't work with PSIZE == 4 on DB8500v2 */ - .src_info.psize = STEDMA40_PSIZE_LOG_1, - .dst_info.psize = STEDMA40_PSIZE_LOG_1, - - /* data_width is set during configuration */ -}; - -static struct stedma40_chan_cfg msp2_dma_tx = { - .high_priority = true, - .dir = STEDMA40_MEM_TO_PERIPH, - - .src_dev_type = STEDMA40_DEV_DST_MEMORY, - .dst_dev_type = DB8500_DMA_DEV14_MSP2_TX, - - .src_info.psize = STEDMA40_PSIZE_LOG_4, - .dst_info.psize = STEDMA40_PSIZE_LOG_4, - - .use_fixed_channel = true, - .phy_channel = 1, - - /* data_width is set during configuration */ -}; - -static struct platform_device *db8500_add_msp_i2s(struct device *parent, - int id, - resource_size_t base, int irq, - struct msp_i2s_platform_data *pdata) -{ - struct platform_device *pdev; - struct resource res[] = { - DEFINE_RES_MEM(base, SZ_4K), - DEFINE_RES_IRQ(irq), - }; - - pr_info("Register platform-device 'ux500-msp-i2s', id %d, irq %d\n", - id, irq); - pdev = platform_device_register_resndata(parent, "ux500-msp-i2s", id, - res, ARRAY_SIZE(res), - pdata, sizeof(*pdata)); - if (!pdev) { - pr_err("Failed to register platform-device 'ux500-msp-i2s.%d'!\n", - id); - return NULL; - } - - return pdev; -} - -/* Platform device for ASoC U8500 machine */ -static struct platform_device snd_soc_mop500 = { - .name = "snd-soc-mop500", - .id = 0, - .dev = { - .platform_data = NULL, - }, -}; - -/* Platform device for Ux500-PCM */ -static struct platform_device ux500_pcm = { - .name = "ux500-pcm", - .id = 0, - .dev = { - .platform_data = NULL, - }, -}; - -struct msp_i2s_platform_data msp2_platform_data = { - .id = MSP_I2S_2, - .msp_i2s_dma_rx = &msp2_dma_rx, - .msp_i2s_dma_tx = &msp2_dma_tx, -}; - -struct msp_i2s_platform_data msp3_platform_data = { - .id = MSP_I2S_3, - .msp_i2s_dma_rx = &msp1_dma_rx, - .msp_i2s_dma_tx = NULL, - .use_pinctrl = true, -}; - -void mop500_msp_init(struct device *parent) -{ - pr_info("%s: Register platform-device 'snd-soc-u8500'.\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); - 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); - - pr_info("%s: Register platform-device 'ux500-pcm'\n", __func__); - platform_device_register(&ux500_pcm); -} diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 2ef26c8..202df4b 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -607,7 +607,7 @@ static void __init mop500_init_machine(void) mop500_i2c_init(parent); mop500_sdi_init(parent); mop500_spi_init(parent); - mop500_msp_init(parent); + mop500_audio_init(parent); mop500_uart_init(parent);
u8500_cryp1_hash1_init(parent); @@ -641,7 +641,7 @@ static void __init snowball_init_machine(void) mop500_i2c_init(parent); snowball_sdi_init(parent); mop500_spi_init(parent); - mop500_msp_init(parent); + mop500_audio_init(parent); mop500_uart_init(parent);
/* This board has full regulator constraints */ @@ -673,7 +673,7 @@ static void __init hrefv60_init_machine(void) mop500_i2c_init(parent); hrefv60_sdi_init(parent); mop500_spi_init(parent); - mop500_msp_init(parent); + mop500_audio_init(parent); mop500_uart_init(parent);
i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); @@ -802,7 +802,7 @@ static void __init u8500_init_machine(void) ARRAY_SIZE(mop500_platform_devs));
mop500_sdi_init(parent); - mop500_msp_init(parent); + mop500_audio_init(parent); i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs); i2c_register_board_info(2, mop500_i2c2_devices, @@ -821,7 +821,7 @@ static void __init u8500_init_machine(void) ARRAY_SIZE(mop500_platform_devs));
hrefv60_sdi_init(parent); - mop500_msp_init(parent); + mop500_audio_init(parent);
i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES; diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h index e56c983..a0f920d 100644 --- a/arch/arm/mach-ux500/board-mop500.h +++ b/arch/arm/mach-ux500/board-mop500.h @@ -97,7 +97,7 @@ void __init mop500_stuib_init(void); void __init mop500_pinmaps_init(void); void __init snowball_pinmaps_init(void); void __init hrefv60_pinmaps_init(void); -void mop500_msp_init(struct device *parent); +void mop500_audio_init(struct device *parent);
int __init mop500_uib_init(void); void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
participants (2)
-
Lee Jones
-
Mark Brown