cregit-Linux how code gets into the kernel

Release 4.7 sound/soc/nuc900/nuc900-pcm.c

Directory: sound/soc/nuc900
/*
 * Copyright (c) 2010 Nuvoton technology corporation.
 *
 * Wan ZongShun <mcuos.com@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation;version 2 of the License.
 *
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>

#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>

#include <mach/hardware.h>

#include "nuc900-audio.h"


static const struct snd_pcm_hardware nuc900_pcm_hardware = {
	.info			= SNDRV_PCM_INFO_INTERLEAVED |
					SNDRV_PCM_INFO_BLOCK_TRANSFER |
					SNDRV_PCM_INFO_MMAP |
					SNDRV_PCM_INFO_MMAP_VALID |
					SNDRV_PCM_INFO_PAUSE |
					SNDRV_PCM_INFO_RESUME,
	.buffer_bytes_max	= 4*1024,
	.period_bytes_min	= 1*1024,
	.period_bytes_max	= 4*1024,
	.periods_min		= 1,
	.periods_max		= 1024,
};


static int nuc900_dma_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); }

Contributors

PersonTokensPropCommitsCommitProp
wan zongshunwan zongshun2696.30%150.00%
lars-peter clausenlars-peter clausen13.70%150.00%
Total27100.00%2100.00%


static void nuc900_update_dma_register(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct nuc900_audio *nuc900_audio = runtime->private_data; void __iomem *mmio_addr, *mmio_len; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { mmio_addr = nuc900_audio->mmio + ACTL_PDSTB; mmio_len = nuc900_audio->mmio + ACTL_PDST_LENGTH; } else { mmio_addr = nuc900_audio->mmio + ACTL_RDSTB; mmio_len = nuc900_audio->mmio + ACTL_RDST_LENGTH; } AUDIO_WRITE(mmio_addr, runtime->dma_addr); AUDIO_WRITE(mmio_len, runtime->dma_bytes); }

Contributors

PersonTokensPropCommitsCommitProp
wan zongshunwan zongshun9595.00%266.67%
lars-peter clausenlars-peter clausen55.00%133.33%
Total100100.00%3100.00%


static void nuc900_dma_start(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct nuc900_audio *nuc900_audio = runtime->private_data; unsigned long val; val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON); val |= (T_DMA_IRQ | R_DMA_IRQ); AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val); }

Contributors

PersonTokensPropCommitsCommitProp
wan zongshunwan zongshun63100.00%1100.00%
Total63100.00%1100.00%


static void nuc900_dma_stop(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct nuc900_audio *nuc900_audio = runtime->private_data; unsigned long val; val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON); val &= ~(T_DMA_IRQ | R_DMA_IRQ); AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val); }

Contributors

PersonTokensPropCommitsCommitProp
wan zongshunwan zongshun64100.00%1100.00%
Total64100.00%1100.00%


static irqreturn_t nuc900_dma_interrupt(int irq, void *dev_id) { struct snd_pcm_substream *substream = dev_id; struct nuc900_audio *nuc900_audio = substream->runtime->private_data; unsigned long val; spin_lock(&nuc900_audio->lock); val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON); if (val & R_DMA_IRQ) { AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val | R_DMA_IRQ); val = AUDIO_READ(nuc900_audio->mmio + ACTL_RSR); if (val & R_DMA_MIDDLE_IRQ) { val |= R_DMA_MIDDLE_IRQ; AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, val); } if (val & R_DMA_END_IRQ) { val |= R_DMA_END_IRQ; AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, val); } } else if (val & T_DMA_IRQ) { AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val | T_DMA_IRQ); val = AUDIO_READ(nuc900_audio->mmio + ACTL_PSR); if (val & P_DMA_MIDDLE_IRQ) { val |= P_DMA_MIDDLE_IRQ; AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, val); } if (val & P_DMA_END_IRQ) { val |= P_DMA_END_IRQ; AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, val); } } else { dev_err(nuc900_audio->dev, "Wrong DMA interrupt status!\n"); spin_unlock(&nuc900_audio->lock); return IRQ_HANDLED; } spin_unlock(&nuc900_audio->lock); snd_pcm_period_elapsed(substream); return IRQ_HANDLED; }

Contributors

PersonTokensPropCommitsCommitProp
wan zongshunwan zongshun250100.00%1100.00%
Total250100.00%1100.00%


static int nuc900_dma_hw_free(struct snd_pcm_substream *substream) { snd_pcm_lib_free_pages(substream); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
wan zongshunwan zongshun19100.00%1100.00%
Total19100.00%1100.00%


static int nuc900_dma_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct nuc900_audio *nuc900_audio = runtime->private_data; unsigned long flags, val; int ret = 0; spin_lock_irqsave(&nuc900_audio->lock, flags); nuc900_update_dma_register(substream); val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); switch (runtime->channels) { case 1: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { val &= ~(PLAY_LEFT_CHNNEL | PLAY_RIGHT_CHNNEL); val |= PLAY_RIGHT_CHNNEL; } else { val &= ~(RECORD_LEFT_CHNNEL | RECORD_RIGHT_CHNNEL); val |= RECORD_RIGHT_CHNNEL; } AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); break; case 2: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) val |= (PLAY_LEFT_CHNNEL | PLAY_RIGHT_CHNNEL); else val |= (RECORD_LEFT_CHNNEL | RECORD_RIGHT_CHNNEL); AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); break; default: ret = -EINVAL; } spin_unlock_irqrestore(&nuc900_audio->lock, flags); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
wan zongshunwan zongshun17895.19%266.67%
axel linaxel lin94.81%133.33%
Total187100.00%3100.00%


static int nuc900_dma_trigger(struct snd_pcm_substream *substream, int cmd) { int ret = 0; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: nuc900_dma_start(substream); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: nuc900_dma_stop(substream); break; default: ret = -EINVAL; break; } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
wan zongshunwan zongshun59100.00%1100.00%
Total59100.00%1100.00%


static int nuc900_dma_getposition(struct snd_pcm_substream *substream, dma_addr_t *src, dma_addr_t *dst) { struct snd_pcm_runtime *runtime = substream->runtime; struct nuc900_audio *nuc900_audio = runtime->private_data; if (src != NULL) *src = AUDIO_READ(nuc900_audio->mmio + ACTL_PDSTC); if (dst != NULL) *dst = AUDIO_READ(nuc900_audio->mmio + ACTL_RDSTC); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
wan zongshunwan zongshun7598.68%150.00%
axel linaxel lin11.32%150.00%
Total76100.00%2100.00%


static snd_pcm_uframes_t nuc900_dma_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; dma_addr_t src, dst; unsigned long res; nuc900_dma_getposition(substream, &src, &dst); if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) res = dst - runtime->dma_addr; else res = src - runtime->dma_addr; return bytes_to_frames(substream->runtime, res); }

Contributors

PersonTokensPropCommitsCommitProp
wan zongshunwan zongshun75100.00%1100.00%
Total75100.00%1100.00%


static int nuc900_dma_open(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct nuc900_audio *nuc900_audio; snd_soc_set_runtime_hwparams(substream, &nuc900_pcm_hardware); nuc900_audio = nuc900_ac97_data; if (request_irq(nuc900_audio->irq_num, nuc900_dma_interrupt, 0, "nuc900-dma", substream)) return -EBUSY; runtime->private_data = nuc900_audio; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
wan zongshunwan zongshun6698.51%150.00%
yong zhangyong zhang11.49%150.00%
Total67100.00%2100.00%


static int nuc900_dma_close(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct nuc900_audio *nuc900_audio = runtime->private_data; free_irq(nuc900_audio->irq_num, substream); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
wan zongshunwan zongshun41100.00%1100.00%
Total41100.00%1100.00%


static int nuc900_dma_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma) { struct snd_pcm_runtime *runtime = substream->runtime; return dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area, runtime->dma_addr, runtime->dma_bytes); }

Contributors

PersonTokensPropCommitsCommitProp
wan zongshunwan zongshun5098.04%150.00%
luis r. rodriguezluis r. rodriguez11.96%150.00%
Total51100.00%2100.00%

static struct snd_pcm_ops nuc900_dma_ops = { .open = nuc900_dma_open, .close = nuc900_dma_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = nuc900_dma_hw_params, .hw_free = nuc900_dma_hw_free, .prepare = nuc900_dma_prepare, .trigger = nuc900_dma_trigger, .pointer = nuc900_dma_pointer, .mmap = nuc900_dma_mmap, };
static int nuc900_dma_new(struct snd_soc_pcm_runtime *rtd) { struct snd_card *card = rtd->card->snd_card; struct snd_pcm *pcm = rtd->pcm; int ret; ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); if (ret) return ret; snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, card->dev, 4 * 1024, (4 * 1024) - 1); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
wan zongshunwan zongshun4859.26%133.33%
liam girdwoodliam girdwood1822.22%133.33%
russell kingrussell king1518.52%133.33%
Total81100.00%3100.00%

static struct snd_soc_platform_driver nuc900_soc_platform = { .ops = &nuc900_dma_ops, .pcm_new = nuc900_dma_new, };
static int nuc900_soc_platform_probe(struct platform_device *pdev) { return devm_snd_soc_register_platform(&pdev->dev, &nuc900_soc_platform); }

Contributors

PersonTokensPropCommitsCommitProp
liam girdwoodliam girdwood1356.52%125.00%
axel linaxel lin730.43%250.00%
wan zongshunwan zongshun313.04%125.00%
Total23100.00%4100.00%

static struct platform_driver nuc900_pcm_driver = { .driver = { .name = "nuc900-pcm-audio", }, .probe = nuc900_soc_platform_probe, }; module_platform_driver(nuc900_pcm_driver); MODULE_AUTHOR("Wan ZongShun, <mcuos.com@gmail.com>"); MODULE_DESCRIPTION("nuc900 Audio DMA module"); MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
wan zongshunwan zongshun128892.93%321.43%
liam girdwoodliam girdwood564.04%214.29%
axel linaxel lin191.37%535.71%
russell kingrussell king151.08%17.14%
lars-peter clausenlars-peter clausen60.43%17.14%
luis r. rodriguezluis r. rodriguez10.07%17.14%
yong zhangyong zhang10.07%17.14%
Total1386100.00%14100.00%
Directory: sound/soc/nuc900
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}