Commit bf557a50 authored by Mark Brown's avatar Mark Brown

Merge branch 'for-2.6.37' of...

Merge branch 'for-2.6.37' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/asoc-2.6 into for-2.6.37
parents 26b01ccd 3fabe089
This diff is collapsed.
/*
* sound/soc/codec/wl1273.h
*
* ALSA SoC WL1273 codec driver
*
* Copyright (C) Nokia Corporation
* Author: Matti Aaltonen <matti.j.aaltonen@nokia.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL1273_CODEC_H__
#define __WL1273_CODEC_H__
/* I2S protocol, left channel first, data width 16 bits */
#define WL1273_PCM_DEF_MODE 0x00
/* Rx */
#define WL1273_AUDIO_ENABLE_I2S (1 << 0)
#define WL1273_AUDIO_ENABLE_ANALOG (1 << 1)
/* Tx */
#define WL1273_AUDIO_IO_SET_ANALOG 0
#define WL1273_AUDIO_IO_SET_I2S 1
#define WL1273_POWER_SET_OFF 0
#define WL1273_POWER_SET_FM (1 << 0)
#define WL1273_POWER_SET_RDS (1 << 1)
#define WL1273_POWER_SET_RETENTION (1 << 4)
#define WL1273_PUPD_SET_OFF 0x00
#define WL1273_PUPD_SET_ON 0x01
#define WL1273_PUPD_SET_RETENTION 0x10
/* I2S mode */
#define WL1273_IS2_WIDTH_32 0x0
#define WL1273_IS2_WIDTH_40 0x1
#define WL1273_IS2_WIDTH_22_23 0x2
#define WL1273_IS2_WIDTH_23_22 0x3
#define WL1273_IS2_WIDTH_48 0x4
#define WL1273_IS2_WIDTH_50 0x5
#define WL1273_IS2_WIDTH_60 0x6
#define WL1273_IS2_WIDTH_64 0x7
#define WL1273_IS2_WIDTH_80 0x8
#define WL1273_IS2_WIDTH_96 0x9
#define WL1273_IS2_WIDTH_128 0xa
#define WL1273_IS2_WIDTH 0xf
#define WL1273_IS2_FORMAT_STD (0x0 << 4)
#define WL1273_IS2_FORMAT_LEFT (0x1 << 4)
#define WL1273_IS2_FORMAT_RIGHT (0x2 << 4)
#define WL1273_IS2_FORMAT_USER (0x3 << 4)
#define WL1273_IS2_MASTER (0x0 << 6)
#define WL1273_IS2_SLAVEW (0x1 << 6)
#define WL1273_IS2_TRI_AFTER_SENDING (0x0 << 7)
#define WL1273_IS2_TRI_ALWAYS_ACTIVE (0x1 << 7)
#define WL1273_IS2_SDOWS_RR (0x0 << 8)
#define WL1273_IS2_SDOWS_RF (0x1 << 8)
#define WL1273_IS2_SDOWS_FR (0x2 << 8)
#define WL1273_IS2_SDOWS_FF (0x3 << 8)
#define WL1273_IS2_TRI_OPT (0x0 << 10)
#define WL1273_IS2_TRI_ALWAYS (0x1 << 10)
#define WL1273_IS2_RATE_48K (0x0 << 12)
#define WL1273_IS2_RATE_44_1K (0x1 << 12)
#define WL1273_IS2_RATE_32K (0x2 << 12)
#define WL1273_IS2_RATE_22_05K (0x4 << 12)
#define WL1273_IS2_RATE_16K (0x5 << 12)
#define WL1273_IS2_RATE_12K (0x8 << 12)
#define WL1273_IS2_RATE_11_025 (0x9 << 12)
#define WL1273_IS2_RATE_8K (0xa << 12)
#define WL1273_IS2_RATE (0xf << 12)
#define WL1273_I2S_DEF_MODE (WL1273_IS2_WIDTH_32 | \
WL1273_IS2_FORMAT_STD | \
WL1273_IS2_MASTER | \
WL1273_IS2_TRI_AFTER_SENDING | \
WL1273_IS2_SDOWS_RR | \
WL1273_IS2_TRI_OPT | \
WL1273_IS2_RATE_48K)
int wl1273_get_format(struct snd_soc_codec *codec, unsigned int *fmt);
#endif /* End of __WL1273_CODEC_H__ */
......@@ -60,6 +60,7 @@ struct dma_object {
struct snd_soc_platform_driver dai;
dma_addr_t ssi_stx_phys;
dma_addr_t ssi_srx_phys;
unsigned int ssi_fifo_depth;
struct ccsr_dma_channel __iomem *channel;
unsigned int irq;
bool assigned;
......@@ -99,6 +100,7 @@ struct fsl_dma_private {
unsigned int irq;
struct snd_pcm_substream *substream;
dma_addr_t ssi_sxx_phys;
unsigned int ssi_fifo_depth;
dma_addr_t ld_buf_phys;
unsigned int current_link;
dma_addr_t dma_buf_phys;
......@@ -439,6 +441,7 @@ static int fsl_dma_open(struct snd_pcm_substream *substream)
else
dma_private->ssi_sxx_phys = dma->ssi_srx_phys;
dma_private->ssi_fifo_depth = dma->ssi_fifo_depth;
dma_private->dma_channel = dma->channel;
dma_private->irq = dma->irq;
dma_private->substream = substream;
......@@ -552,11 +555,11 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
struct device *dev = rtd->platform->dev;
/* Number of bits per sample */
unsigned int sample_size =
unsigned int sample_bits =
snd_pcm_format_physical_width(params_format(hw_params));
/* Number of bytes per frame */
unsigned int frame_size = 2 * (sample_size / 8);
unsigned int sample_bytes = sample_bits / 8;
/* Bus address of SSI STX register */
dma_addr_t ssi_sxx_phys = dma_private->ssi_sxx_phys;
......@@ -596,7 +599,7 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
* that offset here. While we're at it, also tell the DMA controller
* how much data to transfer per sample.
*/
switch (sample_size) {
switch (sample_bits) {
case 8:
mr |= CCSR_DMA_MR_DAHTS_1 | CCSR_DMA_MR_SAHTS_1;
ssi_sxx_phys += 3;
......@@ -610,22 +613,42 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
break;
default:
/* We should never get here */
dev_err(dev, "unsupported sample size %u\n", sample_size);
dev_err(dev, "unsupported sample size %u\n", sample_bits);
return -EINVAL;
}
/*
* BWC should always be a multiple of the frame size. BWC determines
* how many bytes are sent/received before the DMA controller checks the
* SSI to see if it needs to stop. For playback, the transmit FIFO can
* hold three frames, so we want to send two frames at a time. For
* capture, the receive FIFO is triggered when it contains one frame, so
* we want to receive one frame at a time.
* BWC determines how many bytes are sent/received before the DMA
* controller checks the SSI to see if it needs to stop. BWC should
* always be a multiple of the frame size, so that we always transmit
* whole frames. Each frame occupies two slots in the FIFO. The
* parameter for CCSR_DMA_MR_BWC() is rounded down the next power of two
* (MR[BWC] can only represent even powers of two).
*
* To simplify the process, we set BWC to the largest value that is
* less than or equal to the FIFO watermark. For playback, this ensures
* that we transfer the maximum amount without overrunning the FIFO.
* For capture, this ensures that we transfer the maximum amount without
* underrunning the FIFO.
*
* f = SSI FIFO depth
* w = SSI watermark value (which equals f - 2)
* b = DMA bandwidth count (in bytes)
* s = sample size (in bytes, which equals frame_size * 2)
*
* For playback, we never transmit more than the transmit FIFO
* watermark, otherwise we might write more data than the FIFO can hold.
* The watermark is equal to the FIFO depth minus two.
*
* For capture, two equations must hold:
* w > f - (b / s)
* w >= b / s
*
* So, b > 2 * s, but b must also be <= s * w. To simplify, we set
* b = s * w, which is equal to
* (dma_private->ssi_fifo_depth - 2) * sample_bytes.
*/
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
mr |= CCSR_DMA_MR_BWC(2 * frame_size);
else
mr |= CCSR_DMA_MR_BWC(frame_size);
mr |= CCSR_DMA_MR_BWC((dma_private->ssi_fifo_depth - 2) * sample_bytes);
out_be32(&dma_channel->mr, mr);
......@@ -879,6 +902,7 @@ static int __devinit fsl_soc_dma_probe(struct of_device *of_dev,
struct device_node *np = of_dev->dev.of_node;
struct device_node *ssi_np;
struct resource res;
const uint32_t *iprop;
int ret;
/* Find the SSI node that points to us. */
......@@ -889,15 +913,17 @@ static int __devinit fsl_soc_dma_probe(struct of_device *of_dev,
}
ret = of_address_to_resource(ssi_np, 0, &res);
of_node_put(ssi_np);
if (ret) {
dev_err(&of_dev->dev, "could not determine device resources\n");
dev_err(&of_dev->dev, "could not determine resources for %s\n",
ssi_np->full_name);
of_node_put(ssi_np);
return ret;
}
dma = kzalloc(sizeof(*dma) + strlen(np->full_name), GFP_KERNEL);
if (!dma) {
dev_err(&of_dev->dev, "could not allocate dma object\n");
of_node_put(ssi_np);
return -ENOMEM;
}
......@@ -910,6 +936,15 @@ static int __devinit fsl_soc_dma_probe(struct of_device *of_dev,
dma->ssi_stx_phys = res.start + offsetof(struct ccsr_ssi, stx0);
dma->ssi_srx_phys = res.start + offsetof(struct ccsr_ssi, srx0);
iprop = of_get_property(ssi_np, "fsl,fifo-depth", NULL);
if (iprop)
dma->ssi_fifo_depth = *iprop;
else
/* Older 8610 DTs didn't have the fifo-depth property */
dma->ssi_fifo_depth = 8;
of_node_put(ssi_np);
ret = snd_soc_register_platform(&of_dev->dev, &dma->dai);
if (ret) {
dev_err(&of_dev->dev, "could not register platform\n");
......
......@@ -93,6 +93,7 @@ struct fsl_ssi_private {
unsigned int playback;
unsigned int capture;
int asynchronous;
unsigned int fifo_depth;
struct snd_soc_dai_driver cpu_dai_drv;
struct device_attribute dev_attr;
struct platform_device *pdev;
......@@ -337,11 +338,20 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
/*
* Set the watermark for transmit FIFI 0 and receive FIFO 0. We
* don't use FIFO 1. Since the SSI only supports stereo, the
* watermark should never be an odd number.
* don't use FIFO 1. We program the transmit water to signal a
* DMA transfer if there are only two (or fewer) elements left
* in the FIFO. Two elements equals one frame (left channel,
* right channel). This value, however, depends on the depth of
* the transmit buffer.
*
* We program the receive FIFO to notify us if at least two
* elements (one frame) have been written to the FIFO. We could
* make this value larger (and maybe we should), but this way
* data will be written to memory as soon as it's available.
*/
out_be32(&ssi->sfcsr,
CCSR_SSI_SFCSR_TFWM0(6) | CCSR_SSI_SFCSR_RFWM0(2));
CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) |
CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2));
/*
* We keep the SSI disabled because if we enable it, then the
......@@ -622,6 +632,7 @@ static int __devinit fsl_ssi_probe(struct of_device *of_dev,
struct device_attribute *dev_attr = NULL;
struct device_node *np = of_dev->dev.of_node;
const char *p, *sprop;
const uint32_t *iprop;
struct resource res;
char name[64];
......@@ -678,6 +689,14 @@ static int __devinit fsl_ssi_probe(struct of_device *of_dev,
else
ssi_private->cpu_dai_drv.symmetric_rates = 1;
/* Determine the FIFO depth. */
iprop = of_get_property(np, "fsl,fifo-depth", NULL);
if (iprop)
ssi_private->fifo_depth = *iprop;
else
/* Older 8610 DTs didn't have the fifo-depth property */
ssi_private->fifo_depth = 8;
/* Initialize the the device_attribute structure */
dev_attr = &ssi_private->dev_attr;
dev_attr->attr.name = "statistics";
......
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