2018-11-16 13:41:32

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH 0/4] ASoC; davinci-mcasp: Pin handling updates

Hi,

The series will improve the McASP pin handling:
- To avoid non configured clocks leaking out from McASP
- make sure that the AXR pin (TX) state is correct in all scenarios
- Allow user configurable DISMOD for the tx pin instead of hardwiring it in the
code to low

The DISMOD configuration is needed when the codec requires the TX line to be
high during inactive slots (mu-law codecs for example).

Regards,
Peter
---
Peter Ujfalusi (4):
ASoC: davinci-mcasp: Clear TXSTAT register before activating
serializers
ASoC: davinci-mcasp: Update PDIR (pin direction) register handling
bindings: sound: davinci-mcasp: Document dismod optional property
ASoC: davinci-mcasp: Implement configurable dismod handling

.../bindings/sound/davinci-mcasp-audio.txt | 5 +
include/linux/platform_data/davinci_asp.h | 1 +
sound/soc/davinci/davinci-mcasp.c | 109 +++++++++++++++---
sound/soc/davinci/davinci-mcasp.h | 30 ++---
4 files changed, 112 insertions(+), 33 deletions(-)

--
Peter

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki



2018-11-16 13:41:34

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH 1/4] ASoC: davinci-mcasp: Clear TXSTAT register before activating serializers

Follow the guideline from the TRM:
Before starting, clear the respective transmitter and receiver status
registers

To avoid stale state stored in the status registers.

Signed-off-by: Peter Ujfalusi <[email protected]>
---
sound/soc/davinci/davinci-mcasp.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 267aee776b2d..740030b4d37a 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -192,6 +192,7 @@ static void mcasp_start_rx(struct davinci_mcasp *mcasp)
}

/* Activate serializer(s) */
+ mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
/* Release RX state machine */
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
@@ -220,6 +221,7 @@ static void mcasp_start_tx(struct davinci_mcasp *mcasp)
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
/* Activate serializer(s) */
+ mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);

/* wait for XDATA to be cleared */
--
Peter

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki


2018-11-16 13:41:40

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH 2/4] ASoC: davinci-mcasp: Update PDIR (pin direction) register handling

When McASP is master and the PDIR for the clock pins are configured as
outputs before the clocking is configured it will output whatever clock
is generated at the moment internally.
The clock will switch to the correct rate only when the we start the clock
generators.

To avoid this we must only set the pin as output after the clock is
configured and enabled.

AXR pins configured as outputs behaves somehow interesting as well:
when McASP is not enabled and the pin is selected as output it will not
honor the DISMOD settings for the inactive state, but will pull the pin
down.

Add a new bitfield and mark the pins there which needs to be output and
set the pins only at the time when they will behave correctly.

On stream stop configure the pins back to input which makes them to obey
the global pin configuration regarding to pull up/down.

Signed-off-by: Peter Ujfalusi <[email protected]>
---
sound/soc/davinci/davinci-mcasp.c | 88 ++++++++++++++++++++++++++-----
sound/soc/davinci/davinci-mcasp.h | 29 ++++------
2 files changed, 85 insertions(+), 32 deletions(-)

diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 740030b4d37a..0f3911be1c8e 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -28,6 +28,7 @@
#include <linux/of_device.h>
#include <linux/platform_data/davinci_asp.h>
#include <linux/math64.h>
+#include <linux/bitmap.h>

#include <sound/asoundef.h>
#include <sound/core.h>
@@ -95,6 +96,8 @@ struct davinci_mcasp {
int sysclk_freq;
bool bclk_master;

+ unsigned long pdir; /* Pin direction bitfield */
+
/* McASP FIFO related */
u8 txnumevt;
u8 rxnumevt;
@@ -169,6 +172,30 @@ static bool mcasp_is_synchronous(struct davinci_mcasp *mcasp)
return !(aclkxctl & TX_ASYNC) && rxfmctl & AFSRE;
}

+static inline void mcasp_set_clk_pdir(struct davinci_mcasp *mcasp, bool enable)
+{
+ u32 bit = PIN_BIT_AMUTE;
+
+ for_each_set_bit_from(bit, &mcasp->pdir, PIN_BIT_AFSR + 1) {
+ if (enable)
+ mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit));
+ else
+ mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit));
+ }
+}
+
+static inline void mcasp_set_axr_pdir(struct davinci_mcasp *mcasp, bool enable)
+{
+ u32 bit;
+
+ for_each_set_bit(bit, &mcasp->pdir, PIN_BIT_AFSR) {
+ if (enable)
+ mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit));
+ else
+ mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit));
+ }
+}
+
static void mcasp_start_rx(struct davinci_mcasp *mcasp)
{
if (mcasp->rxnumevt) { /* enable FIFO */
@@ -220,6 +247,8 @@ static void mcasp_start_tx(struct davinci_mcasp *mcasp)
/* Start clocks */
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
+ mcasp_set_clk_pdir(mcasp, true);
+
/* Activate serializer(s) */
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
@@ -230,6 +259,8 @@ static void mcasp_start_tx(struct davinci_mcasp *mcasp)
(cnt < 100000))
cnt++;

+ mcasp_set_axr_pdir(mcasp, true);
+
/* Release TX state machine */
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
/* Release Frame Sync generator */
@@ -260,8 +291,10 @@ static void mcasp_stop_rx(struct davinci_mcasp *mcasp)
* In synchronous mode stop the TX clocks if no other stream is
* running
*/
- if (mcasp_is_synchronous(mcasp) && !mcasp->streams)
+ if (mcasp_is_synchronous(mcasp) && !mcasp->streams) {
+ mcasp_set_clk_pdir(mcasp, false);
mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, 0);
+ }

mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, 0);
mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
@@ -287,6 +320,9 @@ static void mcasp_stop_tx(struct davinci_mcasp *mcasp)
*/
if (mcasp_is_synchronous(mcasp) && mcasp->streams)
val = TXHCLKRST | TXCLKRST | TXFSRST;
+ else
+ mcasp_set_clk_pdir(mcasp, false);
+

mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, val);
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
@@ -296,6 +332,8 @@ static void mcasp_stop_tx(struct davinci_mcasp *mcasp)

mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
}
+
+ mcasp_set_axr_pdir(mcasp, false);
}

static void davinci_mcasp_stop(struct davinci_mcasp *mcasp, int stream)
@@ -446,8 +484,13 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);

- mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR);
- mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR);
+ /* BCLK */
+ set_bit(PIN_BIT_ACLKX, &mcasp->pdir);
+ set_bit(PIN_BIT_ACLKR, &mcasp->pdir);
+ /* Frame Sync */
+ set_bit(PIN_BIT_AFSX, &mcasp->pdir);
+ set_bit(PIN_BIT_AFSR, &mcasp->pdir);
+
mcasp->bclk_master = 1;
break;
case SND_SOC_DAIFMT_CBS_CFM:
@@ -458,8 +501,13 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);

- mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR);
- mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR);
+ /* BCLK */
+ set_bit(PIN_BIT_ACLKX, &mcasp->pdir);
+ set_bit(PIN_BIT_ACLKR, &mcasp->pdir);
+ /* Frame Sync */
+ clear_bit(PIN_BIT_AFSX, &mcasp->pdir);
+ clear_bit(PIN_BIT_AFSR, &mcasp->pdir);
+
mcasp->bclk_master = 1;
break;
case SND_SOC_DAIFMT_CBM_CFS:
@@ -470,8 +518,13 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);

- mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR);
- mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR);
+ /* BCLK */
+ clear_bit(PIN_BIT_ACLKX, &mcasp->pdir);
+ clear_bit(PIN_BIT_ACLKR, &mcasp->pdir);
+ /* Frame Sync */
+ set_bit(PIN_BIT_AFSX, &mcasp->pdir);
+ set_bit(PIN_BIT_AFSR, &mcasp->pdir);
+
mcasp->bclk_master = 0;
break;
case SND_SOC_DAIFMT_CBM_CFM:
@@ -482,8 +535,13 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);

- mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG,
- ACLKX | AFSX | ACLKR | AHCLKR | AFSR);
+ /* BCLK */
+ clear_bit(PIN_BIT_ACLKX, &mcasp->pdir);
+ clear_bit(PIN_BIT_ACLKR, &mcasp->pdir);
+ /* Frame Sync */
+ clear_bit(PIN_BIT_AFSX, &mcasp->pdir);
+ clear_bit(PIN_BIT_AFSR, &mcasp->pdir);
+
mcasp->bclk_master = 0;
break;
default:
@@ -598,11 +656,11 @@ static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
if (dir == SND_SOC_CLOCK_OUT) {
mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
- mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AHCLKX);
+ set_bit(PIN_BIT_AHCLKX, &mcasp->pdir);
} else {
mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
- mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AHCLKX);
+ clear_bit(PIN_BIT_AHCLKX, &mcasp->pdir);
}

mcasp->sysclk_freq = freq;
@@ -775,17 +833,21 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
mcasp->serial_dir[i]);
if (mcasp->serial_dir[i] == TX_MODE &&
tx_ser < max_active_serializers) {
- mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AXR(i));
mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
DISMOD_LOW, DISMOD_MASK);
+ set_bit(PIN_BIT_AXR(i), &mcasp->pdir);
tx_ser++;
} else if (mcasp->serial_dir[i] == RX_MODE &&
rx_ser < max_active_serializers) {
- mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AXR(i));
+ clear_bit(PIN_BIT_AXR(i), &mcasp->pdir);
rx_ser++;
} else if (mcasp->serial_dir[i] == INACTIVE_MODE) {
mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
SRMOD_INACTIVE, SRMOD_MASK);
+ clear_bit(PIN_BIT_AXR(i), &mcasp->pdir);
+ } else if (mcasp->serial_dir[i] == TX_MODE) {
+ /* Unused TX pins, clear PDIR */
+ clear_bit(PIN_BIT_AXR(i), &mcasp->pdir);
}
}

diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h
index afddc8010c54..acb024ab6a9d 100644
--- a/sound/soc/davinci/davinci-mcasp.h
+++ b/sound/soc/davinci/davinci-mcasp.h
@@ -108,27 +108,18 @@

/*
* DAVINCI_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits
- */
-#define AXR(n) (1<<n)
-#define PFUNC_AMUTE BIT(25)
-#define ACLKX BIT(26)
-#define AHCLKX BIT(27)
-#define AFSX BIT(28)
-#define ACLKR BIT(29)
-#define AHCLKR BIT(30)
-#define AFSR BIT(31)
-
-/*
* DAVINCI_MCASP_PDIR_REG - Pin Direction Register Bits
+ * DAVINCI_MCASP_PDOUT_REG - Pin output in GPIO mode
+ * DAVINCI_MCASP_PDSET_REG - Pin input in GPIO mode
*/
-#define AXR(n) (1<<n)
-#define PDIR_AMUTE BIT(25)
-#define ACLKX BIT(26)
-#define AHCLKX BIT(27)
-#define AFSX BIT(28)
-#define ACLKR BIT(29)
-#define AHCLKR BIT(30)
-#define AFSR BIT(31)
+#define PIN_BIT_AXR(n) (n)
+#define PIN_BIT_AMUTE 25
+#define PIN_BIT_ACLKX 26
+#define PIN_BIT_AHCLKX 27
+#define PIN_BIT_AFSX 28
+#define PIN_BIT_ACLKR 29
+#define PIN_BIT_AHCLKR 30
+#define PIN_BIT_AFSR 31

