Commit a22c074f authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-next-2021-08-10-1' of...

Merge tag 'drm-intel-next-2021-08-10-1' of git://anongit.freedesktop.org/drm/drm-intel into drm-next

drm/i915 changes for v5.15:

Features:
- Basic DG2 platform enabling (Matt, Animesh, Gwan-gyeong, José)
- Add PSF GV point support for display bandwidth calculation (Stan)
- Add platform release id version support (Lucas)
- Add support for forcing DSC BPP for testing (Vandita, Patnana)

Refactoring and cleanups:
- Remove CNL support completely (Lucas)
- Revid/stepping cleanup (Matt, Anusha)
- Make display stepping check upper bounds exclusive (Matt)
- Remove old GEN macros (Lucas)
- Refactor DG1 interrupt handler (Paulo)
- Refactor DMC stepping info (Anusha)

Fixes:
- Fix XELPD color capability reporting; it's not yet enabled (Uma)
- Fix DG1 memory bandwidth computation (Clint)
- Fix mux on certain HP laptops (Kai-Heng)
- Various display workarounds (José, Matt, Imre)
- Fix error state dumps wrt SFC_DONE (Matt)
- Fix DG1 and XEPLD audio power domains (Anshuman)
- Fix ADL-P and ADL-S ddi buf translation tables (Matt)
- Fix DP/HDMI modeset sequences causing issues on ADL-P (José)
- PSR2 fixes (José)
- Fix DP MST modeset with FEC on TGL+
- Fix MBUS DBOX A credits on ADL-P (José)
- Fix DP PHY test training set programming (Khaled)
- Fix dgfx pcode uncore init done wait (Badal)
- Fix DSC disable fuse check on GLK (Lucas)
- Fix shared dpll mismatch for bigjoiner secondary pipe (Manasi)
- Fix ADL-P underrun recovery (Matt)
- Fix permissions on FEC support debugfs file (Vandita)

Misc:
- Backmerge drm-next (Rodrigo)
- Bump RKL and TGL DMC firmware version (Anusha)
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

