sound/virtio/virtio_chmap.c

Source file repositories/reference/linux-study-clean/sound/virtio/virtio_chmap.c

File Facts

System
Linux kernel
Corpus path
sound/virtio/virtio_chmap.c
Extension
.c
Size
5959 bytes
Lines
220
Domain
Driver Families
Bucket
sound/virtio
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

switch (info->direction) {
		case VIRTIO_SND_D_OUTPUT:
			vs = &vpcm->streams[SNDRV_PCM_STREAM_PLAYBACK];
			break;
		case VIRTIO_SND_D_INPUT:
			vs = &vpcm->streams[SNDRV_PCM_STREAM_CAPTURE];
			break;
		default:
			dev_err(&vdev->dev,
				"chmap #%u: unknown direction (%u)\n", i,
				info->direction);
			return -EINVAL;
		}

		vs->nchmaps++;
	}

	return 0;
}

/**
 * virtsnd_chmap_add_ctls() - Create an ALSA control for channel maps.
 * @pcm: ALSA PCM device.
 * @direction: PCM stream direction (SNDRV_PCM_STREAM_XXX).
 * @vs: VirtIO PCM stream.
 *
 * Context: Any context.
 * Return: 0 on success, -errno on failure.
 */
static int virtsnd_chmap_add_ctls(struct snd_pcm *pcm, int direction,
				  struct virtio_pcm_stream *vs)
{
	u32 i;
	int max_channels = 0;

	for (i = 0; i < vs->nchmaps; i++)
		if (max_channels < vs->chmaps[i].channels)
			max_channels = vs->chmaps[i].channels;

	return snd_pcm_add_chmap_ctls(pcm, direction, vs->chmaps, max_channels,
				      0, NULL);
}

/**
 * virtsnd_chmap_build_devs() - Build ALSA controls for channel maps.
 * @snd: VirtIO sound device.
 *
 * Context: Any context.
 * Return: 0 on success, -errno on failure.
 */
int virtsnd_chmap_build_devs(struct virtio_snd *snd)
{
	struct virtio_device *vdev = snd->vdev;
	struct virtio_pcm *vpcm;
	struct virtio_pcm_stream *vs;
	u32 i;
	int rc;

	/* Allocate channel map elements per each PCM device/stream. */
	list_for_each_entry(vpcm, &snd->pcm_list, list) {
		for (i = 0; i < ARRAY_SIZE(vpcm->streams); ++i) {
			vs = &vpcm->streams[i];

			if (!vs->nchmaps)
				continue;

			vs->chmaps = devm_kcalloc(&vdev->dev, vs->nchmaps + 1,
						  sizeof(*vs->chmaps),
						  GFP_KERNEL);
			if (!vs->chmaps)
				return -ENOMEM;

			vs->nchmaps = 0;
		}
	}

	/* Initialize channel maps per each PCM device/stream. */
	for (i = 0; i < snd->nchmaps; ++i) {
		struct virtio_snd_chmap_info *info = &snd->chmaps[i];
		unsigned int channels = info->channels;
		unsigned int ch;
		struct snd_pcm_chmap_elem *chmap;

		vpcm = virtsnd_pcm_find(snd, le32_to_cpu(info->hdr.hda_fn_nid));
		if (IS_ERR(vpcm))
			return PTR_ERR(vpcm);

		if (info->direction == VIRTIO_SND_D_OUTPUT)
			vs = &vpcm->streams[SNDRV_PCM_STREAM_PLAYBACK];
		else

Annotation

Implementation Notes