linux/drivers/gpu/drm/i915/display/intel_display_power.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: MIT */
   2/*
   3 * Copyright © 2019 Intel Corporation
   4 */
   5
   6#ifndef __INTEL_DISPLAY_POWER_H__
   7#define __INTEL_DISPLAY_POWER_H__
   8
   9#include "intel_display.h"
  10#include "intel_runtime_pm.h"
  11#include "i915_reg.h"
  12
  13struct drm_i915_private;
  14struct intel_encoder;
  15
  16enum intel_display_power_domain {
  17        POWER_DOMAIN_DISPLAY_CORE,
  18        POWER_DOMAIN_PIPE_A,
  19        POWER_DOMAIN_PIPE_B,
  20        POWER_DOMAIN_PIPE_C,
  21        POWER_DOMAIN_PIPE_D,
  22        POWER_DOMAIN_PIPE_A_PANEL_FITTER,
  23        POWER_DOMAIN_PIPE_B_PANEL_FITTER,
  24        POWER_DOMAIN_PIPE_C_PANEL_FITTER,
  25        POWER_DOMAIN_PIPE_D_PANEL_FITTER,
  26        POWER_DOMAIN_TRANSCODER_A,
  27        POWER_DOMAIN_TRANSCODER_B,
  28        POWER_DOMAIN_TRANSCODER_C,
  29        POWER_DOMAIN_TRANSCODER_D,
  30        POWER_DOMAIN_TRANSCODER_EDP,
  31        /* VDSC/joining for eDP/DSI transcoder (ICL) or pipe A (TGL) */
  32        POWER_DOMAIN_TRANSCODER_VDSC_PW2,
  33        POWER_DOMAIN_TRANSCODER_DSI_A,
  34        POWER_DOMAIN_TRANSCODER_DSI_C,
  35        POWER_DOMAIN_PORT_DDI_A_LANES,
  36        POWER_DOMAIN_PORT_DDI_B_LANES,
  37        POWER_DOMAIN_PORT_DDI_C_LANES,
  38        POWER_DOMAIN_PORT_DDI_D_LANES,
  39        POWER_DOMAIN_PORT_DDI_E_LANES,
  40        POWER_DOMAIN_PORT_DDI_F_LANES,
  41        POWER_DOMAIN_PORT_DDI_G_LANES,
  42        POWER_DOMAIN_PORT_DDI_H_LANES,
  43        POWER_DOMAIN_PORT_DDI_I_LANES,
  44
  45        POWER_DOMAIN_PORT_DDI_LANES_TC1 = POWER_DOMAIN_PORT_DDI_D_LANES, /* tgl+ */
  46        POWER_DOMAIN_PORT_DDI_LANES_TC2,
  47        POWER_DOMAIN_PORT_DDI_LANES_TC3,
  48        POWER_DOMAIN_PORT_DDI_LANES_TC4,
  49        POWER_DOMAIN_PORT_DDI_LANES_TC5,
  50        POWER_DOMAIN_PORT_DDI_LANES_TC6,
  51
  52        POWER_DOMAIN_PORT_DDI_LANES_D_XELPD = POWER_DOMAIN_PORT_DDI_LANES_TC5, /* XELPD */
  53        POWER_DOMAIN_PORT_DDI_LANES_E_XELPD,
  54
  55        POWER_DOMAIN_PORT_DDI_A_IO,
  56        POWER_DOMAIN_PORT_DDI_B_IO,
  57        POWER_DOMAIN_PORT_DDI_C_IO,
  58        POWER_DOMAIN_PORT_DDI_D_IO,
  59        POWER_DOMAIN_PORT_DDI_E_IO,
  60        POWER_DOMAIN_PORT_DDI_F_IO,
  61        POWER_DOMAIN_PORT_DDI_G_IO,
  62        POWER_DOMAIN_PORT_DDI_H_IO,
  63        POWER_DOMAIN_PORT_DDI_I_IO,
  64
  65        POWER_DOMAIN_PORT_DDI_IO_TC1 = POWER_DOMAIN_PORT_DDI_D_IO, /* tgl+ */
  66        POWER_DOMAIN_PORT_DDI_IO_TC2,
  67        POWER_DOMAIN_PORT_DDI_IO_TC3,
  68        POWER_DOMAIN_PORT_DDI_IO_TC4,
  69        POWER_DOMAIN_PORT_DDI_IO_TC5,
  70        POWER_DOMAIN_PORT_DDI_IO_TC6,
  71
  72        POWER_DOMAIN_PORT_DDI_IO_D_XELPD = POWER_DOMAIN_PORT_DDI_IO_TC5, /* XELPD */
  73        POWER_DOMAIN_PORT_DDI_IO_E_XELPD,
  74
  75        POWER_DOMAIN_PORT_DSI,
  76        POWER_DOMAIN_PORT_CRT,
  77        POWER_DOMAIN_PORT_OTHER,
  78        POWER_DOMAIN_VGA,
  79        POWER_DOMAIN_AUDIO,
  80        POWER_DOMAIN_AUX_A,
  81        POWER_DOMAIN_AUX_B,
  82        POWER_DOMAIN_AUX_C,
  83        POWER_DOMAIN_AUX_D,
  84        POWER_DOMAIN_AUX_E,
  85        POWER_DOMAIN_AUX_F,
  86        POWER_DOMAIN_AUX_G,
  87        POWER_DOMAIN_AUX_H,
  88        POWER_DOMAIN_AUX_I,
  89
  90        POWER_DOMAIN_AUX_USBC1 = POWER_DOMAIN_AUX_D, /* tgl+ */
  91        POWER_DOMAIN_AUX_USBC2,
  92        POWER_DOMAIN_AUX_USBC3,
  93        POWER_DOMAIN_AUX_USBC4,
  94        POWER_DOMAIN_AUX_USBC5,
  95        POWER_DOMAIN_AUX_USBC6,
  96
  97        POWER_DOMAIN_AUX_D_XELPD = POWER_DOMAIN_AUX_USBC5, /* XELPD */
  98        POWER_DOMAIN_AUX_E_XELPD,
  99
 100        POWER_DOMAIN_AUX_IO_A,
 101        POWER_DOMAIN_AUX_C_TBT,
 102        POWER_DOMAIN_AUX_D_TBT,
 103        POWER_DOMAIN_AUX_E_TBT,
 104        POWER_DOMAIN_AUX_F_TBT,
 105        POWER_DOMAIN_AUX_G_TBT,
 106        POWER_DOMAIN_AUX_H_TBT,
 107        POWER_DOMAIN_AUX_I_TBT,
 108
 109        POWER_DOMAIN_AUX_TBT1 = POWER_DOMAIN_AUX_D_TBT, /* tgl+ */
 110        POWER_DOMAIN_AUX_TBT2,
 111        POWER_DOMAIN_AUX_TBT3,
 112        POWER_DOMAIN_AUX_TBT4,
 113        POWER_DOMAIN_AUX_TBT5,
 114        POWER_DOMAIN_AUX_TBT6,
 115
 116        POWER_DOMAIN_GMBUS,
 117        POWER_DOMAIN_MODESET,
 118        POWER_DOMAIN_GT_IRQ,
 119        POWER_DOMAIN_DPLL_DC_OFF,
 120        POWER_DOMAIN_TC_COLD_OFF,
 121        POWER_DOMAIN_INIT,
 122
 123        POWER_DOMAIN_NUM,
 124};
 125
 126/*
 127 * i915_power_well_id:
 128 *
 129 * IDs used to look up power wells. Power wells accessed directly bypassing
 130 * the power domains framework must be assigned a unique ID. The rest of power
 131 * wells must be assigned DISP_PW_ID_NONE.
 132 */
 133enum i915_power_well_id {
 134        DISP_PW_ID_NONE,
 135
 136        VLV_DISP_PW_DISP2D,
 137        BXT_DISP_PW_DPIO_CMN_A,
 138        VLV_DISP_PW_DPIO_CMN_BC,
 139        GLK_DISP_PW_DPIO_CMN_C,
 140        CHV_DISP_PW_DPIO_CMN_D,
 141        HSW_DISP_PW_GLOBAL,
 142        SKL_DISP_PW_MISC_IO,
 143        SKL_DISP_PW_1,
 144        SKL_DISP_PW_2,
 145        CNL_DISP_PW_DDI_F_IO,
 146        CNL_DISP_PW_DDI_F_AUX,
 147        ICL_DISP_PW_3,
 148        SKL_DISP_DC_OFF,
 149        TGL_DISP_PW_TC_COLD_OFF,
 150};
 151
 152#define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A)
 153#define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \
 154                ((pipe) + POWER_DOMAIN_PIPE_A_PANEL_FITTER)
 155#define POWER_DOMAIN_TRANSCODER(tran) \
 156        ((tran) == TRANSCODER_EDP ? POWER_DOMAIN_TRANSCODER_EDP : \
 157         (tran) + POWER_DOMAIN_TRANSCODER_A)
 158
 159struct i915_power_well;
 160
 161struct i915_power_well_ops {
 162        /*
 163         * Synchronize the well's hw state to match the current sw state, for
 164         * example enable/disable it based on the current refcount. Called
 165         * during driver init and resume time, possibly after first calling
 166         * the enable/disable handlers.
 167         */
 168        void (*sync_hw)(struct drm_i915_private *dev_priv,
 169                        struct i915_power_well *power_well);
 170        /*
 171         * Enable the well and resources that depend on it (for example
 172         * interrupts located on the well). Called after the 0->1 refcount
 173         * transition.
 174         */
 175        void (*enable)(struct drm_i915_private *dev_priv,
 176                       struct i915_power_well *power_well);
 177        /*
 178         * Disable the well and resources that depend on it. Called after
 179         * the 1->0 refcount transition.
 180         */
 181        void (*disable)(struct drm_i915_private *dev_priv,
 182                        struct i915_power_well *power_well);
 183        /* Returns the hw enabled state. */
 184        bool (*is_enabled)(struct drm_i915_private *dev_priv,
 185                           struct i915_power_well *power_well);
 186};
 187
 188struct i915_power_well_regs {
 189        i915_reg_t bios;
 190        i915_reg_t driver;
 191        i915_reg_t kvmr;
 192        i915_reg_t debug;
 193};
 194
 195/* Power well structure for haswell */
 196struct i915_power_well_desc {
 197        const char *name;
 198        bool always_on;
 199        u64 domains;
 200        /* unique identifier for this power well */
 201        enum i915_power_well_id id;
 202        /*
 203         * Arbitraty data associated with this power well. Platform and power
 204         * well specific.
 205         */
 206        union {
 207                struct {
 208                        /*
 209                         * request/status flag index in the PUNIT power well
 210                         * control/status registers.
 211                         */
 212                        u8 idx;
 213                } vlv;
 214                struct {
 215                        enum dpio_phy phy;
 216                } bxt;
 217                struct {
 218                        const struct i915_power_well_regs *regs;
 219                        /*
 220                         * request/status flag index in the power well
 221                         * constrol/status registers.
 222                         */
 223                        u8 idx;
 224                        /* Mask of pipes whose IRQ logic is backed by the pw */
 225                        u8 irq_pipe_mask;
 226                        /* The pw is backing the VGA functionality */
 227                        bool has_vga:1;
 228                        bool has_fuses:1;
 229                        /*
 230                         * The pw is for an ICL+ TypeC PHY port in
 231                         * Thunderbolt mode.
 232                         */
 233                        bool is_tc_tbt:1;
 234                } hsw;
 235        };
 236        const struct i915_power_well_ops *ops;
 237};
 238
 239struct i915_power_well {
 240        const struct i915_power_well_desc *desc;
 241        /* power well enable/disable usage count */
 242        int count;
 243        /* cached hw enabled state */
 244        bool hw_enabled;
 245};
 246
 247struct i915_power_domains {
 248        /*
 249         * Power wells needed for initialization at driver init and suspend
 250         * time are on. They are kept on until after the first modeset.
 251         */
 252        bool initializing;
 253        bool display_core_suspended;
 254        int power_well_count;
 255
 256        intel_wakeref_t init_wakeref;
 257        intel_wakeref_t disable_wakeref;
 258
 259        struct mutex lock;
 260        int domain_use_count[POWER_DOMAIN_NUM];
 261
 262        struct delayed_work async_put_work;
 263        intel_wakeref_t async_put_wakeref;
 264        u64 async_put_domains[2];
 265
 266        struct i915_power_well *power_wells;
 267};
 268
 269struct intel_display_power_domain_set {
 270        u64 mask;
 271#ifdef CONFIG_DRM_I915_DEBUG_RUNTIME_PM
 272        intel_wakeref_t wakerefs[POWER_DOMAIN_NUM];
 273#endif
 274};
 275
 276#define for_each_power_domain(domain, mask)                             \
 277        for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)     \
 278                for_each_if(BIT_ULL(domain) & (mask))
 279
 280#define for_each_power_well(__dev_priv, __power_well)                           \
 281        for ((__power_well) = (__dev_priv)->power_domains.power_wells;  \
 282             (__power_well) - (__dev_priv)->power_domains.power_wells < \
 283                (__dev_priv)->power_domains.power_well_count;           \
 284             (__power_well)++)
 285
 286#define for_each_power_well_reverse(__dev_priv, __power_well)                   \
 287        for ((__power_well) = (__dev_priv)->power_domains.power_wells +         \
 288                              (__dev_priv)->power_domains.power_well_count - 1; \
 289             (__power_well) - (__dev_priv)->power_domains.power_wells >= 0;     \
 290             (__power_well)--)
 291
 292#define for_each_power_domain_well(__dev_priv, __power_well, __domain_mask)     \
 293        for_each_power_well(__dev_priv, __power_well)                           \
 294                for_each_if((__power_well)->desc->domains & (__domain_mask))
 295
 296#define for_each_power_domain_well_reverse(__dev_priv, __power_well, __domain_mask) \
 297        for_each_power_well_reverse(__dev_priv, __power_well)                   \
 298                for_each_if((__power_well)->desc->domains & (__domain_mask))
 299
 300int intel_power_domains_init(struct drm_i915_private *dev_priv);
 301void intel_power_domains_cleanup(struct drm_i915_private *dev_priv);
 302void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume);
 303void intel_power_domains_driver_remove(struct drm_i915_private *dev_priv);
 304void intel_power_domains_enable(struct drm_i915_private *dev_priv);
 305void intel_power_domains_disable(struct drm_i915_private *dev_priv);
 306void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
 307                                 enum i915_drm_suspend_mode);
 308void intel_power_domains_resume(struct drm_i915_private *dev_priv);
 309
 310void intel_display_power_suspend_late(struct drm_i915_private *i915);
 311void intel_display_power_resume_early(struct drm_i915_private *i915);
 312void intel_display_power_suspend(struct drm_i915_private *i915);
 313void intel_display_power_resume(struct drm_i915_private *i915);
 314void intel_display_power_set_target_dc_state(struct drm_i915_private *dev_priv,
 315                                             u32 state);
 316
 317const char *
 318intel_display_power_domain_str(enum intel_display_power_domain domain);
 319
 320bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
 321                                    enum intel_display_power_domain domain);
 322bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
 323                                         enum i915_power_well_id power_well_id);
 324bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
 325                                      enum intel_display_power_domain domain);
 326intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv,
 327                                        enum intel_display_power_domain domain);
 328intel_wakeref_t
 329intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
 330                                   enum intel_display_power_domain domain);
 331void __intel_display_power_put_async(struct drm_i915_private *i915,
 332                                     enum intel_display_power_domain domain,
 333                                     intel_wakeref_t wakeref);
 334void intel_display_power_flush_work(struct drm_i915_private *i915);
 335#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
 336void intel_display_power_put(struct drm_i915_private *dev_priv,
 337                             enum intel_display_power_domain domain,
 338                             intel_wakeref_t wakeref);
 339static inline void
 340intel_display_power_put_async(struct drm_i915_private *i915,
 341                              enum intel_display_power_domain domain,
 342                              intel_wakeref_t wakeref)
 343{
 344        __intel_display_power_put_async(i915, domain, wakeref);
 345}
 346#else
 347void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv,
 348                                       enum intel_display_power_domain domain);
 349
 350static inline void
 351intel_display_power_put(struct drm_i915_private *i915,
 352                        enum intel_display_power_domain domain,
 353                        intel_wakeref_t wakeref)
 354{
 355        intel_display_power_put_unchecked(i915, domain);
 356}
 357
 358static inline void
 359intel_display_power_put_async(struct drm_i915_private *i915,
 360                              enum intel_display_power_domain domain,
 361                              intel_wakeref_t wakeref)
 362{
 363        __intel_display_power_put_async(i915, domain, -1);
 364}
 365#endif
 366
 367void
 368intel_display_power_get_in_set(struct drm_i915_private *i915,
 369                               struct intel_display_power_domain_set *power_domain_set,
 370                               enum intel_display_power_domain domain);
 371
 372bool
 373intel_display_power_get_in_set_if_enabled(struct drm_i915_private *i915,
 374                                          struct intel_display_power_domain_set *power_domain_set,
 375                                          enum intel_display_power_domain domain);
 376
 377void
 378intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
 379                                    struct intel_display_power_domain_set *power_domain_set,
 380                                    u64 mask);
 381
 382static inline void
 383intel_display_power_put_all_in_set(struct drm_i915_private *i915,
 384                                   struct intel_display_power_domain_set *power_domain_set)
 385{
 386        intel_display_power_put_mask_in_set(i915, power_domain_set, power_domain_set->mask);
 387}
 388
 389enum dbuf_slice {
 390        DBUF_S1,
 391        DBUF_S2,
 392        DBUF_S3,
 393        DBUF_S4,
 394        I915_MAX_DBUF_SLICES
 395};
 396
 397void gen9_dbuf_slices_update(struct drm_i915_private *dev_priv,
 398                             u8 req_slices);
 399
 400#define with_intel_display_power(i915, domain, wf) \
 401        for ((wf) = intel_display_power_get((i915), (domain)); (wf); \
 402             intel_display_power_put_async((i915), (domain), (wf)), (wf) = 0)
 403
 404void chv_phy_powergate_lanes(struct intel_encoder *encoder,
 405                             bool override, unsigned int mask);
 406bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
 407                          enum dpio_channel ch, bool override);
 408
 409#endif /* __INTEL_DISPLAY_POWER_H__ */
 410