/*
* DAVINCI_MCASP_TXDITCTL_REG - Transmit DIT Control Register Bits
--
Peter

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki


2018-11-16 13:41:43

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH 3/4] bindings: sound: davinci-mcasp: Document dismod optional property

The dismod property can be used to specify the drive on level of inactive
TX slots.

Signed-off-by: Peter Ujfalusi <[email protected]>
---
.../devicetree/bindings/sound/davinci-mcasp-audio.txt | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
index 46bc9829c71a..b279b6072bd5 100644
--- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
+++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
@@ -30,6 +30,11 @@ Optional properties:
- ti,hwmods : Must be "mcasp<n>", n is controller instance starting 0
- tx-num-evt : FIFO levels.
- rx-num-evt : FIFO levels.
+- dismod : Specify the drive on TX pin during inactive slots
+ 0 : 3-state
+ 2 : logic low
+ 3 : logic high
+ Defaults to 'logic low' when the property is not present
- sram-size-playback : size of sram to be allocated during playback
- sram-size-capture : size of sram to be allocated during capture
- interrupts : Interrupt numbers for McASP
--
Peter

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki


2018-11-16 13:43:24

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH 4/4] ASoC: davinci-mcasp: Implement configurable dismod handling

If the dismod is specified in the DT node, use the specified custom value
to configure the drive on state of the inactive TX slots.

If the dismod is not present or booted in legacy mode, the dismod is set
to low as it was the original behavior.

Signed-off-by: Peter Ujfalusi <[email protected]>
---
include/linux/platform_data/davinci_asp.h | 1 +
sound/soc/davinci/davinci-mcasp.c | 19 ++++++++++++++++++-
sound/soc/davinci/davinci-mcasp.h | 1 +
3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h
index 85ad68f9206a..7fe80f1c7e08 100644
--- a/include/linux/platform_data/davinci_asp.h
+++ b/include/linux/platform_data/davinci_asp.h
@@ -79,6 +79,7 @@ struct davinci_mcasp_pdata {
/* McASP specific fields */
int tdm_slots;
u8 op_mode;
+ u8 dismod;
u8 num_serializer;
u8 *serial_dir;
u8 version;
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 0f3911be1c8e..40d3a916fb74 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -85,6 +85,7 @@ struct davinci_mcasp {
u32 tdm_mask[2];
int slot_width;
u8 op_mode;
+ u8 dismod;
u8 num_serializer;
u8 *serial_dir;
u8 version;
@@ -834,7 +835,7 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
if (mcasp->serial_dir[i] == TX_MODE &&
tx_ser < max_active_serializers) {
mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
- DISMOD_LOW, DISMOD_MASK);
+ mcasp->dismod, DISMOD_MASK);
set_bit(PIN_BIT_AXR(i), &mcasp->pdir);
tx_ser++;
} else if (mcasp->serial_dir[i] == RX_MODE &&
@@ -847,6 +848,8 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
clear_bit(PIN_BIT_AXR(i), &mcasp->pdir);
} else if (mcasp->serial_dir[i] == TX_MODE) {
/* Unused TX pins, clear PDIR */
+ mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
+ mcasp->dismod, DISMOD_MASK);
clear_bit(PIN_BIT_AXR(i), &mcasp->pdir);
}
}
@@ -1709,6 +1712,7 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of(

if (pdev->dev.platform_data) {
pdata = pdev->dev.platform_data;
+ pdata->dismod = DISMOD_LOW;
return pdata;
} else if (match) {
pdata = devm_kmemdup(&pdev->dev, match->data, sizeof(*pdata),
@@ -1798,6 +1802,18 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of(
if (ret >= 0)
pdata->sram_size_capture = val;

+ ret = of_property_read_u32(np, "dismod", &val);
+ if (ret >= 0) {
+ if (val == 0 || val == 2 || val == 3) {
+ pdata->dismod = DISMOD_VAL(val);
+ } else {
+ dev_warn(&pdev->dev, "Invalid dismod value: %u\n", val);
+ pdata->dismod = DISMOD_LOW;
+ }
+ } else {
+ pdata->dismod = DISMOD_LOW;
+ }
+
return pdata;

nodata:
@@ -1973,6 +1989,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
mcasp->version = pdata->version;
mcasp->txnumevt = pdata->txnumevt;
mcasp->rxnumevt = pdata->rxnumevt;
+ mcasp->dismod = pdata->dismod;

mcasp->dev = &pdev->dev;

diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h
index acb024ab6a9d..5e4060d8fe56 100644
--- a/sound/soc/davinci/davinci-mcasp.h
+++ b/sound/soc/davinci/davinci-mcasp.h
@@ -209,6 +209,7 @@
#define DISMOD_3STATE (0x0)
#define DISMOD_LOW (0x2 << 2)
#define DISMOD_HIGH (0x3 << 2)
+#define DISMOD_VAL(x) ((x) << 2)
#define DISMOD_MASK DISMOD_HIGH
#define TXSTATE BIT(4)
#define RXSTATE BIT(5)
--
Peter

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki


2018-11-28 12:58:18

by Mark Brown

[permalink] [raw]
Subject: Applied "ASoC: davinci-mcasp: Implement configurable dismod handling" to the asoc tree

The patch

ASoC: davinci-mcasp: Implement configurable dismod handling

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 bc184549853133303cf08d1f19477f9c87ef39fb Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <[email protected]>
Date: Fri, 16 Nov 2018 15:41:41 +0200
Subject: [PATCH] ASoC: davinci-mcasp: Implement configurable dismod handling

If the dismod is specified in the DT node, use the specified custom value
to configure the drive on state of the inactive TX slots.

If the dismod is not present or booted in legacy mode, the dismod is set
to low as it was the original behavior.

Signed-off-by: Peter Ujfalusi <[email protected]>
Signed-off-by: Mark Brown <[email protected]>
---
include/linux/platform_data/davinci_asp.h | 1 +
sound/soc/davinci/davinci-mcasp.c | 19 ++++++++++++++++++-
sound/soc/davinci/davinci-mcasp.h | 1 +
3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h
index 85ad68f9206a..7fe80f1c7e08 100644
--- a/include/linux/platform_data/davinci_asp.h
+++ b/include/linux/platform_data/davinci_asp.h
@@ -79,6 +79,7 @@ struct davinci_mcasp_pdata {
/* McASP specific fields */
int tdm_slots;
u8 op_mode;
+ u8 dismod;
u8 num_serializer;
u8 *serial_dir;
u8 version;
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 0f3911be1c8e..40d3a916fb74 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -85,6 +85,7 @@ struct davinci_mcasp {
u32 tdm_mask[2];
int slot_width;
u8 op_mode;
+ u8 dismod;
u8 num_serializer;
u8 *serial_dir;
u8 version;
@@ -834,7 +835,7 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
if (mcasp->serial_dir[i] == TX_MODE &&
tx_ser < max_active_serializers) {
mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
- DISMOD_LOW, DISMOD_MASK);
+ mcasp->dismod, DISMOD_MASK);
set_bit(PIN_BIT_AXR(i), &mcasp->pdir);
tx_ser++;
} else if (mcasp->serial_dir[i] == RX_MODE &&
@@ -847,6 +848,8 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
clear_bit(PIN_BIT_AXR(i), &mcasp->pdir);
} else if (mcasp->serial_dir[i] == TX_MODE) {
/* Unused TX pins, clear PDIR */
+ mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
+ mcasp->dismod, DISMOD_MASK);
clear_bit(PIN_BIT_AXR(i), &mcasp->pdir);
}
}
@@ -1709,6 +1712,7 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of(

if (pdev->dev.platform_data) {
pdata = pdev->dev.platform_data;
+ pdata->dismod = DISMOD_LOW;
return pdata;
} else if (match) {
pdata = devm_kmemdup(&pdev->dev, match->data, sizeof(*pdata),
@@ -1798,6 +1802,18 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of(
if (ret >= 0)
pdata->sram_size_capture = val;

+ ret = of_property_read_u32(np, "dismod", &val);
+ if (ret >= 0) {
+ if (val == 0 || val == 2 || val == 3) {
+ pdata->dismod = DISMOD_VAL(val);
+ } else {
+ dev_warn(&pdev->dev, "Invalid dismod value: %u\n", val);
+ pdata->dismod = DISMOD_LOW;
+ }
+ } else {
+ pdata->dismod = DISMOD_LOW;
+ }
+
return pdata;

nodata:
@@ -1973,6 +1989,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
mcasp->version = pdata->version;
mcasp->txnumevt = pdata->txnumevt;
mcasp->rxnumevt = pdata->rxnumevt;
+ mcasp->dismod = pdata->dismod;

mcasp->dev = &pdev->dev;

diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h
index acb024ab6a9d..5e4060d8fe56 100644
--- a/sound/soc/davinci/davinci-mcasp.h
+++ b/sound/soc/davinci/davinci-mcasp.h
@@ -209,6 +209,7 @@
#define DISMOD_3STATE (0x0)
#define DISMOD_LOW (0x2 << 2)
#define DISMOD_HIGH (0x3 << 2)
+#define DISMOD_VAL(x) ((x) << 2)
#define DISMOD_MASK DISMOD_HIGH
#define TXSTATE BIT(4)
#define RXSTATE BIT(5)
--
2.19.1


2018-11-28 12:58:25

by Mark Brown

[permalink] [raw]
Subject: Applied "ASoC: davinci-mcasp: Document dismod optional property" to the asoc tree

The patch

ASoC: davinci-mcasp: Document dismod optional property

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 a3641b30c19b93b1298028a7210b55145e70056c Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <[email protected]>
Date: Fri, 16 Nov 2018 15:41:40 +0200
Subject: [PATCH] ASoC: davinci-mcasp: Document dismod optional property

The dismod property can be used to specify the drive on level of inactive
TX slots.

Signed-off-by: Peter Ujfalusi <[email protected]>
Signed-off-by: Mark Brown <[email protected]>
---
.../devicetree/bindings/sound/davinci-mcasp-audio.txt | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
index 46bc9829c71a..b279b6072bd5 100644
--- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
+++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
@@ -30,6 +30,11 @@ Optional properties:
- ti,hwmods : Must be "mcasp<n>", n is controller instance starting 0
- tx-num-evt : FIFO levels.
- rx-num-evt : FIFO levels.
+- dismod : Specify the drive on TX pin during inactive slots
+ 0 : 3-state
+ 2 : logic low
+ 3 : logic high
+ Defaults to 'logic low' when the property is not present
- sram-size-playback : size of sram to be allocated during playback
- sram-size-capture : size of sram to be allocated during capture
- interrupts : Interrupt numbers for McASP
--
2.19.1


2018-11-28 12:59:48

by Mark Brown

[permalink] [raw]
Subject: Applied "ASoC: davinci-mcasp: Update PDIR (pin direction) register handling" to the asoc tree

The patch

ASoC: davinci-mcasp: Update PDIR (pin direction) register handling

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 ca3d9433349ed6a8eadfc9d0ec9e88fff439d0e9 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <[email protected]>
Date: Fri, 16 Nov 2018 15:41:39 +0200
Subject: [PATCH] ASoC: davinci-mcasp: Update PDIR (pin direction) register
handling

When McASP is master and the PDIR for the clock pins are configured as
outputs before the clocking is configured it will output whatever clock
is generated at the moment internally.
The clock will switch to the correct rate only when the we start the clock
generators.

To avoid this we must only set the pin as output after the clock is
configured and enabled.

AXR pins configured as outputs behaves somehow interesting as well:
when McASP is not enabled and the pin is selected as output it will not
honor the DISMOD settings for the inactive state, but will pull the pin
down.

Add a new bitfield and mark the pins there which needs to be output and
set the pins only at the time when they will behave correctly.

On stream stop configure the pins back to input which makes them to obey
the global pin configuration regarding to pull up/down.

Signed-off-by: Peter Ujfalusi <[email protected]>
Signed-off-by: Mark Brown <[email protected]>
---
sound/soc/davinci/davinci-mcasp.c | 88 ++++++++++++++++++++++++++-----
sound/soc/davinci/davinci-mcasp.h | 29 ++++------
2 files changed, 85 insertions(+), 32 deletions(-)

diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 740030b4d37a..0f3911be1c8e 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -28,6 +28,7 @@
#include <linux/of_device.h>
#include <linux/platform_data/davinci_asp.h>
#include <linux/math64.h>
+#include <linux/bitmap.h>

#include <sound/asoundef.h>
#include <sound/core.h>
@@ -95,6 +96,8 @@ struct davinci_mcasp {
int sysclk_freq;
bool bclk_master;

+ unsigned long pdir; /* Pin direction bitfield */
+
/* McASP FIFO related */
u8 txnumevt;
u8 rxnumevt;
@@ -169,6 +172,30 @@ static bool mcasp_is_synchronous(struct davinci_mcasp *mcasp)
return !(aclkxctl & TX_ASYNC) && rxfmctl & AFSRE;
}

+static inline void mcasp_set_clk_pdir(struct davinci_mcasp *mcasp, bool enable)
+{
+ u32 bit = PIN_BIT_AMUTE;
+
+ for_each_set_bit_from(bit, &mcasp->pdir, PIN_BIT_AFSR + 1) {
+ if (enable)
+ mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit));
+ else
+ mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit));
+ }
+}
+
+static inline void mcasp_set_axr_pdir(struct davinci_mcasp *mcasp, bool enable)
+{
+ u32 bit;
+
+ for_each_set_bit(bit, &mcasp->pdir, PIN_BIT_AFSR) {
+ if (enable)
+ mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit));
+ else
+ mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit));
+ }
+}
+
static void mcasp_start_rx(struct davinci_mcasp *mcasp)
{
if (mcasp->rxnumevt) { /* enable FIFO */
@@ -220,6 +247,8 @@ static void mcasp_start_tx(struct davinci_mcasp *mcasp)
/* Start clocks */
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
+ mcasp_set_clk_pdir(mcasp, true);
+
/* Activate serializer(s) */
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
@@ -230,6 +259,8 @@ static void mcasp_start_tx(struct davinci_mcasp *mcasp)
(cnt < 100000))
cnt++;

+ mcasp_set_axr_pdir(mcasp, true);
+
/* Release TX state machine */
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
/* Release Frame Sync generator */
@@ -260,8 +291,10 @@ static void mcasp_stop_rx(struct davinci_mcasp *mcasp)
* In synchronous mode stop the TX clocks if no other stream is
* running
*/
- if (mcasp_is_synchronous(mcasp) && !mcasp->streams)
+ if (mcasp_is_synchronous(mcasp) && !mcasp->streams) {
+ mcasp_set_clk_pdir(mcasp, false);
mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, 0);
+ }

mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, 0);
mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
@@ -287,6 +320,9 @@ static void mcasp_stop_tx(struct davinci_mcasp *mcasp)
*/
if (mcasp_is_synchronous(mcasp) && mcasp->streams)
val = TXHCLKRST | TXCLKRST | TXFSRST;
+ else
+ mcasp_set_clk_pdir(mcasp, false);
+

mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, val);
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
@@ -296,6 +332,8 @@ static void mcasp_stop_tx(struct davinci_mcasp *mcasp)

mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
}
+
+ mcasp_set_axr_pdir(mcasp, false);
}

static void davinci_mcasp_stop(struct davinci_mcasp *mcasp, int stream)
@@ -446,8 +484,13 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);

- mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR);
- mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR);
+ /* BCLK */
+ set_bit(PIN_BIT_ACLKX, &mcasp->pdir);
+ set_bit(PIN_BIT_ACLKR, &mcasp->pdir);
+ /* Frame Sync */
+ set_bit(PIN_BIT_AFSX, &mcasp->pdir);
+ set_bit(PIN_BIT_AFSR, &mcasp->pdir);
+
mcasp->bclk_master = 1;
break;
case SND_SOC_DAIFMT_CBS_CFM:
@@ -458,8 +501,13 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);

- mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR);
- mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR);
+ /* BCLK */
+ set_bit(PIN_BIT_ACLKX, &mcasp->pdir);
+ set_bit(PIN_BIT_ACLKR, &mcasp->pdir);
+ /* Frame Sync */
+ clear_bit(PIN_BIT_AFSX, &mcasp->pdir);
+ clear_bit(PIN_BIT_AFSR, &mcasp->pdir);
+
mcasp->bclk_master = 1;
break;
case SND_SOC_DAIFMT_CBM_CFS:
@@ -470,8 +518,13 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);

- mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR);
- mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR);
+ /* BCLK */
+ clear_bit(PIN_BIT_ACLKX, &mcasp->pdir);
+ clear_bit(PIN_BIT_ACLKR, &mcasp->pdir);
+ /* Frame Sync */
+ set_bit(PIN_BIT_AFSX, &mcasp->pdir);
+ set_bit(PIN_BIT_AFSR, &mcasp->pdir);
+
mcasp->bclk_master = 0;
break;
case SND_SOC_DAIFMT_CBM_CFM:
@@ -482,8 +535,13 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);

- mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG,
- ACLKX | AFSX | ACLKR | AHCLKR | AFSR);
+ /* BCLK */
+ clear_bit(PIN_BIT_ACLKX, &mcasp->pdir);
+ clear_bit(PIN_BIT_ACLKR, &mcasp->pdir);
+ /* Frame Sync */
+ clear_bit(PIN_BIT_AFSX, &mcasp->pdir);
+ clear_bit(PIN_BIT_AFSR, &mcasp->pdir);
+
mcasp->bclk_master = 0;
break;
default:
@@ -598,11 +656,11 @@ static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
if (dir == SND_SOC_CLOCK_OUT) {
mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
- mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AHCLKX);
+ set_bit(PIN_BIT_AHCLKX, &mcasp->pdir);
} else {
mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
- mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AHCLKX);
+ clear_bit(PIN_BIT_AHCLKX, &mcasp->pdir);
}

