Revert "ALSA: usb-audio: Split endpoint setups for hw_params and prepare (take#2)"

This reverts commit 56e28371fa which is
commit 2be79d5864 upstream.

It breaks the Android kernel abi and can be brought back in the future
in an abi-safe way if it is really needed.

Bug: 161946584
Change-Id: Ia50296da98428649613548dfe31c8dc9669da0d6
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2024-05-16 10:18:57 +00:00
parent fb3086b8e6
commit 7c2694fa40
3 changed files with 64 additions and 71 deletions

View File

@@ -42,7 +42,6 @@ struct snd_usb_clock_ref {
unsigned char clock;
atomic_t locked;
int rate;
bool need_setup;
struct list_head list;
};
@@ -768,8 +767,7 @@ bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip,
* The endpoint needs to be closed via snd_usb_endpoint_close() later.
*
* Note that this function doesn't configure the endpoint. The substream
* needs to set it up later via snd_usb_endpoint_set_params() and
* snd_usb_endpoint_prepare().
* needs to set it up later via snd_usb_endpoint_configure().
*/
struct snd_usb_endpoint *
snd_usb_endpoint_open(struct snd_usb_audio *chip,
@@ -1302,39 +1300,15 @@ out_of_memory:
return -ENOMEM;
}
/* update the rate of the referred clock; return the actual rate */
static int update_clock_ref_rate(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep)
{
struct snd_usb_clock_ref *clock = ep->clock_ref;
int rate = ep->cur_rate;
if (!clock || clock->rate == rate)
return rate;
if (clock->rate) {
if (atomic_read(&clock->locked))
return clock->rate;
if (clock->rate != rate) {
usb_audio_err(chip, "Mismatched sample rate %d vs %d for EP 0x%x\n",
clock->rate, rate, ep->ep_num);
return clock->rate;
}
}
clock->rate = rate;
clock->need_setup = true;
return rate;
}
/*
* snd_usb_endpoint_set_params: configure an snd_usb_endpoint
*
* It's called either from hw_params callback.
* Determine the number of URBs to be used on this endpoint.
* An endpoint must be configured before it can be started.
* An endpoint that is already running can not be reconfigured.
*/
int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep)
static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep)
{
const struct audioformat *fmt = ep->cur_audiofmt;
int err;
@@ -1386,46 +1360,49 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
ep->maxframesize = ep->maxpacksize / ep->cur_frame_bytes;
ep->curframesize = ep->curpacksize / ep->cur_frame_bytes;
return update_clock_ref_rate(chip, ep);
return 0;
}
static int init_sample_rate(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep)
{
struct snd_usb_clock_ref *clock = ep->clock_ref;
int rate, err;
int err;
rate = update_clock_ref_rate(chip, ep);
if (rate < 0)
return rate;
if (clock && !clock->need_setup)
return 0;
err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, rate);
if (err < 0) {
if (clock)
clock->rate = 0; /* reset rate */
return err;
if (clock) {
if (atomic_read(&clock->locked))
return 0;
if (clock->rate == ep->cur_rate)
return 0;
if (clock->rate && clock->rate != ep->cur_rate) {
usb_audio_dbg(chip, "Mismatched sample rate %d vs %d for EP 0x%x\n",
clock->rate, ep->cur_rate, ep->ep_num);
return -EINVAL;
}
}
err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, ep->cur_rate);
if (err < 0)
return err;
if (clock)
clock->need_setup = false;
clock->rate = ep->cur_rate;
return 0;
}
/*
* snd_usb_endpoint_prepare: Prepare the endpoint
* snd_usb_endpoint_configure: Configure the endpoint
*
* This function sets up the EP to be fully usable state.
* It's called either from prepare callback.
* It's called either from hw_params or prepare callback.
* The function checks need_setup flag, and performs nothing unless needed,
* so it's safe to call this multiple times.
*
* This returns zero if unchanged, 1 if the configuration has changed,
* or a negative error code.
*/
int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep)
int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep)
{
bool iface_first;
int err = 0;
@@ -1446,6 +1423,9 @@ int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
if (err < 0)
goto unlock;
}
err = snd_usb_endpoint_set_params(chip, ep);
if (err < 0)
goto unlock;
goto done;
}
@@ -1473,6 +1453,10 @@ int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
if (err < 0)
goto unlock;
err = snd_usb_endpoint_set_params(chip, ep);
if (err < 0)
goto unlock;
err = snd_usb_select_mode_quirk(chip, ep->cur_audiofmt);
if (err < 0)
goto unlock;

View File

@@ -17,10 +17,8 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
bool is_sync_ep);
void snd_usb_endpoint_close(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep);
int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep);
int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep);
int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep);
int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock);
bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip,

View File

@@ -442,6 +442,35 @@ static void close_endpoints(struct snd_usb_audio *chip,
}
}
static int configure_endpoints(struct snd_usb_audio *chip,
struct snd_usb_substream *subs)
{
int err;
if (subs->data_endpoint->need_setup) {
/* stop any running stream beforehand */
if (stop_endpoints(subs, false))
sync_pending_stops(subs);
if (subs->sync_endpoint) {
err = snd_usb_endpoint_configure(chip, subs->sync_endpoint);
if (err < 0)
return err;
}
err = snd_usb_endpoint_configure(chip, subs->data_endpoint);
if (err < 0)
return err;
snd_usb_set_format_quirk(subs, subs->cur_audiofmt);
} else {
if (subs->sync_endpoint) {
err = snd_usb_endpoint_configure(chip, subs->sync_endpoint);
if (err < 0)
return err;
}
}
return 0;
}
/*
* hw_params callback
*
@@ -533,16 +562,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
subs->cur_audiofmt = fmt;
mutex_unlock(&chip->mutex);
if (!subs->data_endpoint->need_setup)
goto unlock;
if (subs->sync_endpoint) {
ret = snd_usb_endpoint_set_params(chip, subs->sync_endpoint);
if (ret < 0)
goto unlock;
}
ret = snd_usb_endpoint_set_params(chip, subs->data_endpoint);
ret = configure_endpoints(chip, subs);
unlock:
if (ret < 0)
@@ -625,18 +645,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
goto unlock;
}
if (subs->sync_endpoint) {
ret = snd_usb_endpoint_prepare(chip, subs->sync_endpoint);
if (ret < 0)
goto unlock;
}
ret = snd_usb_endpoint_prepare(chip, subs->data_endpoint);
ret = configure_endpoints(chip, subs);
if (ret < 0)
goto unlock;
else if (ret > 0)
snd_usb_set_format_quirk(subs, subs->cur_audiofmt);
ret = 0;
/* reset the pointer */
subs->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size);