Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 81a4275b authored by Mark Brown's avatar Mark Brown
Browse files

Merge branch 'for-2.6.30' into for-2.6.31

parents 63c26baa f492ec9f
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
/*
 * <mach/asp.h> - DaVinci Audio Serial Port support
 */
#ifndef __ASM_ARCH_DAVINCI_ASP_H
#define __ASM_ARCH_DAVINCI_ASP_H

#include <mach/irqs.h>

/* Bases of register banks */
#define DAVINCI_ASP0_BASE	0x01E02000
#define DAVINCI_ASP1_BASE	0x01E04000

/* EDMA channels */
#define DAVINCI_DMA_ASP0_TX	2
#define DAVINCI_DMA_ASP0_RX	3
#define DAVINCI_DMA_ASP1_TX	8
#define DAVINCI_DMA_ASP1_RX	9

/* Interrupts */
#define DAVINCI_ASP0_RX_INT	IRQ_MBRINT
#define DAVINCI_ASP0_TX_INT	IRQ_MBXINT
#define DAVINCI_ASP1_RX_INT	IRQ_MBRINT
#define DAVINCI_ASP1_TX_INT	IRQ_MBXINT

#endif /* __ASM_ARCH_DAVINCI_ASP_H */
+4 −3
Original line number Diff line number Diff line
@@ -10,13 +10,14 @@ config SND_DAVINCI_SOC_I2S
	tristate

config SND_DAVINCI_SOC_EVM
	tristate "SoC Audio support for DaVinci EVM"
	depends on SND_DAVINCI_SOC && MACH_DAVINCI_EVM
	tristate "SoC Audio support for DaVinci DM6446 or DM355 EVM"
	depends on SND_DAVINCI_SOC
	depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM
	select SND_DAVINCI_SOC_I2S
	select SND_SOC_TLV320AIC3X
	help
	  Say Y if you want to add support for SoC audio on TI
	  DaVinci EVM platform.
	  DaVinci DM6446 or DM355 EVM platforms.

config SND_DAVINCI_SOC_SFFSDR
	tristate "SoC Audio support for SFFSDR"
+52 −11
Original line number Diff line number Diff line
@@ -20,7 +20,11 @@
#include <sound/soc-dapm.h>

#include <asm/dma.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>

#include <mach/asp.h>
#include <mach/edma.h>
#include <mach/mux.h>