mcasp->sysclk_freq = freq;
@@ -775,17 +833,21 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
mcasp->serial_dir[i]);
if (mcasp->serial_dir[i] == TX_MODE &&
tx_ser < max_active_serializers) {
- mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AXR(i));
mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
DISMOD_LOW, DISMOD_MASK);
+ set_bit(PIN_BIT_AXR(i), &mcasp->pdir);
tx_ser++;
} else if (mcasp->serial_dir[i] == RX_MODE &&
rx_ser < max_active_serializers) {
- mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AXR(i));
+ clear_bit(PIN_BIT_AXR(i), &mcasp->pdir);
rx_ser++;
} else if (mcasp->serial_dir[i] == INACTIVE_MODE) {
mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
SRMOD_INACTIVE, SRMOD_MASK);
+ clear_bit(PIN_BIT_AXR(i), &mcasp->pdir);
+ } else if (mcasp->serial_dir[i] == TX_MODE) {
+ /* Unused TX pins, clear PDIR */
+ clear_bit(PIN_BIT_AXR(i), &mcasp->pdir);
}
}

diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h
index afddc8010c54..acb024ab6a9d 100644
--- a/sound/soc/davinci/davinci-mcasp.h
+++ b/sound/soc/davinci/davinci-mcasp.h
@@ -108,27 +108,18 @@

