Lines Matching +full:usb +full:- +full:audio +full:- +full:intr +full:- +full:idx

1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
8 #include <linux/dma-mapping.h>
9 #include <linux/dma-map-ops.h>
23 #include <sound/soc-usb.h>
25 #include <dt-bindings/sound/qcom,q6afe.h>
28 #include "q6dsp-lpass-ports.h"
35 struct snd_soc_usb *usb; member
39 /* Protects against operations between SOC USB and ASoC */
49 {"USB Playback", NULL, "USB_RX_BE"},
56 struct q6usb_port_data *data = dev_get_drvdata(dai->dev); in q6usb_hw_params()
57 struct snd_soc_pcm_runtime *rtd = substream->private_data; in q6usb_hw_params()
59 int direction = substream->stream; in q6usb_hw_params()
62 int ret = -EINVAL; in q6usb_hw_params()
64 mutex_lock(&data->mutex); in q6usb_hw_params()
67 if (list_empty(&data->devices)) in q6usb_hw_params()
70 sdev = list_last_entry(&data->devices, struct snd_soc_usb_device, list); in q6usb_hw_params()
72 ret = snd_soc_usb_find_supported_format(sdev->chip_idx, params, direction); in q6usb_hw_params()
76 q6usb_afe = q6afe_port_get_from_id(cpu_dai->dev, USB_RX); in q6usb_hw_params()
82 /* Notify audio DSP about the devices being offloaded */ in q6usb_hw_params()
83 ret = afe_port_send_usb_dev_param(q6usb_afe, sdev->card_idx, in q6usb_hw_params()
84 sdev->ppcm_idx[sdev->num_playback - 1]); in q6usb_hw_params()
87 mutex_unlock(&data->mutex); in q6usb_hw_params()
99 .stream_name = "USB BE RX",
124 int id = args->args[0]; in q6usb_audio_ports_of_xlate_dai_name()
125 int ret = -EINVAL; in q6usb_audio_ports_of_xlate_dai_name()
144 for_each_card_rtds(w->dapm->card, rtd) { in q6usb_get_pcm_id_from_widget()
150 if (dai->stream[0].widget == w) in q6usb_get_pcm_id_from_widget()
151 return rtd->id; in q6usb_get_pcm_id_from_widget()
154 return -1; in q6usb_get_pcm_id_from_widget()
161 /* Checks to ensure USB path is enabled/connected */ in q6usb_usb_mixer_enabled()
163 if (!strcmp(p->sink->name, "USB Mixer") && p->connect) in q6usb_usb_mixer_enabled()
178 * MultiMedia* <-> MM_DL* <-> USB Mixer* in q6usb_get_pcm_id()
180 for_each_card_widgets(component->card, w) { in q6usb_get_pcm_id()
181 if (!strncmp(w->name, "MultiMedia", 10)) { in q6usb_get_pcm_id()
184 * the USB BE is enabled. The sink widget is responsible to in q6usb_get_pcm_id()
185 * link with the USB mixers. in q6usb_get_pcm_id()
188 if (q6usb_usb_mixer_enabled(p->sink)) { in q6usb_get_pcm_id()
196 return -1; in q6usb_get_pcm_id()
203 struct q6usb_port_data *data = dev_get_drvdata(component->dev); in q6usb_update_offload_route()
206 int idx = -1; in q6usb_update_offload_route() local
208 mutex_lock(&data->mutex); in q6usb_update_offload_route()
210 if (list_empty(&data->devices) || in q6usb_update_offload_route()
212 ret = -ENODEV; in q6usb_update_offload_route()
216 sdev = list_last_entry(&data->devices, struct snd_soc_usb_device, list); in q6usb_update_offload_route()
222 if (card == sdev->card_idx && in q6usb_update_offload_route()
223 pcm == sdev->ppcm_idx[sdev->num_playback - 1]) { in q6usb_update_offload_route()
224 idx = path == SND_SOC_USB_KCTL_CARD_ROUTE ? in q6usb_update_offload_route()
225 component->card->snd_card->number : in q6usb_update_offload_route()
230 route[0] = idx; in q6usb_update_offload_route()
231 mutex_unlock(&data->mutex); in q6usb_update_offload_route()
236 static int q6usb_alsa_connection_cb(struct snd_soc_usb *usb, in q6usb_alsa_connection_cb() argument
241 if (!usb->component) in q6usb_alsa_connection_cb()
242 return -ENODEV; in q6usb_alsa_connection_cb()
244 data = dev_get_drvdata(usb->component->dev); in q6usb_alsa_connection_cb()
246 mutex_lock(&data->mutex); in q6usb_alsa_connection_cb()
248 if (data->hs_jack) in q6usb_alsa_connection_cb()
249 snd_jack_report(data->hs_jack->jack, SND_JACK_USB); in q6usb_alsa_connection_cb()
251 /* Selects the latest USB headset plugged in for offloading */ in q6usb_alsa_connection_cb()
252 list_add_tail(&sdev->list, &data->devices); in q6usb_alsa_connection_cb()
254 list_del(&sdev->list); in q6usb_alsa_connection_cb()
256 if (data->hs_jack) in q6usb_alsa_connection_cb()
257 snd_jack_report(data->hs_jack->jack, 0); in q6usb_alsa_connection_cb()
259 mutex_unlock(&data->mutex); in q6usb_alsa_connection_cb()
267 if (!data->hs_jack) in q6usb_component_disable_jack()
270 snd_jack_report(data->hs_jack->jack, 0); in q6usb_component_disable_jack()
271 data->hs_jack = NULL; in q6usb_component_disable_jack()
277 snd_jack_report(jack->jack, !list_empty(&data->devices) ? SND_JACK_USB : 0); in q6usb_component_enable_jack()
278 data->hs_jack = jack; in q6usb_component_enable_jack()
284 struct q6usb_port_data *data = dev_get_drvdata(component->dev); in q6usb_component_set_jack()
286 mutex_lock(&data->mutex); in q6usb_component_set_jack()
291 mutex_unlock(&data->mutex); in q6usb_component_set_jack()
303 auxdev->dev.parent = data->priv.dev; in q6usb_dai_add_aux_device()
304 auxdev->dev.release = q6usb_dai_aux_release; in q6usb_dai_add_aux_device()
305 auxdev->name = "qc-usb-audio-offload"; in q6usb_dai_add_aux_device()
320 struct q6usb_port_data *data = dev_get_drvdata(component->dev); in q6usb_component_probe()
321 struct snd_soc_usb *usb; in q6usb_component_probe() local
324 /* Add the QC USB SND aux device */ in q6usb_component_probe()
325 ret = q6usb_dai_add_aux_device(data, &data->uauxdev); in q6usb_component_probe()
329 usb = snd_soc_usb_allocate_port(component, &data->priv); in q6usb_component_probe()
330 if (IS_ERR(usb)) in q6usb_component_probe()
331 return -ENOMEM; in q6usb_component_probe()
333 usb->connection_status_cb = q6usb_alsa_connection_cb; in q6usb_component_probe()
334 usb->update_offload_route_info = q6usb_update_offload_route; in q6usb_component_probe()
336 snd_soc_usb_add_port(usb); in q6usb_component_probe()
337 data->usb = usb; in q6usb_component_probe()
344 struct q6usb_port_data *data = dev_get_drvdata(component->dev); in q6usb_component_remove()
346 snd_soc_usb_remove_port(data->usb); in q6usb_component_remove()
347 auxiliary_device_delete(&data->uauxdev); in q6usb_component_remove()
348 auxiliary_device_uninit(&data->uauxdev); in q6usb_component_remove()
349 snd_soc_usb_free_port(data->usb); in q6usb_component_remove()
356 .name = "q6usb-dai-component",
366 struct device_node *node = pdev->dev.of_node; in q6usb_dai_dev_probe()
368 struct device *dev = &pdev->dev; in q6usb_dai_dev_probe()
374 return -ENOMEM; in q6usb_dai_dev_probe()
376 ret = of_property_read_u16(node, "qcom,usb-audio-intr-idx", in q6usb_dai_dev_probe()
377 &data->priv.intr_num); in q6usb_dai_dev_probe()
379 dev_err(&pdev->dev, "failed to read intr idx.\n"); in q6usb_dai_dev_probe()
385 data->priv.sid = args.args[0] & Q6_USB_SID_MASK; in q6usb_dai_dev_probe()
387 ret = devm_mutex_init(dev, &data->mutex); in q6usb_dai_dev_probe()
391 data->priv.domain = iommu_get_domain_for_dev(&pdev->dev); in q6usb_dai_dev_probe()
393 data->priv.dev = dev; in q6usb_dai_dev_probe()
394 INIT_LIST_HEAD(&data->devices); in q6usb_dai_dev_probe()
409 .name = "q6usb-dai",
420 MODULE_DESCRIPTION("Q6 USB backend dai driver");