#include "../codecs/tlv320aic3x.h"
#include "davinci-pcm.h"
@@ -150,7 +154,7 @@ static struct snd_soc_card snd_soc_card_evm = {

/* evm audio private data */
static struct aic3x_setup_data evm_aic3x_setup = {
	.i2c_bus = 0,
	.i2c_bus = 1,
	.i2c_address = 0x1b,
};

@@ -161,36 +165,73 @@ static struct snd_soc_device evm_snd_devdata = {
	.codec_data = &evm_aic3x_setup,
};

/* DM6446 EVM uses ASP0; line-out is a pair of RCA jacks */
static struct resource evm_snd_resources[] = {
	{
		.start = DAVINCI_MCBSP_BASE,
		.end = DAVINCI_MCBSP_BASE + SZ_8K - 1,
		.start = DAVINCI_ASP0_BASE,
		.end = DAVINCI_ASP0_BASE + SZ_8K - 1,
		.flags = IORESOURCE_MEM,
	},
};

static struct evm_snd_platform_data evm_snd_data = {
	.tx_dma_ch	= DM644X_DMACH_MCBSP_TX,
	.rx_dma_ch	= DM644X_DMACH_MCBSP_RX,
	.tx_dma_ch	= DAVINCI_DMA_ASP0_TX,
	.rx_dma_ch	= DAVINCI_DMA_ASP0_RX,
};

/* DM335 EVM uses ASP1; line-out is a stereo mini-jack */
static struct resource dm335evm_snd_resources[] = {
	{
		.start = DAVINCI_ASP1_BASE,
		.end = DAVINCI_ASP1_BASE + SZ_8K - 1,
		.flags = IORESOURCE_MEM,
	},
};

static struct evm_snd_platform_data dm335evm_snd_data = {
	.tx_dma_ch	= DAVINCI_DMA_ASP1_TX,
	.rx_dma_ch	= DAVINCI_DMA_ASP1_RX,
};

static struct platform_device *evm_snd_device;

static int __init evm_init(void)
{
	struct resource *resources;
	unsigned num_resources;
	struct evm_snd_platform_data *data;
	int index;
	int ret;

	evm_snd_device = platform_device_alloc("soc-audio", 0);
	if (machine_is_davinci_evm()) {
		davinci_cfg_reg(DM644X_MCBSP);

		resources = evm_snd_resources;
		num_resources = ARRAY_SIZE(evm_snd_resources);
		data = &evm_snd_data;
		index = 0;
	} else if (machine_is_davinci_dm355_evm()) {
		/* we don't use ASP1 IRQs, or we'd need to mux them ... */
		davinci_cfg_reg(DM355_EVT8_ASP1_TX);
		davinci_cfg_reg(DM355_EVT9_ASP1_RX);

		resources = dm335evm_snd_resources;
		num_resources = ARRAY_SIZE(dm335evm_snd_resources);
		data = &dm335evm_snd_data;
		index = 1;
	} else
		return -EINVAL;

	evm_snd_device = platform_device_alloc("soc-audio", index);
	if (!evm_snd_device)
		return -ENOMEM;

	platform_set_drvdata(evm_snd_device, &evm_snd_devdata);
	evm_snd_devdata.dev = &evm_snd_device->dev;
	platform_device_add_data(evm_snd_device, &evm_snd_data,
				 sizeof(evm_snd_data));
	platform_device_add_data(evm_snd_device, data, sizeof(*data));

	ret = platform_device_add_resources(evm_snd_device, evm_snd_resources,
					    ARRAY_SIZE(evm_snd_resources));
	ret = platform_device_add_resources(evm_snd_device, resources,
			num_resources);
	if (ret) {
		platform_device_put(evm_snd_device);
		return ret;
+23 −3
Original line number Diff line number Diff line
@@ -24,6 +24,26 @@

#include "davinci-pcm.h"


/*
 * NOTE:  terminology here is confusing.
 *
 *  - This driver supports the "Audio Serial Port" (ASP),
 *    found on dm6446, dm355, and other DaVinci chips.
 *
 *  - But it labels it a "Multi-channel Buffered Serial Port"
 *    (McBSP) as on older chips like the dm642 ... which was
 *    backward-compatible, possibly explaining that confusion.
 *
 *  - OMAP chips have a controller called McBSP, which is
 *    incompatible with the DaVinci flavor of McBSP.
 *
 *  - Newer DaVinci chips have a controller called McASP,
 *    incompatible with ASP and with either McBSP.
 *
 * In short:  this uses ASP to implement I2S, not McBSP.
 * And it won't be the only DaVinci implemention of I2S.
 */
#define DAVINCI_MCBSP_DRR_REG	0x00
#define DAVINCI_MCBSP_DXR_REG	0x04
#define DAVINCI_MCBSP_SPCR_REG	0x08
@@ -421,7 +441,7 @@ static int davinci_i2s_probe(struct platform_device *pdev,
{
	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
	struct snd_soc_card *card = socdev->card;
	struct snd_soc_dai *cpu_dai = card->dai_link[pdev->id].cpu_dai;
	struct snd_soc_dai *cpu_dai = card->dai_link->cpu_dai;
	struct davinci_mcbsp_dev *dev;
	struct resource *mem, *ioarea;
	struct evm_snd_platform_data *pdata;
@@ -448,7 +468,7 @@ static int davinci_i2s_probe(struct platform_device *pdev,

	cpu_dai->private_data = dev;

	dev->clk = clk_get(&pdev->dev, "McBSPCLK");
	dev->clk = clk_get(&pdev->dev, NULL);
	if (IS_ERR(dev->clk)) {
		ret = -ENODEV;
		goto err_free_mem;
@@ -483,7 +503,7 @@ static void davinci_i2s_remove(struct platform_device *pdev,
{
	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
	struct snd_soc_card *card = socdev->card;
	struct snd_soc_dai *cpu_dai = card->dai_link[pdev->id].cpu_dai;
	struct snd_soc_dai *cpu_dai = card->dai_link->cpu_dai;
	struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
	struct resource *mem;

+42 −29
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <sound/soc.h>

#include <asm/dma.h>
#include <mach/edma.h>

#include "davinci-pcm.h"

@@ -51,7 +52,7 @@ struct davinci_runtime_data {
	spinlock_t lock;
	int period;		/* current DMA period */
	int master_lch;		/* Master DMA channel */
	int slave_lch;		/* Slave DMA channel */
	int slave_lch;		/* linked parameter RAM reload slot */
	struct davinci_pcm_dma_params *params;	/* DMA params */
};

@@ -90,18 +91,18 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
		dst_bidx = data_type;
	}

	davinci_set_dma_src_params(lch, src, INCR, W8BIT);
	davinci_set_dma_dest_params(lch, dst, INCR, W8BIT);
	davinci_set_dma_src_index(lch, src_bidx, 0);
	davinci_set_dma_dest_index(lch, dst_bidx, 0);
	davinci_set_dma_transfer_params(lch, data_type, count, 1, 0, ASYNC);
	edma_set_src(lch, src, INCR, W8BIT);
	edma_set_dest(lch, dst, INCR, W8BIT);
	edma_set_src_index(lch, src_bidx, 0);
	edma_set_dest_index(lch, dst_bidx, 0);
	edma_set_transfer_params(lch, data_type, count, 1, 0, ASYNC);

	prtd->period++;
	if (unlikely(prtd->period >= runtime->periods))
		prtd->period = 0;
}

static void davinci_pcm_dma_irq(int lch, u16 ch_status, void *data)
static void davinci_pcm_dma_irq(unsigned lch, u16 ch_status, void *data)
{
	struct snd_pcm_substream *substream = data;
	struct davinci_runtime_data *prtd = substream->runtime->private_data;
@@ -125,7 +126,7 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
	struct davinci_runtime_data *prtd = substream->runtime->private_data;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct davinci_pcm_dma_params *dma_data = rtd->dai->cpu_dai->dma_data;
	int tcc = TCC_ANY;
	struct edmacc_param p_ram;
	int ret;

	if (!dma_data)
@@ -134,22 +135,34 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
	prtd->params = dma_data;

	/* Request master DMA channel */
	ret = davinci_request_dma(prtd->params->channel, prtd->params->name,
	ret = edma_alloc_channel(prtd->params->channel,
				  davinci_pcm_dma_irq, substream,
				  &prtd->master_lch, &tcc, EVENTQ_0);
	if (ret)
				  EVENTQ_0);
	if (ret < 0)
		return ret;
	prtd->master_lch = ret;

	/* Request slave DMA channel */
	ret = davinci_request_dma(PARAM_ANY, "Link",
				  NULL, NULL, &prtd->slave_lch, &tcc, EVENTQ_0);
	if (ret) {
		davinci_free_dma(prtd->master_lch);
	/* Request parameter RAM reload slot */
	ret = edma_alloc_slot(EDMA_SLOT_ANY);
	if (ret < 0) {
		edma_free_channel(prtd->master_lch);
		return ret;
	}
	prtd->slave_lch = ret;

	/* Link slave DMA channel in loopback */
	davinci_dma_link_lch(prtd->slave_lch, prtd->slave_lch);
	/* Issue transfer completion IRQ when the channel completes a
	 * transfer, then always reload from the same slot (by a kind
	 * of loopback link).  The completion IRQ handler will update
	 * the reload slot with a new buffer.
	 *
	 * REVISIT save p_ram here after setting up everything except
	 * the buffer and its length (ccnt) ... use it as a template
	 * so davinci_pcm_enqueue_dma() takes less time in IRQ.
	 */
	edma_read_slot(prtd->slave_lch, &p_ram);
	p_ram.opt |= TCINTEN | EDMA_TCC(prtd->master_lch);
	p_ram.link_bcntrld = prtd->slave_lch << 5;
	edma_write_slot(prtd->slave_lch, &p_ram);

	return 0;
}
@@ -165,12 +178,12 @@ static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		davinci_start_dma(prtd->master_lch);
		edma_start(prtd->master_lch);
		break;
	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
		davinci_stop_dma(prtd->master_lch);
		edma_stop(prtd->master_lch);
		break;
	default:
		ret = -EINVAL;
@@ -185,14 +198,14 @@ static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
{
	struct davinci_runtime_data *prtd = substream->runtime->private_data;
	struct paramentry_descriptor temp;
	struct edmacc_param temp;

	prtd->period = 0;
	davinci_pcm_enqueue_dma(substream);

	/* Get slave channel dma params for master channel startup */
	davinci_get_dma_params(prtd->slave_lch, &temp);
	davinci_set_dma_params(prtd->master_lch, &temp);
	/* Copy self-linked parameter RAM entry into master channel */
	edma_read_slot(prtd->slave_lch, &temp);
	edma_write_slot(prtd->master_lch, &temp);

	return 0;
}
@@ -208,7 +221,7 @@ davinci_pcm_pointer(struct snd_pcm_substream *substream)

	spin_lock(&prtd->lock);

	davinci_dma_getposition(prtd->master_lch, &src, &dst);
	edma_get_position(prtd->master_lch, &src, &dst);
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		count = src - runtime->dma_addr;
	else
@@ -253,10 +266,10 @@ static int davinci_pcm_close(struct snd_pcm_substream *substream)
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct davinci_runtime_data *prtd = runtime->private_data;

	davinci_dma_unlink_lch(prtd->slave_lch, prtd->slave_lch);
	edma_unlink(prtd->slave_lch);

	davinci_free_dma(prtd->slave_lch);
	davinci_free_dma(prtd->master_lch);
	edma_free_slot(prtd->slave_lch);
	edma_free_channel(prtd->master_lch);

	kfree(prtd);