Quelle soc-usb.c
Sprache: C
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright ( c ) 2022 - 2025 Qualcomm Innovation Center , Inc . All rights reserved .
*/
#include <linux/of.h>
#include <linux/usb.h>
#include <sound/jack.h>
#include <sound/soc-usb.h>
#include "../usb/card.h"
static DEFINE_MUTEX(ctx_mutex);
static LIST_HEAD(usb_ctx_list);
static struct device_node *snd_soc_find_phandle(struct device *dev)
{
struct device_node *node;
node = of_parse_phandle(dev->of_node, "usb-soc-be" , 0 );
if (!node)
return ERR_PTR(-ENODEV);
return node;
}
static struct snd_soc_usb *snd_soc_usb_ctx_lookup(struct device_node *node)
{
struct snd_soc_usb *ctx;
if (!node)
return NULL;
list_for_each_entry(ctx, &usb_ctx_list, list) {
if (ctx->component->dev->of_node == node)
return ctx;
}
return NULL;
}
static struct snd_soc_usb *snd_soc_find_usb_ctx(struct device *dev)
{
struct snd_soc_usb *ctx;
struct device_node *node;
node = snd_soc_find_phandle(dev);
if (!IS_ERR(node)) {
ctx = snd_soc_usb_ctx_lookup(node);
of_node_put(node);
} else {
ctx = snd_soc_usb_ctx_lookup(dev->of_node);
}
return ctx ? ctx : NULL;
}
/* SOC USB sound kcontrols */
/**
* snd_soc_usb_setup_offload_jack ( ) - Create USB offloading jack
* @ component : USB DPCM backend DAI component
* @ jack : jack structure to create
*
* Creates a jack device for notifying userspace of the availability
* of an offload capable device .
*
* Returns 0 on success , negative on error .
*
*/
int snd_soc_usb_setup_offload_jack(struct snd_soc_component *component,
struct snd_soc_jack *jack)
{
int ret;
ret = snd_soc_card_jack_new(component->card, "USB Offload Jack" ,
SND_JACK_USB, jack);
if (ret < 0 ) {
dev_err(component->card->dev, "Unable to add USB offload jack: %d\n" ,
ret);
return ret;
}
ret = snd_soc_component_set_jack(component, jack, NULL);
if (ret) {
dev_err(component->card->dev, "Failed to set jack: %d\n" , ret);
return ret;
}
return 0 ;
}
EXPORT_SYMBOL_GPL(snd_soc_usb_setup_offload_jack);
/**
* snd_soc_usb_update_offload_route - Find active USB offload path
* @ dev : USB device to get offload status
* @ card : USB card index
* @ pcm : USB PCM device index
* @ direction : playback or capture direction
* @ path : pcm or card index
* @ route : pointer to route output array
*
* Fetch the current status for the USB SND card and PCM device indexes
* specified . The " route " argument should be an array of integers being
* used for a kcontrol output . The first element should have the selected
* card index , and the second element should have the selected pcm device
* index .
*/
int snd_soc_usb_update_offload_route(struct device *dev, int card, int pcm,
int direction, enum snd_soc_usb_kctl path,
long *route)
{
struct snd_soc_usb *ctx;
int ret = -ENODEV;
mutex_lock(&ctx_mutex);
ctx = snd_soc_find_usb_ctx(dev);
if (!ctx)
goto exit ;
if (ctx->update_offload_route_info)
ret = ctx->update_offload_route_info(ctx->component, card, pcm,
direction, path, route);
exit :
mutex_unlock(&ctx_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_usb_update_offload_route);
/**
* snd_soc_usb_find_priv_data ( ) - Retrieve private data stored
* @ usbdev : device reference
*
* Fetch the private data stored in the USB SND SoC structure .
*
*/
void *snd_soc_usb_find_priv_data(struct device *usbdev)
{
struct snd_soc_usb *ctx;
mutex_lock(&ctx_mutex);
ctx = snd_soc_find_usb_ctx(usbdev);
mutex_unlock(&ctx_mutex);
return ctx ? ctx->priv_data : NULL;
}
EXPORT_SYMBOL_GPL(snd_soc_usb_find_priv_data);
/**
* snd_soc_usb_find_supported_format ( ) - Check if audio format is supported
* @ card_idx : USB sound chip array index
* @ params : PCM parameters
* @ direction : capture or playback
*
* Ensure that a requested audio profile from the ASoC side is able to be
* supported by the USB device .
*
* Return 0 on success , negative on error .
*
*/
int snd_soc_usb_find_supported_format(int card_idx,
struct snd_pcm_hw_params *params,
int direction)
{
struct snd_usb_stream *as;
as = snd_usb_find_suppported_substream(card_idx, params, direction);
if (!as)
return -EOPNOTSUPP;
return 0 ;
}
EXPORT_SYMBOL_GPL(snd_soc_usb_find_supported_format);
/**
* snd_soc_usb_allocate_port ( ) - allocate a SoC USB port for offloading support
* @ component : USB DPCM backend DAI component
* @ data : private data
*
* Allocate and initialize a SoC USB port . The SoC USB port is used to communicate
* different USB audio devices attached , in order to start audio offloading handled
* by an ASoC entity . USB device plug in / out events are signaled with a
* notification , but don ' t directly impact the memory allocated for the SoC USB
* port .
*
*/
struct snd_soc_usb *snd_soc_usb_allocate_port(struct snd_soc_component *component,
void *data)
{
struct snd_soc_usb *usb;
usb = kzalloc(sizeof (*usb), GFP_KERNEL);
if (!usb)
return ERR_PTR(-ENOMEM);
usb->component = component;
usb->priv_data = data;
return usb;
}
EXPORT_SYMBOL_GPL(snd_soc_usb_allocate_port);
/**
* snd_soc_usb_free_port ( ) - free a SoC USB port used for offloading support
* @ usb : allocated SoC USB port
*
* Free and remove the SoC USB port from the available list of ports . This will
* ensure that the communication between USB SND and ASoC is halted .
*
*/
void snd_soc_usb_free_port(struct snd_soc_usb *usb)
{
snd_soc_usb_remove_port(usb);
kfree(usb);
}
EXPORT_SYMBOL_GPL(snd_soc_usb_free_port);
/**
* snd_soc_usb_add_port ( ) - Add a USB backend port
* @ usb : soc usb port to add
*
* Register a USB backend DAI link to the USB SoC framework . Memory is allocated
* as part of the USB backend DAI link .
*
*/
void snd_soc_usb_add_port(struct snd_soc_usb *usb)
{
mutex_lock(&ctx_mutex);
list_add_tail(&usb->list, &usb_ctx_list);
mutex_unlock(&ctx_mutex);
snd_usb_rediscover_devices();
}
EXPORT_SYMBOL_GPL(snd_soc_usb_add_port);
/**
* snd_soc_usb_remove_port ( ) - Remove a USB backend port
* @ usb : soc usb port to remove
*
* Remove a USB backend DAI link from USB SoC . Memory is freed when USB backend
* DAI is removed , or when snd_soc_usb_free_port ( ) is called .
*
*/
void snd_soc_usb_remove_port(struct snd_soc_usb *usb)
{
struct snd_soc_usb *ctx, *tmp;
mutex_lock(&ctx_mutex);
list_for_each_entry_safe(ctx, tmp, &usb_ctx_list, list) {
if (ctx == usb) {
list_del(&ctx->list);
break ;
}
}
mutex_unlock(&ctx_mutex);
}
EXPORT_SYMBOL_GPL(snd_soc_usb_remove_port);
/**
* snd_soc_usb_connect ( ) - Notification of USB device connection
* @ usbdev : USB bus device
* @ sdev : USB SND device to add
*
* Notify of a new USB SND device connection . The sdev - > card_idx can be used to
* handle how the DPCM backend selects , which device to enable USB offloading
* on .
*
*/
int snd_soc_usb_connect(struct device *usbdev, struct snd_soc_usb_device *sdev)
{
struct snd_soc_usb *ctx;
if (!usbdev)
return -ENODEV;
mutex_lock(&ctx_mutex);
ctx = snd_soc_find_usb_ctx(usbdev);
if (!ctx)
goto exit ;
if (ctx->connection_status_cb)
ctx->connection_status_cb(ctx, sdev, true );
exit :
mutex_unlock(&ctx_mutex);
return 0 ;
}
EXPORT_SYMBOL_GPL(snd_soc_usb_connect);
/**
* snd_soc_usb_disconnect ( ) - Notification of USB device disconnection
* @ usbdev : USB bus device
* @ sdev : USB SND device to remove
*
* Notify of a new USB SND device disconnection to the USB backend .
*
*/
int snd_soc_usb_disconnect(struct device *usbdev, struct snd_soc_usb_device *sdev)
{
struct snd_soc_usb *ctx;
if (!usbdev)
return -ENODEV;
mutex_lock(&ctx_mutex);
ctx = snd_soc_find_usb_ctx(usbdev);
if (!ctx)
goto exit ;
if (ctx->connection_status_cb)
ctx->connection_status_cb(ctx, sdev, false );
exit :
mutex_unlock(&ctx_mutex);
return 0 ;
}
EXPORT_SYMBOL_GPL(snd_soc_usb_disconnect);
MODULE_LICENSE("GPL" );
MODULE_DESCRIPTION("SoC USB driver for offloading" );
Messung V0.5 in Prozent C=97 H=95 G=95
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-09-29)
¤
*© Formatika GbR, Deutschland
2026-10-10
Neuigkeiten
Aktuelles
Motto des Tages
Open Source Software
Jenseits des Üblichen ....
Besucherstatistik
Statistik
#Sources=1126438
#Domains=1897691