Skip to content

Commit

Permalink
Merge tag 'topic/i915-hda-componentized-2015-01-12' of git://anongit.…
Browse files Browse the repository at this point in the history
…freedesktop.org/drm-intel into for-next
  • Loading branch information
Takashi Iwai committed Jan 13, 2015
2 parents 7bfb857 + fcf3aac commit 1d69970
Show file tree
Hide file tree
Showing 12 changed files with 361 additions and 225 deletions.
4 changes: 4 additions & 0 deletions drivers/gpu/drm/i915/i915_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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);
Expand Down
9 changes: 3 additions & 6 deletions drivers/gpu/drm/i915/i915_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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;
Expand Down
8 changes: 8 additions & 0 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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__)++) \
Expand Down
110 changes: 110 additions & 0 deletions drivers/gpu/drm/i915/intel_audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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 changes: 2 additions & 0 deletions drivers/gpu/drm/i915/intel_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
56 changes: 0 additions & 56 deletions drivers/gpu/drm/i915/intel_runtime_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@

#include "i915_drv.h"
#include "intel_drv.h"
#include <drm/i915_powerwell.h>

/**
* DOC: runtime pm
Expand All @@ -50,8 +49,6 @@
* present for a given platform.
*/

static struct i915_power_domains *hsw_pwr;

#define for_each_power_well(i, power_well, domain_mask, power_domains) \
for (i = 0; \
i < (power_domains)->power_well_count && \
Expand Down Expand Up @@ -1071,10 +1068,8 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
*/
if (IS_HASWELL(dev_priv->dev)) {
set_power_wells(power_domains, hsw_power_wells);
hsw_pwr = power_domains;
} else if (IS_BROADWELL(dev_priv->dev)) {
set_power_wells(power_domains, bdw_power_wells);
hsw_pwr = power_domains;
} else if (IS_CHERRYVIEW(dev_priv->dev)) {
set_power_wells(power_domains, chv_power_wells);
} else if (IS_VALLEYVIEW(dev_priv->dev)) {
Expand Down Expand Up @@ -1118,8 +1113,6 @@ void intel_power_domains_fini(struct drm_i915_private *dev_priv)
* the power well is not enabled, so just enable it in case
* we're going to unload/reload. */
intel_display_set_init_power(dev_priv, true);

hsw_pwr = NULL;
}

static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
Expand Down Expand Up @@ -1328,52 +1321,3 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
pm_runtime_put_autosuspend(device);
}

/* Display audio driver power well request */
int i915_request_power_well(void)
{
struct drm_i915_private *dev_priv;

if (!hsw_pwr)
return -ENODEV;

dev_priv = container_of(hsw_pwr, struct drm_i915_private,
power_domains);
intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
return 0;
}
EXPORT_SYMBOL_GPL(i915_request_power_well);

/* Display audio driver power well release */
int i915_release_power_well(void)
{
struct drm_i915_private *dev_priv;

if (!hsw_pwr)
return -ENODEV;

dev_priv = container_of(hsw_pwr, struct drm_i915_private,
power_domains);
intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
return 0;
}
EXPORT_SYMBOL_GPL(i915_release_power_well);

/*
* Private interface for the audio driver to get CDCLK in kHz.
*
* Caller must request power well using i915_request_power_well() prior to
* making the call.
*/
int i915_get_cdclk_freq(void)
{
struct drm_i915_private *dev_priv;

if (!hsw_pwr)
return -ENODEV;

dev_priv = container_of(hsw_pwr, struct drm_i915_private,
power_domains);

return intel_ddi_get_cdclk_freq(dev_priv);
}
EXPORT_SYMBOL_GPL(i915_get_cdclk_freq);
38 changes: 38 additions & 0 deletions include/drm/i915_component.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright © 2014 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/

#ifndef _I915_COMPONENT_H_
#define _I915_COMPONENT_H_

struct i915_audio_component {
struct device *dev;

const struct i915_audio_component_ops {
struct module *owner;
void (*get_power)(struct device *);
void (*put_power)(struct device *);
int (*get_cdclk_freq)(struct device *);
} *ops;
};

#endif /* _I915_COMPONENT_H_ */
37 changes: 0 additions & 37 deletions include/drm/i915_powerwell.h

This file was deleted.

Loading

0 comments on commit 1d69970

Please sign in to comment.