0001
0002
0003
0004 #include <linux/init.h>
0005 #include <linux/module.h>
0006 #include <linux/pci.h>
0007 #include <linux/component.h>
0008 #include <sound/core.h>
0009 #include <sound/hdaudio.h>
0010 #include <sound/hda_component.h>
0011 #include <sound/hda_register.h>
0012
0013 static void hdac_acomp_release(struct device *dev, void *res)
0014 {
0015 }
0016
0017 static struct drm_audio_component *hdac_get_acomp(struct device *dev)
0018 {
0019 return devres_find(dev, hdac_acomp_release, NULL, NULL);
0020 }
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable)
0036 {
0037 struct drm_audio_component *acomp = bus->audio_component;
0038
0039 if (!acomp || !acomp->ops)
0040 return -ENODEV;
0041
0042 if (!acomp->ops->codec_wake_override)
0043 return 0;
0044
0045 dev_dbg(bus->dev, "%s codec wakeup\n",
0046 enable ? "enable" : "disable");
0047
0048 acomp->ops->codec_wake_override(acomp->dev, enable);
0049
0050 return 0;
0051 }
0052 EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup);
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066 void snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable)
0067 {
0068 struct drm_audio_component *acomp = bus->audio_component;
0069
0070 dev_dbg(bus->dev, "display power %s\n",
0071 enable ? "enable" : "disable");
0072
0073 mutex_lock(&bus->lock);
0074 if (enable)
0075 set_bit(idx, &bus->display_power_status);
0076 else
0077 clear_bit(idx, &bus->display_power_status);
0078
0079 if (!acomp || !acomp->ops)
0080 goto unlock;
0081
0082 if (bus->display_power_status) {
0083 if (!bus->display_power_active) {
0084 unsigned long cookie = -1;
0085
0086 if (acomp->ops->get_power)
0087 cookie = acomp->ops->get_power(acomp->dev);
0088
0089 snd_hdac_set_codec_wakeup(bus, true);
0090 snd_hdac_set_codec_wakeup(bus, false);
0091 bus->display_power_active = cookie;
0092 }
0093 } else {
0094 if (bus->display_power_active) {
0095 unsigned long cookie = bus->display_power_active;
0096
0097 if (acomp->ops->put_power)
0098 acomp->ops->put_power(acomp->dev, cookie);
0099
0100 bus->display_power_active = 0;
0101 }
0102 }
0103 unlock:
0104 mutex_unlock(&bus->lock);
0105 }
0106 EXPORT_SYMBOL_GPL(snd_hdac_display_power);
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121 int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid,
0122 int dev_id, int rate)
0123 {
0124 struct hdac_bus *bus = codec->bus;
0125 struct drm_audio_component *acomp = bus->audio_component;
0126 int port, pipe;
0127
0128 if (!acomp || !acomp->ops || !acomp->ops->sync_audio_rate)
0129 return -ENODEV;
0130 port = nid;
0131 if (acomp->audio_ops && acomp->audio_ops->pin2port) {
0132 port = acomp->audio_ops->pin2port(codec, nid);
0133 if (port < 0)
0134 return -EINVAL;
0135 }
0136 pipe = dev_id;
0137 return acomp->ops->sync_audio_rate(acomp->dev, port, pipe, rate);
0138 }
0139 EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate);
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162 int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id,
0163 bool *audio_enabled, char *buffer, int max_bytes)
0164 {
0165 struct hdac_bus *bus = codec->bus;
0166 struct drm_audio_component *acomp = bus->audio_component;
0167 int port, pipe;
0168
0169 if (!acomp || !acomp->ops || !acomp->ops->get_eld)
0170 return -ENODEV;
0171
0172 port = nid;
0173 if (acomp->audio_ops && acomp->audio_ops->pin2port) {
0174 port = acomp->audio_ops->pin2port(codec, nid);
0175 if (port < 0)
0176 return -EINVAL;
0177 }
0178 pipe = dev_id;
0179 return acomp->ops->get_eld(acomp->dev, port, pipe, audio_enabled,
0180 buffer, max_bytes);
0181 }
0182 EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld);
0183
0184 static int hdac_component_master_bind(struct device *dev)
0185 {
0186 struct drm_audio_component *acomp = hdac_get_acomp(dev);
0187 int ret;
0188
0189 if (WARN_ON(!acomp))
0190 return -EINVAL;
0191
0192 ret = component_bind_all(dev, acomp);
0193 if (ret < 0)
0194 return ret;
0195
0196 if (WARN_ON(!(acomp->dev && acomp->ops))) {
0197 ret = -EINVAL;
0198 goto out_unbind;
0199 }
0200
0201
0202 if (!try_module_get(acomp->ops->owner)) {
0203 ret = -ENODEV;
0204 goto out_unbind;
0205 }
0206
0207 if (acomp->audio_ops && acomp->audio_ops->master_bind) {
0208 ret = acomp->audio_ops->master_bind(dev, acomp);
0209 if (ret < 0)
0210 goto module_put;
0211 }
0212
0213 complete_all(&acomp->master_bind_complete);
0214 return 0;
0215
0216 module_put:
0217 module_put(acomp->ops->owner);
0218 out_unbind:
0219 component_unbind_all(dev, acomp);
0220 complete_all(&acomp->master_bind_complete);
0221
0222 return ret;
0223 }
0224
0225 static void hdac_component_master_unbind(struct device *dev)
0226 {
0227 struct drm_audio_component *acomp = hdac_get_acomp(dev);
0228
0229 if (acomp->audio_ops && acomp->audio_ops->master_unbind)
0230 acomp->audio_ops->master_unbind(dev, acomp);
0231 module_put(acomp->ops->owner);
0232 component_unbind_all(dev, acomp);
0233 WARN_ON(acomp->ops || acomp->dev);
0234 }
0235
0236 static const struct component_master_ops hdac_component_master_ops = {
0237 .bind = hdac_component_master_bind,
0238 .unbind = hdac_component_master_unbind,
0239 };
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253 int snd_hdac_acomp_register_notifier(struct hdac_bus *bus,
0254 const struct drm_audio_component_audio_ops *aops)
0255 {
0256 if (!bus->audio_component)
0257 return -ENODEV;
0258
0259 bus->audio_component->audio_ops = aops;
0260 return 0;
0261 }
0262 EXPORT_SYMBOL_GPL(snd_hdac_acomp_register_notifier);
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283 int snd_hdac_acomp_init(struct hdac_bus *bus,
0284 const struct drm_audio_component_audio_ops *aops,
0285 int (*match_master)(struct device *, int, void *),
0286 size_t extra_size)
0287 {
0288 struct component_match *match = NULL;
0289 struct device *dev = bus->dev;
0290 struct drm_audio_component *acomp;
0291 int ret;
0292
0293 if (WARN_ON(hdac_get_acomp(dev)))
0294 return -EBUSY;
0295
0296 acomp = devres_alloc(hdac_acomp_release, sizeof(*acomp) + extra_size,
0297 GFP_KERNEL);
0298 if (!acomp)
0299 return -ENOMEM;
0300 acomp->audio_ops = aops;
0301 init_completion(&acomp->master_bind_complete);
0302 bus->audio_component = acomp;
0303 devres_add(dev, acomp);
0304
0305 component_match_add_typed(dev, &match, match_master, bus);
0306 ret = component_master_add_with_match(dev, &hdac_component_master_ops,
0307 match);
0308 if (ret < 0)
0309 goto out_err;
0310
0311 return 0;
0312
0313 out_err:
0314 bus->audio_component = NULL;
0315 devres_destroy(dev, hdac_acomp_release, NULL, NULL);
0316 dev_info(dev, "failed to add audio component master (%d)\n", ret);
0317
0318 return ret;
0319 }
0320 EXPORT_SYMBOL_GPL(snd_hdac_acomp_init);
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333 int snd_hdac_acomp_exit(struct hdac_bus *bus)
0334 {
0335 struct device *dev = bus->dev;
0336 struct drm_audio_component *acomp = bus->audio_component;
0337
0338 if (!acomp)
0339 return 0;
0340
0341 if (WARN_ON(bus->display_power_active) && acomp->ops)
0342 acomp->ops->put_power(acomp->dev, bus->display_power_active);
0343
0344 bus->display_power_active = 0;
0345 bus->display_power_status = 0;
0346
0347 component_master_del(dev, &hdac_component_master_ops);
0348
0349 bus->audio_component = NULL;
0350 devres_destroy(dev, hdac_acomp_release, NULL, NULL);
0351
0352 return 0;
0353 }
0354 EXPORT_SYMBOL_GPL(snd_hdac_acomp_exit);