linux/sound/hda/hdac_i915.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  hdac_i915.c - routines for sync between HD-A core and i915 display driver
   4 */
   5
   6#include <linux/init.h>
   7#include <linux/module.h>
   8#include <linux/pci.h>
   9#include <sound/core.h>
  10#include <sound/hdaudio.h>
  11#include <sound/hda_i915.h>
  12#include <sound/hda_register.h>
  13
  14static struct completion bind_complete;
  15
  16#define CONTROLLER_IN_GPU(pci) (((pci)->device == 0x0a0c) || \
  17                                ((pci)->device == 0x0c0c) || \
  18                                ((pci)->device == 0x0d0c) || \
  19                                ((pci)->device == 0x160c))
  20
  21/**
  22 * snd_hdac_i915_set_bclk - Reprogram BCLK for HSW/BDW
  23 * @bus: HDA core bus
  24 *
  25 * Intel HSW/BDW display HDA controller is in GPU. Both its power and link BCLK
  26 * depends on GPU. Two Extended Mode registers EM4 (M value) and EM5 (N Value)
  27 * are used to convert CDClk (Core Display Clock) to 24MHz BCLK:
  28 * BCLK = CDCLK * M / N
  29 * The values will be lost when the display power well is disabled and need to
  30 * be restored to avoid abnormal playback speed.
  31 *
  32 * Call this function at initializing and changing power well, as well as
  33 * at ELD notifier for the hotplug.
  34 */
  35void snd_hdac_i915_set_bclk(struct hdac_bus *bus)
  36{
  37        struct drm_audio_component *acomp = bus->audio_component;
  38        struct pci_dev *pci = to_pci_dev(bus->dev);
  39        int cdclk_freq;
  40        unsigned int bclk_m, bclk_n;
  41
  42        if (!acomp || !acomp->ops || !acomp->ops->get_cdclk_freq)
  43                return; /* only for i915 binding */
  44        if (!CONTROLLER_IN_GPU(pci))
  45                return; /* only HSW/BDW */
  46
  47        cdclk_freq = acomp->ops->get_cdclk_freq(acomp->dev);
  48        switch (cdclk_freq) {
  49        case 337500:
  50                bclk_m = 16;
  51                bclk_n = 225;
  52                break;
  53
  54        case 450000:
  55        default: /* default CDCLK 450MHz */
  56                bclk_m = 4;
  57                bclk_n = 75;
  58                break;
  59
  60        case 540000:
  61                bclk_m = 4;
  62                bclk_n = 90;
  63                break;
  64
  65        case 675000:
  66                bclk_m = 8;
  67                bclk_n = 225;
  68                break;
  69        }
  70
  71        snd_hdac_chip_writew(bus, HSW_EM4, bclk_m);
  72        snd_hdac_chip_writew(bus, HSW_EM5, bclk_n);
  73}
  74EXPORT_SYMBOL_GPL(snd_hdac_i915_set_bclk);
  75
  76static int i915_component_master_match(struct device *dev, int subcomponent,
  77                                       void *data)
  78{
  79        return !strcmp(dev->driver->name, "i915") &&
  80               subcomponent == I915_COMPONENT_AUDIO;
  81}
  82
  83/* check whether intel graphics is present */
  84static bool i915_gfx_present(void)
  85{
  86        static const struct pci_device_id ids[] = {
  87                { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID),
  88                  .class = PCI_BASE_CLASS_DISPLAY << 16,
  89                  .class_mask = 0xff << 16 },
  90                {}
  91        };
  92        return pci_dev_present(ids);
  93}
  94
  95static int i915_master_bind(struct device *dev,
  96                            struct drm_audio_component *acomp)
  97{
  98        complete_all(&bind_complete);
  99        /* clear audio_ops here as it was needed only for completion call */
 100        acomp->audio_ops = NULL;
 101        return 0;
 102}
 103
 104static const struct drm_audio_component_audio_ops i915_init_ops = {
 105        .master_bind = i915_master_bind
 106};
 107
 108/**
 109 * snd_hdac_i915_init - Initialize i915 audio component
 110 * @bus: HDA core bus
 111 *
 112 * This function is supposed to be used only by a HD-audio controller
 113 * driver that needs the interaction with i915 graphics.
 114 *
 115 * This function initializes and sets up the audio component to communicate
 116 * with i915 graphics driver.
 117 *
 118 * Returns zero for success or a negative error code.
 119 */
 120int snd_hdac_i915_init(struct hdac_bus *bus)
 121{
 122        struct drm_audio_component *acomp;
 123        int err;
 124
 125        if (!i915_gfx_present())
 126                return -ENODEV;
 127
 128        init_completion(&bind_complete);
 129
 130        err = snd_hdac_acomp_init(bus, &i915_init_ops,
 131                                  i915_component_master_match,
 132                                  sizeof(struct i915_audio_component) - sizeof(*acomp));
 133        if (err < 0)
 134                return err;
 135        acomp = bus->audio_component;
 136        if (!acomp)
 137                return -ENODEV;
 138        if (!acomp->ops) {
 139                if (!IS_ENABLED(CONFIG_MODULES) ||
 140                    !request_module("i915")) {
 141                        /* 60s timeout */
 142                        wait_for_completion_timeout(&bind_complete,
 143                                                   msecs_to_jiffies(60 * 1000));
 144                }
 145        }
 146        if (!acomp->ops) {
 147                dev_info(bus->dev, "couldn't bind with audio component\n");
 148                snd_hdac_acomp_exit(bus);
 149                return -ENODEV;
 150        }
 151        return 0;
 152}
 153EXPORT_SYMBOL_GPL(snd_hdac_i915_init);
 154