0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063 #include <linux/acpi.h>
0064 #include <linux/delay.h>
0065 #include <linux/device.h>
0066 #include <linux/irq.h>
0067 #include <linux/pci.h>
0068 #include <linux/platform_device.h>
0069 #include <linux/pm_runtime.h>
0070
0071 #include <drm/intel_lpe_audio.h>
0072
0073 #include "i915_drv.h"
0074 #include "intel_de.h"
0075 #include "intel_lpe_audio.h"
0076
0077 #define HAS_LPE_AUDIO(dev_priv) ((dev_priv)->audio.lpe.platdev != NULL)
0078
0079 static struct platform_device *
0080 lpe_audio_platdev_create(struct drm_i915_private *dev_priv)
0081 {
0082 struct drm_device *dev = &dev_priv->drm;
0083 struct pci_dev *pdev = to_pci_dev(dev->dev);
0084 struct platform_device_info pinfo = {};
0085 struct resource *rsc;
0086 struct platform_device *platdev;
0087 struct intel_hdmi_lpe_audio_pdata *pdata;
0088
0089 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
0090 if (!pdata)
0091 return ERR_PTR(-ENOMEM);
0092
0093 rsc = kcalloc(2, sizeof(*rsc), GFP_KERNEL);
0094 if (!rsc) {
0095 kfree(pdata);
0096 return ERR_PTR(-ENOMEM);
0097 }
0098
0099 rsc[0].start = rsc[0].end = dev_priv->audio.lpe.irq;
0100 rsc[0].flags = IORESOURCE_IRQ;
0101 rsc[0].name = "hdmi-lpe-audio-irq";
0102
0103 rsc[1].start = pci_resource_start(pdev, 0) +
0104 I915_HDMI_LPE_AUDIO_BASE;
0105 rsc[1].end = pci_resource_start(pdev, 0) +
0106 I915_HDMI_LPE_AUDIO_BASE + I915_HDMI_LPE_AUDIO_SIZE - 1;
0107 rsc[1].flags = IORESOURCE_MEM;
0108 rsc[1].name = "hdmi-lpe-audio-mmio";
0109
0110 pinfo.parent = dev->dev;
0111 pinfo.name = "hdmi-lpe-audio";
0112 pinfo.id = -1;
0113 pinfo.res = rsc;
0114 pinfo.num_res = 2;
0115 pinfo.data = pdata;
0116 pinfo.size_data = sizeof(*pdata);
0117 pinfo.dma_mask = DMA_BIT_MASK(32);
0118
0119 pdata->num_pipes = INTEL_NUM_PIPES(dev_priv);
0120 pdata->num_ports = IS_CHERRYVIEW(dev_priv) ? 3 : 2;
0121 pdata->port[0].pipe = -1;
0122 pdata->port[1].pipe = -1;
0123 pdata->port[2].pipe = -1;
0124 spin_lock_init(&pdata->lpe_audio_slock);
0125
0126 platdev = platform_device_register_full(&pinfo);
0127 kfree(rsc);
0128 kfree(pdata);
0129
0130 if (IS_ERR(platdev)) {
0131 drm_err(&dev_priv->drm,
0132 "Failed to allocate LPE audio platform device\n");
0133 return platdev;
0134 }
0135
0136 pm_runtime_no_callbacks(&platdev->dev);
0137
0138 return platdev;
0139 }
0140
0141 static void lpe_audio_platdev_destroy(struct drm_i915_private *dev_priv)
0142 {
0143
0144
0145
0146
0147
0148
0149
0150
0151 platform_device_unregister(dev_priv->audio.lpe.platdev);
0152 }
0153
0154 static void lpe_audio_irq_unmask(struct irq_data *d)
0155 {
0156 }
0157
0158 static void lpe_audio_irq_mask(struct irq_data *d)
0159 {
0160 }
0161
0162 static struct irq_chip lpe_audio_irqchip = {
0163 .name = "hdmi_lpe_audio_irqchip",
0164 .irq_mask = lpe_audio_irq_mask,
0165 .irq_unmask = lpe_audio_irq_unmask,
0166 };
0167
0168 static int lpe_audio_irq_init(struct drm_i915_private *dev_priv)
0169 {
0170 int irq = dev_priv->audio.lpe.irq;
0171
0172 drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv));
0173 irq_set_chip_and_handler_name(irq,
0174 &lpe_audio_irqchip,
0175 handle_simple_irq,
0176 "hdmi_lpe_audio_irq_handler");
0177
0178 return irq_set_chip_data(irq, dev_priv);
0179 }
0180
0181 static bool lpe_audio_detect(struct drm_i915_private *dev_priv)
0182 {
0183 int lpe_present = false;
0184
0185 if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
0186 static const struct pci_device_id atom_hdaudio_ids[] = {
0187
0188 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0f04)},
0189
0190 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2284)},
0191 {}
0192 };
0193
0194 if (!pci_dev_present(atom_hdaudio_ids)) {
0195 drm_info(&dev_priv->drm,
0196 "HDaudio controller not detected, using LPE audio instead\n");
0197 lpe_present = true;
0198 }
0199 }
0200 return lpe_present;
0201 }
0202
0203 static int lpe_audio_setup(struct drm_i915_private *dev_priv)
0204 {
0205 int ret;
0206
0207 dev_priv->audio.lpe.irq = irq_alloc_desc(0);
0208 if (dev_priv->audio.lpe.irq < 0) {
0209 drm_err(&dev_priv->drm, "Failed to allocate IRQ desc: %d\n",
0210 dev_priv->audio.lpe.irq);
0211 ret = dev_priv->audio.lpe.irq;
0212 goto err;
0213 }
0214
0215 drm_dbg(&dev_priv->drm, "irq = %d\n", dev_priv->audio.lpe.irq);
0216
0217 ret = lpe_audio_irq_init(dev_priv);
0218
0219 if (ret) {
0220 drm_err(&dev_priv->drm,
0221 "Failed to initialize irqchip for lpe audio: %d\n",
0222 ret);
0223 goto err_free_irq;
0224 }
0225
0226 dev_priv->audio.lpe.platdev = lpe_audio_platdev_create(dev_priv);
0227
0228 if (IS_ERR(dev_priv->audio.lpe.platdev)) {
0229 ret = PTR_ERR(dev_priv->audio.lpe.platdev);
0230 drm_err(&dev_priv->drm,
0231 "Failed to create lpe audio platform device: %d\n",
0232 ret);
0233 goto err_free_irq;
0234 }
0235
0236
0237
0238
0239 intel_de_write(dev_priv, VLV_AUD_CHICKEN_BIT_REG,
0240 VLV_CHICKEN_BIT_DBG_ENABLE);
0241
0242 return 0;
0243 err_free_irq:
0244 irq_free_desc(dev_priv->audio.lpe.irq);
0245 err:
0246 dev_priv->audio.lpe.irq = -1;
0247 dev_priv->audio.lpe.platdev = NULL;
0248 return ret;
0249 }
0250
0251
0252
0253
0254
0255
0256
0257
0258 void intel_lpe_audio_irq_handler(struct drm_i915_private *dev_priv)
0259 {
0260 int ret;
0261
0262 if (!HAS_LPE_AUDIO(dev_priv))
0263 return;
0264
0265 ret = generic_handle_irq(dev_priv->audio.lpe.irq);
0266 if (ret)
0267 drm_err_ratelimited(&dev_priv->drm,
0268 "error handling LPE audio irq: %d\n", ret);
0269 }
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279 int intel_lpe_audio_init(struct drm_i915_private *dev_priv)
0280 {
0281 int ret = -ENODEV;
0282
0283 if (lpe_audio_detect(dev_priv)) {
0284 ret = lpe_audio_setup(dev_priv);
0285 if (ret < 0)
0286 drm_err(&dev_priv->drm,
0287 "failed to setup LPE Audio bridge\n");
0288 }
0289 return ret;
0290 }
0291
0292
0293
0294
0295
0296
0297
0298
0299 void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv)
0300 {
0301 if (!HAS_LPE_AUDIO(dev_priv))
0302 return;
0303
0304 lpe_audio_platdev_destroy(dev_priv);
0305
0306 irq_free_desc(dev_priv->audio.lpe.irq);
0307
0308 dev_priv->audio.lpe.irq = -1;
0309 dev_priv->audio.lpe.platdev = NULL;
0310 }
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324 void intel_lpe_audio_notify(struct drm_i915_private *dev_priv,
0325 enum pipe pipe, enum port port,
0326 const void *eld, int ls_clock, bool dp_output)
0327 {
0328 unsigned long irqflags;
0329 struct intel_hdmi_lpe_audio_pdata *pdata;
0330 struct intel_hdmi_lpe_audio_port_pdata *ppdata;
0331 u32 audio_enable;
0332
0333 if (!HAS_LPE_AUDIO(dev_priv))
0334 return;
0335
0336 pdata = dev_get_platdata(&dev_priv->audio.lpe.platdev->dev);
0337 ppdata = &pdata->port[port - PORT_B];
0338
0339 spin_lock_irqsave(&pdata->lpe_audio_slock, irqflags);
0340
0341 audio_enable = intel_de_read(dev_priv, VLV_AUD_PORT_EN_DBG(port));
0342
0343 if (eld != NULL) {
0344 memcpy(ppdata->eld, eld, HDMI_MAX_ELD_BYTES);
0345 ppdata->pipe = pipe;
0346 ppdata->ls_clock = ls_clock;
0347 ppdata->dp_output = dp_output;
0348
0349
0350 intel_de_write(dev_priv, VLV_AUD_PORT_EN_DBG(port),
0351 audio_enable & ~VLV_AMP_MUTE);
0352 } else {
0353 memset(ppdata->eld, 0, HDMI_MAX_ELD_BYTES);
0354 ppdata->pipe = -1;
0355 ppdata->ls_clock = 0;
0356 ppdata->dp_output = false;
0357
0358
0359 intel_de_write(dev_priv, VLV_AUD_PORT_EN_DBG(port),
0360 audio_enable | VLV_AMP_MUTE);
0361 }
0362
0363 if (pdata->notify_audio_lpe)
0364 pdata->notify_audio_lpe(dev_priv->audio.lpe.platdev, port - PORT_B);
0365
0366 spin_unlock_irqrestore(&pdata->lpe_audio_slock, irqflags);
0367 }