
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>
68 lines
2.0 KiB
C
68 lines
2.0 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
// HD-Audio helpers to sync with DRM driver
|
|
|
|
#ifndef __SOUND_HDA_COMPONENT_H
|
|
#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, 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,
|
|
bool *audio_enabled, char *buffer, int max_bytes);
|
|
int snd_hdac_acomp_init(struct hdac_bus *bus,
|
|
const struct drm_audio_component_audio_ops *aops,
|
|
int (*match_master)(struct device *, void *),
|
|
size_t extra_size);
|
|
int snd_hdac_acomp_exit(struct hdac_bus *bus);
|
|
int snd_hdac_acomp_register_notifier(struct hdac_bus *bus,
|
|
const struct drm_audio_component_audio_ops *ops);
|
|
#else
|
|
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,
|
|
unsigned int idx, bool enable)
|
|
{
|
|
return 0;
|
|
}
|
|
static inline int snd_hdac_sync_audio_rate(struct hdac_device *codec,
|
|
hda_nid_t nid, int dev_id, int rate)
|
|
{
|
|
return 0;
|
|
}
|
|
static inline int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid,
|
|
int dev_id, bool *audio_enabled,
|
|
char *buffer, int max_bytes)
|
|
{
|
|
return -ENODEV;
|
|
}
|
|
static inline int snd_hdac_acomp_init(struct hdac_bus *bus,
|
|
const struct drm_audio_component_audio_ops *aops,
|
|
int (*match_master)(struct device *, void *),
|
|
size_t extra_size)
|
|
{
|
|
return -ENODEV;
|
|
}
|
|
static inline int snd_hdac_acomp_exit(struct hdac_bus *bus)
|
|
{
|
|
return 0;
|
|
}
|
|
static inline int snd_hdac_acomp_register_notifier(struct hdac_bus *bus,
|
|
const struct drm_audio_component_audio_ops *ops)
|
|
{
|
|
return -ENODEV;
|
|
}
|
|
#endif
|
|
|
|
#endif /* __SOUND_HDA_COMPONENT_H */
|