sound/soc/fsl/imx-pcm-fiq.c

Source file repositories/reference/linux-study-clean/sound/soc/fsl/imx-pcm-fiq.c

File Facts

System
Linux kernel
Corpus path
sound/soc/fsl/imx-pcm-fiq.c
Extension
.c
Size
7849 bytes
Lines
323
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

struct imx_pcm_runtime_data {
	unsigned int period;
	int periods;
	unsigned long offset;
	struct hrtimer hrt;
	int poll_time_ns;
	struct snd_pcm_substream *substream;
	atomic_t playing;
	atomic_t capturing;
};

static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt)
{
	struct imx_pcm_runtime_data *iprtd =
		container_of(hrt, struct imx_pcm_runtime_data, hrt);
	struct snd_pcm_substream *substream = iprtd->substream;
	struct pt_regs regs;

	if (!atomic_read(&iprtd->playing) && !atomic_read(&iprtd->capturing))
		return HRTIMER_NORESTART;

	get_fiq_regs(&regs);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		iprtd->offset = regs.ARM_r8 & 0xffff;
	else
		iprtd->offset = regs.ARM_r9 & 0xffff;

	snd_pcm_period_elapsed(substream);

	hrtimer_forward_now(hrt, ns_to_ktime(iprtd->poll_time_ns));

	return HRTIMER_RESTART;
}

static struct fiq_handler fh = {
	.name		= DRV_NAME,
};

static int snd_imx_pcm_hw_params(struct snd_soc_component *component,
				 struct snd_pcm_substream *substream,
				 struct snd_pcm_hw_params *params)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct imx_pcm_runtime_data *iprtd = runtime->private_data;

	iprtd->periods = params_periods(params);
	iprtd->period = params_period_bytes(params);
	iprtd->offset = 0;
	iprtd->poll_time_ns = 1000000000 / params_rate(params) *
				params_period_size(params);

	return 0;
}

static int snd_imx_pcm_prepare(struct snd_soc_component *component,
			       struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct imx_pcm_runtime_data *iprtd = runtime->private_data;
	struct pt_regs regs;

	get_fiq_regs(&regs);
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		regs.ARM_r8 = (iprtd->period * iprtd->periods - 1) << 16;
	else
		regs.ARM_r9 = (iprtd->period * iprtd->periods - 1) << 16;

	set_fiq_regs(&regs);

	return 0;
}

static int imx_pcm_fiq;

static int snd_imx_pcm_trigger(struct snd_soc_component *component,
			       struct snd_pcm_substream *substream, int cmd)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct imx_pcm_runtime_data *iprtd = runtime->private_data;

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
			atomic_set(&iprtd->playing, 1);
		else
			atomic_set(&iprtd->capturing, 1);
		hrtimer_start(&iprtd->hrt, ns_to_ktime(iprtd->poll_time_ns),

Annotation

Implementation Notes