Skip to content

Commit

Permalink
Merge remote-tracking branch 'asoc/topic/davinci' into asoc-next
Browse files Browse the repository at this point in the history
  • Loading branch information
Mark Brown committed Dec 9, 2012
2 parents 5776954 + 1b3bc06 commit 1bd202e
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 97 deletions.
24 changes: 14 additions & 10 deletions arch/arm/mach-davinci/board-da850-evm.c
Original file line number Diff line number Diff line change
Expand Up @@ -762,16 +762,19 @@ static u8 da850_iis_serializer_direction[] = {
};

static struct snd_platform_data da850_evm_snd_data = {
.tx_dma_offset = 0x2000,
.rx_dma_offset = 0x2000,
.op_mode = DAVINCI_MCASP_IIS_MODE,
.num_serializer = ARRAY_SIZE(da850_iis_serializer_direction),
.tdm_slots = 2,
.serial_dir = da850_iis_serializer_direction,
.asp_chan_q = EVENTQ_0,
.version = MCASP_VERSION_2,
.txnumevt = 1,
.rxnumevt = 1,
.tx_dma_offset = 0x2000,
.rx_dma_offset = 0x2000,
.op_mode = DAVINCI_MCASP_IIS_MODE,
.num_serializer = ARRAY_SIZE(da850_iis_serializer_direction),
.tdm_slots = 2,
.serial_dir = da850_iis_serializer_direction,
.asp_chan_q = EVENTQ_0,
.ram_chan_q = EVENTQ_1,
.version = MCASP_VERSION_2,
.txnumevt = 1,
.rxnumevt = 1,
.sram_size_playback = SZ_8K,
.sram_size_capture = SZ_8K,
};

static const short da850_evm_mcasp_pins[] __initconst = {
Expand Down Expand Up @@ -1509,6 +1512,7 @@ static __init void da850_evm_init(void)
pr_warning("da850_evm_init: mcasp mux setup failed: %d\n",
ret);

da850_evm_snd_data.sram_pool = sram_get_gen_pool();
da8xx_register_mcasp(0, &da850_evm_snd_data);

ret = davinci_cfg_reg_list(da850_lcdcntl_pins);
Expand Down
4 changes: 3 additions & 1 deletion include/linux/platform_data/davinci_asp.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@
#ifndef __DAVINCI_ASP_H
#define __DAVINCI_ASP_H

#include <linux/genalloc.h>

struct snd_platform_data {
u32 tx_dma_offset;
u32 rx_dma_offset;
int asp_chan_q; /* event queue number for ASP channel */
int ram_chan_q; /* event queue number for RAM channel */
unsigned int codec_fmt;
/*
* Allowing this is more efficient and eliminates left and right swaps
* caused by underruns, but will swap the left and right channels
Expand All @@ -30,6 +31,7 @@ struct snd_platform_data {
unsigned enable_channel_combine:1;
unsigned sram_size_playback;
unsigned sram_size_capture;
struct gen_pool *sram_pool;

/*
* If McBSP peripheral gets the clock from an external pin,
Expand Down
5 changes: 5 additions & 0 deletions sound/soc/davinci/davinci-evm.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
if (ret < 0)
return ret;

/* set the CPU system clock */
ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
if (ret < 0)
return ret;

return 0;
}

Expand Down
152 changes: 97 additions & 55 deletions sound/soc/davinci/davinci-mcasp.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@
#define ACLKXE BIT(5)
#define TX_ASYNC BIT(6)
#define ACLKXPOL BIT(7)
#define ACLKXDIV_MASK 0x1f

/*
* DAVINCI_MCASP_ACLKRCTL_REG Receive Clock Control Register Bits
Expand All @@ -207,6 +208,7 @@
#define ACLKRE BIT(5)
#define RX_ASYNC BIT(6)
#define ACLKRPOL BIT(7)
#define ACLKRDIV_MASK 0x1f

/*
* DAVINCI_MCASP_AHCLKXCTL_REG - High Frequency Transmit Clock Control
Expand All @@ -215,6 +217,7 @@
#define AHCLKXDIV(val) (val)
#define AHCLKXPOL BIT(14)
#define AHCLKXE BIT(15)
#define AHCLKXDIV_MASK 0xfff

/*
* DAVINCI_MCASP_AHCLKRCTL_REG - High Frequency Receive Clock Control
Expand All @@ -223,6 +226,7 @@
#define AHCLKRDIV(val) (val)
#define AHCLKRPOL BIT(14)
#define AHCLKRE BIT(15)
#define AHCLKRDIV_MASK 0xfff

/*
* DAVINCI_MCASP_XRSRCTL_BASE_REG - Serializer Control Register Bits
Expand Down Expand Up @@ -473,6 +477,23 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
void __iomem *base = dev->base;

switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_DSP_B:
case SND_SOC_DAIFMT_AC97:
mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
break;
default:
/* configure a full-word SYNC pulse (LRCLK) */
mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);

