File Index
Files and directories
Sign in
FILE

mixer_usb_offload.c

File preview with syntax highlighting.

linux-6.19.14/sound/usb/qcom/mixer_usb_offload.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
  4 */
  5
  6#include <linux/usb.h>
  7
  8#include <sound/core.h>
  9#include <sound/control.h>
 10#include <sound/soc-usb.h>
 11
 12#include "../usbaudio.h"
 13#include "../card.h"
 14#include "../helper.h"
 15#include "../mixer.h"
 16
 17#include "mixer_usb_offload.h"
 18
 19#define PCM_IDX(n)  ((n) & 0xffff)
 20#define CARD_IDX(n) ((n) >> 16)
 21
 22static int
 23snd_usb_offload_card_route_get(struct snd_kcontrol *kcontrol,
 24			       struct snd_ctl_elem_value *ucontrol)
 25{
 26	struct device *sysdev = snd_kcontrol_chip(kcontrol);
 27	int ret;
 28
 29	ret = snd_soc_usb_update_offload_route(sysdev,
 30					       CARD_IDX(kcontrol->private_value),
 31					       PCM_IDX(kcontrol->private_value),
 32					       SNDRV_PCM_STREAM_PLAYBACK,
 33					       SND_SOC_USB_KCTL_CARD_ROUTE,
 34					       ucontrol->value.integer.value);
 35	if (ret < 0) {
 36		ucontrol->value.integer.value[0] = -1;
 37		ucontrol->value.integer.value[1] = -1;
 38	}
 39
 40	return 0;
 41}
 42
 43static int snd_usb_offload_card_route_info(struct snd_kcontrol *kcontrol,
 44					   struct snd_ctl_elem_info *uinfo)
 45{
 46	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 47	uinfo->count = 1;
 48	uinfo->value.integer.min = -1;
 49	uinfo->value.integer.max = SNDRV_CARDS;
 50
 51	return 0;
 52}
 53
 54static struct snd_kcontrol_new snd_usb_offload_mapped_card_ctl = {
 55	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
 56	.access = SNDRV_CTL_ELEM_ACCESS_READ,
 57	.info = snd_usb_offload_card_route_info,
 58	.get = snd_usb_offload_card_route_get,
 59};
 60
 61static int
 62snd_usb_offload_pcm_route_get(struct snd_kcontrol *kcontrol,
 63			      struct snd_ctl_elem_value *ucontrol)
 64{
 65	struct device *sysdev = snd_kcontrol_chip(kcontrol);
 66	int ret;
 67
 68	ret = snd_soc_usb_update_offload_route(sysdev,
 69					       CARD_IDX(kcontrol->private_value),
 70					       PCM_IDX(kcontrol->private_value),
 71					       SNDRV_PCM_STREAM_PLAYBACK,
 72					       SND_SOC_USB_KCTL_PCM_ROUTE,
 73					       ucontrol->value.integer.value);
 74	if (ret < 0) {
 75		ucontrol->value.integer.value[0] = -1;
 76		ucontrol->value.integer.value[1] = -1;
 77	}
 78
 79	return 0;
 80}
 81
 82static int snd_usb_offload_pcm_route_info(struct snd_kcontrol *kcontrol,
 83					  struct snd_ctl_elem_info *uinfo)
 84{
 85	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 86	uinfo->count = 1;
 87	uinfo->value.integer.min = -1;
 88	/* Arbitrary max value, as there is no 'limit' on number of PCM devices */
 89	uinfo->value.integer.max = 0xff;
 90
 91	return 0;
 92}
 93
 94static struct snd_kcontrol_new snd_usb_offload_mapped_pcm_ctl = {
 95	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
 96	.access = SNDRV_CTL_ELEM_ACCESS_READ,
 97	.info = snd_usb_offload_pcm_route_info,
 98	.get = snd_usb_offload_pcm_route_get,
 99};
100
101/**
102 * snd_usb_offload_create_ctl() - Add USB offload bounded mixer
103 * @chip: USB SND chip device
104 * @bedev: Reference to USB backend DAI device
105 *
106 * Creates a sound control for a USB audio device, so that applications can
107 * query for if there is an available USB audio offload path, and which
108 * card is managing it.
109 */
110int snd_usb_offload_create_ctl(struct snd_usb_audio *chip, struct device *bedev)
111{
112	struct snd_kcontrol_new *chip_kctl;
113	struct snd_usb_substream *subs;
114	struct snd_usb_stream *as;
115	char ctl_name[48];
116	int ret;
117
118	list_for_each_entry(as, &chip->pcm_list, list) {
119		subs = &as->substream[SNDRV_PCM_STREAM_PLAYBACK];
120		if (!subs->ep_num || as->pcm_index > 0xff)
121			continue;
122
123		chip_kctl = &snd_usb_offload_mapped_card_ctl;
124		chip_kctl->count = 1;
125		/*
126		 * Store the associated USB SND card number and PCM index for
127		 * the kctl.
128		 */
129		chip_kctl->private_value = as->pcm_index |
130					  chip->card->number << 16;
131		sprintf(ctl_name, "USB Offload Playback Card Route PCM#%d",
132			as->pcm_index);
133		chip_kctl->name = ctl_name;
134		ret = snd_ctl_add(chip->card, snd_ctl_new1(chip_kctl, bedev));
135		if (ret < 0)
136			break;
137
138		chip_kctl = &snd_usb_offload_mapped_pcm_ctl;
139		chip_kctl->count = 1;
140		/*
141		 * Store the associated USB SND card number and PCM index for
142		 * the kctl.
143		 */
144		chip_kctl->private_value = as->pcm_index |
145					  chip->card->number << 16;
146		sprintf(ctl_name, "USB Offload Playback PCM Route PCM#%d",
147			as->pcm_index);
148		chip_kctl->name = ctl_name;
149		ret = snd_ctl_add(chip->card, snd_ctl_new1(chip_kctl, bedev));
150		if (ret < 0)
151			break;
152	}
153
154	return ret;
155}
~/ Read-only file preview.