Re: [PATCH v11 7/7] drm/i915/mtl: Add support for PM DEMAND

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 2023-06-01 at 11:34 -0300, Gustavo Sousa wrote:
> Hi, Vinod.
> 
> I have some comments for this version, please see them below. With those
> fixed,
> 
> Acked-by: Gustavo Sousa <gustavo.sousa@xxxxxxxxx>
> 
> Quoting Vinod Govindapillai (2023-06-01 09:19:23-03:00)
> > From: Mika Kahola <mika.kahola@xxxxxxxxx>
> > 
> > MTL introduces a new way to instruct the PUnit with
> > power and bandwidth requirements of DE. Add the functionality
> > to program the registers and handle waits using interrupts.
> > The current wait time for timeouts is programmed for 10 msecs to
> > factor in the worst case scenarios. Changes made to use REG_BIT
> > for a register that we touched(GEN8_DE_MISC_IER _MMIO).
> > 
> > Wa_14016740474 is added which applies to Xe_LPD+ display
> > 
> > v2: checkpatch warning fixes, simplify program pmdemand part
> > 
> > v3: update to dbufs and pipes values to pmdemand register(stan)
> >    Removed the macro usage in update_pmdemand_values()
> > 
> > v4: move the pmdemand_pre_plane_update before cdclk update
> >    pmdemand_needs_update included cdclk params comparisons
> >    pmdemand_state NULL check (Gustavo)
> >    pmdemand.o in sorted order in the makefile (Jani)
> >    update pmdemand misc irq handler loop (Gustavo)
> >    active phys bitmask and programming correction (Gustavo)
> > 
> > v5: simplify pmdemand_state structure
> >    simplify methods to find active phys and max port clock
> >    Timeout in case of previou pmdemand task pending (Gustavo)
> > 
> > v6: rebasing
> >    updates to max_ddiclk calculations (Gustavo)
> >    updates to active_phys count method (Gustavo)
> > 
> > v7: use two separate loop to iterate throug old and new
> >    crtc states to calculate the active phys (Gustavo)
> > 
> > v8: use uniform function names (Gustavo)
> > 
> > v9: For phys change iterate through connectors (Imre)
> >    Look for change in phys for pmdemand update (Gustavo, Imre)
> >    Some more stlying changes (Imre)
> >    Update pmdemand state during HW readout/sanitize (Imre)
> > 
> > v10: Fix CI checkpatch warnings
> > 
> > Bspec: 66451, 64636, 64602, 64603
> > Cc: Matt Atwood <matthew.s.atwood@xxxxxxxxx>
> > Cc: Matt Roper <matthew.d.roper@xxxxxxxxx>
> > Cc: Lucas De Marchi <lucas.demarchi@xxxxxxxxx>
> > Cc: Gustavo Sousa <gustavo.sousa@xxxxxxxxx>
> > Signed-off-by: José Roberto de Souza <jose.souza@xxxxxxxxx>
> > Signed-off-by: Radhakrishna Sripada <radhakrishna.sripada@xxxxxxxxx>
> > Signed-off-by: Gustavo Sousa <gustavo.sousa@xxxxxxxxx>
> > Signed-off-by: Mika Kahola <mika.kahola@xxxxxxxxx>
> > Signed-off-by: Vinod Govindapillai <vinod.govindapillai@xxxxxxxxx>
> > Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@xxxxxxxxx>
> > ---
> > drivers/gpu/drm/i915/Makefile                 |   1 +
> > drivers/gpu/drm/i915/display/intel_display.c  |  14 +
> > .../gpu/drm/i915/display/intel_display_core.h |   9 +
> > .../drm/i915/display/intel_display_driver.c   |   7 +
> > .../gpu/drm/i915/display/intel_display_irq.c  |  23 +-
> > .../drm/i915/display/intel_display_power.c    |  14 +-
> > .../drm/i915/display/intel_modeset_setup.c    |  18 +
> > drivers/gpu/drm/i915/display/intel_pmdemand.c | 555 ++++++++++++++++++
> > drivers/gpu/drm/i915/display/intel_pmdemand.h |  56 ++
> > drivers/gpu/drm/i915/i915_reg.h               |  36 +-
> > 10 files changed, 727 insertions(+), 6 deletions(-)
> > create mode 100644 drivers/gpu/drm/i915/display/intel_pmdemand.c
> > create mode 100644 drivers/gpu/drm/i915/display/intel_pmdemand.h
> > 
> > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> > index 1c9ed4c52760..2cd8de174bf6 100644
> > --- a/drivers/gpu/drm/i915/Makefile
> > +++ b/drivers/gpu/drm/i915/Makefile
> > @@ -269,6 +269,7 @@ i915-y += \
> >         display/intel_pch_display.o \
> >         display/intel_pch_refclk.o \
> >         display/intel_plane_initial.o \
> > +        display/intel_pmdemand.o \
> >         display/intel_psr.o \
> >         display/intel_quirks.o \
> >         display/intel_sprite.o \
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> > b/drivers/gpu/drm/i915/display/intel_display.c
> > index f51a55f4e9d0..5cbf5eae2414 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > @@ -99,6 +99,7 @@
> > #include "intel_pcode.h"
> > #include "intel_pipe_crc.h"
> > #include "intel_plane_initial.h"
> > +#include "intel_pmdemand.h"
> > #include "intel_pps.h"
> > #include "intel_psr.h"
> > #include "intel_sdvo.h"
> > @@ -6352,6 +6353,10 @@ int intel_atomic_check(struct drm_device *dev,
> >                         return ret;
> >         }
> > 
> > +        ret = intel_pmdemand_atomic_check(state);
> > +        if (ret)
> > +                goto fail;
> > +
> >         ret = intel_atomic_check_crtcs(state);
> >         if (ret)
> >                 goto fail;
> > @@ -6997,6 +7002,14 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
> >         for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
> >                 crtc->config = new_crtc_state;
> > 
> > +        /*
> > +         * In XE_LPD+ Pmdemand combines many parameters such as voltage index,
> > +         * plls, cdclk frequency, QGV point selection parameter etc. Voltage
> > +         * index, cdclk/ddiclk frequencies are supposed to be configured before
> > +         * the cdclk config is set.
> > +         */
> > +        intel_pmdemand_pre_plane_update(state);
> > +
> >         if (state->modeset) {
> >                 drm_atomic_helper_update_legacy_modeset_state(dev, &state->base);
> > 
> > @@ -7116,6 +7129,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
> >                 intel_verify_planes(state);
> > 
> >         intel_sagv_post_plane_update(state);
> > +        intel_pmdemand_post_plane_update(state);
> > 
> >         drm_atomic_helper_commit_hw_done(&state->base);
> > 
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h
> > b/drivers/gpu/drm/i915/display/intel_display_core.h
> > index dd8e08c8598f..8d2243c71dd8 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_core.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display_core.h
> > @@ -345,6 +345,15 @@ struct intel_display {
> >                 struct intel_global_obj obj;
> >         } dbuf;
> > 
> > +        struct {
> > +                wait_queue_head_t waitqueue;
> > +
> > +                /* mutex to protect pmdemand programming sequence */
> > +                struct mutex lock;
> > +
> > +                struct intel_global_obj obj;
> > +        } pmdemand;
> > +
> >         struct {
> >                 /*
> >                  * dkl.phy_lock protects against concurrent access of the
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c
> > b/drivers/gpu/drm/i915/display/intel_display_driver.c
> > index 60ce10fc7205..dc8de861339d 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_driver.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c
> > @@ -47,6 +47,7 @@
> > #include "intel_opregion.h"
> > #include "intel_overlay.h"
> > #include "intel_plane_initial.h"
> > +#include "intel_pmdemand.h"
> > #include "intel_pps.h"
> > #include "intel_quirks.h"
> > #include "intel_vga.h"
> > @@ -211,6 +212,8 @@ int intel_display_driver_probe_noirq(struct drm_i915_private *i915)
> >         if (ret < 0)
> >                 goto cleanup_vga;
> > 
> > +        intel_pmdemand_init_early(i915);
> > +
> >         intel_power_domains_init_hw(i915, false);
> > 
> >         if (!HAS_DISPLAY(i915))
> > @@ -240,6 +243,10 @@ int intel_display_driver_probe_noirq(struct drm_i915_private *i915)
> >         if (ret)
> >                 goto cleanup_vga_client_pw_domain_dmc;
> > 
> > +        ret = intel_pmdemand_init(i915);
> > +        if (ret)
> > +                goto cleanup_vga_client_pw_domain_dmc;
> > +
> >         init_llist_head(&i915->display.atomic_helper.free_list);
> >         INIT_WORK(&i915->display.atomic_helper.free_work,
> >                   intel_atomic_helper_free_state_worker);
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c
> > b/drivers/gpu/drm/i915/display/intel_display_irq.c
> > index 3b2a287d2041..0b3739310f81 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_irq.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c
> > @@ -18,6 +18,7 @@
> > #include "intel_fifo_underrun.h"
> > #include "intel_gmbus.h"
> > #include "intel_hotplug_irq.h"
> > +#include "intel_pmdemand.h"
> > #include "intel_psr.h"
> > #include "intel_psr_regs.h"
> > 
> > @@ -827,12 +828,27 @@ static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv)
> >                 return GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
> > }
> > 
> > +static void intel_pmdemand_irq_handler(struct drm_i915_private *dev_priv)
> > +{
> > +        wake_up_all(&dev_priv->display.pmdemand.waitqueue);
> > +}
> > +
> > static void
> > gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
> > {
> >         bool found = false;
> > 
> > -        if (iir & GEN8_DE_MISC_GSE) {
> > +        if (DISPLAY_VER(dev_priv) >= 14) {
> > +                if (iir & (XELPDP_PMDEMAND_RSP |
> > +                           XELPDP_PMDEMAND_RSPTOUT_ERR)) {
> > +                        if (iir & XELPDP_PMDEMAND_RSPTOUT_ERR)
> > +                                drm_dbg(&dev_priv->drm,
> > +                                        "Error waiting for Punit PM Demand Response\n");
> > +
> > +                        intel_pmdemand_irq_handler(dev_priv);
> > +                        found = true;
> > +                }
> > +        } else if (iir & GEN8_DE_MISC_GSE) {
> >                 intel_opregion_asle_intr(dev_priv);
> >                 found = true;
> >         }
> > @@ -1576,7 +1592,10 @@ void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
> >         if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
> >                 de_port_masked |= BXT_DE_PORT_GMBUS;
> > 
> > -        if (DISPLAY_VER(dev_priv) >= 11) {
> > +        if (DISPLAY_VER(dev_priv) >= 14) {
> > +                de_misc_masked |= XELPDP_PMDEMAND_RSPTOUT_ERR |
> > +                                  XELPDP_PMDEMAND_RSP;
> > +        } else if (DISPLAY_VER(dev_priv) >= 11) {
> >                 enum port port;
> > 
> >                 if (intel_bios_is_dsi_present(dev_priv, &port))
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c
> > b/drivers/gpu/drm/i915/display/intel_display_power.c
> > index 9c9a809c71f1..db827cf3c9ca 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_power.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display_power.c
> > @@ -20,6 +20,7 @@
> > #include "intel_mchbar_regs.h"
> > #include "intel_pch_refclk.h"
> > #include "intel_pcode.h"
> > +#include "intel_pmdemand.h"
> > #include "intel_pps_regs.h"
> > #include "intel_snps_phy.h"
> > #include "skl_watermark.h"
> > @@ -1082,20 +1083,29 @@ void gen9_dbuf_slices_update(struct drm_i915_private *dev_priv,
> > 
> > static void gen9_dbuf_enable(struct drm_i915_private *dev_priv)
> > {
> > +        u8 slices_mask;
> > +
> >         dev_priv->display.dbuf.enabled_slices =
> >                 intel_enabled_dbuf_slices_mask(dev_priv);
> > 
> > +        slices_mask = BIT(DBUF_S1) | dev_priv->display.dbuf.enabled_slices;
> > +
> > +        if (DISPLAY_VER(dev_priv) >= 14)
> > +                intel_pmdemand_program_dbuf(dev_priv, slices_mask);
> > +
> >         /*
> >          * Just power up at least 1 slice, we will
> >          * figure out later which slices we have and what we need.
> >          */
> > -        gen9_dbuf_slices_update(dev_priv, BIT(DBUF_S1) |
> > -                                dev_priv->display.dbuf.enabled_slices);
> > +        gen9_dbuf_slices_update(dev_priv, slices_mask);
> > }
> > 
> > static void gen9_dbuf_disable(struct drm_i915_private *dev_priv)
> > {
> >         gen9_dbuf_slices_update(dev_priv, 0);
> > +
> > +        if (DISPLAY_VER(dev_priv) >= 14)
> > +                intel_pmdemand_program_dbuf(dev_priv, 0);
> > }
> > 
> > static void gen12_dbuf_slices_config(struct drm_i915_private *dev_priv)
> > diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c
> > b/drivers/gpu/drm/i915/display/intel_modeset_setup.c
> > index 5ff99ca7f1de..87f41040916b 100644
> > --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c
> > +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c
> > @@ -26,6 +26,7 @@
> > #include "intel_fifo_underrun.h"
> > #include "intel_modeset_setup.h"
> > #include "intel_pch_display.h"
> > +#include "intel_pmdemand.h"
> > #include "intel_tc.h"
> > #include "intel_vblank.h"
> > #include "intel_wm.h"
> > @@ -153,6 +154,8 @@ static void intel_crtc_disable_noatomic_complete(struct intel_crtc *crtc)
> >                 to_intel_dbuf_state(i915->display.dbuf.obj.state);
> >         struct intel_crtc_state *crtc_state =
> >                 to_intel_crtc_state(crtc->base.state);
> > +        struct intel_pmdemand_state *pmdemand_state =
> > +                to_intel_pmdemand_state(i915->display.dbuf.obj.state);
> 
> s/dbuf/pmdemand/?

ah! ( thanks! 

> 
> Also, a cosmetic nitpick: maybe do this above the line with "struct
> intel_crtc_state *crtc_state ="? Just so we have global state variables grouped
> together.
> 
> >         enum pipe pipe = crtc->pipe;
> > 
> >         __drm_atomic_helper_crtc_destroy_state(&crtc_state->uapi);
> > @@ -174,6 +177,8 @@ static void intel_crtc_disable_noatomic_complete(struct intel_crtc *crtc)
> > 
> >         bw_state->data_rate[pipe] = 0;
> >         bw_state->num_active_planes[pipe] = 0;
> > +
> > +        pmdemand_state->ddi_clocks[pipe] = 0;
> > }
> > 
> > /*
> > @@ -661,6 +666,9 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
> >                 to_intel_cdclk_state(i915->display.cdclk.obj.state);
> >         struct intel_dbuf_state *dbuf_state =
> >                 to_intel_dbuf_state(i915->display.dbuf.obj.state);
> > +        struct intel_pmdemand_state *pmdemand_state =
> > +                to_intel_pmdemand_state(i915->display.dbuf.obj.state);
> 
> s/dbuf/pmdemand/?
> 
> > +        u16 active_phys = 0;
> >         enum pipe pipe;
> >         struct intel_crtc *crtc;
> >         struct intel_encoder *encoder;
> > @@ -742,6 +750,8 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
> > 
> >         drm_connector_list_iter_begin(&i915->drm, &conn_iter);
> >         for_each_intel_connector_iter(connector, &conn_iter) {
> > +                enum phy phy;
> > +
> >                 if (connector->get_hw_state(connector)) {
> >                         struct intel_crtc_state *crtc_state;
> >                         struct intel_crtc *crtc;
> > @@ -764,6 +774,10 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
> >                                         drm_connector_mask(&connector->base);
> >                                 crtc_state->uapi.encoder_mask |=
> >                                         drm_encoder_mask(&encoder->base);
> > +
> > +                                phy = intel_port_to_phy(i915, encoder->port);
> > +                                if (!intel_phy_is_tc(i915, phy))
> > +                                        active_phys |= BIT(phy);
> >                         }
> >                 } else {
> >                         connector->base.dpms = DRM_MODE_DPMS_OFF;
> > @@ -776,6 +790,8 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
> >         }
> >         drm_connector_list_iter_end(&conn_iter);
> > 
> > +        pmdemand_state->active_phys_mask = active_phys;
> > +
> >         for_each_intel_crtc(&i915->drm, crtc) {
> >                 struct intel_bw_state *bw_state =
> >                         to_intel_bw_state(i915->display.bw.obj.state);
> > @@ -840,6 +856,8 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
> >                 cdclk_state->min_cdclk[crtc->pipe] = min_cdclk;
> >                 cdclk_state->min_voltage_level[crtc->pipe] =
> >                         crtc_state->min_voltage_level;
> > +                pmdemand_state->ddi_clocks[crtc->pipe] =
> > +                        crtc_state->port_clock;
> > 
> >                 intel_bw_crtc_update(bw_state, crtc_state);
> >         }
> > diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.c
> > b/drivers/gpu/drm/i915/display/intel_pmdemand.c
> > new file mode 100644
> > index 000000000000..fca99b84c835
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/display/intel_pmdemand.c
> > @@ -0,0 +1,555 @@
> > +// SPDX-License-Identifier: MIT
> > +/*
> > + * Copyright © 2023 Intel Corporation
> > + */
> > +
> > +#include <linux/bitops.h>
> > +
> > +#include "i915_drv.h"
> > +#include "i915_reg.h"
> > +#include "intel_atomic.h"
> > +#include "intel_bw.h"
> > +#include "intel_cdclk.h"
> > +#include "intel_de.h"
> > +#include "intel_display_trace.h"
> > +#include "intel_pmdemand.h"
> > +#include "skl_watermark.h"
> > +
> > +static struct intel_global_state *
> > +intel_pmdemand_duplicate_state(struct intel_global_obj *obj)
> > +{
> > +        struct intel_pmdemand_state *pmdemand_state;
> > +
> > +        pmdemand_state = kmemdup(obj->state, sizeof(*pmdemand_state), GFP_KERNEL);
> > +        if (!pmdemand_state)
> > +                return NULL;
> > +
> > +        return &pmdemand_state->base;
> > +}
> > +
> > +static void intel_pmdemand_destroy_state(struct intel_global_obj *obj,
> > +                                         struct intel_global_state *state)
> > +{
> > +        kfree(state);
> > +}
> > +
> > +static const struct intel_global_state_funcs intel_pmdemand_funcs = {
> > +        .atomic_duplicate_state = intel_pmdemand_duplicate_state,
> > +        .atomic_destroy_state = intel_pmdemand_destroy_state,
> > +};
> > +
> > +static struct intel_pmdemand_state *
> > +intel_atomic_get_pmdemand_state(struct intel_atomic_state *state)
> > +{
> > +        struct drm_i915_private *i915 = to_i915(state->base.dev);
> > +        struct intel_global_state *pmdemand_state =
> > +                intel_atomic_get_global_obj_state(state,
> > +                                                  &i915->display.pmdemand.obj);
> > +
> > +        if (IS_ERR(pmdemand_state))
> > +                return ERR_CAST(pmdemand_state);
> > +
> > +        return to_intel_pmdemand_state(pmdemand_state);
> > +}
> > +
> > +static struct intel_pmdemand_state *
> > +intel_atomic_get_old_pmdemand_state(struct intel_atomic_state *state)
> > +{
> > +        struct drm_i915_private *i915 = to_i915(state->base.dev);
> > +        struct intel_global_state *pmdemand_state =
> > +                intel_atomic_get_old_global_obj_state(state,
> > +                                                      &i915->display.pmdemand.obj);
> > +
> > +        if (!pmdemand_state)
> > +                return NULL;
> > +
> > +        return to_intel_pmdemand_state(pmdemand_state);
> > +}
> > +
> > +static struct intel_pmdemand_state *
> > +intel_atomic_get_new_pmdemand_state(struct intel_atomic_state *state)
> > +{
> > +        struct drm_i915_private *i915 = to_i915(state->base.dev);
> > +        struct intel_global_state *pmdemand_state =
> > +                intel_atomic_get_new_global_obj_state(state,
> > +                                                      &i915->display.pmdemand.obj);
> > +
> > +        if (!pmdemand_state)
> > +                return NULL;
> > +
> > +        return to_intel_pmdemand_state(pmdemand_state);
> > +}
> > +
> > +int intel_pmdemand_init(struct drm_i915_private *i915)
> > +{
> > +        struct intel_pmdemand_state *pmdemand_state;
> > +
> > +        pmdemand_state = kzalloc(sizeof(*pmdemand_state), GFP_KERNEL);
> > +        if (!pmdemand_state)
> > +                return -ENOMEM;
> > +
> > +        intel_atomic_global_obj_init(i915, &i915->display.pmdemand.obj,
> > +                                     &pmdemand_state->base,
> > +                                     &intel_pmdemand_funcs);
> > +
> > +        if (IS_MTL_DISPLAY_STEP(i915, STEP_A0, STEP_C0))
> > +                /* Wa_14016740474 */
> > +                intel_de_rmw(i915, XELPD_CHICKEN_DCPR_3, 0, DMD_RSP_TIMEOUT_DISABLE);
> > +
> > +        return 0;
> > +}
> > +
> > +void intel_pmdemand_init_early(struct drm_i915_private *i915)
> > +{
> > +        mutex_init(&i915->display.pmdemand.lock);
> > +        init_waitqueue_head(&i915->display.pmdemand.waitqueue);
> > +}
> > +
> > +static void
> > +intel_pmdemand_update_max_ddiclk(struct intel_atomic_state *state,
> > +                                 struct intel_pmdemand_state *pmdemand_state)
> > +{
> > +        int max_ddiclk = 0;
> > +        struct intel_crtc *crtc;
> > +        int i;
> > +        const struct intel_crtc_state *new_crtc_state;
> > +
> > +        for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
> > +                pmdemand_state->ddi_clocks[crtc->pipe] =
> > +                        new_crtc_state->port_clock;
> > +
> > +        for (i = 0; i < ARRAY_SIZE(pmdemand_state->ddi_clocks); i++)
> > +                max_ddiclk = max(pmdemand_state->ddi_clocks[i], max_ddiclk);
> > +
> > +        pmdemand_state->params.ddiclk_max = DIV_ROUND_UP(max_ddiclk, 1000);
> > +}
> > +
> > +static void
> > +intel_pmdemand_update_phys_mask(struct drm_i915_private *i915,
> > +                                struct intel_atomic_state *state,
> > +                                struct drm_connector_state *conn_state,
> > +                                bool for_old_state, u16 *phys_mask)
> > +{
> > +        struct intel_crtc *crtc = to_intel_crtc(conn_state->crtc);
> > +        struct intel_encoder *encoder = to_intel_encoder(conn_state->best_encoder);
> > +        struct intel_crtc_state *crtc_state;
> > +        enum phy phy;
> > +
> > +        if (!crtc || !encoder)
> 
> I believe the safest thing here is to use conn_state->crtc and
> conn_state->best_encoder in the condition.
> 
> This falls in the same type of argument used for our earlier discussion
> on the explicit NULL check for the pmdemand_state. In my humble opinion,
> we should only use the result of container_of() for valid pointers.
> 
> That said, I see that checking for NULL *after* conversions is done in
> other parts of the driver, so I think other developers might not agree
> with me here. So, your call on this :-)

Well.. I get your comments. I think such usage being used in all other places. So for the time being
sticking to this. May be this need a much bigger discussion with others involved !

> 
> > +                return;
> > +
> > +        phy = intel_port_to_phy(i915, encoder->port);
> > +        if (intel_phy_is_tc(i915, phy))
> > +                return;
> > +
> > +        if (for_old_state)
> > +                crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
> > +        else
> > +                crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
> > +
> > +        if (!crtc_state->hw.active)
> > +                return;
> > +
> > +        if (for_old_state)
> > +                *phys_mask &= ~BIT(phy);
> > +        else
> > +                *phys_mask |= BIT(phy);
> > +}
> > +
> > +static void
> > +intel_pmdemand_update_active_non_tc_phys(struct drm_i915_private *i915,
> > +                                         struct intel_atomic_state *state,
> > +                                         struct intel_pmdemand_state *pmdemand_state)
> > +{
> > +        u16 *phys_mask = &pmdemand_state->active_phys_mask;
> > +        struct drm_connector *connector;
> > +        int i;
> > +        struct drm_connector_state *old_conn_state, *new_conn_state;
> > +
> > +        for_each_oldnew_connector_in_state(&state->base, connector,
> > +                                           old_conn_state, new_conn_state, i) {
> > +                if (!intel_connector_needs_modeset(state, connector))
> > +                        continue;
> > +
> > +                /* First clear the active phys in the old connector state */
> > +                intel_pmdemand_update_phys_mask(i915, state, old_conn_state,
> > +                                                true, phys_mask);
> > +
> > +                /* First set the active phys in new connector state */
> 
> s/First/Then/?
> 
> > +                intel_pmdemand_update_phys_mask(i915, state, new_conn_state,
> > +                                                false, phys_mask);
> > +        }
> > +
> > +        pmdemand_state->params.active_phys = hweight16(*phys_mask);
> > +}
> > +
> > +static bool intel_pmdemand_phys_needs_update(struct intel_atomic_state *state)
> > +{
> > +        struct drm_connector *connector;
> > +        int i;
> > +        struct drm_connector_state *old_conn_state, *new_conn_state;
> > +
> > +        for_each_oldnew_connector_in_state(&state->base, connector,
> > +                                           old_conn_state, new_conn_state, i) {
> > +                struct intel_crtc *old_crtc =
> > +                        to_intel_crtc(old_conn_state->crtc);
> > +                struct intel_crtc *new_crtc =
> > +                        to_intel_crtc(new_conn_state->crtc);
> > +                struct intel_crtc_state *new_crtc_state, *old_crtc_state;
> > +
> > +                /* If the connector do not need modeset, no phys change */
> > +                if (!intel_connector_needs_modeset(state, connector))
> > +                        continue;
> 
> I believe all of the checks below are already done once we call
> intel_connector_needs_modeset(). In that case, I guess this loop could
> be inlined directly in intel_pmdemand_needs_update() since it becomes a
> simple one.

Wanted to avoid the false positives from other mode check cases. But probably it is better to
simplify this only check intel_pmdemand_needs_update()

BR
vinod

> 
> > +
> > +                /* If crtcs are different, update phys */
> > +                if (old_crtc != new_crtc)
> > +                        return true;
> > +
> > +                if (!new_crtc)
> > +                        continue;
> > +
> > +                /* If crtc state's active status changed, update the phys */
> > +                old_crtc_state = intel_atomic_get_old_crtc_state(state,
> > +                                                                 new_crtc);
> > +                new_crtc_state = intel_atomic_get_old_crtc_state(state,
> > +                                                                 new_crtc);
> > +                if (old_crtc_state->hw.active != new_crtc_state->hw.active)
> > +                        return true;
> > +        }
> > +
> > +        return false;
> > +}
> > +
> > +static bool intel_pmdemand_needs_update(struct intel_atomic_state *state)
> > +{
> > +        struct intel_crtc *crtc;
> > +        int i;
> > +        const struct intel_bw_state *new_bw_state, *old_bw_state;
> > +        const struct intel_cdclk_state *new_cdclk_state, *old_cdclk_state;
> > +        const struct intel_crtc_state *new_crtc_state, *old_crtc_state;
> > +        const struct intel_dbuf_state *new_dbuf_state, *old_dbuf_state;
> > +
> > +        new_bw_state = intel_atomic_get_new_bw_state(state);
> > +        old_bw_state = intel_atomic_get_old_bw_state(state);
> > +        if (new_bw_state && new_bw_state->qgv_point_peakbw !=
> > +            old_bw_state->qgv_point_peakbw)
> > +                return true;
> > +
> > +        new_dbuf_state = intel_atomic_get_new_dbuf_state(state);
> > +        old_dbuf_state = intel_atomic_get_old_dbuf_state(state);
> > +        if (new_dbuf_state &&
> > +            (new_dbuf_state->active_pipes !=
> > +             old_dbuf_state->active_pipes ||
> > +             new_dbuf_state->enabled_slices !=
> > +             old_dbuf_state->enabled_slices))
> > +                return true;
> > +
> > +        new_cdclk_state = intel_atomic_get_new_cdclk_state(state);
> > +        old_cdclk_state = intel_atomic_get_old_cdclk_state(state);
> > +        if (new_cdclk_state &&
> > +            (new_cdclk_state->actual.cdclk !=
> > +             old_cdclk_state->actual.cdclk ||
> > +             new_cdclk_state->actual.voltage_level !=
> > +             old_cdclk_state->actual.voltage_level))
> > +                return true;
> > +
> > +        for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
> > +                                            new_crtc_state, i)
> > +                if (new_crtc_state->port_clock != old_crtc_state->port_clock)
> > +                        return true;
> > +
> > +        return intel_pmdemand_phys_needs_update(state);
> > +}
> > +
> > +int intel_pmdemand_atomic_check(struct intel_atomic_state *state)
> > +{
> > +        struct drm_i915_private *i915 = to_i915(state->base.dev);
> > +        const struct intel_bw_state *new_bw_state;
> > +        const struct intel_cdclk_state *new_cdclk_state;
> > +        const struct intel_dbuf_state *new_dbuf_state;
> > +        struct intel_pmdemand_state *new_pmdemand_state;
> > +        int ret;
> > +
> > +        if (DISPLAY_VER(i915) < 14)
> > +                return 0;
> > +
> > +        if (!intel_pmdemand_needs_update(state))
> > +                return 0;
> > +
> > +        new_pmdemand_state = intel_atomic_get_pmdemand_state(state);
> > +        if (IS_ERR(new_pmdemand_state))
> > +                return PTR_ERR(new_pmdemand_state);
> > +
> > +        ret = intel_atomic_lock_global_state(&new_pmdemand_state->base);
> > +        if (ret)
> > +                return ret;
> > +
> > +        new_bw_state = intel_atomic_get_bw_state(state);
> > +        if (IS_ERR(new_bw_state))
> > +                return PTR_ERR(new_bw_state);
> > +
> > +        /* firmware will calculate the qclck_gc_index, requirement is set to 0 */
> > +        new_pmdemand_state->params.qclk_gv_index = 0;
> > +        new_pmdemand_state->params.qclk_gv_bw =
> > +                min_t(u16, new_bw_state->qgv_point_peakbw, 0xffff);
> > +
> > +        new_dbuf_state = intel_atomic_get_dbuf_state(state);
> > +        if (IS_ERR(new_dbuf_state))
> > +                return PTR_ERR(new_dbuf_state);
> > +
> > +        new_pmdemand_state->params.active_pipes =
> > +                min_t(u8, hweight8(new_dbuf_state->active_pipes), 3);
> > +        new_pmdemand_state->params.active_dbufs =
> > +                min_t(u8,
> > +                      hweight8(BIT(DBUF_S1) | new_dbuf_state->enabled_slices),
> > +                      3);
> > +
> > +        new_cdclk_state = intel_atomic_get_cdclk_state(state);
> > +        if (IS_ERR(new_cdclk_state))
> > +                return PTR_ERR(new_cdclk_state);
> > +
> > +        new_pmdemand_state->params.voltage_index =
> > +                new_cdclk_state->actual.voltage_level;
> > +        new_pmdemand_state->params.cdclk_freq_mhz =
> > +                DIV_ROUND_UP(new_cdclk_state->actual.cdclk, 1000);
> > +
> > +        intel_pmdemand_update_max_ddiclk(state, new_pmdemand_state);
> > +
> > +        intel_pmdemand_update_active_non_tc_phys(i915, state, new_pmdemand_state);
> > +
> > +        /*
> > +         * Setting scalers to max as it can not be calculated during flips and
> > +         * fastsets without taking global states locks.
> > +         */
> > +        new_pmdemand_state->params.scalers = 7;
> > +
> > +        ret = intel_atomic_serialize_global_state(&new_pmdemand_state->base);
> > +        if (ret)
> > +                return ret;
> > +
> > +        return 0;
> > +}
> > +
> > +static bool intel_pmdemand_check_prev_transaction(struct drm_i915_private *i915)
> > +{
> > +        return !(intel_de_wait_for_clear(i915,
> > +                                         XELPDP_INITIATE_PMDEMAND_REQUEST(1),
> > +                                         XELPDP_PMDEMAND_REQ_ENABLE, 10) ||
> > +                 intel_de_wait_for_clear(i915,
> > +                                         GEN12_DCPR_STATUS_1,
> > +                                         XELPDP_PMDEMAND_INFLIGHT_STATUS, 10));
> > +}
> > +
> > +static bool intel_pmdemand_req_complete(struct drm_i915_private *i915)
> > +{
> > +        return !(intel_de_read(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(1)) &
> > +                 XELPDP_PMDEMAND_REQ_ENABLE);
> > +}
> > +
> > +static void intel_pmdemand_wait(struct drm_i915_private *i915)
> > +{
> > +        const unsigned int timeout_ms = 10;
> > +
> > +        if (!wait_event_timeout(i915->display.pmdemand.waitqueue,
> > +                                intel_pmdemand_req_complete(i915),
> > +                                msecs_to_jiffies_timeout(timeout_ms)))
> > +                drm_err(&i915->drm,
> > +                        "timed out waiting for Punit PM Demand Response\n");
> > +}
> > +
> > +/* Required to be programmed during Display Init Sequences. */
> > +void intel_pmdemand_program_dbuf(struct drm_i915_private *i915,
> > +                                 u8 dbuf_slices)
> > +{
> > +        u32 dbufs = min_t(u32, hweight8(dbuf_slices), 3);
> > +
> > +        mutex_lock(&i915->display.pmdemand.lock);
> > +        if (drm_WARN_ON(&i915->drm,
> > +                        !intel_pmdemand_check_prev_transaction(i915)))
> > +                goto unlock;
> > +
> > +        intel_de_rmw(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(0),
> > +                     XELPDP_PMDEMAND_DBUFS_MASK, XELPDP_PMDEMAND_DBUFS(dbufs));
> > +        intel_de_rmw(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(1), 0,
> > +                     XELPDP_PMDEMAND_REQ_ENABLE);
> > +
> > +        intel_pmdemand_wait(i915);
> > +
> > +unlock:
> > +        mutex_unlock(&i915->display.pmdemand.lock);
> > +}
> > +
> > +static void
> > +intel_pmdemand_update_params(const struct intel_pmdemand_state *new,
> > +                             const struct intel_pmdemand_state *old,
> > +                             u32 *reg1, u32 *reg2)
> > +{
> > +        u32 plls, tmp;
> > +
> > +        /*
> > +         * The pmdemand parameter updates happens in two steps. Pre plane and
> > +         * post plane updates. During the pre plane, as DE might still be
> > +         * handling with some old operations, to avoid unwanted performance
> > +         * issues, program the pmdemand parameters with higher of old and new
> > +         * values. And then after once settled, use the new parameter values
> > +         * as part of the post plane update.
> > +         */
> > +
> > +        /* Set 1*/
> > +        *reg1 &= ~XELPDP_PMDEMAND_QCLK_GV_BW_MASK;
> > +        tmp = old ? max(old->params.qclk_gv_bw, new->params.qclk_gv_bw) :
> > +                    new->params.qclk_gv_bw;
> > +        *reg1 |= XELPDP_PMDEMAND_QCLK_GV_BW(tmp);
> > +
> > +        *reg1 &= ~XELPDP_PMDEMAND_VOLTAGE_INDEX_MASK;
> > +        tmp = old ? max(old->params.voltage_index, new->params.voltage_index) :
> > +                    new->params.voltage_index;
> > +        *reg1 |= XELPDP_PMDEMAND_VOLTAGE_INDEX(tmp);
> > +
> > +        *reg1 &= ~XELPDP_PMDEMAND_QCLK_GV_INDEX_MASK;
> > +        tmp = old ? max(old->params.qclk_gv_index, new->params.qclk_gv_index) :
> > +                    new->params.qclk_gv_index;
> > +        *reg1 |= XELPDP_PMDEMAND_QCLK_GV_INDEX(tmp);
> > +
> > +        *reg1 &= ~XELPDP_PMDEMAND_PIPES_MASK;
> > +        tmp = old ? max(old->params.active_pipes, new->params.active_pipes) :
> > +                    new->params.active_pipes;
> > +        *reg1 |= XELPDP_PMDEMAND_PIPES(tmp);
> > +
> > +        *reg1 &= ~XELPDP_PMDEMAND_DBUFS_MASK;
> > +        tmp = old ? max(old->params.active_dbufs, new->params.active_dbufs) :
> > +                    new->params.active_dbufs;
> > +        *reg1 |= XELPDP_PMDEMAND_DBUFS(tmp);
> > +
> > +        *reg1 &= ~XELPDP_PMDEMAND_PHYS_MASK;
> > +        plls = old ? max(old->params.active_phys, new->params.active_phys) :
> > +                     new->params.active_phys;
> > +        plls = min_t(u32, plls, 7);
> > +        *reg1 |= XELPDP_PMDEMAND_PHYS(plls);
> > +
> > +        /* Set 2*/
> > +        *reg2 &= ~XELPDP_PMDEMAND_CDCLK_FREQ_MASK;
> > +        tmp = old ? max(old->params.cdclk_freq_mhz,
> > +                        new->params.cdclk_freq_mhz) :
> > +                    new->params.cdclk_freq_mhz;
> > +        *reg2 |= XELPDP_PMDEMAND_CDCLK_FREQ(tmp);
> > +
> > +        *reg2 &= ~XELPDP_PMDEMAND_DDICLK_FREQ_MASK;
> > +        tmp = old ? max(old->params.ddiclk_max, new->params.ddiclk_max) :
> > +                    new->params.ddiclk_max;
> > +        *reg2 |= XELPDP_PMDEMAND_DDICLK_FREQ(tmp);
> > +
> > +        *reg2 &= ~XELPDP_PMDEMAND_SCALERS_MASK;
> > +        tmp = old ? max(old->params.scalers, new->params.scalers) :
> > +                    new->params.scalers;
> > +        *reg2 |= XELPDP_PMDEMAND_SCALERS(tmp);
> > +
> > +        /*
> > +         * Active_PLLs starts with 1 because of CDCLK PLL.
> > +         * TODO: Missing to account genlock filter when it gets used.
> > +         */
> > +        plls = min_t(u32, plls + 1, 7);
> > +        *reg2 &= ~XELPDP_PMDEMAND_PLLS_MASK;
> > +        *reg2 |= XELPDP_PMDEMAND_PLLS(plls);
> > +}
> > +
> > +static void
> > +intel_pmdemand_program_params(struct drm_i915_private *i915,
> > +                              const struct intel_pmdemand_state *new,
> > +                              const struct intel_pmdemand_state *old)
> > +{
> > +        bool changed = false;
> > +        u32 reg1, mod_reg1;
> > +        u32 reg2, mod_reg2;
> > +
> > +        mutex_lock(&i915->display.pmdemand.lock);
> > +        if (drm_WARN_ON(&i915->drm,
> > +                        !intel_pmdemand_check_prev_transaction(i915)))
> > +                goto unlock;
> > +
> > +        reg1 = intel_de_read(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(0));
> > +        mod_reg1 = reg1;
> > +
> > +        reg2 = intel_de_read(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(1));
> > +        mod_reg2 = reg2;
> > +
> > +        intel_pmdemand_update_params(new, old, &mod_reg1, &mod_reg2);
> > +
> > +        if (reg1 != mod_reg1) {
> > +                intel_de_write(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(0),
> > +                               mod_reg1);
> > +                changed = true;
> > +        }
> > +
> > +        if (reg2 != mod_reg2) {
> > +                intel_de_write(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(1),
> > +                               mod_reg2);
> > +                changed = true;
> > +        }
> > +
> > +        /* Initiate pm demand request only if register values are changed */
> > +        if (!changed)
> > +                goto unlock;
> > +
> > +        drm_dbg_kms(&i915->drm,
> > +                    "initate pmdemand request values: (0x%x 0x%x)\n",
> > +                    mod_reg1, mod_reg2);
> > +
> > +        intel_de_rmw(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(1), 0,
> > +                     XELPDP_PMDEMAND_REQ_ENABLE);
> > +
> > +        intel_pmdemand_wait(i915);
> > +
> > +unlock:
> > +        mutex_unlock(&i915->display.pmdemand.lock);
> > +}
> > +
> > +static bool
> > +intel_pmdemand_state_changed(const struct intel_pmdemand_state *new,
> > +                             const struct intel_pmdemand_state *old)
> > +{
> > +        return memcmp(&new->params, &old->params, sizeof(new->params)) != 0;
> > +}
> > +
> > +void intel_pmdemand_pre_plane_update(struct intel_atomic_state *state)
> > +{
> > +        struct drm_i915_private *i915 = to_i915(state->base.dev);
> > +        const struct intel_pmdemand_state *new_pmdemand_state =
> > +                intel_atomic_get_new_pmdemand_state(state);
> > +        const struct intel_pmdemand_state *old_pmdemand_state =
> > +                intel_atomic_get_old_pmdemand_state(state);
> > +
> > +        if (DISPLAY_VER(i915) < 14)
> > +                return;
> > +
> > +        if (!new_pmdemand_state ||
> > +            !intel_pmdemand_state_changed(new_pmdemand_state,
> > +                                          old_pmdemand_state))
> > +                return;
> > +
> > +        WARN_ON(!new_pmdemand_state->base.changed);
> > +
> > +        intel_pmdemand_program_params(i915, new_pmdemand_state,
> > +                                      old_pmdemand_state);
> > +}
> > +
> > +void intel_pmdemand_post_plane_update(struct intel_atomic_state *state)
> > +{
> > +        struct drm_i915_private *i915 = to_i915(state->base.dev);
> > +        const struct intel_pmdemand_state *new_pmdemand_state =
> > +                intel_atomic_get_new_pmdemand_state(state);
> > +        const struct intel_pmdemand_state *old_pmdemand_state =
> > +                intel_atomic_get_old_pmdemand_state(state);
> > +
> > +        if (DISPLAY_VER(i915) < 14)
> > +                return;
> > +
> > +        if (!new_pmdemand_state ||
> > +            !intel_pmdemand_state_changed(new_pmdemand_state,
> > +                                          old_pmdemand_state))
> > +                return;
> > +
> > +        WARN_ON(!new_pmdemand_state->base.changed);
> > +
> > +        intel_pmdemand_program_params(i915, new_pmdemand_state, NULL);
> > +}
> > diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.h
> > b/drivers/gpu/drm/i915/display/intel_pmdemand.h
> > new file mode 100644
> > index 000000000000..c1c9b93934bb
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/display/intel_pmdemand.h
> > @@ -0,0 +1,56 @@
> > +/* SPDX-License-Identifier: MIT */
> > +/*
> > + * Copyright © 2023 Intel Corporation
> > + */
> > +
> > +#ifndef __INTEL_PMDEMAND_H__
> > +#define __INTEL_PMDEMAND_H__
> > +
> > +#include "intel_display_limits.h"
> > +#include "intel_global_state.h"
> > +
> > +struct drm_i915_private;
> > +struct intel_atomic_state;
> > +struct intel_crtc_state;
> > +struct intel_plane_state;
> > +
> > +struct pmdemand_params {
> > +        u16 qclk_gv_bw;
> > +        u8 voltage_index;
> > +        u8 qclk_gv_index;
> > +        u8 active_pipes;
> > +        u8 active_dbufs;
> > +        /* Total number of non type C active phys from active_phys_mask */
> > +        u8 active_phys;
> > +        u16 cdclk_freq_mhz;
> > +        /* max from ddi_clocks[] */
> > +        u16 ddiclk_max;
> > +        u8 scalers;
> > +};
> > +
> > +struct intel_pmdemand_state {
> > +        struct intel_global_state base;
> > +
> > +        /* Maintain a persistent list of port clocks across all crtcs */
> > +        int ddi_clocks[I915_MAX_PIPES];
> > +
> > +        /* Maintain a persistent list of non type C phys mask */
> > +        u16 active_phys_mask;
> > +
> > +        /* Parameters to be configured in the pmdemand registers */
> > +        struct pmdemand_params params;
> > +};
> > +
> > +#define to_intel_pmdemand_state(x) container_of((x), \
> > +                                                struct intel_pmdemand_state, \
> > +                                                base)
> > +
> > +void intel_pmdemand_init_early(struct drm_i915_private *i915);
> > +int intel_pmdemand_init(struct drm_i915_private *i915);
> > +void intel_pmdemand_program_dbuf(struct drm_i915_private *i915,
> > +                                 u8 dbuf_slices);
> > +void intel_pmdemand_pre_plane_update(struct intel_atomic_state *state);
> > +void intel_pmdemand_post_plane_update(struct intel_atomic_state *state);
> > +int intel_pmdemand_atomic_check(struct intel_atomic_state *state);
> > +
> > +#endif /* __INTEL_PMDEMAND_H__ */
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index 0523418129c5..6d34d9f59b1c 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -4418,8 +4418,10 @@
> > #define GEN8_DE_MISC_IMR _MMIO(0x44464)
> > #define GEN8_DE_MISC_IIR _MMIO(0x44468)
> > #define GEN8_DE_MISC_IER _MMIO(0x4446c)
> > -#define  GEN8_DE_MISC_GSE                (1 << 27)
> > -#define  GEN8_DE_EDP_PSR                (1 << 19)
> > +#define  XELPDP_PMDEMAND_RSPTOUT_ERR        REG_BIT(27)
> > +#define  GEN8_DE_MISC_GSE                REG_BIT(27)
> > +#define  GEN8_DE_EDP_PSR                REG_BIT(19)
> > +#define  XELPDP_PMDEMAND_RSP                REG_BIT(3)
> > 
> > #define GEN8_PCU_ISR _MMIO(0x444e0)
> > #define GEN8_PCU_IMR _MMIO(0x444e4)
> > @@ -4504,6 +4506,33 @@
> > #define  XELPDP_DP_ALT_HPD_LONG_DETECT                REG_BIT(1)
> > #define  XELPDP_DP_ALT_HPD_SHORT_DETECT                REG_BIT(0)
> > 
> > +#define XELPDP_INITIATE_PMDEMAND_REQUEST(dword)                _MMIO(0x45230 + 4 * (dword))
> > +#define  XELPDP_PMDEMAND_QCLK_GV_BW_MASK                REG_GENMASK(31, 16)
> > +#define  XELPDP_PMDEMAND_QCLK_GV_BW(x)                       
> > REG_FIELD_PREP(XELPDP_PMDEMAND_QCLK_GV_BW_MASK, x)
> > +#define  XELPDP_PMDEMAND_VOLTAGE_INDEX_MASK                REG_GENMASK(14, 12)
> > +#define  XELPDP_PMDEMAND_VOLTAGE_INDEX(x)               
> > REG_FIELD_PREP(XELPDP_PMDEMAND_VOLTAGE_INDEX_MASK, x)
> > +#define  XELPDP_PMDEMAND_QCLK_GV_INDEX_MASK                REG_GENMASK(11, 8)
> > +#define  XELPDP_PMDEMAND_QCLK_GV_INDEX(x)               
> > REG_FIELD_PREP(XELPDP_PMDEMAND_QCLK_GV_INDEX_MASK, x)
> > +#define  XELPDP_PMDEMAND_PIPES_MASK                        REG_GENMASK(7, 6)
> > +#define  XELPDP_PMDEMAND_PIPES(x)                       
> > REG_FIELD_PREP(XELPDP_PMDEMAND_PIPES_MASK, x)
> > +#define  XELPDP_PMDEMAND_DBUFS_MASK                        REG_GENMASK(5, 4)
> > +#define  XELPDP_PMDEMAND_DBUFS(x)                       
> > REG_FIELD_PREP(XELPDP_PMDEMAND_DBUFS_MASK, x)
> > +#define  XELPDP_PMDEMAND_PHYS_MASK                        REG_GENMASK(2, 0)
> > +#define  XELPDP_PMDEMAND_PHYS(x)                       
> > REG_FIELD_PREP(XELPDP_PMDEMAND_PHYS_MASK, x)
> > +
> > +#define  XELPDP_PMDEMAND_REQ_ENABLE                        REG_BIT(31)
> > +#define  XELPDP_PMDEMAND_CDCLK_FREQ_MASK                REG_GENMASK(30, 20)
> > +#define  XELPDP_PMDEMAND_CDCLK_FREQ(x)                       
> > REG_FIELD_PREP(XELPDP_PMDEMAND_CDCLK_FREQ_MASK, x)
> > +#define  XELPDP_PMDEMAND_DDICLK_FREQ_MASK                REG_GENMASK(18, 8)
> > +#define  XELPDP_PMDEMAND_DDICLK_FREQ(x)                       
> > REG_FIELD_PREP(XELPDP_PMDEMAND_DDICLK_FREQ_MASK, x)
> > +#define  XELPDP_PMDEMAND_SCALERS_MASK                        REG_GENMASK(6, 4)
> > +#define  XELPDP_PMDEMAND_SCALERS(x)                       
> > REG_FIELD_PREP(XELPDP_PMDEMAND_SCALERS_MASK, x)
> > +#define  XELPDP_PMDEMAND_PLLS_MASK                        REG_GENMASK(2, 0)
> > +#define  XELPDP_PMDEMAND_PLLS(x)                       
> > REG_FIELD_PREP(XELPDP_PMDEMAND_PLLS_MASK, x)
> > +
> > +#define GEN12_DCPR_STATUS_1                                _MMIO(0x46440)
> > +#define  XELPDP_PMDEMAND_INFLIGHT_STATUS                REG_BIT(26)
> > +
> > #define ILK_DISPLAY_CHICKEN2        _MMIO(0x42004)
> > /* Required on all Ironlake and Sandybridge according to the B-Spec. */
> > #define   ILK_ELPIN_409_SELECT        REG_BIT(25)
> > @@ -4663,6 +4692,9 @@
> > #define   DCPR_SEND_RESP_IMM                        REG_BIT(25)
> > #define   DCPR_CLEAR_MEMSTAT_DIS                REG_BIT(24)
> > 
> > +#define XELPD_CHICKEN_DCPR_3                        _MMIO(0x46438)
> > +#define   DMD_RSP_TIMEOUT_DISABLE                REG_BIT(19)
> > +
> > #define SKL_DFSM                        _MMIO(0x51000)
> > #define   SKL_DFSM_DISPLAY_PM_DISABLE        (1 << 27)
> > #define   SKL_DFSM_DISPLAY_HDCP_DISABLE        (1 << 25)
> > -- 
> > 2.34.1
> > 





[Index of Archives]     [AMD Graphics]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux