Skip to content

Commit 1d69970

Browse files
committed
Merge tag 'topic/i915-hda-componentized-2015-01-12' of git://anongit.freedesktop.org/drm-intel into for-next
2 parents 7bfb857 + fcf3aac commit 1d69970

File tree

12 files changed

+361
-225
lines changed

12 files changed

+361
-225
lines changed

drivers/gpu/drm/i915/i915_dma.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
830830

831831
intel_runtime_pm_enable(dev_priv);
832832

833+
i915_audio_component_init(dev_priv);
834+
833835
return 0;
834836

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

875+
i915_audio_component_cleanup(dev_priv);
876+
873877
ret = i915_gem_suspend(dev);
874878
if (ret) {
875879
DRM_ERROR("failed to idle hardware: %d\n", ret);

drivers/gpu/drm/i915/i915_drv.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -940,8 +940,7 @@ static int i915_pm_suspend(struct device *dev)
940940

941941
static int i915_pm_suspend_late(struct device *dev)
942942
{
943-
struct pci_dev *pdev = to_pci_dev(dev);
944-
struct drm_device *drm_dev = pci_get_drvdata(pdev);
943+
struct drm_device *drm_dev = dev_to_i915(dev)->dev;
945944

946945
/*
947946
* 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)
960959

961960
static int i915_pm_resume_early(struct device *dev)
962961
{
963-
struct pci_dev *pdev = to_pci_dev(dev);
964-
struct drm_device *drm_dev = pci_get_drvdata(pdev);
962+
struct drm_device *drm_dev = dev_to_i915(dev)->dev;
965963

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

972970
static int i915_pm_resume(struct device *dev)
973971
{
974-
struct pci_dev *pdev = to_pci_dev(dev);
975-
struct drm_device *drm_dev = pci_get_drvdata(pdev);
972+
struct drm_device *drm_dev = dev_to_i915(dev)->dev;
976973

977974
if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
978975
return 0;

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,6 +1698,9 @@ struct drm_i915_private {
16981698
struct drm_property *broadcast_rgb_property;
16991699
struct drm_property *force_audio_property;
17001700

1701+
/* hda/i915 audio component */
1702+
bool audio_component_registered;
1703+
17011704
uint32_t hw_context_size;
17021705
struct list_head context_list;
17031706

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

1787+
static inline struct drm_i915_private *dev_to_i915(struct device *dev)
1788+
{
1789+
return to_i915(dev_get_drvdata(dev));
1790+
}
1791+
17841792
/* Iterate over initialised rings */
17851793
#define for_each_ring(ring__, dev_priv__, i__) \
17861794
for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \

drivers/gpu/drm/i915/intel_audio.c

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
*/
2323

2424
#include <linux/kernel.h>
25+
#include <linux/component.h>
26+
#include <drm/i915_component.h>
27+
#include "intel_drv.h"
2528

2629
#include <drm/drmP.h>
2730
#include <drm/drm_edid.h>
@@ -461,3 +464,110 @@ void intel_init_audio(struct drm_device *dev)
461464
dev_priv->display.audio_codec_disable = ilk_audio_codec_disable;
462465
}
463466
}
467+
468+
static void i915_audio_component_get_power(struct device *dev)
469+
{
470+
intel_display_power_get(dev_to_i915(dev), POWER_DOMAIN_AUDIO);
471+
}
472+
473+
static void i915_audio_component_put_power(struct device *dev)
474+
{
475+
intel_display_power_put(dev_to_i915(dev), POWER_DOMAIN_AUDIO);
476+
}
477+
478+
/* Get CDCLK in kHz */
479+
static int i915_audio_component_get_cdclk_freq(struct device *dev)
480+
{
481+
struct drm_i915_private *dev_priv = dev_to_i915(dev);
482+
int ret;
483+
484+
if (WARN_ON_ONCE(!HAS_DDI(dev_priv)))
485+
return -ENODEV;
486+
487+
intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
488+
ret = intel_ddi_get_cdclk_freq(dev_priv);
489+
intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
490+
491+
return ret;
492+
}
493+
494+
static const struct i915_audio_component_ops i915_audio_component_ops = {
495+
.owner = THIS_MODULE,
496+
.get_power = i915_audio_component_get_power,
497+
.put_power = i915_audio_component_put_power,
498+
.get_cdclk_freq = i915_audio_component_get_cdclk_freq,
499+
};
500+
501+
static int i915_audio_component_bind(struct device *i915_dev,
502+
struct device *hda_dev, void *data)
503+
{
504+
struct i915_audio_component *acomp = data;
505+
506+
if (WARN_ON(acomp->ops || acomp->dev))
507+
return -EEXIST;
508+
509+
acomp->ops = &i915_audio_component_ops;
510+
acomp->dev = i915_dev;
511+
512+
return 0;
513+
}
514+
515+
static void i915_audio_component_unbind(struct device *i915_dev,
516+
struct device *hda_dev, void *data)
517+
{
518+
struct i915_audio_component *acomp = data;
519+
520+
acomp->ops = NULL;
521+
acomp->dev = NULL;
522+
}
523+
524+
static const struct component_ops i915_audio_component_bind_ops = {
525+
.bind = i915_audio_component_bind,
526+
.unbind = i915_audio_component_unbind,
527+
};
528+
529+
/**
530+
* i915_audio_component_init - initialize and register the audio component
531+
* @dev_priv: i915 device instance
532+
*
533+
* This will register with the component framework a child component which
534+
* will bind dynamically to the snd_hda_intel driver's corresponding master
535+
* component when the latter is registered. During binding the child
536+
* initializes an instance of struct i915_audio_component which it receives
537+
* from the master. The master can then start to use the interface defined by
538+
* this struct. Each side can break the binding at any point by deregistering
539+
* its own component after which each side's component unbind callback is
540+
* called.
541+
*
542+
* We ignore any error during registration and continue with reduced
543+
* functionality (i.e. without HDMI audio).
544+
*/
545+
void i915_audio_component_init(struct drm_i915_private *dev_priv)
546+
{
547+
int ret;
548+
549+
ret = component_add(dev_priv->dev->dev, &i915_audio_component_bind_ops);
550+
if (ret < 0) {
551+
DRM_ERROR("failed to add audio component (%d)\n", ret);
552+
/* continue with reduced functionality */
553+
return;
554+
}
555+
556+
dev_priv->audio_component_registered = true;
557+
}
558+
559+
/**
560+
* i915_audio_component_cleanup - deregister the audio component
561+
* @dev_priv: i915 device instance
562+
*
563+
* Deregisters the audio component, breaking any existing binding to the
564+
* corresponding snd_hda_intel driver's master component.
565+
*/
566+
void i915_audio_component_cleanup(struct drm_i915_private *dev_priv)
567+
{
568+
if (!dev_priv->audio_component_registered)
569+
return;
570+
571+
component_del(dev_priv->dev->dev, &i915_audio_component_bind_ops);
572+
dev_priv->audio_component_registered = false;
573+
}