/* make 1st data bit occur one ACLK cycle after the frame sync */
mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, FSXDLY(1));
mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, FSRDLY(1));
break;
}

switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
/* codec is clock and frame slave */
Expand All @@ -482,8 +503,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);

mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG,
ACLKX | AHCLKX | AFSX);
mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, ACLKX | AFSX);
break;
case SND_SOC_DAIFMT_CBM_CFS:
/* codec is clock master and frame slave */
Expand Down Expand Up @@ -554,59 +574,75 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
return 0;
}

static int davinci_config_channel_size(struct davinci_audio_dev *dev,
int channel_size)
static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
{
u32 fmt = 0;
u32 mask, rotate;

switch (channel_size) {
case DAVINCI_AUDIO_WORD_8:
fmt = 0x03;
rotate = 6;
mask = 0x000000ff;
break;
struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);

case DAVINCI_AUDIO_WORD_12:
fmt = 0x05;
rotate = 5;
mask = 0x00000fff;
switch (div_id) {
case 0: /* MCLK divider */
mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
AHCLKXDIV(div - 1), AHCLKXDIV_MASK);
mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
AHCLKRDIV(div - 1), AHCLKRDIV_MASK);
break;

case DAVINCI_AUDIO_WORD_16:
fmt = 0x07;
rotate = 4;
mask = 0x0000ffff;
case 1: /* BCLK divider */
mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
ACLKXDIV(div - 1), ACLKXDIV_MASK);
mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKRCTL_REG,
ACLKRDIV(div - 1), ACLKRDIV_MASK);
break;

case DAVINCI_AUDIO_WORD_20:
fmt = 0x09;
rotate = 3;
mask = 0x000fffff;
case 2: /* BCLK/LRCLK ratio */
dev->bclk_lrclk_ratio = div;
break;

case DAVINCI_AUDIO_WORD_24:
fmt = 0x0B;
rotate = 2;
mask = 0x00ffffff;
break;
default:
return -EINVAL;
}

case DAVINCI_AUDIO_WORD_28:
fmt = 0x0D;
rotate = 1;
mask = 0x0fffffff;
break;
return 0;
}

case DAVINCI_AUDIO_WORD_32:
fmt = 0x0F;
rotate = 0;
mask = 0xffffffff;
break;
static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
unsigned int freq, int dir)
{
struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);

default:
return -EINVAL;
if (dir == SND_SOC_CLOCK_OUT) {
mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AHCLKX);
} else {
mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AHCLKX);
}

return 0;
}

static int davinci_config_channel_size(struct davinci_audio_dev *dev,
int word_length)
{
u32 fmt;
u32 rotate = (32 - word_length) / 4;
u32 mask = (1ULL << word_length) - 1;

/*
* if s BCLK-to-LRCLK ratio has been configured via the set_clkdiv()
* callback, take it into account here. That allows us to for example
* send 32 bits per channel to the codec, while only 16 of them carry
* audio payload.
* The clock ratio is given for a full period of data (both left and
* right channels), so it has to be divided by 2.
*/
if (dev->bclk_lrclk_ratio)
word_length = dev->bclk_lrclk_ratio / 2;

/* mapping of the XSSZ bit-field as described in the datasheet */
fmt = (word_length >> 1) - 1;

mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
RXSSZ(fmt), RXSSZ(0x0F));
mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
Expand Down Expand Up @@ -709,8 +745,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
/* bit stream is MSB first with no delay */
/* DSP_B mode */
mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
AHCLKXE);
mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);

Expand All @@ -720,14 +754,10 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
else
printk(KERN_ERR "playback tdm slot %d not supported\n",
dev->tdm_slots);

mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
} else {
/* bit stream is MSB first with no delay */
/* DSP_B mode */
mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD);
mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
AHCLKRE);
mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);

if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32))
Expand All @@ -736,8 +766,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
else
printk(KERN_ERR "capture tdm slot %d not supported\n",
dev->tdm_slots);

mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
}
}

Expand Down Expand Up @@ -800,19 +828,27 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
case SNDRV_PCM_FORMAT_U8:
case SNDRV_PCM_FORMAT_S8:
dma_params->data_type = 1;
word_length = DAVINCI_AUDIO_WORD_8;
word_length = 8;
break;

case SNDRV_PCM_FORMAT_U16_LE:
case SNDRV_PCM_FORMAT_S16_LE:
dma_params->data_type = 2;
word_length = DAVINCI_AUDIO_WORD_16;
word_length = 16;
break;

case SNDRV_PCM_FORMAT_U24_3LE:
case SNDRV_PCM_FORMAT_S24_3LE:
dma_params->data_type = 3;
word_length = 24;
break;

case SNDRV_PCM_FORMAT_U24_LE:
case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_U32_LE:
case SNDRV_PCM_FORMAT_S32_LE:
dma_params->data_type = 4;
word_length = DAVINCI_AUDIO_WORD_32;
word_length = 32;
break;

default:
Expand Down Expand Up @@ -880,13 +916,18 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
.trigger = davinci_mcasp_trigger,
.hw_params = davinci_mcasp_hw_params,
.set_fmt = davinci_mcasp_set_dai_fmt,

.set_clkdiv = davinci_mcasp_set_clkdiv,
.set_sysclk = davinci_mcasp_set_sysclk,
};

#define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_U8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_U16_LE | \
SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_U24_LE | \
SNDRV_PCM_FMTBIT_S24_3LE | \
SNDRV_PCM_FMTBIT_U24_3LE | \
SNDRV_PCM_FMTBIT_S32_LE | \
SNDRV_PCM_FMTBIT_U32_LE)

Expand Down Expand Up @@ -1089,7 +1130,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
dev->tdm_slots = pdata->tdm_slots;
dev->num_serializer = pdata->num_serializer;
dev->serial_dir = pdata->serial_dir;
dev->codec_fmt = pdata->codec_fmt;
dev->version = pdata->version;
dev->txnumevt = pdata->txnumevt;
dev->rxnumevt = pdata->rxnumevt;
Expand All @@ -1098,6 +1138,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
dma_data->asp_chan_q = pdata->asp_chan_q;
dma_data->ram_chan_q = pdata->ram_chan_q;
dma_data->sram_pool = pdata->sram_pool;
dma_data->sram_size = pdata->sram_size_playback;
dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
mem->start);
Expand All @@ -1115,6 +1156,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE];
dma_data->asp_chan_q = pdata->asp_chan_q;
dma_data->ram_chan_q = pdata->ram_chan_q;
dma_data->sram_pool = pdata->sram_pool;
dma_data->sram_size = pdata->sram_size_capture;
dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
mem->start);
Expand Down
15 changes: 2 additions & 13 deletions sound/soc/davinci/davinci-mcasp.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,22 @@

#include "davinci-pcm.h"

#define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000
#define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_192000
#define DAVINCI_MCASP_I2S_DAI 0
#define DAVINCI_MCASP_DIT_DAI 1

enum {
DAVINCI_AUDIO_WORD_8 = 0,
DAVINCI_AUDIO_WORD_12,
DAVINCI_AUDIO_WORD_16,
DAVINCI_AUDIO_WORD_20,
DAVINCI_AUDIO_WORD_24,
DAVINCI_AUDIO_WORD_32,
DAVINCI_AUDIO_WORD_28, /* This is only valid for McASP */
};

struct davinci_audio_dev {
struct davinci_pcm_dma_params dma_params[2];
void __iomem *base;
int sample_rate;
struct device *dev;
unsigned int codec_fmt;

/* McASP specific data */
int tdm_slots;
u8 op_mode;
u8 num_serializer;
u8 *serial_dir;
u8 version;
u8 bclk_lrclk_ratio;

/* McASP FIFO related */
u8 txnumevt;
Expand Down
Loading

0 comments on commit 1bd202e

Please sign in to comment.