linux/sound/soc/ux500/ux500_pcm.c
Linus Torvalds 1286da8bc0 sound updates for 3.11
A relative calm release at this time with a flat diffstat.
 The only significant change in the ALSA core side is the support for
 more than 32 card instances, configurable via kconfig.
 Other than that, in both ASoC and other parts, mostly some
 improvements and fixes on the driver side.
 
 - hda: More quirks for ALC269-variants on Dell & co, VIA codec fixes
 - hda: Haswell HDMI audio fixes, runtime PM improvements
 - hda: Intel BayTrail support, ALC5505 DSP support
 - es1968: MediaForte M56VAP support
 - usb-audio: Improved support for Yamaha/Roland devices
 - usb-audio: M2Tech hiFace, Audio Advantage Micro II support
 - hdspm: wordclock fixes
 - ASoC: Pending fixes for WM8962
 - ASoC: Cleanups and fixes for Blackfin, SGTL5000 and UX500
 - ASoC: Generalisation of the Bluetooth and HDMI stub drivers
 - ASoC: SSM2518 and RT5640 codec drivers.
 - ASoC: Tegra CPUs with RT5640 machine driver
 - ASoC: AC'97 refactoring bug fixes
 - ASoC: ADAU1701 driver fixes
 - Clean up of *_set_drvdata() in a wide range of drivers
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.19 (GNU/Linux)
 
 iQIcBAABAgAGBQJR1BNeAAoJEGwxgFQ9KSmk5mAP/iH8IPdaMq/EI3Kdk2lwqXwK
 xQvpQCKTeux4UrETSDM5kOfk+Nv0oq7jD60wEZs6eONAZdfIzACEjdpQBdC4vr6f
 2S8b9J6xBe2siHGbzBsgV9g8xhnYXC5m0u8QBRa9fyNVpMu1o1X6Mv7FS/wUCMZ6
 M7vaSdrU4pfa4v9sy9loOYbyDZoSZg0revwqWAm8Kfp4XSd1aPwiCVPLVOWcvNYC
 hriz5ICARFg+yqzJADPBYtSU752zxlZd/N1b2YQw1YnoxA66FoVaqQfYD1voL0WY
 8m9abNlnln6qxyeQPMvRMZty1I/kCwOlp5dO0OZHisMLE8MApLk1e7ct9+W+b9hn
 NORbo3klmwZfIl1s8JSGHs5Nknqzhdzau35TVPTmtC50wgnPO6EYVeYFiZqkuYyK
 UdCHJTRjyS6HlmbdKeSaRr+PoCR0zVQruXFjWnAwQ9Zy+1qrnVb5Ly9np7YCc8YC
 3iYOygJyn+JmyfeeIxVUCg6Rdf4NUv+JPx48yuoq79YnWAbRiSSct1/J+4YcYcm5
 VjJdtCwElil3dSeba+Oy2wcSwaJzyaINbClzmZdysT26M8QLZaRCBU0zujeiyl/n
 lV/p/n+UmmtfHIdJDz6Eu6fQVAbh0v89mZrEJdjroLebwS1NBLAaKkb9vY63AdKt
 P5c/7KWejQ/CtoVYeo3O
 =i5lT
 -----END PGP SIGNATURE-----

Merge tag 'sound-3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound updates from Takashi Iwai:
 "A relative calm release at this time with a flat diffstat.  The only
  significant change in the ALSA core side is the support for more than
  32 card instances, configurable via kconfig.  Other than that, in both
  ASoC and other parts, mostly some improvements and fixes on the driver
  side.

   - hda: More quirks for ALC269-variants on Dell & co, VIA codec fixes
   - hda: Haswell HDMI audio fixes, runtime PM improvements
   - hda: Intel BayTrail support, ALC5505 DSP support
   - es1968: MediaForte M56VAP support
   - usb-audio: Improved support for Yamaha/Roland devices
   - usb-audio: M2Tech hiFace, Audio Advantage Micro II support
   - hdspm: wordclock fixes
   - ASoC: Pending fixes for WM8962
   - ASoC: Cleanups and fixes for Blackfin, SGTL5000 and UX500
   - ASoC: Generalisation of the Bluetooth and HDMI stub drivers
   - ASoC: SSM2518 and RT5640 codec drivers.
   - ASoC: Tegra CPUs with RT5640 machine driver
   - ASoC: AC'97 refactoring bug fixes
   - ASoC: ADAU1701 driver fixes
   - Clean up of *_set_drvdata() in a wide range of drivers"

* tag 'sound-3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (284 commits)
  ALSA: vmaster: Fix the regression of missing vmaster hook call
  ALSA: hda - Add Dell SSID to support Headset Mic recording
  ASoC: adau1701: remove control_data assignment
  ASoC: adau1701: more direct regmap usage
  ASoC: ac97: fixup multi-platform AC'97 module build failure
  ASoC: pxa2xx: fixup multi-platform AC'97 build failures
  ASoC: tegra20-ac97: Remove unused variable
  ASoC: tegra20-ac97: Remove duplicate error message
  ALSA: usb-audio: Add Audio Advantage Micro II
  ASoC: tas5086: fix Mid-Z implementation
  ASoC: tas5086: fix TAS5086_CLOCK_CONTROL register size
  ALSA: Replace the magic number 44 with const
  ALSA: hda - Fix the max length of control name in generic parser
  ALSA: hda - Guess what, it's two more Dell headset mic quirks
  ALSA: hda - Yet another Dell headset mic quirk
  ALSA: hda - Add support for ALC5505 DSP power-save mode
  ASoC: mfld: Remove unused variable
  ALSA: usb-audio: add quirks for Roland QUAD/OCTO-CAPTURE
  ALSA: usb-audio: claim autodetected PCM interfaces all at once
  ALSA: usb-audio: remove superfluous Roland quirks
  ...