drivers/gpu/drm/i915/intel_drv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,8 @@ void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire);
872872
void intel_init_audio(struct drm_device *dev);
873873
void intel_audio_codec_enable(struct intel_encoder *encoder);
874874
void intel_audio_codec_disable(struct intel_encoder *encoder);
875+
void i915_audio_component_init(struct drm_i915_private *dev_priv);
876+
void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
875877

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

drivers/gpu/drm/i915/intel_runtime_pm.c

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131

3232
#include "i915_drv.h"
3333
#include "intel_drv.h"
34-
#include <drm/i915_powerwell.h>
3534

3635
/**
3736
* DOC: runtime pm
@@ -50,8 +49,6 @@
5049
* present for a given platform.
5150
*/
5251

53-
static struct i915_power_domains *hsw_pwr;
54-
5552
#define for_each_power_well(i, power_well, domain_mask, power_domains) \
5653
for (i = 0; \
5754
i < (power_domains)->power_well_count && \
@@ -1071,10 +1068,8 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
10711068
*/
10721069
if (IS_HASWELL(dev_priv->dev)) {
10731070
set_power_wells(power_domains, hsw_power_wells);
1074-
hsw_pwr = power_domains;
10751071
} else if (IS_BROADWELL(dev_priv->dev)) {
10761072
set_power_wells(power_domains, bdw_power_wells);
1077-
hsw_pwr = power_domains;
10781073
} else if (IS_CHERRYVIEW(dev_priv->dev)) {
10791074
set_power_wells(power_domains, chv_power_wells);
10801075
} else if (IS_VALLEYVIEW(dev_priv->dev)) {
@@ -1118,8 +1113,6 @@ void intel_power_domains_fini(struct drm_i915_private *dev_priv)
11181113
* the power well is not enabled, so just enable it in case
11191114
* we're going to unload/reload. */
11201115
intel_display_set_init_power(dev_priv, true);
1121-
1122-
hsw_pwr = NULL;
11231116
}
11241117

11251118
static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
@@ -1328,52 +1321,3 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
13281321
pm_runtime_put_autosuspend(device);
13291322
}
13301323

1331-
/* Display audio driver power well request */
1332-
int i915_request_power_well(void)
1333-
{
1334-
struct drm_i915_private *dev_priv;
1335-
1336-
if (!hsw_pwr)
1337-
return -ENODEV;
1338-
1339-
dev_priv = container_of(hsw_pwr, struct drm_i915_private,
1340-
power_domains);
1341-
intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
1342-
return 0;
1343-
}
1344-
EXPORT_SYMBOL_GPL(i915_request_power_well);
1345-
1346-
/* Display audio driver power well release */
1347-
int i915_release_power_well(void)
1348-
{
1349-
struct drm_i915_private *dev_priv;
1350-
1351-
if (!hsw_pwr)
1352-
return -ENODEV;
1353-
1354-
dev_priv = container_of(hsw_pwr, struct drm_i915_private,
1355-
power_domains);
1356-
intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
1357-
return 0;
1358-
}
1359-
EXPORT_SYMBOL_GPL(i915_release_power_well);
1360-
1361-
/*
1362-
* Private interface for the audio driver to get CDCLK in kHz.
1363-
*
1364-
* Caller must request power well using i915_request_power_well() prior to
1365-
* making the call.
1366-
*/
1367-
int i915_get_cdclk_freq(void)
1368-
{
1369-
struct drm_i915_private *dev_priv;
1370-
1371-
if (!hsw_pwr)
1372-
return -ENODEV;
1373-
1374-
dev_priv = container_of(hsw_pwr, struct drm_i915_private,
1375-
power_domains);
1376-
1377-
return intel_ddi_get_cdclk_freq(dev_priv);
1378-
}
1379-
EXPORT_SYMBOL_GPL(i915_get_cdclk_freq);

include/drm/i915_component.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright © 2014 Intel Corporation
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a
5+
* copy of this software and associated documentation files (the "Software"),
6+
* to deal in the Software without restriction, including without limitation
7+
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8+
* and/or sell copies of the Software, and to permit persons to whom the
9+
* Software is furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice (including the next
12+
* paragraph) shall be included in all copies or substantial portions of the
13+
* Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18+
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21+
* IN THE SOFTWARE.
22+
*/
23+
24+
#ifndef _I915_COMPONENT_H_
25+
#define _I915_COMPONENT_H_
26+
27+
struct i915_audio_component {
28+
struct device *dev;
29+
30+
const struct i915_audio_component_ops {
31+
struct module *owner;
32+
void (*get_power)(struct device *);
33+
void (*put_power)(struct device *);
34+
int (*get_cdclk_freq)(struct device *);
35+
} *ops;
36+
};
37+
38+
#endif /* _I915_COMPONENT_H_ */

include/drm/i915_powerwell.h

Lines changed: 0 additions & 37 deletions
This file was deleted.

0 commit comments

Comments
 (0)