sound/soc/sof/compress.c

Source file repositories/reference/linux-study-clean/sound/soc/sof/compress.c

File Facts

System
Linux kernel
Corpus path
sound/soc/sof/compress.c
Extension
.c
Size
11240 bytes
Lines
405
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-only OR BSD-3-Clause)
//
// Copyright 2021 NXP
//
// Author: Daniel Baluta <daniel.baluta@nxp.com>

#include <sound/soc.h>
#include <sound/sof.h>
#include <sound/compress_driver.h>
#include "sof-audio.h"
#include "sof-priv.h"
#include "sof-utils.h"
#include "ops.h"

static void sof_set_transferred_bytes(struct sof_compr_stream *sstream,
				      u64 host_pos, u64 buffer_size)
{
	u64 prev_pos;
	unsigned int copied;

	div64_u64_rem(sstream->copied_total, buffer_size, &prev_pos);

	if (host_pos < prev_pos)
		copied = (buffer_size - prev_pos) + host_pos;
	else
		copied = host_pos - prev_pos;

	sstream->copied_total += copied;
}

static void snd_sof_compr_fragment_elapsed_work(struct work_struct *work)
{
	struct snd_sof_pcm_stream *sps =
		container_of(work, struct snd_sof_pcm_stream,
			     period_elapsed_work);

	snd_compr_fragment_elapsed(sps->cstream);
}

void snd_sof_compr_init_elapsed_work(struct work_struct *work)
{
	INIT_WORK(work, snd_sof_compr_fragment_elapsed_work);
}

/*
 * sof compr fragment elapse, this could be called in irq thread context
 */
void snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstream)
{
	struct snd_soc_pcm_runtime *rtd;
	struct snd_compr_runtime *crtd;
	struct snd_soc_component *component;
	struct sof_compr_stream *sstream;
	struct snd_sof_pcm *spcm;

	if (!cstream)
		return;

	rtd = cstream->private_data;
	crtd = cstream->runtime;
	sstream = crtd->private_data;
	component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);

	spcm = snd_sof_find_spcm_dai(component, rtd);
	if (!spcm) {
		dev_err(component->dev,
			"fragment elapsed called for unknown stream!\n");
		return;
	}

	sof_set_transferred_bytes(sstream, spcm->stream[cstream->direction].posn.host_posn,
				  crtd->buffer_size);

	/* use the same workqueue-based solution as for PCM, cf. snd_sof_pcm_elapsed */
	schedule_work(&spcm->stream[cstream->direction].period_elapsed_work);
}

static int create_page_table(struct snd_soc_component *component,
			     struct snd_compr_stream *cstream,
			     unsigned char *dma_area, size_t size)
{
	struct snd_dma_buffer *dmab = cstream->runtime->dma_buffer_p;
	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
	int dir = cstream->direction;
	struct snd_sof_pcm *spcm;

	spcm = snd_sof_find_spcm_dai(component, rtd);
	if (!spcm)
		return -EINVAL;

Annotation

Implementation Notes