[alsa-devel] [PATCH 0/3] ASoC: ti: davinci-mcasp: GPIO mode support for pins
Hi,
Each McASP pins can be configured individually to be used as McASP or GPIO pin.
This series will allow client drivers to use pins as GPIO (optional) in case the board wired up them to be used in this mode.
Regards, Peter --- Peter Ujfalusi (3): ASoC: ti: davinci-mcasp: Move context save/restore to runtime_pm callbacks bindings: sound: davinci-mcasp: Document GPIO support ASoC: ti: davinci-mcasp: Add support for GPIO mode of the pins
.../bindings/sound/davinci-mcasp-audio.txt | 17 + sound/soc/ti/davinci-mcasp.c | 295 +++++++++++++----- 2 files changed, 237 insertions(+), 75 deletions(-)
McASP can loose it's context when runtime_pm is disabled. Save and restore the context when suspending and resuming the device.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- sound/soc/ti/davinci-mcasp.c | 136 +++++++++++++++++------------------ 1 file changed, 64 insertions(+), 72 deletions(-)
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index ee9ab58d4d0c..a6a470a76900 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -108,7 +108,7 @@ struct davinci_mcasp { /* Used for comstraint setting on the second stream */ u32 channels;
-#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM struct davinci_mcasp_context context; #endif
@@ -1486,74 +1486,6 @@ static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai) return 0; }
-#ifdef CONFIG_PM_SLEEP -static int davinci_mcasp_suspend(struct snd_soc_dai *dai) -{ - struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); - struct davinci_mcasp_context *context = &mcasp->context; - u32 reg; - int i; - - context->pm_state = pm_runtime_active(mcasp->dev); - if (!context->pm_state) - pm_runtime_get_sync(mcasp->dev); - - for (i = 0; i < ARRAY_SIZE(context_regs); i++) - context->config_regs[i] = mcasp_get_reg(mcasp, context_regs[i]); - - if (mcasp->txnumevt) { - reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; - context->afifo_regs[0] = mcasp_get_reg(mcasp, reg); - } - if (mcasp->rxnumevt) { - reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; - context->afifo_regs[1] = mcasp_get_reg(mcasp, reg); - } - - for (i = 0; i < mcasp->num_serializer; i++) - context->xrsr_regs[i] = mcasp_get_reg(mcasp, - DAVINCI_MCASP_XRSRCTL_REG(i)); - - pm_runtime_put_sync(mcasp->dev); - - return 0; -} - -static int davinci_mcasp_resume(struct snd_soc_dai *dai) -{ - struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); - struct davinci_mcasp_context *context = &mcasp->context; - u32 reg; - int i; - - pm_runtime_get_sync(mcasp->dev); - - for (i = 0; i < ARRAY_SIZE(context_regs); i++) - mcasp_set_reg(mcasp, context_regs[i], context->config_regs[i]); - - if (mcasp->txnumevt) { - reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; - mcasp_set_reg(mcasp, reg, context->afifo_regs[0]); - } - if (mcasp->rxnumevt) { - reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; - mcasp_set_reg(mcasp, reg, context->afifo_regs[1]); - } - - for (i = 0; i < mcasp->num_serializer; i++) - mcasp_set_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), - context->xrsr_regs[i]); - - if (!context->pm_state) - pm_runtime_put_sync(mcasp->dev); - - return 0; -} -#else -#define davinci_mcasp_suspend NULL -#define davinci_mcasp_resume NULL -#endif - #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_192000
#define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \ @@ -1571,8 +1503,6 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { { .name = "davinci-mcasp.0", .probe = davinci_mcasp_dai_probe, - .suspend = davinci_mcasp_suspend, - .resume = davinci_mcasp_resume, .playback = { .channels_min = 1, .channels_max = 32 * 16, @@ -1976,7 +1906,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) }
mcasp->num_serializer = pdata->num_serializer; -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM mcasp->context.xrsr_regs = devm_kcalloc(&pdev->dev, mcasp->num_serializer, sizeof(u32), GFP_KERNEL); @@ -2180,11 +2110,73 @@ static int davinci_mcasp_remove(struct platform_device *pdev) return 0; }
+#ifdef CONFIG_PM +static int davinci_mcasp_runtime_suspend(struct device *dev) +{ + struct davinci_mcasp *mcasp = dev_get_drvdata(dev); + struct davinci_mcasp_context *context = &mcasp->context; + u32 reg; + int i; + + for (i = 0; i < ARRAY_SIZE(context_regs); i++) + context->config_regs[i] = mcasp_get_reg(mcasp, context_regs[i]); + + if (mcasp->txnumevt) { + reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; + context->afifo_regs[0] = mcasp_get_reg(mcasp, reg); + } + if (mcasp->rxnumevt) { + reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; + context->afifo_regs[1] = mcasp_get_reg(mcasp, reg); + } + + for (i = 0; i < mcasp->num_serializer; i++) + context->xrsr_regs[i] = mcasp_get_reg(mcasp, + DAVINCI_MCASP_XRSRCTL_REG(i)); + + return 0; +} + +static int davinci_mcasp_runtime_resume(struct device *dev) +{ + struct davinci_mcasp *mcasp = dev_get_drvdata(dev); + struct davinci_mcasp_context *context = &mcasp->context; + u32 reg; + int i; + + for (i = 0; i < ARRAY_SIZE(context_regs); i++) + mcasp_set_reg(mcasp, context_regs[i], context->config_regs[i]); + + if (mcasp->txnumevt) { + reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; + mcasp_set_reg(mcasp, reg, context->afifo_regs[0]); + } + if (mcasp->rxnumevt) { + reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; + mcasp_set_reg(mcasp, reg, context->afifo_regs[1]); + } + + for (i = 0; i < mcasp->num_serializer; i++) + mcasp_set_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), + context->xrsr_regs[i]); + + return 0; +} + +#endif + +static const struct dev_pm_ops davinci_mcasp_pm_ops = { + SET_RUNTIME_PM_OPS(davinci_mcasp_runtime_suspend, + davinci_mcasp_runtime_resume, + NULL) +}; + static struct platform_driver davinci_mcasp_driver = { .probe = davinci_mcasp_probe, .remove = davinci_mcasp_remove, .driver = { .name = "davinci-mcasp", + .pm = &davinci_mcasp_pm_ops, .of_match_table = mcasp_dt_ids, }, };
The patch
ASoC: ti: davinci-mcasp: Move context save/restore to runtime_pm callbacks
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 6175471755075d256c1c654151fc1cad183c1e33 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi peter.ujfalusi@ti.com Date: Thu, 3 Jan 2019 16:05:50 +0200 Subject: [PATCH] ASoC: ti: davinci-mcasp: Move context save/restore to runtime_pm callbacks
McASP can loose it's context when runtime_pm is disabled. Save and restore the context when suspending and resuming the device.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/ti/davinci-mcasp.c | 136 +++++++++++++++++------------------ 1 file changed, 64 insertions(+), 72 deletions(-)
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index eeda6d5565bc..a10fcb5963c6 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -108,7 +108,7 @@ struct davinci_mcasp { /* Used for comstraint setting on the second stream */ u32 channels;
-#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM struct davinci_mcasp_context context; #endif
@@ -1486,74 +1486,6 @@ static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai) return 0; }
-#ifdef CONFIG_PM_SLEEP -static int davinci_mcasp_suspend(struct snd_soc_dai *dai) -{ - struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); - struct davinci_mcasp_context *context = &mcasp->context; - u32 reg; - int i; - - context->pm_state = pm_runtime_active(mcasp->dev); - if (!context->pm_state) - pm_runtime_get_sync(mcasp->dev); - - for (i = 0; i < ARRAY_SIZE(context_regs); i++) - context->config_regs[i] = mcasp_get_reg(mcasp, context_regs[i]); - - if (mcasp->txnumevt) { - reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; - context->afifo_regs[0] = mcasp_get_reg(mcasp, reg); - } - if (mcasp->rxnumevt) { - reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; - context->afifo_regs[1] = mcasp_get_reg(mcasp, reg); - } - - for (i = 0; i < mcasp->num_serializer; i++) - context->xrsr_regs[i] = mcasp_get_reg(mcasp, - DAVINCI_MCASP_XRSRCTL_REG(i)); - - pm_runtime_put_sync(mcasp->dev); - - return 0; -} - -static int davinci_mcasp_resume(struct snd_soc_dai *dai) -{ - struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); - struct davinci_mcasp_context *context = &mcasp->context; - u32 reg; - int i; - - pm_runtime_get_sync(mcasp->dev); - - for (i = 0; i < ARRAY_SIZE(context_regs); i++) - mcasp_set_reg(mcasp, context_regs[i], context->config_regs[i]); - - if (mcasp->txnumevt) { - reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; - mcasp_set_reg(mcasp, reg, context->afifo_regs[0]); - } - if (mcasp->rxnumevt) { - reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; - mcasp_set_reg(mcasp, reg, context->afifo_regs[1]); - } - - for (i = 0; i < mcasp->num_serializer; i++) - mcasp_set_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), - context->xrsr_regs[i]); - - if (!context->pm_state) - pm_runtime_put_sync(mcasp->dev); - - return 0; -} -#else -#define davinci_mcasp_suspend NULL -#define davinci_mcasp_resume NULL -#endif - #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_192000
#define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \ @@ -1571,8 +1503,6 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { { .name = "davinci-mcasp.0", .probe = davinci_mcasp_dai_probe, - .suspend = davinci_mcasp_suspend, - .resume = davinci_mcasp_resume, .playback = { .channels_min = 1, .channels_max = 32 * 16, @@ -1976,7 +1906,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) }
mcasp->num_serializer = pdata->num_serializer; -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM mcasp->context.xrsr_regs = devm_kcalloc(&pdev->dev, mcasp->num_serializer, sizeof(u32), GFP_KERNEL); @@ -2196,11 +2126,73 @@ static int davinci_mcasp_remove(struct platform_device *pdev) return 0; }
+#ifdef CONFIG_PM +static int davinci_mcasp_runtime_suspend(struct device *dev) +{ + struct davinci_mcasp *mcasp = dev_get_drvdata(dev); + struct davinci_mcasp_context *context = &mcasp->context; + u32 reg; + int i; + + for (i = 0; i < ARRAY_SIZE(context_regs); i++) + context->config_regs[i] = mcasp_get_reg(mcasp, context_regs[i]); + + if (mcasp->txnumevt) { + reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; + context->afifo_regs[0] = mcasp_get_reg(mcasp, reg); + } + if (mcasp->rxnumevt) { + reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; + context->afifo_regs[1] = mcasp_get_reg(mcasp, reg); + } + + for (i = 0; i < mcasp->num_serializer; i++) + context->xrsr_regs[i] = mcasp_get_reg(mcasp, + DAVINCI_MCASP_XRSRCTL_REG(i)); + + return 0; +} + +static int davinci_mcasp_runtime_resume(struct device *dev) +{ + struct davinci_mcasp *mcasp = dev_get_drvdata(dev); + struct davinci_mcasp_context *context = &mcasp->context; + u32 reg; + int i; + + for (i = 0; i < ARRAY_SIZE(context_regs); i++) + mcasp_set_reg(mcasp, context_regs[i], context->config_regs[i]); + + if (mcasp->txnumevt) { + reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; + mcasp_set_reg(mcasp, reg, context->afifo_regs[0]); + } + if (mcasp->rxnumevt) { + reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; + mcasp_set_reg(mcasp, reg, context->afifo_regs[1]); + } + + for (i = 0; i < mcasp->num_serializer; i++) + mcasp_set_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), + context->xrsr_regs[i]); + + return 0; +} + +#endif + +static const struct dev_pm_ops davinci_mcasp_pm_ops = { + SET_RUNTIME_PM_OPS(davinci_mcasp_runtime_suspend, + davinci_mcasp_runtime_resume, + NULL) +}; + static struct platform_driver davinci_mcasp_driver = { .probe = davinci_mcasp_probe, .remove = davinci_mcasp_remove, .driver = { .name = "davinci-mcasp", + .pm = &davinci_mcasp_pm_ops, .of_match_table = mcasp_dt_ids, }, };
McASP pins can be used as GPIO, add optional section to enable GPIO support for McASP.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- .../bindings/sound/davinci-mcasp-audio.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt index b279b6072bd5..a58f79f5345c 100644 --- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt +++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt @@ -45,6 +45,23 @@ Optional properties: - fck_parent : Should contain a valid clock name which will be used as parent for the McASP fck
+Optional GPIO support: +If any McASP pin need to be used as GPIO then the McASP node must have: +... + gpio-controller + #gpio-cells = <2>; +... + +When requesting a GPIO, the first parameter is the PIN index in McASP_P* +registers. +For example to request the AXR2 pin of mcasp8: +function-gpios = <&mcasp8 2 0>; + +Or to request the ACLKR pin of mcasp8: +function-gpios = <&mcasp8 29 0>; + +For generic gpio information, please refer to bindings/gpio/gpio.txt + Example:
mcasp0: mcasp0@1d00000 {
The patch
ASoC: davinci-mcasp: Document GPIO support
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 4664b94c98b4f9fdd3845da41d5c65288e59c66c Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi peter.ujfalusi@ti.com Date: Thu, 3 Jan 2019 16:05:51 +0200 Subject: [PATCH] ASoC: davinci-mcasp: Document GPIO support
McASP pins can be used as GPIO, add optional section to enable GPIO support for McASP.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com Signed-off-by: Mark Brown broonie@kernel.org --- .../bindings/sound/davinci-mcasp-audio.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt index b279b6072bd5..a58f79f5345c 100644 --- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt +++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt @@ -45,6 +45,23 @@ Optional properties: - fck_parent : Should contain a valid clock name which will be used as parent for the McASP fck
+Optional GPIO support: +If any McASP pin need to be used as GPIO then the McASP node must have: +... + gpio-controller + #gpio-cells = <2>; +... + +When requesting a GPIO, the first parameter is the PIN index in McASP_P* +registers. +For example to request the AXR2 pin of mcasp8: +function-gpios = <&mcasp8 2 0>; + +Or to request the ACLKR pin of mcasp8: +function-gpios = <&mcasp8 29 0>; + +For generic gpio information, please refer to bindings/gpio/gpio.txt + Example:
mcasp0: mcasp0@1d00000 {
The patch
ASoC: davinci-mcasp: Document GPIO support
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 4664b94c98b4f9fdd3845da41d5c65288e59c66c Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi peter.ujfalusi@ti.com Date: Thu, 3 Jan 2019 16:05:51 +0200 Subject: [PATCH] ASoC: davinci-mcasp: Document GPIO support
McASP pins can be used as GPIO, add optional section to enable GPIO support for McASP.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com Signed-off-by: Mark Brown broonie@kernel.org --- .../bindings/sound/davinci-mcasp-audio.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt index b279b6072bd5..a58f79f5345c 100644 --- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt +++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt @@ -45,6 +45,23 @@ Optional properties: - fck_parent : Should contain a valid clock name which will be used as parent for the McASP fck
+Optional GPIO support: +If any McASP pin need to be used as GPIO then the McASP node must have: +... + gpio-controller + #gpio-cells = <2>; +... + +When requesting a GPIO, the first parameter is the PIN index in McASP_P* +registers. +For example to request the AXR2 pin of mcasp8: +function-gpios = <&mcasp8 2 0>; + +Or to request the ACLKR pin of mcasp8: +function-gpios = <&mcasp8 29 0>; + +For generic gpio information, please refer to bindings/gpio/gpio.txt + Example:
mcasp0: mcasp0@1d00000 {
The patch
ASoC: davinci-mcasp: Document GPIO support
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 4664b94c98b4f9fdd3845da41d5c65288e59c66c Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi peter.ujfalusi@ti.com Date: Thu, 3 Jan 2019 16:05:51 +0200 Subject: [PATCH] ASoC: davinci-mcasp: Document GPIO support
McASP pins can be used as GPIO, add optional section to enable GPIO support for McASP.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com Signed-off-by: Mark Brown broonie@kernel.org --- .../bindings/sound/davinci-mcasp-audio.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt index b279b6072bd5..a58f79f5345c 100644 --- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt +++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt @@ -45,6 +45,23 @@ Optional properties: - fck_parent : Should contain a valid clock name which will be used as parent for the McASP fck
+Optional GPIO support: +If any McASP pin need to be used as GPIO then the McASP node must have: +... + gpio-controller + #gpio-cells = <2>; +... + +When requesting a GPIO, the first parameter is the PIN index in McASP_P* +registers. +For example to request the AXR2 pin of mcasp8: +function-gpios = <&mcasp8 2 0>; + +Or to request the ACLKR pin of mcasp8: +function-gpios = <&mcasp8 29 0>; + +For generic gpio information, please refer to bindings/gpio/gpio.txt + Example:
mcasp0: mcasp0@1d00000 {
The patch
ASoC: davinci-mcasp: Document GPIO support
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 4664b94c98b4f9fdd3845da41d5c65288e59c66c Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi peter.ujfalusi@ti.com Date: Thu, 3 Jan 2019 16:05:51 +0200 Subject: [PATCH] ASoC: davinci-mcasp: Document GPIO support
McASP pins can be used as GPIO, add optional section to enable GPIO support for McASP.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com Signed-off-by: Mark Brown broonie@kernel.org --- .../bindings/sound/davinci-mcasp-audio.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt index b279b6072bd5..a58f79f5345c 100644 --- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt +++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt @@ -45,6 +45,23 @@ Optional properties: - fck_parent : Should contain a valid clock name which will be used as parent for the McASP fck
+Optional GPIO support: +If any McASP pin need to be used as GPIO then the McASP node must have: +... + gpio-controller + #gpio-cells = <2>; +... + +When requesting a GPIO, the first parameter is the PIN index in McASP_P* +registers. +For example to request the AXR2 pin of mcasp8: +function-gpios = <&mcasp8 2 0>; + +Or to request the ACLKR pin of mcasp8: +function-gpios = <&mcasp8 29 0>; + +For generic gpio information, please refer to bindings/gpio/gpio.txt + Example:
mcasp0: mcasp0@1d00000 {
All McASP pin can be configured as GPIO. Add gpiochip support for McASP and only enable it when the gpio-controller is present in the DT node.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- sound/soc/ti/davinci-mcasp.c | 159 ++++++++++++++++++++++++++++++++++- 1 file changed, 156 insertions(+), 3 deletions(-)
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index a6a470a76900..a3a67a8f0f54 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -29,6 +29,7 @@ #include <linux/platform_data/davinci_asp.h> #include <linux/math64.h> #include <linux/bitmap.h> +#include <linux/gpio/driver.h>
#include <sound/asoundef.h> #include <sound/core.h> @@ -54,6 +55,7 @@ static u32 context_regs[] = { DAVINCI_MCASP_AHCLKXCTL_REG, DAVINCI_MCASP_AHCLKRCTL_REG, DAVINCI_MCASP_PDIR_REG, + DAVINCI_MCASP_PFUNC_REG, DAVINCI_MCASP_RXMASK_REG, DAVINCI_MCASP_TXMASK_REG, DAVINCI_MCASP_RXTDM_REG, @@ -108,6 +110,10 @@ struct davinci_mcasp { /* Used for comstraint setting on the second stream */ u32 channels;
+#ifdef CONFIG_GPIOLIB + struct gpio_chip gpio_chip; +#endif + #ifdef CONFIG_PM struct davinci_mcasp_context context; #endif @@ -818,9 +824,6 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, if (mcasp->version < MCASP_VERSION_3) mcasp_set_bits(mcasp, DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
- /* All PINS as McASP */ - mcasp_set_reg(mcasp, DAVINCI_MCASP_PFUNC_REG, 0x00000000); - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); @@ -1845,6 +1848,147 @@ static u32 davinci_mcasp_rxdma_offset(struct davinci_mcasp_pdata *pdata) return offset; }
+#ifdef CONFIG_GPIOLIB +static int davinci_mcasp_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + + if (mcasp->num_serializer && offset < mcasp->num_serializer && + mcasp->serial_dir[offset] != INACTIVE_MODE) { + dev_err(mcasp->dev, "AXR%u pin is used for audio\n", offset); + return -EBUSY; + } + + /* Do not change the PIN yet */ + + return pm_runtime_get_sync(mcasp->dev); +} + +static void davinci_mcasp_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + + /* Set the direction to input */ + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(offset)); + + /* Set the pin as McASP pin */ + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PFUNC_REG, BIT(offset)); + + pm_runtime_put_sync(mcasp->dev); +} + +static int davinci_mcasp_gpio_direction_out(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + if (value) + mcasp_set_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); + else + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PFUNC_REG); + if (!(val & BIT(offset))) { + /* Set the pin as GPIO pin */ + mcasp_set_bits(mcasp, DAVINCI_MCASP_PFUNC_REG, BIT(offset)); + + /* Set the direction to output */ + mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(offset)); + } + + return 0; +} + +static void davinci_mcasp_gpio_set(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + + if (value) + mcasp_set_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); + else + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); +} + +static int davinci_mcasp_gpio_direction_in(struct gpio_chip *chip, + unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PFUNC_REG); + if (!(val & BIT(offset))) { + /* Set the direction to input */ + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(offset)); + + /* Set the pin as GPIO pin */ + mcasp_set_bits(mcasp, DAVINCI_MCASP_PFUNC_REG, BIT(offset)); + } + + return 0; +} + +static int davinci_mcasp_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDSET_REG); + if (val & BIT(offset)) + return 1; + + return 0; +} + +static int davinci_mcasp_gpio_get_direction(struct gpio_chip *chip, + unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG); + if (val & BIT(offset)) + return 0; + + return 1; +} + +static const struct gpio_chip davinci_mcasp_template_chip = { + .owner = THIS_MODULE, + .request = davinci_mcasp_gpio_request, + .free = davinci_mcasp_gpio_free, + .direction_output = davinci_mcasp_gpio_direction_out, + .set = davinci_mcasp_gpio_set, + .direction_input = davinci_mcasp_gpio_direction_in, + .get = davinci_mcasp_gpio_get, + .get_direction = davinci_mcasp_gpio_get_direction, + .base = -1, + .ngpio = 32, +}; + +static int davinci_mcasp_init_gpiochip(struct davinci_mcasp *mcasp) +{ + if (!of_property_read_bool(mcasp->dev->of_node, "gpio-controller")) + return 0; + + mcasp->gpio_chip = davinci_mcasp_template_chip; + mcasp->gpio_chip.label = dev_name(mcasp->dev); + mcasp->gpio_chip.parent = mcasp->dev; +#ifdef CONFIG_OF_GPIO + mcasp->gpio_chip.of_node = mcasp->dev->of_node; +#endif + + return devm_gpiochip_add_data(mcasp->dev, &mcasp->gpio_chip, mcasp); +} + +#else /* CONFIG_GPIOLIB */ +static inline int davinci_mcasp_init_gpiochip(struct davinci_mcasp *mcasp) +{ + return 0; +} +#endif /* CONFIG_GPIOLIB */ + static int davinci_mcasp_probe(struct platform_device *pdev) { struct snd_dmaengine_dai_dma_data *dma_data; @@ -2069,6 +2213,15 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
mcasp_reparent_fck(pdev);
+ /* All PINS as McASP */ + pm_runtime_get_sync(mcasp->dev); + mcasp_set_reg(mcasp, DAVINCI_MCASP_PFUNC_REG, 0x00000000); + pm_runtime_put(mcasp->dev); + + ret = davinci_mcasp_init_gpiochip(mcasp); + if (ret) + goto err; + ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, &davinci_mcasp_dai[pdata->op_mode], 1);
The patch
ASoC: ti: davinci-mcasp: Add support for GPIO mode of the pins
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 540f1ba7b3a5596827a3bfeaae9c5e754347c933 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi peter.ujfalusi@ti.com Date: Thu, 3 Jan 2019 16:05:52 +0200 Subject: [PATCH] ASoC: ti: davinci-mcasp: Add support for GPIO mode of the pins
All McASP pin can be configured as GPIO. Add gpiochip support for McASP and only enable it when the gpio-controller is present in the DT node.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/ti/davinci-mcasp.c | 159 ++++++++++++++++++++++++++++++++++- 1 file changed, 156 insertions(+), 3 deletions(-)
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index a6a470a76900..a3a67a8f0f54 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -29,6 +29,7 @@ #include <linux/platform_data/davinci_asp.h> #include <linux/math64.h> #include <linux/bitmap.h> +#include <linux/gpio/driver.h>
#include <sound/asoundef.h> #include <sound/core.h> @@ -54,6 +55,7 @@ static u32 context_regs[] = { DAVINCI_MCASP_AHCLKXCTL_REG, DAVINCI_MCASP_AHCLKRCTL_REG, DAVINCI_MCASP_PDIR_REG, + DAVINCI_MCASP_PFUNC_REG, DAVINCI_MCASP_RXMASK_REG, DAVINCI_MCASP_TXMASK_REG, DAVINCI_MCASP_RXTDM_REG, @@ -108,6 +110,10 @@ struct davinci_mcasp { /* Used for comstraint setting on the second stream */ u32 channels;
+#ifdef CONFIG_GPIOLIB + struct gpio_chip gpio_chip; +#endif + #ifdef CONFIG_PM struct davinci_mcasp_context context; #endif @@ -818,9 +824,6 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, if (mcasp->version < MCASP_VERSION_3) mcasp_set_bits(mcasp, DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
- /* All PINS as McASP */ - mcasp_set_reg(mcasp, DAVINCI_MCASP_PFUNC_REG, 0x00000000); - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); @@ -1845,6 +1848,147 @@ static u32 davinci_mcasp_rxdma_offset(struct davinci_mcasp_pdata *pdata) return offset; }
+#ifdef CONFIG_GPIOLIB +static int davinci_mcasp_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + + if (mcasp->num_serializer && offset < mcasp->num_serializer && + mcasp->serial_dir[offset] != INACTIVE_MODE) { + dev_err(mcasp->dev, "AXR%u pin is used for audio\n", offset); + return -EBUSY; + } + + /* Do not change the PIN yet */ + + return pm_runtime_get_sync(mcasp->dev); +} + +static void davinci_mcasp_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + + /* Set the direction to input */ + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(offset)); + + /* Set the pin as McASP pin */ + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PFUNC_REG, BIT(offset)); + + pm_runtime_put_sync(mcasp->dev); +} + +static int davinci_mcasp_gpio_direction_out(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + if (value) + mcasp_set_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); + else + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PFUNC_REG); + if (!(val & BIT(offset))) { + /* Set the pin as GPIO pin */ + mcasp_set_bits(mcasp, DAVINCI_MCASP_PFUNC_REG, BIT(offset)); + + /* Set the direction to output */ + mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(offset)); + } + + return 0; +} + +static void davinci_mcasp_gpio_set(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + + if (value) + mcasp_set_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); + else + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); +} + +static int davinci_mcasp_gpio_direction_in(struct gpio_chip *chip, + unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PFUNC_REG); + if (!(val & BIT(offset))) { + /* Set the direction to input */ + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(offset)); + + /* Set the pin as GPIO pin */ + mcasp_set_bits(mcasp, DAVINCI_MCASP_PFUNC_REG, BIT(offset)); + } + + return 0; +} + +static int davinci_mcasp_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDSET_REG); + if (val & BIT(offset)) + return 1; + + return 0; +} + +static int davinci_mcasp_gpio_get_direction(struct gpio_chip *chip, + unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG); + if (val & BIT(offset)) + return 0; + + return 1; +} + +static const struct gpio_chip davinci_mcasp_template_chip = { + .owner = THIS_MODULE, + .request = davinci_mcasp_gpio_request, + .free = davinci_mcasp_gpio_free, + .direction_output = davinci_mcasp_gpio_direction_out, + .set = davinci_mcasp_gpio_set, + .direction_input = davinci_mcasp_gpio_direction_in, + .get = davinci_mcasp_gpio_get, + .get_direction = davinci_mcasp_gpio_get_direction, + .base = -1, + .ngpio = 32, +}; + +static int davinci_mcasp_init_gpiochip(struct davinci_mcasp *mcasp) +{ + if (!of_property_read_bool(mcasp->dev->of_node, "gpio-controller")) + return 0; + + mcasp->gpio_chip = davinci_mcasp_template_chip; + mcasp->gpio_chip.label = dev_name(mcasp->dev); + mcasp->gpio_chip.parent = mcasp->dev; +#ifdef CONFIG_OF_GPIO + mcasp->gpio_chip.of_node = mcasp->dev->of_node; +#endif + + return devm_gpiochip_add_data(mcasp->dev, &mcasp->gpio_chip, mcasp); +} + +#else /* CONFIG_GPIOLIB */ +static inline int davinci_mcasp_init_gpiochip(struct davinci_mcasp *mcasp) +{ + return 0; +} +#endif /* CONFIG_GPIOLIB */ + static int davinci_mcasp_probe(struct platform_device *pdev) { struct snd_dmaengine_dai_dma_data *dma_data; @@ -2069,6 +2213,15 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
mcasp_reparent_fck(pdev);
+ /* All PINS as McASP */ + pm_runtime_get_sync(mcasp->dev); + mcasp_set_reg(mcasp, DAVINCI_MCASP_PFUNC_REG, 0x00000000); + pm_runtime_put(mcasp->dev); + + ret = davinci_mcasp_init_gpiochip(mcasp); + if (ret) + goto err; + ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, &davinci_mcasp_dai[pdata->op_mode], 1);
The patch
ASoC: ti: davinci-mcasp: Add support for GPIO mode of the pins
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 540f1ba7b3a5596827a3bfeaae9c5e754347c933 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi peter.ujfalusi@ti.com Date: Thu, 3 Jan 2019 16:05:52 +0200 Subject: [PATCH] ASoC: ti: davinci-mcasp: Add support for GPIO mode of the pins
All McASP pin can be configured as GPIO. Add gpiochip support for McASP and only enable it when the gpio-controller is present in the DT node.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/ti/davinci-mcasp.c | 159 ++++++++++++++++++++++++++++++++++- 1 file changed, 156 insertions(+), 3 deletions(-)
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index a6a470a76900..a3a67a8f0f54 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -29,6 +29,7 @@ #include <linux/platform_data/davinci_asp.h> #include <linux/math64.h> #include <linux/bitmap.h> +#include <linux/gpio/driver.h>
#include <sound/asoundef.h> #include <sound/core.h> @@ -54,6 +55,7 @@ static u32 context_regs[] = { DAVINCI_MCASP_AHCLKXCTL_REG, DAVINCI_MCASP_AHCLKRCTL_REG, DAVINCI_MCASP_PDIR_REG, + DAVINCI_MCASP_PFUNC_REG, DAVINCI_MCASP_RXMASK_REG, DAVINCI_MCASP_TXMASK_REG, DAVINCI_MCASP_RXTDM_REG, @@ -108,6 +110,10 @@ struct davinci_mcasp { /* Used for comstraint setting on the second stream */ u32 channels;
+#ifdef CONFIG_GPIOLIB + struct gpio_chip gpio_chip; +#endif + #ifdef CONFIG_PM struct davinci_mcasp_context context; #endif @@ -818,9 +824,6 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, if (mcasp->version < MCASP_VERSION_3) mcasp_set_bits(mcasp, DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
- /* All PINS as McASP */ - mcasp_set_reg(mcasp, DAVINCI_MCASP_PFUNC_REG, 0x00000000); - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); @@ -1845,6 +1848,147 @@ static u32 davinci_mcasp_rxdma_offset(struct davinci_mcasp_pdata *pdata) return offset; }
+#ifdef CONFIG_GPIOLIB +static int davinci_mcasp_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + + if (mcasp->num_serializer && offset < mcasp->num_serializer && + mcasp->serial_dir[offset] != INACTIVE_MODE) { + dev_err(mcasp->dev, "AXR%u pin is used for audio\n", offset); + return -EBUSY; + } + + /* Do not change the PIN yet */ + + return pm_runtime_get_sync(mcasp->dev); +} + +static void davinci_mcasp_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + + /* Set the direction to input */ + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(offset)); + + /* Set the pin as McASP pin */ + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PFUNC_REG, BIT(offset)); + + pm_runtime_put_sync(mcasp->dev); +} + +static int davinci_mcasp_gpio_direction_out(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + if (value) + mcasp_set_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); + else + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PFUNC_REG); + if (!(val & BIT(offset))) { + /* Set the pin as GPIO pin */ + mcasp_set_bits(mcasp, DAVINCI_MCASP_PFUNC_REG, BIT(offset)); + + /* Set the direction to output */ + mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(offset)); + } + + return 0; +} + +static void davinci_mcasp_gpio_set(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + + if (value) + mcasp_set_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); + else + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); +} + +static int davinci_mcasp_gpio_direction_in(struct gpio_chip *chip, + unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PFUNC_REG); + if (!(val & BIT(offset))) { + /* Set the direction to input */ + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(offset)); + + /* Set the pin as GPIO pin */ + mcasp_set_bits(mcasp, DAVINCI_MCASP_PFUNC_REG, BIT(offset)); + } + + return 0; +} + +static int davinci_mcasp_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDSET_REG); + if (val & BIT(offset)) + return 1; + + return 0; +} + +static int davinci_mcasp_gpio_get_direction(struct gpio_chip *chip, + unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG); + if (val & BIT(offset)) + return 0; + + return 1; +} + +static const struct gpio_chip davinci_mcasp_template_chip = { + .owner = THIS_MODULE, + .request = davinci_mcasp_gpio_request, + .free = davinci_mcasp_gpio_free, + .direction_output = davinci_mcasp_gpio_direction_out, + .set = davinci_mcasp_gpio_set, + .direction_input = davinci_mcasp_gpio_direction_in, + .get = davinci_mcasp_gpio_get, + .get_direction = davinci_mcasp_gpio_get_direction, + .base = -1, + .ngpio = 32, +}; + +static int davinci_mcasp_init_gpiochip(struct davinci_mcasp *mcasp) +{ + if (!of_property_read_bool(mcasp->dev->of_node, "gpio-controller")) + return 0; + + mcasp->gpio_chip = davinci_mcasp_template_chip; + mcasp->gpio_chip.label = dev_name(mcasp->dev); + mcasp->gpio_chip.parent = mcasp->dev; +#ifdef CONFIG_OF_GPIO + mcasp->gpio_chip.of_node = mcasp->dev->of_node; +#endif + + return devm_gpiochip_add_data(mcasp->dev, &mcasp->gpio_chip, mcasp); +} + +#else /* CONFIG_GPIOLIB */ +static inline int davinci_mcasp_init_gpiochip(struct davinci_mcasp *mcasp) +{ + return 0; +} +#endif /* CONFIG_GPIOLIB */ + static int davinci_mcasp_probe(struct platform_device *pdev) { struct snd_dmaengine_dai_dma_data *dma_data; @@ -2069,6 +2213,15 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
mcasp_reparent_fck(pdev);
+ /* All PINS as McASP */ + pm_runtime_get_sync(mcasp->dev); + mcasp_set_reg(mcasp, DAVINCI_MCASP_PFUNC_REG, 0x00000000); + pm_runtime_put(mcasp->dev); + + ret = davinci_mcasp_init_gpiochip(mcasp); + if (ret) + goto err; + ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, &davinci_mcasp_dai[pdata->op_mode], 1);
The patch
ASoC: ti: davinci-mcasp: Add support for GPIO mode of the pins
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 540f1ba7b3a5596827a3bfeaae9c5e754347c933 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi peter.ujfalusi@ti.com Date: Thu, 3 Jan 2019 16:05:52 +0200 Subject: [PATCH] ASoC: ti: davinci-mcasp: Add support for GPIO mode of the pins
All McASP pin can be configured as GPIO. Add gpiochip support for McASP and only enable it when the gpio-controller is present in the DT node.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/ti/davinci-mcasp.c | 159 ++++++++++++++++++++++++++++++++++- 1 file changed, 156 insertions(+), 3 deletions(-)
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index a6a470a76900..a3a67a8f0f54 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -29,6 +29,7 @@ #include <linux/platform_data/davinci_asp.h> #include <linux/math64.h> #include <linux/bitmap.h> +#include <linux/gpio/driver.h>
#include <sound/asoundef.h> #include <sound/core.h> @@ -54,6 +55,7 @@ static u32 context_regs[] = { DAVINCI_MCASP_AHCLKXCTL_REG, DAVINCI_MCASP_AHCLKRCTL_REG, DAVINCI_MCASP_PDIR_REG, + DAVINCI_MCASP_PFUNC_REG, DAVINCI_MCASP_RXMASK_REG, DAVINCI_MCASP_TXMASK_REG, DAVINCI_MCASP_RXTDM_REG, @@ -108,6 +110,10 @@ struct davinci_mcasp { /* Used for comstraint setting on the second stream */ u32 channels;
+#ifdef CONFIG_GPIOLIB + struct gpio_chip gpio_chip; +#endif + #ifdef CONFIG_PM struct davinci_mcasp_context context; #endif @@ -818,9 +824,6 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, if (mcasp->version < MCASP_VERSION_3) mcasp_set_bits(mcasp, DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
- /* All PINS as McASP */ - mcasp_set_reg(mcasp, DAVINCI_MCASP_PFUNC_REG, 0x00000000); - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); @@ -1845,6 +1848,147 @@ static u32 davinci_mcasp_rxdma_offset(struct davinci_mcasp_pdata *pdata) return offset; }
+#ifdef CONFIG_GPIOLIB +static int davinci_mcasp_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + + if (mcasp->num_serializer && offset < mcasp->num_serializer && + mcasp->serial_dir[offset] != INACTIVE_MODE) { + dev_err(mcasp->dev, "AXR%u pin is used for audio\n", offset); + return -EBUSY; + } + + /* Do not change the PIN yet */ + + return pm_runtime_get_sync(mcasp->dev); +} + +static void davinci_mcasp_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + + /* Set the direction to input */ + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(offset)); + + /* Set the pin as McASP pin */ + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PFUNC_REG, BIT(offset)); + + pm_runtime_put_sync(mcasp->dev); +} + +static int davinci_mcasp_gpio_direction_out(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + if (value) + mcasp_set_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); + else + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PFUNC_REG); + if (!(val & BIT(offset))) { + /* Set the pin as GPIO pin */ + mcasp_set_bits(mcasp, DAVINCI_MCASP_PFUNC_REG, BIT(offset)); + + /* Set the direction to output */ + mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(offset)); + } + + return 0; +} + +static void davinci_mcasp_gpio_set(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + + if (value) + mcasp_set_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); + else + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); +} + +static int davinci_mcasp_gpio_direction_in(struct gpio_chip *chip, + unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PFUNC_REG); + if (!(val & BIT(offset))) { + /* Set the direction to input */ + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(offset)); + + /* Set the pin as GPIO pin */ + mcasp_set_bits(mcasp, DAVINCI_MCASP_PFUNC_REG, BIT(offset)); + } + + return 0; +} + +static int davinci_mcasp_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDSET_REG); + if (val & BIT(offset)) + return 1; + + return 0; +} + +static int davinci_mcasp_gpio_get_direction(struct gpio_chip *chip, + unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG); + if (val & BIT(offset)) + return 0; + + return 1; +} + +static const struct gpio_chip davinci_mcasp_template_chip = { + .owner = THIS_MODULE, + .request = davinci_mcasp_gpio_request, + .free = davinci_mcasp_gpio_free, + .direction_output = davinci_mcasp_gpio_direction_out, + .set = davinci_mcasp_gpio_set, + .direction_input = davinci_mcasp_gpio_direction_in, + .get = davinci_mcasp_gpio_get, + .get_direction = davinci_mcasp_gpio_get_direction, + .base = -1, + .ngpio = 32, +}; + +static int davinci_mcasp_init_gpiochip(struct davinci_mcasp *mcasp) +{ + if (!of_property_read_bool(mcasp->dev->of_node, "gpio-controller")) + return 0; + + mcasp->gpio_chip = davinci_mcasp_template_chip; + mcasp->gpio_chip.label = dev_name(mcasp->dev); + mcasp->gpio_chip.parent = mcasp->dev; +#ifdef CONFIG_OF_GPIO + mcasp->gpio_chip.of_node = mcasp->dev->of_node; +#endif + + return devm_gpiochip_add_data(mcasp->dev, &mcasp->gpio_chip, mcasp); +} + +#else /* CONFIG_GPIOLIB */ +static inline int davinci_mcasp_init_gpiochip(struct davinci_mcasp *mcasp) +{ + return 0; +} +#endif /* CONFIG_GPIOLIB */ + static int davinci_mcasp_probe(struct platform_device *pdev) { struct snd_dmaengine_dai_dma_data *dma_data; @@ -2069,6 +2213,15 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
mcasp_reparent_fck(pdev);
+ /* All PINS as McASP */ + pm_runtime_get_sync(mcasp->dev); + mcasp_set_reg(mcasp, DAVINCI_MCASP_PFUNC_REG, 0x00000000); + pm_runtime_put(mcasp->dev); + + ret = davinci_mcasp_init_gpiochip(mcasp); + if (ret) + goto err; + ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, &davinci_mcasp_dai[pdata->op_mode], 1);
The patch
ASoC: ti: davinci-mcasp: Add support for GPIO mode of the pins
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 540f1ba7b3a5596827a3bfeaae9c5e754347c933 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi peter.ujfalusi@ti.com Date: Thu, 3 Jan 2019 16:05:52 +0200 Subject: [PATCH] ASoC: ti: davinci-mcasp: Add support for GPIO mode of the pins
All McASP pin can be configured as GPIO. Add gpiochip support for McASP and only enable it when the gpio-controller is present in the DT node.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/ti/davinci-mcasp.c | 159 ++++++++++++++++++++++++++++++++++- 1 file changed, 156 insertions(+), 3 deletions(-)
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index a6a470a76900..a3a67a8f0f54 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -29,6 +29,7 @@ #include <linux/platform_data/davinci_asp.h> #include <linux/math64.h> #include <linux/bitmap.h> +#include <linux/gpio/driver.h>
#include <sound/asoundef.h> #include <sound/core.h> @@ -54,6 +55,7 @@ static u32 context_regs[] = { DAVINCI_MCASP_AHCLKXCTL_REG, DAVINCI_MCASP_AHCLKRCTL_REG, DAVINCI_MCASP_PDIR_REG, + DAVINCI_MCASP_PFUNC_REG, DAVINCI_MCASP_RXMASK_REG, DAVINCI_MCASP_TXMASK_REG, DAVINCI_MCASP_RXTDM_REG, @@ -108,6 +110,10 @@ struct davinci_mcasp { /* Used for comstraint setting on the second stream */ u32 channels;
+#ifdef CONFIG_GPIOLIB + struct gpio_chip gpio_chip; +#endif + #ifdef CONFIG_PM struct davinci_mcasp_context context; #endif @@ -818,9 +824,6 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, if (mcasp->version < MCASP_VERSION_3) mcasp_set_bits(mcasp, DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
- /* All PINS as McASP */ - mcasp_set_reg(mcasp, DAVINCI_MCASP_PFUNC_REG, 0x00000000); - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); @@ -1845,6 +1848,147 @@ static u32 davinci_mcasp_rxdma_offset(struct davinci_mcasp_pdata *pdata) return offset; }
+#ifdef CONFIG_GPIOLIB +static int davinci_mcasp_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + + if (mcasp->num_serializer && offset < mcasp->num_serializer && + mcasp->serial_dir[offset] != INACTIVE_MODE) { + dev_err(mcasp->dev, "AXR%u pin is used for audio\n", offset); + return -EBUSY; + } + + /* Do not change the PIN yet */ + + return pm_runtime_get_sync(mcasp->dev); +} + +static void davinci_mcasp_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + + /* Set the direction to input */ + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(offset)); + + /* Set the pin as McASP pin */ + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PFUNC_REG, BIT(offset)); + + pm_runtime_put_sync(mcasp->dev); +} + +static int davinci_mcasp_gpio_direction_out(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + if (value) + mcasp_set_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); + else + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PFUNC_REG); + if (!(val & BIT(offset))) { + /* Set the pin as GPIO pin */ + mcasp_set_bits(mcasp, DAVINCI_MCASP_PFUNC_REG, BIT(offset)); + + /* Set the direction to output */ + mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(offset)); + } + + return 0; +} + +static void davinci_mcasp_gpio_set(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + + if (value) + mcasp_set_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); + else + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset)); +} + +static int davinci_mcasp_gpio_direction_in(struct gpio_chip *chip, + unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PFUNC_REG); + if (!(val & BIT(offset))) { + /* Set the direction to input */ + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(offset)); + + /* Set the pin as GPIO pin */ + mcasp_set_bits(mcasp, DAVINCI_MCASP_PFUNC_REG, BIT(offset)); + } + + return 0; +} + +static int davinci_mcasp_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDSET_REG); + if (val & BIT(offset)) + return 1; + + return 0; +} + +static int davinci_mcasp_gpio_get_direction(struct gpio_chip *chip, + unsigned offset) +{ + struct davinci_mcasp *mcasp = gpiochip_get_data(chip); + u32 val; + + val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG); + if (val & BIT(offset)) + return 0; + + return 1; +} + +static const struct gpio_chip davinci_mcasp_template_chip = { + .owner = THIS_MODULE, + .request = davinci_mcasp_gpio_request, + .free = davinci_mcasp_gpio_free, + .direction_output = davinci_mcasp_gpio_direction_out, + .set = davinci_mcasp_gpio_set, + .direction_input = davinci_mcasp_gpio_direction_in, + .get = davinci_mcasp_gpio_get, + .get_direction = davinci_mcasp_gpio_get_direction, + .base = -1, + .ngpio = 32, +}; + +static int davinci_mcasp_init_gpiochip(struct davinci_mcasp *mcasp) +{ + if (!of_property_read_bool(mcasp->dev->of_node, "gpio-controller")) + return 0; + + mcasp->gpio_chip = davinci_mcasp_template_chip; + mcasp->gpio_chip.label = dev_name(mcasp->dev); + mcasp->gpio_chip.parent = mcasp->dev; +#ifdef CONFIG_OF_GPIO + mcasp->gpio_chip.of_node = mcasp->dev->of_node; +#endif + + return devm_gpiochip_add_data(mcasp->dev, &mcasp->gpio_chip, mcasp); +} + +#else /* CONFIG_GPIOLIB */ +static inline int davinci_mcasp_init_gpiochip(struct davinci_mcasp *mcasp) +{ + return 0; +} +#endif /* CONFIG_GPIOLIB */ + static int davinci_mcasp_probe(struct platform_device *pdev) { struct snd_dmaengine_dai_dma_data *dma_data; @@ -2069,6 +2213,15 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
mcasp_reparent_fck(pdev);
+ /* All PINS as McASP */ + pm_runtime_get_sync(mcasp->dev); + mcasp_set_reg(mcasp, DAVINCI_MCASP_PFUNC_REG, 0x00000000); + pm_runtime_put(mcasp->dev); + + ret = davinci_mcasp_init_gpiochip(mcasp); + if (ret) + goto err; + ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, &davinci_mcasp_dai[pdata->op_mode], 1);
participants (2)
-
Mark Brown
-
Peter Ujfalusi