ALSA: hda: Refactor display power management
The current HD-audio code manages the DRM audio power via too complex redirections, and this seems even still unbalanced in a corner case as Intel DRM CI has been intermittently reporting. This patch is a big surgery for addressing the complexity and the possible unbalance. Basically the patch changes the display PM in the following ways: - Both HD-audio controller and codec drivers call a single helper, snd_hdac_display_power(). (Formerly, the display power control from a codec was done indirectly via link_power bus ops.) - snd_hdac_display_power() receives the codec address index. For turning on/off from the controller, pass HDA_CODEC_IDX_CONTROLLER. - snd_hdac_display_power() doesn't manage refcounts any longer, but keeps the power status in bitmap. If any of controller or codecs is turned on, the function updates the DRM power state via get_power() or put_power(). Also this refactor allows us more cleanup: - The link_power bus ops is dropped, so there is no longer indirect management, as mentioned in the above. - hdac_device link_power_control flag is moved to hda_codec display_power_control flag, as it's only for HDA legacy. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=106525 Signed-off-by: Takashi Iwai <tiwai@suse.de>
このコミットが含まれているのは:
@@ -236,6 +236,7 @@ struct hda_codec {
|
||||
/* misc flags */
|
||||
unsigned int in_freeing:1; /* being released */
|
||||
unsigned int registered:1; /* codec was registered */
|
||||
unsigned int display_power_control:1; /* needs display power */
|
||||
unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each
|
||||
* status change
|
||||
* (e.g. Realtek codecs)
|
||||
|
@@ -5,10 +5,15 @@
|
||||
#define __SOUND_HDA_COMPONENT_H
|
||||
|
||||
#include <drm/drm_audio_component.h>
|
||||
#include <sound/hdaudio.h>
|
||||
|
||||
/* virtual idx for controller */
|
||||
#define HDA_CODEC_IDX_CONTROLLER HDA_MAX_CODECS
|
||||
|
||||
#ifdef CONFIG_SND_HDA_COMPONENT
|
||||
int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable);
|
||||
int snd_hdac_display_power(struct hdac_bus *bus, bool enable);
|
||||
int snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx,
|
||||
bool enable);
|
||||
int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid,
|
||||
int dev_id, int rate);
|
||||
int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id,
|
||||
@@ -25,7 +30,8 @@ static inline int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int snd_hdac_display_power(struct hdac_bus *bus, bool enable)
|
||||
static inline int snd_hdac_display_power(struct hdac_bus *bus,
|
||||
unsigned int idx, bool enable)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@@ -79,7 +79,6 @@ struct hdac_device {
|
||||
|
||||
/* misc flags */
|
||||
atomic_t in_pm; /* suspend/resume being performed */
|
||||
bool link_power_control:1;
|
||||
|
||||
/* sysfs */
|
||||
struct hdac_widget_tree *widgets;
|
||||
@@ -237,8 +236,6 @@ struct hdac_bus_ops {
|
||||
/* get a response from the last command */
|
||||
int (*get_response)(struct hdac_bus *bus, unsigned int addr,
|
||||
unsigned int *res);
|
||||
/* control the link power */
|
||||
int (*link_power)(struct hdac_bus *bus, bool enable);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -363,7 +360,8 @@ struct hdac_bus {
|
||||
|
||||
/* DRM component interface */
|
||||
struct drm_audio_component *audio_component;
|
||||
int drm_power_refcount;
|
||||
long display_power_status;
|
||||
bool display_power_active;
|
||||
|
||||
/* parameters required for enhanced capabilities */
|
||||
int num_streams;
|
||||
@@ -404,7 +402,6 @@ int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val);
|
||||
int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
|
||||
unsigned int *res);
|
||||
int snd_hdac_bus_parse_capabilities(struct hdac_bus *bus);
|
||||
int snd_hdac_link_power(struct hdac_device *codec, bool enable);
|
||||
|
||||
bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset);
|
||||
void snd_hdac_bus_stop_chip(struct hdac_bus *bus);
|
||||
|
新しいイシューから参照
ユーザーをブロックする