FAILED: patch "[PATCH] ALSA: aoa: i2sbus: clear stale prepared state" failed to apply to 6.12-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x 5ed060d5491597490fb53ec69da3edc4b1e8c165
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026050150-collie-pacific-386a@gregkh' --subject-prefix 'PATCH 6.12.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 5ed060d5491597490fb53ec69da3edc4b1e8c165 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= <[email protected]>
Date: Tue, 31 Mar 2026 18:14:04 -0300
Subject: [PATCH] ALSA: aoa: i2sbus: clear stale prepared state
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The i2sbus PCM code uses pi->active to constrain the sibling stream to an already prepared duplex format and rate in i2sbus_pcm_open().
That state is set from i2sbus_pcm_prepare(), but the current code only clears it on close. As a result, the sibling stream can inherit stale constraints after the prepared state has been torn down.
Clear pi->active when hw_params() or hw_free() tears down the prepared state, and set it again only after prepare succeeds.
Replace the stale FIXME in the duplex constraint comment with a description of the current driver behavior: i2sbus still programs a single shared transport configuration for both directions, so mixed formats are not supported in duplex mode.
sound/aoa/soundbus/i2sbus/pcm.c +44 -11
@@ -165,17 +165,16 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in)* currently in use (if any). */ hw->rate_min =5512 ; hw->rate_max =192000 ; -/* if the other stream is active, then we can only -* support what it is currently using. -* FIXME: I lied. This comment is wrong. We can support -* anything that works with the same serial format, ie. -* when recording 24 bit sound we can well play 16 bit -* sound at the same time iff using the same transfer mode. +/* If the other stream is already prepared, keep this stream +* on the same duplex format and rate. +* +* i2sbus_pcm_prepare() still programs one shared transport +* configuration for both directions, so mixed duplex formats +* are not supported here. */ if (other->active) { -/* FIXME: is this guaranteed by the alsa api? */ hw->formats &=pcm_format_to_bits (i2sdev->format); -/* see above, restrict rates to the one we already have */ +/* Restrict rates to the one already in use. */ hw->rate_min = i2sdev->rate; hw->rate_max = i2sdev->rate; }
@@ -283,6 +282,23 @@ void i2sbus_wait_for_stop_both(struct i2sbus_dev *i2sdev) }#endif +static void i2sbus_pcm_clear_active (struct i2sbus_dev *i2sdev,int in) +{ +struct pcm_info *pi; + +guard (mutex)(&i2sdev->lock); + +get_pcm_info (i2sdev, in, &pi,NULL ); + pi->active =0 ; +} + +static inline int i2sbus_hw_params (struct snd_pcm_substream *substream, +struct snd_pcm_hw_params *params,int in) +{ +i2sbus_pcm_clear_active (snd_pcm_substream_chip (substream), in); +return 0 ; +} +static inline int i2sbus_hw_free (struct snd_pcm_substream *substream,int in) {struct i2sbus_dev *i2sdev =snd_pcm_substream_chip (substream);
@@ -291,14 +307,27 @@ static inline int i2sbus_hw_free(struct snd_pcm_substream *substream, int in)get_pcm_info (i2sdev, in, &pi,NULL );if (pi->dbdma_ring.stopping)i2sbus_wait_for_stop (i2sdev, pi); +i2sbus_pcm_clear_active (i2sdev, in);return 0 ; } +static int i2sbus_playback_hw_params (struct snd_pcm_substream *substream, +struct snd_pcm_hw_params *params) +{ +return i2sbus_hw_params (substream, params,0 ); +} +static int i2sbus_playback_hw_free (struct snd_pcm_substream *substream) {return i2sbus_hw_free (substream,0 ); } +static int i2sbus_record_hw_params (struct snd_pcm_substream *substream, +struct snd_pcm_hw_params *params) +{ +return i2sbus_hw_params (substream, params,1 ); +} +static int i2sbus_record_hw_free (struct snd_pcm_substream *substream) {return i2sbus_hw_free (substream,1 );
@@ -335,7 +364,6 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)return -EINVAL ; runtime = pi->substream->runtime; - pi->active =1 ;if (other->active && ((i2sdev->format != runtime->format) || (i2sdev->rate != runtime->rate)))
@@ -444,9 +472,11 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)/* early exit if already programmed correctly */ /* not locking these is fine since we touch them only in this function */ -if (in_le32 (&i2sdev->intfregs->serial_format) == sfr - &&in_le32 (&i2sdev->intfregs->data_word_sizes) == dws) +if (in_le32 (&i2sdev->intfregs->serial_format) == sfr && +in_le32 (&i2sdev->intfregs->data_word_sizes) == dws) { + pi->active =1 ;return 0 ; + }/* let's notify the codecs about clocks going away. * For now we only do mastering on the i2s cell... */
@@ -484,6 +514,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)if (cii->codec->switch_clock) cii->codec->switch_clock (cii,CLOCK_SWITCH_SLAVE ); + pi->active =1 ;return 0 ; }
@@ -728,6 +759,7 @@ static snd_pcm_uframes_t i2sbus_playback_pointer(struct snd_pcm_substreamstatic const struct snd_pcm_ops i2sbus_playback_ops = { .open = i2sbus_playback_open, .close = i2sbus_playback_close, + .hw_params = i2sbus_playback_hw_params, .hw_free = i2sbus_playback_hw_free, .prepare = i2sbus_playback_prepare, .trigger = i2sbus_playback_trigger,
@@ -796,6 +828,7 @@ static snd_pcm_uframes_t i2sbus_record_pointer(struct snd_pcm_substreamstatic const struct snd_pcm_ops i2sbus_record_ops = { .open = i2sbus_record_open, .close = i2sbus_record_close, + .hw_params = i2sbus_record_hw_params, .hw_free = i2sbus_record_hw_free, .prepare = i2sbus_record_prepare, .trigger = i2sbus_record_trigger,
Sasha Levin
maintainerPATCH 1/2 ALSA: aoa: Use guard() for mutex locks
From: Takashi Iwai <[email protected]>
[ Upstream commit 1cb6ecbb372002ef9e531c5377e5f60122411e40 ]
Replace the manual mutex lock/unlock pairs with guard() for code simplification.
Only code refactoring, and no behavior change.
Stable-dep-of: 5ed060d54915 ("ALSA: aoa: i2sbus: clear stale prepared state")
--- sound/aoa/codecs/onyx.c | 104 +++++++++-------------------- sound/aoa/codecs/tas.c | 113 +++++++++++--------------------- sound/aoa/core/gpio-feature.c | 20 ++---- sound/aoa/core/gpio-pmf.c | 26 +++----- sound/aoa/soundbus/i2sbus/pcm.c | 76 +++++++-------------- 5 files changed, 112 insertions(+), 227 deletions(-)
sound/aoa/codecs/onyx.c +32 -72
@@ -122,10 +122,9 @@ static int onyx_snd_vol_get(struct snd_kcontrol *kcontrol,struct onyx *onyx =snd_kcontrol_chip (kcontrol);s8 l, r; -mutex_lock (&onyx->mutex); +guard (mutex)(&onyx->mutex);onyx_read_register (onyx,ONYX_REG_DAC_ATTEN_LEFT , &l);onyx_read_register (onyx,ONYX_REG_DAC_ATTEN_RIGHT , &r); -mutex_unlock (&onyx->mutex); ucontrol->value.integer.value[0 ] = l +VOLUME_RANGE_SHIFT ; ucontrol->value.integer.value[1 ] = r +VOLUME_RANGE_SHIFT ;
@@ -146,15 +145,13 @@ static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[1] > -1 + VOLUME_RANGE_SHIFT)return -EINVAL ; -mutex_lock (&onyx->mutex); +guard (mutex)(&onyx->mutex);onyx_read_register (onyx,ONYX_REG_DAC_ATTEN_LEFT , &l);onyx_read_register (onyx,ONYX_REG_DAC_ATTEN_RIGHT , &r);if (l +VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[0 ] && - r +VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1 ]) { -mutex_unlock (&onyx->mutex); + r +VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1 ])return 0 ; - }onyx_write_register (onyx,ONYX_REG_DAC_ATTEN_LEFT , ucontrol->value.integer.value[0]
@@ -162,7 +159,6 @@ static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol,onyx_write_register (onyx,ONYX_REG_DAC_ATTEN_RIGHT , ucontrol->value.integer.value[1 ] -VOLUME_RANGE_SHIFT ); -mutex_unlock (&onyx->mutex);return 1 ; }
@@ -198,9 +194,8 @@ static int onyx_snd_inputgain_get(struct snd_kcontrol *kcontrol,struct onyx *onyx =snd_kcontrol_chip (kcontrol);u8 ig; -mutex_lock (&onyx->mutex); +guard (mutex)(&onyx->mutex);onyx_read_register (onyx,ONYX_REG_ADC_CONTROL , &ig); -mutex_unlock (&onyx->mutex); ucontrol->value.integer.value[0 ] = (ig &ONYX_ADC_PGA_GAIN_MASK ) +INPUTGAIN_RANGE_SHIFT ;
@@ -217,14 +212,13 @@ static int onyx_snd_inputgain_put(struct snd_kcontrol *kcontrol,if (ucontrol->value.integer.value[0 ] <3 +INPUTGAIN_RANGE_SHIFT || ucontrol->value.integer.value[0 ] >28 +INPUTGAIN_RANGE_SHIFT )return -EINVAL ; -mutex_lock (&onyx->mutex); +guard (mutex)(&onyx->mutex);onyx_read_register (onyx,ONYX_REG_ADC_CONTROL , &v); n = v; n &= ~ONYX_ADC_PGA_GAIN_MASK ; n |= (ucontrol->value.integer.value[0 ] -INPUTGAIN_RANGE_SHIFT ) &ONYX_ADC_PGA_GAIN_MASK ;onyx_write_register (onyx,ONYX_REG_ADC_CONTROL , n); -mutex_unlock (&onyx->mutex);return n != v; }
@@ -252,9 +246,8 @@ static int onyx_snd_capture_source_get(struct snd_kcontrol *kcontrol,struct onyx *onyx =snd_kcontrol_chip (kcontrol);s8 v; -mutex_lock (&onyx->mutex); +guard (mutex)(&onyx->mutex);onyx_read_register (onyx,ONYX_REG_ADC_CONTROL , &v); -mutex_unlock (&onyx->mutex); ucontrol->value.enumerated.item[0 ] = !!(v&ONYX_ADC_INPUT_MIC );
@@ -265,13 +258,12 @@ static void onyx_set_capture_source(struct onyx *onyx, int mic) {s8 v; -mutex_lock (&onyx->mutex); +guard (mutex)(&onyx->mutex);onyx_read_register (onyx,ONYX_REG_ADC_CONTROL , &v); v &= ~ONYX_ADC_INPUT_MIC ;if (mic) v |=ONYX_ADC_INPUT_MIC ;onyx_write_register (onyx,ONYX_REG_ADC_CONTROL , v); -mutex_unlock (&onyx->mutex); } static int onyx_snd_capture_source_put(struct snd_kcontrol *kcontrol,
@@ -312,9 +304,8 @@ static int onyx_snd_mute_get(struct snd_kcontrol *kcontrol,struct onyx *onyx =snd_kcontrol_chip (kcontrol);u8 c; -mutex_lock (&onyx->mutex); +guard (mutex)(&onyx->mutex);onyx_read_register (onyx,ONYX_REG_DAC_CONTROL , &c); -mutex_unlock (&onyx->mutex); ucontrol->value.integer.value[0 ] = !(c &ONYX_MUTE_LEFT ); ucontrol->value.integer.value[1 ] = !(c &ONYX_MUTE_RIGHT );
@@ -329,9 +320,9 @@ static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol,u8 v =0 , c =0 ;int err = -EBUSY ; -mutex_lock (&onyx->mutex); +guard (mutex)(&onyx->mutex);if (onyx->analog_locked) - goto out_unlock; +return -EBUSY ;onyx_read_register (onyx,ONYX_REG_DAC_CONTROL , &v); c = v;
@@ -342,9 +333,6 @@ static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol, c |=ONYX_MUTE_RIGHT ; err =onyx_write_register (onyx,ONYX_REG_DAC_CONTROL , c); - out_unlock: -mutex_unlock (&onyx->mutex); -return !err ? (v != c) : err; }
@@ -373,9 +361,8 @@ static int onyx_snd_single_bit_get(struct snd_kcontrol *kcontrol,u8 address = (pv >>8 ) &0xff ;u8 mask = pv &0xff ; -mutex_lock (&onyx->mutex); +guard (mutex)(&onyx->mutex);onyx_read_register (onyx, address, &c); -mutex_unlock (&onyx->mutex); ucontrol->value.integer.value[0 ] = !!(c & mask) ^ polarity;
@@ -394,11 +381,10 @@ static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol,u8 address = (pv >>8 ) &0xff ;u8 mask = pv &0xff ; -mutex_lock (&onyx->mutex); +guard (mutex)(&onyx->mutex);if (spdiflock && onyx->spdif_locked) {/* even if alsamixer doesn't care.. */ - err = -EBUSY ; - goto out_unlock; +return -EBUSY ; }onyx_read_register (onyx, address, &v); c = v;
@@ -407,9 +393,6 @@ static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol, c |= mask; err =onyx_write_register (onyx, address, c); - out_unlock: -mutex_unlock (&onyx->mutex); -return !err ? (v != c) : err; }
@@ -490,7 +473,7 @@ static int onyx_spdif_get(struct snd_kcontrol *kcontrol,struct onyx *onyx =snd_kcontrol_chip (kcontrol);u8 v; -mutex_lock (&onyx->mutex); +guard (mutex)(&onyx->mutex);onyx_read_register (onyx,ONYX_REG_DIG_INFO1 , &v); ucontrol->value.iec958.status[0 ] = v &0x3e ;
@@ -502,7 +485,6 @@ static int onyx_spdif_get(struct snd_kcontrol *kcontrol,onyx_read_register (onyx,ONYX_REG_DIG_INFO4 , &v); ucontrol->value.iec958.status[4 ] = v &0x0f ; -mutex_unlock (&onyx->mutex);return 0 ; }
@@ -513,7 +495,7 @@ static int onyx_spdif_put(struct snd_kcontrol *kcontrol,struct onyx *onyx =snd_kcontrol_chip (kcontrol);u8 v; -mutex_lock (&onyx->mutex); +guard (mutex)(&onyx->mutex);onyx_read_register (onyx,ONYX_REG_DIG_INFO1 , &v); v = (v & ~0x3e ) | (ucontrol->value.iec958.status[0 ] &0x3e );onyx_write_register (onyx,ONYX_REG_DIG_INFO1 , v);
@@ -528,7 +510,6 @@ static int onyx_spdif_put(struct snd_kcontrol *kcontrol,onyx_read_register (onyx,ONYX_REG_DIG_INFO4 , &v); v = (v & ~0x0f ) | (ucontrol->value.iec958.status[4 ] &0x0f );onyx_write_register (onyx,ONYX_REG_DIG_INFO4 , v); -mutex_unlock (&onyx->mutex);return 1 ; }
@@ -673,14 +654,13 @@ static int onyx_usable(struct codec_info_item *cii,struct onyx *onyx = cii->codec_data;int spdif_enabled, analog_enabled; -mutex_lock (&onyx->mutex); +guard (mutex)(&onyx->mutex);onyx_read_register (onyx,ONYX_REG_DIG_INFO4 , &v); spdif_enabled = !!(v &ONYX_SPDIF_ENABLE );onyx_read_register (onyx,ONYX_REG_DAC_CONTROL , &v); analog_enabled = (v & (ONYX_MUTE_RIGHT |ONYX_MUTE_LEFT )) != (ONYX_MUTE_RIGHT |ONYX_MUTE_LEFT ); -mutex_unlock (&onyx->mutex);switch (ti->tag) {case 0 :return 1 ;
@@ -696,9 +676,8 @@ static int onyx_prepare(struct codec_info_item *cii, {u8 v;struct onyx *onyx = cii->codec_data; -int err = -EBUSY ; -mutex_lock (&onyx->mutex); +guard (mutex)(&onyx->mutex);#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE if (substream->runtime->format ==SNDRV_PCM_FMTBIT_COMPRESSED_16BE ) {
@@ -707,10 +686,9 @@ static int onyx_prepare(struct codec_info_item *cii,if (onyx_write_register (onyx,ONYX_REG_DAC_CONTROL , v |ONYX_MUTE_RIGHT |ONYX_MUTE_LEFT )) - goto out_unlock; +return -EBUSY ; onyx->analog_locked =1 ; - err =0 ; - goto out_unlock; + return 0; }#endif switch (substream->runtime->rate) {
@@ -720,8 +698,7 @@ static int onyx_prepare(struct codec_info_item *cii,/* these rates are ok for all outputs */ /* FIXME: program spdif channel control bits here so that * userspace doesn't have to if it only plays pcm! */ - err =0 ; - goto out_unlock; +return 0 ;default :/* got some rate that the digital output can't do, * so disable and lock it */
@@ -729,16 +706,12 @@ static int onyx_prepare(struct codec_info_item *cii,if (onyx_write_register (onyx,ONYX_REG_DIG_INFO4 , v & ~ONYX_SPDIF_ENABLE )) - goto out_unlock; +return -EBUSY ; onyx->spdif_locked =1 ; - err =0 ; - goto out_unlock; +return 0 ; } - out_unlock: -mutex_unlock (&onyx->mutex); - -return err; +return -EBUSY ; } static int onyx_open(struct codec_info_item *cii,
@@ -746,9 +719,8 @@ static int onyx_open(struct codec_info_item *cii, {struct onyx *onyx = cii->codec_data; -mutex_lock (&onyx->mutex); +guard (mutex)(&onyx->mutex); onyx->open_count++; -mutex_unlock (&onyx->mutex);return 0 ; }
@@ -758,11 +730,10 @@ static int onyx_close(struct codec_info_item *cii, {struct onyx *onyx = cii->codec_data; -mutex_lock (&onyx->mutex); +guard (mutex)(&onyx->mutex); onyx->open_count--;if (!onyx->open_count) onyx->spdif_locked = onyx->analog_locked =0 ; -mutex_unlock (&onyx->mutex);return 0 ; }
@@ -772,7 +743,7 @@ static int onyx_switch_clock(struct codec_info_item *cii, {struct onyx *onyx = cii->codec_data; -mutex_lock (&onyx->mutex); +guard (mutex)(&onyx->mutex);/* this *MUST* be more elaborate later... */ switch (what) {case CLOCK_SWITCH_PREPARE_SLAVE :
@@ -784,7 +755,6 @@ static int onyx_switch_clock(struct codec_info_item *cii,default :/* silence warning */ break ; } -mutex_unlock (&onyx->mutex);return 0 ; }
@@ -795,27 +765,21 @@ static int onyx_suspend(struct codec_info_item *cii, pm_message_t state) {struct onyx *onyx = cii->codec_data;u8 v; -int err = -ENXIO ; -mutex_lock (&onyx->mutex); +guard (mutex)(&onyx->mutex);if (onyx_read_register (onyx,ONYX_REG_CONTROL , &v)) - goto out_unlock; +return -ENXIO ;onyx_write_register (onyx,ONYX_REG_CONTROL , v |ONYX_ADPSV |ONYX_DAPSV );/* Apple does a sleep here but the datasheet says to do it on resume */ - err =0 ; - out_unlock: -mutex_unlock (&onyx->mutex); - -return err; +return 0 ; }static int onyx_resume (struct codec_info_item *cii) {struct onyx *onyx = cii->codec_data;u8 v; -int err = -ENXIO ; -mutex_lock (&onyx->mutex); +guard (mutex)(&onyx->mutex);/* reset codec */ onyx->codec.gpio->methods->set_hw_reset (onyx->codec.gpio,0 );
@@ -827,17 +791,13 @@ static int onyx_resume(struct codec_info_item *cii)/* take codec out of suspend (if it still is after reset) */ if (onyx_read_register (onyx,ONYX_REG_CONTROL , &v)) - goto out_unlock; +return -ENXIO ;onyx_write_register (onyx,ONYX_REG_CONTROL , v & ~(ONYX_ADPSV |ONYX_DAPSV ));/* FIXME: should divide by sample rate, but 8k is the lowest we go */ msleep (2205000 /8000 );/* reset all values */ onyx_register_init (onyx); - err =0 ; - out_unlock: -mutex_unlock (&onyx->mutex); - - return err; + return 0; }#endif /* CONFIG_PM */
sound/aoa/codecs/tas.c +39 -74
303 lines not on this page · raw message
sound/aoa/core/gpio-feature.c +7 -13
@@ -212,10 +212,9 @@ static void ftr_handle_notify(struct work_struct *work)struct gpio_notification *notif = container_of(work, struct gpio_notification, work.work); -mutex_lock (¬if->mutex); +guard (mutex)(¬if->mutex);if (notif->notify) notif->notify (notif->data); -mutex_unlock (¬if->mutex); }static void gpio_enable_dual_edge (int gpio)
@@ -341,19 +340,17 @@ static int ftr_set_notify(struct gpio_runtime *rt,if (!irq)return -ENODEV ; -mutex_lock (¬if->mutex); +guard (mutex)(¬if->mutex); old = notif->notify; -if (!old && !notify) { - err =0 ; - goto out_unlock; - } +if (!old && !notify) +return 0 ;if (old && notify) {if (old == notify && notif->data == data) err =0 ; - goto out_unlock; +return err; }if (old && !notify)
@@ -362,16 +359,13 @@ static int ftr_set_notify(struct gpio_runtime *rt,if (!old && notify) { err =request_irq (irq, ftr_handle_notify_irq,0 , name, notif);if (err) - goto out_unlock; +return err; } notif->notify = notify; notif->data = data; - err =0 ; - out_unlock: -mutex_unlock (¬if->mutex); -return err; +return 0 ; } static int ftr_get_detect(struct gpio_runtime *rt,
sound/aoa/core/gpio-pmf.c +9 -17
@@ -74,10 +74,9 @@ static void pmf_handle_notify(struct work_struct *work)struct gpio_notification *notif = container_of(work, struct gpio_notification, work.work); -mutex_lock (¬if->mutex); +guard (mutex)(¬if->mutex);if (notif->notify) notif->notify (notif->data); -mutex_unlock (¬if->mutex); }static void pmf_gpio_init (struct gpio_runtime *rt)
@@ -154,19 +153,17 @@ static int pmf_set_notify(struct gpio_runtime *rt,return -EINVAL ; } -mutex_lock (¬if->mutex); +guard (mutex)(¬if->mutex); old = notif->notify; -if (!old && !notify) { - err =0 ; - goto out_unlock; - } +if (!old && !notify) +return 0 ;if (old && notify) {if (old == notify && notif->data == data) err =0 ; - goto out_unlock; +return err; }if (old && !notify) {
@@ -178,10 +175,8 @@ static int pmf_set_notify(struct gpio_runtime *rt,if (!old && notify) { irq_client =kzalloc (sizeof (struct pmf_irq_client ),GFP_KERNEL ); -if (!irq_client) { - err = -ENOMEM ; - goto out_unlock; - } +if (!irq_client) +return -ENOMEM ; irq_client->data = notif; irq_client->handler = pmf_handle_notify_irq; irq_client->owner =THIS_MODULE ;
@@ -192,17 +187,14 @@ static int pmf_set_notify(struct gpio_runtime *rt,printk (KERN_ERR "snd-aoa: gpio layer failed to" " register %s irq (%d)\n" , name, err);kfree (irq_client); - goto out_unlock; +return err; } notif->gpio_private = irq_client; } notif->notify = notify; notif->data = data; - err =0 ; - out_unlock: -mutex_unlock (¬if->mutex); -return err; +return 0 ; } static int pmf_get_detect(struct gpio_runtime *rt,
sound/aoa/soundbus/i2sbus/pcm.c +25 -51
184 lines not on this page · raw message
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 ALSA: aoa: i2sbus: clear stale prepared state
From: Cássio Gabriel <[email protected]>
[ Upstream commit 5ed060d5491597490fb53ec69da3edc4b1e8c165 ]
The i2sbus PCM code uses pi->active to constrain the sibling stream to an already prepared duplex format and rate in i2sbus_pcm_open().
That state is set from i2sbus_pcm_prepare(), but the current code only clears it on close. As a result, the sibling stream can inherit stale constraints after the prepared state has been torn down.
Clear pi->active when hw_params() or hw_free() tears down the prepared state, and set it again only after prepare succeeds.
Replace the stale FIXME in the duplex constraint comment with a description of the current driver behavior: i2sbus still programs a single shared transport configuration for both directions, so mixed formats are not supported in duplex mode.
--- sound/aoa/soundbus/i2sbus/pcm.c | 55 ++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 11 deletions(-)
sound/aoa/soundbus/i2sbus/pcm.c +44 -11
@@ -165,17 +165,16 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in)* currently in use (if any). */ hw->rate_min =5512 ; hw->rate_max =192000 ; -/* if the other stream is active, then we can only -* support what it is currently using. -* FIXME: I lied. This comment is wrong. We can support -* anything that works with the same serial format, ie. -* when recording 24 bit sound we can well play 16 bit -* sound at the same time iff using the same transfer mode. +/* If the other stream is already prepared, keep this stream +* on the same duplex format and rate. +* +* i2sbus_pcm_prepare() still programs one shared transport +* configuration for both directions, so mixed duplex formats +* are not supported here. */ if (other->active) { -/* FIXME: is this guaranteed by the alsa api? */ hw->formats &=pcm_format_to_bits (i2sdev->format); -/* see above, restrict rates to the one we already have */ +/* Restrict rates to the one already in use. */ hw->rate_min = i2sdev->rate; hw->rate_max = i2sdev->rate; }
@@ -283,6 +282,23 @@ void i2sbus_wait_for_stop_both(struct i2sbus_dev *i2sdev) }#endif +static void i2sbus_pcm_clear_active (struct i2sbus_dev *i2sdev,int in) +{ +struct pcm_info *pi; + +guard (mutex)(&i2sdev->lock); + +get_pcm_info (i2sdev, in, &pi,NULL ); + pi->active =0 ; +} + +static inline int i2sbus_hw_params (struct snd_pcm_substream *substream, +struct snd_pcm_hw_params *params,int in) +{ +i2sbus_pcm_clear_active (snd_pcm_substream_chip (substream), in); +return 0 ; +} +static inline int i2sbus_hw_free (struct snd_pcm_substream *substream,int in) {struct i2sbus_dev *i2sdev =snd_pcm_substream_chip (substream);
@@ -291,14 +307,27 @@ static inline int i2sbus_hw_free(struct snd_pcm_substream *substream, int in)get_pcm_info (i2sdev, in, &pi,NULL );if (pi->dbdma_ring.stopping)i2sbus_wait_for_stop (i2sdev, pi); +i2sbus_pcm_clear_active (i2sdev, in);return 0 ; } +static int i2sbus_playback_hw_params (struct snd_pcm_substream *substream, +struct snd_pcm_hw_params *params) +{ +return i2sbus_hw_params (substream, params,0 ); +} +static int i2sbus_playback_hw_free (struct snd_pcm_substream *substream) {return i2sbus_hw_free (substream,0 ); } +static int i2sbus_record_hw_params (struct snd_pcm_substream *substream, +struct snd_pcm_hw_params *params) +{ +return i2sbus_hw_params (substream, params,1 ); +} +static int i2sbus_record_hw_free (struct snd_pcm_substream *substream) {return i2sbus_hw_free (substream,1 );
@@ -335,7 +364,6 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)return -EINVAL ; runtime = pi->substream->runtime; - pi->active =1 ;if (other->active && ((i2sdev->format != runtime->format) || (i2sdev->rate != runtime->rate)))
@@ -450,9 +478,11 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)/* early exit if already programmed correctly */ /* not locking these is fine since we touch them only in this function */ -if (in_le32 (&i2sdev->intfregs->serial_format) == sfr - &&in_le32 (&i2sdev->intfregs->data_word_sizes) == dws) +if (in_le32 (&i2sdev->intfregs->serial_format) == sfr && +in_le32 (&i2sdev->intfregs->data_word_sizes) == dws) { + pi->active =1 ;return 0 ; + }/* let's notify the codecs about clocks going away. * For now we only do mastering on the i2s cell... */
@@ -490,6 +520,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)if (cii->codec->switch_clock) cii->codec->switch_clock (cii,CLOCK_SWITCH_SLAVE ); + pi->active =1 ;return 0 ; }
@@ -746,6 +777,7 @@ static snd_pcm_uframes_t i2sbus_playback_pointer(struct snd_pcm_substreamstatic const struct snd_pcm_ops i2sbus_playback_ops = { .open = i2sbus_playback_open, .close = i2sbus_playback_close, + .hw_params = i2sbus_playback_hw_params, .hw_free = i2sbus_playback_hw_free, .prepare = i2sbus_playback_prepare, .trigger = i2sbus_playback_trigger,
@@ -814,6 +846,7 @@ static snd_pcm_uframes_t i2sbus_record_pointer(struct snd_pcm_substreamstatic const struct snd_pcm_ops i2sbus_record_ops = { .open = i2sbus_record_open, .close = i2sbus_record_close, + .hw_params = i2sbus_record_hw_params, .hw_free = i2sbus_record_hw_free, .prepare = i2sbus_record_prepare, .trigger = i2sbus_record_trigger,
Signature · 1 line
2.53.0