hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/sound/hda/hdac_component.c
....@@ -54,41 +54,54 @@
5454 /**
5555 * snd_hdac_display_power - Power up / down the power refcount
5656 * @bus: HDA core bus
57
+ * @idx: HDA codec address, pass HDA_CODEC_IDX_CONTROLLER for controller
5758 * @enable: power up or down
5859 *
59
- * This function is supposed to be used only by a HD-audio controller
60
- * driver that needs the interaction with graphics driver.
60
+ * This function is used by either HD-audio controller or codec driver that
61
+ * needs the interaction with graphics driver.
6162 *
62
- * This function manages a refcount and calls the get_power() and
63
+ * This function updates the power status, and calls the get_power() and
6364 * put_power() ops accordingly, toggling the codec wakeup, too.
64
- *
65
- * Returns zero for success or a negative error code.
6665 */
67
-int snd_hdac_display_power(struct hdac_bus *bus, bool enable)
66
+void snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable)
6867 {
6968 struct drm_audio_component *acomp = bus->audio_component;
70
-
71
- if (!acomp || !acomp->ops)
72
- return -ENODEV;
7369
7470 dev_dbg(bus->dev, "display power %s\n",
7571 enable ? "enable" : "disable");
7672
77
- if (enable) {
78
- if (!bus->drm_power_refcount++) {
73
+ mutex_lock(&bus->lock);
74
+ if (enable)
75
+ set_bit(idx, &bus->display_power_status);
76
+ else
77
+ clear_bit(idx, &bus->display_power_status);
78
+
79
+ if (!acomp || !acomp->ops)
80
+ goto unlock;
81
+
82
+ if (bus->display_power_status) {
83
+ if (!bus->display_power_active) {
84
+ unsigned long cookie = -1;
85
+
7986 if (acomp->ops->get_power)
80
- acomp->ops->get_power(acomp->dev);
87
+ cookie = acomp->ops->get_power(acomp->dev);
88
+
8189 snd_hdac_set_codec_wakeup(bus, true);
8290 snd_hdac_set_codec_wakeup(bus, false);
91
+ bus->display_power_active = cookie;
8392 }
8493 } else {
85
- WARN_ON(!bus->drm_power_refcount);
86
- if (!--bus->drm_power_refcount)
87
- if (acomp->ops->put_power)
88
- acomp->ops->put_power(acomp->dev);
89
- }
94
+ if (bus->display_power_active) {
95
+ unsigned long cookie = bus->display_power_active;
9096
91
- return 0;
97
+ if (acomp->ops->put_power)
98
+ acomp->ops->put_power(acomp->dev, cookie);
99
+
100
+ bus->display_power_active = 0;
101
+ }
102
+ }
103
+ unlock:
104
+ mutex_unlock(&bus->lock);
92105 }
93106 EXPORT_SYMBOL_GPL(snd_hdac_display_power);
94107
....@@ -197,12 +210,14 @@
197210 goto module_put;
198211 }
199212
213
+ complete_all(&acomp->master_bind_complete);
200214 return 0;
201215
202216 module_put:
203217 module_put(acomp->ops->owner);
204218 out_unbind:
205219 component_unbind_all(dev, acomp);
220
+ complete_all(&acomp->master_bind_complete);
206221
207222 return ret;
208223 }
....@@ -249,6 +264,7 @@
249264 /**
250265 * snd_hdac_acomp_init - Initialize audio component
251266 * @bus: HDA core bus
267
+ * @aops: audio component ops
252268 * @match_master: match function for finding components
253269 * @extra_size: Extra bytes to allocate
254270 *
....@@ -266,7 +282,7 @@
266282 */
267283 int snd_hdac_acomp_init(struct hdac_bus *bus,
268284 const struct drm_audio_component_audio_ops *aops,
269
- int (*match_master)(struct device *, void *),
285
+ int (*match_master)(struct device *, int, void *),
270286 size_t extra_size)
271287 {
272288 struct component_match *match = NULL;
....@@ -282,10 +298,11 @@
282298 if (!acomp)
283299 return -ENOMEM;
284300 acomp->audio_ops = aops;
301
+ init_completion(&acomp->master_bind_complete);
285302 bus->audio_component = acomp;
286303 devres_add(dev, acomp);
287304
288
- component_match_add(dev, &match, match_master, bus);
305
+ component_match_add_typed(dev, &match, match_master, bus);
289306 ret = component_master_add_with_match(dev, &hdac_component_master_ops,
290307 match);
291308 if (ret < 0)
....@@ -321,9 +338,11 @@
321338 if (!acomp)
322339 return 0;
323340
324
- WARN_ON(bus->drm_power_refcount);
325
- if (bus->drm_power_refcount > 0 && acomp->ops)
326
- acomp->ops->put_power(acomp->dev);
341
+ if (WARN_ON(bus->display_power_active) && acomp->ops)
342
+ acomp->ops->put_power(acomp->dev, bus->display_power_active);
343
+
344
+ bus->display_power_active = 0;
345
+ bus->display_power_status = 0;
327346
328347 component_master_del(dev, &hdac_component_master_ops);
329348