[PATCH v1 3/3] sound: usb: Exynos usb audio offloading driver
Greg Kroah-Hartman
gregkh at linuxfoundation.org
Thu Mar 24 09:41:26 CET 2022
On Thu, Mar 24, 2022 at 05:10:44PM +0900, Oh Eomji wrote:
> This is for usb audio offloading. usb audio offloading processes usb
> audio stream data directly from the audio box even if ap usb enters
> suspend, there is no problem in stream data transmission. This obtains
> power saving effect while using usb audio device.
>
> AP usb and audio usb f/w communicate via AUDIO IPC. By performing AUDIO
> IPC in the vendor operations, abox can access and control the xhci to
> transmit the data directly.
>
> The types of commands and data delivered through AUDIO IPC include the
> following (AP USB <-> AUDIO USB f/w) :
> 1. usb audio connection/disconnection status
> 2. xhci memory information
> 3. full descriptor for usb audio device
> 4. UAC(usb audio class) control command
>
> Signed-off-by: Oh Eomji <eomji.oh at samsung.com>
> ---
> sound/usb/Kconfig | 9 +
> sound/usb/Makefile | 2 +
> sound/usb/exynos_usb_audio.c | 560 +++++++++++++++++++++++++++++++++++++++++++
> sound/usb/exynos_usb_audio.h | 150 ++++++++++++
> 4 files changed, 721 insertions(+)
> create mode 100644 sound/usb/exynos_usb_audio.c
> create mode 100644 sound/usb/exynos_usb_audio.h
>
> diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
> index 059242f..70252a3 100644
> --- a/sound/usb/Kconfig
> +++ b/sound/usb/Kconfig
> @@ -27,6 +27,15 @@ config SND_USB_AUDIO
> config SND_USB_AUDIO_USE_MEDIA_CONTROLLER
> bool
>
> +config SND_EXYNOS_USB_AUDIO
> + tristate "EXYNOS USB Audio offloading module"
> + depends on SND_USB_AUDIO
> + help
> + Say Y here to include support for Exynos USB Audio ABOX offloading.
> +
> + To compile this driver as a module, choose M here: the module
> + will be called exynos-usb-audio-offloading.
> +
> config SND_USB_UA101
> tristate "Edirol UA-101/UA-1000 driver"
> select SND_PCM
> diff --git a/sound/usb/Makefile b/sound/usb/Makefile
> index 9ccb21a..bf019c7 100644
> --- a/sound/usb/Makefile
> +++ b/sound/usb/Makefile
> @@ -28,6 +28,8 @@ snd-usbmidi-lib-objs := midi.o
>
> # Toplevel Module Dependency
> obj-$(CONFIG_SND_USB_AUDIO) += snd-usb-audio.o snd-usbmidi-lib.o
> +obj-$(CONFIG_SND_EXYNOS_USB_AUDIO) += exynos-usb-audio-offloading.o
> +exynos-usb-audio-offloading-y += exynos_usb_audio.o
>
> obj-$(CONFIG_SND_USB_UA101) += snd-usbmidi-lib.o
> obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o
> diff --git a/sound/usb/exynos_usb_audio.c b/sound/usb/exynos_usb_audio.c
> new file mode 100644
> index 0000000..456cc78
> --- /dev/null
> +++ b/sound/usb/exynos_usb_audio.c
> @@ -0,0 +1,560 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
Are you sure about this license? I have to ask, sorry.
> +/*
> + * USB Audio offloading Driver for Exynos
> + *
> + * Copyright (c) 2017 by Kyounghye Yun <k-hye.yun at samsung.com>
> + *
> + */
> +
> +
> +#include <linux/bitops.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/string.h>
> +#include <linux/ctype.h>
> +#include <linux/usb.h>
> +#include <linux/usb/audio.h>
> +#include <linux/usb/audio-v2.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/io.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/completion.h>
> +
> +#include <sound/pcm.h>
> +#include "../../../sound/usb/exynos_usb_audio.h"
Did this patch just break the build? It should not need this type of
.../../../ mess.
> +#include "usbaudio.h"
> +#include "helper.h"
> +#include "card.h"
> +#include "quirks.h"
> +
> +static struct exynos_usb_audio *usb_audio;
> +static struct snd_usb_audio_vendor_ops exynos_usb_audio_ops;
> +
> +struct hcd_hw_info *g_hwinfo;
> +EXPORT_SYMBOL_GPL(g_hwinfo);
> +int otg_connection;
> +EXPORT_SYMBOL_GPL(otg_connection);
> +int usb_audio_connection;
> +EXPORT_SYMBOL_GPL(usb_audio_connection);
Why are these exported? Who uses them? And why generic names for a
driver-specific variable? And what do they do and how are they
accessed?
No one in this patch series needs these exports, so why are they
exported?
> +
> +static void exynos_usb_audio_set_device(struct usb_device *udev)
> +{
> + usb_audio->udev = udev;
> + usb_audio->is_audio = 1;
boolean?
How do you know? Did you check?
And why a single static variable?
> +}
> +
> +static int exynos_usb_audio_unmap_all(void)
> +{
> + /*
> + * TODO: unmapping pcm buffer, usb descriptor, Device Context,
> + * Input Context, ERST, URAM.
> + */
If this is not completed, just don't have the function at all.
Why isn't this done?
> +
> + return 0;
> +}
> +
> +static int exynos_usb_audio_pcmbuf(struct usb_device *udev, int iface)
> +{
> + if (!usb_audio->is_audio || !otg_connection)
> + return -1;
Do not make up error values. Use correct ones.
> +
> + /*
> + * TODO: Transmit the DRAM address that contains the xhci device
> + * information,and the DMA address required for operation to the abox
> + * usb f/w.
> + */
So this function does nothing?
Does this driver even work properly? Where is the missing logic?
> +
> + return 0;
> +}
> +
> +static int exynos_usb_audio_setrate(int iface, int rate, int alt)
> +{
> + if (!usb_audio->is_audio || !otg_connection)
> + return -1;
> +
> + /*
> + * TODO: Notify the abox usb f/w the audio sample rate supported by
> + * the interface of the connected audio device.
> + */
Same as above.
Does this driver actually work on real hardware? Or is this just a
"fake" driver that is never intended for anyone to use just to allow the
hooks to be added to the kernel tree?
What hardware has this driver worked on? Can I take the pixel6 device
today and replace their out-of-tree driver with this one and will it
work properly? If not, what is missing?
> +
> + return 0;
> +}
> +
> +static int exynos_usb_audio_setintf(struct usb_device *udev, int iface, int alt, int direction)
> +{
> + struct hcd_hw_info *hwinfo = g_hwinfo;
> + u64 in_offset, out_offset;
> +
> + if (!usb_audio->pcm_open_done)
> + return -EPERM;
How is that a permission error?
> +
> + if (!usb_audio->is_audio || !otg_connection)
> + return -1;
Again, no fake error numbers.
> +
> + if (direction) {
> + /* IN EP */
> + if (!usb_audio->indeq_map_done ||
> + (hwinfo->in_deq != hwinfo->old_in_deq)) {
> + /* TODO: Transmit pcm interface number, alt setting
> + * number to abox usb f/w
> + */
Fix all TODO please before resubmitting.
> + usb_audio->indeq_map_done = 1;
> + in_offset = hwinfo->in_deq % PAGE_SIZE;
Why does PAGE_SIZE matter?
> + }
> +
> + if (hwinfo->fb_out_deq) {
> + if (!usb_audio->fb_outdeq_map_done ||
> + (hwinfo->fb_out_deq != hwinfo->fb_old_out_deq)) {
> + /* TODO: Transmit pcm interface number,
> + * alt setting number to abox usb f/w
> + */
> + usb_audio->fb_outdeq_map_done = 1;
> + out_offset = hwinfo->fb_out_deq % PAGE_SIZE;
> + }
> + }
> + } else {
> + /* OUT EP */
> + if (!usb_audio->outdeq_map_done ||
> + (hwinfo->out_deq != hwinfo->old_out_deq)) {
> + /* TODO: Transmit pcm interface number, alt setting
> + * number to abox usb f/w
> + */
> + usb_audio->outdeq_map_done = 1;
> + out_offset = hwinfo->out_deq % PAGE_SIZE;
> + }
> +
> + if (hwinfo->fb_in_deq) {
> + if (!usb_audio->fb_indeq_map_done ||
> + (hwinfo->fb_in_deq != hwinfo->fb_old_in_deq)) {
> + /* TODO: Transmit pcm interface number,
> + * alt setting number to abox usb f/w
> + */
> + usb_audio->fb_indeq_map_done = 1;
> + in_offset = hwinfo->fb_in_deq % PAGE_SIZE;
> + }
> + }
> + }
> +
> + /* one more check connection to prevent kernel panic */
> + if (!usb_audio->is_audio || !otg_connection)
> + return -1;
> +
> + /* TODO: Notify abox usb f/w a dequeue pointer */
> +
> + return 0;
> +}
> +
> +static int exynos_usb_audio_hcd(struct usb_device *udev)
> +{
> + struct hcd_hw_info *hwinfo = g_hwinfo;
> +
> + /* back up each address for unmap */
> + usb_audio->dcbaa_dma = hwinfo->dcbaa_dma;
> + usb_audio->save_dma = hwinfo->save_dma;
> + usb_audio->in_ctx = hwinfo->in_ctx;
> + usb_audio->out_ctx = hwinfo->out_ctx;
> + usb_audio->erst_addr = hwinfo->erst_addr;
> + usb_audio->speed = hwinfo->speed;
> + usb_audio->use_uram = hwinfo->use_uram;
> +
> + /*
> + * TODO: DCBAA, Device Context, Input Context, URAM, ERST mapping
> + * and notify abox usb f/w the address about xhci h/w resource to
> + * directly control the xhci in abox.
> + */
> +
> + return 0;
> +}
> +
> +static int exynos_usb_audio_desc(struct usb_device *udev)
> +{
> + int configuration, cfgno, i;
> + unsigned char *buffer;
> + u64 desc_addr;
> + u64 offset;
> +
> + configuration = usb_choose_configuration(udev);
> +
> + cfgno = -1;
> + for (i = 0; i < udev->descriptor.bNumConfigurations; i++) {
> + if (udev->config[i].desc.bConfigurationValue ==
> + configuration) {
> + cfgno = i;
> + break;
> + }
> + }
> +
> + if (cfgno == -1)
> + cfgno = 0;
> +
> + /* need to memory mapping for usb descriptor */
> + buffer = udev->rawdescriptors[cfgno];
> + desc_addr = virt_to_phys(buffer);
> + offset = desc_addr % PAGE_SIZE;
> +
> + /* store address information */
> + usb_audio->desc_addr = desc_addr;
> + usb_audio->offset = offset;
> +
> + desc_addr -= offset;
> +
> + /*
> + * TODO: Notify the abox usb f/w that all descriptors have been recived
> + * from the connected usb audio device, and that copy and memory mapping
> + * have beed completed so that it can be used in abox usb f/w
> + */
> +
> + return 0;
> +}
> +
> +static int exynos_usb_audio_conn(struct usb_device *udev, int is_conn)
> +{
> +
> + /* TODO: Notify abox usb f/w whether usb device is connected or not */
> + if (!is_conn) {
> + if (usb_audio->is_audio) {
> + usb_audio->is_audio = 0;
> + usb_audio->usb_audio_state = USB_AUDIO_REMOVING;
> + }
> + } else {
> + cancel_work_sync(&usb_audio->usb_work);
> + usb_audio->indeq_map_done = 0;
> + usb_audio->outdeq_map_done = 0;
> + usb_audio->fb_indeq_map_done = 0;
> + usb_audio->fb_outdeq_map_done = 0;
> + usb_audio->pcm_open_done = 0;
> + reinit_completion(&usb_audio->discon_done);
> + usb_audio->usb_audio_state = USB_AUDIO_CONNECT;
> + usb_audio_connection = 1;
> + }
> +
> + return 0;
> +}
> +
> +static int exynos_usb_audio_pcm(bool is_open, bool direction)
> +{
> + if (!usb_audio->is_audio || !otg_connection)
> + return -1;
> +
> + if (is_open)
> + usb_audio->pcm_open_done = 1;
> +
> + /* TODO: Notify the abox usb f/w the pcm open/close status */
> +
> + return 0;
> +}
> +
> +static void exynos_usb_audio_work(struct work_struct *w)
> +{
> + /* Don't unmap in USB_AUDIO_TIMEOUT_PROBE state */
> + if (usb_audio->usb_audio_state != USB_AUDIO_REMOVING)
> + return;
> +
> + exynos_usb_audio_unmap_all();
> + usb_audio->usb_audio_state = USB_AUDIO_DISCONNECT;
> + usb_audio_connection = 0;
> + complete(&usb_audio->discon_done);
> +}
> +
> +static int exynos_usb_scenario_ctl_info(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_info *uinfo)
> +{
> + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
> + uinfo->count = 1;
> + uinfo->value.integer.min = AUDIO_MODE_NORMAL;
> + uinfo->value.integer.max = AUDIO_MODE_CALL_SCREEN;
> + return 0;
> +}
> +
> +static int exynos_usb_scenario_ctl_get(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + struct exynos_usb_audio *usb = snd_kcontrol_chip(kcontrol);
> +
> + ucontrol->value.integer.value[0] = usb->user_scenario;
> + return 0;
> +}
> +
> +static int exynos_usb_scenario_ctl_put(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + struct exynos_usb_audio *usb = snd_kcontrol_chip(kcontrol);
> + int changed = 0;
> +
> + if (usb->user_scenario !=
> + ucontrol->value.integer.value[0]) {
> + usb->user_scenario = ucontrol->value.integer.value[0];
> + changed = 1;
> + }
> +
> + return changed;
> +}
> +
> +static int exynos_usb_add_ctls(struct snd_usb_audio *chip,
> + unsigned long private_value)
> +{
> + struct snd_kcontrol_new knew = {
> + .iface = SNDRV_CTL_ELEM_IFACE_PCM,
> + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
> + .name = "USB Audio Mode",
> + .info = exynos_usb_scenario_ctl_info,
> + .get = exynos_usb_scenario_ctl_get,
> + .put = exynos_usb_scenario_ctl_put,
> + };
> +
> + int err;
> +
> + if (!chip)
> + return -ENODEV;
> +
> + knew.private_value = private_value;
> + usb_audio->kctl = snd_ctl_new1(&knew, usb_audio);
> + if (!usb_audio->kctl)
> + return -ENOMEM;
> +
> + err = snd_ctl_add(chip->card, usb_audio->kctl);
> + if (err < 0)
> + return err;
> +
> + return 0;
> +}
> +
> +int exynos_usb_audio_init(struct device *dev, struct platform_device *pdev)
> +{
> + struct device_node *np = dev->of_node;
> + struct device_node *np_abox;
> + struct platform_device *pdev_abox;
> + int ret = 0;
> +
> + if (!usb_audio) {
> + usb_audio = kmalloc(sizeof(struct exynos_usb_audio), GFP_KERNEL);
> + if (!usb_audio)
> + return -ENOMEM;
> + }
> +
> + np_abox = of_parse_phandle(np, "abox", 0);
> + if (!np_abox)
> + return -EPROBE_DEFER;
> +
> + pdev_abox = of_find_device_by_node(np_abox);
> + if (!pdev_abox)
> + return -EPROBE_DEFER;
> +
> + init_completion(&usb_audio->in_conn_stop);
> + init_completion(&usb_audio->out_conn_stop);
> + init_completion(&usb_audio->discon_done);
> + usb_audio->abox = pdev_abox;
> + usb_audio->hcd_pdev = pdev;
> + usb_audio->udev = NULL;
> + usb_audio->is_audio = 0;
> + usb_audio->is_first_probe = 1;
> + usb_audio->user_scenario = AUDIO_MODE_NORMAL;
> + usb_audio->usb_audio_state = USB_AUDIO_DISCONNECT;
> + usb_audio_connection = 0;
> +
> + INIT_WORK(&usb_audio->usb_work, exynos_usb_audio_work);
> +
> + /* interface function mapping */
> + ret = snd_vendor_set_ops(&exynos_usb_audio_ops);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(exynos_usb_audio_init);
Why are you exporting functions that are never called?
> +
> +/* card */
> +static int exynos_usb_audio_connect(struct usb_interface *intf)
> +{
> + struct usb_interface_descriptor *altsd;
> + struct usb_host_interface *alts;
> + struct usb_device *udev = interface_to_usbdev(intf);
> + int timeout = 0;
> +
> + alts = &intf->altsetting[0];
> + altsd = get_iface_desc(alts);
> +
> + if ((altsd->bInterfaceClass == USB_CLASS_AUDIO ||
> + altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC) &&
> + altsd->bInterfaceSubClass == USB_SUBCLASS_MIDISTREAMING) {
> + } else {
> + if (usb_audio->usb_audio_state == USB_AUDIO_REMOVING) {
> + timeout = wait_for_completion_timeout(
> + &usb_audio->discon_done,
> + msecs_to_jiffies(DISCONNECT_TIMEOUT));
> +
> + if ((usb_audio->usb_audio_state == USB_AUDIO_REMOVING)
> + && !timeout) {
> + usb_audio->usb_audio_state =
> + USB_AUDIO_TIMEOUT_PROBE;
> + }
> + }
> +
> + if ((usb_audio->usb_audio_state == USB_AUDIO_DISCONNECT)
> + || (usb_audio->usb_audio_state == USB_AUDIO_TIMEOUT_PROBE)) {
> + exynos_usb_audio_set_device(udev);
> + exynos_usb_audio_hcd(udev);
> + exynos_usb_audio_conn(udev, 1);
> + exynos_usb_audio_desc(udev);
> + } else {
> + return -EPERM;
> + }
> + }
> +
> + return 0;
> +}
> +
> +static void exynos_usb_audio_disconn(struct usb_interface *intf)
> +{
> + struct usb_device *udev = interface_to_usbdev(intf);
> +
> + exynos_usb_audio_conn(udev, 0);
> +}
> +
> +/* clock */
> +static int exynos_usb_audio_set_interface(struct usb_device *udev,
> + struct usb_host_interface *alts, int iface, int alt)
> +{
> + unsigned char ep;
> + unsigned char numEndpoints;
> + int direction;
> + int i;
> + int ret = 0;
> +
> + if (alts != NULL) {
> + numEndpoints = get_iface_desc(alts)->bNumEndpoints;
> + if (numEndpoints < 1)
> + return -22;
> + if (numEndpoints == 1)
> + ep = get_endpoint(alts, 0)->bEndpointAddress;
> + else {
> + for (i = 0; i < numEndpoints; i++) {
> + ep = get_endpoint(alts, i)->bmAttributes;
> + if (!(ep & 0x30)) {
> + ep = get_endpoint(alts, i)->bEndpointAddress;
> + break;
> + }
> + }
> + }
> + if (ep & USB_DIR_IN)
> + direction = SNDRV_PCM_STREAM_CAPTURE;
> + else
> + direction = SNDRV_PCM_STREAM_PLAYBACK;
> +
> + ret = exynos_usb_audio_setintf(udev, iface, alt, direction);
> + }
> +
> + return ret;
> +}
> +
> +/* pcm */
> +static int exynos_usb_audio_set_rate(int iface, int rate, int alt)
> +{
> + int ret;
> +
> + ret = exynos_usb_audio_setrate(iface, rate, alt);
> +
> + return ret;
> +}
> +
> +static int exynos_usb_audio_set_pcmbuf(struct usb_device *dev, int iface)
> +{
> + int ret;
> +
> + ret = exynos_usb_audio_pcmbuf(dev, iface);
> +
> + return ret;
> +}
> +
> +static int exynos_usb_audio_set_pcm_intf(struct usb_interface *intf,
> + int iface, int alt, int direction)
> +{
> + struct usb_device *udev = interface_to_usbdev(intf);
> + int ret;
> +
> + ret = exynos_usb_audio_setintf(udev, iface, alt, direction);
> +
> + return ret;
> +}
> +
> +static int exynos_usb_audio_pcm_control(struct usb_device *udev,
> + enum snd_vendor_pcm_open_close onoff, int direction)
> +{
> + int ret = 0;
> +
> + if (onoff == 1) {
> + ret = exynos_usb_audio_pcm(1, direction);
> + } else if (onoff == 0) {
> + if (direction == SNDRV_PCM_STREAM_PLAYBACK)
> + reinit_completion(&usb_audio->out_conn_stop);
> + else if (direction == SNDRV_PCM_STREAM_CAPTURE)
> + reinit_completion(&usb_audio->in_conn_stop);
> +
> + if (!usb_audio->pcm_open_done)
> + return 0;
> +
> + ret = exynos_usb_audio_pcm(0, direction);
> + }
> +
> + return ret;
> +}
> +
> +static int exynos_usb_audio_add_control(struct snd_usb_audio *chip)
> +{
> + int ret;
> +
> + if (chip != NULL)
> + ret = exynos_usb_add_ctls(chip, 0);
> + else
> + ret = usb_audio->user_scenario;
> +
> + return ret;
> +}
> +
> +static int exynos_usb_audio_set_pcm_binterval(const struct audioformat *fp,
> + const struct audioformat *found,
> + int *cur_attr, int *attr)
> +{
> + if (usb_audio->user_scenario >= AUDIO_MODE_IN_CALL) {
> + if (fp->datainterval < found->datainterval) {
> + found = fp;
> + cur_attr = attr;
> + }
> + } else {
> + if (fp->datainterval > found->datainterval) {
> + found = fp;
> + cur_attr = attr;
> + }
> + }
> +
> + return 0;
> +}
> +
> +/* Set interface function */
> +static struct snd_usb_audio_vendor_ops exynos_usb_audio_ops = {
> + /* card */
> + .connect = exynos_usb_audio_connect,
> + .disconnect = exynos_usb_audio_disconn,
> + /* clock */
> + .set_interface = exynos_usb_audio_set_interface,
> + /* pcm */
> + .set_rate = exynos_usb_audio_set_rate,
> + .set_pcm_buf = exynos_usb_audio_set_pcmbuf,
> + .set_pcm_intf = exynos_usb_audio_set_pcm_intf,
> + .set_pcm_connection = exynos_usb_audio_pcm_control,
> + .set_pcm_binterval = exynos_usb_audio_set_pcm_binterval,
> + .usb_add_ctls = exynos_usb_audio_add_control,
> +};
> +
> +int exynos_usb_audio_exit(void)
> +{
> + /* future use */
What needs to be done here?
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(exynos_usb_audio_exit);
Why did you export a function that does nothing?
> +
> +MODULE_AUTHOR("Jaehun Jung <jh0801.jung at samsung.com>");
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("Exynos USB Audio offloading driver");
> +
> diff --git a/sound/usb/exynos_usb_audio.h b/sound/usb/exynos_usb_audio.h
> new file mode 100644
> index 0000000..13707744
> --- /dev/null
> +++ b/sound/usb/exynos_usb_audio.h
> @@ -0,0 +1,150 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/* USB Audio Driver for Exynos
> + *
> + * Copyright (c) 2017 by Kyounghye Yun <k-hye.yun at samsung.com>
> + *
> + */
> +
> +#ifndef __LINUX_USB_EXYNOS_AUDIO_H
> +#define __LINUX_USB_EXYNOS_AUDIO_H
> +
> +#include "../../../sound/usb/usbaudio.h"
> +
> +/* for KM */
> +
> +#define USB_AUDIO_MEM_BASE 0xC0000000
> +
> +#define USB_AUDIO_SAVE_RESTORE (USB_AUDIO_MEM_BASE)
> +#define USB_AUDIO_DEV_CTX (USB_AUDIO_SAVE_RESTORE+PAGE_SIZE)
> +#define USB_AUDIO_INPUT_CTX (USB_AUDIO_DEV_CTX+PAGE_SIZE)
> +#define USB_AUDIO_OUT_DEQ (USB_AUDIO_INPUT_CTX+PAGE_SIZE)
> +#define USB_AUDIO_IN_DEQ (USB_AUDIO_OUT_DEQ+PAGE_SIZE)
> +#define USB_AUDIO_FBOUT_DEQ (USB_AUDIO_IN_DEQ+PAGE_SIZE)
> +#define USB_AUDIO_FBIN_DEQ (USB_AUDIO_FBOUT_DEQ+PAGE_SIZE)
> +#define USB_AUDIO_ERST (USB_AUDIO_FBIN_DEQ+PAGE_SIZE)
> +#define USB_AUDIO_DESC (USB_AUDIO_ERST+PAGE_SIZE)
> +#define USB_AUDIO_PCM_OUTBUF (USB_AUDIO_MEM_BASE+0x100000)
> +#define USB_AUDIO_PCM_INBUF (USB_AUDIO_MEM_BASE+0x800000)
> +
> +#if defined(CONFIG_SOC_S5E9815)
> +#define USB_AUDIO_XHCI_BASE 0x12210000
> +#define USB_URAM_BASE 0x122a0000
> +#define USB_URAM_SIZE (SZ_1K * 24)
> +#elif defined(CONFIG_SOC_S5E9935)
> +#define USB_AUDIO_XHCI_BASE 0x10B00000
> +#define USB_URAM_BASE 0x02a00000
> +#define USB_URAM_SIZE (SZ_1K * 24)
Shouldn't this information come from a DT file?
> +#else
> +#error
Error what?
> +#endif
> +
> +#define USB_AUDIO_CONNECT (1 << 0)
> +#define USB_AUDIO_REMOVING (1 << 1)
> +#define USB_AUDIO_DISCONNECT (1 << 2)
> +#define USB_AUDIO_TIMEOUT_PROBE (1 << 3)
BIT()?
> +
> +#define DISCONNECT_TIMEOUT (500)
> +
> +#define AUDIO_MODE_NORMAL 0
> +#define AUDIO_MODE_RINGTONE 1
> +#define AUDIO_MODE_IN_CALL 2
> +#define AUDIO_MODE_IN_COMMUNICATION 3
> +#define AUDIO_MODE_CALL_SCREEN 4
> +
> +#define CALL_INTERVAL_THRESHOLD 3
> +
> +#define USB_AUDIO_CONNECT (1 << 0)
> +#define USB_AUDIO_REMOVING (1 << 1)
> +#define USB_AUDIO_DISCONNECT (1 << 2)
> +#define USB_AUDIO_TIMEOUT_PROBE (1 << 3)
> +
> +#define DISCONNECT_TIMEOUT (500)
What units is this in?
> +
> +struct host_data {
> + dma_addr_t out_data_dma;
> + dma_addr_t in_data_dma;
> + void *out_data_addr;
> + void *in_data_addr;
Why void pointers? io pointers?
Again, does this code even work?
confused,
greg k-h
More information about the Alsa-devel
mailing list