# Conflicts:
#	drivers/gpu/drm/i915/i915_drv.h
#	drivers/gpu/drm/i915/intel_device_info.h
From: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/87a6lpo1a9.fsf@intel.com
parents cb22f12f 3bfa7d40
......@@ -269,6 +269,7 @@ i915-y += \
display/intel_pps.o \
display/intel_qp_tables.o \
display/intel_sdvo.o \
display/intel_snps_phy.o \
display/intel_tv.o \
display/intel_vdsc.o \
display/intel_vrr.o \
......
......@@ -912,7 +912,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
zpos = 0;
drm_plane_create_zpos_immutable_property(&plane->base, zpos);
drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
intel_plane_helper_add(plane);
return plane;
......
......@@ -19,6 +19,12 @@ static const guid_t intel_dsm_guid =
GUID_INIT(0x7ed873d3, 0xc2d0, 0x4e4f,
0xa8, 0x54, 0x0f, 0x13, 0x17, 0xb0, 0x1c, 0x2c);
#define INTEL_DSM_FN_GET_BIOS_DATA_FUNCS_SUPPORTED 0 /* No args */
static const guid_t intel_dsm_guid2 =
GUID_INIT(0x3e5b41c6, 0xeb1d, 0x4260,
0x9d, 0x15, 0xc7, 0x1f, 0xba, 0xda, 0xe4, 0x14);
static char *intel_dsm_port_name(u8 id)
{
switch (id) {
......@@ -176,6 +182,19 @@ void intel_unregister_dsm_handler(void)
{
}
void intel_dsm_get_bios_data_funcs_supported(struct drm_i915_private *i915)
{
struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
acpi_handle dhandle;
dhandle = ACPI_HANDLE(&pdev->dev);
if (!dhandle)
return;
acpi_evaluate_dsm(dhandle, &intel_dsm_guid2, INTEL_DSM_REVISION_ID,
INTEL_DSM_FN_GET_BIOS_DATA_FUNCS_SUPPORTED, NULL);
}
/*
* ACPI Specification, Revision 5.0, Appendix B.3.2 _DOD (Enumerate All Devices
* Attached to the Display Adapter).
......
......@@ -11,11 +11,14 @@ struct drm_i915_private;
#ifdef CONFIG_ACPI
void intel_register_dsm_handler(void);
void intel_unregister_dsm_handler(void);
void intel_dsm_get_bios_data_funcs_supported(struct drm_i915_private *i915);
void intel_acpi_device_id_update(struct drm_i915_private *i915);
#else
static inline void intel_register_dsm_handler(void) { return; }
static inline void intel_unregister_dsm_handler(void) { return; }
static inline
void intel_dsm_get_bios_data_funcs_supported(struct drm_i915_private *i915) { return; }
static inline
void intel_acpi_device_id_update(struct drm_i915_private *i915) { return; }
#endif /* CONFIG_ACPI */
......
......@@ -601,7 +601,12 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state,
return 0;
}
const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
static const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
.prepare_fb = intel_prepare_plane_fb,
.cleanup_fb = intel_cleanup_plane_fb,
};
void intel_plane_helper_add(struct intel_plane *plane)
{
drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
}
......@@ -17,8 +17,6 @@ struct intel_crtc_state;
struct intel_plane;
struct intel_plane_state;
extern const struct drm_plane_helper_funcs intel_plane_helper_funcs;
unsigned int intel_adjusted_rate(const struct drm_rect *src,
const struct drm_rect *dst,
unsigned int rate);
......@@ -65,5 +63,6 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state,
bool can_position);
void intel_plane_set_invisible(struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state);
void intel_plane_helper_add(struct intel_plane *plane);
#endif /* __INTEL_ATOMIC_PLANE_H__ */
......@@ -1001,7 +1001,7 @@ static unsigned long i915_audio_component_get_power(struct device *kdev)
/* Catch potential impedance mismatches before they occur! */
BUILD_BUG_ON(sizeof(intel_wakeref_t) > sizeof(unsigned long));
ret = intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
ret = intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO_PLAYBACK);
if (dev_priv->audio_power_refcount++ == 0) {
if (DISPLAY_VER(dev_priv) >= 9) {
......@@ -1034,7 +1034,7 @@ static void i915_audio_component_put_power(struct device *kdev,
if (IS_GEMINILAKE(dev_priv))
glk_force_audio_cdclk(dev_priv, false);
intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO, cookie);
intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO_PLAYBACK, cookie);
}
static void i915_audio_component_codec_wake_override(struct device *kdev,
......
......@@ -1871,12 +1871,12 @@ intel_bios_encoder_supports_edp(const struct intel_bios_encoder_data *devdata)
static bool is_port_valid(struct drm_i915_private *i915, enum port port)
{
/*
* On some ICL/CNL SKUs port F is not present, but broken VBTs mark
* On some ICL SKUs port F is not present, but broken VBTs mark
* the port as present. Only try to initialize port F for the
* SKUs that may actually have it.
*/
if (port == PORT_F && (IS_ICELAKE(i915) || IS_CANNONLAKE(i915)))
return IS_ICL_WITH_PORT_F(i915) || IS_CNL_WITH_PORT_F(i915);
if (port == PORT_F && IS_ICELAKE(i915))
return IS_ICL_WITH_PORT_F(i915);
return true;
}
......@@ -1998,7 +1998,7 @@ static void parse_ddi_port(struct drm_i915_private *i915,
"Port %c VBT HDMI boost level: %d\n",
port_name(port), hdmi_boost_level);
/* DP max link rate for CNL+ */
/* DP max link rate for GLK+ */
if (i915->vbt.version >= 216) {
if (i915->vbt.version >= 230)
info->dp_max_link_rate = parse_bdb_230_dp_max_link_rate(child->dp_max_link_rate);
......@@ -2166,7 +2166,8 @@ static void
init_vbt_missing_defaults(struct drm_i915_private *i915)
{
enum port port;
int ports = PORT_A | PORT_B | PORT_C | PORT_D | PORT_E | PORT_F;
int ports = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) |
BIT(PORT_D) | BIT(PORT_E) | BIT(PORT_F);
if (!HAS_DDI(i915) && !IS_CHERRYVIEW(i915))
return;
......
......@@ -17,12 +17,53 @@ struct intel_qgv_point {
u16 dclk, t_rp, t_rdpre, t_rc, t_ras, t_rcd;
};
struct intel_psf_gv_point {
u8 clk; /* clock in multiples of 16.6666 MHz */
};
struct intel_qgv_info {
struct intel_qgv_point points[I915_NUM_QGV_POINTS];
struct intel_psf_gv_point psf_points[I915_NUM_PSF_GV_POINTS];
u8 num_points;
u8 num_psf_points;
u8 t_bl;
};
static int dg1_mchbar_read_qgv_point_info(struct drm_i915_private *dev_priv,
struct intel_qgv_point *sp,
int point)
{
u32 dclk_ratio, dclk_reference;
u32 val;
val = intel_uncore_read(&dev_priv->uncore, SA_PERF_STATUS_0_0_0_MCHBAR_PC);
dclk_ratio = REG_FIELD_GET(DG1_QCLK_RATIO_MASK, val);
if (val & DG1_QCLK_REFERENCE)
dclk_reference = 6; /* 6 * 16.666 MHz = 100 MHz */
else
dclk_reference = 8; /* 8 * 16.666 MHz = 133 MHz */
sp->dclk = dclk_ratio * dclk_reference;
val = intel_uncore_read(&dev_priv->uncore, SKL_MC_BIOS_DATA_0_0_0_MCHBAR_PCU);
if (val & DG1_GEAR_TYPE)
sp->dclk *= 2;
if (sp->dclk == 0)
return -EINVAL;
val = intel_uncore_read(&dev_priv->uncore, MCHBAR_CH0_CR_TC_PRE_0_0_0_MCHBAR);
sp->t_rp = REG_FIELD_GET(DG1_DRAM_T_RP_MASK, val);
sp->t_rdpre = REG_FIELD_GET(DG1_DRAM_T_RDPRE_MASK, val);
val = intel_uncore_read(&dev_priv->uncore, MCHBAR_CH0_CR_TC_PRE_0_0_0_MCHBAR_HIGH);
sp->t_rcd = REG_FIELD_GET(DG1_DRAM_T_RCD_MASK, val);
sp->t_ras = REG_FIELD_GET(DG1_DRAM_T_RAS_MASK, val);
sp->t_rc = sp->t_rp + sp->t_ras;
return 0;
}
static int icl_pcode_read_qgv_point_info(struct drm_i915_private *dev_priv,
struct intel_qgv_point *sp,
int point)
......@@ -49,6 +90,28 @@ static int icl_pcode_read_qgv_point_info(struct drm_i915_private *dev_priv,
return 0;
}
static int adls_pcode_read_psf_gv_point_info(struct drm_i915_private *dev_priv,
struct intel_psf_gv_point *points)
{
u32 val = 0;
int ret;
int i;
ret = sandybridge_pcode_read(dev_priv,
ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
ADL_PCODE_MEM_SS_READ_PSF_GV_INFO,
&val, NULL);
if (ret)
return ret;
for (i = 0; i < I915_NUM_PSF_GV_POINTS; i++) {
points[i].clk = val & 0xff;
val >>= 8;
}
return 0;
}
int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv,
u32 points_mask)
{
......@@ -62,7 +125,7 @@ int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv,
1);
if (ret < 0) {
drm_err(&dev_priv->drm, "Failed to disable qgv points (%d)\n", ret);
drm_err(&dev_priv->drm, "Failed to disable qgv points (%d) points: 0x%x\n", ret, points_mask);
return ret;
}
......@@ -76,6 +139,7 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv,
int i, ret;
qi->num_points = dram_info->num_qgv_points;
qi->num_psf_points = dram_info->num_psf_gv_points;
if (DISPLAY_VER(dev_priv) == 12)
switch (dram_info->type) {
......@@ -99,7 +163,11 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv,
for (i = 0; i < qi->num_points; i++) {
struct intel_qgv_point *sp = &qi->points[i];
ret = icl_pcode_read_qgv_point_info(dev_priv, sp, i);
if (IS_DG1(dev_priv))
ret = dg1_mchbar_read_qgv_point_info(dev_priv, sp, i);
else
ret = icl_pcode_read_qgv_point_info(dev_priv, sp, i);
if (ret)
return ret;
......@@ -109,6 +177,19 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv,
sp->t_rcd, sp->t_rc);
}
if (qi->num_psf_points > 0) {
ret = adls_pcode_read_psf_gv_point_info(dev_priv, qi->psf_points);
if (ret) {
drm_err(&dev_priv->drm, "Failed to read PSF point data; PSF points will not be considered in bandwidth calculations.\n");
qi->num_psf_points = 0;
}
for (i = 0; i < qi->num_psf_points; i++)
drm_dbg_kms(&dev_priv->drm,
"PSF GV %d: CLK=%d \n",
i, qi->psf_points[i].clk);
}
return 0;
}
......@@ -118,6 +199,16 @@ static int icl_calc_bw(int dclk, int num, int den)
return DIV_ROUND_CLOSEST(num * dclk * 100, den * 6);
}
static int adl_calc_psf_bw(int clk)
{
/*
* clk is multiples of 16.666MHz (100/6)
* According to BSpec PSF GV bandwidth is
* calculated as BW = 64 * clk * 16.666Mhz
*/
return DIV_ROUND_CLOSEST(64 * clk * 100, 6);
}
static int icl_sagv_max_dclk(const struct intel_qgv_info *qi)
{
u16 dclk = 0;
......@@ -194,6 +285,7 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel
bi->num_planes = (ipqdepth - clpchgroup) / clpchgroup + 1;
bi->num_qgv_points = qi.num_points;
bi->num_psf_gv_points = qi.num_psf_points;
for (j = 0; j < qi.num_points; j++) {
const struct intel_qgv_point *sp = &qi.points[j];
......@@ -217,6 +309,16 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel
i, j, bi->num_planes, bi->deratedbw[j]);
}
for (j = 0; j < qi.num_psf_points; j++) {
const struct intel_psf_gv_point *sp = &qi.psf_points[j];
bi->psf_bw[j] = adl_calc_psf_bw(sp->clk);
drm_dbg_kms(&dev_priv->drm,
"BW%d / PSF GV %d: num_planes=%d bw=%u\n",
i, j, bi->num_planes, bi->psf_bw[j]);
}
if (bi->num_planes == 1)
break;
}
......@@ -234,6 +336,26 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel
return 0;
}
static void dg2_get_bw_info(struct drm_i915_private *i915)
{
struct intel_bw_info *bi = &i915->max_bw[0];
/*
* DG2 doesn't have SAGV or QGV points, just a constant max bandwidth
* that doesn't depend on the number of planes enabled. Create a
* single dummy QGV point to reflect that. DG2-G10 platforms have a
* constant 50 GB/s bandwidth, whereas DG2-G11 platforms have 38 GB/s.
*/
bi->num_planes = 1;
bi->num_qgv_points = 1;
if (IS_DG2_G11(i915))
bi->deratedbw[0] = 38000;
else
bi->deratedbw[0] = 50000;
i915->sagv_status = I915_SAGV_NOT_CONTROLLED;
}
static unsigned int icl_max_bw(struct drm_i915_private *dev_priv,
int num_planes, int qgv_point)
{
......@@ -262,12 +384,23 @@ static unsigned int icl_max_bw(struct drm_i915_private *dev_priv,
return 0;
}
static unsigned int adl_psf_bw(struct drm_i915_private *dev_priv,
int psf_gv_point)
{
const struct intel_bw_info *bi =
&dev_priv->max_bw[0];
return bi->psf_bw[psf_gv_point];
}
void intel_bw_init_hw(struct drm_i915_private *dev_priv)
{
if (!HAS_DISPLAY(dev_priv))
return;
if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv))
if (IS_DG2(dev_priv))
dg2_get_bw_info(dev_priv);
else if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv))
icl_get_bw_info(dev_priv, &adls_sa_info);
else if (IS_ROCKETLAKE(dev_priv))
icl_get_bw_info(dev_priv, &rkl_sa_info);
......@@ -534,12 +667,24 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
u32 allowed_points = 0;
unsigned int max_bw_point = 0, max_bw = 0;
unsigned int num_qgv_points = dev_priv->max_bw[0].num_qgv_points;
u32 mask = (1 << num_qgv_points) - 1;
unsigned int num_psf_gv_points = dev_priv->max_bw[0].num_psf_gv_points;
u32 mask = 0;
/* FIXME earlier gens need some checks too */
if (DISPLAY_VER(dev_priv) < 11)
return 0;
/*
* We can _not_ use the whole ADLS_QGV_PT_MASK here, as PCode rejects
* it with failure if we try masking any unadvertised points.
* So need to operate only with those returned from PCode.
*/
if (num_qgv_points > 0)
mask |= REG_GENMASK(num_qgv_points - 1, 0);
if (num_psf_gv_points > 0)
mask |= REG_GENMASK(num_psf_gv_points - 1, 0) << ADLS_PSF_PT_SHIFT;
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
unsigned int old_data_rate =
......@@ -602,23 +747,44 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
max_bw = max_data_rate;
}
if (max_data_rate >= data_rate)
allowed_points |= BIT(i);
allowed_points |= REG_FIELD_PREP(ADLS_QGV_PT_MASK, BIT(i));
drm_dbg_kms(&dev_priv->drm, "QGV point %d: max bw %d required %d\n",
i, max_data_rate, data_rate);
}
for (i = 0; i < num_psf_gv_points; i++) {
unsigned int max_data_rate = adl_psf_bw(dev_priv, i);
if (max_data_rate >= data_rate)
allowed_points |= REG_FIELD_PREP(ADLS_PSF_PT_MASK, BIT(i));
drm_dbg_kms(&dev_priv->drm, "PSF GV point %d: max bw %d"
" required %d\n",
i, max_data_rate, data_rate);
}
/*
* BSpec states that we always should have at least one allowed point
* left, so if we couldn't - simply reject the configuration for obvious
* reasons.
*/
if (allowed_points == 0) {
if ((allowed_points & ADLS_QGV_PT_MASK) == 0) {
drm_dbg_kms(&dev_priv->drm, "No QGV points provide sufficient memory"
" bandwidth %d for display configuration(%d active planes).\n",
data_rate, num_active_planes);
return -EINVAL;
}
if (num_psf_gv_points > 0) {
if ((allowed_points & ADLS_PSF_PT_MASK) == 0) {
drm_dbg_kms(&dev_priv->drm, "No PSF GV points provide sufficient memory"
" bandwidth %d for display configuration(%d active planes).\n",
data_rate, num_active_planes);
return -EINVAL;
}
}
/*
* Leave only single point with highest bandwidth, if
* we can't enable SAGV due to the increased memory latency it may
......
......@@ -1195,17 +1195,6 @@ static const struct intel_cdclk_vals glk_cdclk_table[] = {
{}
};
static const struct intel_cdclk_vals cnl_cdclk_table[] = {
{ .refclk = 19200, .cdclk = 168000, .divider = 4, .ratio = 35 },
{ .refclk = 19200, .cdclk = 336000, .divider = 2, .ratio = 35 },
{ .refclk = 19200, .cdclk = 528000, .divider = 2, .ratio = 55 },
{ .refclk = 24000, .cdclk = 168000, .divider = 4, .ratio = 28 },
{ .refclk = 24000, .cdclk = 336000, .divider = 2, .ratio = 28 },
{ .refclk = 24000, .cdclk = 528000, .divider = 2, .ratio = 44 },
{}
};
static const struct intel_cdclk_vals icl_cdclk_table[] = {
{ .refclk = 19200, .cdclk = 172800, .divider = 2, .ratio = 18 },
{ .refclk = 19200, .cdclk = 192000, .divider = 2, .ratio = 20 },
......@@ -1290,6 +1279,16 @@ static const struct intel_cdclk_vals adlp_cdclk_table[] = {
{}
};
static const struct intel_cdclk_vals dg2_cdclk_table[] = {
{ .refclk = 38400, .cdclk = 172800, .divider = 2, .ratio = 9 },
{ .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 10 },
{ .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16 },
{ .refclk = 38400, .cdclk = 326400, .divider = 4, .ratio = 34 },
{ .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29 },
{ .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34 },
{}
};
static int bxt_calc_cdclk(struct drm_i915_private *dev_priv, int min_cdclk)
{
const struct intel_cdclk_vals *table = dev_priv->cdclk.table;
......@@ -1329,16 +1328,6 @@ static u8 bxt_calc_voltage_level(int cdclk)
return DIV_ROUND_UP(cdclk, 25000);
}
static u8 cnl_calc_voltage_level(int cdclk)
{
if (cdclk > 336000)
return 2;
else if (cdclk > 168000)
return 1;
else
return 0;
}
static u8 icl_calc_voltage_level(int cdclk)
{
if (cdclk > 556800)
......@@ -1373,15 +1362,6 @@ static u8 tgl_calc_voltage_level(int cdclk)
return 0;
}
static void cnl_readout_refclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_config *cdclk_config)
{
if (intel_de_read(dev_priv, SKL_DSSM) & CNL_DSSM_CDCLK_PLL_REFCLK_24MHz)
cdclk_config->ref = 24000;
else
cdclk_config->ref = 19200;
}
static void icl_readout_refclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_config *cdclk_config)
{
......@@ -1408,10 +1388,10 @@ static void bxt_de_pll_readout(struct drm_i915_private *dev_priv,
{
u32 val, ratio;
if (DISPLAY_VER(dev_priv) >= 11)
if (IS_DG2(dev_priv))
cdclk_config->ref = 38400;
else if (DISPLAY_VER(dev_priv) >= 11)
icl_readout_refclk(dev_priv, cdclk_config);
else if (IS_CANNONLAKE(dev_priv))
cnl_readout_refclk(dev_priv, cdclk_config);
else
cdclk_config->ref = 19200;
......@@ -1427,11 +1407,11 @@ static void bxt_de_pll_readout(struct drm_i915_private *dev_priv,
}
/*
* CNL+ have the ratio directly in the PLL enable register, gen9lp had
* it in a separate PLL control register.
* DISPLAY_VER >= 11 have the ratio directly in the PLL enable register,
* gen9lp had it in a separate PLL control register.
*/
if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv))
ratio = val & CNL_CDCLK_PLL_RATIO_MASK;
if (DISPLAY_VER(dev_priv) >= 11)
ratio = val & ICL_CDCLK_PLL_RATIO_MASK;
else
ratio = intel_de_read(dev_priv, BXT_DE_PLL_CTL) & BXT_DE_PLL_RATIO_MASK;
......@@ -1518,7 +1498,7 @@ static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
dev_priv->cdclk.hw.vco = vco;
}
static void cnl_cdclk_pll_disable(struct drm_i915_private *dev_priv)
static void icl_cdclk_pll_disable(struct drm_i915_private *dev_priv)
{
intel_de_rmw(dev_priv, BXT_DE_PLL_ENABLE,
BXT_DE_PLL_PLL_ENABLE, 0);
......@@ -1530,12 +1510,12 @@ static void cnl_cdclk_pll_disable(struct drm_i915_private *dev_priv)
dev_priv->cdclk.hw.vco = 0;
}
static void cnl_cdclk_pll_enable(struct drm_i915_private *dev_priv, int vco)
static void icl_cdclk_pll_enable(struct drm_i915_private *dev_priv, int vco)
{
int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk.hw.ref);
u32 val;
val = CNL_CDCLK_PLL_RATIO(ratio);
val = ICL_CDCLK_PLL_RATIO(ratio);
intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, val);
val |= BXT_DE_PLL_PLL_ENABLE;
......@@ -1548,18 +1528,13 @@ static void cnl_cdclk_pll_enable(struct drm_i915_private *dev_priv, int vco)
dev_priv->cdclk.hw.vco = vco;
}
static bool has_cdclk_crawl(struct drm_i915_private *i915)
{
return INTEL_INFO(i915)->has_cdclk_crawl;
}
static void adlp_cdclk_pll_crawl(struct drm_i915_private *dev_priv, int vco)
{
int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk.hw.ref);
u32 val;
/* Write PLL ratio without disabling */
val = CNL_CDCLK_PLL_RATIO(ratio) | BXT_DE_PLL_PLL_ENABLE;
val = ICL_CDCLK_PLL_RATIO(ratio) | BXT_DE_PLL_PLL_ENABLE;
intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, val);
/* Submit freq change request */
......@@ -1628,7 +1603,7 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
int ret;
/* Inform power controller of upcoming frequency change. */
if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv))
if (DISPLAY_VER(dev_priv) >= 11)
ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL,
SKL_CDCLK_PREPARE_FOR_CHANGE,
SKL_CDCLK_READY_FOR_CHANGE,
......@@ -1649,16 +1624,16 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
return;
}
if (has_cdclk_crawl(dev_priv) && dev_priv->cdclk.hw.vco > 0 && vco > 0) {
if (HAS_CDCLK_CRAWL(dev_priv) && dev_priv->cdclk.hw.vco > 0 && vco > 0) {
if (dev_priv->cdclk.hw.vco != vco)
adlp_cdclk_pll_crawl(dev_priv, vco);
} else if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) {
} else if (DISPLAY_VER(dev_priv) >= 11) {
if (dev_priv->cdclk.hw.vco != 0 &&
dev_priv->cdclk.hw.vco != vco)
cnl_cdclk_pll_disable(dev_priv);
icl_cdclk_pll_disable(dev_priv);
if (dev_priv->cdclk.hw.vco != vco)
cnl_cdclk_pll_enable(dev_priv, vco);
icl_cdclk_pll_enable(dev_priv, vco);
} else {
if (dev_priv->cdclk.hw.vco != 0 &&
dev_priv->cdclk.hw.vco != vco)
......@@ -1684,7 +1659,7 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
if (pipe != INVALID_PIPE)
intel_wait_for_vblank(dev_priv, pipe);
if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) {
if (DISPLAY_VER(dev_priv) >= 11) {
ret = sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL,
cdclk_config->voltage_level);
} else {
......@@ -1709,7 +1684,7 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
intel_update_cdclk(dev_priv);
if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv))
if (DISPLAY_VER(dev_priv) >= 11)
/*
* Can't read out the voltage level :(
* Let's just assume everything is as expected.
......@@ -1857,7 +1832,7 @@ static bool intel_cdclk_can_crawl(struct drm_i915_private *dev_priv,
{
int a_div, b_div;
if (!has_cdclk_crawl(dev_priv))
if (!HAS_CDCLK_CRAWL(dev_priv))
return false;
/*
......@@ -2118,7 +2093,7 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
crtc_state->port_clock >= 540000 &&
crtc_state->lane_count == 4) {
if (DISPLAY_VER(dev_priv) == 10) {
/* Display WA #1145: glk,cnl */
/* Display WA #1145: glk */
min_cdclk = max(316800, min_cdclk);
} else if (DISPLAY_VER(dev_priv) == 9 || IS_BROADWELL(dev_priv)) {
/* Display WA #1144: skl,bxt */
......@@ -2239,7 +2214,7 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state)
/*
* Account for port clock min voltage level requirements.
* This only really does something on CNL+ but can be
* This only really does something on DISPLA_VER >= 11 but can be
* called on earlier platforms as well.
*
* Note that this functions assumes that 0 is
......@@ -2653,8 +2628,6 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
dev_priv->max_cdclk_freq = 648000;
else
dev_priv->max_cdclk_freq = 652800;
} else if (IS_CANNONLAKE(dev_priv)) {
dev_priv->max_cdclk_freq = 528000;
} else if (IS_GEMINILAKE(dev_priv)) {
dev_priv->max_cdclk_freq = 316800;
} else if (IS_BROXTON(dev_priv)) {
......@@ -2878,13 +2851,19 @@ u32 intel_read_rawclk(struct drm_i915_private *dev_priv)
*/
void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
{
if (IS_ALDERLAKE_P(dev_priv)) {
if (IS_DG2(dev_priv)) {
dev_priv->display.set_cdclk = bxt_set_cdclk;
dev_priv->display.bw_calc_min_cdclk = skl_bw_calc_min_cdclk;
dev_priv->display.modeset_calc_cdclk = bxt_modeset_calc_cdclk;
dev_priv->display.calc_voltage_level = tgl_calc_voltage_level;
dev_priv->cdclk.table = dg2_cdclk_table;
} else if (IS_ALDERLAKE_P(dev_priv)) {
dev_priv->display.set_cdclk = bxt_set_cdclk;
dev_priv->display.bw_calc_min_cdclk = skl_bw_calc_min_cdclk;
dev_priv->display.modeset_calc_cdclk = bxt_modeset_calc_cdclk;
dev_priv->display.calc_voltage_level = tgl_calc_voltage_level;
/* Wa_22011320316:adlp[a0] */
if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_A0))
/* Wa_22011320316:adl-p[a0] */
if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
dev_priv->cdclk.table = adlp_a_step_cdclk_table;
else
dev_priv->cdclk.table = adlp_cdclk_table;
......@@ -2912,12 +2891,6 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
dev_priv->display.modeset_calc_cdclk = bxt_modeset_calc_cdclk;
dev_priv->display.calc_voltage_level = icl_calc_voltage_level;
dev_priv->cdclk.table = icl_cdclk_table;
} else if (IS_CANNONLAKE(dev_priv)) {
dev_priv->display.bw_calc_min_cdclk = skl_bw_calc_min_cdclk;
dev_priv->display.set_cdclk = bxt_set_cdclk;
dev_priv->display.modeset_calc_cdclk = bxt_modeset_calc_cdclk;
dev_priv->display.calc_voltage_level = cnl_calc_voltage_level;
dev_priv->cdclk.table = cnl_cdclk_table;
} else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
dev_priv->display.bw_calc_min_cdclk = skl_bw_calc_min_cdclk;
dev_priv->display.set_cdclk = bxt_set_cdclk;
......
......@@ -305,13 +305,12 @@ static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state)
ilk_csc_postoff_limited_range);
} else if (crtc_state->csc_enable) {
/*
* On GLK+ both pipe CSC and degamma LUT are controlled
* On GLK both pipe CSC and degamma LUT are controlled
* by csc_enable. Hence for the cases where the degama
* LUT is needed but CSC is not we need to load an
* identity matrix.
*/
drm_WARN_ON(&dev_priv->drm, !IS_CANNONLAKE(dev_priv) &&
!IS_GEMINILAKE(dev_priv));
drm_WARN_ON(&dev_priv->drm, !IS_GEMINILAKE(dev_priv));
ilk_update_pipe_csc(crtc, ilk_csc_off_zero,
ilk_csc_coeff_identity,
......
......@@ -23,9 +23,9 @@ enum {
PROCMON_1_05V_DOT_1,
};
static const struct cnl_procmon {
static const struct icl_procmon {
u32 dw1, dw9, dw10;
} cnl_procmon_values[] = {
} icl_procmon_values[] = {
[PROCMON_0_85V_DOT_0] =
{ .dw1 = 0x00000000, .dw9 = 0x62AB67BB, .dw10 = 0x51914F96, },
[PROCMON_0_95V_DOT_0] =
......@@ -38,15 +38,10 @@ static const struct cnl_procmon {
{ .dw1 = 0x00440000, .dw9 = 0x9A00AB25, .dw10 = 0x8AE38FF1, },
};
/*
* CNL has just one set of registers, while gen11 has a set for each combo PHY.
* The CNL registers are equivalent to the gen11 PHY A registers, that's why we
* call the ICL macros even though the function has CNL on its name.
*/
static const struct cnl_procmon *
cnl_get_procmon_ref_values(struct drm_i915_private *dev_priv, enum phy phy)
static const struct icl_procmon *
icl_get_procmon_ref_values(struct drm_i915_private *dev_priv, enum phy phy)
{
const struct cnl_procmon *procmon;
const struct icl_procmon *procmon;
u32 val;
val = intel_de_read(dev_priv, ICL_PORT_COMP_DW3(phy));
......@@ -55,32 +50,32 @@ cnl_get_procmon_ref_values(struct drm_i915_private *dev_priv, enum phy phy)
MISSING_CASE(val);
fallthrough;
case VOLTAGE_INFO_0_85V | PROCESS_INFO_DOT_0:
procmon = &cnl_procmon_values[PROCMON_0_85V_DOT_0];
procmon = &icl_procmon_values[PROCMON_0_85V_DOT_0];
break;
case VOLTAGE_INFO_0_95V | PROCESS_INFO_DOT_0:
procmon = &cnl_procmon_values[PROCMON_0_95V_DOT_0];
procmon = &icl_procmon_values[PROCMON_0_95V_DOT_0];
break;
case VOLTAGE_INFO_0_95V | PROCESS_INFO_DOT_1:
procmon = &cnl_procmon_values[PROCMON_0_95V_DOT_1];
procmon = &icl_procmon_values[PROCMON_0_95V_DOT_1];
break;
case VOLTAGE_INFO_1_05V | PROCESS_INFO_DOT_0:
procmon = &cnl_procmon_values[PROCMON_1_05V_DOT_0];
procmon = &icl_procmon_values[PROCMON_1_05V_DOT_0];
break;
case VOLTAGE_INFO_1_05V | PROCESS_INFO_DOT_1:
procmon = &cnl_procmon_values[PROCMON_1_05V_DOT_1];
procmon = &icl_procmon_values[PROCMON_1_05V_DOT_1];
break;
}
return procmon;
}
static void cnl_set_procmon_ref_values(struct drm_i915_private *dev_priv,
static void icl_set_procmon_ref_values(struct drm_i915_private *dev_priv,
enum phy phy)
{
const struct cnl_procmon *procmon;
const struct icl_procmon *procmon;
u32 val;
procmon = cnl_get_procmon_ref_values(dev_priv, phy);
procmon = icl_get_procmon_ref_values(dev_priv, phy);
val = intel_de_read(dev_priv, ICL_PORT_COMP_DW1(phy));
val &= ~((0xff << 16) | 0xff);
......@@ -109,13 +104,13 @@ static bool check_phy_reg(struct drm_i915_private *dev_priv,
return true;
}
static bool cnl_verify_procmon_ref_values(struct drm_i915_private *dev_priv,
static bool icl_verify_procmon_ref_values(struct drm_i915_private *dev_priv,
enum phy phy)
{
const struct cnl_procmon *procmon;
const struct icl_procmon *procmon;
bool ret;
procmon = cnl_get_procmon_ref_values(dev_priv, phy);
procmon = icl_get_procmon_ref_values(dev_priv, phy);
ret = check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW1(phy),
(0xff << 16) | 0xff, procmon->dw1);
......@@ -127,61 +122,6 @@ static bool cnl_verify_procmon_ref_values(struct drm_i915_private *dev_priv,
return ret;
}
static bool cnl_combo_phy_enabled(struct drm_i915_private *dev_priv)
{
return !(intel_de_read(dev_priv, CHICKEN_MISC_2) & CNL_COMP_PWR_DOWN) &&
(intel_de_read(dev_priv, CNL_PORT_COMP_DW0) & COMP_INIT);
}
static bool cnl_combo_phy_verify_state(struct drm_i915_private *dev_priv)
{
enum phy phy = PHY_A;
bool ret;
if (!cnl_combo_phy_enabled(dev_priv))
return false;
ret = cnl_verify_procmon_ref_values(dev_priv, phy);
ret &= check_phy_reg(dev_priv, phy, CNL_PORT_CL1CM_DW5,
CL_POWER_DOWN_ENABLE, CL_POWER_DOWN_ENABLE);
return ret;
}
static void cnl_combo_phys_init(struct drm_i915_private *dev_priv)
{
u32 val;
val = intel_de_read(dev_priv, CHICKEN_MISC_2);
val &= ~CNL_COMP_PWR_DOWN;
intel_de_write(dev_priv, CHICKEN_MISC_2, val);
/* Dummy PORT_A to get the correct CNL register from the ICL macro */
cnl_set_procmon_ref_values(dev_priv, PHY_A);
val = intel_de_read(dev_priv, CNL_PORT_COMP_DW0);
val |= COMP_INIT;
intel_de_write(dev_priv, CNL_PORT_COMP_DW0, val);
val = intel_de_read(dev_priv, CNL_PORT_CL1CM_DW5);
val |= CL_POWER_DOWN_ENABLE;
intel_de_write(dev_priv, CNL_PORT_CL1CM_DW5, val);
}
static void cnl_combo_phys_uninit(struct drm_i915_private *dev_priv)
{
u32 val;
if (!cnl_combo_phy_verify_state(dev_priv))
drm_warn(&dev_priv->drm,
"Combo PHY HW state changed unexpectedly.\n");
val = intel_de_read(dev_priv, CHICKEN_MISC_2);
val |= CNL_COMP_PWR_DOWN;
intel_de_write(dev_priv, CHICKEN_MISC_2, val);
}
static bool has_phy_misc(struct drm_i915_private *i915, enum phy phy)
{
/*
......@@ -291,7 +231,7 @@ static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv,
DCC_MODE_SELECT_CONTINUOSLY);
}
ret &= cnl_verify_procmon_ref_values(dev_priv, phy);
ret &= icl_verify_procmon_ref_values(dev_priv, phy);
if (phy_is_master(dev_priv, phy)) {
ret &= check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW8(phy),
......@@ -415,7 +355,7 @@ static void icl_combo_phys_init(struct drm_i915_private *dev_priv)
intel_de_write(dev_priv, ICL_PORT_PCS_DW1_GRP(phy), val);
}
cnl_set_procmon_ref_values(dev_priv, phy);
icl_set_procmon_ref_values(dev_priv, phy);
if (phy_is_master(dev_priv, phy)) {
val = intel_de_read(dev_priv, ICL_PORT_COMP_DW8(phy));
......@@ -474,16 +414,10 @@ static void icl_combo_phys_uninit(struct drm_i915_private *dev_priv)
void intel_combo_phy_init(struct drm_i915_private *i915)
{
if (DISPLAY_VER(i915) >= 11)
icl_combo_phys_init(i915);
else if (IS_CANNONLAKE(i915))
cnl_combo_phys_init(i915);
icl_combo_phys_init(i915);
}
void intel_combo_phy_uninit(struct drm_i915_private *i915)
{
if (DISPLAY_VER(i915) >= 11)
icl_combo_phys_uninit(i915);
else if (IS_CANNONLAKE(i915))
cnl_combo_phys_uninit(i915);
icl_combo_phys_uninit(i915);
}
......@@ -335,7 +335,7 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
dev_priv->plane_to_crtc_mapping[i9xx_plane] = crtc;
}
if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv))
if (DISPLAY_VER(dev_priv) >= 11)
drm_crtc_create_scaling_filter_property(&crtc->base,
BIT(DRM_SCALING_FILTER_DEFAULT) |
BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
......
......@@ -383,7 +383,7 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
if (plane_state->hw.rotation & DRM_MODE_ROTATE_180)
cntl |= MCURSOR_ROTATE_180;
/* Wa_22012358565:adlp */
/* Wa_22012358565:adl-p */
if (DISPLAY_VER(dev_priv) == 13)
cntl |= MCURSOR_ARB_SLOTS(1);
......@@ -629,12 +629,16 @@ intel_legacy_cursor_update(struct drm_plane *_plane,
/*
* When crtc is inactive or there is a modeset pending,
* wait for it to complete in the slowpath
* wait for it to complete in the slowpath.
* PSR2 selective fetch also requires the slow path as
* PSR2 plane and transcoder registers can only be updated during
* vblank.
*
* FIXME bigjoiner fastpath would be good
*/
if (!crtc_state->hw.active || intel_crtc_needs_modeset(crtc_state) ||
crtc_state->update_pipe || crtc_state->bigjoiner)
crtc_state->update_pipe || crtc_state->bigjoiner ||
crtc_state->enable_psr2_sel_fetch)
goto slow;
/*
......@@ -801,7 +805,7 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
if (DISPLAY_VER(dev_priv) >= 12)
drm_plane_enable_fb_damage_clips(&cursor->base);
drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
intel_plane_helper_add(cursor);
return cursor;
......
This diff is collapsed.
......@@ -25,7 +25,7 @@ struct bxt_ddi_buf_trans {
u8 deemphasis;
};
struct cnl_ddi_buf_trans {
struct icl_ddi_buf_trans {
u8 dw2_swing_sel;
u8 dw7_n_scalar;
u8 dw4_cursor_coeff;
......@@ -48,7 +48,7 @@ struct tgl_dkl_phy_ddi_buf_trans {
union intel_ddi_buf_trans_entry {
struct hsw_ddi_buf_trans hsw;
struct bxt_ddi_buf_trans bxt;
struct cnl_ddi_buf_trans cnl;
struct icl_ddi_buf_trans icl;
struct icl_mg_phy_ddi_buf_trans mg;
struct tgl_dkl_phy_ddi_buf_trans dkl;
};
......
......@@ -561,6 +561,7 @@ struct drm_display_mode *
intel_encoder_current_mode(struct intel_encoder *encoder);
bool intel_phy_is_combo(struct drm_i915_private *dev_priv, enum phy phy);
bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy);
bool intel_phy_is_snps(struct drm_i915_private *dev_priv, enum phy phy);
enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv,
enum port port);
int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
......
......@@ -2256,6 +2256,11 @@ static int i915_lpsp_capability_show(struct seq_file *m, void *data)
if (connector->status != connector_status_connected)
return -ENODEV;
if (DISPLAY_VER(i915) >= 13) {
LPSP_CAPABLE(encoder->port <= PORT_B);
return 0;
}
switch (DISPLAY_VER(i915)) {
case 12:
/*
......@@ -2390,6 +2395,73 @@ static const struct file_operations i915_dsc_fec_support_fops = {
.write = i915_dsc_fec_support_write
};
static int i915_dsc_bpp_show(struct seq_file *m, void *data)
{
struct drm_connector *connector = m->private;
struct drm_device *dev = connector->dev;
struct drm_crtc *crtc;
struct intel_crtc_state *crtc_state;
struct intel_encoder *encoder = intel_attached_encoder(to_intel_connector(connector));
int ret;
if (!encoder)
return -ENODEV;
ret = drm_modeset_lock_single_interruptible(&dev->mode_config.connection_mutex);
if (ret)
return ret;
crtc = connector->state->crtc;
if (connector->status != connector_status_connected || !crtc) {
ret = -ENODEV;
goto out;
}
crtc_state = to_intel_crtc_state(crtc->state);
seq_printf(m, "Compressed_BPP: %d\n", crtc_state->dsc.compressed_bpp);
out: drm_modeset_unlock(&dev->mode_config.connection_mutex);
return ret;
}
static ssize_t i915_dsc_bpp_write(struct file *file,
const char __user *ubuf,
size_t len, loff_t *offp)
{
struct drm_connector *connector =
((struct seq_file *)file->private_data)->private;
struct intel_encoder *encoder = intel_attached_encoder(to_intel_connector(connector));
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
int dsc_bpp = 0;
int ret;
ret = kstrtoint_from_user(ubuf, len, 0, &dsc_bpp);
if (ret < 0)
return ret;
intel_dp->force_dsc_bpp = dsc_bpp;
*offp += len;
return len;
}
static int i915_dsc_bpp_open(struct inode *inode,
struct file *file)
{
return single_open(file, i915_dsc_bpp_show,
inode->i_private);
}
static const struct file_operations i915_dsc_bpp_fops = {
.owner = THIS_MODULE,
.open = i915_dsc_bpp_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = i915_dsc_bpp_write
};
/**
* intel_connector_debugfs_add - add i915 specific connector debugfs files
* @connector: pointer to a registered drm_connector
......@@ -2428,10 +2500,17 @@ int intel_connector_debugfs_add(struct drm_connector *connector)
connector, &i915_hdcp_sink_capability_fops);
}
if ((DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) && ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort && !to_intel_connector(connector)->mst_port) || connector->connector_type == DRM_MODE_CONNECTOR_eDP))
debugfs_create_file("i915_dsc_fec_support", S_IRUGO, root,
if (DISPLAY_VER(dev_priv) >= 11 &&
((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort &&
!to_intel_connector(connector)->mst_port) ||
connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
debugfs_create_file("i915_dsc_fec_support", 0644, root,
connector, &i915_dsc_fec_support_fops);
debugfs_create_file("i915_dsc_bpp", 0644, root,
connector, &i915_dsc_bpp_fops);
}
/* Legacy panels doesn't lpsp on any platform */
if ((DISPLAY_VER(dev_priv) >= 9 || IS_HASWELL(dev_priv) ||
IS_BROADWELL(dev_priv)) &&
......
......@@ -76,7 +76,8 @@ enum intel_display_power_domain {
POWER_DOMAIN_PORT_CRT,
POWER_DOMAIN_PORT_OTHER,
POWER_DOMAIN_VGA,
POWER_DOMAIN_AUDIO,
POWER_DOMAIN_AUDIO_MMIO,
POWER_DOMAIN_AUDIO_PLAYBACK,
POWER_DOMAIN_AUX_A,
POWER_DOMAIN_AUX_B,
POWER_DOMAIN_AUX_C,
......@@ -142,8 +143,6 @@ enum i915_power_well_id {
SKL_DISP_PW_MISC_IO,
SKL_DISP_PW_1,
SKL_DISP_PW_2,
CNL_DISP_PW_DDI_F_IO,
CNL_DISP_PW_DDI_F_AUX,
ICL_DISP_PW_3,
SKL_DISP_DC_OFF,
TGL_DISP_PW_TC_COLD_OFF,
......@@ -223,6 +222,12 @@ struct i915_power_well_desc {
u8 idx;
/* Mask of pipes whose IRQ logic is backed by the pw */
u8 irq_pipe_mask;
/*
* Instead of waiting for the status bit to ack enables,
* just wait a specific amount of time and then consider
* the well enabled.
*/
u16 fixed_enable_delay;
/* The pw is backing the VGA functionality */
bool has_vga:1;
bool has_fuses:1;
......@@ -386,6 +391,10 @@ intel_display_power_put_all_in_set(struct drm_i915_private *i915,
intel_display_power_put_mask_in_set(i915, power_domain_set, power_domain_set->mask);
}
/*
* FIXME: We should probably switch this to a 0-based scheme to be consistent
* with how we now name/number DBUF_CTL instances.
*/
enum dbuf_slice {
DBUF_S1,
DBUF_S2,
......
......@@ -196,6 +196,10 @@ struct intel_encoder {
void (*update_complete)(struct intel_atomic_state *,
struct intel_encoder *,
struct intel_crtc *);
void (*pre_disable)(struct intel_atomic_state *,
struct intel_encoder *,
const struct intel_crtc_state *,
const struct drm_connector_state *);
void (*disable)(struct intel_atomic_state *,
struct intel_encoder *,
const struct intel_crtc_state *,
......@@ -884,6 +888,18 @@ enum intel_output_format {
INTEL_OUTPUT_FORMAT_YCBCR444,
};
struct intel_mpllb_state {
u32 clock; /* in KHz */
u32 ref_control;
u32 mpllb_cp;
u32 mpllb_div;
u32 mpllb_div2;
u32 mpllb_fracn1;
u32 mpllb_fracn2;
u32 mpllb_sscen;
u32 mpllb_sscstep;
};
struct intel_crtc_state {
/*
* uapi (drm) state. This is the software state shown to userspace.
......@@ -1018,7 +1034,10 @@ struct intel_crtc_state {
struct intel_shared_dpll *shared_dpll;
/* Actual register state of the dpll, for shared dpll cross-checking. */
struct intel_dpll_hw_state dpll_hw_state;
union {
struct intel_dpll_hw_state dpll_hw_state;
struct intel_mpllb_state mpllb_state;
};
/*
* ICL reserved DPLLs for the CRTC/port. The active PLL is selected by
......@@ -1612,6 +1631,7 @@ struct intel_dp {
/* Display stream compression testing */
bool force_dsc_en;
int force_dsc_bpp;
bool hobl_failed;
bool hobl_active;
......
......@@ -57,12 +57,12 @@ MODULE_FIRMWARE(ADLS_DMC_PATH);
#define DG1_DMC_VERSION_REQUIRED DMC_VERSION(2, 2)
MODULE_FIRMWARE(DG1_DMC_PATH);
#define RKL_DMC_PATH DMC_PATH(rkl, 2, 02)
#define RKL_DMC_VERSION_REQUIRED DMC_VERSION(2, 2)
#define RKL_DMC_PATH DMC_PATH(rkl, 2, 03)
#define RKL_DMC_VERSION_REQUIRED DMC_VERSION(2, 3)
MODULE_FIRMWARE(RKL_DMC_PATH);
#define TGL_DMC_PATH DMC_PATH(tgl, 2, 08)
#define TGL_DMC_VERSION_REQUIRED DMC_VERSION(2, 8)
#define TGL_DMC_PATH DMC_PATH(tgl, 2, 12)
#define TGL_DMC_VERSION_REQUIRED DMC_VERSION(2, 12)
MODULE_FIRMWARE(TGL_DMC_PATH);
#define ICL_DMC_PATH DMC_PATH(icl, 1, 09)
......@@ -70,11 +70,6 @@ MODULE_FIRMWARE(TGL_DMC_PATH);
#define ICL_DMC_MAX_FW_SIZE 0x6000
MODULE_FIRMWARE(ICL_DMC_PATH);
#define CNL_DMC_PATH DMC_PATH(cnl, 1, 07)
#define CNL_DMC_VERSION_REQUIRED DMC_VERSION(1, 7)
#define CNL_DMC_MAX_FW_SIZE GLK_DMC_MAX_FW_SIZE
MODULE_FIRMWARE(CNL_DMC_PATH);
#define GLK_DMC_PATH DMC_PATH(glk, 1, 04)
#define GLK_DMC_VERSION_REQUIRED DMC_VERSION(1, 4)
#define GLK_DMC_MAX_FW_SIZE 0x4000
......@@ -247,50 +242,15 @@ bool intel_dmc_has_payload(struct drm_i915_private *i915)
return i915->dmc.dmc_info[DMC_FW_MAIN].payload;
}
static const struct stepping_info skl_stepping_info[] = {
{'A', '0'}, {'B', '0'}, {'C', '0'},
{'D', '0'}, {'E', '0'}, {'F', '0'},
{'G', '0'}, {'H', '0'}, {'I', '0'},
{'J', '0'}, {'K', '0'}
};
static const struct stepping_info bxt_stepping_info[] = {
{'A', '0'}, {'A', '1'}, {'A', '2'},
{'B', '0'}, {'B', '1'}, {'B', '2'}
};
static const struct stepping_info icl_stepping_info[] = {
{'A', '0'}, {'A', '1'}, {'A', '2'},
{'B', '0'}, {'B', '2'},
{'C', '0'}
};
static const struct stepping_info no_stepping_info = { '*', '*' };
static const struct stepping_info *
intel_get_stepping_info(struct drm_i915_private *dev_priv)
intel_get_stepping_info(struct drm_i915_private *i915,
struct stepping_info *si)
{
const struct stepping_info *si;
unsigned int size;
if (IS_ICELAKE(dev_priv)) {
size = ARRAY_SIZE(icl_stepping_info);
si = icl_stepping_info;
} else if (IS_SKYLAKE(dev_priv)) {
size = ARRAY_SIZE(skl_stepping_info);
si = skl_stepping_info;
} else if (IS_BROXTON(dev_priv)) {
size = ARRAY_SIZE(bxt_stepping_info);
si = bxt_stepping_info;
} else {
size = 0;
si = NULL;
}
if (INTEL_REVID(dev_priv) < size)
return si + INTEL_REVID(dev_priv);
const char *step_name = intel_step_name(RUNTIME_INFO(i915)->step.display_step);
return &no_stepping_info;
si->stepping = step_name[0];
si->substepping = step_name[1];
return si;
}
static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv)
......@@ -616,7 +576,8 @@ static void parse_dmc_fw(struct drm_i915_private *dev_priv,
struct intel_package_header *package_header;
struct intel_dmc_header_base *dmc_header;
struct intel_dmc *dmc = &dev_priv->dmc;
const struct stepping_info *si = intel_get_stepping_info(dev_priv);
struct stepping_info display_info = { '*', '*'};
const struct stepping_info *si = intel_get_stepping_info(dev_priv, &display_info);
u32 readcount = 0;
u32 r, offset;
int id;
......@@ -752,10 +713,6 @@ void intel_dmc_ucode_init(struct drm_i915_private *dev_priv)
dmc->fw_path = ICL_DMC_PATH;
dmc->required_version = ICL_DMC_VERSION_REQUIRED;
dmc->max_fw_size = ICL_DMC_MAX_FW_SIZE;
} else if (IS_CANNONLAKE(dev_priv)) {
dmc->fw_path = CNL_DMC_PATH;
dmc->required_version = CNL_DMC_VERSION_REQUIRED;
dmc->max_fw_size = CNL_DMC_MAX_FW_SIZE;
} else if (IS_GEMINILAKE(dev_priv)) {
dmc->fw_path = GLK_DMC_PATH;
dmc->required_version = GLK_DMC_VERSION_REQUIRED;
......
......@@ -222,29 +222,6 @@ bool intel_dp_can_bigjoiner(struct intel_dp *intel_dp)
encoder->port != PORT_A);
}
static int cnl_max_source_rate(struct intel_dp *intel_dp)
{
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
enum port port = dig_port->base.port;
u32 voltage = intel_de_read(dev_priv, CNL_PORT_COMP_DW3) & VOLTAGE_INFO_MASK;
/* Low voltage SKUs are limited to max of 5.4G */
if (voltage == VOLTAGE_INFO_0_85V)
return 540000;
/* For this SKU 8.1G is supported in all ports */
if (IS_CNL_WITH_PORT_F(dev_priv))
return 810000;
/* For other SKUs, max rate on ports A and D is 5.4G */
if (port == PORT_A || port == PORT_D)
return 540000;
return 810000;
}
static int icl_max_source_rate(struct intel_dp *intel_dp)
{
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
......@@ -270,7 +247,7 @@ static void
intel_dp_set_source_rates(struct intel_dp *intel_dp)
{
/* The values must be in increasing order */
static const int cnl_rates[] = {
static const int icl_rates[] = {
162000, 216000, 270000, 324000, 432000, 540000, 648000, 810000
};
static const int bxt_rates[] = {
......@@ -295,12 +272,10 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp)
drm_WARN_ON(&dev_priv->drm,
intel_dp->source_rates || intel_dp->num_source_rates);
if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) {
source_rates = cnl_rates;
size = ARRAY_SIZE(cnl_rates);
if (DISPLAY_VER(dev_priv) == 10)
max_rate = cnl_max_source_rate(intel_dp);
else if (IS_JSL_EHL(dev_priv))
if (DISPLAY_VER(dev_priv) >= 11) {
source_rates = icl_rates;
size = ARRAY_SIZE(icl_rates);
if (IS_JSL_EHL(dev_priv))
max_rate = ehl_max_source_rate(intel_dp);
else
max_rate = icl_max_source_rate(intel_dp);
......@@ -1274,6 +1249,23 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
pipe_config->pipe_bpp);
pipe_config->dsc.slice_count = dsc_dp_slice_count;
}
/* As of today we support DSC for only RGB */
if (intel_dp->force_dsc_bpp) {
if (intel_dp->force_dsc_bpp >= 8 &&
intel_dp->force_dsc_bpp < pipe_bpp) {
drm_dbg_kms(&dev_priv->drm,
"DSC BPP forced to %d",
intel_dp->force_dsc_bpp);
pipe_config->dsc.compressed_bpp =
intel_dp->force_dsc_bpp;
} else {
drm_dbg_kms(&dev_priv->drm,
"Invalid DSC BPP %d",
intel_dp->force_dsc_bpp);
}
}
/*
* VDSC engine operates at 1 Pixel per clock, so if peak pixel rate
* is greater than the maximum Cdclock and if slice count is even
......@@ -3339,6 +3331,9 @@ static void intel_dp_process_phy_request(struct intel_dp *intel_dp,
intel_dp_autotest_phy_ddi_enable(intel_dp, crtc_state);
drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET,
intel_dp->train_set, crtc_state->lane_count);
drm_dp_set_phy_test_pattern(&intel_dp->aux, data,
link_status[DP_DPCD_REV]);
}
......
......@@ -158,7 +158,6 @@ static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp,
/*
* Max timeout values:
* SKL-GLK: 1.6ms
* CNL: 3.2ms
* ICL+: 4ms
*/
ret = DP_AUX_CH_CTL_SEND_BUSY |
......
......@@ -348,6 +348,16 @@ static void wait_for_act_sent(struct intel_encoder *encoder,
drm_dp_check_act_status(&intel_dp->mst_mgr);
}
static void intel_mst_pre_disable_dp(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
if (old_crtc_state->has_audio)
intel_audio_codec_disable(encoder, old_crtc_state,
old_conn_state);
}
static void intel_mst_disable_dp(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
......@@ -372,9 +382,6 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
if (ret) {
drm_dbg_kms(&i915->drm, "failed to update payload %d\n", ret);
}
if (old_crtc_state->has_audio)
intel_audio_codec_disable(encoder,
old_crtc_state, old_conn_state);
}
static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
......@@ -542,7 +549,7 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
struct intel_digital_port *dig_port = intel_mst->primary;
struct intel_dp *intel_dp = &dig_port->dp;
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
u32 val;
enum transcoder trans = pipe_config->cpu_transcoder;
drm_WARN_ON(&dev_priv->drm, pipe_config->has_pch_encoder);
......@@ -550,12 +557,8 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
intel_ddi_enable_transcoder_func(encoder, pipe_config);
val = intel_de_read(dev_priv,
TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder));
val |= TRANS_DDI_DP_VC_PAYLOAD_ALLOC;
intel_de_write(dev_priv,
TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder),
val);
intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(trans), 0,
TRANS_DDI_DP_VC_PAYLOAD_ALLOC);
drm_dbg_kms(&dev_priv->drm, "active links %d\n",
intel_dp->active_mst_links);
......@@ -564,6 +567,10 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
drm_dp_update_payload_part2(&intel_dp->mst_mgr);
if (DISPLAY_VER(dev_priv) >= 12 && pipe_config->fec_enable)
intel_de_rmw(dev_priv, CHICKEN_TRANS(trans), 0,
FECSTALL_DIS_DPTSTREAM_DPTTG);
intel_enable_pipe(pipe_config);
intel_crtc_vblank_on(pipe_config);
......@@ -903,6 +910,7 @@ intel_dp_create_fake_mst_encoder(struct intel_digital_port *dig_port, enum pipe
intel_encoder->compute_config = intel_dp_mst_compute_config;
intel_encoder->compute_config_late = intel_dp_mst_compute_config_late;
intel_encoder->pre_disable = intel_mst_pre_disable_dp;
intel_encoder->disable = intel_mst_disable_dp;
intel_encoder->post_disable = intel_mst_post_disable_dp;
intel_encoder->update_pipe = intel_ddi_update_pipe;
......
......@@ -11,6 +11,7 @@
#include "intel_lvds.h"
#include "intel_panel.h"
#include "intel_sideband.h"
#include "display/intel_snps_phy.h"
struct intel_limit {
struct {
......@@ -923,12 +924,13 @@ static int hsw_crtc_compute_clock(struct intel_crtc *crtc,
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_atomic_state *state =
to_intel_atomic_state(crtc_state->uapi.state);
struct intel_encoder *encoder =
intel_get_crtc_new_encoder(state, crtc_state);
if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) ||
DISPLAY_VER(dev_priv) >= 11) {
struct intel_encoder *encoder =
intel_get_crtc_new_encoder(state, crtc_state);
if (IS_DG2(dev_priv)) {
return intel_mpllb_calc_state(crtc_state, encoder);
} else if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) ||
DISPLAY_VER(dev_priv) >= 11) {
if (!intel_reserve_shared_dplls(state, crtc, encoder)) {
drm_dbg_kms(&dev_priv->drm,
"failed to find PLL for pipe %c\n",
......
......@@ -204,9 +204,8 @@ struct intel_dpll_hw_state {
/* HDMI only, 0 when used for DP */
u32 cfgcr1, cfgcr2;
/* cnl */
/* icl */
u32 cfgcr0;
/* CNL also uses cfgcr1 */
/* bxt */
u32 ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10, pcsdw12;
......
......@@ -912,11 +912,11 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
}
/*
* Tigerlake is not supporting FBC with PSR2.
* Display 12+ is not supporting FBC with PSR2.
* Recommendation is to keep this combination disabled
* Bspec: 50422 HSD: 14010260002
*/
if (fbc->state_cache.psr2_active && IS_TIGERLAKE(dev_priv)) {
if (fbc->state_cache.psr2_active && DISPLAY_VER(dev_priv) >= 12) {
fbc->no_fbc_reason = "not supported with PSR2";
return false;
}
......
......@@ -600,7 +600,7 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
int i = 0, inc, try = 0;
int ret = 0;
/* Display WA #0868: skl,bxt,kbl,cfl,glk,cnl */
/* Display WA #0868: skl,bxt,kbl,cfl,glk */
if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
bxt_gmbus_clock_gating(dev_priv, false);
else if (HAS_PCH_SPT(dev_priv) || HAS_PCH_CNP(dev_priv))
......@@ -713,7 +713,7 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
ret = -EAGAIN;
out:
/* Display WA #0868: skl,bxt,kbl,cfl,glk,cnl */
/* Display WA #0868: skl,bxt,kbl,cfl,glk */
if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
bxt_gmbus_clock_gating(dev_priv, true);
else if (HAS_PCH_SPT(dev_priv) || HAS_PCH_CNP(dev_priv))
......
......@@ -51,6 +51,7 @@
#include "intel_hdmi.h"
#include "intel_lspcon.h"
#include "intel_panel.h"
#include "intel_snps_phy.h"
static struct drm_device *intel_hdmi_to_dev(struct intel_hdmi *intel_hdmi)
{
......@@ -1850,6 +1851,16 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi,
if (IS_CHERRYVIEW(dev_priv) && clock > 216000 && clock < 240000)
return MODE_CLOCK_RANGE;
/*
* SNPS PHYs' MPLLB table-based programming can only handle a fixed
* set of link rates.
*
* FIXME: We will hopefully get an algorithmic way of programming
* the MPLLB for HDMI in the future.
*/
if (IS_DG2(dev_priv))
return intel_snps_phy_check_hdmi_link_rate(clock);
return MODE_OK;
}
......
......@@ -1078,6 +1078,9 @@ void intel_opregion_resume(struct drm_i915_private *i915)
opregion->asle->ardy = ASLE_ARDY_READY;
}
/* Some platforms abuse the _DSM to enable MUX */
intel_dsm_get_bios_data_funcs_supported(i915);
intel_opregion_notify_adapter(i915, PCI_D0);
}
......
This diff is collapsed.
This diff is collapsed.
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2019 Intel Corporation
*/
#ifndef __INTEL_SNPS_PHY_H__
#define __INTEL_SNPS_PHY_H__
#include <linux/types.h>
struct drm_i915_private;
struct intel_encoder;
struct intel_crtc_state;
struct intel_mpllb_state;
enum phy;
void intel_snps_phy_wait_for_calibration(struct drm_i915_private *dev_priv);
void intel_snps_phy_update_psr_power_state(struct drm_i915_private *dev_priv,
enum phy phy, bool enable);
int intel_mpllb_calc_state(struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder);
void intel_mpllb_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_mpllb_disable(struct intel_encoder *encoder);
void intel_mpllb_readout_hw_state(struct intel_encoder *encoder,
struct intel_mpllb_state *pll_state);
int intel_mpllb_calc_port_clock(struct intel_encoder *encoder,
const struct intel_mpllb_state *pll_state);
int intel_snps_phy_check_hdmi_link_rate(int clock);
void intel_snps_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
u32 level);
#endif /* __INTEL_SNPS_PHY_H__ */
......@@ -1856,7 +1856,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
zpos = sprite + 1;
drm_plane_create_zpos_immutable_property(&plane->base, zpos);
drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
intel_plane_helper_add(plane);
return plane;
......
......@@ -456,7 +456,7 @@ struct child_device_config {
u16 dp_gpio_pin_num; /* 195 */
u8 dp_iboost_level:4; /* 196 */
u8 hdmi_iboost_level:4; /* 196 */
u8 dp_max_link_rate:3; /* 216/230 CNL+ */
u8 dp_max_link_rate:3; /* 216/230 GLK+ */
u8 dp_max_link_rate_reserved:5; /* 216/230 */
} __packed;
......
......@@ -348,7 +348,10 @@ bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state)
if (DISPLAY_VER(i915) >= 12)
return true;
if ((DISPLAY_VER(i915) >= 11 || IS_CANNONLAKE(i915)) && (pipe != PIPE_A || (cpu_transcoder == TRANSCODER_EDP || cpu_transcoder == TRANSCODER_DSI_0 || cpu_transcoder == TRANSCODER_DSI_1)))
if (DISPLAY_VER(i915) >= 11 &&
(pipe != PIPE_A || cpu_transcoder == TRANSCODER_EDP ||
cpu_transcoder == TRANSCODER_DSI_0 ||
cpu_transcoder == TRANSCODER_DSI_1))
return true;
return false;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment