diff options
-rw-r--r-- | arch/arm/mach-davinci/board-da850-evm.c | 24 | ||||
-rw-r--r-- | include/linux/platform_data/davinci_asp.h | 3 | ||||
-rw-r--r-- | sound/soc/davinci/davinci-evm.c | 5 | ||||
-rw-r--r-- | sound/soc/davinci/davinci-mcasp.c | 93 | ||||
-rw-r--r-- | sound/soc/davinci/davinci-mcasp.h | 2 | ||||
-rw-r--r-- | sound/soc/davinci/davinci-pcm.c | 53 | ||||
-rw-r--r-- | sound/soc/davinci/davinci-pcm.h | 2 |
7 files changed, 142 insertions, 40 deletions
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index 32ee3f895967..d9bc3fa7bb22 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -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 = { @@ -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); diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h index d0c5825876f8..f3d6e4f20962 100644 --- a/include/linux/platform_data/davinci_asp.h +++ b/include/linux/platform_data/davinci_asp.h @@ -16,6 +16,8 @@ #ifndef __DAVINCI_ASP_H #define __DAVINCI_ASP_H +#include <linux/genalloc.h> + struct snd_platform_data { u32 tx_dma_offset; u32 rx_dma_offset; @@ -30,6 +32,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, diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 6fac5af13298..d55e6477bff0 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -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; } diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 714e51e5be5b..571559501b0b 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 */ @@ -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 */ @@ -554,6 +574,50 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, return 0; } +static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) +{ + struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai); + + 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 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; + + default: + return -EINVAL; + } + + return 0; +} + +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); + + 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 channel_size) { @@ -709,8 +773,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); @@ -720,14 +782,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)) @@ -736,8 +794,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); } } @@ -809,6 +865,14 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, word_length = DAVINCI_AUDIO_WORD_16; break; + case SNDRV_PCM_FORMAT_U24_3LE: + case SNDRV_PCM_FORMAT_S24_3LE: + dma_params->data_type = 3; + word_length = DAVINCI_AUDIO_WORD_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; @@ -880,13 +944,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) @@ -1098,6 +1167,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); @@ -1115,6 +1185,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); diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h index 0de9ed6ce038..156f15f55744 100644 --- a/sound/soc/davinci/davinci-mcasp.h +++ b/sound/soc/davinci/davinci-mcasp.h @@ -23,7 +23,7 @@ #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 diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 93ea3bf567e1..afab81f844ae 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c @@ -16,6 +16,7 @@ #include <linux/slab.h> #include <linux/dma-mapping.h> #include <linux/kernel.h> +#include <linux/genalloc.h> #include <sound/core.h> #include <sound/pcm.h> @@ -23,7 +24,6 @@ #include <sound/soc.h> #include <asm/dma.h> -#include <mach/sram.h> #include "davinci-pcm.h" @@ -67,13 +67,9 @@ static struct snd_pcm_hardware pcm_hardware_playback = { SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME| SNDRV_PCM_INFO_BATCH), .formats = DAVINCI_PCM_FMTBITS, - .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_KNOT), + .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT, .rate_min = 8000, - .rate_max = 96000, + .rate_max = 192000, .channels_min = 2, .channels_max = 384, .buffer_bytes_max = 128 * 1024, @@ -90,13 +86,9 @@ static struct snd_pcm_hardware pcm_hardware_capture = { SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_BATCH), .formats = DAVINCI_PCM_FMTBITS, - .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_KNOT), + .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT, .rate_min = 8000, - .rate_max = 96000, + .rate_max = 192000, .channels_min = 2, .channels_max = 384, .buffer_bytes_max = 128 * 1024, @@ -259,7 +251,9 @@ static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data) } } -static int allocate_sram(struct snd_pcm_substream *substream, unsigned size, +#ifdef CONFIG_GENERIC_ALLOCATOR +static int allocate_sram(struct snd_pcm_substream *substream, + struct gen_pool *sram_pool, unsigned size, struct snd_pcm_hardware *ppcm) { struct snd_dma_buffer *buf = &substream->dma_buffer; @@ -271,9 +265,10 @@ static int allocate_sram(struct snd_pcm_substream *substream, unsigned size, return 0; ppcm->period_bytes_max = size; - iram_virt = sram_alloc(size, &iram_phys); + iram_virt = (void *)gen_pool_alloc(sram_pool, size); if (!iram_virt) goto exit1; + iram_phys = gen_pool_virt_to_phys(sram_pool, (unsigned)iram_virt); iram_dma = kzalloc(sizeof(*iram_dma), GFP_KERNEL); if (!iram_dma) goto exit2; @@ -285,11 +280,33 @@ static int allocate_sram(struct snd_pcm_substream *substream, unsigned size, return 0; exit2: if (iram_virt) - sram_free(iram_virt, size); + gen_pool_free(sram_pool, (unsigned)iram_virt, size); exit1: return -ENOMEM; } +static void davinci_free_sram(struct snd_pcm_substream *substream, + struct snd_dma_buffer *iram_dma) +{ + struct davinci_runtime_data *prtd = substream->runtime->private_data; + struct gen_pool *sram_pool = prtd->params->sram_pool; + + gen_pool_free(sram_pool, (unsigned) iram_dma->area, iram_dma->bytes); +} +#else +static int allocate_sram(struct snd_pcm_substream *substream, + struct gen_pool *sram_pool, unsigned size, + struct snd_pcm_hardware *ppcm) +{ + return 0; +} + +static void davinci_free_sram(struct snd_pcm_substream *substream, + struct snd_dma_buffer *iram_dma) +{ +} +#endif + /* * Only used with ping/pong. * This is called after runtime->dma_addr, period_bytes and data_type are valid @@ -676,7 +693,7 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream) ppcm = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? &pcm_hardware_playback : &pcm_hardware_capture; - allocate_sram(substream, params->sram_size, ppcm); + allocate_sram(substream, params->sram_pool, params->sram_size, ppcm); snd_soc_set_runtime_hwparams(substream, ppcm); /* ensure that buffer size is a multiple of period size */ ret = snd_pcm_hw_constraint_integer(runtime, @@ -819,7 +836,7 @@ static void davinci_pcm_free(struct snd_pcm *pcm) buf->area = NULL; iram_dma = buf->private_data; if (iram_dma) { - sram_free(iram_dma->area, iram_dma->bytes); + davinci_free_sram(substream, iram_dma); kfree(iram_dma); } } diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h index fc4d01cdd8c9..b6ef7039dd09 100644 --- a/sound/soc/davinci/davinci-pcm.h +++ b/sound/soc/davinci/davinci-pcm.h @@ -12,6 +12,7 @@ #ifndef _DAVINCI_PCM_H #define _DAVINCI_PCM_H +#include <linux/genalloc.h> #include <linux/platform_data/davinci_asp.h> #include <mach/edma.h> @@ -20,6 +21,7 @@ struct davinci_pcm_dma_params { unsigned short acnt; dma_addr_t dma_addr; /* device physical address for DMA */ unsigned sram_size; + struct gen_pool *sram_pool; /* SRAM gen_pool for ping pong */ enum dma_event_q asp_chan_q; /* event queue number for ASP channel */ enum dma_event_q ram_chan_q; /* event queue number for RAM channel */ unsigned char data_type; /* xfer data type */ |