Commit c7072f5f authored by Takashi Iwai's avatar Takashi Iwai
Browse files

Merge branch 'topic/hda-pm-refactor' into for-next



Pull refactoring / fixes of HD-audio PM and display power management

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parents a91f6760 46594d33
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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)
+8 −3
Original line number Diff line number Diff line
@@ -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);
void 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,9 +30,9 @@ 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 void 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)
+2 −5
Original line number Diff line number Diff line
@@ -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);
+22 −17
Original line number Diff line number Diff line
@@ -54,41 +54,44 @@ EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup);
/**
 * snd_hdac_display_power - Power up / down the power refcount
 * @bus: HDA core bus
 * @idx: HDA codec address, pass HDA_CODEC_IDX_CONTROLLER for controller
 * @enable: power up or down
 *
 * This function is supposed to be used only by a HD-audio controller
 * driver that needs the interaction with graphics driver.
 * This function is used by either HD-audio controller or codec driver that
 * needs the interaction with graphics driver.
 *
 * This function manages a refcount and calls the get_power() and
 * This function updates the power status, and calls the get_power() and
 * put_power() ops accordingly, toggling the codec wakeup, too.
 *
 * Returns zero for success or a negative error code.
 */
int snd_hdac_display_power(struct hdac_bus *bus, bool enable)
void snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable)
{
	struct drm_audio_component *acomp = bus->audio_component;

	if (!acomp || !acomp->ops)
		return -ENODEV;

	dev_dbg(bus->dev, "display power %s\n",
		enable ? "enable" : "disable");
	if (enable)
		set_bit(idx, &bus->display_power_status);
	else
		clear_bit(idx, &bus->display_power_status);

	if (enable) {
		if (!bus->drm_power_refcount++) {
	if (!acomp || !acomp->ops)
		return;

	if (bus->display_power_status) {
		if (!bus->display_power_active) {
			if (acomp->ops->get_power)
				acomp->ops->get_power(acomp->dev);
			snd_hdac_set_codec_wakeup(bus, true);
			snd_hdac_set_codec_wakeup(bus, false);
			bus->display_power_active = true;
		}
	} else {
		WARN_ON(!bus->drm_power_refcount);
		if (!--bus->drm_power_refcount)
		if (bus->display_power_active) {
			if (acomp->ops->put_power)
				acomp->ops->put_power(acomp->dev);
			bus->display_power_active = false;
		}
	}

	return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_display_power);

@@ -321,10 +324,12 @@ int snd_hdac_acomp_exit(struct hdac_bus *bus)
	if (!acomp)
		return 0;

	WARN_ON(bus->drm_power_refcount);
	if (bus->drm_power_refcount > 0 && acomp->ops)
	if (WARN_ON(bus->display_power_active) && acomp->ops)
		acomp->ops->put_power(acomp->dev);

	bus->display_power_active = false;
	bus->display_power_status = 0;

	component_master_del(dev, &hdac_component_master_ops);

	bus->audio_component = NULL;
+0 −17
Original line number Diff line number Diff line
@@ -622,23 +622,6 @@ int snd_hdac_power_down_pm(struct hdac_device *codec)
EXPORT_SYMBOL_GPL(snd_hdac_power_down_pm);
#endif

/**
 * snd_hdac_link_power - Enable/disable the link power for a codec
 * @codec: the codec object
 * @bool: enable or disable the link power
 */
int snd_hdac_link_power(struct hdac_device *codec, bool enable)
{
	if  (!codec->link_power_control)
		return 0;

	if  (codec->bus->ops->link_power)
		return codec->bus->ops->link_power(codec->bus, enable);
	else
		return -EINVAL;
}
EXPORT_SYMBOL_GPL(snd_hdac_link_power);

/* codec vendor labels */
struct hda_vendor_id {
	unsigned int id;
Loading