From e636c8d336489bf3eed5878299e6cc045bbad077 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Tue, 20 Feb 2024 01:17:29 +0000
Subject: [PATCH] debug lk
---
kernel/sound/usb/pcm.c | 284 +++++++++++++++++++++++++++++++++-----------------------
1 files changed, 169 insertions(+), 115 deletions(-)
diff --git a/kernel/sound/usb/pcm.c b/kernel/sound/usb/pcm.c
index ae136dc..9e93a43 100644
--- a/kernel/sound/usb/pcm.c
+++ b/kernel/sound/usb/pcm.c
@@ -1,17 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/init.h>
@@ -26,6 +14,8 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
+#include <trace/hooks/sound.h>
+
#include "usbaudio.h"
#include "card.h"
#include "quirks.h"
@@ -35,6 +25,7 @@
#include "pcm.h"
#include "clock.h"
#include "power.h"
+#include "media.h"
#define SUBSTREAM_FLAG_DATA_EP_STARTED 0
#define SUBSTREAM_FLAG_SYNC_EP_STARTED 1
@@ -145,6 +136,8 @@
found = fp;
cur_attr = attr;
}
+
+ snd_vendor_set_pcm_binterval(fp, found, &cur_attr, &attr);
}
return found;
}
@@ -334,19 +327,28 @@
return 0;
}
-static void stop_endpoints(struct snd_usb_substream *subs, bool wait)
+static void sync_pending_stops(struct snd_usb_substream *subs)
{
- if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {
- snd_usb_endpoint_stop(subs->sync_endpoint);
- if (wait)
- snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint);
- }
+ snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint);
+ snd_usb_endpoint_sync_pending_stop(subs->data_endpoint);
+}
- if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) {
+static void stop_endpoints(struct snd_usb_substream *subs)
+{
+ if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags))
+ snd_usb_endpoint_stop(subs->sync_endpoint);
+
+ if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags))
snd_usb_endpoint_stop(subs->data_endpoint);
- if (wait)
- snd_usb_endpoint_sync_pending_stop(subs->data_endpoint);
- }
+}
+
+/* PCM sync_stop callback */
+static int snd_usb_pcm_sync_stop(struct snd_pcm_substream *substream)
+{
+ struct snd_usb_substream *subs = substream->runtime->private_data;
+
+ sync_pending_stops(subs);
+ return 0;
}
static int search_roland_implicit_fb(struct usb_device *dev, int ifnum,
@@ -425,6 +427,28 @@
ep = 0x81;
ifnum = 1;
goto add_sync_ep_from_ifnum;
+ case USB_ID(0x07fd, 0x0004): /* MOTU MicroBook II/IIc */
+ /* MicroBook IIc */
+ if (altsd->bInterfaceClass == USB_CLASS_AUDIO)
+ return 0;
+
+ /* MicroBook II */
+ ep = 0x84;
+ ifnum = 0;
+ goto add_sync_ep_from_ifnum;
+ case USB_ID(0x07fd, 0x0008): /* MOTU M Series */
+ case USB_ID(0x31e9, 0x0001): /* Solid State Logic SSL2 */
+ case USB_ID(0x31e9, 0x0002): /* Solid State Logic SSL2+ */
+ case USB_ID(0x0499, 0x172f): /* Steinberg UR22C */
+ case USB_ID(0x0d9a, 0x00df): /* RTX6001 */
+ ep = 0x81;
+ ifnum = 2;
+ goto add_sync_ep_from_ifnum;
+ case USB_ID(0x2b73, 0x000a): /* Pioneer DJ DJM-900NXS2 */
+ case USB_ID(0x2b73, 0x0017): /* Pioneer DJ DJM-250MK2 */
+ ep = 0x82;
+ ifnum = 0;
+ goto add_sync_ep_from_ifnum;
case USB_ID(0x0582, 0x01d8): /* BOSS Katana */
/* BOSS Katana amplifiers do not need quirks */
return 0;
@@ -458,6 +482,8 @@
SND_USB_ENDPOINT_TYPE_DATA);
if (!subs->sync_endpoint)
return -EINVAL;
+
+ subs->sync_endpoint->is_implicit_feedback = 1;
subs->data_endpoint->sync_master = subs->sync_endpoint;
@@ -557,11 +583,14 @@
implicit_fb ?
SND_USB_ENDPOINT_TYPE_DATA :
SND_USB_ENDPOINT_TYPE_SYNC);
+
if (!subs->sync_endpoint) {
if (is_playback && attr == USB_ENDPOINT_SYNC_NONE)
return 0;
return -EINVAL;
}
+
+ subs->sync_endpoint->is_implicit_feedback = implicit_fb;
subs->data_endpoint->sync_master = subs->sync_endpoint;
@@ -623,6 +652,10 @@
}
dev_dbg(&dev->dev, "setting usb interface %d:%d\n",
fmt->iface, fmt->altsetting);
+ err = snd_vendor_set_pcm_intf(iface, fmt->iface,
+ fmt->altsetting, subs->direction);
+ if (err)
+ return err;
snd_usb_set_interface_quirk(dev);
}
@@ -650,12 +683,8 @@
return 0;
}
-/**
- * snd_usb_enable_audio_stream - Enable/disable the specified usb substream.
- * @subs: pointer to the usb substream.
- * @datainterval: data packet interval.
- * @enable: if true, enable the usb substream. Else disable.
- */
+static int snd_usb_pcm_change_state(struct snd_usb_substream *subs, int state);
+
int snd_usb_enable_audio_stream(struct snd_usb_substream *subs,
int datainterval, bool enable)
{
@@ -663,9 +692,6 @@
struct usb_host_interface *alts;
struct usb_interface *iface;
int ret;
-
- if (!subs || !subs->stream)
- return -EINVAL;
if (!enable) {
if (subs->interface >= 0) {
@@ -680,12 +706,17 @@
}
snd_usb_autoresume(subs->stream->chip);
+
+ ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0);
+ if (ret < 0)
+ return ret;
+
if (datainterval != -EINVAL)
fmt = find_format_and_si(subs, datainterval);
else
fmt = find_format(subs);
if (!fmt) {
- dev_dbg(&subs->dev->dev,
+ dev_err(&subs->dev->dev,
"cannot set format: format = %#x, rate = %d, channels = %d\n",
subs->pcm_format, subs->cur_rate, subs->channels);
return -EINVAL;
@@ -693,19 +724,12 @@
subs->altset_idx = 0;
subs->interface = -1;
-
- if (!subs->stream->chip)
- return -EINVAL;
-
if (atomic_read(&subs->stream->chip->shutdown)) {
ret = -ENODEV;
} else {
ret = set_format(subs, fmt);
if (ret < 0)
return ret;
-
- if (!subs->cur_audiofmt)
- return -EINVAL;
iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface);
if (!iface) {
@@ -861,7 +885,8 @@
int ret;
/* format changed */
- stop_endpoints(subs, true);
+ stop_endpoints(subs);
+ sync_pending_stops(subs);
ret = snd_usb_endpoint_set_params(subs->data_endpoint,
subs->pcm_format,
subs->channels,
@@ -945,13 +970,8 @@
struct audioformat *fmt;
int ret;
- if (snd_usb_use_vmalloc)
- ret = snd_pcm_lib_alloc_vmalloc_buffer(substream,
- params_buffer_bytes(hw_params));
- else
- ret = snd_pcm_lib_malloc_pages(substream,
- params_buffer_bytes(hw_params));
- if (ret < 0)
+ ret = snd_media_start_pipeline(subs);
+ if (ret)
return ret;
subs->pcm_format = params_format(hw_params);
@@ -966,12 +986,13 @@
dev_dbg(&subs->dev->dev,
"cannot set format: format = %#x, rate = %d, channels = %d\n",
subs->pcm_format, subs->cur_rate, subs->channels);
- return -EINVAL;
+ ret = -EINVAL;
+ goto stop_pipeline;
}
ret = snd_usb_lock_shutdown(subs->stream->chip);
if (ret < 0)
- return ret;
+ goto stop_pipeline;
ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0);
if (ret < 0)
@@ -987,6 +1008,12 @@
unlock:
snd_usb_unlock_shutdown(subs->stream->chip);
+ if (ret < 0)
+ goto stop_pipeline;
+ return ret;
+
+ stop_pipeline:
+ snd_media_stop_pipeline(subs);
return ret;
}
@@ -999,20 +1026,19 @@
{
struct snd_usb_substream *subs = substream->runtime->private_data;
+ snd_media_stop_pipeline(subs);
subs->cur_audiofmt = NULL;
subs->cur_rate = 0;
subs->period_bytes = 0;
if (!snd_usb_lock_shutdown(subs->stream->chip)) {
- stop_endpoints(subs, true);
+ stop_endpoints(subs);
+ sync_pending_stops(subs);
snd_usb_endpoint_deactivate(subs->sync_endpoint);
snd_usb_endpoint_deactivate(subs->data_endpoint);
snd_usb_unlock_shutdown(subs->stream->chip);
}
- if (snd_usb_use_vmalloc)
- return snd_pcm_lib_free_vmalloc_buffer(substream);
- else
- return snd_pcm_lib_free_pages(substream);
+ return 0;
}
/*
@@ -1028,6 +1054,10 @@
struct usb_interface *iface;
int ret;
+ ret = snd_vendor_set_pcm_buf(subs->dev, subs->cur_audiofmt->iface);
+ if (ret)
+ return ret;
+
if (! subs->cur_audiofmt) {
dev_err(&subs->dev->dev, "no format is specified!\n");
return -ENXIO;
@@ -1040,9 +1070,6 @@
ret = -EIO;
goto unlock;
}
-
- snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint);
- snd_usb_endpoint_sync_pending_stop(subs->data_endpoint);
ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0);
if (ret < 0)
@@ -1063,6 +1090,17 @@
subs->cur_rate);
if (ret < 0)
goto unlock;
+
+ if (snd_vendor_get_ops()) {
+ ret = snd_vendor_set_rate(iface,
+ subs->cur_audiofmt->iface,
+ subs->cur_rate,
+ subs->cur_audiofmt->altsetting);
+ if (!ret) {
+ subs->need_setup_ep = false;
+ goto unlock;
+ }
+ }
ret = configure_endpoint(subs);
if (ret < 0)
@@ -1471,6 +1509,13 @@
struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_usb_substream *subs = &as->substream[direction];
+ int ret;
+ bool is_support = false;
+
+ ret = snd_vendor_set_pcm_connection(subs->dev, SOUND_PCM_OPEN,
+ direction);
+ if (ret)
+ return ret;
subs->interface = -1;
subs->altset_idx = 0;
@@ -1484,7 +1529,18 @@
subs->dsd_dop.channel = 0;
subs->dsd_dop.marker = 1;
- return setup_hw_info(runtime, subs);
+ ret = setup_hw_info(runtime, subs);
+ if (ret == 0) {
+ ret = snd_media_stream_init(subs, as->pcm, direction);
+ if (ret)
+ snd_usb_autosuspend(subs->stream->chip);
+ }
+
+ trace_android_vh_sound_usb_support_cpu_suspend(subs->dev, direction, &is_support);
+ if (!ret && is_support)
+ snd_usb_autosuspend(subs->stream->chip);
+
+ return ret;
}
static int snd_usb_pcm_close(struct snd_pcm_substream *substream)
@@ -1493,13 +1549,29 @@
struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
struct snd_usb_substream *subs = &as->substream[direction];
int ret;
+ bool is_support = false;
- stop_endpoints(subs, true);
+ ret = snd_vendor_set_pcm_connection(subs->dev, SOUND_PCM_CLOSE,
+ direction);
+ if (ret)
+ return ret;
+
+ trace_android_vh_sound_usb_support_cpu_suspend(subs->dev, direction, &is_support);
+ if (!ret && is_support)
+ snd_usb_autoresume(subs->stream->chip);
+
+ snd_media_stop_pipeline(subs);
if (!as->chip->keep_iface &&
subs->interface >= 0 &&
!snd_usb_lock_shutdown(subs->stream->chip)) {
usb_set_interface(subs->dev, subs->interface, 0);
+ ret = snd_vendor_set_pcm_intf(usb_ifnum_to_if(subs->dev,
+ subs->interface),
+ subs->interface, 0,
+ direction);
+ if (ret)
+ return ret;
subs->interface = -1;
ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D1);
snd_usb_unlock_shutdown(subs->stream->chip);
@@ -1541,6 +1613,12 @@
// continue;
}
bytes = urb->iso_frame_desc[i].actual_length;
+ if (subs->stream_offset_adj > 0) {
+ unsigned int adj = min(subs->stream_offset_adj, bytes);
+ cp += adj;
+ bytes -= adj;
+ subs->stream_offset_adj -= adj;
+ }
frames = bytes / stride;
if (!subs->txfr_quirk)
bytes = frames * stride;
@@ -1712,6 +1790,8 @@
for (i = 0; i < ctx->packets; i++) {
if (ctx->packet_size[i])
counts = ctx->packet_size[i];
+ else if (ep->sync_master)
+ counts = snd_usb_endpoint_slave_next_packet_size(ep);
else
counts = snd_usb_endpoint_next_packet_size(ep);
@@ -1815,8 +1895,8 @@
int processed = urb->transfer_buffer_length / ep->stride;
int est_delay;
- /* ignore the delay accounting when procssed=0 is given, i.e.
- * silent payloads are procssed before handling the actual data
+ /* ignore the delay accounting when processed=0 is given, i.e.
+ * silent payloads are processed before handling the actual data
*/
if (!processed)
return;
@@ -1862,22 +1942,15 @@
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
subs->trigger_tstamp_pending_update = true;
- /* fall through */
+ fallthrough;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
subs->data_endpoint->prepare_data_urb = prepare_playback_urb;
subs->data_endpoint->retire_data_urb = retire_playback_urb;
subs->running = 1;
return 0;
- case SNDRV_PCM_TRIGGER_SUSPEND:
- stop_endpoints(subs, true);
- subs->running = 0;
- if (subs->stream->chip->setup_fmt_after_resume_quirk)
- subs->need_setup_fmt = true;
- return 0;
case SNDRV_PCM_TRIGGER_STOP:
- stop_endpoints(subs, false);
+ stop_endpoints(subs);
subs->running = 0;
return 0;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -1886,6 +1959,13 @@
subs->data_endpoint->retire_data_urb = retire_playback_urb;
subs->running = 0;
return 0;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ if (subs->stream->chip->setup_fmt_after_resume_quirk) {
+ stop_endpoints(subs);
+ subs->need_setup_fmt = true;
+ return 0;
+ }
+ break;
}
return -EINVAL;
@@ -1899,7 +1979,6 @@
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
err = start_endpoints(subs);
if (err < 0)
return err;
@@ -1907,14 +1986,9 @@
subs->data_endpoint->retire_data_urb = retire_capture_urb;
subs->running = 1;
return 0;
- case SNDRV_PCM_TRIGGER_SUSPEND:
- stop_endpoints(subs, true);
- subs->running = 0;
- if (subs->stream->chip->setup_fmt_after_resume_quirk)
- subs->need_setup_fmt = true;
- return 0;
case SNDRV_PCM_TRIGGER_STOP:
- stop_endpoints(subs, false);
+ stop_endpoints(subs);
+ subs->data_endpoint->retire_data_urb = NULL;
subs->running = 0;
return 0;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -1925,6 +1999,13 @@
subs->data_endpoint->retire_data_urb = retire_capture_urb;
subs->running = 1;
return 0;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ if (subs->stream->chip->setup_fmt_after_resume_quirk) {
+ stop_endpoints(subs);
+ subs->need_setup_fmt = true;
+ return 0;
+ }
+ break;
}
return -EINVAL;
@@ -1933,61 +2014,31 @@
static const struct snd_pcm_ops snd_usb_playback_ops = {
.open = snd_usb_pcm_open,
.close = snd_usb_pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_usb_hw_params,
.hw_free = snd_usb_hw_free,
.prepare = snd_usb_pcm_prepare,
.trigger = snd_usb_substream_playback_trigger,
+ .sync_stop = snd_usb_pcm_sync_stop,
.pointer = snd_usb_pcm_pointer,
- .page = snd_pcm_lib_get_vmalloc_page,
};
static const struct snd_pcm_ops snd_usb_capture_ops = {
.open = snd_usb_pcm_open,
.close = snd_usb_pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_usb_hw_params,
.hw_free = snd_usb_hw_free,
.prepare = snd_usb_pcm_prepare,
.trigger = snd_usb_substream_capture_trigger,
+ .sync_stop = snd_usb_pcm_sync_stop,
.pointer = snd_usb_pcm_pointer,
- .page = snd_pcm_lib_get_vmalloc_page,
-};
-
-static const struct snd_pcm_ops snd_usb_playback_dev_ops = {
- .open = snd_usb_pcm_open,
- .close = snd_usb_pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_usb_hw_params,
- .hw_free = snd_usb_hw_free,
- .prepare = snd_usb_pcm_prepare,
- .trigger = snd_usb_substream_playback_trigger,
- .pointer = snd_usb_pcm_pointer,
- .page = snd_pcm_sgbuf_ops_page,
-};
-
-static const struct snd_pcm_ops snd_usb_capture_dev_ops = {
- .open = snd_usb_pcm_open,
- .close = snd_usb_pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_usb_hw_params,
- .hw_free = snd_usb_hw_free,
- .prepare = snd_usb_pcm_prepare,
- .trigger = snd_usb_substream_capture_trigger,
- .pointer = snd_usb_pcm_pointer,
- .page = snd_pcm_sgbuf_ops_page,
};
void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream)
{
const struct snd_pcm_ops *ops;
- if (snd_usb_use_vmalloc)
- ops = stream == SNDRV_PCM_STREAM_PLAYBACK ?
+ ops = stream == SNDRV_PCM_STREAM_PLAYBACK ?
&snd_usb_playback_ops : &snd_usb_capture_ops;
- else
- ops = stream == SNDRV_PCM_STREAM_PLAYBACK ?
- &snd_usb_playback_dev_ops : &snd_usb_capture_dev_ops;
snd_pcm_set_ops(pcm, stream, ops);
}
@@ -1997,7 +2048,10 @@
struct snd_pcm_substream *s = pcm->streams[subs->direction].substream;
struct device *dev = subs->dev->bus->sysdev;
- if (!snd_usb_use_vmalloc)
- snd_pcm_lib_preallocate_pages(s, SNDRV_DMA_TYPE_DEV_SG,
- dev, 64*1024, 512*1024);
+ if (snd_usb_use_vmalloc)
+ snd_pcm_set_managed_buffer(s, SNDRV_DMA_TYPE_VMALLOC,
+ NULL, 0, 0);
+ else
+ snd_pcm_set_managed_buffer(s, SNDRV_DMA_TYPE_DEV_SG,
+ dev, 64*1024, 512*1024);
}
--
Gitblit v1.6.2