2019-05-19 13:08:55 +01:00
// SPDX-License-Identifier: GPL-2.0-only
2015-02-17 15:25:37 +01:00
/*
* HD - audio codec driver binding
* Copyright ( c ) Takashi Iwai < tiwai @ suse . de >
*/
# include <linux/init.h>
# include <linux/slab.h>
# include <linux/mutex.h>
# include <linux/module.h>
# include <linux/export.h>
2015-02-18 15:39:59 +01:00
# include <linux/pm.h>
2015-03-05 17:21:32 +01:00
# include <linux/pm_runtime.h>
2015-02-17 15:25:37 +01:00
# include <sound/core.h>
2018-08-22 15:24:57 -05:00
# include <sound/hda_codec.h>
2015-02-17 15:25:37 +01:00
# include "hda_local.h"
2021-11-17 14:30:40 +01:00
# include "hda_jack.h"
2015-02-17 15:25:37 +01:00
/*
2015-10-01 16:20:04 +02:00
* find a matching codec id
2015-02-17 15:25:37 +01:00
*/
2015-02-17 21:46:37 +01:00
static int hda_codec_match ( struct hdac_device * dev , struct hdac_driver * drv )
2015-02-17 15:25:37 +01:00
{
2015-02-17 21:46:37 +01:00
struct hda_codec * codec = container_of ( dev , struct hda_codec , core ) ;
2015-02-17 15:25:37 +01:00
struct hda_codec_driver * driver =
2015-02-17 21:46:37 +01:00
container_of ( drv , struct hda_codec_driver , core ) ;
2015-10-01 16:20:04 +02:00
const struct hda_device_id * list ;
2015-02-17 15:25:37 +01:00
/* check probe_id instead of vendor_id if set */
2015-03-03 10:07:24 +01:00
u32 id = codec - > probe_id ? codec - > probe_id : codec - > core . vendor_id ;
2015-10-01 16:20:04 +02:00
u32 rev_id = codec - > core . revision_id ;
2015-02-17 15:25:37 +01:00
2015-10-01 16:20:04 +02:00
for ( list = driver - > id ; list - > vendor_id ; list + + ) {
if ( list - > vendor_id = = id & &
( ! list - > rev_id | | list - > rev_id = = rev_id ) ) {
codec - > preset = list ;
2015-02-17 15:25:37 +01:00
return 1 ;
}
}
return 0 ;
}
2015-03-02 23:22:59 +01:00
/* process an unsolicited event */
static void hda_codec_unsol_event ( struct hdac_device * dev , unsigned int ev )
{
struct hda_codec * codec = container_of ( dev , struct hda_codec , core ) ;
2019-10-28 11:58:03 +01:00
/* ignore unsol events during shutdown */
if ( codec - > bus - > shutdown )
return ;
2021-03-10 12:28:08 +01:00
/* ignore unsol events during system suspend/resume */
if ( codec - > core . dev . power . power_state . event ! = PM_EVENT_ON )
return ;
2015-03-02 23:22:59 +01:00
if ( codec - > patch_ops . unsol_event )
codec - > patch_ops . unsol_event ( codec , ev ) ;
}
2015-10-01 17:59:43 +02:00
/**
* snd_hda_codec_set_name - set the codec name
* @ codec : the HDA codec
* @ name : name string to set
*/
int snd_hda_codec_set_name ( struct hda_codec * codec , const char * name )
2015-02-17 15:25:37 +01:00
{
2015-10-01 17:59:43 +02:00
int err ;
if ( ! name )
return 0 ;
err = snd_hdac_device_set_chip_name ( & codec - > core , name ) ;
if ( err < 0 )
return err ;
/* update the mixer name */
2015-10-15 14:06:14 +02:00
if ( ! * codec - > card - > mixername | |
2015-10-17 18:25:38 +02:00
codec - > bus - > mixer_assigned > = codec - > core . addr ) {
2015-10-01 17:59:43 +02:00
snprintf ( codec - > card - > mixername ,
sizeof ( codec - > card - > mixername ) , " %s %s " ,
codec - > core . vendor_name , codec - > core . chip_name ) ;
2015-10-17 18:25:38 +02:00
codec - > bus - > mixer_assigned = codec - > core . addr ;
2015-02-17 15:25:37 +01:00
}
2015-10-01 17:59:43 +02:00
return 0 ;
2015-02-17 15:25:37 +01:00
}
2015-10-01 17:59:43 +02:00
EXPORT_SYMBOL_GPL ( snd_hda_codec_set_name ) ;
2015-02-17 15:25:37 +01:00
static int hda_codec_driver_probe ( struct device * dev )
{
struct hda_codec * codec = dev_to_hda_codec ( dev ) ;
struct module * owner = dev - > driver - > owner ;
2015-10-01 16:20:04 +02:00
hda_codec_patch_t patch ;
2015-02-17 15:25:37 +01:00
int err ;
2018-08-22 15:25:03 -05:00
if ( codec - > bus - > core . ext_ops ) {
if ( WARN_ON ( ! codec - > bus - > core . ext_ops - > hdev_attach ) )
return - EINVAL ;
return codec - > bus - > core . ext_ops - > hdev_attach ( & codec - > core ) ;
}
2015-02-17 15:25:37 +01:00
if ( WARN_ON ( ! codec - > preset ) )
return - EINVAL ;
2015-10-01 17:59:43 +02:00
err = snd_hda_codec_set_name ( codec , codec - > preset - > name ) ;
ALSA: hda - Add regmap support
This patch adds an infrastructure to support regmap-based verb
accesses. Because o the asymmetric nature of HD-audio verbs,
especially the amp verbs, we need to translate the verbs as a sort of
pseudo registers to be mapped uniquely in regmap.
In this patch, a pseudo register is built from the NID, the
AC_VERB_GET_* and 8bit parameters, i.e. almost in the form to be sent
to HD-audio bus but without codec address field. OTOH, for writing,
the same pseudo register is translated to AC_VERB_SET_* automatically.
The AC_VERB_SET_AMP_* verb is re-encoded from the corresponding
AC_VERB_GET_AMP_* verb and parameter at writing.
Some verbs has a single command for read but multiple for writes. A
write for such a verb is split automatically to multiple verbs.
The patch provides also a few handy helper functions. They are
designed to be accessible even without regmap. When no regmap is set
up (e.g. before the codec device instantiation), the direct hardware
access is used. Also, it tries to avoid the unnecessary power-up.
The power up/down sequence is performed only on demand.
The codec driver needs to call snd_hdac_regmap_exit() and
snd_hdac_regmap_exit() at probe and remove if it wants the regmap
access.
There is one flag added to hdac_device. When the flag lazy_cache is
set, regmap helper ignores a write for a suspended device and returns
as if it was actually written. It reduces the hardware access pretty
much, e.g. when adjusting the mixer volume while in idle. This
assumes that the driver will sync the cache later at resume properly,
so use it carefully.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-02-25 14:42:38 +01:00
if ( err < 0 )
goto error ;
err = snd_hdac_regmap_init ( & codec - > core ) ;
2015-02-17 15:25:37 +01:00
if ( err < 0 )
goto error ;
if ( ! try_module_get ( owner ) ) {
err = - EINVAL ;
goto error ;
}
2015-10-01 16:20:04 +02:00
patch = ( hda_codec_patch_t ) codec - > preset - > driver_data ;
if ( patch ) {
err = patch ( codec ) ;
if ( err < 0 )
2017-09-04 23:17:09 +08:00
goto error_module_put ;
2015-10-01 16:20:04 +02:00
}
2015-02-27 20:44:54 +01:00
err = snd_hda_codec_build_pcms ( codec ) ;
if ( err < 0 )
goto error_module ;
err = snd_hda_codec_build_controls ( codec ) ;
if ( err < 0 )
goto error_module ;
2019-01-30 17:46:03 +01:00
/* only register after the bus probe finished; otherwise it's racy */
if ( ! codec - > bus - > bus_probing & & codec - > card - > registered ) {
2015-02-27 20:44:54 +01:00
err = snd_card_register ( codec - > card ) ;
if ( err < 0 )
goto error_module ;
2015-03-03 17:22:12 +01:00
snd_hda_codec_register ( codec ) ;
2015-02-17 15:25:37 +01:00
}
ALSA: hda - Add regmap support
This patch adds an infrastructure to support regmap-based verb
accesses. Because o the asymmetric nature of HD-audio verbs,
especially the amp verbs, we need to translate the verbs as a sort of
pseudo registers to be mapped uniquely in regmap.
In this patch, a pseudo register is built from the NID, the
AC_VERB_GET_* and 8bit parameters, i.e. almost in the form to be sent
to HD-audio bus but without codec address field. OTOH, for writing,
the same pseudo register is translated to AC_VERB_SET_* automatically.
The AC_VERB_SET_AMP_* verb is re-encoded from the corresponding
AC_VERB_GET_AMP_* verb and parameter at writing.
Some verbs has a single command for read but multiple for writes. A
write for such a verb is split automatically to multiple verbs.
The patch provides also a few handy helper functions. They are
designed to be accessible even without regmap. When no regmap is set
up (e.g. before the codec device instantiation), the direct hardware
access is used. Also, it tries to avoid the unnecessary power-up.
The power up/down sequence is performed only on demand.
The codec driver needs to call snd_hdac_regmap_exit() and
snd_hdac_regmap_exit() at probe and remove if it wants the regmap
access.
There is one flag added to hdac_device. When the flag lazy_cache is
set, regmap helper ignores a write for a suspended device and returns
as if it was actually written. It reduces the hardware access pretty
much, e.g. when adjusting the mixer volume while in idle. This
assumes that the driver will sync the cache later at resume properly,
so use it carefully.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-02-25 14:42:38 +01:00
codec - > core . lazy_cache = true ;
2015-02-17 15:25:37 +01:00
return 0 ;
2015-02-27 20:44:54 +01:00
error_module :
2017-09-04 23:17:09 +08:00
if ( codec - > patch_ops . free )
codec - > patch_ops . free ( codec ) ;
error_module_put :
2015-02-27 20:44:54 +01:00
module_put ( owner ) ;
2015-02-17 15:25:37 +01:00
error :
2015-02-27 20:44:54 +01:00
snd_hda_codec_cleanup_for_unbind ( codec ) ;
2015-02-17 15:25:37 +01:00
return err ;
}
static int hda_codec_driver_remove ( struct device * dev )
{
struct hda_codec * codec = dev_to_hda_codec ( dev ) ;
2018-08-22 15:25:03 -05:00
if ( codec - > bus - > core . ext_ops ) {
if ( WARN_ON ( ! codec - > bus - > core . ext_ops - > hdev_detach ) )
return - EINVAL ;
return codec - > bus - > core . ext_ops - > hdev_detach ( & codec - > core ) ;
}
ALSA: hda: Fix potential deadlock at codec unbinding
When a codec is unbound dynamically via sysfs while its stream is in
use, we may face a potential deadlock at the proc remove or a UAF.
This happens since the hda_pcm is managed by a linked list, as it
handles the hda_pcm object release via kref.
When a PCM is opened at the unbinding time, the release of hda_pcm
gets delayed and it ends up with the close of the PCM stream releasing
the associated hda_pcm object of its own. The hda_pcm destructor
contains the PCM device release that includes the removal of procfs
entries. And, this removal has the sync of the close of all in-use
files -- which would never finish because it's called from the PCM
file descriptor itself, i.e. it's trying to shoot its foot.
For addressing the deadlock above, this patch changes the way to
manage and release the hda_pcm object. The kref of hda_pcm is
dropped, and instead a simple refcount is introduced in hda_codec for
keeping the track of the active PCM streams, and at each PCM open and
close, this refcount is adjusted accordingly. At unbinding, the
driver calls snd_device_disconnect() for each PCM stream, then
synchronizes with the refcount finish, and finally releases the object
resources.
Fixes: bbbc7e8502c9 ("ALSA: hda - Allocate hda_pcm objects dynamically")
Link: https://lore.kernel.org/r/20211116072459.18930-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2021-11-16 08:24:59 +01:00
refcount_dec ( & codec - > pcm_ref ) ;
snd_hda_codec_disconnect_pcms ( codec ) ;
2021-11-17 14:30:40 +01:00
snd_hda_jack_tbl_disconnect ( codec ) ;
ALSA: hda: Fix potential deadlock at codec unbinding
When a codec is unbound dynamically via sysfs while its stream is in
use, we may face a potential deadlock at the proc remove or a UAF.
This happens since the hda_pcm is managed by a linked list, as it
handles the hda_pcm object release via kref.
When a PCM is opened at the unbinding time, the release of hda_pcm
gets delayed and it ends up with the close of the PCM stream releasing
the associated hda_pcm object of its own. The hda_pcm destructor
contains the PCM device release that includes the removal of procfs
entries. And, this removal has the sync of the close of all in-use
files -- which would never finish because it's called from the PCM
file descriptor itself, i.e. it's trying to shoot its foot.
For addressing the deadlock above, this patch changes the way to
manage and release the hda_pcm object. The kref of hda_pcm is
dropped, and instead a simple refcount is introduced in hda_codec for
keeping the track of the active PCM streams, and at each PCM open and
close, this refcount is adjusted accordingly. At unbinding, the
driver calls snd_device_disconnect() for each PCM stream, then
synchronizes with the refcount finish, and finally releases the object
resources.
Fixes: bbbc7e8502c9 ("ALSA: hda - Allocate hda_pcm objects dynamically")
Link: https://lore.kernel.org/r/20211116072459.18930-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2021-11-16 08:24:59 +01:00
wait_event ( codec - > remove_sleep , ! refcount_read ( & codec - > pcm_ref ) ) ;
snd_power_sync_ref ( codec - > bus - > card ) ;
2015-02-17 15:25:37 +01:00
if ( codec - > patch_ops . free )
codec - > patch_ops . free ( codec ) ;
2015-02-27 18:17:28 +01:00
snd_hda_codec_cleanup_for_unbind ( codec ) ;
2015-02-17 15:25:37 +01:00
module_put ( dev - > driver - > owner ) ;
return 0 ;
}
2015-03-05 17:21:32 +01:00
static void hda_codec_driver_shutdown ( struct device * dev )
{
2021-08-13 10:12:29 +02:00
snd_hda_codec_shutdown ( dev_to_hda_codec ( dev ) ) ;
2015-03-05 17:21:32 +01:00
}
2015-02-17 15:25:37 +01:00
int __hda_codec_driver_register ( struct hda_codec_driver * drv , const char * name ,
struct module * owner )
{
2015-02-17 21:46:37 +01:00
drv - > core . driver . name = name ;
drv - > core . driver . owner = owner ;
drv - > core . driver . bus = & snd_hda_bus_type ;
drv - > core . driver . probe = hda_codec_driver_probe ;
drv - > core . driver . remove = hda_codec_driver_remove ;
drv - > core . driver . shutdown = hda_codec_driver_shutdown ;
drv - > core . driver . pm = & hda_codec_driver_pm ;
drv - > core . type = HDA_DEV_LEGACY ;
drv - > core . match = hda_codec_match ;
2015-03-02 23:22:59 +01:00
drv - > core . unsol_event = hda_codec_unsol_event ;
2015-02-17 21:46:37 +01:00
return driver_register ( & drv - > core . driver ) ;
2015-02-17 15:25:37 +01:00
}
EXPORT_SYMBOL_GPL ( __hda_codec_driver_register ) ;
void hda_codec_driver_unregister ( struct hda_codec_driver * drv )
{
2015-02-17 21:46:37 +01:00
driver_unregister ( & drv - > core . driver ) ;
2015-02-17 15:25:37 +01:00
}
EXPORT_SYMBOL_GPL ( hda_codec_driver_unregister ) ;
static inline bool codec_probed ( struct hda_codec * codec )
{
return device_attach ( hda_codec_dev ( codec ) ) > 0 & & codec - > preset ;
}
2016-01-20 15:46:44 +01:00
/* try to auto-load codec module */
static void request_codec_module ( struct hda_codec * codec )
2015-02-17 15:25:37 +01:00
{
# ifdef MODULE
2015-10-01 16:20:04 +02:00
char modalias [ 32 ] ;
2016-01-20 15:46:44 +01:00
const char * mod = NULL ;
switch ( codec - > probe_id ) {
case HDA_CODEC_ID_GENERIC_HDMI :
# if IS_MODULE(CONFIG_SND_HDA_CODEC_HDMI)
mod = " snd-hda-codec-hdmi " ;
# endif
break ;
case HDA_CODEC_ID_GENERIC :
# if IS_MODULE(CONFIG_SND_HDA_GENERIC)
mod = " snd-hda-codec-generic " ;
# endif
break ;
default :
snd_hdac_codec_modalias ( & codec - > core , modalias , sizeof ( modalias ) ) ;
mod = modalias ;
break ;
}
if ( mod )
request_module ( mod ) ;
# endif /* MODULE */
}
2015-10-01 16:20:04 +02:00
2016-01-20 15:46:44 +01:00
/* try to auto-load and bind the codec module */
static void codec_bind_module ( struct hda_codec * codec )
{
# ifdef MODULE
request_codec_module ( codec ) ;
2015-02-17 15:25:37 +01:00
if ( codec_probed ( codec ) )
return ;
# endif
}
# if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI)
/* if all audio out widgets are digital, let's assume the codec as a HDMI/DP */
static bool is_likely_hdmi_codec ( struct hda_codec * codec )
{
2015-03-03 10:07:24 +01:00
hda_nid_t nid ;
2015-02-17 15:25:37 +01:00
2015-03-03 10:07:24 +01:00
for_each_hda_codec_node ( nid , codec ) {
2015-02-17 15:25:37 +01:00
unsigned int wcaps = get_wcaps ( codec , nid ) ;
switch ( get_wcaps_type ( wcaps ) ) {
case AC_WID_AUD_IN :
return false ; /* HDMI parser supports only HDMI out */
case AC_WID_AUD_OUT :
if ( ! ( wcaps & AC_WCAP_DIGITAL ) )
return false ;
break ;
}
}
return true ;
}
# else
/* no HDMI codec parser support */
# define is_likely_hdmi_codec(codec) false
# endif /* CONFIG_SND_HDA_CODEC_HDMI */
static int codec_bind_generic ( struct hda_codec * codec )
{
if ( codec - > probe_id )
return - ENODEV ;
if ( is_likely_hdmi_codec ( codec ) ) {
codec - > probe_id = HDA_CODEC_ID_GENERIC_HDMI ;
2016-01-20 15:46:44 +01:00
request_codec_module ( codec ) ;
2015-02-17 15:25:37 +01:00
if ( codec_probed ( codec ) )
return 0 ;
}
codec - > probe_id = HDA_CODEC_ID_GENERIC ;
2016-01-20 15:46:44 +01:00
request_codec_module ( codec ) ;
2015-02-17 15:25:37 +01:00
if ( codec_probed ( codec ) )
return 0 ;
return - ENODEV ;
}
# if IS_ENABLED(CONFIG_SND_HDA_GENERIC)
# define is_generic_config(codec) \
( codec - > modelname & & ! strcmp ( codec - > modelname , " generic " ) )
# else
# define is_generic_config(codec) 0
# endif
/**
* snd_hda_codec_configure - ( Re - ) configure the HD - audio codec
* @ codec : the HDA codec
*
* Start parsing of the given codec tree and ( re - ) initialize the whole
* patch instance .
*
* Returns 0 if successful or a negative error code .
*/
int snd_hda_codec_configure ( struct hda_codec * codec )
{
int err ;
ALSA: hda: intel: Allow repeatedly probing on codec configuration errors
It seems that a few recent AMD systems show the codec configuration
errors at the early boot, while loading the driver at a later stage
works magically. Although the root cause of the error isn't clear,
it's certainly not bad to allow retrying the codec probe in such a
case if that helps.
This patch adds the capability for retrying the probe upon codec probe
errors on the certain AMD platforms. The probe_work is changed to a
delayed work, and at the secondary call, it'll jump to the codec
probing.
Note that, not only adding the re-probing, this includes the behavior
changes in the codec configuration function. Namely,
snd_hda_codec_configure() won't unregister the codec at errors any
longer. Instead, its caller, azx_codec_configure() unregisters the
codecs with the probe failures *if* any codec has been successfully
configured. If all codec probe failed, it doesn't unregister but let
it re-probed -- which is the most case we're seeing and this patch
tries to improve.
Even if the driver doesn't re-probe or give up, it will go to the
"free-all" error path, hence the leftover codecs shall be disabled /
deleted in anyway.
BugLink: https://bugzilla.suse.com/show_bug.cgi?id=1190801
Link: https://lore.kernel.org/r/20211006141940.2897-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2021-10-06 16:19:40 +02:00
if ( codec - > configured )
return 0 ;
2015-02-17 15:25:37 +01:00
if ( is_generic_config ( codec ) )
codec - > probe_id = HDA_CODEC_ID_GENERIC ;
else
codec - > probe_id = 0 ;
ALSA: hda: intel: Allow repeatedly probing on codec configuration errors
It seems that a few recent AMD systems show the codec configuration
errors at the early boot, while loading the driver at a later stage
works magically. Although the root cause of the error isn't clear,
it's certainly not bad to allow retrying the codec probe in such a
case if that helps.
This patch adds the capability for retrying the probe upon codec probe
errors on the certain AMD platforms. The probe_work is changed to a
delayed work, and at the secondary call, it'll jump to the codec
probing.
Note that, not only adding the re-probing, this includes the behavior
changes in the codec configuration function. Namely,
snd_hda_codec_configure() won't unregister the codec at errors any
longer. Instead, its caller, azx_codec_configure() unregisters the
codecs with the probe failures *if* any codec has been successfully
configured. If all codec probe failed, it doesn't unregister but let
it re-probed -- which is the most case we're seeing and this patch
tries to improve.
Even if the driver doesn't re-probe or give up, it will go to the
"free-all" error path, hence the leftover codecs shall be disabled /
deleted in anyway.
BugLink: https://bugzilla.suse.com/show_bug.cgi?id=1190801
Link: https://lore.kernel.org/r/20211006141940.2897-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2021-10-06 16:19:40 +02:00
if ( ! device_is_registered ( & codec - > core . dev ) ) {
err = snd_hdac_device_register ( & codec - > core ) ;
if ( err < 0 )
return err ;
}
2015-02-17 15:25:37 +01:00
if ( ! codec - > preset )
codec_bind_module ( codec ) ;
if ( ! codec - > preset ) {
err = codec_bind_generic ( codec ) ;
if ( err < 0 ) {
ALSA: hda: intel: Allow repeatedly probing on codec configuration errors
It seems that a few recent AMD systems show the codec configuration
errors at the early boot, while loading the driver at a later stage
works magically. Although the root cause of the error isn't clear,
it's certainly not bad to allow retrying the codec probe in such a
case if that helps.
This patch adds the capability for retrying the probe upon codec probe
errors on the certain AMD platforms. The probe_work is changed to a
delayed work, and at the secondary call, it'll jump to the codec
probing.
Note that, not only adding the re-probing, this includes the behavior
changes in the codec configuration function. Namely,
snd_hda_codec_configure() won't unregister the codec at errors any
longer. Instead, its caller, azx_codec_configure() unregisters the
codecs with the probe failures *if* any codec has been successfully
configured. If all codec probe failed, it doesn't unregister but let
it re-probed -- which is the most case we're seeing and this patch
tries to improve.
Even if the driver doesn't re-probe or give up, it will go to the
"free-all" error path, hence the leftover codecs shall be disabled /
deleted in anyway.
BugLink: https://bugzilla.suse.com/show_bug.cgi?id=1190801
Link: https://lore.kernel.org/r/20211006141940.2897-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2021-10-06 16:19:40 +02:00
codec_dbg ( codec , " Unable to bind the codec \n " ) ;
return err ;
2015-02-17 15:25:37 +01:00
}
}
ALSA: hda: intel: Allow repeatedly probing on codec configuration errors
It seems that a few recent AMD systems show the codec configuration
errors at the early boot, while loading the driver at a later stage
works magically. Although the root cause of the error isn't clear,
it's certainly not bad to allow retrying the codec probe in such a
case if that helps.
This patch adds the capability for retrying the probe upon codec probe
errors on the certain AMD platforms. The probe_work is changed to a
delayed work, and at the secondary call, it'll jump to the codec
probing.
Note that, not only adding the re-probing, this includes the behavior
changes in the codec configuration function. Namely,
snd_hda_codec_configure() won't unregister the codec at errors any
longer. Instead, its caller, azx_codec_configure() unregisters the
codecs with the probe failures *if* any codec has been successfully
configured. If all codec probe failed, it doesn't unregister but let
it re-probed -- which is the most case we're seeing and this patch
tries to improve.
Even if the driver doesn't re-probe or give up, it will go to the
"free-all" error path, hence the leftover codecs shall be disabled /
deleted in anyway.
BugLink: https://bugzilla.suse.com/show_bug.cgi?id=1190801
Link: https://lore.kernel.org/r/20211006141940.2897-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2021-10-06 16:19:40 +02:00
codec - > configured = 1 ;
2015-02-17 15:25:37 +01:00
return 0 ;
}
EXPORT_SYMBOL_GPL ( snd_hda_codec_configure ) ;