sound/soc/renesas/rcar/msiof.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/renesas/rcar/msiof.c
Extension
.c
Size
16447 bytes
Lines
625
Domain
Driver Families
Bucket
sound/soc
Inferred role
Driver Families: implementation source
Status
source 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

struct msiof_priv {
	struct device *dev;
	struct snd_pcm_substream *substream[SNDRV_PCM_STREAM_LAST + 1];
	struct reset_control *reset;
	spinlock_t lock;
	void __iomem *base;
	resource_size_t phy_addr;

	int count;

	/* for error */
	int err_syc[SNDRV_PCM_STREAM_LAST + 1];
	int err_ovf[SNDRV_PCM_STREAM_LAST + 1];
	int err_udf[SNDRV_PCM_STREAM_LAST + 1];

	/* bit field */
	u32 flags;
#define MSIOF_FLAGS_NEED_DELAY		(1 << 0)
};
#define msiof_flag_has(priv, flag)	(priv->flags &  flag)
#define msiof_flag_set(priv, flag)	(priv->flags |= flag)

#define msiof_is_play(substream)	((substream)->stream == SNDRV_PCM_STREAM_PLAYBACK)
#define msiof_read(priv, reg)		ioread32((priv)->base + reg)
#define msiof_write(priv, reg, val)	iowrite32(val, (priv)->base + reg)

static int msiof_update(struct msiof_priv *priv, u32 reg, u32 mask, u32 val)
{
	u32 old = msiof_read(priv, reg);
	u32 new = (old & ~mask) | (val & mask);
	int updated = false;

	if (old != new) {
		msiof_write(priv, reg, new);
		updated = true;
	}

	return updated;
}

static void msiof_update_and_wait(struct msiof_priv *priv, u32 reg, u32 mask, u32 val, u32 expect)
{
	u32 data;
	int ret;

	ret = msiof_update(priv, reg, mask, val);
	if (!ret) /* no update */
		return;

	ret = readl_poll_timeout_atomic(priv->base + reg, data,
					(data & mask) == expect, 1, 128);
	if (ret)
		dev_warn(priv->dev, "write timeout [0x%02x] 0x%08x / 0x%08x\n",
			 reg, data, expect);
}

static int msiof_hw_start(struct snd_soc_component *component,
			  struct snd_pcm_substream *substream, int cmd)
{
	struct msiof_priv *priv = snd_soc_component_get_drvdata(component);
	struct snd_pcm_runtime *runtime = substream->runtime;
	int is_play = msiof_is_play(substream);
	int width = snd_pcm_format_width(runtime->format);
	u32 val;

	/*
	 * see
	 *	[NOTE-CLOCK-MODE] on top of this driver
	 */
	/*
	 * see
	 *	Datasheet 109.3.6 [Transmit and Receive Procedures]
	 *
	 *	TX: Fig 109.14	- Fig 109.23
	 *	RX: Fig 109.15
	 */

	/*
	 * Use reset_control_xx() instead of TXRST/RXRST.
	 * see
	 *	[NOTE-RESET]
	 */
	if (!priv->count)
		reset_control_deassert(priv->reset);

	priv->count++;

	/*
	 * Reset errors. ignore 1st FSERR
	 *

Annotation

Implementation Notes