mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-03 17:40:04 +00:00
![Shuah Khan](/assets/img/avatar_default.png)
Media Device Allocator API to allows multiple drivers share a media device. This API solves a very common use-case for media devices where one physical device (an USB stick) provides both audio and video. When such media device exposes a standard USB Audio class, a proprietary Video class, two or more independent drivers will share a single physical USB bridge. In such cases, it is necessary to coordinate access to the shared resource. Using this API, drivers can allocate a media device with the shared struct device as the key. Once the media device is allocated by a driver, other drivers can get a reference to it. The media device is released when all the references are released. Change the ALSA driver to use the Media Controller API to share media resources with DVB, and V4L2 drivers on a AU0828 media device. The Media Controller specific initialization is done after sound card is registered. ALSA creates Media interface and entity function graph nodes for Control, Mixer, PCM Playback, and PCM Capture devices. snd_usb_hw_params() will call Media Controller enable source handler interface to request the media resource. If resource request is granted, it will release it from snd_usb_hw_free(). If resource is busy, -EBUSY is returned. Media specific cleanup is done in usb_audio_disconnect(). Reviewed-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Shuah Khan <shuah@kernel.org> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
117 lines
3.3 KiB
C
117 lines
3.3 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef __USBMIXER_H
|
|
#define __USBMIXER_H
|
|
|
|
#include <sound/info.h>
|
|
|
|
struct media_mixer_ctl;
|
|
|
|
struct usb_mixer_interface {
|
|
struct snd_usb_audio *chip;
|
|
struct usb_host_interface *hostif;
|
|
struct list_head list;
|
|
unsigned int ignore_ctl_error;
|
|
struct urb *urb;
|
|
/* array[MAX_ID_ELEMS], indexed by unit id */
|
|
struct usb_mixer_elem_list **id_elems;
|
|
|
|
/* the usb audio specification version this interface complies to */
|
|
int protocol;
|
|
|
|
/* Sound Blaster remote control stuff */
|
|
const struct rc_config *rc_cfg;
|
|
u32 rc_code;
|
|
wait_queue_head_t rc_waitq;
|
|
struct urb *rc_urb;
|
|
struct usb_ctrlrequest *rc_setup_packet;
|
|
u8 rc_buffer[6];
|
|
struct media_mixer_ctl *media_mixer_ctl;
|
|
|
|
bool disconnected;
|
|
};
|
|
|
|
#define MAX_CHANNELS 16 /* max logical channels */
|
|
|
|
enum {
|
|
USB_MIXER_BOOLEAN,
|
|
USB_MIXER_INV_BOOLEAN,
|
|
USB_MIXER_S8,
|
|
USB_MIXER_U8,
|
|
USB_MIXER_S16,
|
|
USB_MIXER_U16,
|
|
USB_MIXER_S32,
|
|
USB_MIXER_U32,
|
|
};
|
|
|
|
typedef void (*usb_mixer_elem_dump_func_t)(struct snd_info_buffer *buffer,
|
|
struct usb_mixer_elem_list *list);
|
|
typedef int (*usb_mixer_elem_resume_func_t)(struct usb_mixer_elem_list *elem);
|
|
|
|
struct usb_mixer_elem_list {
|
|
struct usb_mixer_interface *mixer;
|
|
struct usb_mixer_elem_list *next_id_elem; /* list of controls with same id */
|
|
struct snd_kcontrol *kctl;
|
|
unsigned int id;
|
|
usb_mixer_elem_dump_func_t dump;
|
|
usb_mixer_elem_resume_func_t resume;
|
|
};
|
|
|
|
/* iterate over mixer element list of the given unit id */
|
|
#define for_each_mixer_elem(list, mixer, id) \
|
|
for ((list) = (mixer)->id_elems[id]; (list); (list) = (list)->next_id_elem)
|
|
#define mixer_elem_list_to_info(list) \
|
|
container_of(list, struct usb_mixer_elem_info, head)
|
|
|
|
struct usb_mixer_elem_info {
|
|
struct usb_mixer_elem_list head;
|
|
unsigned int control; /* CS or ICN (high byte) */
|
|
unsigned int cmask; /* channel mask bitmap: 0 = master */
|
|
unsigned int idx_off; /* Control index offset */
|
|
unsigned int ch_readonly;
|
|
unsigned int master_readonly;
|
|
int channels;
|
|
int val_type;
|
|
int min, max, res;
|
|
int dBmin, dBmax;
|
|
int cached;
|
|
int cache_val[MAX_CHANNELS];
|
|
u8 initialized;
|
|
u8 min_mute;
|
|
void *private_data;
|
|
};
|
|
|
|
int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
|
|
int ignore_error);
|
|
void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer);
|
|
|
|
void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid);
|
|
|
|
int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
|
|
int request, int validx, int value_set);
|
|
|
|
int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list,
|
|
struct snd_kcontrol *kctl);
|
|
|
|
void snd_usb_mixer_elem_init_std(struct usb_mixer_elem_list *list,
|
|
struct usb_mixer_interface *mixer,
|
|
int unitid);
|
|
|
|
int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
|
|
unsigned int size, unsigned int __user *_tlv);
|
|
|
|
#ifdef CONFIG_PM
|
|
int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer);
|
|
int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume);
|
|
#endif
|
|
|
|
int snd_usb_set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
|
|
int index, int value);
|
|
|
|
int snd_usb_get_cur_mix_value(struct usb_mixer_elem_info *cval,
|
|
int channel, int index, int *value);
|
|
|
|
extern void snd_usb_mixer_elem_free(struct snd_kcontrol *kctl);
|
|
|
|
extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
|
|
|
|
#endif /* __USBMIXER_H */
|