/*
* DAVINCI_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits
- */
-#define AXR(n) (1<<n)
-#define PFUNC_AMUTE BIT(25)
-#define ACLKX BIT(26)
-#define AHCLKX BIT(27)
-#define AFSX BIT(28)
-#define ACLKR BIT(29)
-#define AHCLKR BIT(30)
-#define AFSR BIT(31)
-
-/*
* DAVINCI_MCASP_PDIR_REG - Pin Direction Register Bits
+ * DAVINCI_MCASP_PDOUT_REG - Pin output in GPIO mode
+ * DAVINCI_MCASP_PDSET_REG - Pin input in GPIO mode
*/
-#define AXR(n) (1<<n)
-#define PDIR_AMUTE BIT(25)
-#define ACLKX BIT(26)
-#define AHCLKX BIT(27)
-#define AFSX BIT(28)
-#define ACLKR BIT(29)
-#define AHCLKR BIT(30)
-#define AFSR BIT(31)
+#define PIN_BIT_AXR(n) (n)
+#define PIN_BIT_AMUTE 25
+#define PIN_BIT_ACLKX 26
+#define PIN_BIT_AHCLKX 27
+#define PIN_BIT_AFSX 28
+#define PIN_BIT_ACLKR 29
+#define PIN_BIT_AHCLKR 30
+#define PIN_BIT_AFSR 31

/*
* DAVINCI_MCASP_TXDITCTL_REG - Transmit DIT Control Register Bits
--
2.19.1


2018-11-28 12:59:55

by Mark Brown

[permalink] [raw]
Subject: Applied "ASoC: davinci-mcasp: Clear TXSTAT register before activating serializers" to the asoc tree

The patch

ASoC: davinci-mcasp: Clear TXSTAT register before activating serializers

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 1003c27acfc2174558b2a0803bd6974e19be2738 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <[email protected]>
Date: Fri, 16 Nov 2018 15:41:38 +0200
Subject: [PATCH] ASoC: davinci-mcasp: Clear TXSTAT register before activating
serializers

Follow the guideline from the TRM:
Before starting, clear the respective transmitter and receiver status
registers

To avoid stale state stored in the status registers.

Signed-off-by: Peter Ujfalusi <[email protected]>
Signed-off-by: Mark Brown <[email protected]>
---
sound/soc/davinci/davinci-mcasp.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 267aee776b2d..740030b4d37a 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -192,6 +192,7 @@ static void mcasp_start_rx(struct davinci_mcasp *mcasp)
}

/* Activate serializer(s) */
+ mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
/* Release RX state machine */
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
@@ -220,6 +221,7 @@ static void mcasp_start_tx(struct davinci_mcasp *mcasp)
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
/* Activate serializer(s) */
+ mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);

/* wait for XDATA to be cleared */
--
2.19.1