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 #include #include +#include #include #include @@ -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<