Commit ca3d9433 authored by Peter Ujfalusi's avatar Peter Ujfalusi Committed by Mark Brown

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: default avatarPeter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 1003c27a
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/platform_data/davinci_asp.h> #include <linux/platform_data/davinci_asp.h>
#include <linux/math64.h> #include <linux/math64.h>
#include <linux/bitmap.h>
#include <sound/asoundef.h> #include <sound/asoundef.h>
#include <sound/core.h> #include <sound/core.h>
...@@ -95,6 +96,8 @@ struct davinci_mcasp { ...@@ -95,6 +96,8 @@ struct davinci_mcasp {
int sysclk_freq; int sysclk_freq;
bool bclk_master; bool bclk_master;
unsigned long pdir; /* Pin direction bitfield */
/* McASP FIFO related */ /* McASP FIFO related */
u8 txnumevt; u8 txnumevt;
u8 rxnumevt; u8 rxnumevt;
...@@ -169,6 +172,30 @@ static bool mcasp_is_synchronous(struct davinci_mcasp *mcasp) ...@@ -169,6 +172,30 @@ static bool mcasp_is_synchronous(struct davinci_mcasp *mcasp)
return !(aclkxctl & TX_ASYNC) && rxfmctl & AFSRE; 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) static void mcasp_start_rx(struct davinci_mcasp *mcasp)
{ {
if (mcasp->rxnumevt) { /* enable FIFO */ if (mcasp->rxnumevt) { /* enable FIFO */
...@@ -220,6 +247,8 @@ static void mcasp_start_tx(struct davinci_mcasp *mcasp) ...@@ -220,6 +247,8 @@ static void mcasp_start_tx(struct davinci_mcasp *mcasp)
/* Start clocks */ /* Start clocks */
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
mcasp_set_clk_pdir(mcasp, true);
/* Activate serializer(s) */ /* Activate serializer(s) */
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR); mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
...@@ -230,6 +259,8 @@ static void mcasp_start_tx(struct davinci_mcasp *mcasp) ...@@ -230,6 +259,8 @@ static void mcasp_start_tx(struct davinci_mcasp *mcasp)
(cnt < 100000)) (cnt < 100000))
cnt++; cnt++;
mcasp_set_axr_pdir(mcasp, true);
/* Release TX state machine */ /* Release TX state machine */
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST); mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
/* Release Frame Sync generator */ /* Release Frame Sync generator */
...@@ -260,8 +291,10 @@ static void mcasp_stop_rx(struct davinci_mcasp *mcasp) ...@@ -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 * In synchronous mode stop the TX clocks if no other stream is
* running * 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_GBLCTLX_REG, 0);
}
mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, 0); mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, 0);
mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
...@@ -287,6 +320,9 @@ static void mcasp_stop_tx(struct davinci_mcasp *mcasp) ...@@ -287,6 +320,9 @@ static void mcasp_stop_tx(struct davinci_mcasp *mcasp)
*/ */
if (mcasp_is_synchronous(mcasp) && mcasp->streams) if (mcasp_is_synchronous(mcasp) && mcasp->streams)
val = TXHCLKRST | TXCLKRST | TXFSRST; 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_GBLCTLX_REG, val);
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
...@@ -296,6 +332,8 @@ static void mcasp_stop_tx(struct davinci_mcasp *mcasp) ...@@ -296,6 +332,8 @@ static void mcasp_stop_tx(struct davinci_mcasp *mcasp)
mcasp_clr_bits(mcasp, reg, FIFO_ENABLE); mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
} }
mcasp_set_axr_pdir(mcasp, false);
} }
static void davinci_mcasp_stop(struct davinci_mcasp *mcasp, int stream) 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, ...@@ -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_ACLKRCTL_REG, ACLKRE);
mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE); mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR); /* BCLK */
mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR); 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; mcasp->bclk_master = 1;
break; break;
case SND_SOC_DAIFMT_CBS_CFM: case SND_SOC_DAIFMT_CBS_CFM:
...@@ -458,8 +501,13 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, ...@@ -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_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE); mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR); /* BCLK */
mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR); 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; mcasp->bclk_master = 1;
break; break;
case SND_SOC_DAIFMT_CBM_CFS: case SND_SOC_DAIFMT_CBM_CFS:
...@@ -470,8 +518,13 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, ...@@ -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_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE); mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR); /* BCLK */
mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR); 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; mcasp->bclk_master = 0;
break; break;
case SND_SOC_DAIFMT_CBM_CFM: case SND_SOC_DAIFMT_CBM_CFM:
...@@ -482,8 +535,13 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, ...@@ -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_ACLKRCTL_REG, ACLKRE);
mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE); mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, /* BCLK */
ACLKX | AFSX | ACLKR | AHCLKR | AFSR); 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; mcasp->bclk_master = 0;
break; break;
default: default:
...@@ -598,11 +656,11 @@ static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id, ...@@ -598,11 +656,11 @@ static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
if (dir == SND_SOC_CLOCK_OUT) { if (dir == SND_SOC_CLOCK_OUT) {
mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE); mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE); 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 { } else {
mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE); mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE); 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; mcasp->sysclk_freq = freq;
...@@ -775,17 +833,21 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, ...@@ -775,17 +833,21 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
mcasp->serial_dir[i]); mcasp->serial_dir[i]);
if (mcasp->serial_dir[i] == TX_MODE && if (mcasp->serial_dir[i] == TX_MODE &&
tx_ser < max_active_serializers) { tx_ser < max_active_serializers) {
mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AXR(i));
mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
DISMOD_LOW, DISMOD_MASK); DISMOD_LOW, DISMOD_MASK);
set_bit(PIN_BIT_AXR(i), &mcasp->pdir);
tx_ser++; tx_ser++;
} else if (mcasp->serial_dir[i] == RX_MODE && } else if (mcasp->serial_dir[i] == RX_MODE &&
rx_ser < max_active_serializers) { 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++; rx_ser++;
} else if (mcasp->serial_dir[i] == INACTIVE_MODE) { } else if (mcasp->serial_dir[i] == INACTIVE_MODE) {
mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
SRMOD_INACTIVE, SRMOD_MASK); 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);
} }
} }
......
...@@ -108,27 +108,18 @@ ...@@ -108,27 +108,18 @@
/* /*
* DAVINCI_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits * 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_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 PIN_BIT_AXR(n) (n)
#define PDIR_AMUTE BIT(25) #define PIN_BIT_AMUTE 25
#define ACLKX BIT(26) #define PIN_BIT_ACLKX 26
#define AHCLKX BIT(27) #define PIN_BIT_AHCLKX 27
#define AFSX BIT(28) #define PIN_BIT_AFSX 28
#define ACLKR BIT(29) #define PIN_BIT_ACLKR 29
#define AHCLKR BIT(30) #define PIN_BIT_AHCLKR 30
#define AFSR BIT(31) #define PIN_BIT_AFSR 31
/* /*
* DAVINCI_MCASP_TXDITCTL_REG - Transmit DIT Control Register Bits * DAVINCI_MCASP_TXDITCTL_REG - Transmit DIT Control Register Bits
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment