aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_i915.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/hda_i915.c')
-rw-r--r--sound/pci/hda/hda_i915.c154
1 files changed, 107 insertions, 47 deletions
diff --git a/sound/pci/hda/hda_i915.c b/sound/pci/hda/hda_i915.c
index d4d0375ac181..714894527e06 100644
--- a/sound/pci/hda/hda_i915.c
+++ b/sound/pci/hda/hda_i915.c
@@ -18,10 +18,12 @@
18 18
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/pci.h>
22#include <linux/component.h>
23#include <drm/i915_component.h>
21#include <sound/core.h> 24#include <sound/core.h>
22#include <drm/i915_powerwell.h>
23#include "hda_priv.h" 25#include "hda_priv.h"
24#include "hda_i915.h" 26#include "hda_intel.h"
25 27
26/* Intel HSW/BDW display HDA controller Extended Mode registers. 28/* Intel HSW/BDW display HDA controller Extended Mode registers.
27 * EM4 (M value) and EM5 (N Value) are used to convert CDClk (Core Display 29 * EM4 (M value) and EM5 (N Value) are used to convert CDClk (Core Display
@@ -31,32 +33,33 @@
31#define AZX_REG_EM4 0x100c 33#define AZX_REG_EM4 0x100c
32#define AZX_REG_EM5 0x1010 34#define AZX_REG_EM5 0x1010
33 35
34static int (*get_power)(void); 36int hda_display_power(struct hda_intel *hda, bool enable)
35static int (*put_power)(void);
36static int (*get_cdclk)(void);
37
38int hda_display_power(bool enable)
39{ 37{
40 if (!get_power || !put_power) 38 struct i915_audio_component *acomp = &hda->audio_component;
39
40 if (!acomp->ops)
41 return -ENODEV; 41 return -ENODEV;
42 42
43 pr_debug("HDA display power %s \n", 43 dev_dbg(&hda->chip.pci->dev, "display power %s\n",
44 enable ? "Enable" : "Disable"); 44 enable ? "enable" : "disable");
45 if (enable) 45 if (enable)
46 return get_power(); 46 acomp->ops->get_power(acomp->dev);
47 else 47 else
48 return put_power(); 48 acomp->ops->put_power(acomp->dev);
49
50 return 0;
49} 51}
50 52
51void haswell_set_bclk(struct azx *chip) 53void haswell_set_bclk(struct hda_intel *hda)
52{ 54{
53 int cdclk_freq; 55 int cdclk_freq;
54 unsigned int bclk_m, bclk_n; 56 unsigned int bclk_m, bclk_n;
57 struct i915_audio_component *acomp = &hda->audio_component;
55 58
56 if (!get_cdclk) 59 if (!acomp->ops)
57 return; 60 return;
58 61
59 cdclk_freq = get_cdclk(); 62 cdclk_freq = acomp->ops->get_cdclk_freq(acomp->dev);
60 switch (cdclk_freq) { 63 switch (cdclk_freq) {
61 case 337500: 64 case 337500:
62 bclk_m = 16; 65 bclk_m = 16;
@@ -80,51 +83,108 @@ void haswell_set_bclk(struct azx *chip)
80 break; 83 break;
81 } 84 }
82 85
83 azx_writew(chip, EM4, bclk_m); 86 azx_writew(&hda->chip, EM4, bclk_m);
84 azx_writew(chip, EM5, bclk_n); 87 azx_writew(&hda->chip, EM5, bclk_n);
85} 88}
86 89
87 90static int hda_component_master_bind(struct device *dev)
88int hda_i915_init(void)
89{ 91{
90 int err = 0; 92 struct snd_card *card = dev_get_drvdata(dev);
91 93 struct azx *chip = card->private_data;
92 get_power = symbol_request(i915_request_power_well); 94 struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
93 if (!get_power) { 95 struct i915_audio_component *acomp = &hda->audio_component;
94 pr_warn("hda-i915: get_power symbol get fail\n"); 96 int ret;
95 return -ENODEV; 97
98 ret = component_bind_all(dev, acomp);
99 if (ret < 0)
100 return ret;
101
102 if (WARN_ON(!(acomp->dev && acomp->ops && acomp->ops->get_power &&
103 acomp->ops->put_power && acomp->ops->get_cdclk_freq))) {
104 ret = -EINVAL;
105 goto out_unbind;
96 } 106 }
97 107
98 put_power = symbol_request(i915_release_power_well); 108 /*
99 if (!put_power) { 109 * Atm, we don't support dynamic unbinding initiated by the child
100 symbol_put(i915_request_power_well); 110 * component, so pin its containing module until we unbind.
101 get_power = NULL; 111 */
102 return -ENODEV; 112 if (!try_module_get(acomp->ops->owner)) {
113 ret = -ENODEV;
114 goto out_unbind;
103 } 115 }
104 116
105 get_cdclk = symbol_request(i915_get_cdclk_freq); 117 return 0;
106 if (!get_cdclk) /* may have abnormal BCLK and audio playback rate */
107 pr_warn("hda-i915: get_cdclk symbol get fail\n");
108 118
109 pr_debug("HDA driver get symbol successfully from i915 module\n"); 119out_unbind:
120 component_unbind_all(dev, acomp);
110 121
111 return err; 122 return ret;
112} 123}
113 124
114int hda_i915_exit(void) 125static void hda_component_master_unbind(struct device *dev)
115{ 126{
116 if (get_power) { 127 struct snd_card *card = dev_get_drvdata(dev);
117 symbol_put(i915_request_power_well); 128 struct azx *chip = card->private_data;
118 get_power = NULL; 129 struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
119 } 130 struct i915_audio_component *acomp = &hda->audio_component;
120 if (put_power) { 131
121 symbol_put(i915_release_power_well); 132 module_put(acomp->ops->owner);
122 put_power = NULL; 133 component_unbind_all(dev, acomp);
123 } 134 WARN_ON(acomp->ops || acomp->dev);
124 if (get_cdclk) { 135}
125 symbol_put(i915_get_cdclk_freq); 136
126 get_cdclk = NULL; 137static const struct component_master_ops hda_component_master_ops = {
138 .bind = hda_component_master_bind,
139 .unbind = hda_component_master_unbind,
140};
141
142static int hda_component_master_match(struct device *dev, void *data)
143{
144 /* i915 is the only supported component */
145 return !strcmp(dev->driver->name, "i915");
146}
147
148int hda_i915_init(struct hda_intel *hda)
149{
150 struct component_match *match = NULL;
151 struct device *dev = &hda->chip.pci->dev;
152 struct i915_audio_component *acomp = &hda->audio_component;
153 int ret;
154
155 component_match_add(dev, &match, hda_component_master_match, hda);
156 ret = component_master_add_with_match(dev, &hda_component_master_ops,
157 match);
158 if (ret < 0)
159 goto out_err;
160
161 /*
162 * Atm, we don't support deferring the component binding, so make sure
163 * i915 is loaded and that the binding successfully completes.
164 */
165 request_module("i915");
166
167 if (!acomp->ops) {
168 ret = -ENODEV;
169 goto out_master_del;
127 } 170 }
128 171
172 dev_dbg(dev, "bound to i915 component master\n");
173
174 return 0;
175out_master_del:
176 component_master_del(dev, &hda_component_master_ops);
177out_err:
178 dev_err(dev, "failed to add i915 component master (%d)\n", ret);
179
180 return ret;
181}
182
183int hda_i915_exit(struct hda_intel *hda)
184{
185 struct device *dev = &hda->chip.pci->dev;
186
187 component_master_del(dev, &hda_component_master_ops);
188
129 return 0; 189 return 0;
130} 190}