2013-07-03 19:52:22 -07:00

168 lines
4.7 KiB
C

/*
* Copyright (C) ST-Ericsson SA 2012
*
* Author: Ola Lilja <ola.o.lilja@stericsson.com>,
* Roger Nilsson <roger.xr.nilsson@stericsson.com>
* for ST-Ericsson.
*
* License terms:
*
* 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.
*/
#include <asm/page.h>
#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/slab.h>
#include <linux/platform_data/dma-ste-dma40.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include "ux500_msp_i2s.h"
#include "ux500_pcm.h"
#define UX500_PLATFORM_MIN_RATE 8000
#define UX500_PLATFORM_MAX_RATE 48000
#define UX500_PLATFORM_MIN_CHANNELS 1
#define UX500_PLATFORM_MAX_CHANNELS 8
#define UX500_PLATFORM_PERIODS_BYTES_MIN 128
#define UX500_PLATFORM_PERIODS_BYTES_MAX (64 * PAGE_SIZE)
#define UX500_PLATFORM_PERIODS_MIN 2
#define UX500_PLATFORM_PERIODS_MAX 48
#define UX500_PLATFORM_BUFFER_BYTES_MAX (2048 * PAGE_SIZE)
static const struct snd_pcm_hardware ux500_pcm_hw = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_PAUSE,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_U16_LE |
SNDRV_PCM_FMTBIT_S16_BE |
SNDRV_PCM_FMTBIT_U16_BE,
.rates = SNDRV_PCM_RATE_KNOT,
.rate_min = UX500_PLATFORM_MIN_RATE,
.rate_max = UX500_PLATFORM_MAX_RATE,
.channels_min = UX500_PLATFORM_MIN_CHANNELS,
.channels_max = UX500_PLATFORM_MAX_CHANNELS,
.buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX,
.period_bytes_min = UX500_PLATFORM_PERIODS_BYTES_MIN,
.period_bytes_max = UX500_PLATFORM_PERIODS_BYTES_MAX,
.periods_min = UX500_PLATFORM_PERIODS_MIN,
.periods_max = UX500_PLATFORM_PERIODS_MAX,
};
static struct dma_chan *ux500_pcm_request_chan(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_substream *substream)
{
struct snd_soc_dai *dai = rtd->cpu_dai;
struct device *dev = dai->dev;
u16 per_data_width, mem_data_width;
struct stedma40_chan_cfg *dma_cfg;
struct ux500_msp_dma_params *dma_params;
dev_dbg(dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id,
snd_pcm_stream_str(substream));
dma_params = snd_soc_dai_get_dma_data(dai, substream);
dma_cfg = dma_params->dma_cfg;
mem_data_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
switch (dma_params->data_size) {
case 32:
per_data_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
break;
case 16:
per_data_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
break;
case 8:
per_data_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
break;
default:
per_data_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
dma_cfg->src_info.data_width = mem_data_width;
dma_cfg->dst_info.data_width = per_data_width;
} else {
dma_cfg->src_info.data_width = per_data_width;
dma_cfg->dst_info.data_width = mem_data_width;
}
return snd_dmaengine_pcm_request_channel(stedma40_filter, dma_cfg);
}
static int ux500_pcm_prepare_slave_config(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct dma_slave_config *slave_config)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct ux500_msp_dma_params *dma_params;
struct stedma40_chan_cfg *dma_cfg;
int ret;
dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
dma_cfg = dma_params->dma_cfg;
ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config);
if (ret)
return ret;
slave_config->dst_maxburst = 4;
slave_config->dst_addr_width = dma_cfg->dst_info.data_width;
slave_config->src_maxburst = 4;
slave_config->src_addr_width = dma_cfg->src_info.data_width;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
slave_config->dst_addr = dma_params->tx_rx_addr;
else
slave_config->src_addr = dma_params->tx_rx_addr;
return 0;
}
static const struct snd_dmaengine_pcm_config ux500_dmaengine_pcm_config = {
.pcm_hardware = &ux500_pcm_hw,
.compat_request_channel = ux500_pcm_request_chan,
.prealloc_buffer_size = 128 * 1024,
.prepare_slave_config = ux500_pcm_prepare_slave_config,
};
int ux500_pcm_register_platform(struct platform_device *pdev)
{
int ret;
ret = snd_dmaengine_pcm_register(&pdev->dev,
&ux500_dmaengine_pcm_config,
SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
SND_DMAENGINE_PCM_FLAG_COMPAT |
SND_DMAENGINE_PCM_FLAG_NO_DT);
if (ret < 0) {
dev_err(&pdev->dev,
"%s: ERROR: Failed to register platform '%s' (%d)!\n",
__func__, pdev->name, ret);
return ret;
}
return 0;
}
EXPORT_SYMBOL_GPL(ux500_pcm_register_platform);
int ux500_pcm_unregister_platform(struct platform_device *pdev)
{
snd_dmaengine_pcm_unregister(&pdev->dev);
return 0;
}
EXPORT_SYMBOL_GPL(ux500_pcm_unregister_platform);