1 // SPDX-License-Identifier: GPL-2.0 2 // hdac_component.c - routines for sync between HD-A core and DRM driver 3 4 #include <linux/init.h> 5 #include <linux/module.h> 6 #include <linux/pci.h> 7 #include <linux/component.h> 8 #include <sound/core.h> 9 #include <sound/hdaudio.h> 10 #include <sound/hda_component.h> 11 #include <sound/hda_register.h> 12 13 static void hdac_acomp_release(struct device *dev, void *res) 14 { 15 } 16 17 static struct drm_audio_component *hdac_get_acomp(struct device *dev) 18 { 19 return devres_find(dev, hdac_acomp_release, NULL, NULL); 20 } 21 22 /** 23 * snd_hdac_set_codec_wakeup - Enable / disable HDMI/DP codec wakeup 24 * @bus: HDA core bus 25 * @enable: enable or disable the wakeup 26 * 27 * This function is supposed to be used only by a HD-audio controller 28 * driver that needs the interaction with graphics driver. 29 * 30 * This function should be called during the chip reset, also called at 31 * resume for updating STATESTS register read. 32 * 33 * Returns zero for success or a negative error code. 34 */ 35 int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) 36 { 37 struct drm_audio_component *acomp = bus->audio_component; 38 39 if (!acomp || !acomp->ops) 40 return -ENODEV; 41 42 if (!acomp->ops->codec_wake_override) 43 return 0; 44 45 dev_dbg(bus->dev, "%s codec wakeup\n", 46 enable ? "enable" : "disable"); 47 48 acomp->ops->codec_wake_override(acomp->dev, enable); 49 50 return 0; 51 } 52 EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup); 53 54 /** 55 * snd_hdac_display_power - Power up / down the power refcount 56 * @bus: HDA core bus 57 * @enable: power up or down 58 * 59 * This function is supposed to be used only by a HD-audio controller 60 * driver that needs the interaction with graphics driver. 61 * 62 * This function manages a refcount and calls the get_power() and 63 * put_power() ops accordingly, toggling the codec wakeup, too. 64 * 65 * Returns zero for success or a negative error code. 66 */ 67 int snd_hdac_display_power(struct hdac_bus *bus, bool enable) 68 { 69 struct drm_audio_component *acomp = bus->audio_component; 70 71 if (!acomp || !acomp->ops) 72 return -ENODEV; 73 74 dev_dbg(bus->dev, "display power %s\n", 75 enable ? "enable" : "disable"); 76 77 if (enable) { 78 if (!bus->drm_power_refcount++) { 79 if (acomp->ops->get_power) 80 acomp->ops->get_power(acomp->dev); 81 snd_hdac_set_codec_wakeup(bus, true); 82 snd_hdac_set_codec_wakeup(bus, false); 83 } 84 } 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 } 90 91 return 0; 92 } 93 EXPORT_SYMBOL_GPL(snd_hdac_display_power); 94 95 /** 96 * snd_hdac_sync_audio_rate - Set N/CTS based on the sample rate 97 * @codec: HDA codec 98 * @nid: the pin widget NID 99 * @dev_id: device identifier 100 * @rate: the sample rate to set 101 * 102 * This function is supposed to be used only by a HD-audio controller 103 * driver that needs the interaction with graphics driver. 104 * 105 * This function sets N/CTS value based on the given sample rate. 106 * Returns zero for success, or a negative error code. 107 */ 108 int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, 109 int dev_id, int rate) 110 { 111 struct hdac_bus *bus = codec->bus; 112 struct drm_audio_component *acomp = bus->audio_component; 113 int port, pipe; 114 115 if (!acomp || !acomp->ops || !acomp->ops->sync_audio_rate) 116 return -ENODEV; 117 port = nid; 118 if (acomp->audio_ops && acomp->audio_ops->pin2port) { 119 port = acomp->audio_ops->pin2port(codec, nid); 120 if (port < 0) 121 return -EINVAL; 122 } 123 pipe = dev_id; 124 return acomp->ops->sync_audio_rate(acomp->dev, port, pipe, rate); 125 } 126 EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate); 127 128 /** 129 * snd_hdac_acomp_get_eld - Get the audio state and ELD via component 130 * @codec: HDA codec 131 * @nid: the pin widget NID 132 * @dev_id: device identifier 133 * @audio_enabled: the pointer to store the current audio state 134 * @buffer: the buffer pointer to store ELD bytes 135 * @max_bytes: the max bytes to be stored on @buffer 136 * 137 * This function is supposed to be used only by a HD-audio controller 138 * driver that needs the interaction with graphics driver. 139 * 140 * This function queries the current state of the audio on the given 141 * digital port and fetches the ELD bytes onto the given buffer. 142 * It returns the number of bytes for the total ELD data, zero for 143 * invalid ELD, or a negative error code. 144 * 145 * The return size is the total bytes required for the whole ELD bytes, 146 * thus it may be over @max_bytes. If it's over @max_bytes, it implies 147 * that only a part of ELD bytes have been fetched. 148 */ 149 int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, 150 bool *audio_enabled, char *buffer, int max_bytes) 151 { 152 struct hdac_bus *bus = codec->bus; 153 struct drm_audio_component *acomp = bus->audio_component; 154 int port, pipe; 155 156 if (!acomp || !acomp->ops || !acomp->ops->get_eld) 157 return -ENODEV; 158 159 port = nid; 160 if (acomp->audio_ops && acomp->audio_ops->pin2port) { 161 port = acomp->audio_ops->pin2port(codec, nid); 162 if (port < 0) 163 return -EINVAL; 164 } 165 pipe = dev_id; 166 return acomp->ops->get_eld(acomp->dev, port, pipe, audio_enabled, 167 buffer, max_bytes); 168 } 169 EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld); 170 171 static int hdac_component_master_bind(struct device *dev) 172 { 173 struct drm_audio_component *acomp = hdac_get_acomp(dev); 174 int ret; 175 176 if (WARN_ON(!acomp)) 177 return -EINVAL; 178 179 ret = component_bind_all(dev, acomp); 180 if (ret < 0) 181 return ret; 182 183 if (WARN_ON(!(acomp->dev && acomp->ops))) { 184 ret = -EINVAL; 185 goto out_unbind; 186 } 187 188 /* pin the module to avoid dynamic unbinding, but only if given */ 189 if (!try_module_get(acomp->ops->owner)) { 190 ret = -ENODEV; 191 goto out_unbind; 192 } 193 194 if (acomp->audio_ops && acomp->audio_ops->master_bind) { 195 ret = acomp->audio_ops->master_bind(dev, acomp); 196 if (ret < 0) 197 goto module_put; 198 } 199 200 return 0; 201 202 module_put: 203 module_put(acomp->ops->owner); 204 out_unbind: 205 component_unbind_all(dev, acomp); 206 207 return ret; 208 } 209 210 static void hdac_component_master_unbind(struct device *dev) 211 { 212 struct drm_audio_component *acomp = hdac_get_acomp(dev); 213 214 if (acomp->audio_ops && acomp->audio_ops->master_unbind) 215 acomp->audio_ops->master_unbind(dev, acomp); 216 module_put(acomp->ops->owner); 217 component_unbind_all(dev, acomp); 218 WARN_ON(acomp->ops || acomp->dev); 219 } 220 221 static const struct component_master_ops hdac_component_master_ops = { 222 .bind = hdac_component_master_bind, 223 .unbind = hdac_component_master_unbind, 224 }; 225 226 /** 227 * snd_hdac_acomp_register_notifier - Register audio component ops 228 * @bus: HDA core bus 229 * @aops: audio component ops 230 * 231 * This function is supposed to be used only by a HD-audio controller 232 * driver that needs the interaction with graphics driver. 233 * 234 * This function sets the given ops to be called by the graphics driver. 235 * 236 * Returns zero for success or a negative error code. 237 */ 238 int snd_hdac_acomp_register_notifier(struct hdac_bus *bus, 239 const struct drm_audio_component_audio_ops *aops) 240 { 241 if (!bus->audio_component) 242 return -ENODEV; 243 244 bus->audio_component->audio_ops = aops; 245 return 0; 246 } 247 EXPORT_SYMBOL_GPL(snd_hdac_acomp_register_notifier); 248 249 /** 250 * snd_hdac_acomp_init - Initialize audio component 251 * @bus: HDA core bus 252 * @match_master: match function for finding components 253 * @extra_size: Extra bytes to allocate 254 * 255 * This function is supposed to be used only by a HD-audio controller 256 * driver that needs the interaction with graphics driver. 257 * 258 * This function initializes and sets up the audio component to communicate 259 * with graphics driver. 260 * 261 * Unlike snd_hdac_i915_init(), this function doesn't synchronize with the 262 * binding with the DRM component. Each caller needs to sync via master_bind 263 * audio_ops. 264 * 265 * Returns zero for success or a negative error code. 266 */ 267 int snd_hdac_acomp_init(struct hdac_bus *bus, 268 const struct drm_audio_component_audio_ops *aops, 269 int (*match_master)(struct device *, void *), 270 size_t extra_size) 271 { 272 struct component_match *match = NULL; 273 struct device *dev = bus->dev; 274 struct drm_audio_component *acomp; 275 int ret; 276 277 if (WARN_ON(hdac_get_acomp(dev))) 278 return -EBUSY; 279 280 acomp = devres_alloc(hdac_acomp_release, sizeof(*acomp) + extra_size, 281 GFP_KERNEL); 282 if (!acomp) 283 return -ENOMEM; 284 acomp->audio_ops = aops; 285 bus->audio_component = acomp; 286 devres_add(dev, acomp); 287 288 component_match_add(dev, &match, match_master, bus); 289 ret = component_master_add_with_match(dev, &hdac_component_master_ops, 290 match); 291 if (ret < 0) 292 goto out_err; 293 294 return 0; 295 296 out_err: 297 bus->audio_component = NULL; 298 devres_destroy(dev, hdac_acomp_release, NULL, NULL); 299 dev_info(dev, "failed to add audio component master (%d)\n", ret); 300 301 return ret; 302 } 303 EXPORT_SYMBOL_GPL(snd_hdac_acomp_init); 304 305 /** 306 * snd_hdac_acomp_exit - Finalize audio component 307 * @bus: HDA core bus 308 * 309 * This function is supposed to be used only by a HD-audio controller 310 * driver that needs the interaction with graphics driver. 311 * 312 * This function releases the audio component that has been used. 313 * 314 * Returns zero for success or a negative error code. 315 */ 316 int snd_hdac_acomp_exit(struct hdac_bus *bus) 317 { 318 struct device *dev = bus->dev; 319 struct drm_audio_component *acomp = bus->audio_component; 320 321 if (!acomp) 322 return 0; 323 324 WARN_ON(bus->drm_power_refcount); 325 if (bus->drm_power_refcount > 0 && acomp->ops) 326 acomp->ops->put_power(acomp->dev); 327 328 component_master_del(dev, &hdac_component_master_ops); 329 330 bus->audio_component = NULL; 331 devres_destroy(dev, hdac_acomp_release, NULL, NULL); 332 333 return 0; 334 } 335 EXPORT_SYMBOL_GPL(snd_hdac_acomp_exit); 336