Re: [PATCH v3] drm/i915/cmtg: Disable the CMTG

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

 



On Tue, 2024-12-31 at 10:08 -0300, Gustavo Sousa wrote:
> Quoting Hogander, Jouni (2024-12-31 08:23:58-03:00)
> > On Tue, 2024-12-24 at 13:53 -0300, Gustavo Sousa wrote:
> > > The CMTG is a timing generator that runs in parallel with
> > > transcoders
> > > timing generators and can be used as a reference for
> > > synchronization.
> > > 
> > > On PTL (display Xe3_LPD), we have observed that we are inheriting
> > > from
> > > GOP a display configuration with the CMTG enabled. Because our
> > > driver
> > > doesn't currently implement any CMTG sequences, the CMTG ends up
> > > still
> > > enabled after our driver takes over.
> > > 
> > > We need to make sure that the CMTG is not enabled if we are not
> > > going
> > > to
> > > use it. For that, let's add a partial implementation in our
> > > driver
> > > that
> > > only cares about disabling the CMTG if it was found enabled
> > > during
> > > initial hardware readout. In the future, we can also implement
> > > sequences
> > > for enabling CMTG if that becomes a needed feature.
> > > 
> > > For completeness, we do not only cover Xe3_LPD but also all
> > > previous
> > > display IPs that provide the CMTG.
> > > 
> > > v2:
> > >  - DG2 does not have the CMTG. Update HAS_CMTG() accordingly.
> > >  - Update logic to force disabling of CMTG only for initial
> > > commit.
> > > v3:
> > >  - Add missing changes for v2 that were staged but not committed.
> > > 
> > > Signed-off-by: Gustavo Sousa <gustavo.sousa@xxxxxxxxx>
> > > ---
> > >  drivers/gpu/drm/i915/Makefile                 |   1 +
> > >  drivers/gpu/drm/i915/display/intel_cmtg.c     | 311
> > > ++++++++++++++++++
> > >  drivers/gpu/drm/i915/display/intel_cmtg.h     |  38 +++
> > >  .../gpu/drm/i915/display/intel_cmtg_regs.h    |  21 ++
> > >  drivers/gpu/drm/i915/display/intel_display.c  |  11 +
> > >  .../gpu/drm/i915/display/intel_display_core.h |   4 +
> > >  .../drm/i915/display/intel_display_device.h   |   1 +
> > >  .../drm/i915/display/intel_display_driver.c   |   5 +
> > >  .../drm/i915/display/intel_modeset_setup.c    |   5 +
> > >  drivers/gpu/drm/i915/i915_reg.h               |   1 +
> > >  drivers/gpu/drm/xe/Makefile                   |   1 +
> > >  11 files changed, 399 insertions(+)
> > >  create mode 100644 drivers/gpu/drm/i915/display/intel_cmtg.c
> > >  create mode 100644 drivers/gpu/drm/i915/display/intel_cmtg.h
> > >  create mode 100644
> > > drivers/gpu/drm/i915/display/intel_cmtg_regs.h
> > > 
> > > diff --git a/drivers/gpu/drm/i915/Makefile
> > > b/drivers/gpu/drm/i915/Makefile
> > > index 3dda9f0eda82..7e7414453765 100644
> > > --- a/drivers/gpu/drm/i915/Makefile
> > > +++ b/drivers/gpu/drm/i915/Makefile
> > > @@ -231,6 +231,7 @@ i915-y += \
> > >          display/intel_bo.o \
> > >          display/intel_bw.o \
> > >          display/intel_cdclk.o \
> > > +        display/intel_cmtg.o \
> > >          display/intel_color.o \
> > >          display/intel_combo_phy.o \
> > >          display/intel_connector.o \
> > > diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.c
> > > b/drivers/gpu/drm/i915/display/intel_cmtg.c
> > > new file mode 100644
> > > index 000000000000..27491497f515
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/i915/display/intel_cmtg.c
> > > @@ -0,0 +1,311 @@
> > > +// SPDX-License-Identifier: MIT
> > > +/*
> > > + * Copyright (C) 2024 Intel Corporation
> > > + */
> > > +
> > > +#include <linux/string.h>
> > > +#include <linux/string_choices.h>
> > > +#include <linux/types.h>
> > > +
> > > +#include "i915_drv.h"
> > > +#include "i915_reg.h"
> > > +#include "intel_crtc.h"
> > > +#include "intel_de.h"
> > > +#include "intel_cmtg.h"
> > > +#include "intel_cmtg_regs.h"
> > > +#include "intel_display_device.h"
> > > +#include "intel_display_types.h"
> > > +
> > > +/**
> > > + * DOC: Common Primary Timing Generator (CMTG)
> > > + *
> > > + * The CMTG is a timing generator that runs in parallel to
> > > transcoders timing
> > > + * generators (TG) to provide a synchronization mechanism where
> > > CMTG
> > > acts as
> > > + * primary and transcoders TGs act as secondary to the CMTG. The
> > > CMTG outputs
> > > + * its TG start and frame sync signals to the transcoders that
> > > are
> > > configured
> > > + * as secondary, which use those signals to synchronize their
> > > own
> > > timing with
> > > + * the CMTG's.
> > > + *
> > > + * The CMTG can be used only with eDP or MIPI command mode and
> > > supports the
> > > + * following use cases:
> > > + *
> > > + * - Dual eDP: The CMTG can be used to keep two eDP TGs in sync
> > > when
> > > on a
> > > + *   dual eDP configuration (with or without PSR/PSR2 enabled).
> > > + *
> > > + * - Single eDP as secondary: It is also possible to use a
> > > single
> > > eDP
> > > + *   configuration with the transcoder TG as secondary to the
> > > CMTG.
> > > That would
> > > + *   allow a flow that would not require a modeset on the
> > > existing
> > > eDP when a
> > > + *   new eDP is added for a dual eDP configuration with CMTG.
> > > + *
> > > + * - DC6v: In DC6v, the transcoder might be off but the CMTG
> > > keeps
> > > running to
> > > + *   maintain frame timings. When exiting DC6v, the transcoder
> > > TG
> > > then is
> > > + *   synced back the CMTG.
> > > + *
> > > + * Currently, the driver does not use the CMTG, but we need to
> > > make
> > > sure that
> > > + * we disable it in case we inherit a display configuration with
> > > it
> > > enabled.
> > > + */
> > > +
> > > +static struct intel_global_state *
> > > +intel_cmtg_duplicate_state(struct intel_global_obj *obj)
> > > +{
> > > +        struct intel_cmtg_state *cmtg_state =
> > > to_intel_cmtg_state(obj->state);
> > > +
> > > +        cmtg_state = kmemdup(cmtg_state, sizeof(*cmtg_state),
> > > GFP_KERNEL);
> > > +        if (!cmtg_state)
> > > +                return NULL;
> > > +
> > > +        return &cmtg_state->base;
> > > +}
> > > +
> > > +static void intel_cmtg_destroy_state(struct intel_global_obj
> > > *obj,
> > > +                                     struct intel_global_state
> > > *state)
> > > +{
> > > +        kfree(state);
> > > +}
> > > +
> > > +static const struct intel_global_state_funcs
> > > intel_cmtg_state_funcs
> > > = {
> > > +        .atomic_duplicate_state = intel_cmtg_duplicate_state,
> > > +        .atomic_destroy_state = intel_cmtg_destroy_state,
> > > +};
> > > +
> > > +static bool intel_cmtg_has_cmtg_b(struct intel_display *display)
> > > +{
> > > +        return DISPLAY_VER(display) >= 20;
> > > +}
> > > +
> > > +static bool intel_cmtg_has_clock_sel(struct intel_display
> > > *display)
> > > +{
> > > +        return DISPLAY_VER(display) >= 14;
> > > +}
> > > +
> > > +static bool intel_cmtg_requires_modeset(struct intel_display
> > > *display)
> > > +{
> > > +        return DISPLAY_VER(display) < 20;
> > > +}
> > > +
> > > +static void intel_cmtg_dump_state(struct intel_display *display,
> > > +                                  struct intel_cmtg_state
> > > *cmtg_state)
> > > +{
> > > +        if (intel_cmtg_has_cmtg_b(display))
> > > +                drm_dbg_kms(display->drm,
> > > +                            "CMTG state readout: CMTG A: %s,
> > > CMTG B:
> > > %s, transcoder A secondary: %s, transcoder B secondary: %s\n",
> > > +                            str_enabled_disabled(cmtg_state-
> > > > cmtg_a_enable),
> > > +                            str_enabled_disabled(cmtg_state-
> > > > cmtg_b_enable),
> > > +                            str_yes_no(cmtg_state-
> > > > trans_a_secondary),
> > > +                            str_yes_no(cmtg_state-
> > > > trans_b_secondary));
> > > +        else
> > > +                drm_dbg_kms(display->drm,
> > > +                            "CMTG state readout: %s, Transcoder
> > > A
> > > secondary: %s, Transcoder B secondary: %s\n",
> > > +                            str_enabled_disabled(cmtg_state-
> > > > cmtg_a_enable),
> > > +                            str_yes_no(cmtg_state-
> > > > trans_a_secondary),
> > > +                            str_yes_no(cmtg_state-
> > > > trans_b_secondary));
> > > +}
> > > +
> > > +int intel_cmtg_init(struct intel_display *display)
> > > +{
> > > +        struct drm_i915_private *i915 = to_i915(display->drm);
> > > +        struct intel_cmtg_state *cmtg_state;
> > > +
> > > +        cmtg_state = kzalloc(sizeof(*cmtg_state), GFP_KERNEL);
> > > +        if (!cmtg_state)
> > > +                return -ENOMEM;
> > > +
> > > +        intel_atomic_global_obj_init(i915, &display->cmtg.obj,
> > > +                                     &cmtg_state->base,
> > > +                                     &intel_cmtg_state_funcs);
> > > +
> > > +        return 0;
> > > +}
> > > +
> > > +void intel_cmtg_readout_state(struct intel_display *display,
> > > +                              struct intel_cmtg_state
> > > *cmtg_state)
> > > +{
> > > +        struct drm_i915_private *i915 = to_i915(display->drm);
> > > +        u32 val;
> > > +
> > > +        if (!HAS_CMTG(display))
> > > +                return;
> > > +
> > > +        val = intel_de_read(display, TRANS_CMTG_CTL_A);
> > > +        cmtg_state->cmtg_a_enable = val & CMTG_ENABLE;
> > > +
> > > +        if (intel_cmtg_has_cmtg_b(display)) {
> > > +                val = intel_de_read(display, TRANS_CMTG_CTL_B);
> > > +                cmtg_state->cmtg_b_enable = val & CMTG_ENABLE;
> > > +        }
> > > +
> > > +        if (intel_crtc_for_pipe(display, PIPE_A)) {
> > > +                val = intel_de_read(display,
> > > TRANS_DDI_FUNC_CTL2(i915, TRANSCODER_A));
> > > +                cmtg_state->trans_a_secondary = val &
> > > CMTG_SECONDARY_MODE;
> > > +        }
> > > +
> > > +        if (intel_crtc_for_pipe(display, PIPE_B)) {
> > > +                val = intel_de_read(display,
> > > TRANS_DDI_FUNC_CTL2(i915, TRANSCODER_B));
> > > +                cmtg_state->trans_b_secondary = val &
> > > CMTG_SECONDARY_MODE;
> > > +        }
> > > +
> > > +        intel_cmtg_dump_state(display, cmtg_state);
> > > +}
> > > +
> > > +static struct intel_cmtg_state *
> > > +intel_atomic_get_cmtg_state(struct intel_atomic_state *state)
> > > +{
> > > +        struct intel_display *display = to_intel_display(state);
> > > +        struct intel_global_state *obj_state =
> > > +                intel_atomic_get_global_obj_state(state,
> > > +                                                  &display-
> > > > cmtg.obj);
> > > +
> > > +        if (IS_ERR(obj_state))
> > > +                return ERR_CAST(obj_state);
> > > +
> > > +        return to_intel_cmtg_state(obj_state);
> > > +}
> > > +
> > > +static struct intel_cmtg_state *
> > > +intel_atomic_get_old_cmtg_state(struct intel_atomic_state
> > > *state)
> > > +{
> > > +        struct intel_display *display = to_intel_display(state);
> > > +        struct intel_global_state *obj_state =
> > > +                intel_atomic_get_old_global_obj_state(state,
> > > +                                                      &display-
> > > > cmtg.obj);
> > > +
> > > +        if (!obj_state)
> > > +                return NULL;
> > > +
> > > +        return to_intel_cmtg_state(obj_state);
> > > +}
> > > +
> > > +static struct intel_cmtg_state *
> > > +intel_atomic_get_new_cmtg_state(struct intel_atomic_state
> > > *state)
> > > +{
> > > +        struct intel_display *display = to_intel_display(state);
> > > +        struct intel_global_state *obj_state =
> > > +                intel_atomic_get_new_global_obj_state(state,
> > > +                                                      &display-
> > > > cmtg.obj);
> > > +
> > > +        if (!obj_state)
> > > +                return NULL;
> > > +
> > > +        return to_intel_cmtg_state(obj_state);
> > > +}
> > > +
> > > +static bool intel_cmtg_state_changed(struct intel_cmtg_state
> > > *old_cmtg_state,
> > > +                                     struct intel_cmtg_state
> > > *new_cmtg_state)
> > > +{
> > > +        if (!new_cmtg_state)
> > > +                return false;
> > > +
> > > +        return old_cmtg_state->cmtg_a_enable != new_cmtg_state-
> > > > cmtg_a_enable ||
> > > +                old_cmtg_state->cmtg_b_enable != new_cmtg_state-
> > > > cmtg_b_enable ||
> > > +                old_cmtg_state->trans_a_secondary !=
> > > new_cmtg_state-
> > > > trans_a_secondary ||
> > > +                old_cmtg_state->trans_b_secondary !=
> > > new_cmtg_state-
> > > > trans_b_secondary;
> > > +}
> > > +
> > > +static int intel_cmtg_check_modeset(struct intel_atomic_state
> > > *state,
> > > +                                    struct intel_cmtg_state
> > > *old_cmtg_state,
> > > +                                    struct intel_cmtg_state
> > > *new_cmtg_state)
> > > +{
> > > +        struct intel_display *display = to_intel_display(state);
> > > +        u8 pipe_mask;
> > > +
> > > +        if (!intel_cmtg_requires_modeset(display))
> > > +                return 0;
> > > +
> > > +        pipe_mask = 0;
> > > +
> > > +        if (old_cmtg_state->trans_a_secondary != new_cmtg_state-
> > > > trans_a_secondary)
> > > +                pipe_mask |= BIT(PIPE_A);
> > > +
> > > +        if (old_cmtg_state->trans_b_secondary != new_cmtg_state-
> > > > trans_b_secondary)
> > > +                pipe_mask |= BIT(PIPE_B);
> > 
> > On PTL this would mean we are always doing full modeset on boot? Is
> 
> No. Because of intel_cmtg_requires_modeset(), we only go through this
> if
> we are on a display prior to Xe2_LPD (LNL's display). So, for PTL, a
> modeset will not be required.
> 
> > full modeset really required when disabling CTMG? Bspec says:
> > 
> > "Switching between the local timing generator within the eDP and
> > the
> > CMTG will require a modeset."
> 
> This is from the BSpec for pre-LNL displays (i.e. pre-Xe2_LPD). The
> BSpec for LNL and PTL does not impose this restriction.
> 
> > 
> > Are we really using CTMG or is it just enabled?
> 
> The setup from GOP is using the CMTG with Pipe A.

Ok, thank you for the clarification.

BR,

Jouni Högander

> 
> --
> Gustavo Sousa
> 
> > 
> > BR,
> > 
> > Jouni Högander
> > 
> > > +
> > > +        if (!pipe_mask)
> > > +                return 0;
> > > +
> > > +        return intel_modeset_pipes_in_mask_early(state,
> > > "updating
> > > CMTG config", pipe_mask);
> > > +}
> > > +
> > > +int intel_cmtg_force_disabled(struct intel_atomic_state *state)
> > > +{
> > > +        struct intel_display *display = to_intel_display(state);
> > > +        struct intel_cmtg_state *new_cmtg_state;
> > > +
> > > +        if (!HAS_CMTG(display))
> > > +                return 0;
> > > +
> > > +        new_cmtg_state = intel_atomic_get_cmtg_state(state);
> > > +        if (IS_ERR(new_cmtg_state))
> > > +                return PTR_ERR(new_cmtg_state);
> > > +
> > > +        new_cmtg_state->cmtg_a_enable = false;
> > > +        new_cmtg_state->cmtg_b_enable = false;
> > > +        new_cmtg_state->trans_a_secondary = false;
> > > +        new_cmtg_state->trans_b_secondary = false;
> > > +        return 0;
> > > +}
> > > +
> > > +int intel_cmtg_atomic_check(struct intel_atomic_state *state)
> > > +{
> > > +        struct intel_display *display = to_intel_display(state);
> > > +        struct intel_cmtg_state *old_cmtg_state;
> > > +        struct intel_cmtg_state *new_cmtg_state;
> > > +        int ret;
> > > +
> > > +        if (!HAS_CMTG(display))
> > > +                return 0;
> > > +
> > > +        old_cmtg_state = intel_atomic_get_old_cmtg_state(state);
> > > +        new_cmtg_state = intel_atomic_get_new_cmtg_state(state);
> > > +        if (!intel_cmtg_state_changed(old_cmtg_state,
> > > new_cmtg_state))
> > > +                return 0;
> > > +
> > > +        ret = intel_cmtg_check_modeset(state, old_cmtg_state,
> > > new_cmtg_state);
> > > +        if (ret)
> > > +                return ret;
> > > +
> > > +        return
> > > intel_atomic_serialize_global_state(&new_cmtg_state-
> > > > base);
> > > +}
> > > +
> > > +/*
> > > + * Access to CMTG registers require the PHY PLL that provides
> > > its
> > > clock to be
> > > + * running (which is configured via CMTG_CLK_SEL). As such, this
> > > function needs
> > > + * to be called before intel_commit_modeset_disables() to ensure
> > > that the PHY
> > > + * PLL is still enabled when doing this.
> > > + */
> > > +void intel_cmtg_disable(struct intel_atomic_state *state)
> > > +{
> > > +        struct intel_display *display = to_intel_display(state);
> > > +        struct drm_i915_private *i915 = to_i915(display->drm);
> > > +        struct intel_cmtg_state *old_cmtg_state;
> > > +        struct intel_cmtg_state *new_cmtg_state;
> > > +
> > > +        if (!HAS_CMTG(display))
> > > +                return;
> > > +
> > > +        old_cmtg_state = intel_atomic_get_old_cmtg_state(state);
> > > +        new_cmtg_state = intel_atomic_get_new_cmtg_state(state);
> > > +        if (!intel_cmtg_state_changed(old_cmtg_state,
> > > new_cmtg_state))
> > > +                return;
> > > +
> > > +        drm_info(display->drm, "Disabling CMTG\n");
> > > +
> > > +        intel_de_rmw(display, TRANS_DDI_FUNC_CTL2(i915,
> > > TRANSCODER_A), CMTG_SECONDARY_MODE, 0);
> > > +        intel_de_rmw(display, TRANS_DDI_FUNC_CTL2(i915,
> > > TRANSCODER_B), CMTG_SECONDARY_MODE, 0);
> > > +
> > > +        intel_de_rmw(display, TRANS_CMTG_CTL_A, CMTG_ENABLE, 0);
> > > +
> > > +        if (intel_cmtg_has_cmtg_b(display))
> > > +                intel_de_rmw(display, TRANS_CMTG_CTL_B,
> > > CMTG_ENABLE,
> > > 0);
> > > +
> > > +        if (intel_cmtg_has_clock_sel(display)) {
> > > +                u32 clk_sel_clr = CMTG_CLK_SEL_A_MASK;
> > > +                u32 clk_sel_set = CMTG_CLK_SEL_A_DISABLED;
> > > +
> > > +                if (intel_cmtg_has_cmtg_b(display)) {
> > > +                        clk_sel_clr |= CMTG_CLK_SEL_B_MASK;
> > > +                        clk_sel_set |= CMTG_CLK_SEL_B_DISABLED;
> > > +                }
> > > +
> > > +                intel_de_rmw(display, CMTG_CLK_SEL, clk_sel_clr,
> > > clk_sel_set);
> > > +        }
> > > +}
> > > diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.h
> > > b/drivers/gpu/drm/i915/display/intel_cmtg.h
> > > new file mode 100644
> > > index 000000000000..4dfd31906d81
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/i915/display/intel_cmtg.h
> > > @@ -0,0 +1,38 @@
> > > +/* SPDX-License-Identifier: MIT */
> > > +/*
> > > + * Copyright (C) 2024 Intel Corporation
> > > + */
> > > +
> > > +#ifndef __INTEL_CMTG_H__
> > > +#define __INTEL_CMTG_H__
> > > +
> > > +#include "intel_display_core.h"
> > > +#include "intel_global_state.h"
> > > +
> > > +/*
> > > + * We describe here only the minimum state required to allow us
> > > to
> > > properly
> > > + * disable the CMTG if necessary.
> > > + */
> > > +struct intel_cmtg_state {
> > > +        struct intel_global_state base;
> > > +
> > > +        bool cmtg_a_enable;
> > > +        /*
> > > +         * Xe3_LPD adds a second CMTG that can be used for dual
> > > eDP
> > > async mode.
> > > +         */
> > > +        bool cmtg_b_enable;
> > > +        bool trans_a_secondary;
> > > +        bool trans_b_secondary;
> > > +};
> > > +
> > > +#define to_intel_cmtg_state(global_state) \
> > > +        container_of_const((global_state), struct
> > > intel_cmtg_state,
> > > base)
> > > +
> > > +int intel_cmtg_init(struct intel_display *display);
> > > +void intel_cmtg_readout_state(struct intel_display *display,
> > > +                              struct intel_cmtg_state
> > > *cmtg_state);
> > > +int intel_cmtg_force_disabled(struct intel_atomic_state *state);
> > > +int intel_cmtg_atomic_check(struct intel_atomic_state *state);
> > > +void intel_cmtg_disable(struct intel_atomic_state *state);
> > > +
> > > +#endif /* __INTEL_CMTG_H__ */
> > > diff --git a/drivers/gpu/drm/i915/display/intel_cmtg_regs.h
> > > b/drivers/gpu/drm/i915/display/intel_cmtg_regs.h
> > > new file mode 100644
> > > index 000000000000..082f96cad284
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/i915/display/intel_cmtg_regs.h
> > > @@ -0,0 +1,21 @@
> > > +/* SPDX-License-Identifier: MIT */
> > > +/*
> > > + * Copyright (C) 2024 Intel Corporation
> > > + */
> > > +
> > > +#ifndef __INTEL_CMTG_REGS_H__
> > > +#define __INTEL_CMTG_REGS_H__
> > > +
> > > +#include "i915_reg_defs.h"
> > > +
> > > +#define CMTG_CLK_SEL                        _MMIO(0x46160)
> > > +#define CMTG_CLK_SEL_A_MASK                REG_GENMASK(31, 29)
> > > +#define
> > > CMTG_CLK_SEL_A_DISABLED               
> > > REG_FIELD_PREP(CMTG_CLK_SEL_A_MASK, 0)
> > > +#define CMTG_CLK_SEL_B_MASK                REG_GENMASK(15, 13)
> > > +#define
> > > CMTG_CLK_SEL_B_DISABLED               
> > > REG_FIELD_PREP(CMTG_CLK_SEL_B_MASK, 0)
> > > +
> > > +#define TRANS_CMTG_CTL_A                _MMIO(0x6fa88)
> > > +#define TRANS_CMTG_CTL_B                _MMIO(0x6fb88)
> > > +#define  CMTG_ENABLE                        REG_BIT(31)
> > > +
> > > +#endif /* __INTEL_CMTG_REGS_H__ */
> > > diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> > > b/drivers/gpu/drm/i915/display/intel_display.c
> > > index 4271da219b41..098985ad7ad4 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > > @@ -62,6 +62,7 @@
> > >  #include "intel_bw.h"
> > >  #include "intel_cdclk.h"
> > >  #include "intel_clock_gating.h"
> > > +#include "intel_cmtg.h"
> > >  #include "intel_color.h"
> > >  #include "intel_crt.h"
> > >  #include "intel_crtc.h"
> > > @@ -6828,6 +6829,10 @@ int intel_atomic_check(struct drm_device
> > > *dev,
> > >          if (ret)
> > >                  goto fail;
> > >  
> > > +        ret = intel_cmtg_atomic_check(state);
> > > +        if (ret)
> > > +                goto fail;
> > > +
> > >          for_each_new_intel_crtc_in_state(state, crtc,
> > > new_crtc_state, i) {
> > >                  if (!intel_crtc_needs_modeset(new_crtc_state))
> > >                          continue;
> > > @@ -7757,6 +7762,8 @@ static void intel_atomic_commit_tail(struct
> > > intel_atomic_state *state)
> > >                         
> > > intel_modeset_get_crtc_power_domains(new_crt
> > > c_state, &put_domains[crtc->pipe]);
> > >          }
> > >  
> > > +        intel_cmtg_disable(state);
> > > +
> > >          intel_commit_modeset_disables(state);
> > >  
> > >          intel_dp_tunnel_atomic_alloc_bw(state);
> > > @@ -8582,6 +8589,10 @@ int intel_initial_commit(struct drm_device
> > > *dev)
> > >                  }
> > >          }
> > >  
> > > +        ret =
> > > intel_cmtg_force_disabled(to_intel_atomic_state(state));
> > > +        if (ret)
> > > +                goto out;
> > > +
> > >          ret = drm_atomic_commit(state);
> > >  
> > >  out:
> > > diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h
> > > b/drivers/gpu/drm/i915/display/intel_display_core.h
> > > index 554870d2494b..d0b039114e2d 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_display_core.h
> > > +++ b/drivers/gpu/drm/i915/display/intel_display_core.h
> > > @@ -354,6 +354,10 @@ struct intel_display {
> > >                  unsigned int skl_preferred_vco_freq;
> > >          } cdclk;
> > >  
> > > +        struct {
> > > +                struct intel_global_obj obj;
> > > +        } cmtg;
> > > +
> > >          struct {
> > >                  struct drm_property_blob
> > > *glk_linear_degamma_lut;
> > >          } color;
> > > diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h
> > > b/drivers/gpu/drm/i915/display/intel_display_device.h
> > > index 9a333d9e6601..a126247eb6b8 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_display_device.h
> > > +++ b/drivers/gpu/drm/i915/display/intel_display_device.h
> > > @@ -145,6 +145,7 @@ struct intel_display_platforms {
> > >  #define HAS_BIGJOINER(__display)        (DISPLAY_VER(__display)
> > > >=
> > > 11 && HAS_DSC(__display))
> > >  #define HAS_CDCLK_CRAWL(__display)       
> > > (DISPLAY_INFO(__display)-
> > > > has_cdclk_crawl)
> > >  #define HAS_CDCLK_SQUASH(__display)       
> > > (DISPLAY_INFO(__display)-
> > > > has_cdclk_squash)
> > > +#define HAS_CMTG(__display)                (!(__display)-
> > > >platform.dg2
> > > && DISPLAY_VER(__display) >= 13)
> > >  #define HAS_CUR_FBC(__display)               
> > > (!HAS_GMCH(__display) &&
> > > IS_DISPLAY_VER(__display, 7, 13))
> > >  #define HAS_D12_PLANE_MINIMIZATION(__display)       
> > > ((__display)-
> > > > platform.rocketlake || (__display)->platform.alderlake_s)
> > >  #define
> > > HAS_DBUF_OVERLAP_DETECTION(__display)       
> > > (DISPLAY_RUNTIME_INFO(__display)->has_dbuf_overlap_detection)
> > > diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c
> > > b/drivers/gpu/drm/i915/display/intel_display_driver.c
> > > index 497b4a1f045f..3e1483814e8d 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_display_driver.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c
> > > @@ -25,6 +25,7 @@
> > >  #include "intel_bios.h"
> > >  #include "intel_bw.h"
> > >  #include "intel_cdclk.h"
> > > +#include "intel_cmtg.h"
> > >  #include "intel_color.h"
> > >  #include "intel_crtc.h"
> > >  #include "intel_display_debugfs.h"
> > > @@ -269,6 +270,10 @@ int intel_display_driver_probe_noirq(struct
> > > intel_display *display)
> > >          if (ret)
> > >                  goto cleanup_vga_client_pw_domain_dmc;
> > >  
> > > +        ret = intel_cmtg_init(display);
> > > +        if (ret)
> > > +                goto cleanup_vga_client_pw_domain_dmc;
> > > +
> > >          intel_init_quirks(display);
> > >  
> > >          intel_fbc_init(display);
> > > diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c
> > > b/drivers/gpu/drm/i915/display/intel_modeset_setup.c
> > > index 9db30db428f7..737a43916ac5 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c
> > > @@ -15,6 +15,7 @@
> > >  #include "i9xx_wm.h"
> > >  #include "intel_atomic.h"
> > >  #include "intel_bw.h"
> > > +#include "intel_cmtg.h"
> > >  #include "intel_color.h"
> > >  #include "intel_crtc.h"
> > >  #include "intel_crtc_state_dump.h"
> > > @@ -702,6 +703,8 @@ static void
> > > intel_modeset_readout_hw_state(struct
> > > drm_i915_private *i915)
> > >          struct intel_display *display = &i915->display;
> > >          struct intel_cdclk_state *cdclk_state =
> > >                  to_intel_cdclk_state(i915-
> > > >display.cdclk.obj.state);
> > > +        struct intel_cmtg_state *cmtg_state =
> > > +                to_intel_cmtg_state(display->cmtg.obj.state);
> > >          struct intel_dbuf_state *dbuf_state =
> > >                  to_intel_dbuf_state(i915-
> > > >display.dbuf.obj.state);
> > >          struct intel_pmdemand_state *pmdemand_state =
> > > @@ -906,6 +909,8 @@ static void
> > > intel_modeset_readout_hw_state(struct
> > > drm_i915_private *i915)
> > >          }
> > >  
> > >          intel_pmdemand_init_pmdemand_params(i915,
> > > pmdemand_state);
> > > +
> > > +        intel_cmtg_readout_state(display, cmtg_state);
> > >  }
> > >  
> > >  static void
> > > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > > b/drivers/gpu/drm/i915/i915_reg.h
> > > index 765e6c0528fb..b34bccfb1ccc 100644
> > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > @@ -3565,6 +3565,7 @@ enum skl_power_gate {
> > >  #define _TRANS_DDI_FUNC_CTL2_DSI1        0x6bc04
> > >  #define TRANS_DDI_FUNC_CTL2(dev_priv,
> > > tran)        _MMIO_TRANS2(dev_priv, tran, _TRANS_DDI_FUNC_CTL2_A)
> > >  #define  PORT_SYNC_MODE_ENABLE                        REG_BIT(4)
> > > +#define  CMTG_SECONDARY_MODE                        REG_BIT(3)
> > >  #define  PORT_SYNC_MODE_MASTER_SELECT_MASK        REG_GENMASK(2,
> > > 0)
> > >  #define 
> > > PORT_SYNC_MODE_MASTER_SELECT(x)       
> > > REG_FIELD_PREP(PORT_SYNC_MODE_MASTER_SELECT_MASK,(x))
> > >  
> > > diff --git a/drivers/gpu/drm/xe/Makefile
> > > b/drivers/gpu/drm/xe/Makefile
> > > index 5c97ad6ed738..cd0e25fce14b 100644
> > > --- a/drivers/gpu/drm/xe/Makefile
> > > +++ b/drivers/gpu/drm/xe/Makefile
> > > @@ -199,6 +199,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \
> > >          i915-display/intel_bios.o \
> > >          i915-display/intel_bw.o \
> > >          i915-display/intel_cdclk.o \
> > > +        i915-display/intel_cmtg.o \
> > >          i915-display/intel_color.o \
> > >          i915-display/intel_combo_phy.o \
> > >          i915-display/intel_connector.o \
> > 





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

  Powered by Linux