Commit 1d69970d authored by Takashi Iwai's avatar Takashi Iwai
Browse files

Merge tag 'topic/i915-hda-componentized-2015-01-12' of...

Merge tag 'topic/i915-hda-componentized-2015-01-12' of git://anongit.freedesktop.org/drm-intel into for-next
parents 7bfb8575 fcf3aac5
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -830,6 +830,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)

	intel_runtime_pm_enable(dev_priv);

	i915_audio_component_init(dev_priv);

	return 0;

out_power_well:
@@ -870,6 +872,8 @@ int i915_driver_unload(struct drm_device *dev)
	struct drm_i915_private *dev_priv = dev->dev_private;
	int ret;

	i915_audio_component_cleanup(dev_priv);

	ret = i915_gem_suspend(dev);
	if (ret) {
		DRM_ERROR("failed to idle hardware: %d\n", ret);
+3 −6
Original line number Diff line number Diff line
@@ -940,8 +940,7 @@ static int i915_pm_suspend(struct device *dev)

static int i915_pm_suspend_late(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct drm_device *drm_dev = pci_get_drvdata(pdev);
	struct drm_device *drm_dev = dev_to_i915(dev)->dev;

	/*
	 * We have a suspedn ordering issue with the snd-hda driver also
@@ -960,8 +959,7 @@ static int i915_pm_suspend_late(struct device *dev)

static int i915_pm_resume_early(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct drm_device *drm_dev = pci_get_drvdata(pdev);
	struct drm_device *drm_dev = dev_to_i915(dev)->dev;

	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
		return 0;
@@ -971,8 +969,7 @@ static int i915_pm_resume_early(struct device *dev)

static int i915_pm_resume(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct drm_device *drm_dev = pci_get_drvdata(pdev);
	struct drm_device *drm_dev = dev_to_i915(dev)->dev;

	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
		return 0;
+8 −0
Original line number Diff line number Diff line
@@ -1698,6 +1698,9 @@ struct drm_i915_private {
	struct drm_property *broadcast_rgb_property;
	struct drm_property *force_audio_property;

	/* hda/i915 audio component */
	bool audio_component_registered;

	uint32_t hw_context_size;
	struct list_head context_list;

@@ -1781,6 +1784,11 @@ static inline struct drm_i915_private *to_i915(const struct drm_device *dev)
	return dev->dev_private;
}

static inline struct drm_i915_private *dev_to_i915(struct device *dev)
{
	return to_i915(dev_get_drvdata(dev));
}

/* Iterate over initialised rings */
#define for_each_ring(ring__, dev_priv__, i__) \
	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
+110 −0
Original line number Diff line number Diff line
@@ -22,6 +22,9 @@
 */

#include <linux/kernel.h>
#include <linux/component.h>
#include <drm/i915_component.h>
#include "intel_drv.h"

#include <drm/drmP.h>
#include <drm/drm_edid.h>
@@ -461,3 +464,110 @@ void intel_init_audio(struct drm_device *dev)
		dev_priv->display.audio_codec_disable = ilk_audio_codec_disable;
	}
}

static void i915_audio_component_get_power(struct device *dev)
{
	intel_display_power_get(dev_to_i915(dev), POWER_DOMAIN_AUDIO);
}

static void i915_audio_component_put_power(struct device *dev)
{
	intel_display_power_put(dev_to_i915(dev), POWER_DOMAIN_AUDIO);
}

/* Get CDCLK in kHz  */
static int i915_audio_component_get_cdclk_freq(struct device *dev)
{
	struct drm_i915_private *dev_priv = dev_to_i915(dev);
	int ret;

	if (WARN_ON_ONCE(!HAS_DDI(dev_priv)))
		return -ENODEV;

	intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
	ret = intel_ddi_get_cdclk_freq(dev_priv);
	intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);

	return ret;
}

static const struct i915_audio_component_ops i915_audio_component_ops = {
	.owner		= THIS_MODULE,
	.get_power	= i915_audio_component_get_power,
	.put_power	= i915_audio_component_put_power,
	.get_cdclk_freq	= i915_audio_component_get_cdclk_freq,
};

static int i915_audio_component_bind(struct device *i915_dev,
				     struct device *hda_dev, void *data)
{
	struct i915_audio_component *acomp = data;

	if (WARN_ON(acomp->ops || acomp->dev))
		return -EEXIST;

	acomp->ops = &i915_audio_component_ops;
	acomp->dev = i915_dev;

	return 0;
}

static void i915_audio_component_unbind(struct device *i915_dev,
					struct device *hda_dev, void *data)
{
	struct i915_audio_component *acomp = data;

	acomp->ops = NULL;
	acomp->dev = NULL;
}

static const struct component_ops i915_audio_component_bind_ops = {
	.bind	= i915_audio_component_bind,
	.unbind	= i915_audio_component_unbind,
};

/**
 * i915_audio_component_init - initialize and register the audio component
 * @dev_priv: i915 device instance
 *
 * This will register with the component framework a child component which
 * will bind dynamically to the snd_hda_intel driver's corresponding master
 * component when the latter is registered. During binding the child
 * initializes an instance of struct i915_audio_component which it receives
 * from the master. The master can then start to use the interface defined by
 * this struct. Each side can break the binding at any point by deregistering
 * its own component after which each side's component unbind callback is
 * called.
 *
 * We ignore any error during registration and continue with reduced
 * functionality (i.e. without HDMI audio).
 */
void i915_audio_component_init(struct drm_i915_private *dev_priv)
{
	int ret;

	ret = component_add(dev_priv->dev->dev, &i915_audio_component_bind_ops);
	if (ret < 0) {
		DRM_ERROR("failed to add audio component (%d)\n", ret);
		/* continue with reduced functionality */
		return;
	}

	dev_priv->audio_component_registered = true;
}

/**
 * i915_audio_component_cleanup - deregister the audio component
 * @dev_priv: i915 device instance
 *
 * Deregisters the audio component, breaking any existing binding to the
 * corresponding snd_hda_intel driver's master component.
 */
void i915_audio_component_cleanup(struct drm_i915_private *dev_priv)
{
	if (!dev_priv->audio_component_registered)
		return;

	component_del(dev_priv->dev->dev, &i915_audio_component_bind_ops);
	dev_priv->audio_component_registered = false;
}
+2 −0
Original line number Diff line number Diff line
@@ -872,6 +872,8 @@ void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire);
void intel_init_audio(struct drm_device *dev);
void intel_audio_codec_enable(struct intel_encoder *encoder);
void intel_audio_codec_disable(struct intel_encoder *encoder);
void i915_audio_component_init(struct drm_i915_private *dev_priv);
void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);

/* intel_display.c */
const char *intel_output_name(int output);
Loading