sound/soc/renesas/siu_pcm.c

Source file repositories/reference/linux-study-clean/sound/soc/renesas/siu_pcm.c

File Facts

System
Linux kernel
Corpus path
sound/soc/renesas/siu_pcm.c
Extension
.c
Size
14874 bytes
Lines
553
Domain
Driver Families
Bucket
sound/soc
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0+
//
// siu_pcm.c - ALSA driver for Renesas SH7343, SH7722 SIU peripheral.
//
// Copyright (C) 2009-2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
// Copyright (C) 2006 Carlos Munoz <carlos@kenati.com>

#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/platform_device.h>

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

#include <asm/siu.h>

#include "siu.h"

#define DRV_NAME "siu-i2s"
#define GET_MAX_PERIODS(buf_bytes, period_bytes) \
				((buf_bytes) / (period_bytes))
#define PERIOD_OFFSET(buf_addr, period_num, period_bytes) \
				((buf_addr) + ((period_num) * (period_bytes)))

#define RWF_STM_RD		0x01		/* Read in progress */
#define RWF_STM_WT		0x02		/* Write in progress */

struct siu_port *siu_ports[SIU_PORT_NUM];

/* transfersize is number of u32 dma transfers per period */
static int siu_pcm_stmwrite_stop(struct siu_port *port_info)
{
	struct siu_info *info = siu_i2s_data;
	u32 __iomem *base = info->reg;
	struct siu_stream *siu_stream = &port_info->playback;
	u32 stfifo;

	if (!siu_stream->rw_flg)
		return -EPERM;

	/* output FIFO disable */
	stfifo = siu_read32(base + SIU_STFIFO);
	siu_write32(base + SIU_STFIFO, stfifo & ~0x0c180c18);
	pr_debug("%s: STFIFO %x -> %x\n", __func__,
		 stfifo, stfifo & ~0x0c180c18);

	/* during stmwrite clear */
	siu_stream->rw_flg = 0;

	return 0;
}

static int siu_pcm_stmwrite_start(struct siu_port *port_info)
{
	struct siu_stream *siu_stream = &port_info->playback;

	if (siu_stream->rw_flg)
		return -EPERM;

	/* Current period in buffer */
	port_info->playback.cur_period = 0;

	/* during stmwrite flag set */
	siu_stream->rw_flg = RWF_STM_WT;

	/* DMA transfer start */
	queue_work(system_highpri_wq, &siu_stream->work);

	return 0;
}

static void siu_dma_tx_complete(void *arg)
{
	struct siu_stream *siu_stream = arg;

	if (!siu_stream->rw_flg)
		return;

	/* Update completed period count */
	if (++siu_stream->cur_period >=
	    GET_MAX_PERIODS(siu_stream->buf_bytes,
			    siu_stream->period_bytes))
		siu_stream->cur_period = 0;

Annotation

Implementation Notes