Merge drm/drm-next into drm-intel-gt-next
In order to get the GSC Support merged on drm-intel-gt-next
in a clean fashion we needed this ATS-M patch to avoid
conflict in i915_pci.c:
commit 412c942bdf
("drm/i915/ats-m: add ATS-M platform info")
--
Fixing a silent conflict on drivers/gpu/drm/i915/gt/intel_gt_gmch.c:
- if (!intel_vtd_active(i915))
+ if (!i915_vtd_active(i915))
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
This commit is contained in:
commit
e1e1f4e325
|
@ -187,19 +187,7 @@ Display Refresh Rate Switching (DRRS)
|
|||
:doc: Display Refresh Rate Switching (DRRS)
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
|
||||
:functions: intel_drrs_enable
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
|
||||
:functions: intel_drrs_disable
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
|
||||
:functions: intel_drrs_invalidate
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
|
||||
:functions: intel_drrs_flush
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
|
||||
:functions: intel_drrs_init
|
||||
:internal:
|
||||
|
||||
DPIO
|
||||
----
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/bcma/bcma_regs.h>
|
||||
#include <linux/platform_data/x86/apple.h>
|
||||
#include <drm/i915_drm.h>
|
||||
#include <drm/i915_pciids.h>
|
||||
#include <asm/pci-direct.h>
|
||||
#include <asm/dma.h>
|
||||
#include <asm/io_apic.h>
|
||||
|
|
|
@ -2390,9 +2390,36 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_S
|
|||
}
|
||||
EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
|
||||
|
||||
static int drm_dp_read_lttpr_regs(struct drm_dp_aux *aux,
|
||||
const u8 dpcd[DP_RECEIVER_CAP_SIZE], int address,
|
||||
u8 *buf, int buf_size)
|
||||
{
|
||||
/*
|
||||
* At least the DELL P2715Q monitor with a DPCD_REV < 0x14 returns
|
||||
* corrupted values when reading from the 0xF0000- range with a block
|
||||
* size bigger than 1.
|
||||
*/
|
||||
int block_size = dpcd[DP_DPCD_REV] < 0x14 ? 1 : buf_size;
|
||||
int offset;
|
||||
int ret;
|
||||
|
||||
for (offset = 0; offset < buf_size; offset += block_size) {
|
||||
ret = drm_dp_dpcd_read(aux,
|
||||
address + offset,
|
||||
&buf[offset], block_size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
WARN_ON(ret != block_size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_dp_read_lttpr_common_caps - read the LTTPR common capabilities
|
||||
* @aux: DisplayPort AUX channel
|
||||
* @dpcd: DisplayPort configuration data
|
||||
* @caps: buffer to return the capability info in
|
||||
*
|
||||
* Read capabilities common to all LTTPRs.
|
||||
|
@ -2400,25 +2427,19 @@ EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
|
|||
* Returns 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux,
|
||||
const u8 dpcd[DP_RECEIVER_CAP_SIZE],
|
||||
u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = drm_dp_dpcd_read(aux,
|
||||
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
|
||||
caps, DP_LTTPR_COMMON_CAP_SIZE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
WARN_ON(ret != DP_LTTPR_COMMON_CAP_SIZE);
|
||||
|
||||
return 0;
|
||||
return drm_dp_read_lttpr_regs(aux, dpcd,
|
||||
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
|
||||
caps, DP_LTTPR_COMMON_CAP_SIZE);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_read_lttpr_common_caps);
|
||||
|
||||
/**
|
||||
* drm_dp_read_lttpr_phy_caps - read the capabilities for a given LTTPR PHY
|
||||
* @aux: DisplayPort AUX channel
|
||||
* @dpcd: DisplayPort configuration data
|
||||
* @dp_phy: LTTPR PHY to read the capabilities for
|
||||
* @caps: buffer to return the capability info in
|
||||
*
|
||||
|
@ -2427,20 +2448,13 @@ EXPORT_SYMBOL(drm_dp_read_lttpr_common_caps);
|
|||
* Returns 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux,
|
||||
const u8 dpcd[DP_RECEIVER_CAP_SIZE],
|
||||
enum drm_dp_phy dp_phy,
|
||||
u8 caps[DP_LTTPR_PHY_CAP_SIZE])
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = drm_dp_dpcd_read(aux,
|
||||
DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy),
|
||||
caps, DP_LTTPR_PHY_CAP_SIZE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
WARN_ON(ret != DP_LTTPR_PHY_CAP_SIZE);
|
||||
|
||||
return 0;
|
||||
return drm_dp_read_lttpr_regs(aux, dpcd,
|
||||
DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy),
|
||||
caps, DP_LTTPR_PHY_CAP_SIZE);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_read_lttpr_phy_caps);
|
||||
|
||||
|
|
|
@ -220,6 +220,7 @@ i915-y += \
|
|||
display/intel_cursor.o \
|
||||
display/intel_display.o \
|
||||
display/intel_display_power.o \
|
||||
display/intel_display_power_well.o \
|
||||
display/intel_dmc.o \
|
||||
display/intel_dpio_phy.o \
|
||||
display/intel_dpll.o \
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
* DisplayPort support for G4x,ILK,SNB,IVB,VLV,CHV (HSW+ handled by the DDI code).
|
||||
*/
|
||||
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include "g4x_dp.h"
|
||||
#include "intel_audio.h"
|
||||
#include "intel_backlight.h"
|
||||
|
@ -22,58 +24,37 @@
|
|||
#include "intel_pps.h"
|
||||
#include "vlv_sideband.h"
|
||||
|
||||
struct dp_link_dpll {
|
||||
int clock;
|
||||
struct dpll dpll;
|
||||
static const struct dpll g4x_dpll[] = {
|
||||
{ .dot = 162000, .p1 = 2, .p2 = 10, .n = 2, .m1 = 23, .m2 = 8, },
|
||||
{ .dot = 270000, .p1 = 1, .p2 = 10, .n = 1, .m1 = 14, .m2 = 2, },
|
||||
};
|
||||
|
||||
static const struct dp_link_dpll g4x_dpll[] = {
|
||||
{ 162000,
|
||||
{ .p1 = 2, .p2 = 10, .n = 2, .m1 = 23, .m2 = 8 } },
|
||||
{ 270000,
|
||||
{ .p1 = 1, .p2 = 10, .n = 1, .m1 = 14, .m2 = 2 } }
|
||||
static const struct dpll pch_dpll[] = {
|
||||
{ .dot = 162000, .p1 = 2, .p2 = 10, .n = 1, .m1 = 12, .m2 = 9, },
|
||||
{ .dot = 270000, .p1 = 1, .p2 = 10, .n = 2, .m1 = 14, .m2 = 8, },
|
||||
};
|
||||
|
||||
static const struct dp_link_dpll pch_dpll[] = {
|
||||
{ 162000,
|
||||
{ .p1 = 2, .p2 = 10, .n = 1, .m1 = 12, .m2 = 9 } },
|
||||
{ 270000,
|
||||
{ .p1 = 1, .p2 = 10, .n = 2, .m1 = 14, .m2 = 8 } }
|
||||
static const struct dpll vlv_dpll[] = {
|
||||
{ .dot = 162000, .p1 = 3, .p2 = 2, .n = 5, .m1 = 3, .m2 = 81, },
|
||||
{ .dot = 270000, .p1 = 2, .p2 = 2, .n = 1, .m1 = 2, .m2 = 27, },
|
||||
};
|
||||
|
||||
static const struct dp_link_dpll vlv_dpll[] = {
|
||||
{ 162000,
|
||||
{ .p1 = 3, .p2 = 2, .n = 5, .m1 = 3, .m2 = 81 } },
|
||||
{ 270000,
|
||||
{ .p1 = 2, .p2 = 2, .n = 1, .m1 = 2, .m2 = 27 } }
|
||||
};
|
||||
|
||||
/*
|
||||
* CHV supports eDP 1.4 that have more link rates.
|
||||
* Below only provides the fixed rate but exclude variable rate.
|
||||
*/
|
||||
static const struct dp_link_dpll chv_dpll[] = {
|
||||
/*
|
||||
* CHV requires to program fractional division for m2.
|
||||
* m2 is stored in fixed point format using formula below
|
||||
* (m2_int << 22) | m2_fraction
|
||||
*/
|
||||
{ 162000, /* m2_int = 32, m2_fraction = 1677722 */
|
||||
{ .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a } },
|
||||
{ 270000, /* m2_int = 27, m2_fraction = 0 */
|
||||
{ .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } },
|
||||
static const struct dpll chv_dpll[] = {
|
||||
/* m2 is .22 binary fixed point */
|
||||
{ .dot = 162000, .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a /* 32.4 */ },
|
||||
{ .dot = 270000, .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 /* 27.0 */ },
|
||||
};
|
||||
|
||||
const struct dpll *vlv_get_dpll(struct drm_i915_private *i915)
|
||||
{
|
||||
return IS_CHERRYVIEW(i915) ? &chv_dpll[0].dpll : &vlv_dpll[0].dpll;
|
||||
return IS_CHERRYVIEW(i915) ? &chv_dpll[0] : &vlv_dpll[0];
|
||||
}
|
||||
|
||||
void g4x_dp_set_clock(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
const struct dp_link_dpll *divisor = NULL;
|
||||
const struct dpll *divisor = NULL;
|
||||
int i, count = 0;
|
||||
|
||||
if (IS_G4X(dev_priv)) {
|
||||
|
@ -92,8 +73,8 @@ void g4x_dp_set_clock(struct intel_encoder *encoder,
|
|||
|
||||
if (divisor && count) {
|
||||
for (i = 0; i < count; i++) {
|
||||
if (pipe_config->port_clock == divisor[i].clock) {
|
||||
pipe_config->dpll = divisor[i].dpll;
|
||||
if (pipe_config->port_clock == divisor[i].dot) {
|
||||
pipe_config->dpll = divisor[i];
|
||||
pipe_config->clock_set = true;
|
||||
break;
|
||||
}
|
||||
|
@ -192,7 +173,7 @@ static void assert_dp_port(struct intel_dp *intel_dp, bool state)
|
|||
I915_STATE_WARN(cur_state != state,
|
||||
"[ENCODER:%d:%s] state assertion failure (expected %s, current %s)\n",
|
||||
dig_port->base.base.base.id, dig_port->base.base.name,
|
||||
onoff(state), onoff(cur_state));
|
||||
str_on_off(state), str_on_off(cur_state));
|
||||
}
|
||||
#define assert_dp_port_disabled(d) assert_dp_port((d), false)
|
||||
|
||||
|
@ -202,7 +183,7 @@ static void assert_edp_pll(struct drm_i915_private *dev_priv, bool state)
|
|||
|
||||
I915_STATE_WARN(cur_state != state,
|
||||
"eDP PLL state assertion failure (expected %s, current %s)\n",
|
||||
onoff(state), onoff(cur_state));
|
||||
str_on_off(state), str_on_off(cur_state));
|
||||
}
|
||||
#define assert_edp_pll_enabled(d) assert_edp_pll((d), true)
|
||||
#define assert_edp_pll_disabled(d) assert_edp_pll((d), false)
|
||||
|
@ -514,9 +495,7 @@ static void intel_disable_dp(struct intel_atomic_state *state,
|
|||
|
||||
intel_dp->link_trained = false;
|
||||
|
||||
if (old_crtc_state->has_audio)
|
||||
intel_audio_codec_disable(encoder,
|
||||
old_crtc_state, old_conn_state);
|
||||
intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
|
||||
|
||||
/*
|
||||
* Make sure the panel is off before trying to change the mode.
|
||||
|
@ -677,9 +656,7 @@ static void intel_enable_dp(struct intel_atomic_state *state,
|
|||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
|
||||
u32 dp_reg = intel_de_read(dev_priv, intel_dp->output_reg);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
intel_wakeref_t wakeref;
|
||||
|
||||
if (drm_WARN_ON(&dev_priv->drm, dp_reg & DP_PORT_EN))
|
||||
|
@ -713,11 +690,7 @@ static void intel_enable_dp(struct intel_atomic_state *state,
|
|||
intel_dp_start_link_train(intel_dp, pipe_config);
|
||||
intel_dp_stop_link_train(intel_dp, pipe_config);
|
||||
|
||||
if (pipe_config->has_audio) {
|
||||
drm_dbg(&dev_priv->drm, "Enabling DP audio on pipe %c\n",
|
||||
pipe_name(pipe));
|
||||
intel_audio_codec_enable(encoder, pipe_config, conn_state);
|
||||
}
|
||||
intel_audio_codec_enable(encoder, pipe_config, conn_state);
|
||||
}
|
||||
|
||||
static void g4x_enable_dp(struct intel_atomic_state *state,
|
||||
|
|
|
@ -143,19 +143,6 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
|
|||
&pipe_config->infoframes.hdmi);
|
||||
}
|
||||
|
||||
static void intel_enable_hdmi_audio(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *pipe_config,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
|
||||
|
||||
drm_WARN_ON(&i915->drm, !pipe_config->has_hdmi_sink);
|
||||
drm_dbg_kms(&i915->drm, "Enabling HDMI audio on pipe %c\n",
|
||||
pipe_name(crtc->pipe));
|
||||
intel_audio_codec_enable(encoder, pipe_config, conn_state);
|
||||
}
|
||||
|
||||
static void g4x_enable_hdmi(struct intel_atomic_state *state,
|
||||
struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *pipe_config,
|
||||
|
@ -175,8 +162,9 @@ static void g4x_enable_hdmi(struct intel_atomic_state *state,
|
|||
intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
|
||||
intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
|
||||
|
||||
if (pipe_config->has_audio)
|
||||
intel_enable_hdmi_audio(encoder, pipe_config, conn_state);
|
||||
drm_WARN_ON(&dev_priv->drm, pipe_config->has_audio &&
|
||||
!pipe_config->has_hdmi_sink);
|
||||
intel_audio_codec_enable(encoder, pipe_config, conn_state);
|
||||
}
|
||||
|
||||
static void ibx_enable_hdmi(struct intel_atomic_state *state,
|
||||
|
@ -227,8 +215,9 @@ static void ibx_enable_hdmi(struct intel_atomic_state *state,
|
|||
intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
|
||||
}
|
||||
|
||||
if (pipe_config->has_audio)
|
||||
intel_enable_hdmi_audio(encoder, pipe_config, conn_state);
|
||||
drm_WARN_ON(&dev_priv->drm, pipe_config->has_audio &&
|
||||
!pipe_config->has_hdmi_sink);
|
||||
intel_audio_codec_enable(encoder, pipe_config, conn_state);
|
||||
}
|
||||
|
||||
static void cpt_enable_hdmi(struct intel_atomic_state *state,
|
||||
|
@ -281,8 +270,9 @@ static void cpt_enable_hdmi(struct intel_atomic_state *state,
|
|||
intel_de_read(dev_priv, TRANS_CHICKEN1(pipe)) & ~TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE);
|
||||
}
|
||||
|
||||
if (pipe_config->has_audio)
|
||||
intel_enable_hdmi_audio(encoder, pipe_config, conn_state);
|
||||
drm_WARN_ON(&dev_priv->drm, pipe_config->has_audio &&
|
||||
!pipe_config->has_hdmi_sink);
|
||||
intel_audio_codec_enable(encoder, pipe_config, conn_state);
|
||||
}
|
||||
|
||||
static void vlv_enable_hdmi(struct intel_atomic_state *state,
|
||||
|
@ -356,9 +346,7 @@ static void g4x_disable_hdmi(struct intel_atomic_state *state,
|
|||
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);
|
||||
intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
|
||||
|
||||
intel_disable_hdmi(state, encoder, old_crtc_state, old_conn_state);
|
||||
}
|
||||
|
@ -368,9 +356,7 @@ static void pch_disable_hdmi(struct intel_atomic_state *state,
|
|||
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);
|
||||
intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
|
||||
}
|
||||
|
||||
static void pch_post_disable_hdmi(struct intel_atomic_state *state,
|
||||
|
|
|
@ -418,9 +418,6 @@ static void i9xx_plane_update_noarm(struct intel_plane *plane,
|
|||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
||||
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane),
|
||||
plane_state->view.color_plane[0].mapping_stride);
|
||||
|
@ -441,8 +438,6 @@ static void i9xx_plane_update_noarm(struct intel_plane *plane,
|
|||
intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane),
|
||||
DISP_HEIGHT(crtc_h - 1) | DISP_WIDTH(crtc_w - 1));
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void i9xx_plane_update_arm(struct intel_plane *plane,
|
||||
|
@ -454,7 +449,6 @@ static void i9xx_plane_update_arm(struct intel_plane *plane,
|
|||
int x = plane_state->view.color_plane[0].x;
|
||||
int y = plane_state->view.color_plane[0].y;
|
||||
u32 dspcntr, dspaddr_offset, linear_offset;
|
||||
unsigned long irqflags;
|
||||
|
||||
dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
|
||||
|
||||
|
@ -465,8 +459,6 @@ static void i9xx_plane_update_arm(struct intel_plane *plane,
|
|||
else
|
||||
dspaddr_offset = linear_offset;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) {
|
||||
int crtc_x = plane_state->uapi.dst.x1;
|
||||
int crtc_y = plane_state->uapi.dst.y1;
|
||||
|
@ -496,14 +488,13 @@ static void i9xx_plane_update_arm(struct intel_plane *plane,
|
|||
* the control register just before the surface register.
|
||||
*/
|
||||
intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 4)
|
||||
intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
|
||||
intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
|
||||
else
|
||||
intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane),
|
||||
intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void i830_plane_update_arm(struct intel_plane *plane,
|
||||
|
@ -525,7 +516,6 @@ static void i9xx_plane_disable_arm(struct intel_plane *plane,
|
|||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
||||
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
|
||||
unsigned long irqflags;
|
||||
u32 dspcntr;
|
||||
|
||||
/*
|
||||
|
@ -540,15 +530,12 @@ static void i9xx_plane_disable_arm(struct intel_plane *plane,
|
|||
*/
|
||||
dspcntr = i9xx_plane_ctl_crtc(crtc_state);
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 4)
|
||||
intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0);
|
||||
else
|
||||
intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -561,16 +548,14 @@ g4x_primary_async_flip(struct intel_plane *plane,
|
|||
u32 dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
|
||||
u32 dspaddr_offset = plane_state->view.color_plane[0].offset;
|
||||
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
|
||||
unsigned long irqflags;
|
||||
|
||||
if (async_flip)
|
||||
dspcntr |= DISP_ASYNC_FLIP;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
|
||||
|
||||
intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
|
||||
intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -582,12 +567,9 @@ vlv_primary_async_flip(struct intel_plane *plane,
|
|||
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
||||
u32 dspaddr_offset = plane_state->view.color_plane[0].offset;
|
||||
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
intel_de_write_fw(dev_priv, DSPADDR_VLV(i9xx_plane),
|
||||
intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -1967,6 +1967,8 @@ static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
|
|||
|
||||
static void icl_dsi_add_properties(struct intel_connector *connector)
|
||||
{
|
||||
const struct drm_display_mode *fixed_mode =
|
||||
intel_panel_preferred_fixed_mode(connector);
|
||||
u32 allowed_scalers;
|
||||
|
||||
allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT) |
|
||||
|
@ -1979,9 +1981,9 @@ static void icl_dsi_add_properties(struct intel_connector *connector)
|
|||
connector->base.state->scaling_mode = DRM_MODE_SCALE_ASPECT;
|
||||
|
||||
drm_connector_set_panel_orientation_with_quirk(&connector->base,
|
||||
intel_dsi_get_panel_orientation(connector),
|
||||
connector->panel.fixed_mode->hdisplay,
|
||||
connector->panel.fixed_mode->vdisplay);
|
||||
intel_dsi_get_panel_orientation(connector),
|
||||
fixed_mode->hdisplay,
|
||||
fixed_mode->vdisplay);
|
||||
}
|
||||
|
||||
void icl_dsi_init(struct drm_i915_private *dev_priv)
|
||||
|
@ -1991,7 +1993,6 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
|
|||
struct intel_encoder *encoder;
|
||||
struct intel_connector *intel_connector;
|
||||
struct drm_connector *connector;
|
||||
struct drm_display_mode *fixed_mode;
|
||||
enum port port;
|
||||
|
||||
if (!intel_bios_is_dsi_present(dev_priv, &port))
|
||||
|
@ -2048,15 +2049,16 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
|
|||
intel_connector_attach_encoder(intel_connector, encoder);
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
fixed_mode = intel_panel_vbt_fixed_mode(intel_connector);
|
||||
intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
|
||||
if (!fixed_mode) {
|
||||
if (!intel_panel_preferred_fixed_mode(intel_connector)) {
|
||||
drm_err(&dev_priv->drm, "DSI fixed mode info missing\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
|
||||
intel_panel_init(intel_connector);
|
||||
|
||||
intel_backlight_setup(intel_connector, INVALID_PIPE);
|
||||
|
||||
if (dev_priv->vbt.dsi.config->dual_link)
|
||||
|
|
|
@ -181,29 +181,67 @@ unsigned int intel_plane_pixel_rate(const struct intel_crtc_state *crtc_state,
|
|||
}
|
||||
|
||||
unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state)
|
||||
const struct intel_plane_state *plane_state,
|
||||
int color_plane)
|
||||
{
|
||||
const struct drm_framebuffer *fb = plane_state->hw.fb;
|
||||
unsigned int cpp;
|
||||
unsigned int pixel_rate;
|
||||
|
||||
if (!plane_state->uapi.visible)
|
||||
return 0;
|
||||
|
||||
pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
|
||||
return intel_plane_pixel_rate(crtc_state, plane_state) *
|
||||
fb->format->cpp[color_plane];
|
||||
}
|
||||
|
||||
cpp = fb->format->cpp[0];
|
||||
static bool
|
||||
use_min_ddb(const struct intel_crtc_state *crtc_state,
|
||||
struct intel_plane *plane)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(plane->base.dev);
|
||||
|
||||
return DISPLAY_VER(i915) >= 13 &&
|
||||
crtc_state->uapi.async_flip &&
|
||||
plane->async_flip;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
intel_plane_relative_data_rate(const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state,
|
||||
int color_plane)
|
||||
{
|
||||
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
|
||||
const struct drm_framebuffer *fb = plane_state->hw.fb;
|
||||
int width, height;
|
||||
|
||||
if (plane->id == PLANE_CURSOR)
|
||||
return 0;
|
||||
|
||||
if (!plane_state->uapi.visible)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Based on HSD#:1408715493
|
||||
* NV12 cpp == 4, P010 cpp == 8
|
||||
*
|
||||
* FIXME what is the logic behind this?
|
||||
* We calculate extra ddb based on ratio plane rate/total data rate
|
||||
* in case, in some cases we should not allocate extra ddb for the plane,
|
||||
* so do not count its data rate, if this is the case.
|
||||
*/
|
||||
if (fb->format->is_yuv && fb->format->num_planes > 1)
|
||||
cpp *= 4;
|
||||
if (use_min_ddb(crtc_state, plane))
|
||||
return 0;
|
||||
|
||||
return pixel_rate * cpp;
|
||||
/*
|
||||
* Src coordinates are already rotated by 270 degrees for
|
||||
* the 90/270 degree plane rotation cases (to match the
|
||||
* GTT mapping), hence no need to account for rotation here.
|
||||
*/
|
||||
width = drm_rect_width(&plane_state->uapi.src) >> 16;
|
||||
height = drm_rect_height(&plane_state->uapi.src) >> 16;
|
||||
|
||||
/* UV plane does 1/2 pixel sub-sampling */
|
||||
if (color_plane == 1) {
|
||||
width /= 2;
|
||||
height /= 2;
|
||||
}
|
||||
|
||||
return width * height * fb->format->cpp[color_plane];
|
||||
}
|
||||
|
||||
int intel_plane_calc_min_cdclk(struct intel_atomic_state *state,
|
||||
|
@ -326,6 +364,9 @@ void intel_plane_set_invisible(struct intel_crtc_state *crtc_state,
|
|||
crtc_state->nv12_planes &= ~BIT(plane->id);
|
||||
crtc_state->c8_planes &= ~BIT(plane->id);
|
||||
crtc_state->data_rate[plane->id] = 0;
|
||||
crtc_state->data_rate_y[plane->id] = 0;
|
||||
crtc_state->rel_data_rate[plane->id] = 0;
|
||||
crtc_state->rel_data_rate_y[plane->id] = 0;
|
||||
crtc_state->min_cdclk[plane->id] = 0;
|
||||
|
||||
plane_state->uapi.visible = false;
|
||||
|
@ -551,8 +592,27 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_
|
|||
if (new_plane_state->uapi.visible || old_plane_state->uapi.visible)
|
||||
new_crtc_state->update_planes |= BIT(plane->id);
|
||||
|
||||
new_crtc_state->data_rate[plane->id] =
|
||||
intel_plane_data_rate(new_crtc_state, new_plane_state);
|
||||
if (new_plane_state->uapi.visible &&
|
||||
intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) {
|
||||
new_crtc_state->data_rate_y[plane->id] =
|
||||
intel_plane_data_rate(new_crtc_state, new_plane_state, 0);
|
||||
new_crtc_state->data_rate[plane->id] =
|
||||
intel_plane_data_rate(new_crtc_state, new_plane_state, 1);
|
||||
|
||||
new_crtc_state->rel_data_rate_y[plane->id] =
|
||||
intel_plane_relative_data_rate(new_crtc_state,
|
||||
new_plane_state, 0);
|
||||
new_crtc_state->rel_data_rate[plane->id] =
|
||||
intel_plane_relative_data_rate(new_crtc_state,
|
||||
new_plane_state, 1);
|
||||
} else if (new_plane_state->uapi.visible) {
|
||||
new_crtc_state->data_rate[plane->id] =
|
||||
intel_plane_data_rate(new_crtc_state, new_plane_state, 0);
|
||||
|
||||
new_crtc_state->rel_data_rate[plane->id] =
|
||||
intel_plane_relative_data_rate(new_crtc_state,
|
||||
new_plane_state, 0);
|
||||
}
|
||||
|
||||
return intel_plane_atomic_calc_changes(old_crtc_state, new_crtc_state,
|
||||
old_plane_state, new_plane_state);
|
||||
|
@ -616,8 +676,8 @@ int intel_plane_atomic_check(struct intel_atomic_state *state,
|
|||
static struct intel_plane *
|
||||
skl_next_plane_to_commit(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc,
|
||||
struct skl_ddb_entry entries_y[I915_MAX_PLANES],
|
||||
struct skl_ddb_entry entries_uv[I915_MAX_PLANES],
|
||||
struct skl_ddb_entry ddb[I915_MAX_PLANES],
|
||||
struct skl_ddb_entry ddb_y[I915_MAX_PLANES],
|
||||
unsigned int *update_mask)
|
||||
{
|
||||
struct intel_crtc_state *crtc_state =
|
||||
|
@ -636,17 +696,15 @@ skl_next_plane_to_commit(struct intel_atomic_state *state,
|
|||
!(*update_mask & BIT(plane_id)))
|
||||
continue;
|
||||
|
||||
if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_y[plane_id],
|
||||
entries_y,
|
||||
I915_MAX_PLANES, plane_id) ||
|
||||
skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_uv[plane_id],
|
||||
entries_uv,
|
||||
I915_MAX_PLANES, plane_id))
|
||||
if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb[plane_id],
|
||||
ddb, I915_MAX_PLANES, plane_id) ||
|
||||
skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_y[plane_id],
|
||||
ddb_y, I915_MAX_PLANES, plane_id))
|
||||
continue;
|
||||
|
||||
*update_mask &= ~BIT(plane_id);
|
||||
entries_y[plane_id] = crtc_state->wm.skl.plane_ddb_y[plane_id];
|
||||
entries_uv[plane_id] = crtc_state->wm.skl.plane_ddb_uv[plane_id];
|
||||
ddb[plane_id] = crtc_state->wm.skl.plane_ddb[plane_id];
|
||||
ddb_y[plane_id] = crtc_state->wm.skl.plane_ddb_y[plane_id];
|
||||
|
||||
return plane;
|
||||
}
|
||||
|
@ -728,19 +786,17 @@ static void skl_crtc_planes_update_arm(struct intel_atomic_state *state,
|
|||
intel_atomic_get_old_crtc_state(state, crtc);
|
||||
struct intel_crtc_state *new_crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
struct skl_ddb_entry entries_y[I915_MAX_PLANES];
|
||||
struct skl_ddb_entry entries_uv[I915_MAX_PLANES];
|
||||
struct skl_ddb_entry ddb[I915_MAX_PLANES];
|
||||
struct skl_ddb_entry ddb_y[I915_MAX_PLANES];
|
||||
u32 update_mask = new_crtc_state->update_planes;
|
||||
struct intel_plane *plane;
|
||||
|
||||
memcpy(entries_y, old_crtc_state->wm.skl.plane_ddb_y,
|
||||
memcpy(ddb, old_crtc_state->wm.skl.plane_ddb,
|
||||
sizeof(old_crtc_state->wm.skl.plane_ddb));
|
||||
memcpy(ddb_y, old_crtc_state->wm.skl.plane_ddb_y,
|
||||
sizeof(old_crtc_state->wm.skl.plane_ddb_y));
|
||||
memcpy(entries_uv, old_crtc_state->wm.skl.plane_ddb_uv,
|
||||
sizeof(old_crtc_state->wm.skl.plane_ddb_uv));
|
||||
|
||||
while ((plane = skl_next_plane_to_commit(state, crtc,
|
||||
entries_y, entries_uv,
|
||||
&update_mask))) {
|
||||
while ((plane = skl_next_plane_to_commit(state, crtc, ddb, ddb_y, &update_mask))) {
|
||||
struct intel_plane_state *new_plane_state =
|
||||
intel_atomic_get_new_plane_state(state, plane);
|
||||
|
||||
|
@ -802,8 +858,8 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state,
|
|||
struct drm_framebuffer *fb = plane_state->hw.fb;
|
||||
struct drm_rect *src = &plane_state->uapi.src;
|
||||
struct drm_rect *dst = &plane_state->uapi.dst;
|
||||
const struct drm_rect *clip = &crtc_state->pipe_src;
|
||||
unsigned int rotation = plane_state->hw.rotation;
|
||||
struct drm_rect clip = {};
|
||||
int hscale, vscale;
|
||||
|
||||
if (!fb) {
|
||||
|
@ -823,31 +879,25 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state,
|
|||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (crtc_state->hw.enable) {
|
||||
clip.x2 = crtc_state->pipe_src_w;
|
||||
clip.y2 = crtc_state->pipe_src_h;
|
||||
}
|
||||
|
||||
/* right side of the image is on the slave crtc, adjust dst to match */
|
||||
if (intel_crtc_is_bigjoiner_slave(crtc_state))
|
||||
drm_rect_translate(dst, -crtc_state->pipe_src_w, 0);
|
||||
|
||||
/*
|
||||
* FIXME: This might need further adjustment for seamless scaling
|
||||
* with phase information, for the 2p2 and 2p1 scenarios.
|
||||
*/
|
||||
plane_state->uapi.visible = drm_rect_clip_scaled(src, dst, &clip);
|
||||
plane_state->uapi.visible = drm_rect_clip_scaled(src, dst, clip);
|
||||
|
||||
drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation);
|
||||
|
||||
if (!can_position && plane_state->uapi.visible &&
|
||||
!drm_rect_equals(dst, &clip)) {
|
||||
!drm_rect_equals(dst, clip)) {
|
||||
drm_dbg_kms(&i915->drm, "Plane must cover entire CRTC\n");
|
||||
drm_rect_debug_print("dst: ", dst, false);
|
||||
drm_rect_debug_print("clip: ", &clip, false);
|
||||
drm_rect_debug_print("clip: ", clip, false);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* final plane coordinates will be relative to the plane's pipe */
|
||||
drm_rect_translate(dst, -clip->x1, -clip->y1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@ unsigned int intel_plane_pixel_rate(const struct intel_crtc_state *crtc_state,
|
|||
const struct intel_plane_state *plane_state);
|
||||
|
||||
unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state);
|
||||
const struct intel_plane_state *plane_state,
|
||||
int color_plane);
|
||||
void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state,
|
||||
const struct intel_plane_state *from_plane_state,
|
||||
struct intel_crtc *crtc);
|
||||
|
|
|
@ -337,8 +337,6 @@ static void g4x_audio_codec_disable(struct intel_encoder *encoder,
|
|||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
u32 eldv, tmp;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "Disable audio codec\n");
|
||||
|
||||
tmp = intel_de_read(dev_priv, G4X_AUD_VID_DID);
|
||||
if (tmp == INTEL_AUDIO_DEVBLC || tmp == INTEL_AUDIO_DEVCL)
|
||||
eldv = G4X_ELDV_DEVCL_DEVBLC;
|
||||
|
@ -362,9 +360,6 @@ static void g4x_audio_codec_enable(struct intel_encoder *encoder,
|
|||
u32 tmp;
|
||||
int len, i;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "Enable audio codec, %u bytes ELD\n",
|
||||
drm_eld_size(eld));
|
||||
|
||||
tmp = intel_de_read(dev_priv, G4X_AUD_VID_DID);
|
||||
if (tmp == INTEL_AUDIO_DEVBLC || tmp == INTEL_AUDIO_DEVCL)
|
||||
eldv = G4X_ELDV_DEVCL_DEVBLC;
|
||||
|
@ -383,7 +378,6 @@ static void g4x_audio_codec_enable(struct intel_encoder *encoder,
|
|||
intel_de_write(dev_priv, G4X_AUD_CNTL_ST, tmp);
|
||||
|
||||
len = min(drm_eld_size(eld) / 4, len);
|
||||
drm_dbg(&dev_priv->drm, "ELD size %d\n", len);
|
||||
for (i = 0; i < len; i++)
|
||||
intel_de_write(dev_priv, G4X_HDMIW_HDMIEDID,
|
||||
*((const u32 *)eld + i));
|
||||
|
@ -501,9 +495,6 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder,
|
|||
enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
|
||||
u32 tmp;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "Disable audio codec on transcoder %s\n",
|
||||
transcoder_name(cpu_transcoder));
|
||||
|
||||
mutex_lock(&dev_priv->audio.mutex);
|
||||
|
||||
/* Disable timestamps */
|
||||
|
@ -647,10 +638,6 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder,
|
|||
u32 tmp;
|
||||
int len, i;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Enable audio codec on transcoder %s, %u bytes ELD\n",
|
||||
transcoder_name(cpu_transcoder), drm_eld_size(eld));
|
||||
|
||||
mutex_lock(&dev_priv->audio.mutex);
|
||||
|
||||
/* Enable Audio WA for 4k DSC usecases */
|
||||
|
@ -703,11 +690,6 @@ static void ilk_audio_codec_disable(struct intel_encoder *encoder,
|
|||
u32 tmp, eldv;
|
||||
i915_reg_t aud_config, aud_cntrl_st2;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Disable audio codec on [ENCODER:%d:%s], pipe %c\n",
|
||||
encoder->base.base.id, encoder->base.name,
|
||||
pipe_name(pipe));
|
||||
|
||||
if (drm_WARN_ON(&dev_priv->drm, port == PORT_A))
|
||||
return;
|
||||
|
||||
|
@ -754,11 +736,6 @@ static void ilk_audio_codec_enable(struct intel_encoder *encoder,
|
|||
int len, i;
|
||||
i915_reg_t hdmiw_hdmiedid, aud_config, aud_cntl_st, aud_cntrl_st2;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Enable audio codec on [ENCODER:%d:%s], pipe %c, %u bytes ELD\n",
|
||||
encoder->base.base.id, encoder->base.name,
|
||||
pipe_name(pipe), drm_eld_size(eld));
|
||||
|
||||
if (drm_WARN_ON(&dev_priv->drm, port == PORT_A))
|
||||
return;
|
||||
|
||||
|
@ -844,18 +821,20 @@ void intel_audio_codec_enable(struct intel_encoder *encoder,
|
|||
enum port port = encoder->port;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
if (!crtc_state->has_audio)
|
||||
return;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Enable audio codec on pipe %c, %u bytes ELD\n",
|
||||
connector->base.id, connector->name,
|
||||
encoder->base.base.id, encoder->base.name,
|
||||
pipe, drm_eld_size(connector->eld));
|
||||
|
||||
/* FIXME precompute the ELD in .compute_config() */
|
||||
if (!connector->eld[0])
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Bogus ELD on [CONNECTOR:%d:%s]\n",
|
||||
connector->base.id, connector->name);
|
||||
|
||||
drm_dbg(&dev_priv->drm, "ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
|
||||
connector->base.id,
|
||||
connector->name,
|
||||
encoder->base.base.id,
|
||||
encoder->base.name);
|
||||
|
||||
connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2;
|
||||
|
||||
if (dev_priv->audio.funcs)
|
||||
|
@ -900,9 +879,17 @@ void intel_audio_codec_disable(struct intel_encoder *encoder,
|
|||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct i915_audio_component *acomp = dev_priv->audio.component;
|
||||
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
|
||||
struct drm_connector *connector = old_conn_state->connector;
|
||||
enum port port = encoder->port;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
if (!old_crtc_state->has_audio)
|
||||
return;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Disable audio codec on pipe %c\n",
|
||||
connector->base.id, connector->name,
|
||||
encoder->base.base.id, encoder->base.name, pipe);
|
||||
|
||||
if (dev_priv->audio.funcs)
|
||||
dev_priv->audio.funcs->audio_codec_disable(encoder,
|
||||
old_crtc_state,
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pwm.h>
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include "intel_backlight.h"
|
||||
#include "intel_connector.h"
|
||||
|
@ -1633,7 +1634,7 @@ int intel_backlight_setup(struct intel_connector *connector, enum pipe pipe)
|
|||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Connector %s backlight initialized, %s, brightness %u/%u\n",
|
||||
connector->base.name,
|
||||
enableddisabled(panel->backlight.enabled),
|
||||
str_enabled_disabled(panel->backlight.enabled),
|
||||
panel->backlight.level, panel->backlight.max);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -88,7 +88,7 @@ static u32 get_blocksize(const void *block_data)
|
|||
}
|
||||
|
||||
static const void *
|
||||
find_section(const void *_bdb, enum bdb_block_id section_id)
|
||||
find_raw_section(const void *_bdb, enum bdb_block_id section_id)
|
||||
{
|
||||
const struct bdb_header *bdb = _bdb;
|
||||
const u8 *base = _bdb;
|
||||
|
@ -118,6 +118,250 @@ find_section(const void *_bdb, enum bdb_block_id section_id)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Offset from the start of BDB to the start of the
|
||||
* block data (just past the block header).
|
||||
*/
|
||||
static u32 block_offset(const void *bdb, enum bdb_block_id section_id)
|
||||
{
|
||||
const void *block;
|
||||
|
||||
block = find_raw_section(bdb, section_id);
|
||||
if (!block)
|
||||
return 0;
|
||||
|
||||
return block - bdb;
|
||||
}
|
||||
|
||||
/* size of the block excluding the header */
|
||||
static u32 block_size(const void *bdb, enum bdb_block_id section_id)
|
||||
{
|
||||
const void *block;
|
||||
|
||||
block = find_raw_section(bdb, section_id);
|
||||
if (!block)
|
||||
return 0;
|
||||
|
||||
return get_blocksize(block);
|
||||
}
|
||||
|
||||
struct bdb_block_entry {
|
||||
struct list_head node;
|
||||
enum bdb_block_id section_id;
|
||||
u8 data[];
|
||||
};
|
||||
|
||||
static const void *
|
||||
find_section(struct drm_i915_private *i915,
|
||||
enum bdb_block_id section_id)
|
||||
{
|
||||
struct bdb_block_entry *entry;
|
||||
|
||||
list_for_each_entry(entry, &i915->vbt.bdb_blocks, node) {
|
||||
if (entry->section_id == section_id)
|
||||
return entry->data + 3;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
enum bdb_block_id section_id;
|
||||
size_t min_size;
|
||||
} bdb_blocks[] = {
|
||||
{ .section_id = BDB_GENERAL_FEATURES,
|
||||
.min_size = sizeof(struct bdb_general_features), },
|
||||
{ .section_id = BDB_GENERAL_DEFINITIONS,
|
||||
.min_size = sizeof(struct bdb_general_definitions), },
|
||||
{ .section_id = BDB_PSR,
|
||||
.min_size = sizeof(struct bdb_psr), },
|
||||
{ .section_id = BDB_DRIVER_FEATURES,
|
||||
.min_size = sizeof(struct bdb_driver_features), },
|
||||
{ .section_id = BDB_SDVO_LVDS_OPTIONS,
|
||||
.min_size = sizeof(struct bdb_sdvo_lvds_options), },
|
||||
{ .section_id = BDB_SDVO_PANEL_DTDS,
|
||||
.min_size = sizeof(struct bdb_sdvo_panel_dtds), },
|
||||
{ .section_id = BDB_EDP,
|
||||
.min_size = sizeof(struct bdb_edp), },
|
||||
{ .section_id = BDB_LVDS_OPTIONS,
|
||||
.min_size = sizeof(struct bdb_lvds_options), },
|
||||
{ .section_id = BDB_LVDS_LFP_DATA_PTRS,
|
||||
.min_size = sizeof(struct bdb_lvds_lfp_data_ptrs), },
|
||||
{ .section_id = BDB_LVDS_LFP_DATA,
|
||||
.min_size = sizeof(struct bdb_lvds_lfp_data), },
|
||||
{ .section_id = BDB_LVDS_BACKLIGHT,
|
||||
.min_size = sizeof(struct bdb_lfp_backlight_data), },
|
||||
{ .section_id = BDB_LFP_POWER,
|
||||
.min_size = sizeof(struct bdb_lfp_power), },
|
||||
{ .section_id = BDB_MIPI_CONFIG,
|
||||
.min_size = sizeof(struct bdb_mipi_config), },
|
||||
{ .section_id = BDB_MIPI_SEQUENCE,
|
||||
.min_size = sizeof(struct bdb_mipi_sequence) },
|
||||
{ .section_id = BDB_COMPRESSION_PARAMETERS,
|
||||
.min_size = sizeof(struct bdb_compression_parameters), },
|
||||
{ .section_id = BDB_GENERIC_DTD,
|
||||
.min_size = sizeof(struct bdb_generic_dtd), },
|
||||
};
|
||||
|
||||
static bool validate_lfp_data_ptrs(const void *bdb,
|
||||
const struct bdb_lvds_lfp_data_ptrs *ptrs)
|
||||
{
|
||||
int fp_timing_size, dvo_timing_size, panel_pnp_id_size, panel_name_size;
|
||||
int data_block_size, lfp_data_size;
|
||||
int i;
|
||||
|
||||
data_block_size = block_size(bdb, BDB_LVDS_LFP_DATA);
|
||||
if (data_block_size == 0)
|
||||
return false;
|
||||
|
||||
/* always 3 indicating the presence of fp_timing+dvo_timing+panel_pnp_id */
|
||||
if (ptrs->lvds_entries != 3)
|
||||
return false;
|
||||
|
||||
fp_timing_size = ptrs->ptr[0].fp_timing.table_size;
|
||||
dvo_timing_size = ptrs->ptr[0].dvo_timing.table_size;
|
||||
panel_pnp_id_size = ptrs->ptr[0].panel_pnp_id.table_size;
|
||||
panel_name_size = ptrs->panel_name.table_size;
|
||||
|
||||
/* fp_timing has variable size */
|
||||
if (fp_timing_size < 32 ||
|
||||
dvo_timing_size != sizeof(struct lvds_dvo_timing) ||
|
||||
panel_pnp_id_size != sizeof(struct lvds_pnp_id))
|
||||
return false;
|
||||
|
||||
/* panel_name is not present in old VBTs */
|
||||
if (panel_name_size != 0 &&
|
||||
panel_name_size != sizeof(struct lvds_lfp_panel_name))
|
||||
return false;
|
||||
|
||||
lfp_data_size = ptrs->ptr[1].fp_timing.offset - ptrs->ptr[0].fp_timing.offset;
|
||||
if (16 * lfp_data_size > data_block_size)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Except for vlv/chv machines all real VBTs seem to have 6
|
||||
* unaccounted bytes in the fp_timing table. And it doesn't
|
||||
* appear to be a really intentional hole as the fp_timing
|
||||
* 0xffff terminator is always within those 6 missing bytes.
|
||||
*/
|
||||
if (fp_timing_size + dvo_timing_size + panel_pnp_id_size != lfp_data_size &&
|
||||
fp_timing_size + 6 + dvo_timing_size + panel_pnp_id_size != lfp_data_size)
|
||||
return false;
|
||||
|
||||
if (ptrs->ptr[0].fp_timing.offset + fp_timing_size > ptrs->ptr[0].dvo_timing.offset ||
|
||||
ptrs->ptr[0].dvo_timing.offset + dvo_timing_size != ptrs->ptr[0].panel_pnp_id.offset ||
|
||||
ptrs->ptr[0].panel_pnp_id.offset + panel_pnp_id_size != lfp_data_size)
|
||||
return false;
|
||||
|
||||
/* make sure the table entries have uniform size */
|
||||
for (i = 1; i < 16; i++) {
|
||||
if (ptrs->ptr[i].fp_timing.table_size != fp_timing_size ||
|
||||
ptrs->ptr[i].dvo_timing.table_size != dvo_timing_size ||
|
||||
ptrs->ptr[i].panel_pnp_id.table_size != panel_pnp_id_size)
|
||||
return false;
|
||||
|
||||
if (ptrs->ptr[i].fp_timing.offset - ptrs->ptr[i-1].fp_timing.offset != lfp_data_size ||
|
||||
ptrs->ptr[i].dvo_timing.offset - ptrs->ptr[i-1].dvo_timing.offset != lfp_data_size ||
|
||||
ptrs->ptr[i].panel_pnp_id.offset - ptrs->ptr[i-1].panel_pnp_id.offset != lfp_data_size)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* make sure the tables fit inside the data block */
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (ptrs->ptr[i].fp_timing.offset + fp_timing_size > data_block_size ||
|
||||
ptrs->ptr[i].dvo_timing.offset + dvo_timing_size > data_block_size ||
|
||||
ptrs->ptr[i].panel_pnp_id.offset + panel_pnp_id_size > data_block_size)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ptrs->panel_name.offset + 16 * panel_name_size > data_block_size)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* make the data table offsets relative to the data block */
|
||||
static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block)
|
||||
{
|
||||
struct bdb_lvds_lfp_data_ptrs *ptrs = ptrs_block;
|
||||
u32 offset;
|
||||
int i;
|
||||
|
||||
offset = block_offset(bdb, BDB_LVDS_LFP_DATA);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (ptrs->ptr[i].fp_timing.offset < offset ||
|
||||
ptrs->ptr[i].dvo_timing.offset < offset ||
|
||||
ptrs->ptr[i].panel_pnp_id.offset < offset)
|
||||
return false;
|
||||
|
||||
ptrs->ptr[i].fp_timing.offset -= offset;
|
||||
ptrs->ptr[i].dvo_timing.offset -= offset;
|
||||
ptrs->ptr[i].panel_pnp_id.offset -= offset;
|
||||
}
|
||||
|
||||
if (ptrs->panel_name.table_size) {
|
||||
if (ptrs->panel_name.offset < offset)
|
||||
return false;
|
||||
|
||||
ptrs->panel_name.offset -= offset;
|
||||
}
|
||||
|
||||
return validate_lfp_data_ptrs(bdb, ptrs);
|
||||
}
|
||||
|
||||
static void
|
||||
init_bdb_block(struct drm_i915_private *i915,
|
||||
const void *bdb, enum bdb_block_id section_id,
|
||||
size_t min_size)
|
||||
{
|
||||
struct bdb_block_entry *entry;
|
||||
const void *block;
|
||||
size_t block_size;
|
||||
|
||||
block = find_raw_section(bdb, section_id);
|
||||
if (!block)
|
||||
return;
|
||||
|
||||
drm_WARN(&i915->drm, min_size == 0,
|
||||
"Block %d min_size is zero\n", section_id);
|
||||
|
||||
block_size = get_blocksize(block);
|
||||
|
||||
entry = kzalloc(struct_size(entry, data, max(min_size, block_size) + 3),
|
||||
GFP_KERNEL);
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
entry->section_id = section_id;
|
||||
memcpy(entry->data, block - 3, block_size + 3);
|
||||
|
||||
drm_dbg_kms(&i915->drm, "Found BDB block %d (size %zu, min size %zu)\n",
|
||||
section_id, block_size, min_size);
|
||||
|
||||
if (section_id == BDB_LVDS_LFP_DATA_PTRS &&
|
||||
!fixup_lfp_data_ptrs(bdb, entry->data + 3)) {
|
||||
drm_err(&i915->drm, "VBT has malformed LFP data table pointers\n");
|
||||
kfree(entry);
|
||||
return;
|
||||
}
|
||||
|
||||
list_add_tail(&entry->node, &i915->vbt.bdb_blocks);
|
||||
}
|
||||
|
||||
static void init_bdb_blocks(struct drm_i915_private *i915,
|
||||
const void *bdb)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bdb_blocks); i++) {
|
||||
enum bdb_block_id section_id = bdb_blocks[i].section_id;
|
||||
size_t min_size = bdb_blocks[i].min_size;
|
||||
|
||||
init_bdb_block(i915, bdb, section_id, min_size);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
|
||||
const struct lvds_dvo_timing *dvo_timing)
|
||||
|
@ -169,60 +413,31 @@ fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
|
|||
}
|
||||
|
||||
static const struct lvds_dvo_timing *
|
||||
get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data,
|
||||
const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs,
|
||||
get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *data,
|
||||
const struct bdb_lvds_lfp_data_ptrs *ptrs,
|
||||
int index)
|
||||
{
|
||||
/*
|
||||
* the size of fp_timing varies on the different platform.
|
||||
* So calculate the DVO timing relative offset in LVDS data
|
||||
* entry to get the DVO timing entry
|
||||
*/
|
||||
|
||||
int lfp_data_size =
|
||||
lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset -
|
||||
lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset;
|
||||
int dvo_timing_offset =
|
||||
lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset -
|
||||
lvds_lfp_data_ptrs->ptr[0].fp_timing_offset;
|
||||
char *entry = (char *)lvds_lfp_data->data + lfp_data_size * index;
|
||||
|
||||
return (struct lvds_dvo_timing *)(entry + dvo_timing_offset);
|
||||
return (const void *)data + ptrs->ptr[index].dvo_timing.offset;
|
||||
}
|
||||
|
||||
/* get lvds_fp_timing entry
|
||||
* this function may return NULL if the corresponding entry is invalid
|
||||
*/
|
||||
static const struct lvds_fp_timing *
|
||||
get_lvds_fp_timing(const struct bdb_header *bdb,
|
||||
const struct bdb_lvds_lfp_data *data,
|
||||
get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data,
|
||||
const struct bdb_lvds_lfp_data_ptrs *ptrs,
|
||||
int index)
|
||||
{
|
||||
size_t data_ofs = (const u8 *)data - (const u8 *)bdb;
|
||||
u16 data_size = ((const u16 *)data)[-1]; /* stored in header */
|
||||
size_t ofs;
|
||||
|
||||
if (index >= ARRAY_SIZE(ptrs->ptr))
|
||||
return NULL;
|
||||
ofs = ptrs->ptr[index].fp_timing_offset;
|
||||
if (ofs < data_ofs ||
|
||||
ofs + sizeof(struct lvds_fp_timing) > data_ofs + data_size)
|
||||
return NULL;
|
||||
return (const struct lvds_fp_timing *)((const u8 *)bdb + ofs);
|
||||
return (const void *)data + ptrs->ptr[index].fp_timing.offset;
|
||||
}
|
||||
|
||||
/* Parse general panel options */
|
||||
static void
|
||||
parse_panel_options(struct drm_i915_private *i915,
|
||||
const struct bdb_header *bdb)
|
||||
parse_panel_options(struct drm_i915_private *i915)
|
||||
{
|
||||
const struct bdb_lvds_options *lvds_options;
|
||||
int panel_type;
|
||||
int drrs_mode;
|
||||
int ret;
|
||||
|
||||
lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
|
||||
lvds_options = find_section(i915, BDB_LVDS_OPTIONS);
|
||||
if (!lvds_options)
|
||||
return;
|
||||
|
||||
|
@ -257,16 +472,16 @@ parse_panel_options(struct drm_i915_private *i915,
|
|||
*/
|
||||
switch (drrs_mode) {
|
||||
case 0:
|
||||
i915->vbt.drrs_type = STATIC_DRRS_SUPPORT;
|
||||
i915->vbt.drrs_type = DRRS_TYPE_STATIC;
|
||||
drm_dbg_kms(&i915->drm, "DRRS supported mode is static\n");
|
||||
break;
|
||||
case 2:
|
||||
i915->vbt.drrs_type = SEAMLESS_DRRS_SUPPORT;
|
||||
i915->vbt.drrs_type = DRRS_TYPE_SEAMLESS;
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"DRRS supported mode is seamless\n");
|
||||
break;
|
||||
default:
|
||||
i915->vbt.drrs_type = DRRS_NOT_SUPPORTED;
|
||||
i915->vbt.drrs_type = DRRS_TYPE_NONE;
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"DRRS not supported (VBT input)\n");
|
||||
break;
|
||||
|
@ -275,8 +490,7 @@ parse_panel_options(struct drm_i915_private *i915,
|
|||
|
||||
/* Try to find integrated panel timing data */
|
||||
static void
|
||||
parse_lfp_panel_dtd(struct drm_i915_private *i915,
|
||||
const struct bdb_header *bdb)
|
||||
parse_lfp_panel_dtd(struct drm_i915_private *i915)
|
||||
{
|
||||
const struct bdb_lvds_lfp_data *lvds_lfp_data;
|
||||
const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
|
||||
|
@ -285,11 +499,11 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
|
|||
struct drm_display_mode *panel_fixed_mode;
|
||||
int panel_type = i915->vbt.panel_type;
|
||||
|
||||
lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
|
||||
lvds_lfp_data = find_section(i915, BDB_LVDS_LFP_DATA);
|
||||
if (!lvds_lfp_data)
|
||||
return;
|
||||
|
||||
lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS);
|
||||
lvds_lfp_data_ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
|
||||
if (!lvds_lfp_data_ptrs)
|
||||
return;
|
||||
|
||||
|
@ -306,34 +520,32 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
|
|||
i915->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
|
||||
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"Found panel mode in BIOS VBT legacy lfp table:\n");
|
||||
drm_mode_debug_printmodeline(panel_fixed_mode);
|
||||
"Found panel mode in BIOS VBT legacy lfp table: " DRM_MODE_FMT "\n",
|
||||
DRM_MODE_ARG(panel_fixed_mode));
|
||||
|
||||
fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data,
|
||||
fp_timing = get_lvds_fp_timing(lvds_lfp_data,
|
||||
lvds_lfp_data_ptrs,
|
||||
panel_type);
|
||||
if (fp_timing) {
|
||||
/* check the resolution, just to be sure */
|
||||
if (fp_timing->x_res == panel_fixed_mode->hdisplay &&
|
||||
fp_timing->y_res == panel_fixed_mode->vdisplay) {
|
||||
i915->vbt.bios_lvds_val = fp_timing->lvds_reg_val;
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"VBT initial LVDS value %x\n",
|
||||
i915->vbt.bios_lvds_val);
|
||||
}
|
||||
|
||||
/* check the resolution, just to be sure */
|
||||
if (fp_timing->x_res == panel_fixed_mode->hdisplay &&
|
||||
fp_timing->y_res == panel_fixed_mode->vdisplay) {
|
||||
i915->vbt.bios_lvds_val = fp_timing->lvds_reg_val;
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"VBT initial LVDS value %x\n",
|
||||
i915->vbt.bios_lvds_val);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parse_generic_dtd(struct drm_i915_private *i915,
|
||||
const struct bdb_header *bdb)
|
||||
parse_generic_dtd(struct drm_i915_private *i915)
|
||||
{
|
||||
const struct bdb_generic_dtd *generic_dtd;
|
||||
const struct generic_dtd_entry *dtd;
|
||||
struct drm_display_mode *panel_fixed_mode;
|
||||
int num_dtd;
|
||||
|
||||
generic_dtd = find_section(bdb, BDB_GENERIC_DTD);
|
||||
generic_dtd = find_section(i915, BDB_GENERIC_DTD);
|
||||
if (!generic_dtd)
|
||||
return;
|
||||
|
||||
|
@ -397,15 +609,14 @@ parse_generic_dtd(struct drm_i915_private *i915,
|
|||
panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;
|
||||
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"Found panel mode in BIOS VBT generic dtd table:\n");
|
||||
drm_mode_debug_printmodeline(panel_fixed_mode);
|
||||
"Found panel mode in BIOS VBT generic dtd table: " DRM_MODE_FMT "\n",
|
||||
DRM_MODE_ARG(panel_fixed_mode));
|
||||
|
||||
i915->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_panel_dtd(struct drm_i915_private *i915,
|
||||
const struct bdb_header *bdb)
|
||||
parse_panel_dtd(struct drm_i915_private *i915)
|
||||
{
|
||||
/*
|
||||
* Older VBTs provided provided DTD information for internal displays
|
||||
|
@ -415,22 +626,21 @@ parse_panel_dtd(struct drm_i915_private *i915,
|
|||
* try the new generic DTD block first on VBT >= 229, but still fall
|
||||
* back to trying the old LFP block if that fails.
|
||||
*/
|
||||
if (bdb->version >= 229)
|
||||
parse_generic_dtd(i915, bdb);
|
||||
if (i915->vbt.version >= 229)
|
||||
parse_generic_dtd(i915);
|
||||
if (!i915->vbt.lfp_lvds_vbt_mode)
|
||||
parse_lfp_panel_dtd(i915, bdb);
|
||||
parse_lfp_panel_dtd(i915);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_lfp_backlight(struct drm_i915_private *i915,
|
||||
const struct bdb_header *bdb)
|
||||
parse_lfp_backlight(struct drm_i915_private *i915)
|
||||
{
|
||||
const struct bdb_lfp_backlight_data *backlight_data;
|
||||
const struct lfp_backlight_data_entry *entry;
|
||||
int panel_type = i915->vbt.panel_type;
|
||||
u16 level;
|
||||
|
||||
backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
|
||||
backlight_data = find_section(i915, BDB_LVDS_BACKLIGHT);
|
||||
if (!backlight_data)
|
||||
return;
|
||||
|
||||
|
@ -452,12 +662,12 @@ parse_lfp_backlight(struct drm_i915_private *i915,
|
|||
}
|
||||
|
||||
i915->vbt.backlight.type = INTEL_BACKLIGHT_DISPLAY_DDI;
|
||||
if (bdb->version >= 191) {
|
||||
if (i915->vbt.version >= 191) {
|
||||
size_t exp_size;
|
||||
|
||||
if (bdb->version >= 236)
|
||||
if (i915->vbt.version >= 236)
|
||||
exp_size = sizeof(struct bdb_lfp_backlight_data);
|
||||
else if (bdb->version >= 234)
|
||||
else if (i915->vbt.version >= 234)
|
||||
exp_size = EXP_BDB_LFP_BL_DATA_SIZE_REV_234;
|
||||
else
|
||||
exp_size = EXP_BDB_LFP_BL_DATA_SIZE_REV_191;
|
||||
|
@ -474,14 +684,14 @@ parse_lfp_backlight(struct drm_i915_private *i915,
|
|||
i915->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
|
||||
i915->vbt.backlight.active_low_pwm = entry->active_low_pwm;
|
||||
|
||||
if (bdb->version >= 234) {
|
||||
if (i915->vbt.version >= 234) {
|
||||
u16 min_level;
|
||||
bool scale;
|
||||
|
||||
level = backlight_data->brightness_level[panel_type].level;
|
||||
min_level = backlight_data->brightness_min_level[panel_type].level;
|
||||
|
||||
if (bdb->version >= 236)
|
||||
if (i915->vbt.version >= 236)
|
||||
scale = backlight_data->brightness_precision_bits[panel_type] == 16;
|
||||
else
|
||||
scale = level > 255;
|
||||
|
@ -514,8 +724,7 @@ parse_lfp_backlight(struct drm_i915_private *i915,
|
|||
|
||||
/* Try to find sdvo panel data */
|
||||
static void
|
||||
parse_sdvo_panel_data(struct drm_i915_private *i915,
|
||||
const struct bdb_header *bdb)
|
||||
parse_sdvo_panel_data(struct drm_i915_private *i915)
|
||||
{
|
||||
const struct bdb_sdvo_panel_dtds *dtds;
|
||||
struct drm_display_mode *panel_fixed_mode;
|
||||
|
@ -531,14 +740,14 @@ parse_sdvo_panel_data(struct drm_i915_private *i915,
|
|||
if (index == -1) {
|
||||
const struct bdb_sdvo_lvds_options *sdvo_lvds_options;
|
||||
|
||||
sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
|
||||
sdvo_lvds_options = find_section(i915, BDB_SDVO_LVDS_OPTIONS);
|
||||
if (!sdvo_lvds_options)
|
||||
return;
|
||||
|
||||
index = sdvo_lvds_options->panel_type;
|
||||
}
|
||||
|
||||
dtds = find_section(bdb, BDB_SDVO_PANEL_DTDS);
|
||||
dtds = find_section(i915, BDB_SDVO_PANEL_DTDS);
|
||||
if (!dtds)
|
||||
return;
|
||||
|
||||
|
@ -551,8 +760,8 @@ parse_sdvo_panel_data(struct drm_i915_private *i915,
|
|||
i915->vbt.sdvo_lvds_vbt_mode = panel_fixed_mode;
|
||||
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"Found SDVO panel mode in BIOS VBT tables:\n");
|
||||
drm_mode_debug_printmodeline(panel_fixed_mode);
|
||||
"Found SDVO panel mode in BIOS VBT tables: " DRM_MODE_FMT "\n",
|
||||
DRM_MODE_ARG(panel_fixed_mode));
|
||||
}
|
||||
|
||||
static int intel_bios_ssc_frequency(struct drm_i915_private *i915,
|
||||
|
@ -570,18 +779,17 @@ static int intel_bios_ssc_frequency(struct drm_i915_private *i915,
|
|||
}
|
||||
|
||||
static void
|
||||
parse_general_features(struct drm_i915_private *i915,
|
||||
const struct bdb_header *bdb)
|
||||
parse_general_features(struct drm_i915_private *i915)
|
||||
{
|
||||
const struct bdb_general_features *general;
|
||||
|
||||
general = find_section(bdb, BDB_GENERAL_FEATURES);
|
||||
general = find_section(i915, BDB_GENERAL_FEATURES);
|
||||
if (!general)
|
||||
return;
|
||||
|
||||
i915->vbt.int_tv_support = general->int_tv_support;
|
||||
/* int_crt_support can't be trusted on earlier platforms */
|
||||
if (bdb->version >= 155 &&
|
||||
if (i915->vbt.version >= 155 &&
|
||||
(HAS_DDI(i915) || IS_VALLEYVIEW(i915)))
|
||||
i915->vbt.int_crt_support = general->int_crt_support;
|
||||
i915->vbt.lvds_use_ssc = general->enable_ssc;
|
||||
|
@ -589,7 +797,7 @@ parse_general_features(struct drm_i915_private *i915,
|
|||
intel_bios_ssc_frequency(i915, general->ssc_freq);
|
||||
i915->vbt.display_clock_mode = general->display_clock_mode;
|
||||
i915->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted;
|
||||
if (bdb->version >= 181) {
|
||||
if (i915->vbt.version >= 181) {
|
||||
i915->vbt.orientation = general->rotate_180 ?
|
||||
DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP :
|
||||
DRM_MODE_PANEL_ORIENTATION_NORMAL;
|
||||
|
@ -597,7 +805,7 @@ parse_general_features(struct drm_i915_private *i915,
|
|||
i915->vbt.orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
|
||||
}
|
||||
|
||||
if (bdb->version >= 249 && general->afc_startup_config) {
|
||||
if (i915->vbt.version >= 249 && general->afc_startup_config) {
|
||||
i915->vbt.override_afc_startup = true;
|
||||
i915->vbt.override_afc_startup_val = general->afc_startup_config == 0x1 ? 0x0 : 0x7;
|
||||
}
|
||||
|
@ -695,12 +903,11 @@ parse_sdvo_device_mapping(struct drm_i915_private *i915)
|
|||
}
|
||||
|
||||
static void
|
||||
parse_driver_features(struct drm_i915_private *i915,
|
||||
const struct bdb_header *bdb)
|
||||
parse_driver_features(struct drm_i915_private *i915)
|
||||
{
|
||||
const struct bdb_driver_features *driver;
|
||||
|
||||
driver = find_section(bdb, BDB_DRIVER_FEATURES);
|
||||
driver = find_section(i915, BDB_DRIVER_FEATURES);
|
||||
if (!driver)
|
||||
return;
|
||||
|
||||
|
@ -724,13 +931,13 @@ parse_driver_features(struct drm_i915_private *i915,
|
|||
* in the wild with the bits correctly populated. Version
|
||||
* 108 (on i85x) does not have the bits correctly populated.
|
||||
*/
|
||||
if (bdb->version >= 134 &&
|
||||
if (i915->vbt.version >= 134 &&
|
||||
driver->lvds_config != BDB_DRIVER_FEATURE_INT_LVDS &&
|
||||
driver->lvds_config != BDB_DRIVER_FEATURE_INT_SDVO_LVDS)
|
||||
i915->vbt.int_lvds_support = 0;
|
||||
}
|
||||
|
||||
if (bdb->version < 228) {
|
||||
if (i915->vbt.version < 228) {
|
||||
drm_dbg_kms(&i915->drm, "DRRS State Enabled:%d\n",
|
||||
driver->drrs_enabled);
|
||||
/*
|
||||
|
@ -740,23 +947,22 @@ parse_driver_features(struct drm_i915_private *i915,
|
|||
* driver->drrs_enabled=false
|
||||
*/
|
||||
if (!driver->drrs_enabled)
|
||||
i915->vbt.drrs_type = DRRS_NOT_SUPPORTED;
|
||||
i915->vbt.drrs_type = DRRS_TYPE_NONE;
|
||||
|
||||
i915->vbt.psr.enable = driver->psr_enabled;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parse_power_conservation_features(struct drm_i915_private *i915,
|
||||
const struct bdb_header *bdb)
|
||||
parse_power_conservation_features(struct drm_i915_private *i915)
|
||||
{
|
||||
const struct bdb_lfp_power *power;
|
||||
u8 panel_type = i915->vbt.panel_type;
|
||||
|
||||
if (bdb->version < 228)
|
||||
if (i915->vbt.version < 228)
|
||||
return;
|
||||
|
||||
power = find_section(bdb, BDB_LFP_POWER);
|
||||
power = find_section(i915, BDB_LFP_POWER);
|
||||
if (!power)
|
||||
return;
|
||||
|
||||
|
@ -769,21 +975,21 @@ parse_power_conservation_features(struct drm_i915_private *i915,
|
|||
* power->drrs & BIT(panel_type)=false
|
||||
*/
|
||||
if (!(power->drrs & BIT(panel_type)))
|
||||
i915->vbt.drrs_type = DRRS_NOT_SUPPORTED;
|
||||
i915->vbt.drrs_type = DRRS_TYPE_NONE;
|
||||
|
||||
if (bdb->version >= 232)
|
||||
if (i915->vbt.version >= 232)
|
||||
i915->vbt.edp.hobl = power->hobl & BIT(panel_type);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_edp(struct drm_i915_private *i915, const struct bdb_header *bdb)
|
||||
parse_edp(struct drm_i915_private *i915)
|
||||
{
|
||||
const struct bdb_edp *edp;
|
||||
const struct edp_power_seq *edp_pps;
|
||||
const struct edp_fast_link_params *edp_link_params;
|
||||
int panel_type = i915->vbt.panel_type;
|
||||
|
||||
edp = find_section(bdb, BDB_EDP);
|
||||
edp = find_section(i915, BDB_EDP);
|
||||
if (!edp)
|
||||
return;
|
||||
|
||||
|
@ -876,7 +1082,7 @@ parse_edp(struct drm_i915_private *i915, const struct bdb_header *bdb)
|
|||
break;
|
||||
}
|
||||
|
||||
if (bdb->version >= 173) {
|
||||
if (i915->vbt.version >= 173) {
|
||||
u8 vswing;
|
||||
|
||||
/* Don't read from VBT if module parameter has valid value*/
|
||||
|
@ -888,16 +1094,19 @@ parse_edp(struct drm_i915_private *i915, const struct bdb_header *bdb)
|
|||
i915->vbt.edp.low_vswing = vswing == 0;
|
||||
}
|
||||
}
|
||||
|
||||
i915->vbt.edp.drrs_msa_timing_delay =
|
||||
(edp->sdrrs_msa_timing_delay >> (panel_type * 2)) & 3;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_psr(struct drm_i915_private *i915, const struct bdb_header *bdb)
|
||||
parse_psr(struct drm_i915_private *i915)
|
||||
{
|
||||
const struct bdb_psr *psr;
|
||||
const struct psr_table *psr_table;
|
||||
int panel_type = i915->vbt.panel_type;
|
||||
|
||||
psr = find_section(bdb, BDB_PSR);
|
||||
psr = find_section(i915, BDB_PSR);
|
||||
if (!psr) {
|
||||
drm_dbg_kms(&i915->drm, "No PSR BDB found.\n");
|
||||
return;
|
||||
|
@ -916,7 +1125,7 @@ parse_psr(struct drm_i915_private *i915, const struct bdb_header *bdb)
|
|||
* New psr options 0=500us, 1=100us, 2=2500us, 3=0us
|
||||
* Old decimal value is wake up time in multiples of 100 us.
|
||||
*/
|
||||
if (bdb->version >= 205 &&
|
||||
if (i915->vbt.version >= 205 &&
|
||||
(DISPLAY_VER(i915) >= 9 && !IS_BROXTON(i915))) {
|
||||
switch (psr_table->tp1_wakeup_time) {
|
||||
case 0:
|
||||
|
@ -962,7 +1171,7 @@ parse_psr(struct drm_i915_private *i915, const struct bdb_header *bdb)
|
|||
i915->vbt.psr.tp2_tp3_wakeup_time_us = psr_table->tp2_tp3_wakeup_time * 100;
|
||||
}
|
||||
|
||||
if (bdb->version >= 226) {
|
||||
if (i915->vbt.version >= 226) {
|
||||
u32 wakeup_time = psr->psr2_tp2_tp3_wakeup_time;
|
||||
|
||||
wakeup_time = (wakeup_time >> (2 * panel_type)) & 0x3;
|
||||
|
@ -1031,8 +1240,7 @@ static void parse_dsi_backlight_ports(struct drm_i915_private *i915,
|
|||
}
|
||||
|
||||
static void
|
||||
parse_mipi_config(struct drm_i915_private *i915,
|
||||
const struct bdb_header *bdb)
|
||||
parse_mipi_config(struct drm_i915_private *i915)
|
||||
{
|
||||
const struct bdb_mipi_config *start;
|
||||
const struct mipi_config *config;
|
||||
|
@ -1055,7 +1263,7 @@ parse_mipi_config(struct drm_i915_private *i915,
|
|||
/* Parse #52 for panel index used from panel_type already
|
||||
* parsed
|
||||
*/
|
||||
start = find_section(bdb, BDB_MIPI_CONFIG);
|
||||
start = find_section(i915, BDB_MIPI_CONFIG);
|
||||
if (!start) {
|
||||
drm_dbg_kms(&i915->drm, "No MIPI config BDB found");
|
||||
return;
|
||||
|
@ -1082,7 +1290,7 @@ parse_mipi_config(struct drm_i915_private *i915,
|
|||
return;
|
||||
}
|
||||
|
||||
parse_dsi_backlight_ports(i915, bdb->version, port);
|
||||
parse_dsi_backlight_ports(i915, i915->vbt.version, port);
|
||||
|
||||
/* FIXME is the 90 vs. 270 correct? */
|
||||
switch (config->rotation) {
|
||||
|
@ -1351,8 +1559,7 @@ static void fixup_mipi_sequences(struct drm_i915_private *i915)
|
|||
}
|
||||
|
||||
static void
|
||||
parse_mipi_sequence(struct drm_i915_private *i915,
|
||||
const struct bdb_header *bdb)
|
||||
parse_mipi_sequence(struct drm_i915_private *i915)
|
||||
{
|
||||
int panel_type = i915->vbt.panel_type;
|
||||
const struct bdb_mipi_sequence *sequence;
|
||||
|
@ -1365,7 +1572,7 @@ parse_mipi_sequence(struct drm_i915_private *i915,
|
|||
if (i915->vbt.dsi.panel_id != MIPI_DSI_GENERIC_PANEL_ID)
|
||||
return;
|
||||
|
||||
sequence = find_section(bdb, BDB_MIPI_SEQUENCE);
|
||||
sequence = find_section(i915, BDB_MIPI_SEQUENCE);
|
||||
if (!sequence) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"No MIPI Sequence found, parsing complete\n");
|
||||
|
@ -1436,8 +1643,7 @@ parse_mipi_sequence(struct drm_i915_private *i915,
|
|||
}
|
||||
|
||||
static void
|
||||
parse_compression_parameters(struct drm_i915_private *i915,
|
||||
const struct bdb_header *bdb)
|
||||
parse_compression_parameters(struct drm_i915_private *i915)
|
||||
{
|
||||
const struct bdb_compression_parameters *params;
|
||||
struct intel_bios_encoder_data *devdata;
|
||||
|
@ -1445,10 +1651,10 @@ parse_compression_parameters(struct drm_i915_private *i915,
|
|||
u16 block_size;
|
||||
int index;
|
||||
|
||||
if (bdb->version < 198)
|
||||
if (i915->vbt.version < 198)
|
||||
return;
|
||||
|
||||
params = find_section(bdb, BDB_COMPRESSION_PARAMETERS);
|
||||
params = find_section(i915, BDB_COMPRESSION_PARAMETERS);
|
||||
if (params) {
|
||||
/* Sanity checks */
|
||||
if (params->entry_size != sizeof(params->data[0])) {
|
||||
|
@ -1955,6 +2161,12 @@ static int _intel_bios_max_tmds_clock(const struct intel_bios_encoder_data *devd
|
|||
fallthrough;
|
||||
case HDMI_MAX_DATA_RATE_PLATFORM:
|
||||
return 0;
|
||||
case HDMI_MAX_DATA_RATE_594:
|
||||
return 594000;
|
||||
case HDMI_MAX_DATA_RATE_340:
|
||||
return 340000;
|
||||
case HDMI_MAX_DATA_RATE_300:
|
||||
return 300000;
|
||||
case HDMI_MAX_DATA_RATE_297:
|
||||
return 297000;
|
||||
case HDMI_MAX_DATA_RATE_165:
|
||||
|
@ -2077,8 +2289,7 @@ static void parse_ddi_ports(struct drm_i915_private *i915)
|
|||
}
|
||||
|
||||
static void
|
||||
parse_general_definitions(struct drm_i915_private *i915,
|
||||
const struct bdb_header *bdb)
|
||||
parse_general_definitions(struct drm_i915_private *i915)
|
||||
{
|
||||
const struct bdb_general_definitions *defs;
|
||||
struct intel_bios_encoder_data *devdata;
|
||||
|
@ -2088,7 +2299,7 @@ parse_general_definitions(struct drm_i915_private *i915,
|
|||
u16 block_size;
|
||||
int bus_pin;
|
||||
|
||||
defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
|
||||
defs = find_section(i915, BDB_GENERAL_DEFINITIONS);
|
||||
if (!defs) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"No general definition block is found, no devices defined.\n");
|
||||
|
@ -2108,31 +2319,31 @@ parse_general_definitions(struct drm_i915_private *i915,
|
|||
if (intel_gmbus_is_valid_pin(i915, bus_pin))
|
||||
i915->vbt.crt_ddc_pin = bus_pin;
|
||||
|
||||
if (bdb->version < 106) {
|
||||
if (i915->vbt.version < 106) {
|
||||
expected_size = 22;
|
||||
} else if (bdb->version < 111) {
|
||||
} else if (i915->vbt.version < 111) {
|
||||
expected_size = 27;
|
||||
} else if (bdb->version < 195) {
|
||||
} else if (i915->vbt.version < 195) {
|
||||
expected_size = LEGACY_CHILD_DEVICE_CONFIG_SIZE;
|
||||
} else if (bdb->version == 195) {
|
||||
} else if (i915->vbt.version == 195) {
|
||||
expected_size = 37;
|
||||
} else if (bdb->version <= 215) {
|
||||
} else if (i915->vbt.version <= 215) {
|
||||
expected_size = 38;
|
||||
} else if (bdb->version <= 237) {
|
||||
} else if (i915->vbt.version <= 237) {
|
||||
expected_size = 39;
|
||||
} else {
|
||||
expected_size = sizeof(*child);
|
||||
BUILD_BUG_ON(sizeof(*child) < 39);
|
||||
drm_dbg(&i915->drm,
|
||||
"Expected child device config size for VBT version %u not known; assuming %u\n",
|
||||
bdb->version, expected_size);
|
||||
i915->vbt.version, expected_size);
|
||||
}
|
||||
|
||||
/* Flag an error for unexpected size, but continue anyway. */
|
||||
if (defs->child_dev_size != expected_size)
|
||||
drm_err(&i915->drm,
|
||||
"Unexpected child device config size %u (expected %u for VBT version %u)\n",
|
||||
defs->child_dev_size, expected_size, bdb->version);
|
||||
defs->child_dev_size, expected_size, i915->vbt.version);
|
||||
|
||||
/* The legacy sized child device config is the minimum we need. */
|
||||
if (defs->child_dev_size < LEGACY_CHILD_DEVICE_CONFIG_SIZE) {
|
||||
|
@ -2457,6 +2668,7 @@ void intel_bios_init(struct drm_i915_private *i915)
|
|||
const struct bdb_header *bdb;
|
||||
|
||||
INIT_LIST_HEAD(&i915->vbt.display_devices);
|
||||
INIT_LIST_HEAD(&i915->vbt.bdb_blocks);
|
||||
|
||||
if (!HAS_DISPLAY(i915)) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
|
@ -2488,24 +2700,26 @@ void intel_bios_init(struct drm_i915_private *i915)
|
|||
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"VBT signature \"%.*s\", BDB version %d\n",
|
||||
(int)sizeof(vbt->signature), vbt->signature, bdb->version);
|
||||
(int)sizeof(vbt->signature), vbt->signature, i915->vbt.version);
|
||||
|
||||
init_bdb_blocks(i915, bdb);
|
||||
|
||||
/* Grab useful general definitions */
|
||||
parse_general_features(i915, bdb);
|
||||
parse_general_definitions(i915, bdb);
|
||||
parse_panel_options(i915, bdb);
|
||||
parse_panel_dtd(i915, bdb);
|
||||
parse_lfp_backlight(i915, bdb);
|
||||
parse_sdvo_panel_data(i915, bdb);
|
||||
parse_driver_features(i915, bdb);
|
||||
parse_power_conservation_features(i915, bdb);
|
||||
parse_edp(i915, bdb);
|
||||
parse_psr(i915, bdb);
|
||||
parse_mipi_config(i915, bdb);
|
||||
parse_mipi_sequence(i915, bdb);
|
||||
parse_general_features(i915);
|
||||
parse_general_definitions(i915);
|
||||
parse_panel_options(i915);
|
||||
parse_panel_dtd(i915);
|
||||
parse_lfp_backlight(i915);
|
||||
parse_sdvo_panel_data(i915);
|
||||
parse_driver_features(i915);
|
||||
parse_power_conservation_features(i915);
|
||||
parse_edp(i915);
|
||||
parse_psr(i915);
|
||||
parse_mipi_config(i915);
|
||||
parse_mipi_sequence(i915);
|
||||
|
||||
/* Depends on child device list */
|
||||
parse_compression_parameters(i915, bdb);
|
||||
parse_compression_parameters(i915);
|
||||
|
||||
out:
|
||||
if (!vbt) {
|
||||
|
@ -2527,14 +2741,20 @@ void intel_bios_init(struct drm_i915_private *i915)
|
|||
*/
|
||||
void intel_bios_driver_remove(struct drm_i915_private *i915)
|
||||
{
|
||||
struct intel_bios_encoder_data *devdata, *n;
|
||||
struct intel_bios_encoder_data *devdata, *nd;
|
||||
struct bdb_block_entry *entry, *ne;
|
||||
|
||||
list_for_each_entry_safe(devdata, n, &i915->vbt.display_devices, node) {
|
||||
list_for_each_entry_safe(devdata, nd, &i915->vbt.display_devices, node) {
|
||||
list_del(&devdata->node);
|
||||
kfree(devdata->dsc);
|
||||
kfree(devdata);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(entry, ne, &i915->vbt.bdb_blocks, node) {
|
||||
list_del(&entry->node);
|
||||
kfree(entry);
|
||||
}
|
||||
|
||||
kfree(i915->vbt.sdvo_lvds_vbt_mode);
|
||||
i915->vbt.sdvo_lvds_vbt_mode = NULL;
|
||||
kfree(i915->vbt.lfp_lvds_vbt_mode);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <drm/drm_atomic_state_helper.h>
|
||||
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_bw.h"
|
||||
#include "intel_cdclk.h"
|
||||
|
@ -124,8 +125,8 @@ int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv,
|
|||
/* bspec says to keep retrying for at least 1 ms */
|
||||
ret = skl_pcode_request(dev_priv, ICL_PCODE_SAGV_DE_MEM_SS_CONFIG,
|
||||
points_mask,
|
||||
ICL_PCODE_POINTS_RESTRICTED_MASK,
|
||||
ICL_PCODE_POINTS_RESTRICTED,
|
||||
ICL_PCODE_REP_QGV_MASK | ADLS_PCODE_REP_PSF_MASK,
|
||||
ICL_PCODE_REP_QGV_SAFE | ADLS_PCODE_REP_PSF_SAFE,
|
||||
1);
|
||||
|
||||
if (ret < 0) {
|
||||
|
@ -464,20 +465,25 @@ static int tgl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel
|
|||
|
||||
static void dg2_get_bw_info(struct drm_i915_private *i915)
|
||||
{
|
||||
struct intel_bw_info *bi = &i915->max_bw[0];
|
||||
unsigned int deratedbw = IS_DG2_G11(i915) ? 38000 : 50000;
|
||||
int num_groups = ARRAY_SIZE(i915->max_bw);
|
||||
int i;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* that doesn't depend on the number of planes enabled. So fill all the
|
||||
* plane group with constant bw information for uniformity with other
|
||||
* platforms. 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;
|
||||
for (i = 0; i < num_groups; i++) {
|
||||
struct intel_bw_info *bi = &i915->max_bw[i];
|
||||
|
||||
bi->num_planes = 1;
|
||||
/* Need only one dummy QGV point per group */
|
||||
bi->num_qgv_points = 1;
|
||||
bi->deratedbw[0] = deratedbw;
|
||||
}
|
||||
|
||||
i915->sagv_status = I915_SAGV_NOT_CONTROLLED;
|
||||
}
|
||||
|
@ -578,6 +584,7 @@ static unsigned int intel_bw_crtc_num_active_planes(const struct intel_crtc_stat
|
|||
static unsigned int intel_bw_crtc_data_rate(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
unsigned int data_rate = 0;
|
||||
enum plane_id plane_id;
|
||||
|
||||
|
@ -590,11 +597,26 @@ static unsigned int intel_bw_crtc_data_rate(const struct intel_crtc_state *crtc_
|
|||
continue;
|
||||
|
||||
data_rate += crtc_state->data_rate[plane_id];
|
||||
|
||||
if (DISPLAY_VER(i915) < 11)
|
||||
data_rate += crtc_state->data_rate_y[plane_id];
|
||||
}
|
||||
|
||||
return data_rate;
|
||||
}
|
||||
|
||||
/* "Maximum Pipe Read Bandwidth" */
|
||||
static int intel_bw_crtc_min_cdclk(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
|
||||
if (DISPLAY_VER(i915) < 12)
|
||||
return 0;
|
||||
|
||||
return DIV_ROUND_UP_ULL(mul_u32_u32(intel_bw_crtc_data_rate(crtc_state), 10), 512);
|
||||
}
|
||||
|
||||
void intel_bw_crtc_update(struct intel_bw_state *bw_state,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
|
@ -633,8 +655,8 @@ static unsigned int intel_bw_data_rate(struct drm_i915_private *dev_priv,
|
|||
for_each_pipe(dev_priv, pipe)
|
||||
data_rate += bw_state->data_rate[pipe];
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 13 && intel_vtd_active(dev_priv))
|
||||
data_rate = data_rate * 105 / 100;
|
||||
if (DISPLAY_VER(dev_priv) >= 13 && i915_vtd_active(dev_priv))
|
||||
data_rate = DIV_ROUND_UP(data_rate * 105, 100);
|
||||
|
||||
return data_rate;
|
||||
}
|
||||
|
@ -674,6 +696,53 @@ intel_atomic_get_bw_state(struct intel_atomic_state *state)
|
|||
return to_intel_bw_state(bw_state);
|
||||
}
|
||||
|
||||
static bool intel_bw_state_changed(struct drm_i915_private *i915,
|
||||
const struct intel_bw_state *old_bw_state,
|
||||
const struct intel_bw_state *new_bw_state)
|
||||
{
|
||||
enum pipe pipe;
|
||||
|
||||
for_each_pipe(i915, pipe) {
|
||||
const struct intel_dbuf_bw *old_crtc_bw =
|
||||
&old_bw_state->dbuf_bw[pipe];
|
||||
const struct intel_dbuf_bw *new_crtc_bw =
|
||||
&new_bw_state->dbuf_bw[pipe];
|
||||
enum dbuf_slice slice;
|
||||
|
||||
for_each_dbuf_slice(i915, slice) {
|
||||
if (old_crtc_bw->max_bw[slice] != new_crtc_bw->max_bw[slice] ||
|
||||
old_crtc_bw->active_planes[slice] != new_crtc_bw->active_planes[slice])
|
||||
return true;
|
||||
}
|
||||
|
||||
if (old_bw_state->min_cdclk[pipe] != new_bw_state->min_cdclk[pipe])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void skl_plane_calc_dbuf_bw(struct intel_bw_state *bw_state,
|
||||
struct intel_crtc *crtc,
|
||||
enum plane_id plane_id,
|
||||
const struct skl_ddb_entry *ddb,
|
||||
unsigned int data_rate)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
struct intel_dbuf_bw *crtc_bw = &bw_state->dbuf_bw[crtc->pipe];
|
||||
unsigned int dbuf_mask = skl_ddb_dbuf_slice_mask(i915, ddb);
|
||||
enum dbuf_slice slice;
|
||||
|
||||
/*
|
||||
* The arbiter can only really guarantee an
|
||||
* equal share of the total bw to each plane.
|
||||
*/
|
||||
for_each_dbuf_slice_in_mask(i915, slice, dbuf_mask) {
|
||||
crtc_bw->max_bw[slice] = max(crtc_bw->max_bw[slice], data_rate);
|
||||
crtc_bw->active_planes[slice] |= BIT(plane_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void skl_crtc_calc_dbuf_bw(struct intel_bw_state *bw_state,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
|
@ -682,52 +751,90 @@ static void skl_crtc_calc_dbuf_bw(struct intel_bw_state *bw_state,
|
|||
struct intel_dbuf_bw *crtc_bw = &bw_state->dbuf_bw[crtc->pipe];
|
||||
enum plane_id plane_id;
|
||||
|
||||
memset(&crtc_bw->used_bw, 0, sizeof(crtc_bw->used_bw));
|
||||
memset(crtc_bw, 0, sizeof(*crtc_bw));
|
||||
|
||||
if (!crtc_state->hw.active)
|
||||
return;
|
||||
|
||||
for_each_plane_id_on_crtc(crtc, plane_id) {
|
||||
const struct skl_ddb_entry *ddb_y =
|
||||
&crtc_state->wm.skl.plane_ddb_y[plane_id];
|
||||
const struct skl_ddb_entry *ddb_uv =
|
||||
&crtc_state->wm.skl.plane_ddb_uv[plane_id];
|
||||
unsigned int data_rate = crtc_state->data_rate[plane_id];
|
||||
unsigned int dbuf_mask = 0;
|
||||
enum dbuf_slice slice;
|
||||
|
||||
dbuf_mask |= skl_ddb_dbuf_slice_mask(i915, ddb_y);
|
||||
dbuf_mask |= skl_ddb_dbuf_slice_mask(i915, ddb_uv);
|
||||
|
||||
/*
|
||||
* FIXME: To calculate that more properly we probably
|
||||
* need to split per plane data_rate into data_rate_y
|
||||
* and data_rate_uv for multiplanar formats in order not
|
||||
* to get accounted those twice if they happen to reside
|
||||
* on different slices.
|
||||
* However for pre-icl this would work anyway because
|
||||
* we have only single slice and for icl+ uv plane has
|
||||
* non-zero data rate.
|
||||
* So in worst case those calculation are a bit
|
||||
* pessimistic, which shouldn't pose any significant
|
||||
* problem anyway.
|
||||
* We assume cursors are small enough
|
||||
* to not cause bandwidth problems.
|
||||
*/
|
||||
for_each_dbuf_slice_in_mask(i915, slice, dbuf_mask)
|
||||
crtc_bw->used_bw[slice] += data_rate;
|
||||
if (plane_id == PLANE_CURSOR)
|
||||
continue;
|
||||
|
||||
skl_plane_calc_dbuf_bw(bw_state, crtc, plane_id,
|
||||
&crtc_state->wm.skl.plane_ddb[plane_id],
|
||||
crtc_state->data_rate[plane_id]);
|
||||
|
||||
if (DISPLAY_VER(i915) < 11)
|
||||
skl_plane_calc_dbuf_bw(bw_state, crtc, plane_id,
|
||||
&crtc_state->wm.skl.plane_ddb_y[plane_id],
|
||||
crtc_state->data_rate[plane_id]);
|
||||
}
|
||||
}
|
||||
|
||||
int skl_bw_calc_min_cdclk(struct intel_atomic_state *state)
|
||||
/* "Maximum Data Buffer Bandwidth" */
|
||||
static int
|
||||
intel_bw_dbuf_min_cdclk(struct drm_i915_private *i915,
|
||||
const struct intel_bw_state *bw_state)
|
||||
{
|
||||
unsigned int total_max_bw = 0;
|
||||
enum dbuf_slice slice;
|
||||
|
||||
for_each_dbuf_slice(i915, slice) {
|
||||
int num_active_planes = 0;
|
||||
unsigned int max_bw = 0;
|
||||
enum pipe pipe;
|
||||
|
||||
/*
|
||||
* The arbiter can only really guarantee an
|
||||
* equal share of the total bw to each plane.
|
||||
*/
|
||||
for_each_pipe(i915, pipe) {
|
||||
const struct intel_dbuf_bw *crtc_bw = &bw_state->dbuf_bw[pipe];
|
||||
|
||||
max_bw = max(crtc_bw->max_bw[slice], max_bw);
|
||||
num_active_planes += hweight8(crtc_bw->active_planes[slice]);
|
||||
}
|
||||
max_bw *= num_active_planes;
|
||||
|
||||
total_max_bw = max(total_max_bw, max_bw);
|
||||
}
|
||||
|
||||
return DIV_ROUND_UP(total_max_bw, 64);
|
||||
}
|
||||
|
||||
int intel_bw_min_cdclk(struct drm_i915_private *i915,
|
||||
const struct intel_bw_state *bw_state)
|
||||
{
|
||||
enum pipe pipe;
|
||||
int min_cdclk;
|
||||
|
||||
min_cdclk = intel_bw_dbuf_min_cdclk(i915, bw_state);
|
||||
|
||||
for_each_pipe(i915, pipe)
|
||||
min_cdclk = max(bw_state->min_cdclk[pipe], min_cdclk);
|
||||
|
||||
return min_cdclk;
|
||||
}
|
||||
|
||||
int intel_bw_calc_min_cdclk(struct intel_atomic_state *state,
|
||||
bool *need_cdclk_calc)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
|
||||
struct intel_bw_state *new_bw_state = NULL;
|
||||
struct intel_bw_state *old_bw_state = NULL;
|
||||
const struct intel_bw_state *old_bw_state = NULL;
|
||||
const struct intel_cdclk_state *cdclk_state;
|
||||
const struct intel_crtc_state *crtc_state;
|
||||
int old_min_cdclk, new_min_cdclk;
|
||||
struct intel_crtc *crtc;
|
||||
int max_bw = 0;
|
||||
enum pipe pipe;
|
||||
int i;
|
||||
|
||||
if (DISPLAY_VER(dev_priv) < 9)
|
||||
return 0;
|
||||
|
||||
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
|
||||
new_bw_state = intel_atomic_get_bw_state(state);
|
||||
if (IS_ERR(new_bw_state))
|
||||
|
@ -736,82 +843,53 @@ int skl_bw_calc_min_cdclk(struct intel_atomic_state *state)
|
|||
old_bw_state = intel_atomic_get_old_bw_state(state);
|
||||
|
||||
skl_crtc_calc_dbuf_bw(new_bw_state, crtc_state);
|
||||
|
||||
new_bw_state->min_cdclk[crtc->pipe] =
|
||||
intel_bw_crtc_min_cdclk(crtc_state);
|
||||
}
|
||||
|
||||
if (!old_bw_state)
|
||||
return 0;
|
||||
|
||||
for_each_pipe(dev_priv, pipe) {
|
||||
struct intel_dbuf_bw *crtc_bw;
|
||||
enum dbuf_slice slice;
|
||||
|
||||
crtc_bw = &new_bw_state->dbuf_bw[pipe];
|
||||
|
||||
for_each_dbuf_slice(dev_priv, slice) {
|
||||
/*
|
||||
* Current experimental observations show that contrary
|
||||
* to BSpec we get underruns once we exceed 64 * CDCLK
|
||||
* for slices in total.
|
||||
* As a temporary measure in order not to keep CDCLK
|
||||
* bumped up all the time we calculate CDCLK according
|
||||
* to this formula for overall bw consumed by slices.
|
||||
*/
|
||||
max_bw += crtc_bw->used_bw[slice];
|
||||
}
|
||||
}
|
||||
|
||||
new_bw_state->min_cdclk = max_bw / 64;
|
||||
|
||||
if (new_bw_state->min_cdclk != old_bw_state->min_cdclk) {
|
||||
if (intel_bw_state_changed(dev_priv, old_bw_state, new_bw_state)) {
|
||||
int ret = intel_atomic_lock_global_state(&new_bw_state->base);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
old_min_cdclk = intel_bw_min_cdclk(dev_priv, old_bw_state);
|
||||
new_min_cdclk = intel_bw_min_cdclk(dev_priv, new_bw_state);
|
||||
|
||||
int intel_bw_calc_min_cdclk(struct intel_atomic_state *state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
|
||||
struct intel_bw_state *new_bw_state = NULL;
|
||||
struct intel_bw_state *old_bw_state = NULL;
|
||||
const struct intel_crtc_state *crtc_state;
|
||||
struct intel_crtc *crtc;
|
||||
int min_cdclk = 0;
|
||||
enum pipe pipe;
|
||||
int i;
|
||||
|
||||
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
|
||||
new_bw_state = intel_atomic_get_bw_state(state);
|
||||
if (IS_ERR(new_bw_state))
|
||||
return PTR_ERR(new_bw_state);
|
||||
|
||||
old_bw_state = intel_atomic_get_old_bw_state(state);
|
||||
}
|
||||
|
||||
if (!old_bw_state)
|
||||
/*
|
||||
* No need to check against the cdclk state if
|
||||
* the min cdclk doesn't increase.
|
||||
*
|
||||
* Ie. we only ever increase the cdclk due to bandwidth
|
||||
* requirements. This can reduce back and forth
|
||||
* display blinking due to constant cdclk changes.
|
||||
*/
|
||||
if (new_min_cdclk <= old_min_cdclk)
|
||||
return 0;
|
||||
|
||||
for_each_pipe(dev_priv, pipe) {
|
||||
struct intel_cdclk_state *cdclk_state;
|
||||
cdclk_state = intel_atomic_get_cdclk_state(state);
|
||||
if (IS_ERR(cdclk_state))
|
||||
return PTR_ERR(cdclk_state);
|
||||
|
||||
cdclk_state = intel_atomic_get_new_cdclk_state(state);
|
||||
if (!cdclk_state)
|
||||
return 0;
|
||||
/*
|
||||
* No need to recalculate the cdclk state if
|
||||
* the min cdclk doesn't increase.
|
||||
*
|
||||
* Ie. we only ever increase the cdclk due to bandwidth
|
||||
* requirements. This can reduce back and forth
|
||||
* display blinking due to constant cdclk changes.
|
||||
*/
|
||||
if (new_min_cdclk <= cdclk_state->bw_min_cdclk)
|
||||
return 0;
|
||||
|
||||
min_cdclk = max(cdclk_state->min_cdclk[pipe], min_cdclk);
|
||||
}
|
||||
|
||||
new_bw_state->min_cdclk = min_cdclk;
|
||||
|
||||
if (new_bw_state->min_cdclk != old_bw_state->min_cdclk) {
|
||||
int ret = intel_atomic_lock_global_state(&new_bw_state->base);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"new bandwidth min cdclk (%d kHz) > old min cdclk (%d kHz)\n",
|
||||
new_min_cdclk, cdclk_state->bw_min_cdclk);
|
||||
*need_cdclk_calc = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -820,7 +898,7 @@ static u16 icl_qgv_points_mask(struct drm_i915_private *i915)
|
|||
{
|
||||
unsigned int num_psf_gv_points = i915->max_bw[0].num_psf_gv_points;
|
||||
unsigned int num_qgv_points = i915->max_bw[0].num_qgv_points;
|
||||
u16 mask = 0;
|
||||
u16 qgv_points = 0, psf_points = 0;
|
||||
|
||||
/*
|
||||
* We can _not_ use the whole ADLS_QGV_PT_MASK here, as PCode rejects
|
||||
|
@ -828,12 +906,12 @@ static u16 icl_qgv_points_mask(struct drm_i915_private *i915)
|
|||
* So need to operate only with those returned from PCode.
|
||||
*/
|
||||
if (num_qgv_points > 0)
|
||||
mask |= REG_GENMASK(num_qgv_points - 1, 0);
|
||||
qgv_points = 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;
|
||||
psf_points = GENMASK(num_psf_gv_points - 1, 0);
|
||||
|
||||
return mask;
|
||||
return ICL_PCODE_REQ_QGV_PT(qgv_points) | ADLS_PCODE_REQ_PSF_PT(psf_points);
|
||||
}
|
||||
|
||||
static int intel_bw_check_data_rate(struct intel_atomic_state *state, bool *changed)
|
||||
|
@ -890,7 +968,7 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
|
|||
unsigned int data_rate;
|
||||
unsigned int num_active_planes;
|
||||
int i, ret;
|
||||
u32 allowed_points = 0;
|
||||
u16 qgv_points = 0, psf_points = 0;
|
||||
unsigned int max_bw_point = 0, max_bw = 0;
|
||||
unsigned int num_qgv_points = dev_priv->max_bw[0].num_qgv_points;
|
||||
unsigned int num_psf_gv_points = dev_priv->max_bw[0].num_psf_gv_points;
|
||||
|
@ -948,7 +1026,7 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
|
|||
max_bw = max_data_rate;
|
||||
}
|
||||
if (max_data_rate >= data_rate)
|
||||
allowed_points |= REG_FIELD_PREP(ADLS_QGV_PT_MASK, BIT(i));
|
||||
qgv_points |= BIT(i);
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "QGV point %d: max bw %d required %d\n",
|
||||
i, max_data_rate, data_rate);
|
||||
|
@ -958,7 +1036,7 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
|
|||
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));
|
||||
psf_points |= BIT(i);
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "PSF GV point %d: max bw %d"
|
||||
" required %d\n",
|
||||
|
@ -970,20 +1048,18 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
|
|||
* left, so if we couldn't - simply reject the configuration for obvious
|
||||
* reasons.
|
||||
*/
|
||||
if ((allowed_points & ADLS_QGV_PT_MASK) == 0) {
|
||||
if (qgv_points == 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;
|
||||
}
|
||||
if (num_psf_gv_points > 0 && psf_points == 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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -992,16 +1068,18 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
|
|||
* cause.
|
||||
*/
|
||||
if (!intel_can_enable_sagv(dev_priv, new_bw_state)) {
|
||||
allowed_points &= ADLS_PSF_PT_MASK;
|
||||
allowed_points |= BIT(max_bw_point);
|
||||
qgv_points = BIT(max_bw_point);
|
||||
drm_dbg_kms(&dev_priv->drm, "No SAGV, using single QGV point %d\n",
|
||||
max_bw_point);
|
||||
}
|
||||
|
||||
/*
|
||||
* We store the ones which need to be masked as that is what PCode
|
||||
* actually accepts as a parameter.
|
||||
*/
|
||||
new_bw_state->qgv_points_mask = ~allowed_points &
|
||||
new_bw_state->qgv_points_mask =
|
||||
~(ICL_PCODE_REQ_QGV_PT(qgv_points) |
|
||||
ADLS_PCODE_REQ_PSF_PT(psf_points)) &
|
||||
icl_qgv_points_mask(dev_priv);
|
||||
|
||||
/*
|
||||
|
|
|
@ -17,7 +17,8 @@ struct intel_atomic_state;
|
|||
struct intel_crtc_state;
|
||||
|
||||
struct intel_dbuf_bw {
|
||||
int used_bw[I915_MAX_DBUF_SLICES];
|
||||
unsigned int max_bw[I915_MAX_DBUF_SLICES];
|
||||
u8 active_planes[I915_MAX_DBUF_SLICES];
|
||||
};
|
||||
|
||||
struct intel_bw_state {
|
||||
|
@ -40,10 +41,9 @@ struct intel_bw_state {
|
|||
*/
|
||||
u16 qgv_points_mask;
|
||||
|
||||
int min_cdclk[I915_MAX_PIPES];
|
||||
unsigned int data_rate[I915_MAX_PIPES];
|
||||
u8 num_active_planes[I915_MAX_PIPES];
|
||||
|
||||
int min_cdclk;
|
||||
};
|
||||
|
||||
#define to_intel_bw_state(x) container_of((x), struct intel_bw_state, base)
|
||||
|
@ -64,7 +64,9 @@ void intel_bw_crtc_update(struct intel_bw_state *bw_state,
|
|||
const struct intel_crtc_state *crtc_state);
|
||||
int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv,
|
||||
u32 points_mask);
|
||||
int intel_bw_calc_min_cdclk(struct intel_atomic_state *state);
|
||||
int skl_bw_calc_min_cdclk(struct intel_atomic_state *state);
|
||||
int intel_bw_calc_min_cdclk(struct intel_atomic_state *state,
|
||||
bool *need_cdclk_calc);
|
||||
int intel_bw_min_cdclk(struct drm_i915_private *i915,
|
||||
const struct intel_bw_state *bw_state);
|
||||
|
||||
#endif /* __INTEL_BW_H__ */
|
||||
|
|
|
@ -72,7 +72,6 @@ struct intel_cdclk_funcs {
|
|||
void (*set_cdclk)(struct drm_i915_private *i915,
|
||||
const struct intel_cdclk_config *cdclk_config,
|
||||
enum pipe pipe);
|
||||
int (*bw_calc_min_cdclk)(struct intel_atomic_state *state);
|
||||
int (*modeset_calc_cdclk)(struct intel_cdclk_state *state);
|
||||
u8 (*calc_voltage_level)(int cdclk);
|
||||
};
|
||||
|
@ -83,12 +82,6 @@ void intel_cdclk_get_cdclk(struct drm_i915_private *dev_priv,
|
|||
dev_priv->cdclk_funcs->get_cdclk(dev_priv, cdclk_config);
|
||||
}
|
||||
|
||||
static int intel_cdclk_bw_calc_min_cdclk(struct intel_atomic_state *state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
|
||||
return dev_priv->cdclk_funcs->bw_calc_min_cdclk(state);
|
||||
}
|
||||
|
||||
static void intel_cdclk_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
const struct intel_cdclk_config *cdclk_config,
|
||||
enum pipe pipe)
|
||||
|
@ -2325,13 +2318,6 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
|
|||
dev_priv->max_cdclk_freq));
|
||||
}
|
||||
|
||||
if (min_cdclk > dev_priv->max_cdclk_freq) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"required cdclk (%d kHz) exceeds max (%d kHz)\n",
|
||||
min_cdclk, dev_priv->max_cdclk_freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return min_cdclk;
|
||||
}
|
||||
|
||||
|
@ -2339,7 +2325,7 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state)
|
|||
{
|
||||
struct intel_atomic_state *state = cdclk_state->base.state;
|
||||
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
|
||||
struct intel_bw_state *bw_state = NULL;
|
||||
const struct intel_bw_state *bw_state;
|
||||
struct intel_crtc *crtc;
|
||||
struct intel_crtc_state *crtc_state;
|
||||
int min_cdclk, i;
|
||||
|
@ -2352,10 +2338,6 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state)
|
|||
if (min_cdclk < 0)
|
||||
return min_cdclk;
|
||||
|
||||
bw_state = intel_atomic_get_bw_state(state);
|
||||
if (IS_ERR(bw_state))
|
||||
return PTR_ERR(bw_state);
|
||||
|
||||
if (cdclk_state->min_cdclk[crtc->pipe] == min_cdclk)
|
||||
continue;
|
||||
|
||||
|
@ -2366,14 +2348,31 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state)
|
|||
return ret;
|
||||
}
|
||||
|
||||
min_cdclk = cdclk_state->force_min_cdclk;
|
||||
for_each_pipe(dev_priv, pipe) {
|
||||
bw_state = intel_atomic_get_new_bw_state(state);
|
||||
if (bw_state) {
|
||||
min_cdclk = intel_bw_min_cdclk(dev_priv, bw_state);
|
||||
|
||||
if (cdclk_state->bw_min_cdclk != min_cdclk) {
|
||||
int ret;
|
||||
|
||||
cdclk_state->bw_min_cdclk = min_cdclk;
|
||||
|
||||
ret = intel_atomic_lock_global_state(&cdclk_state->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
min_cdclk = max(cdclk_state->force_min_cdclk,
|
||||
cdclk_state->bw_min_cdclk);
|
||||
for_each_pipe(dev_priv, pipe)
|
||||
min_cdclk = max(cdclk_state->min_cdclk[pipe], min_cdclk);
|
||||
|
||||
if (!bw_state)
|
||||
continue;
|
||||
|
||||
min_cdclk = max(bw_state->min_cdclk, min_cdclk);
|
||||
if (min_cdclk > dev_priv->max_cdclk_freq) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"required cdclk (%d kHz) exceeds max (%d kHz)\n",
|
||||
min_cdclk, dev_priv->max_cdclk_freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return min_cdclk;
|
||||
|
@ -2654,14 +2653,10 @@ intel_atomic_get_cdclk_state(struct intel_atomic_state *state)
|
|||
int intel_cdclk_atomic_check(struct intel_atomic_state *state,
|
||||
bool *need_cdclk_calc)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(state->base.dev);
|
||||
const struct intel_cdclk_state *old_cdclk_state;
|
||||
const struct intel_cdclk_state *new_cdclk_state;
|
||||
struct intel_plane_state *plane_state;
|
||||
struct intel_bw_state *new_bw_state;
|
||||
struct intel_plane *plane;
|
||||
int min_cdclk = 0;
|
||||
enum pipe pipe;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
|
@ -2676,6 +2671,10 @@ int intel_cdclk_atomic_check(struct intel_atomic_state *state,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = intel_bw_calc_min_cdclk(state, need_cdclk_calc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
old_cdclk_state = intel_atomic_get_old_cdclk_state(state);
|
||||
new_cdclk_state = intel_atomic_get_new_cdclk_state(state);
|
||||
|
||||
|
@ -2683,23 +2682,6 @@ int intel_cdclk_atomic_check(struct intel_atomic_state *state,
|
|||
old_cdclk_state->force_min_cdclk != new_cdclk_state->force_min_cdclk)
|
||||
*need_cdclk_calc = true;
|
||||
|
||||
ret = intel_cdclk_bw_calc_min_cdclk(state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
new_bw_state = intel_atomic_get_new_bw_state(state);
|
||||
|
||||
if (!new_cdclk_state || !new_bw_state)
|
||||
return 0;
|
||||
|
||||
for_each_pipe(i915, pipe) {
|
||||
min_cdclk = max(new_cdclk_state->min_cdclk[pipe], min_cdclk);
|
||||
|
||||
/* Currently do this change only if we need to increase */
|
||||
if (new_bw_state->min_cdclk > min_cdclk)
|
||||
*need_cdclk_calc = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3072,7 +3054,6 @@ u32 intel_read_rawclk(struct drm_i915_private *dev_priv)
|
|||
static const struct intel_cdclk_funcs tgl_cdclk_funcs = {
|
||||
.get_cdclk = bxt_get_cdclk,
|
||||
.set_cdclk = bxt_set_cdclk,
|
||||
.bw_calc_min_cdclk = skl_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = bxt_modeset_calc_cdclk,
|
||||
.calc_voltage_level = tgl_calc_voltage_level,
|
||||
};
|
||||
|
@ -3080,7 +3061,6 @@ static const struct intel_cdclk_funcs tgl_cdclk_funcs = {
|
|||
static const struct intel_cdclk_funcs ehl_cdclk_funcs = {
|
||||
.get_cdclk = bxt_get_cdclk,
|
||||
.set_cdclk = bxt_set_cdclk,
|
||||
.bw_calc_min_cdclk = skl_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = bxt_modeset_calc_cdclk,
|
||||
.calc_voltage_level = ehl_calc_voltage_level,
|
||||
};
|
||||
|
@ -3088,7 +3068,6 @@ static const struct intel_cdclk_funcs ehl_cdclk_funcs = {
|
|||
static const struct intel_cdclk_funcs icl_cdclk_funcs = {
|
||||
.get_cdclk = bxt_get_cdclk,
|
||||
.set_cdclk = bxt_set_cdclk,
|
||||
.bw_calc_min_cdclk = skl_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = bxt_modeset_calc_cdclk,
|
||||
.calc_voltage_level = icl_calc_voltage_level,
|
||||
};
|
||||
|
@ -3096,7 +3075,6 @@ static const struct intel_cdclk_funcs icl_cdclk_funcs = {
|
|||
static const struct intel_cdclk_funcs bxt_cdclk_funcs = {
|
||||
.get_cdclk = bxt_get_cdclk,
|
||||
.set_cdclk = bxt_set_cdclk,
|
||||
.bw_calc_min_cdclk = skl_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = bxt_modeset_calc_cdclk,
|
||||
.calc_voltage_level = bxt_calc_voltage_level,
|
||||
};
|
||||
|
@ -3104,53 +3082,45 @@ static const struct intel_cdclk_funcs bxt_cdclk_funcs = {
|
|||
static const struct intel_cdclk_funcs skl_cdclk_funcs = {
|
||||
.get_cdclk = skl_get_cdclk,
|
||||
.set_cdclk = skl_set_cdclk,
|
||||
.bw_calc_min_cdclk = skl_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = skl_modeset_calc_cdclk,
|
||||
};
|
||||
|
||||
static const struct intel_cdclk_funcs bdw_cdclk_funcs = {
|
||||
.get_cdclk = bdw_get_cdclk,
|
||||
.set_cdclk = bdw_set_cdclk,
|
||||
.bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = bdw_modeset_calc_cdclk,
|
||||
};
|
||||
|
||||
static const struct intel_cdclk_funcs chv_cdclk_funcs = {
|
||||
.get_cdclk = vlv_get_cdclk,
|
||||
.set_cdclk = chv_set_cdclk,
|
||||
.bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = vlv_modeset_calc_cdclk,
|
||||
};
|
||||
|
||||
static const struct intel_cdclk_funcs vlv_cdclk_funcs = {
|
||||
.get_cdclk = vlv_get_cdclk,
|
||||
.set_cdclk = vlv_set_cdclk,
|
||||
.bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = vlv_modeset_calc_cdclk,
|
||||
};
|
||||
|
||||
static const struct intel_cdclk_funcs hsw_cdclk_funcs = {
|
||||
.get_cdclk = hsw_get_cdclk,
|
||||
.bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
|
||||
};
|
||||
|
||||
/* SNB, IVB, 965G, 945G */
|
||||
static const struct intel_cdclk_funcs fixed_400mhz_cdclk_funcs = {
|
||||
.get_cdclk = fixed_400mhz_get_cdclk,
|
||||
.bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
|
||||
};
|
||||
|
||||
static const struct intel_cdclk_funcs ilk_cdclk_funcs = {
|
||||
.get_cdclk = fixed_450mhz_get_cdclk,
|
||||
.bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
|
||||
};
|
||||
|
||||
static const struct intel_cdclk_funcs gm45_cdclk_funcs = {
|
||||
.get_cdclk = gm45_get_cdclk,
|
||||
.bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
|
||||
};
|
||||
|
||||
|
@ -3158,7 +3128,6 @@ static const struct intel_cdclk_funcs gm45_cdclk_funcs = {
|
|||
|
||||
static const struct intel_cdclk_funcs i965gm_cdclk_funcs = {
|
||||
.get_cdclk = i965gm_get_cdclk,
|
||||
.bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
|
||||
};
|
||||
|
||||
|
@ -3166,19 +3135,16 @@ static const struct intel_cdclk_funcs i965gm_cdclk_funcs = {
|
|||
|
||||
static const struct intel_cdclk_funcs pnv_cdclk_funcs = {
|
||||
.get_cdclk = pnv_get_cdclk,
|
||||
.bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
|
||||
};
|
||||
|
||||
static const struct intel_cdclk_funcs g33_cdclk_funcs = {
|
||||
.get_cdclk = g33_get_cdclk,
|
||||
.bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
|
||||
};
|
||||
|
||||
static const struct intel_cdclk_funcs i945gm_cdclk_funcs = {
|
||||
.get_cdclk = i945gm_get_cdclk,
|
||||
.bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
|
||||
};
|
||||
|
||||
|
@ -3186,37 +3152,31 @@ static const struct intel_cdclk_funcs i945gm_cdclk_funcs = {
|
|||
|
||||
static const struct intel_cdclk_funcs i915gm_cdclk_funcs = {
|
||||
.get_cdclk = i915gm_get_cdclk,
|
||||
.bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
|
||||
};
|
||||
|
||||
static const struct intel_cdclk_funcs i915g_cdclk_funcs = {
|
||||
.get_cdclk = fixed_333mhz_get_cdclk,
|
||||
.bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
|
||||
};
|
||||
|
||||
static const struct intel_cdclk_funcs i865g_cdclk_funcs = {
|
||||
.get_cdclk = fixed_266mhz_get_cdclk,
|
||||
.bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
|
||||
};
|
||||
|
||||
static const struct intel_cdclk_funcs i85x_cdclk_funcs = {
|
||||
.get_cdclk = i85x_get_cdclk,
|
||||
.bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
|
||||
};
|
||||
|
||||
static const struct intel_cdclk_funcs i845g_cdclk_funcs = {
|
||||
.get_cdclk = fixed_200mhz_get_cdclk,
|
||||
.bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
|
||||
};
|
||||
|
||||
static const struct intel_cdclk_funcs i830_cdclk_funcs = {
|
||||
.get_cdclk = fixed_133mhz_get_cdclk,
|
||||
.bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
|
||||
.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
|
||||
};
|
||||
|
||||
|
|
|
@ -36,6 +36,8 @@ struct intel_cdclk_state {
|
|||
*/
|
||||
struct intel_cdclk_config actual;
|
||||
|
||||
/* minimum acceptable cdclk to satisfy bandwidth requirements */
|
||||
int bw_min_cdclk;
|
||||
/* minimum acceptable cdclk for each pipe */
|
||||
int min_cdclk[I915_MAX_PIPES];
|
||||
/* minimum acceptable voltage level for each pipe */
|
||||
|
|
|
@ -31,12 +31,21 @@
|
|||
struct intel_color_funcs {
|
||||
int (*color_check)(struct intel_crtc_state *crtc_state);
|
||||
/*
|
||||
* Program double buffered color management registers during
|
||||
* vblank evasion. The registers should then latch during the
|
||||
* next vblank start, alongside any other double buffered registers
|
||||
* involved with the same commit.
|
||||
* Program non-arming double buffered color management registers
|
||||
* before vblank evasion. The registers should then latch after
|
||||
* the arming register is written (by color_commit_arm()) during
|
||||
* the next vblank start, alongside any other double buffered
|
||||
* registers involved with the same commit. This hook is optional.
|
||||
*/
|
||||
void (*color_commit)(const struct intel_crtc_state *crtc_state);
|
||||
void (*color_commit_noarm)(const struct intel_crtc_state *crtc_state);
|
||||
/*
|
||||
* Program arming double buffered color management registers
|
||||
* during vblank evasion. The registers (and whatever other registers
|
||||
* they arm that were written by color_commit_noarm) should then latch
|
||||
* during the next vblank start, alongside any other double buffered
|
||||
* registers involved with the same commit.
|
||||
*/
|
||||
void (*color_commit_arm)(const struct intel_crtc_state *crtc_state);
|
||||
/*
|
||||
* Load LUTs (and other single buffered color management
|
||||
* registers). Will (hopefully) be called during the vblank
|
||||
|
@ -337,15 +346,11 @@ static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state)
|
|||
ilk_csc_coeff_identity,
|
||||
ilk_csc_off_zero);
|
||||
}
|
||||
|
||||
intel_de_write_fw(dev_priv, PIPE_CSC_MODE(crtc->pipe),
|
||||
crtc_state->csc_mode);
|
||||
}
|
||||
|
||||
static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
|
||||
if (crtc_state->hw.ctm) {
|
||||
u16 coeff[9];
|
||||
|
@ -364,9 +369,6 @@ static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state)
|
|||
ilk_csc_coeff_limited_range,
|
||||
ilk_csc_postoff_limited_range);
|
||||
}
|
||||
|
||||
intel_de_write_fw(dev_priv, PIPE_CSC_MODE(crtc->pipe),
|
||||
crtc_state->csc_mode);
|
||||
}
|
||||
|
||||
static void chv_load_cgm_csc(struct intel_crtc *crtc,
|
||||
|
@ -491,7 +493,17 @@ static void icl_lut_multi_seg_pack(struct drm_color_lut *entry, u32 ldw, u32 udw
|
|||
REG_FIELD_GET(PAL_PREC_MULTI_SEG_BLUE_LDW_MASK, ldw);
|
||||
}
|
||||
|
||||
static void i9xx_color_commit(const struct intel_crtc_state *crtc_state)
|
||||
static void icl_color_commit_noarm(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
icl_load_csc_matrix(crtc_state);
|
||||
}
|
||||
|
||||
static void ilk_color_commit_noarm(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
ilk_load_csc_matrix(crtc_state);
|
||||
}
|
||||
|
||||
static void i9xx_color_commit_arm(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
|
@ -504,7 +516,7 @@ static void i9xx_color_commit(const struct intel_crtc_state *crtc_state)
|
|||
intel_de_write(dev_priv, PIPECONF(pipe), val);
|
||||
}
|
||||
|
||||
static void ilk_color_commit(const struct intel_crtc_state *crtc_state)
|
||||
static void ilk_color_commit_arm(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
|
@ -516,10 +528,11 @@ static void ilk_color_commit(const struct intel_crtc_state *crtc_state)
|
|||
val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
|
||||
intel_de_write(dev_priv, PIPECONF(pipe), val);
|
||||
|
||||
ilk_load_csc_matrix(crtc_state);
|
||||
intel_de_write_fw(dev_priv, PIPE_CSC_MODE(pipe),
|
||||
crtc_state->csc_mode);
|
||||
}
|
||||
|
||||
static void hsw_color_commit(const struct intel_crtc_state *crtc_state)
|
||||
static void hsw_color_commit_arm(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
|
@ -527,10 +540,11 @@ static void hsw_color_commit(const struct intel_crtc_state *crtc_state)
|
|||
intel_de_write(dev_priv, GAMMA_MODE(crtc->pipe),
|
||||
crtc_state->gamma_mode);
|
||||
|
||||
ilk_load_csc_matrix(crtc_state);
|
||||
intel_de_write_fw(dev_priv, PIPE_CSC_MODE(crtc->pipe),
|
||||
crtc_state->csc_mode);
|
||||
}
|
||||
|
||||
static void skl_color_commit(const struct intel_crtc_state *crtc_state)
|
||||
static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
|
@ -551,10 +565,8 @@ static void skl_color_commit(const struct intel_crtc_state *crtc_state)
|
|||
intel_de_write(dev_priv, GAMMA_MODE(crtc->pipe),
|
||||
crtc_state->gamma_mode);
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 11)
|
||||
icl_load_csc_matrix(crtc_state);
|
||||
else
|
||||
ilk_load_csc_matrix(crtc_state);
|
||||
intel_de_write_fw(dev_priv, PIPE_CSC_MODE(crtc->pipe),
|
||||
crtc_state->csc_mode);
|
||||
}
|
||||
|
||||
static void i9xx_load_lut_8(struct intel_crtc *crtc,
|
||||
|
@ -1169,11 +1181,19 @@ void intel_color_load_luts(const struct intel_crtc_state *crtc_state)
|
|||
dev_priv->color_funcs->load_luts(crtc_state);
|
||||
}
|
||||
|
||||
void intel_color_commit(const struct intel_crtc_state *crtc_state)
|
||||
void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
|
||||
|
||||
dev_priv->color_funcs->color_commit(crtc_state);
|
||||
if (dev_priv->color_funcs->color_commit_noarm)
|
||||
dev_priv->color_funcs->color_commit_noarm(crtc_state);
|
||||
}
|
||||
|
||||
void intel_color_commit_arm(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
|
||||
|
||||
dev_priv->color_funcs->color_commit_arm(crtc_state);
|
||||
}
|
||||
|
||||
static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
|
||||
|
@ -2132,70 +2152,77 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state)
|
|||
|
||||
static const struct intel_color_funcs chv_color_funcs = {
|
||||
.color_check = chv_color_check,
|
||||
.color_commit = i9xx_color_commit,
|
||||
.color_commit_arm = i9xx_color_commit_arm,
|
||||
.load_luts = chv_load_luts,
|
||||
.read_luts = chv_read_luts,
|
||||
};
|
||||
|
||||
static const struct intel_color_funcs i965_color_funcs = {
|
||||
.color_check = i9xx_color_check,
|
||||
.color_commit = i9xx_color_commit,
|
||||
.color_commit_arm = i9xx_color_commit_arm,
|
||||
.load_luts = i965_load_luts,
|
||||
.read_luts = i965_read_luts,
|
||||
};
|
||||
|
||||
static const struct intel_color_funcs i9xx_color_funcs = {
|
||||
.color_check = i9xx_color_check,
|
||||
.color_commit = i9xx_color_commit,
|
||||
.color_commit_arm = i9xx_color_commit_arm,
|
||||
.load_luts = i9xx_load_luts,
|
||||
.read_luts = i9xx_read_luts,
|
||||
};
|
||||
|
||||
static const struct intel_color_funcs icl_color_funcs = {
|
||||
.color_check = icl_color_check,
|
||||
.color_commit = skl_color_commit,
|
||||
.color_commit_noarm = icl_color_commit_noarm,
|
||||
.color_commit_arm = skl_color_commit_arm,
|
||||
.load_luts = icl_load_luts,
|
||||
.read_luts = icl_read_luts,
|
||||
};
|
||||
|
||||
static const struct intel_color_funcs glk_color_funcs = {
|
||||
.color_check = glk_color_check,
|
||||
.color_commit = skl_color_commit,
|
||||
.color_commit_noarm = ilk_color_commit_noarm,
|
||||
.color_commit_arm = skl_color_commit_arm,
|
||||
.load_luts = glk_load_luts,
|
||||
.read_luts = glk_read_luts,
|
||||
};
|
||||
|
||||
static const struct intel_color_funcs skl_color_funcs = {
|
||||
.color_check = ivb_color_check,
|
||||
.color_commit = skl_color_commit,
|
||||
.color_commit_noarm = ilk_color_commit_noarm,
|
||||
.color_commit_arm = skl_color_commit_arm,
|
||||
.load_luts = bdw_load_luts,
|
||||
.read_luts = NULL,
|
||||
};
|
||||
|
||||
static const struct intel_color_funcs bdw_color_funcs = {
|
||||
.color_check = ivb_color_check,
|
||||
.color_commit = hsw_color_commit,
|
||||
.color_commit_noarm = ilk_color_commit_noarm,
|
||||
.color_commit_arm = hsw_color_commit_arm,
|
||||
.load_luts = bdw_load_luts,
|
||||
.read_luts = NULL,
|
||||
};
|
||||
|
||||
static const struct intel_color_funcs hsw_color_funcs = {
|
||||
.color_check = ivb_color_check,
|
||||
.color_commit = hsw_color_commit,
|
||||
.color_commit_noarm = ilk_color_commit_noarm,
|
||||
.color_commit_arm = hsw_color_commit_arm,
|
||||
.load_luts = ivb_load_luts,
|
||||
.read_luts = NULL,
|
||||
};
|
||||
|
||||
static const struct intel_color_funcs ivb_color_funcs = {
|
||||
.color_check = ivb_color_check,
|
||||
.color_commit = ilk_color_commit,
|
||||
.color_commit_noarm = ilk_color_commit_noarm,
|
||||
.color_commit_arm = ilk_color_commit_arm,
|
||||
.load_luts = ivb_load_luts,
|
||||
.read_luts = NULL,
|
||||
};
|
||||
|
||||
static const struct intel_color_funcs ilk_color_funcs = {
|
||||
.color_check = ilk_color_check,
|
||||
.color_commit = ilk_color_commit,
|
||||
.color_commit_noarm = ilk_color_commit_noarm,
|
||||
.color_commit_arm = ilk_color_commit_arm,
|
||||
.load_luts = ilk_load_luts,
|
||||
.read_luts = ilk_read_luts,
|
||||
};
|
||||
|
|
|
@ -14,7 +14,8 @@ struct drm_property_blob;
|
|||
|
||||
void intel_color_init(struct intel_crtc *crtc);
|
||||
int intel_color_check(struct intel_crtc_state *crtc_state);
|
||||
void intel_color_commit(const struct intel_crtc_state *crtc_state);
|
||||
void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state);
|
||||
void intel_color_commit_arm(const struct intel_crtc_state *crtc_state);
|
||||
void intel_color_load_luts(const struct intel_crtc_state *crtc_state);
|
||||
void intel_color_get_config(struct intel_crtc_state *crtc_state);
|
||||
int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_state);
|
||||
|
|
|
@ -25,18 +25,29 @@ enum {
|
|||
};
|
||||
|
||||
static const struct icl_procmon {
|
||||
const char *name;
|
||||
u32 dw1, dw9, dw10;
|
||||
} icl_procmon_values[] = {
|
||||
[PROCMON_0_85V_DOT_0] =
|
||||
{ .dw1 = 0x00000000, .dw9 = 0x62AB67BB, .dw10 = 0x51914F96, },
|
||||
[PROCMON_0_95V_DOT_0] =
|
||||
{ .dw1 = 0x00000000, .dw9 = 0x86E172C7, .dw10 = 0x77CA5EAB, },
|
||||
[PROCMON_0_95V_DOT_1] =
|
||||
{ .dw1 = 0x00000000, .dw9 = 0x93F87FE1, .dw10 = 0x8AE871C5, },
|
||||
[PROCMON_1_05V_DOT_0] =
|
||||
{ .dw1 = 0x00000000, .dw9 = 0x98FA82DD, .dw10 = 0x89E46DC1, },
|
||||
[PROCMON_1_05V_DOT_1] =
|
||||
{ .dw1 = 0x00440000, .dw9 = 0x9A00AB25, .dw10 = 0x8AE38FF1, },
|
||||
[PROCMON_0_85V_DOT_0] = {
|
||||
.name = "0.85V dot0 (low-voltage)",
|
||||
.dw1 = 0x00000000, .dw9 = 0x62AB67BB, .dw10 = 0x51914F96,
|
||||
},
|
||||
[PROCMON_0_95V_DOT_0] = {
|
||||
.name = "0.95V dot0",
|
||||
.dw1 = 0x00000000, .dw9 = 0x86E172C7, .dw10 = 0x77CA5EAB,
|
||||
},
|
||||
[PROCMON_0_95V_DOT_1] = {
|
||||
.name = "0.95V dot1",
|
||||
.dw1 = 0x00000000, .dw9 = 0x93F87FE1, .dw10 = 0x8AE871C5,
|
||||
},
|
||||
[PROCMON_1_05V_DOT_0] = {
|
||||
.name = "1.05V dot0",
|
||||
.dw1 = 0x00000000, .dw9 = 0x98FA82DD, .dw10 = 0x89E46DC1,
|
||||
},
|
||||
[PROCMON_1_05V_DOT_1] = {
|
||||
.name = "1.05V dot1",
|
||||
.dw1 = 0x00440000, .dw9 = 0x9A00AB25, .dw10 = 0x8AE38FF1,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct icl_procmon *
|
||||
|
@ -113,6 +124,10 @@ static bool icl_verify_procmon_ref_values(struct drm_i915_private *dev_priv,
|
|||
|
||||
procmon = icl_get_procmon_ref_values(dev_priv, phy);
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Combo PHY %c Voltage/Process Info : %s\n",
|
||||
phy_name(phy), procmon->name);
|
||||
|
||||
ret = check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW1(phy),
|
||||
(0xff << 16) | 0xff, procmon->dw1);
|
||||
ret &= check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW9(phy),
|
||||
|
|
|
@ -54,6 +54,8 @@ int intel_connector_init(struct intel_connector *connector)
|
|||
__drm_atomic_helper_connector_reset(&connector->base,
|
||||
&conn_state->base);
|
||||
|
||||
INIT_LIST_HEAD(&connector->panel.fixed_modes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -100,7 +102,7 @@ void intel_connector_destroy(struct drm_connector *connector)
|
|||
if (!IS_ERR_OR_NULL(intel_connector->edid))
|
||||
kfree(intel_connector->edid);
|
||||
|
||||
intel_panel_fini(&intel_connector->panel);
|
||||
intel_panel_fini(intel_connector);
|
||||
|
||||
drm_connector_cleanup(connector);
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "intel_display_debugfs.h"
|
||||
#include "intel_display_trace.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_drrs.h"
|
||||
#include "intel_dsi.h"
|
||||
#include "intel_pipe_crc.h"
|
||||
#include "intel_psr.h"
|
||||
|
@ -367,6 +368,7 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
|
|||
|
||||
intel_color_init(crtc);
|
||||
|
||||
intel_crtc_drrs_init(crtc);
|
||||
intel_crtc_crc_init(crtc);
|
||||
|
||||
cpu_latency_qos_add_request(&crtc->vblank_pm_qos, PM_QOS_DEFAULT_VALUE);
|
||||
|
@ -485,6 +487,8 @@ void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state)
|
|||
intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
|
||||
DEFINE_WAIT(wait);
|
||||
|
||||
intel_psr_lock(new_crtc_state);
|
||||
|
||||
if (new_crtc_state->do_async_flip)
|
||||
return;
|
||||
|
||||
|
@ -516,7 +520,7 @@ void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state)
|
|||
* VBL interrupts will start the PSR exit and prevent a PSR
|
||||
* re-entry as well.
|
||||
*/
|
||||
intel_psr_wait_for_idle(new_crtc_state);
|
||||
intel_psr_wait_for_idle_locked(new_crtc_state);
|
||||
|
||||
local_irq_disable();
|
||||
|
||||
|
@ -630,6 +634,8 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
|
|||
ktime_t end_vbl_time = ktime_get();
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
|
||||
intel_psr_unlock(new_crtc_state);
|
||||
|
||||
if (new_crtc_state->do_async_flip)
|
||||
return;
|
||||
|
||||
|
|
|
@ -153,6 +153,11 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state,
|
|||
plane_state->uapi.src = src;
|
||||
plane_state->uapi.dst = dst;
|
||||
|
||||
/* final plane coordinates will be relative to the plane's pipe */
|
||||
drm_rect_translate(&plane_state->uapi.dst,
|
||||
-crtc_state->pipe_src.x1,
|
||||
-crtc_state->pipe_src.y1);
|
||||
|
||||
ret = intel_cursor_check_surface(plane_state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -255,7 +260,6 @@ static void i845_cursor_update_arm(struct intel_plane *plane,
|
|||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
||||
u32 cntl = 0, base = 0, pos = 0, size = 0;
|
||||
unsigned long irqflags;
|
||||
|
||||
if (plane_state && plane_state->uapi.visible) {
|
||||
unsigned int width = drm_rect_width(&plane_state->uapi.dst);
|
||||
|
@ -270,8 +274,6 @@ static void i845_cursor_update_arm(struct intel_plane *plane,
|
|||
pos = intel_cursor_position(plane_state);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
/* On these chipsets we can only modify the base/size/stride
|
||||
* whilst the cursor is disabled.
|
||||
*/
|
||||
|
@ -290,8 +292,6 @@ static void i845_cursor_update_arm(struct intel_plane *plane,
|
|||
} else {
|
||||
intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void i845_cursor_disable_arm(struct intel_plane *plane,
|
||||
|
@ -492,7 +492,6 @@ static void i9xx_cursor_update_arm(struct intel_plane *plane,
|
|||
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
||||
enum pipe pipe = plane->pipe;
|
||||
u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
|
||||
unsigned long irqflags;
|
||||
|
||||
if (plane_state && plane_state->uapi.visible) {
|
||||
int width = drm_rect_width(&plane_state->uapi.dst);
|
||||
|
@ -508,8 +507,6 @@ static void i9xx_cursor_update_arm(struct intel_plane *plane,
|
|||
pos = intel_cursor_position(plane_state);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
/*
|
||||
* On some platforms writing CURCNTR first will also
|
||||
* cause CURPOS to be armed by the CURBASE write.
|
||||
|
@ -555,8 +552,6 @@ static void i9xx_cursor_update_arm(struct intel_plane *plane,
|
|||
intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
|
||||
intel_de_write_fw(dev_priv, CURBASE(pipe), base);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void i9xx_cursor_disable_arm(struct intel_plane *plane,
|
||||
|
@ -637,7 +632,7 @@ intel_legacy_cursor_update(struct drm_plane *_plane,
|
|||
* 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_pipes)
|
||||
goto slow;
|
||||
|
||||
/*
|
||||
|
@ -715,6 +710,14 @@ intel_legacy_cursor_update(struct drm_plane *_plane,
|
|||
*/
|
||||
crtc_state->active_planes = new_crtc_state->active_planes;
|
||||
|
||||
/*
|
||||
* Technically we should do a vblank evasion here to make
|
||||
* sure all the cursor registers update on the same frame.
|
||||
* For now just make sure the register writes happen as
|
||||
* quickly as possible to minimize the race window.
|
||||
*/
|
||||
local_irq_disable();
|
||||
|
||||
if (new_plane_state->uapi.visible) {
|
||||
intel_plane_update_noarm(plane, crtc_state, new_plane_state);
|
||||
intel_plane_update_arm(plane, crtc_state, new_plane_state);
|
||||
|
@ -722,6 +725,8 @@ intel_legacy_cursor_update(struct drm_plane *_plane,
|
|||
intel_plane_disable_arm(plane, crtc_state);
|
||||
}
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
intel_plane_unpin_fb(old_plane_state);
|
||||
|
||||
out_free:
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include <drm/drm_privacy_screen_consumer.h>
|
||||
#include <drm/drm_scdc_helper.h>
|
||||
|
||||
|
@ -43,7 +45,6 @@
|
|||
#include "intel_dp_link_training.h"
|
||||
#include "intel_dp_mst.h"
|
||||
#include "intel_dpio_phy.h"
|
||||
#include "intel_drrs.h"
|
||||
#include "intel_dsi.h"
|
||||
#include "intel_fdi.h"
|
||||
#include "intel_fifo_underrun.h"
|
||||
|
@ -2152,7 +2153,7 @@ static void intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel
|
|||
enable ? DP_MSA_TIMING_PAR_IGNORE_EN : 0) <= 0)
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"Failed to %s MSA_TIMING_PAR_IGNORE in the sink\n",
|
||||
enabledisable(enable));
|
||||
str_enable_disable(enable));
|
||||
}
|
||||
|
||||
static void intel_dp_sink_set_fec_ready(struct intel_dp *intel_dp,
|
||||
|
@ -2818,10 +2819,7 @@ static void intel_enable_ddi_dp(struct intel_atomic_state *state,
|
|||
if (!dig_port->lspcon.active || dig_port->dp.has_hdmi_sink)
|
||||
intel_dp_set_infoframes(encoder, true, crtc_state, conn_state);
|
||||
|
||||
intel_drrs_enable(intel_dp, crtc_state);
|
||||
|
||||
if (crtc_state->has_audio)
|
||||
intel_audio_codec_enable(encoder, crtc_state, conn_state);
|
||||
intel_audio_codec_enable(encoder, crtc_state, conn_state);
|
||||
|
||||
trans_port_sync_stop_link_train(state, encoder, crtc_state);
|
||||
}
|
||||
|
@ -2915,8 +2913,7 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
|
|||
intel_de_write(dev_priv, DDI_BUF_CTL(port),
|
||||
dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE);
|
||||
|
||||
if (crtc_state->has_audio)
|
||||
intel_audio_codec_enable(encoder, crtc_state, conn_state);
|
||||
intel_audio_codec_enable(encoder, crtc_state, conn_state);
|
||||
}
|
||||
|
||||
static void intel_enable_ddi(struct intel_atomic_state *state,
|
||||
|
@ -2957,11 +2954,8 @@ static void intel_disable_ddi_dp(struct intel_atomic_state *state,
|
|||
|
||||
intel_dp->link_trained = false;
|
||||
|
||||
if (old_crtc_state->has_audio)
|
||||
intel_audio_codec_disable(encoder,
|
||||
old_crtc_state, old_conn_state);
|
||||
intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
|
||||
|
||||
intel_drrs_disable(intel_dp, old_crtc_state);
|
||||
intel_psr_disable(intel_dp, old_crtc_state);
|
||||
intel_edp_backlight_off(old_conn_state);
|
||||
/* Disable the decompression in DP Sink */
|
||||
|
@ -2980,9 +2974,7 @@ static void intel_disable_ddi_hdmi(struct intel_atomic_state *state,
|
|||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
struct drm_connector *connector = old_conn_state->connector;
|
||||
|
||||
if (old_crtc_state->has_audio)
|
||||
intel_audio_codec_disable(encoder,
|
||||
old_crtc_state, old_conn_state);
|
||||
intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
|
||||
|
||||
if (!intel_hdmi_handle_sink_scrambling(encoder, connector,
|
||||
false, false))
|
||||
|
@ -3011,12 +3003,9 @@ static void intel_ddi_update_pipe_dp(struct intel_atomic_state *state,
|
|||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
|
||||
intel_ddi_set_dp_msa(crtc_state, conn_state);
|
||||
|
||||
intel_dp_set_infoframes(encoder, true, crtc_state, conn_state);
|
||||
intel_drrs_update(intel_dp, crtc_state);
|
||||
|
||||
intel_backlight_update(state, encoder, crtc_state, conn_state);
|
||||
drm_connector_update_privacy_screen(conn_state);
|
||||
|
@ -4308,6 +4297,13 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
|
|||
return;
|
||||
}
|
||||
|
||||
if (intel_phy_is_snps(dev_priv, phy) &&
|
||||
dev_priv->snps_phy_failed_calibration & BIT(phy)) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"SNPS PHY %c failed to calibrate, proceeding anyway\n",
|
||||
phy_name(phy));
|
||||
}
|
||||
|
||||
dig_port = kzalloc(sizeof(*dig_port), GFP_KERNEL);
|
||||
if (!dig_port)
|
||||
return;
|
||||
|
|
|
@ -907,7 +907,7 @@ static const union intel_ddi_buf_trans_entry _adlp_combo_phy_trans_dp_hbr[] = {
|
|||
{ .icl = { 0xA, 0x4C, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */
|
||||
{ .icl = { 0xC, 0x73, 0x34, 0x00, 0x0B } }, /* 500 700 2.9 */
|
||||
{ .icl = { 0x6, 0x7F, 0x2F, 0x00, 0x10 } }, /* 500 900 5.1 */
|
||||
{ .icl = { 0xC, 0x73, 0x3E, 0x00, 0x01 } }, /* 650 700 0.6 */
|
||||
{ .icl = { 0xC, 0x7C, 0x3C, 0x00, 0x03 } }, /* 650 700 0.6 */
|
||||
{ .icl = { 0x6, 0x7F, 0x35, 0x00, 0x0A } }, /* 600 900 3.5 */
|
||||
{ .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */
|
||||
};
|
||||
|
@ -921,7 +921,7 @@ static const union intel_ddi_buf_trans_entry _adlp_combo_phy_trans_dp_hbr2_hbr3[
|
|||
/* NT mV Trans mV db */
|
||||
{ .icl = { 0xA, 0x35, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */
|
||||
{ .icl = { 0xA, 0x4F, 0x37, 0x00, 0x08 } }, /* 350 500 3.1 */
|
||||
{ .icl = { 0xC, 0x71, 0x2F, 0x00, 0x10 } }, /* 350 700 6.0 */
|
||||
{ .icl = { 0xC, 0x71, 0x30, 0x00, 0x0F } }, /* 350 700 6.0 */
|
||||
{ .icl = { 0x6, 0x7F, 0x2B, 0x00, 0x14 } }, /* 350 900 8.2 */
|
||||
{ .icl = { 0xA, 0x4C, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */
|
||||
{ .icl = { 0xC, 0x73, 0x34, 0x00, 0x0B } }, /* 500 700 2.9 */
|
||||
|
@ -931,19 +931,47 @@ static const union intel_ddi_buf_trans_entry _adlp_combo_phy_trans_dp_hbr2_hbr3[
|
|||
{ .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */
|
||||
};
|
||||
|
||||
static const union intel_ddi_buf_trans_entry _adlp_combo_phy_trans_edp_hbr2[] = {
|
||||
/* NT mV Trans mV db */
|
||||
{ .icl = { 0x4, 0x50, 0x38, 0x00, 0x07 } }, /* 200 200 0.0 */
|
||||
{ .icl = { 0x4, 0x58, 0x35, 0x00, 0x0A } }, /* 200 250 1.9 */
|
||||
{ .icl = { 0x4, 0x60, 0x34, 0x00, 0x0B } }, /* 200 300 3.5 */
|
||||
{ .icl = { 0x4, 0x6A, 0x32, 0x00, 0x0D } }, /* 200 350 4.9 */
|
||||
{ .icl = { 0x4, 0x5E, 0x38, 0x00, 0x07 } }, /* 250 250 0.0 */
|
||||
{ .icl = { 0x4, 0x61, 0x36, 0x00, 0x09 } }, /* 250 300 1.6 */
|
||||
{ .icl = { 0x4, 0x6B, 0x34, 0x00, 0x0B } }, /* 250 350 2.9 */
|
||||
{ .icl = { 0x4, 0x69, 0x39, 0x00, 0x06 } }, /* 300 300 0.0 */
|
||||
{ .icl = { 0x4, 0x73, 0x37, 0x00, 0x08 } }, /* 300 350 1.3 */
|
||||
{ .icl = { 0x4, 0x7A, 0x38, 0x00, 0x07 } }, /* 350 350 0.0 */
|
||||
};
|
||||
|
||||
static const union intel_ddi_buf_trans_entry _adlp_combo_phy_trans_dp_hbr2_edp_hbr3[] = {
|
||||
/* NT mV Trans mV db */
|
||||
{ .icl = { 0xA, 0x35, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */
|
||||
{ .icl = { 0xA, 0x4F, 0x37, 0x00, 0x08 } }, /* 350 500 3.1 */
|
||||
{ .icl = { 0xC, 0x71, 0x30, 0x00, 0x0f } }, /* 350 700 6.0 */
|
||||
{ .icl = { 0x6, 0x7F, 0x2B, 0x00, 0x14 } }, /* 350 900 8.2 */
|
||||
{ .icl = { 0xA, 0x4C, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */
|
||||
{ .icl = { 0xC, 0x73, 0x34, 0x00, 0x0B } }, /* 500 700 2.9 */
|
||||
{ .icl = { 0x6, 0x7F, 0x2F, 0x00, 0x10 } }, /* 500 900 5.1 */
|
||||
{ .icl = { 0xC, 0x6C, 0x3C, 0x00, 0x03 } }, /* 650 700 0.6 */
|
||||
{ .icl = { 0x6, 0x7F, 0x35, 0x00, 0x0A } }, /* 600 900 3.5 */
|
||||
{ .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */
|
||||
};
|
||||
|
||||
static const struct intel_ddi_buf_trans adlp_combo_phy_trans_dp_hbr2_hbr3 = {
|
||||
.entries = _adlp_combo_phy_trans_dp_hbr2_hbr3,
|
||||
.num_entries = ARRAY_SIZE(_adlp_combo_phy_trans_dp_hbr2_hbr3),
|
||||
};
|
||||
|
||||
static const struct intel_ddi_buf_trans adlp_combo_phy_trans_edp_hbr3 = {
|
||||
.entries = _icl_combo_phy_trans_dp_hbr2_edp_hbr3,
|
||||
.num_entries = ARRAY_SIZE(_icl_combo_phy_trans_dp_hbr2_edp_hbr3),
|
||||
.entries = _adlp_combo_phy_trans_dp_hbr2_edp_hbr3,
|
||||
.num_entries = ARRAY_SIZE(_adlp_combo_phy_trans_dp_hbr2_edp_hbr3),
|
||||
};
|
||||
|
||||
static const struct intel_ddi_buf_trans adlp_combo_phy_trans_edp_up_to_hbr2 = {
|
||||
.entries = _icl_combo_phy_trans_edp_hbr2,
|
||||
.num_entries = ARRAY_SIZE(_icl_combo_phy_trans_edp_hbr2),
|
||||
.entries = _adlp_combo_phy_trans_edp_hbr2,
|
||||
.num_entries = ARRAY_SIZE(_adlp_combo_phy_trans_edp_hbr2),
|
||||
};
|
||||
|
||||
static const union intel_ddi_buf_trans_entry _adlp_dkl_phy_trans_dp_hbr[] = {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -565,7 +565,6 @@ void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state);
|
|||
void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state);
|
||||
void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe);
|
||||
void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe);
|
||||
enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc);
|
||||
int vlv_get_hpll_vco(struct drm_i915_private *dev_priv);
|
||||
int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
|
||||
const char *name, u32 reg, int ref_freq);
|
||||
|
@ -695,4 +694,6 @@ void assert_transcoder(struct drm_i915_private *dev_priv,
|
|||
#define I915_STATE_WARN_ON(x) \
|
||||
I915_STATE_WARN((x), "%s", "WARN_ON(" __stringify(x) ")")
|
||||
|
||||
bool intel_scanout_needs_vtd_wa(struct drm_i915_private *i915);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
* Copyright © 2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include <drm/drm_debugfs.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
|
||||
|
@ -10,6 +12,7 @@
|
|||
#include "intel_de.h"
|
||||
#include "intel_display_debugfs.h"
|
||||
#include "intel_display_power.h"
|
||||
#include "intel_display_power_well.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dmc.h"
|
||||
#include "intel_dp.h"
|
||||
|
@ -19,6 +22,7 @@
|
|||
#include "intel_fbdev.h"
|
||||
#include "intel_hdcp.h"
|
||||
#include "intel_hdmi.h"
|
||||
#include "intel_panel.h"
|
||||
#include "intel_pm.h"
|
||||
#include "intel_psr.h"
|
||||
#include "intel_sprite.h"
|
||||
|
@ -52,7 +56,7 @@ static int i915_ips_status(struct seq_file *m, void *unused)
|
|||
wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
|
||||
|
||||
seq_printf(m, "Enabled by kernel parameter: %s\n",
|
||||
yesno(dev_priv->params.enable_ips));
|
||||
str_yes_no(dev_priv->params.enable_ips));
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 8) {
|
||||
seq_puts(m, "Currently: unknown\n");
|
||||
|
@ -92,7 +96,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)
|
|||
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref);
|
||||
|
||||
seq_printf(m, "self-refresh: %s\n", enableddisabled(sr_enabled));
|
||||
seq_printf(m, "self-refresh: %s\n", str_enabled_disabled(sr_enabled));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -260,7 +264,7 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
|
|||
bool enabled;
|
||||
u32 val;
|
||||
|
||||
seq_printf(m, "Sink support: %s", yesno(psr->sink_support));
|
||||
seq_printf(m, "Sink support: %s", str_yes_no(psr->sink_support));
|
||||
if (psr->sink_support)
|
||||
seq_printf(m, " [0x%02x]", intel_dp->psr_dpcd[0]);
|
||||
seq_puts(m, "\n");
|
||||
|
@ -279,7 +283,7 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
|
|||
|
||||
if (!psr->enabled) {
|
||||
seq_printf(m, "PSR sink not reliable: %s\n",
|
||||
yesno(psr->sink_not_reliable));
|
||||
str_yes_no(psr->sink_not_reliable));
|
||||
|
||||
goto unlock;
|
||||
}
|
||||
|
@ -294,7 +298,7 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
|
|||
enabled = val & EDP_PSR_ENABLE;
|
||||
}
|
||||
seq_printf(m, "Source PSR ctl: %s [0x%08x]\n",
|
||||
enableddisabled(enabled), val);
|
||||
str_enabled_disabled(enabled), val);
|
||||
psr_source_status(intel_dp, m);
|
||||
seq_printf(m, "Busy frontbuffer bits: 0x%08x\n",
|
||||
psr->busy_frontbuffer_bits);
|
||||
|
@ -341,7 +345,7 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
|
|||
}
|
||||
|
||||
seq_printf(m, "PSR2 selective fetch: %s\n",
|
||||
enableddisabled(psr->psr2_sel_fetch_enabled));
|
||||
str_enabled_disabled(psr->psr2_sel_fetch_enabled));
|
||||
}
|
||||
|
||||
unlock:
|
||||
|
@ -432,75 +436,6 @@ static int i915_power_domain_info(struct seq_file *m, void *unused)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int i915_dmc_info(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = node_to_i915(m->private);
|
||||
intel_wakeref_t wakeref;
|
||||
struct intel_dmc *dmc;
|
||||
i915_reg_t dc5_reg, dc6_reg = {};
|
||||
|
||||
if (!HAS_DMC(dev_priv))
|
||||
return -ENODEV;
|
||||
|
||||
dmc = &dev_priv->dmc;
|
||||
|
||||
wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
|
||||
|
||||
seq_printf(m, "fw loaded: %s\n", yesno(intel_dmc_has_payload(dev_priv)));
|
||||
seq_printf(m, "path: %s\n", dmc->fw_path);
|
||||
seq_printf(m, "Pipe A fw support: %s\n",
|
||||
yesno(GRAPHICS_VER(dev_priv) >= 12));
|
||||
seq_printf(m, "Pipe A fw loaded: %s\n", yesno(dmc->dmc_info[DMC_FW_PIPEA].payload));
|
||||
seq_printf(m, "Pipe B fw support: %s\n", yesno(IS_ALDERLAKE_P(dev_priv)));
|
||||
seq_printf(m, "Pipe B fw loaded: %s\n", yesno(dmc->dmc_info[DMC_FW_PIPEB].payload));
|
||||
|
||||
if (!intel_dmc_has_payload(dev_priv))
|
||||
goto out;
|
||||
|
||||
seq_printf(m, "version: %d.%d\n", DMC_VERSION_MAJOR(dmc->version),
|
||||
DMC_VERSION_MINOR(dmc->version));
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 12) {
|
||||
if (IS_DGFX(dev_priv)) {
|
||||
dc5_reg = DG1_DMC_DEBUG_DC5_COUNT;
|
||||
} else {
|
||||
dc5_reg = TGL_DMC_DEBUG_DC5_COUNT;
|
||||
dc6_reg = TGL_DMC_DEBUG_DC6_COUNT;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: DMC_DEBUG3 is a general purpose reg.
|
||||
* According to B.Specs:49196 DMC f/w reuses DC5/6 counter
|
||||
* reg for DC3CO debugging and validation,
|
||||
* but TGL DMC f/w is using DMC_DEBUG3 reg for DC3CO counter.
|
||||
*/
|
||||
seq_printf(m, "DC3CO count: %d\n", intel_de_read(dev_priv, IS_DGFX(dev_priv) ?
|
||||
DG1_DMC_DEBUG3 : TGL_DMC_DEBUG3));
|
||||
} else {
|
||||
dc5_reg = IS_BROXTON(dev_priv) ? BXT_DMC_DC3_DC5_COUNT :
|
||||
SKL_DMC_DC3_DC5_COUNT;
|
||||
if (!IS_GEMINILAKE(dev_priv) && !IS_BROXTON(dev_priv))
|
||||
dc6_reg = SKL_DMC_DC5_DC6_COUNT;
|
||||
}
|
||||
|
||||
seq_printf(m, "DC3 -> DC5 count: %d\n",
|
||||
intel_de_read(dev_priv, dc5_reg));
|
||||
if (dc6_reg.reg)
|
||||
seq_printf(m, "DC5 -> DC6 count: %d\n",
|
||||
intel_de_read(dev_priv, dc6_reg));
|
||||
|
||||
out:
|
||||
seq_printf(m, "program base: 0x%08x\n",
|
||||
intel_de_read(dev_priv, DMC_PROGRAM(dmc->dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)));
|
||||
seq_printf(m, "ssp base: 0x%08x\n",
|
||||
intel_de_read(dev_priv, DMC_SSP_BASE));
|
||||
seq_printf(m, "htp: 0x%08x\n", intel_de_read(dev_priv, DMC_HTP_SKL));
|
||||
|
||||
intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void intel_seq_print_mode(struct seq_file *m, int tabs,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
|
@ -537,11 +472,18 @@ static void intel_encoder_info(struct seq_file *m,
|
|||
drm_connector_list_iter_end(&conn_iter);
|
||||
}
|
||||
|
||||
static void intel_panel_info(struct seq_file *m, struct intel_panel *panel)
|
||||
static void intel_panel_info(struct seq_file *m,
|
||||
struct intel_connector *connector)
|
||||
{
|
||||
const struct drm_display_mode *mode = panel->fixed_mode;
|
||||
const struct drm_display_mode *fixed_mode;
|
||||
|
||||
seq_printf(m, "\tfixed mode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
|
||||
if (list_empty(&connector->panel.fixed_modes))
|
||||
return;
|
||||
|
||||
seq_puts(m, "\tfixed modes:\n");
|
||||
|
||||
list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head)
|
||||
intel_seq_print_mode(m, 2, fixed_mode);
|
||||
}
|
||||
|
||||
static void intel_hdcp_info(struct seq_file *m,
|
||||
|
@ -577,9 +519,8 @@ static void intel_dp_info(struct seq_file *m,
|
|||
const struct drm_property_blob *edid = intel_connector->base.edid_blob_ptr;
|
||||
|
||||
seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]);
|
||||
seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio));
|
||||
if (intel_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)
|
||||
intel_panel_info(m, &intel_connector->panel);
|
||||
seq_printf(m, "\taudio support: %s\n",
|
||||
str_yes_no(intel_dp->has_audio));
|
||||
|
||||
drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports,
|
||||
edid ? edid->data : NULL, &intel_dp->aux);
|
||||
|
@ -590,7 +531,7 @@ static void intel_dp_mst_info(struct seq_file *m,
|
|||
{
|
||||
bool has_audio = intel_connector->port->has_audio;
|
||||
|
||||
seq_printf(m, "\taudio support: %s\n", yesno(has_audio));
|
||||
seq_printf(m, "\taudio support: %s\n", str_yes_no(has_audio));
|
||||
}
|
||||
|
||||
static void intel_hdmi_info(struct seq_file *m,
|
||||
|
@ -599,13 +540,8 @@ static void intel_hdmi_info(struct seq_file *m,
|
|||
struct intel_encoder *intel_encoder = intel_attached_encoder(intel_connector);
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(intel_encoder);
|
||||
|
||||
seq_printf(m, "\taudio support: %s\n", yesno(intel_hdmi->has_audio));
|
||||
}
|
||||
|
||||
static void intel_lvds_info(struct seq_file *m,
|
||||
struct intel_connector *intel_connector)
|
||||
{
|
||||
intel_panel_info(m, &intel_connector->panel);
|
||||
seq_printf(m, "\taudio support: %s\n",
|
||||
str_yes_no(intel_hdmi->has_audio));
|
||||
}
|
||||
|
||||
static void intel_connector_info(struct seq_file *m,
|
||||
|
@ -642,10 +578,6 @@ static void intel_connector_info(struct seq_file *m,
|
|||
else
|
||||
intel_dp_info(m, intel_connector);
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_LVDS:
|
||||
if (encoder->type == INTEL_OUTPUT_LVDS)
|
||||
intel_lvds_info(m, intel_connector);
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_HDMIA:
|
||||
if (encoder->type == INTEL_OUTPUT_HDMI ||
|
||||
encoder->type == INTEL_OUTPUT_DDI)
|
||||
|
@ -658,6 +590,8 @@ static void intel_connector_info(struct seq_file *m,
|
|||
seq_puts(m, "\tHDCP version: ");
|
||||
intel_hdcp_info(m, intel_connector);
|
||||
|
||||
intel_panel_info(m, intel_connector);
|
||||
|
||||
seq_printf(m, "\tmodes:\n");
|
||||
list_for_each_entry(mode, &connector->modes, head)
|
||||
intel_seq_print_mode(m, 2, mode);
|
||||
|
@ -757,7 +691,7 @@ static void intel_plane_hw_info(struct seq_file *m, struct intel_plane *plane)
|
|||
DRM_RECT_FP_FMT ", dst=" DRM_RECT_FMT ", rotation=%s\n",
|
||||
fb->base.id, &fb->format->format,
|
||||
fb->modifier, fb->width, fb->height,
|
||||
yesno(plane_state->uapi.visible),
|
||||
str_yes_no(plane_state->uapi.visible),
|
||||
DRM_RECT_FP_ARG(&plane_state->uapi.src),
|
||||
DRM_RECT_ARG(&plane_state->uapi.dst),
|
||||
rot_str);
|
||||
|
@ -796,7 +730,7 @@ static void intel_scaler_info(struct seq_file *m, struct intel_crtc *crtc)
|
|||
&crtc_state->scaler_state.scalers[i];
|
||||
|
||||
seq_printf(m, ", scalers[%d]: use=%s, mode=%x",
|
||||
i, yesno(sc->in_use), sc->mode);
|
||||
i, str_yes_no(sc->in_use), sc->mode);
|
||||
}
|
||||
seq_puts(m, "\n");
|
||||
} else {
|
||||
|
@ -919,24 +853,24 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc)
|
|||
crtc->base.base.id, crtc->base.name);
|
||||
|
||||
seq_printf(m, "\tuapi: enable=%s, active=%s, mode=" DRM_MODE_FMT "\n",
|
||||
yesno(crtc_state->uapi.enable),
|
||||
yesno(crtc_state->uapi.active),
|
||||
str_yes_no(crtc_state->uapi.enable),
|
||||
str_yes_no(crtc_state->uapi.active),
|
||||
DRM_MODE_ARG(&crtc_state->uapi.mode));
|
||||
|
||||
seq_printf(m, "\thw: enable=%s, active=%s\n",
|
||||
yesno(crtc_state->hw.enable), yesno(crtc_state->hw.active));
|
||||
str_yes_no(crtc_state->hw.enable), str_yes_no(crtc_state->hw.active));
|
||||
seq_printf(m, "\tadjusted_mode=" DRM_MODE_FMT "\n",
|
||||
DRM_MODE_ARG(&crtc_state->hw.adjusted_mode));
|
||||
seq_printf(m, "\tpipe__mode=" DRM_MODE_FMT "\n",
|
||||
DRM_MODE_ARG(&crtc_state->hw.pipe_mode));
|
||||
|
||||
seq_printf(m, "\tpipe src size=%dx%d, dither=%s, bpp=%d\n",
|
||||
crtc_state->pipe_src_w, crtc_state->pipe_src_h,
|
||||
yesno(crtc_state->dither), crtc_state->pipe_bpp);
|
||||
seq_printf(m, "\tpipe src=" DRM_RECT_FMT ", dither=%s, bpp=%d\n",
|
||||
DRM_RECT_ARG(&crtc_state->pipe_src),
|
||||
str_yes_no(crtc_state->dither), crtc_state->pipe_bpp);
|
||||
|
||||
intel_scaler_info(m, crtc);
|
||||
|
||||
if (crtc_state->bigjoiner)
|
||||
if (crtc_state->bigjoiner_pipes)
|
||||
seq_printf(m, "\tLinked to 0x%x pipes as a %s\n",
|
||||
crtc_state->bigjoiner_pipes,
|
||||
intel_crtc_is_bigjoiner_slave(crtc_state) ? "slave" : "master");
|
||||
|
@ -948,8 +882,8 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc)
|
|||
intel_plane_info(m, crtc);
|
||||
|
||||
seq_printf(m, "\tunderrun reporting: cpu=%s pch=%s\n",
|
||||
yesno(!crtc->cpu_fifo_underrun_disabled),
|
||||
yesno(!crtc->pch_fifo_underrun_disabled));
|
||||
str_yes_no(!crtc->cpu_fifo_underrun_disabled),
|
||||
str_yes_no(!crtc->pch_fifo_underrun_disabled));
|
||||
|
||||
crtc_updates_info(m, crtc, "\t");
|
||||
}
|
||||
|
@ -1005,7 +939,8 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
|
|||
seq_printf(m, "DPLL%i: %s, id: %i\n", i, pll->info->name,
|
||||
pll->info->id);
|
||||
seq_printf(m, " pipe_mask: 0x%x, active: 0x%x, on: %s\n",
|
||||
pll->state.pipe_mask, pll->active_mask, yesno(pll->on));
|
||||
pll->state.pipe_mask, pll->active_mask,
|
||||
str_yes_no(pll->on));
|
||||
seq_printf(m, " tracked hardware state:\n");
|
||||
seq_printf(m, " dpll: 0x%08x\n", pll->state.hw_state.dpll);
|
||||
seq_printf(m, " dpll_md: 0x%08x\n",
|
||||
|
@ -1047,7 +982,7 @@ static int i915_ipc_status_show(struct seq_file *m, void *data)
|
|||
struct drm_i915_private *dev_priv = m->private;
|
||||
|
||||
seq_printf(m, "Isochronous Priority Control: %s\n",
|
||||
yesno(dev_priv->ipc_enabled));
|
||||
str_yes_no(dev_priv->ipc_enabled));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1117,13 +1052,13 @@ static int i915_ddb_info(struct seq_file *m, void *unused)
|
|||
seq_printf(m, "Pipe %c\n", pipe_name(pipe));
|
||||
|
||||
for_each_plane_id_on_crtc(crtc, plane_id) {
|
||||
entry = &crtc_state->wm.skl.plane_ddb_y[plane_id];
|
||||
entry = &crtc_state->wm.skl.plane_ddb[plane_id];
|
||||
seq_printf(m, " Plane%-8d%8u%8u%8u\n", plane_id + 1,
|
||||
entry->start, entry->end,
|
||||
skl_ddb_entry_size(entry));
|
||||
}
|
||||
|
||||
entry = &crtc_state->wm.skl.plane_ddb_y[PLANE_CURSOR];
|
||||
entry = &crtc_state->wm.skl.plane_ddb[PLANE_CURSOR];
|
||||
seq_printf(m, " %-13s%8u%8u%8u\n", "Cursor", entry->start,
|
||||
entry->end, skl_ddb_entry_size(entry));
|
||||
}
|
||||
|
@ -1133,97 +1068,48 @@ static int i915_ddb_info(struct seq_file *m, void *unused)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void drrs_status_per_crtc(struct seq_file *m,
|
||||
struct drm_device *dev,
|
||||
struct intel_crtc *crtc)
|
||||
static int i915_drrs_status(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct i915_drrs *drrs = &dev_priv->drrs;
|
||||
int vrefresh = 0;
|
||||
struct drm_connector *connector;
|
||||
struct drm_i915_private *dev_priv = node_to_i915(m->private);
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
struct intel_connector *connector;
|
||||
struct intel_crtc *crtc;
|
||||
|
||||
drm_connector_list_iter_begin(dev, &conn_iter);
|
||||
drm_for_each_connector_iter(connector, &conn_iter) {
|
||||
bool supported = false;
|
||||
|
||||
if (connector->state->crtc != &crtc->base)
|
||||
continue;
|
||||
|
||||
seq_printf(m, "%s:\n", connector->name);
|
||||
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP &&
|
||||
drrs->type == SEAMLESS_DRRS_SUPPORT)
|
||||
supported = true;
|
||||
|
||||
seq_printf(m, "\tDRRS Supported: %s\n", yesno(supported));
|
||||
drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
|
||||
for_each_intel_connector_iter(connector, &conn_iter) {
|
||||
seq_printf(m, "[CONNECTOR:%d:%s] DRRS type: %s\n",
|
||||
connector->base.base.id, connector->base.name,
|
||||
intel_drrs_type_str(intel_panel_drrs_type(connector)));
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
|
||||
seq_puts(m, "\n");
|
||||
|
||||
if (to_intel_crtc_state(crtc->base.state)->has_drrs) {
|
||||
struct intel_panel *panel;
|
||||
for_each_intel_crtc(&dev_priv->drm, crtc) {
|
||||
const struct intel_crtc_state *crtc_state =
|
||||
to_intel_crtc_state(crtc->base.state);
|
||||
|
||||
seq_printf(m, "[CRTC:%d:%s]:\n",
|
||||
crtc->base.base.id, crtc->base.name);
|
||||
|
||||
mutex_lock(&crtc->drrs.mutex);
|
||||
|
||||
mutex_lock(&drrs->mutex);
|
||||
/* DRRS Supported */
|
||||
seq_puts(m, "\tDRRS Enabled: Yes\n");
|
||||
seq_printf(m, "\tDRRS Enabled: %s\n",
|
||||
str_yes_no(crtc_state->has_drrs));
|
||||
|
||||
/* disable_drrs() will make drrs->dp NULL */
|
||||
if (!drrs->dp) {
|
||||
seq_puts(m, "Idleness DRRS: Disabled\n");
|
||||
mutex_unlock(&drrs->mutex);
|
||||
return;
|
||||
}
|
||||
seq_printf(m, "\tDRRS Active: %s\n",
|
||||
str_yes_no(intel_drrs_is_active(crtc)));
|
||||
|
||||
panel = &drrs->dp->attached_connector->panel;
|
||||
seq_printf(m, "\t\tBusy_frontbuffer_bits: 0x%X",
|
||||
drrs->busy_frontbuffer_bits);
|
||||
seq_printf(m, "\tBusy_frontbuffer_bits: 0x%X\n",
|
||||
crtc->drrs.busy_frontbuffer_bits);
|
||||
|
||||
seq_puts(m, "\n\t\t");
|
||||
if (drrs->refresh_rate_type == DRRS_HIGH_RR) {
|
||||
seq_puts(m, "DRRS_State: DRRS_HIGH_RR\n");
|
||||
vrefresh = drm_mode_vrefresh(panel->fixed_mode);
|
||||
} else if (drrs->refresh_rate_type == DRRS_LOW_RR) {
|
||||
seq_puts(m, "DRRS_State: DRRS_LOW_RR\n");
|
||||
vrefresh = drm_mode_vrefresh(panel->downclock_mode);
|
||||
} else {
|
||||
seq_printf(m, "DRRS_State: Unknown(%d)\n",
|
||||
drrs->refresh_rate_type);
|
||||
mutex_unlock(&drrs->mutex);
|
||||
return;
|
||||
}
|
||||
seq_printf(m, "\t\tVrefresh: %d", vrefresh);
|
||||
seq_printf(m, "\tDRRS refresh rate: %s\n",
|
||||
crtc->drrs.refresh_rate == DRRS_REFRESH_RATE_LOW ?
|
||||
"low" : "high");
|
||||
|
||||
seq_puts(m, "\n\t\t");
|
||||
mutex_unlock(&drrs->mutex);
|
||||
} else {
|
||||
/* DRRS not supported. Print the VBT parameter*/
|
||||
seq_puts(m, "\tDRRS Enabled : No");
|
||||
mutex_unlock(&crtc->drrs.mutex);
|
||||
}
|
||||
seq_puts(m, "\n");
|
||||
}
|
||||
|
||||
static int i915_drrs_status(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = node_to_i915(m->private);
|
||||
struct drm_device *dev = &dev_priv->drm;
|
||||
struct intel_crtc *crtc;
|
||||
int active_crtc_cnt = 0;
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
for_each_intel_crtc(dev, crtc) {
|
||||
if (crtc->base.state->active) {
|
||||
active_crtc_cnt++;
|
||||
seq_printf(m, "\nCRTC %d: ", active_crtc_cnt);
|
||||
|
||||
drrs_status_per_crtc(m, dev, crtc);
|
||||
}
|
||||
}
|
||||
drm_modeset_unlock_all(dev);
|
||||
|
||||
if (!active_crtc_cnt)
|
||||
seq_puts(m, "No active crtc found\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1259,7 +1145,7 @@ static int i915_lpsp_status(struct seq_file *m, void *unused)
|
|||
return 0;
|
||||
}
|
||||
|
||||
seq_printf(m, "LPSP: %s\n", enableddisabled(lpsp_enabled));
|
||||
seq_printf(m, "LPSP: %s\n", str_enabled_disabled(lpsp_enabled));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1740,7 +1626,7 @@ static int i915_hpd_storm_ctl_show(struct seq_file *m, void *data)
|
|||
|
||||
seq_printf(m, "Threshold: %d\n", hotplug->hpd_storm_threshold);
|
||||
seq_printf(m, "Detected: %s\n",
|
||||
yesno(delayed_work_pending(&hotplug->reenable_work)));
|
||||
str_yes_no(delayed_work_pending(&hotplug->reenable_work)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1814,7 +1700,7 @@ static int i915_hpd_short_storm_ctl_show(struct seq_file *m, void *data)
|
|||
struct drm_i915_private *dev_priv = m->private;
|
||||
|
||||
seq_printf(m, "Enabled: %s\n",
|
||||
yesno(dev_priv->hotplug.hpd_short_storm_enabled));
|
||||
str_yes_no(dev_priv->hotplug.hpd_short_storm_enabled));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1888,13 +1774,8 @@ static int i915_drrs_ctl_set(void *data, u64 val)
|
|||
struct drm_device *dev = &dev_priv->drm;
|
||||
struct intel_crtc *crtc;
|
||||
|
||||
if (DISPLAY_VER(dev_priv) < 7)
|
||||
return -ENODEV;
|
||||
|
||||
for_each_intel_crtc(dev, crtc) {
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
struct intel_crtc_state *crtc_state;
|
||||
struct drm_connector *connector;
|
||||
struct drm_crtc_commit *commit;
|
||||
int ret;
|
||||
|
||||
|
@ -1915,30 +1796,13 @@ static int i915_drrs_ctl_set(void *data, u64 val)
|
|||
goto out;
|
||||
}
|
||||
|
||||
drm_connector_list_iter_begin(dev, &conn_iter);
|
||||
drm_for_each_connector_iter(connector, &conn_iter) {
|
||||
struct intel_encoder *encoder;
|
||||
struct intel_dp *intel_dp;
|
||||
drm_dbg(&dev_priv->drm,
|
||||
"Manually %sactivating DRRS\n", val ? "" : "de");
|
||||
|
||||
if (!(crtc_state->uapi.connector_mask &
|
||||
drm_connector_mask(connector)))
|
||||
continue;
|
||||
|
||||
encoder = intel_attached_encoder(to_intel_connector(connector));
|
||||
if (encoder->type != INTEL_OUTPUT_EDP)
|
||||
continue;
|
||||
|
||||
drm_dbg(&dev_priv->drm,
|
||||
"Manually %sabling DRRS. %llu\n",
|
||||
val ? "en" : "dis", val);
|
||||
|
||||
intel_dp = enc_to_intel_dp(encoder);
|
||||
if (val)
|
||||
intel_drrs_enable(intel_dp, crtc_state);
|
||||
else
|
||||
intel_drrs_disable(intel_dp, crtc_state);
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
if (val)
|
||||
intel_drrs_activate(crtc_state);
|
||||
else
|
||||
intel_drrs_deactivate(crtc_state);
|
||||
|
||||
out:
|
||||
drm_modeset_unlock(&crtc->base.mutex);
|
||||
|
@ -2020,7 +1884,6 @@ static const struct drm_info_list intel_display_debugfs_list[] = {
|
|||
{"i915_gem_framebuffer", i915_gem_framebuffer_info, 0},
|
||||
{"i915_edp_psr_status", i915_edp_psr_status, 0},
|
||||
{"i915_power_domain_info", i915_power_domain_info, 0},
|
||||
{"i915_dmc_info", i915_dmc_info, 0},
|
||||
{"i915_display_info", i915_display_info, 0},
|
||||
{"i915_shared_dplls_info", i915_shared_dplls_info, 0},
|
||||
{"i915_dp_mst_info", i915_dp_mst_info, 0},
|
||||
|
@ -2064,6 +1927,7 @@ void intel_display_debugfs_register(struct drm_i915_private *i915)
|
|||
ARRAY_SIZE(intel_display_debugfs_list),
|
||||
minor->debugfs_root, minor);
|
||||
|
||||
intel_dmc_debugfs_register(i915);
|
||||
intel_fbc_debugfs_register(i915);
|
||||
}
|
||||
|
||||
|
@ -2209,14 +2073,14 @@ static int i915_dsc_fec_support_show(struct seq_file *m, void *data)
|
|||
intel_dp = intel_attached_dp(to_intel_connector(connector));
|
||||
crtc_state = to_intel_crtc_state(crtc->state);
|
||||
seq_printf(m, "DSC_Enabled: %s\n",
|
||||
yesno(crtc_state->dsc.compression_enable));
|
||||
str_yes_no(crtc_state->dsc.compression_enable));
|
||||
seq_printf(m, "DSC_Sink_Support: %s\n",
|
||||
yesno(drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)));
|
||||
str_yes_no(drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)));
|
||||
seq_printf(m, "Force_DSC_Enable: %s\n",
|
||||
yesno(intel_dp->force_dsc_en));
|
||||
str_yes_no(intel_dp->force_dsc_en));
|
||||
if (!intel_dp_is_edp(intel_dp))
|
||||
seq_printf(m, "FEC_Sink_Support: %s\n",
|
||||
yesno(drm_dp_sink_supports_fec(intel_dp->fec_capable)));
|
||||
str_yes_no(drm_dp_sink_supports_fec(intel_dp->fec_capable)));
|
||||
} while (try_again);
|
||||
|
||||
drm_modeset_drop_locks(&ctx);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -14,6 +14,11 @@ struct drm_i915_private;
|
|||
struct i915_power_well;
|
||||
struct intel_encoder;
|
||||
|
||||
/*
|
||||
* Keep the pipe, transcoder, port (DDI_LANES,DDI_IO,AUX) domain instances
|
||||
* consecutive, so that the pipe,transcoder,port -> power domain macros
|
||||
* work correctly.
|
||||
*/
|
||||
enum intel_display_power_domain {
|
||||
POWER_DOMAIN_DISPLAY_CORE,
|
||||
POWER_DOMAIN_PIPE_A,
|
||||
|
@ -29,10 +34,12 @@ enum intel_display_power_domain {
|
|||
POWER_DOMAIN_TRANSCODER_C,
|
||||
POWER_DOMAIN_TRANSCODER_D,
|
||||
POWER_DOMAIN_TRANSCODER_EDP,
|
||||
/* VDSC/joining for eDP/DSI transcoder (ICL) or pipe A (TGL) */
|
||||
POWER_DOMAIN_TRANSCODER_VDSC_PW2,
|
||||
POWER_DOMAIN_TRANSCODER_DSI_A,
|
||||
POWER_DOMAIN_TRANSCODER_DSI_C,
|
||||
|
||||
/* VDSC/joining for eDP/DSI transcoder (ICL) or pipe A (TGL) */
|
||||
POWER_DOMAIN_TRANSCODER_VDSC_PW2,
|
||||
|
||||
POWER_DOMAIN_PORT_DDI_A_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_B_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_C_LANES,
|
||||
|
@ -125,30 +132,6 @@ enum intel_display_power_domain {
|
|||
POWER_DOMAIN_NUM,
|
||||
};
|
||||
|
||||
/*
|
||||
* i915_power_well_id:
|
||||
*
|
||||
* IDs used to look up power wells. Power wells accessed directly bypassing
|
||||
* the power domains framework must be assigned a unique ID. The rest of power
|
||||
* wells must be assigned DISP_PW_ID_NONE.
|
||||
*/
|
||||
enum i915_power_well_id {
|
||||
DISP_PW_ID_NONE,
|
||||
|
||||
VLV_DISP_PW_DISP2D,
|
||||
BXT_DISP_PW_DPIO_CMN_A,
|
||||
VLV_DISP_PW_DPIO_CMN_BC,
|
||||
GLK_DISP_PW_DPIO_CMN_C,
|
||||
CHV_DISP_PW_DPIO_CMN_D,
|
||||
HSW_DISP_PW_GLOBAL,
|
||||
SKL_DISP_PW_MISC_IO,
|
||||
SKL_DISP_PW_1,
|
||||
SKL_DISP_PW_2,
|
||||
ICL_DISP_PW_3,
|
||||
SKL_DISP_DC_OFF,
|
||||
TGL_DISP_PW_TC_COLD_OFF,
|
||||
};
|
||||
|
||||
#define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A)
|
||||
#define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \
|
||||
((pipe) + POWER_DOMAIN_PIPE_A_PANEL_FITTER)
|
||||
|
@ -232,8 +215,6 @@ intel_display_power_domain_str(enum intel_display_power_domain domain);
|
|||
|
||||
bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
|
||||
enum intel_display_power_domain domain);
|
||||
bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
|
||||
enum i915_power_well_id power_well_id);
|
||||
bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
|
||||
enum intel_display_power_domain domain);
|
||||
intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv,
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright © 2022 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_display_power_well.h"
|
||||
|
||||
struct i915_power_well *
|
||||
lookup_power_well(struct drm_i915_private *i915,
|
||||
enum i915_power_well_id power_well_id)
|
||||
{
|
||||
struct i915_power_well *power_well;
|
||||
|
||||
for_each_power_well(i915, power_well)
|
||||
if (power_well->desc->id == power_well_id)
|
||||
return power_well;
|
||||
|
||||
/*
|
||||
* It's not feasible to add error checking code to the callers since
|
||||
* this condition really shouldn't happen and it doesn't even make sense
|
||||
* to abort things like display initialization sequences. Just return
|
||||
* the first power well and hope the WARN gets reported so we can fix
|
||||
* our driver.
|
||||
*/
|
||||
drm_WARN(&i915->drm, 1,
|
||||
"Power well %d not defined for this platform\n",
|
||||
power_well_id);
|
||||
return &i915->power_domains.power_wells[0];
|
||||
}
|
||||
|
||||
void intel_power_well_enable(struct drm_i915_private *i915,
|
||||
struct i915_power_well *power_well)
|
||||
{
|
||||
drm_dbg_kms(&i915->drm, "enabling %s\n", power_well->desc->name);
|
||||
power_well->desc->ops->enable(i915, power_well);
|
||||
power_well->hw_enabled = true;
|
||||
}
|
||||
|
||||
void intel_power_well_disable(struct drm_i915_private *i915,
|
||||
struct i915_power_well *power_well)
|
||||
{
|
||||
drm_dbg_kms(&i915->drm, "disabling %s\n", power_well->desc->name);
|
||||
power_well->hw_enabled = false;
|
||||
power_well->desc->ops->disable(i915, power_well);
|
||||
}
|
||||
|
||||
void intel_power_well_sync_hw(struct drm_i915_private *i915,
|
||||
struct i915_power_well *power_well)
|
||||
{
|
||||
power_well->desc->ops->sync_hw(i915, power_well);
|
||||
power_well->hw_enabled =
|
||||
power_well->desc->ops->is_enabled(i915, power_well);
|
||||
}
|
||||
|
||||
void intel_power_well_get(struct drm_i915_private *i915,
|
||||
struct i915_power_well *power_well)
|
||||
{
|
||||
if (!power_well->count++)
|
||||
intel_power_well_enable(i915, power_well);
|
||||
}
|
||||
|
||||
void intel_power_well_put(struct drm_i915_private *i915,
|
||||
struct i915_power_well *power_well)
|
||||
{
|
||||
drm_WARN(&i915->drm, !power_well->count,
|
||||
"Use count on power well %s is already zero",
|
||||
power_well->desc->name);
|
||||
|
||||
if (!--power_well->count)
|
||||
intel_power_well_disable(i915, power_well);
|
||||
}
|
||||
|
||||
bool intel_power_well_is_enabled(struct drm_i915_private *i915,
|
||||
struct i915_power_well *power_well)
|
||||
{
|
||||
return power_well->desc->ops->is_enabled(i915, power_well);
|
||||
}
|
||||
|
||||
bool intel_power_well_is_enabled_cached(struct i915_power_well *power_well)
|
||||
{
|
||||
return power_well->hw_enabled;
|
||||
}
|
||||
|
||||
bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
|
||||
enum i915_power_well_id power_well_id)
|
||||
{
|
||||
struct i915_power_well *power_well;
|
||||
|
||||
power_well = lookup_power_well(dev_priv, power_well_id);
|
||||
|
||||
return intel_power_well_is_enabled(dev_priv, power_well);
|
||||
}
|
||||
|
||||
bool intel_power_well_is_always_on(struct i915_power_well *power_well)
|
||||
{
|
||||
return power_well->desc->always_on;
|
||||
}
|
||||
|
||||
const char *intel_power_well_name(struct i915_power_well *power_well)
|
||||
{
|
||||
return power_well->desc->name;
|
||||
}
|
||||
|
||||
u64 intel_power_well_domains(struct i915_power_well *power_well)
|
||||
{
|
||||
return power_well->desc->domains;
|
||||
}
|
||||
|
||||
int intel_power_well_refcount(struct i915_power_well *power_well)
|
||||
{
|
||||
return power_well->count;
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2022 Intel Corporation
|
||||
*/
|
||||
#ifndef __INTEL_DISPLAY_POWER_WELL_H__
|
||||
#define __INTEL_DISPLAY_POWER_WELL_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "intel_display.h"
|
||||
|
||||
struct drm_i915_private;
|
||||
struct i915_power_well;
|
||||
|
||||
/*
|
||||
* i915_power_well_id:
|
||||
*
|
||||
* IDs used to look up power wells. Power wells accessed directly bypassing
|
||||
* the power domains framework must be assigned a unique ID. The rest of power
|
||||
* wells must be assigned DISP_PW_ID_NONE.
|
||||
*/
|
||||
enum i915_power_well_id {
|
||||
DISP_PW_ID_NONE,
|
||||
|
||||
VLV_DISP_PW_DISP2D,
|
||||
BXT_DISP_PW_DPIO_CMN_A,
|
||||
VLV_DISP_PW_DPIO_CMN_BC,
|
||||
GLK_DISP_PW_DPIO_CMN_C,
|
||||
CHV_DISP_PW_DPIO_CMN_D,
|
||||
HSW_DISP_PW_GLOBAL,
|
||||
SKL_DISP_PW_MISC_IO,
|
||||
SKL_DISP_PW_1,
|
||||
SKL_DISP_PW_2,
|
||||
ICL_DISP_PW_3,
|
||||
SKL_DISP_DC_OFF,
|
||||
TGL_DISP_PW_TC_COLD_OFF,
|
||||
};
|
||||
|
||||
struct i915_power_well_regs {
|
||||
i915_reg_t bios;
|
||||
i915_reg_t driver;
|
||||
i915_reg_t kvmr;
|
||||
i915_reg_t debug;
|
||||
};
|
||||
|
||||
struct i915_power_well_ops {
|
||||
const struct i915_power_well_regs *regs;
|
||||
/*
|
||||
* Synchronize the well's hw state to match the current sw state, for
|
||||
* example enable/disable it based on the current refcount. Called
|
||||
* during driver init and resume time, possibly after first calling
|
||||
* the enable/disable handlers.
|
||||
*/
|
||||
void (*sync_hw)(struct drm_i915_private *i915,
|
||||
struct i915_power_well *power_well);
|
||||
/*
|
||||
* Enable the well and resources that depend on it (for example
|
||||
* interrupts located on the well). Called after the 0->1 refcount
|
||||
* transition.
|
||||
*/
|
||||
void (*enable)(struct drm_i915_private *i915,
|
||||
struct i915_power_well *power_well);
|
||||
/*
|
||||
* Disable the well and resources that depend on it. Called after
|
||||
* the 1->0 refcount transition.
|
||||
*/
|
||||
void (*disable)(struct drm_i915_private *i915,
|
||||
struct i915_power_well *power_well);
|
||||
/* Returns the hw enabled state. */
|
||||
bool (*is_enabled)(struct drm_i915_private *i915,
|
||||
struct i915_power_well *power_well);
|
||||
};
|
||||
|
||||
struct i915_power_well_desc {
|
||||
const char *name;
|
||||
bool always_on;
|
||||
u64 domains;
|
||||
/* unique identifier for this power well */
|
||||
enum i915_power_well_id id;
|
||||
/*
|
||||
* Arbitraty data associated with this power well. Platform and power
|
||||
* well specific.
|
||||
*/
|
||||
union {
|
||||
struct {
|
||||
/*
|
||||
* request/status flag index in the PUNIT power well
|
||||
* control/status registers.
|
||||
*/
|
||||
u8 idx;
|
||||
} vlv;
|
||||
struct {
|
||||
enum dpio_phy phy;
|
||||
} bxt;
|
||||
struct {
|
||||
/*
|
||||
* request/status flag index in the power well
|
||||
* constrol/status registers.
|
||||
*/
|
||||
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;
|
||||
/*
|
||||
* The pw is for an ICL+ TypeC PHY port in
|
||||
* Thunderbolt mode.
|
||||
*/
|
||||
bool is_tc_tbt:1;
|
||||
} hsw;
|
||||
};
|
||||
const struct i915_power_well_ops *ops;
|
||||
};
|
||||
|
||||
struct i915_power_well {
|
||||
const struct i915_power_well_desc *desc;
|
||||
/* power well enable/disable usage count */
|
||||
int count;
|
||||
/* cached hw enabled state */
|
||||
bool hw_enabled;
|
||||
};
|
||||
|
||||
struct i915_power_well *lookup_power_well(struct drm_i915_private *i915,
|
||||
enum i915_power_well_id id);
|
||||
|
||||
void intel_power_well_enable(struct drm_i915_private *i915,
|
||||
struct i915_power_well *power_well);
|
||||
void intel_power_well_disable(struct drm_i915_private *i915,
|
||||
struct i915_power_well *power_well);
|
||||
void intel_power_well_sync_hw(struct drm_i915_private *i915,
|
||||
struct i915_power_well *power_well);
|
||||
void intel_power_well_get(struct drm_i915_private *i915,
|
||||
struct i915_power_well *power_well);
|
||||
void intel_power_well_put(struct drm_i915_private *i915,
|
||||
struct i915_power_well *power_well);
|
||||
bool intel_power_well_is_enabled(struct drm_i915_private *i915,
|
||||
struct i915_power_well *power_well);
|
||||
bool intel_power_well_is_enabled_cached(struct i915_power_well *power_well);
|
||||
bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
|
||||
enum i915_power_well_id power_well_id);
|
||||
bool intel_power_well_is_always_on(struct i915_power_well *power_well);
|
||||
const char *intel_power_well_name(struct i915_power_well *power_well);
|
||||
u64 intel_power_well_domains(struct i915_power_well *power_well);
|
||||
int intel_power_well_refcount(struct i915_power_well *power_well);
|
||||
|
||||
#endif
|
|
@ -9,6 +9,7 @@
|
|||
#if !defined(__INTEL_DISPLAY_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define __INTEL_DISPLAY_TRACE_H__
|
||||
|
||||
#include <linux/string_helpers.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
|
@ -161,7 +162,7 @@ TRACE_EVENT(intel_memory_cxsr,
|
|||
),
|
||||
|
||||
TP_printk("%s->%s, pipe A: frame=%u, scanline=%u, pipe B: frame=%u, scanline=%u, pipe C: frame=%u, scanline=%u",
|
||||
onoff(__entry->old), onoff(__entry->new),
|
||||
str_on_off(__entry->old), str_on_off(__entry->new),
|
||||
__entry->frame[PIPE_A], __entry->scanline[PIPE_A],
|
||||
__entry->frame[PIPE_B], __entry->scanline[PIPE_B],
|
||||
__entry->frame[PIPE_C], __entry->scanline[PIPE_C])
|
||||
|
@ -210,9 +211,9 @@ TRACE_EVENT(g4x_wm,
|
|||
TP_printk("pipe %c, frame=%u, scanline=%u, wm %d/%d/%d, sr %s/%d/%d/%d, hpll %s/%d/%d/%d, fbc %s",
|
||||
pipe_name(__entry->pipe), __entry->frame, __entry->scanline,
|
||||
__entry->primary, __entry->sprite, __entry->cursor,
|
||||
yesno(__entry->cxsr), __entry->sr_plane, __entry->sr_cursor, __entry->sr_fbc,
|
||||
yesno(__entry->hpll), __entry->hpll_plane, __entry->hpll_cursor, __entry->hpll_fbc,
|
||||
yesno(__entry->fbc))
|
||||
str_yes_no(__entry->cxsr), __entry->sr_plane, __entry->sr_cursor, __entry->sr_fbc,
|
||||
str_yes_no(__entry->hpll), __entry->hpll_plane, __entry->hpll_cursor, __entry->hpll_fbc,
|
||||
str_yes_no(__entry->fbc))
|
||||
);
|
||||
|
||||
TRACE_EVENT(vlv_wm,
|
||||
|
|
|
@ -280,8 +280,7 @@ struct intel_panel_bl_funcs {
|
|||
};
|
||||
|
||||
struct intel_panel {
|
||||
struct drm_display_mode *fixed_mode;
|
||||
struct drm_display_mode *downclock_mode;
|
||||
struct list_head fixed_modes;
|
||||
|
||||
/* backlight */
|
||||
struct {
|
||||
|
@ -847,8 +846,13 @@ struct intel_crtc_wm_state {
|
|||
/* gen9+ only needs 1-step wm programming */
|
||||
struct skl_pipe_wm optimal;
|
||||
struct skl_ddb_entry ddb;
|
||||
/*
|
||||
* pre-icl: for packed/planar CbCr
|
||||
* icl+: for everything
|
||||
*/
|
||||
struct skl_ddb_entry plane_ddb[I915_MAX_PLANES];
|
||||
/* pre-icl: for planar Y */
|
||||
struct skl_ddb_entry plane_ddb_y[I915_MAX_PLANES];
|
||||
struct skl_ddb_entry plane_ddb_uv[I915_MAX_PLANES];
|
||||
} skl;
|
||||
|
||||
struct {
|
||||
|
@ -954,7 +958,7 @@ struct intel_crtc_state {
|
|||
/* Pipe source size (ie. panel fitter input size)
|
||||
* All planes will be positioned inside this space,
|
||||
* and get clipped at the edges. */
|
||||
int pipe_src_w, pipe_src_h;
|
||||
struct drm_rect pipe_src;
|
||||
|
||||
/*
|
||||
* Pipe pixel rate, adjusted for
|
||||
|
@ -1125,11 +1129,14 @@ struct intel_crtc_state {
|
|||
|
||||
int min_cdclk[I915_MAX_PLANES];
|
||||
|
||||
/* for packed/planar CbCr */
|
||||
u32 data_rate[I915_MAX_PLANES];
|
||||
/* for planar Y */
|
||||
u32 data_rate_y[I915_MAX_PLANES];
|
||||
|
||||
/* FIXME unify with data_rate[] */
|
||||
u64 plane_data_rate[I915_MAX_PLANES];
|
||||
u64 uv_plane_data_rate[I915_MAX_PLANES];
|
||||
/* FIXME unify with data_rate[]? */
|
||||
u64 rel_data_rate[I915_MAX_PLANES];
|
||||
u64 rel_data_rate_y[I915_MAX_PLANES];
|
||||
|
||||
/* Gamma mode programmed on the pipe */
|
||||
u32 gamma_mode;
|
||||
|
@ -1154,6 +1161,9 @@ struct intel_crtc_state {
|
|||
/* bitmask of planes that will be updated during the commit */
|
||||
u8 update_planes;
|
||||
|
||||
u8 framestart_delay; /* 1-4 */
|
||||
u8 msa_timing_delay; /* 0-3 */
|
||||
|
||||
struct {
|
||||
u32 enable;
|
||||
u32 gcp;
|
||||
|
@ -1179,9 +1189,6 @@ struct intel_crtc_state {
|
|||
/* enable pipe csc? */
|
||||
bool csc_enable;
|
||||
|
||||
/* enable pipe big joiner? */
|
||||
bool bigjoiner;
|
||||
|
||||
/* big joiner pipe bitmask */
|
||||
u8 bigjoiner_pipes;
|
||||
|
||||
|
@ -1252,6 +1259,11 @@ enum intel_pipe_crc_source {
|
|||
INTEL_PIPE_CRC_SOURCE_MAX,
|
||||
};
|
||||
|
||||
enum drrs_refresh_rate {
|
||||
DRRS_REFRESH_RATE_HIGH,
|
||||
DRRS_REFRESH_RATE_LOW,
|
||||
};
|
||||
|
||||
#define INTEL_PIPE_CRC_ENTRIES_NR 128
|
||||
struct intel_pipe_crc {
|
||||
spinlock_t lock;
|
||||
|
@ -1294,6 +1306,16 @@ struct intel_crtc {
|
|||
} active;
|
||||
} wm;
|
||||
|
||||
struct {
|
||||
struct mutex mutex;
|
||||
struct delayed_work work;
|
||||
enum drrs_refresh_rate refresh_rate;
|
||||
unsigned int frontbuffer_bits;
|
||||
unsigned int busy_frontbuffer_bits;
|
||||
enum transcoder cpu_transcoder;
|
||||
struct intel_link_m_n m_n, m2_n2;
|
||||
} drrs;
|
||||
|
||||
int scanline_offset;
|
||||
|
||||
struct {
|
||||
|
@ -1503,6 +1525,7 @@ struct intel_psr {
|
|||
bool colorimetry_support;
|
||||
bool psr2_enabled;
|
||||
bool psr2_sel_fetch_enabled;
|
||||
bool psr2_sel_fetch_cff_enabled;
|
||||
bool req_psr2_sdp_prior_scanline;
|
||||
u8 sink_sync_latency;
|
||||
ktime_t last_entry_attempt;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "i915_reg.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_dmc.h"
|
||||
#include "intel_dmc_regs.h"
|
||||
|
||||
/**
|
||||
* DOC: DMC Firmware Support
|
||||
|
@ -37,6 +38,10 @@
|
|||
* low-power state and comes back to normal.
|
||||
*/
|
||||
|
||||
#define DMC_VERSION(major, minor) ((major) << 16 | (minor))
|
||||
#define DMC_VERSION_MAJOR(version) ((version) >> 16)
|
||||
#define DMC_VERSION_MINOR(version) ((version) & 0xffff)
|
||||
|
||||
#define DMC_PATH(platform, major, minor) \
|
||||
"i915/" \
|
||||
__stringify(platform) "_dmc_ver" \
|
||||
|
@ -47,8 +52,8 @@
|
|||
|
||||
#define DISPLAY_VER12_DMC_MAX_FW_SIZE ICL_DMC_MAX_FW_SIZE
|
||||
|
||||
#define ADLP_DMC_PATH DMC_PATH(adlp, 2, 14)
|
||||
#define ADLP_DMC_VERSION_REQUIRED DMC_VERSION(2, 14)
|
||||
#define ADLP_DMC_PATH DMC_PATH(adlp, 2, 16)
|
||||
#define ADLP_DMC_VERSION_REQUIRED DMC_VERSION(2, 16)
|
||||
MODULE_FIRMWARE(ADLP_DMC_PATH);
|
||||
|
||||
#define ADLS_DMC_PATH DMC_PATH(adls, 2, 01)
|
||||
|
@ -276,17 +281,8 @@ void intel_dmc_load_program(struct drm_i915_private *dev_priv)
|
|||
struct intel_dmc *dmc = &dev_priv->dmc;
|
||||
u32 id, i;
|
||||
|
||||
if (!HAS_DMC(dev_priv)) {
|
||||
drm_err(&dev_priv->drm,
|
||||
"No DMC support available for this platform\n");
|
||||
if (!intel_dmc_has_payload(dev_priv))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dev_priv->dmc.dmc_info[DMC_FW_MAIN].payload) {
|
||||
drm_err(&dev_priv->drm,
|
||||
"Tried to program CSR with empty payload\n");
|
||||
return;
|
||||
}
|
||||
|
||||
assert_rpm_wakelock_held(&dev_priv->runtime_pm);
|
||||
|
||||
|
@ -314,6 +310,17 @@ void intel_dmc_load_program(struct drm_i915_private *dev_priv)
|
|||
gen9_set_dc_state_debugmask(dev_priv);
|
||||
}
|
||||
|
||||
void assert_dmc_loaded(struct drm_i915_private *i915)
|
||||
{
|
||||
drm_WARN_ONCE(&i915->drm,
|
||||
!intel_de_read(i915, DMC_PROGRAM(i915->dmc.dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)),
|
||||
"DMC program storage start is NULL\n");
|
||||
drm_WARN_ONCE(&i915->drm, !intel_de_read(i915, DMC_SSP_BASE),
|
||||
"DMC SSP Base Not fine\n");
|
||||
drm_WARN_ONCE(&i915->drm, !intel_de_read(i915, DMC_HTP_SKL),
|
||||
"DMC HTP Not fine\n");
|
||||
}
|
||||
|
||||
static bool fw_info_matches_stepping(const struct intel_fw_info *fw_info,
|
||||
const struct stepping_info *si)
|
||||
{
|
||||
|
@ -697,7 +704,7 @@ void intel_dmc_ucode_init(struct drm_i915_private *dev_priv)
|
|||
dmc->fw_path = RKL_DMC_PATH;
|
||||
dmc->required_version = RKL_DMC_VERSION_REQUIRED;
|
||||
dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE;
|
||||
} else if (DISPLAY_VER(dev_priv) >= 12) {
|
||||
} else if (IS_TIGERLAKE(dev_priv)) {
|
||||
dmc->fw_path = TGL_DMC_PATH;
|
||||
dmc->required_version = TGL_DMC_VERSION_REQUIRED;
|
||||
dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE;
|
||||
|
@ -808,3 +815,101 @@ void intel_dmc_ucode_fini(struct drm_i915_private *dev_priv)
|
|||
for (id = 0; id < DMC_FW_MAX; id++)
|
||||
kfree(dev_priv->dmc.dmc_info[id].payload);
|
||||
}
|
||||
|
||||
void intel_dmc_print_error_state(struct drm_i915_error_state_buf *m,
|
||||
struct drm_i915_private *i915)
|
||||
{
|
||||
struct intel_dmc *dmc = &i915->dmc;
|
||||
|
||||
if (!HAS_DMC(i915))
|
||||
return;
|
||||
|
||||
i915_error_printf(m, "DMC loaded: %s\n",
|
||||
str_yes_no(intel_dmc_has_payload(i915)));
|
||||
i915_error_printf(m, "DMC fw version: %d.%d\n",
|
||||
DMC_VERSION_MAJOR(dmc->version),
|
||||
DMC_VERSION_MINOR(dmc->version));
|
||||
}
|
||||
|
||||
static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_i915_private *i915 = m->private;
|
||||
intel_wakeref_t wakeref;
|
||||
struct intel_dmc *dmc;
|
||||
i915_reg_t dc5_reg, dc6_reg = INVALID_MMIO_REG;
|
||||
|
||||
if (!HAS_DMC(i915))
|
||||
return -ENODEV;
|
||||
|
||||
dmc = &i915->dmc;
|
||||
|
||||
wakeref = intel_runtime_pm_get(&i915->runtime_pm);
|
||||
|
||||
seq_printf(m, "fw loaded: %s\n",
|
||||
str_yes_no(intel_dmc_has_payload(i915)));
|
||||
seq_printf(m, "path: %s\n", dmc->fw_path);
|
||||
seq_printf(m, "Pipe A fw support: %s\n",
|
||||
str_yes_no(GRAPHICS_VER(i915) >= 12));
|
||||
seq_printf(m, "Pipe A fw loaded: %s\n",
|
||||
str_yes_no(dmc->dmc_info[DMC_FW_PIPEA].payload));
|
||||
seq_printf(m, "Pipe B fw support: %s\n",
|
||||
str_yes_no(IS_ALDERLAKE_P(i915)));
|
||||
seq_printf(m, "Pipe B fw loaded: %s\n",
|
||||
str_yes_no(dmc->dmc_info[DMC_FW_PIPEB].payload));
|
||||
|
||||
if (!intel_dmc_has_payload(i915))
|
||||
goto out;
|
||||
|
||||
seq_printf(m, "version: %d.%d\n", DMC_VERSION_MAJOR(dmc->version),
|
||||
DMC_VERSION_MINOR(dmc->version));
|
||||
|
||||
if (DISPLAY_VER(i915) >= 12) {
|
||||
if (IS_DGFX(i915)) {
|
||||
dc5_reg = DG1_DMC_DEBUG_DC5_COUNT;
|
||||
} else {
|
||||
dc5_reg = TGL_DMC_DEBUG_DC5_COUNT;
|
||||
dc6_reg = TGL_DMC_DEBUG_DC6_COUNT;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: DMC_DEBUG3 is a general purpose reg.
|
||||
* According to B.Specs:49196 DMC f/w reuses DC5/6 counter
|
||||
* reg for DC3CO debugging and validation,
|
||||
* but TGL DMC f/w is using DMC_DEBUG3 reg for DC3CO counter.
|
||||
*/
|
||||
seq_printf(m, "DC3CO count: %d\n",
|
||||
intel_de_read(i915, IS_DGFX(i915) ?
|
||||
DG1_DMC_DEBUG3 : TGL_DMC_DEBUG3));
|
||||
} else {
|
||||
dc5_reg = IS_BROXTON(i915) ? BXT_DMC_DC3_DC5_COUNT :
|
||||
SKL_DMC_DC3_DC5_COUNT;
|
||||
if (!IS_GEMINILAKE(i915) && !IS_BROXTON(i915))
|
||||
dc6_reg = SKL_DMC_DC5_DC6_COUNT;
|
||||
}
|
||||
|
||||
seq_printf(m, "DC3 -> DC5 count: %d\n", intel_de_read(i915, dc5_reg));
|
||||
if (i915_mmio_reg_valid(dc6_reg))
|
||||
seq_printf(m, "DC5 -> DC6 count: %d\n",
|
||||
intel_de_read(i915, dc6_reg));
|
||||
|
||||
out:
|
||||
seq_printf(m, "program base: 0x%08x\n",
|
||||
intel_de_read(i915, DMC_PROGRAM(dmc->dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)));
|
||||
seq_printf(m, "ssp base: 0x%08x\n",
|
||||
intel_de_read(i915, DMC_SSP_BASE));
|
||||
seq_printf(m, "htp: 0x%08x\n", intel_de_read(i915, DMC_HTP_SKL));
|
||||
|
||||
intel_runtime_pm_put(&i915->runtime_pm, wakeref);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SHOW_ATTRIBUTE(intel_dmc_debugfs_status);
|
||||
|
||||
void intel_dmc_debugfs_register(struct drm_i915_private *i915)
|
||||
{
|
||||
struct drm_minor *minor = i915->drm.primary;
|
||||
|
||||
debugfs_create_file("i915_dmc_info", 0444, minor->debugfs_root,
|
||||
i915, &intel_dmc_debugfs_status_fops);
|
||||
}
|
||||
|
|
|
@ -10,12 +10,9 @@
|
|||
#include "intel_wakeref.h"
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
struct drm_i915_error_state_buf;
|
||||
struct drm_i915_private;
|
||||
|
||||
#define DMC_VERSION(major, minor) ((major) << 16 | (minor))
|
||||
#define DMC_VERSION_MAJOR(version) ((version) >> 16)
|
||||
#define DMC_VERSION_MINOR(version) ((version) & 0xffff)
|
||||
|
||||
enum {
|
||||
DMC_FW_MAIN = 0,
|
||||
DMC_FW_PIPEA,
|
||||
|
@ -54,5 +51,10 @@ void intel_dmc_ucode_fini(struct drm_i915_private *i915);
|
|||
void intel_dmc_ucode_suspend(struct drm_i915_private *i915);
|
||||
void intel_dmc_ucode_resume(struct drm_i915_private *i915);
|
||||
bool intel_dmc_has_payload(struct drm_i915_private *i915);
|
||||
void intel_dmc_debugfs_register(struct drm_i915_private *i915);
|
||||
void intel_dmc_print_error_state(struct drm_i915_error_state_buf *m,
|
||||
struct drm_i915_private *i915);
|
||||
|
||||
void assert_dmc_loaded(struct drm_i915_private *i915);
|
||||
|
||||
#endif /* __INTEL_DMC_H__ */
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2022 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_DMC_REGS_H__
|
||||
#define __INTEL_DMC_REGS_H__
|
||||
|
||||
#include "i915_reg_defs.h"
|
||||
|
||||
#define DMC_PROGRAM(addr, i) _MMIO((addr) + (i) * 4)
|
||||
#define DMC_SSP_BASE_ADDR_GEN9 0x00002FC0
|
||||
#define DMC_HTP_ADDR_SKL 0x00500034
|
||||
#define DMC_SSP_BASE _MMIO(0x8F074)
|
||||
#define DMC_HTP_SKL _MMIO(0x8F004)
|
||||
#define DMC_LAST_WRITE _MMIO(0x8F034)
|
||||
#define DMC_LAST_WRITE_VALUE 0xc003b400
|
||||
#define DMC_MMIO_START_RANGE 0x80000
|
||||
#define DMC_MMIO_END_RANGE 0x8FFFF
|
||||
#define SKL_DMC_DC3_DC5_COUNT _MMIO(0x80030)
|
||||
#define SKL_DMC_DC5_DC6_COUNT _MMIO(0x8002C)
|
||||
#define BXT_DMC_DC3_DC5_COUNT _MMIO(0x80038)
|
||||
#define TGL_DMC_DEBUG_DC5_COUNT _MMIO(0x101084)
|
||||
#define TGL_DMC_DEBUG_DC6_COUNT _MMIO(0x101088)
|
||||
#define DG1_DMC_DEBUG_DC5_COUNT _MMIO(0x134154)
|
||||
|
||||
#define TGL_DMC_DEBUG3 _MMIO(0x101090)
|
||||
#define DG1_DMC_DEBUG3 _MMIO(0x13415c)
|
||||
|
||||
#endif /* __INTEL_DMC_REGS_H__ */
|
|
@ -29,6 +29,7 @@
|
|||
#include <linux/i2c.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string_helpers.h>
|
||||
#include <linux/timekeeping.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
|
@ -59,7 +60,6 @@
|
|||
#include "intel_dp_mst.h"
|
||||
#include "intel_dpio_phy.h"
|
||||
#include "intel_dpll.h"
|
||||
#include "intel_drrs.h"
|
||||
#include "intel_fifo_underrun.h"
|
||||
#include "intel_hdcp.h"
|
||||
#include "intel_hdmi.h"
|
||||
|
@ -67,6 +67,7 @@
|
|||
#include "intel_lspcon.h"
|
||||
#include "intel_lvds.h"
|
||||
#include "intel_panel.h"
|
||||
#include "intel_pch_display.h"
|
||||
#include "intel_pps.h"
|
||||
#include "intel_psr.h"
|
||||
#include "intel_tc.h"
|
||||
|
@ -386,23 +387,13 @@ static int dg2_max_source_rate(struct intel_dp *intel_dp)
|
|||
return intel_dp_is_edp(intel_dp) ? 810000 : 1350000;
|
||||
}
|
||||
|
||||
static bool is_low_voltage_sku(struct drm_i915_private *i915, enum phy phy)
|
||||
{
|
||||
u32 voltage;
|
||||
|
||||
voltage = intel_de_read(i915, ICL_PORT_COMP_DW3(phy)) & VOLTAGE_INFO_MASK;
|
||||
|
||||
return voltage == VOLTAGE_INFO_0_85V;
|
||||
}
|
||||
|
||||
static int icl_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 phy phy = intel_port_to_phy(dev_priv, dig_port->base.port);
|
||||
|
||||
if (intel_phy_is_combo(dev_priv, phy) &&
|
||||
(is_low_voltage_sku(dev_priv, phy) || !intel_dp_is_edp(intel_dp)))
|
||||
if (intel_phy_is_combo(dev_priv, phy) && !intel_dp_is_edp(intel_dp))
|
||||
return 540000;
|
||||
|
||||
return 810000;
|
||||
|
@ -410,23 +401,7 @@ static int icl_max_source_rate(struct intel_dp *intel_dp)
|
|||
|
||||
static int ehl_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 phy phy = intel_port_to_phy(dev_priv, dig_port->base.port);
|
||||
|
||||
if (intel_dp_is_edp(intel_dp) || is_low_voltage_sku(dev_priv, phy))
|
||||
return 540000;
|
||||
|
||||
return 810000;
|
||||
}
|
||||
|
||||
static int dg1_max_source_rate(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
|
||||
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
|
||||
enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
|
||||
|
||||
if (intel_phy_is_combo(i915, phy) && is_low_voltage_sku(i915, phy))
|
||||
if (intel_dp_is_edp(intel_dp))
|
||||
return 540000;
|
||||
|
||||
return 810000;
|
||||
|
@ -469,7 +444,7 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp)
|
|||
max_rate = dg2_max_source_rate(intel_dp);
|
||||
else if (IS_ALDERLAKE_P(dev_priv) || IS_ALDERLAKE_S(dev_priv) ||
|
||||
IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv))
|
||||
max_rate = dg1_max_source_rate(intel_dp);
|
||||
max_rate = 810000;
|
||||
else if (IS_JSL_EHL(dev_priv))
|
||||
max_rate = ehl_max_source_rate(intel_dp);
|
||||
else
|
||||
|
@ -580,8 +555,9 @@ static bool intel_dp_can_link_train_fallback_for_edp(struct intel_dp *intel_dp,
|
|||
int link_rate,
|
||||
u8 lane_count)
|
||||
{
|
||||
/* FIXME figure out what we actually want here */
|
||||
const struct drm_display_mode *fixed_mode =
|
||||
intel_dp->attached_connector->panel.fixed_mode;
|
||||
intel_panel_preferred_fixed_mode(intel_dp->attached_connector);
|
||||
int mode_rate, max_rate;
|
||||
|
||||
mode_rate = intel_dp_link_required(fixed_mode->clock, 18);
|
||||
|
@ -783,14 +759,12 @@ static u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
|
|||
}
|
||||
|
||||
static enum intel_output_format
|
||||
intel_dp_output_format(struct drm_connector *connector,
|
||||
const struct drm_display_mode *mode)
|
||||
intel_dp_output_format(struct intel_connector *connector,
|
||||
bool ycbcr_420_output)
|
||||
{
|
||||
struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector));
|
||||
const struct drm_display_info *info = &connector->display_info;
|
||||
struct intel_dp *intel_dp = intel_attached_dp(connector);
|
||||
|
||||
if (!connector->ycbcr_420_allowed ||
|
||||
!drm_mode_is_420_only(info, mode))
|
||||
if (!connector->base.ycbcr_420_allowed || !ycbcr_420_output)
|
||||
return INTEL_OUTPUT_FORMAT_RGB;
|
||||
|
||||
if (intel_dp->dfp.rgb_to_ycbcr &&
|
||||
|
@ -825,11 +799,12 @@ static int intel_dp_output_bpp(enum intel_output_format output_format, int bpp)
|
|||
}
|
||||
|
||||
static int
|
||||
intel_dp_mode_min_output_bpp(struct drm_connector *connector,
|
||||
intel_dp_mode_min_output_bpp(struct intel_connector *connector,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
const struct drm_display_info *info = &connector->base.display_info;
|
||||
enum intel_output_format output_format =
|
||||
intel_dp_output_format(connector, mode);
|
||||
intel_dp_output_format(connector, drm_mode_is_420_only(info, mode));
|
||||
|
||||
return intel_dp_output_bpp(output_format, intel_dp_min_bpp(output_format));
|
||||
}
|
||||
|
@ -853,6 +828,43 @@ static bool intel_dp_hdisplay_bad(struct drm_i915_private *dev_priv,
|
|||
return hdisplay == 4096 && !HAS_DDI(dev_priv);
|
||||
}
|
||||
|
||||
static int intel_dp_max_tmds_clock(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_connector *connector = intel_dp->attached_connector;
|
||||
const struct drm_display_info *info = &connector->base.display_info;
|
||||
int max_tmds_clock = intel_dp->dfp.max_tmds_clock;
|
||||
|
||||
/* Only consider the sink's max TMDS clock if we know this is a HDMI DFP */
|
||||
if (max_tmds_clock && info->max_tmds_clock)
|
||||
max_tmds_clock = min(max_tmds_clock, info->max_tmds_clock);
|
||||
|
||||
return max_tmds_clock;
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
intel_dp_tmds_clock_valid(struct intel_dp *intel_dp,
|
||||
int clock, int bpc, bool ycbcr420_output,
|
||||
bool respect_downstream_limits)
|
||||
{
|
||||
int tmds_clock, min_tmds_clock, max_tmds_clock;
|
||||
|
||||
if (!respect_downstream_limits)
|
||||
return MODE_OK;
|
||||
|
||||
tmds_clock = intel_hdmi_tmds_clock(clock, bpc, ycbcr420_output);
|
||||
|
||||
min_tmds_clock = intel_dp->dfp.min_tmds_clock;
|
||||
max_tmds_clock = intel_dp_max_tmds_clock(intel_dp);
|
||||
|
||||
if (min_tmds_clock && tmds_clock < min_tmds_clock)
|
||||
return MODE_CLOCK_LOW;
|
||||
|
||||
if (max_tmds_clock && tmds_clock > max_tmds_clock)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
intel_dp_mode_valid_downstream(struct intel_connector *connector,
|
||||
const struct drm_display_mode *mode,
|
||||
|
@ -860,13 +872,14 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
|
|||
{
|
||||
struct intel_dp *intel_dp = intel_attached_dp(connector);
|
||||
const struct drm_display_info *info = &connector->base.display_info;
|
||||
int tmds_clock;
|
||||
enum drm_mode_status status;
|
||||
bool ycbcr_420_only;
|
||||
|
||||
/* If PCON supports FRL MODE, check FRL bandwidth constraints */
|
||||
if (intel_dp->dfp.pcon_max_frl_bw) {
|
||||
int target_bw;
|
||||
int max_frl_bw;
|
||||
int bpp = intel_dp_mode_min_output_bpp(&connector->base, mode);
|
||||
int bpp = intel_dp_mode_min_output_bpp(connector, mode);
|
||||
|
||||
target_bw = bpp * target_clock;
|
||||
|
||||
|
@ -885,16 +898,23 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
|
|||
target_clock > intel_dp->dfp.max_dotclock)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
/* Assume 8bpc for the DP++/HDMI/DVI TMDS clock check */
|
||||
tmds_clock = intel_hdmi_tmds_clock(target_clock, 8,
|
||||
drm_mode_is_420_only(info, mode));
|
||||
ycbcr_420_only = drm_mode_is_420_only(info, mode);
|
||||
|
||||
if (intel_dp->dfp.min_tmds_clock &&
|
||||
tmds_clock < intel_dp->dfp.min_tmds_clock)
|
||||
return MODE_CLOCK_LOW;
|
||||
if (intel_dp->dfp.max_tmds_clock &&
|
||||
tmds_clock > intel_dp->dfp.max_tmds_clock)
|
||||
return MODE_CLOCK_HIGH;
|
||||
/* Assume 8bpc for the DP++/HDMI/DVI TMDS clock check */
|
||||
status = intel_dp_tmds_clock_valid(intel_dp, target_clock,
|
||||
8, ycbcr_420_only, true);
|
||||
|
||||
if (status != MODE_OK) {
|
||||
if (ycbcr_420_only ||
|
||||
!connector->base.ycbcr_420_allowed ||
|
||||
!drm_mode_is_420_also(info, mode))
|
||||
return status;
|
||||
|
||||
status = intel_dp_tmds_clock_valid(intel_dp, target_clock,
|
||||
8, true, true);
|
||||
if (status != MODE_OK)
|
||||
return status;
|
||||
}
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
@ -911,13 +931,13 @@ static bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
|
|||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
intel_dp_mode_valid(struct drm_connector *connector,
|
||||
intel_dp_mode_valid(struct drm_connector *_connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector));
|
||||
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||
struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
struct intel_dp *intel_dp = intel_attached_dp(connector);
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
const struct drm_display_mode *fixed_mode;
|
||||
int target_clock = mode->clock;
|
||||
int max_rate, mode_rate, max_lanes, max_link_clock;
|
||||
int max_dotclk = dev_priv->max_dotclk_freq;
|
||||
|
@ -932,8 +952,9 @@ intel_dp_mode_valid(struct drm_connector *connector,
|
|||
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
|
||||
return MODE_H_ILLEGAL;
|
||||
|
||||
fixed_mode = intel_panel_fixed_mode(connector, mode);
|
||||
if (intel_dp_is_edp(intel_dp) && fixed_mode) {
|
||||
status = intel_panel_mode_valid(intel_connector, mode);
|
||||
status = intel_panel_mode_valid(connector, mode);
|
||||
if (status != MODE_OK)
|
||||
return status;
|
||||
|
||||
|
@ -1007,8 +1028,7 @@ intel_dp_mode_valid(struct drm_connector *connector,
|
|||
if (mode_rate > max_rate && !dsc)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
status = intel_dp_mode_valid_downstream(intel_connector,
|
||||
mode, target_clock);
|
||||
status = intel_dp_mode_valid_downstream(connector, mode, target_clock);
|
||||
if (status != MODE_OK)
|
||||
return status;
|
||||
|
||||
|
@ -1130,44 +1150,50 @@ static bool intel_dp_supports_dsc(struct intel_dp *intel_dp,
|
|||
drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd);
|
||||
}
|
||||
|
||||
static bool intel_dp_hdmi_ycbcr420(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
static bool intel_dp_is_ycbcr420(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
return crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
|
||||
(crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444 &&
|
||||
intel_dp->dfp.ycbcr_444_to_420);
|
||||
}
|
||||
|
||||
static bool intel_dp_hdmi_tmds_clock_valid(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state, int bpc)
|
||||
static int intel_dp_hdmi_compute_bpc(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
int bpc, bool respect_downstream_limits)
|
||||
{
|
||||
bool ycbcr420_output = intel_dp_is_ycbcr420(intel_dp, crtc_state);
|
||||
int clock = crtc_state->hw.adjusted_mode.crtc_clock;
|
||||
int tmds_clock = intel_hdmi_tmds_clock(clock, bpc,
|
||||
intel_dp_hdmi_ycbcr420(intel_dp, crtc_state));
|
||||
|
||||
if (intel_dp->dfp.min_tmds_clock &&
|
||||
tmds_clock < intel_dp->dfp.min_tmds_clock)
|
||||
return false;
|
||||
/*
|
||||
* Current bpc could already be below 8bpc due to
|
||||
* FDI bandwidth constraints or other limits.
|
||||
* HDMI minimum is 8bpc however.
|
||||
*/
|
||||
bpc = max(bpc, 8);
|
||||
|
||||
if (intel_dp->dfp.max_tmds_clock &&
|
||||
tmds_clock > intel_dp->dfp.max_tmds_clock)
|
||||
return false;
|
||||
/*
|
||||
* We will never exceed downstream TMDS clock limits while
|
||||
* attempting deep color. If the user insists on forcing an
|
||||
* out of spec mode they will have to be satisfied with 8bpc.
|
||||
*/
|
||||
if (!respect_downstream_limits)
|
||||
bpc = 8;
|
||||
|
||||
return true;
|
||||
}
|
||||
for (; bpc >= 8; bpc -= 2) {
|
||||
if (intel_hdmi_bpc_possible(crtc_state, bpc,
|
||||
intel_dp->has_hdmi_sink, ycbcr420_output) &&
|
||||
intel_dp_tmds_clock_valid(intel_dp, clock, bpc, ycbcr420_output,
|
||||
respect_downstream_limits) == MODE_OK)
|
||||
return bpc;
|
||||
}
|
||||
|
||||
static bool intel_dp_hdmi_bpc_possible(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
int bpc)
|
||||
{
|
||||
|
||||
return intel_hdmi_bpc_possible(crtc_state, bpc, intel_dp->has_hdmi_sink,
|
||||
intel_dp_hdmi_ycbcr420(intel_dp, crtc_state)) &&
|
||||
intel_dp_hdmi_tmds_clock_valid(intel_dp, crtc_state, bpc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int intel_dp_max_bpp(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
bool respect_downstream_limits)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
struct intel_connector *intel_connector = intel_dp->attached_connector;
|
||||
|
@ -1179,10 +1205,14 @@ static int intel_dp_max_bpp(struct intel_dp *intel_dp,
|
|||
bpc = min_t(int, bpc, intel_dp->dfp.max_bpc);
|
||||
|
||||
if (intel_dp->dfp.min_tmds_clock) {
|
||||
for (; bpc >= 10; bpc -= 2) {
|
||||
if (intel_dp_hdmi_bpc_possible(intel_dp, crtc_state, bpc))
|
||||
break;
|
||||
}
|
||||
int max_hdmi_bpc;
|
||||
|
||||
max_hdmi_bpc = intel_dp_hdmi_compute_bpc(intel_dp, crtc_state, bpc,
|
||||
respect_downstream_limits);
|
||||
if (max_hdmi_bpc < 0)
|
||||
return 0;
|
||||
|
||||
bpc = min(bpc, max_hdmi_bpc);
|
||||
}
|
||||
|
||||
bpp = bpc * 3;
|
||||
|
@ -1424,13 +1454,13 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
|
|||
pipe_config->lane_count,
|
||||
adjusted_mode->crtc_clock,
|
||||
adjusted_mode->crtc_hdisplay,
|
||||
pipe_config->bigjoiner,
|
||||
pipe_config->bigjoiner_pipes,
|
||||
pipe_bpp);
|
||||
dsc_dp_slice_count =
|
||||
intel_dp_dsc_get_slice_count(intel_dp,
|
||||
adjusted_mode->crtc_clock,
|
||||
adjusted_mode->crtc_hdisplay,
|
||||
pipe_config->bigjoiner);
|
||||
pipe_config->bigjoiner_pipes);
|
||||
if (!dsc_max_output_bpp || !dsc_dp_slice_count) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Compressed BPP/Slice Count not supported\n");
|
||||
|
@ -1464,7 +1494,7 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
|
|||
* then we need to use 2 VDSC instances.
|
||||
*/
|
||||
if (adjusted_mode->crtc_clock > dev_priv->max_cdclk_freq ||
|
||||
pipe_config->bigjoiner) {
|
||||
pipe_config->bigjoiner_pipes) {
|
||||
if (pipe_config->dsc.slice_count < 2) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Cannot split stream to use 2 VDSC instances\n");
|
||||
|
@ -1497,13 +1527,16 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
|
|||
static int
|
||||
intel_dp_compute_link_config(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config,
|
||||
struct drm_connector_state *conn_state)
|
||||
struct drm_connector_state *conn_state,
|
||||
bool respect_downstream_limits)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
|
||||
const struct drm_display_mode *adjusted_mode =
|
||||
&pipe_config->hw.adjusted_mode;
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
struct link_config_limits limits;
|
||||
bool joiner_needs_dsc = false;
|
||||
int ret;
|
||||
|
||||
limits.min_rate = intel_dp_common_rate(intel_dp, 0);
|
||||
|
@ -1513,7 +1546,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
|
|||
limits.max_lane_count = intel_dp_max_lane_count(intel_dp);
|
||||
|
||||
limits.min_bpp = intel_dp_min_bpp(pipe_config->output_format);
|
||||
limits.max_bpp = intel_dp_max_bpp(intel_dp, pipe_config);
|
||||
limits.max_bpp = intel_dp_max_bpp(intel_dp, pipe_config, respect_downstream_limits);
|
||||
|
||||
if (intel_dp->use_max_params) {
|
||||
/*
|
||||
|
@ -1537,7 +1570,14 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
|
|||
|
||||
if (intel_dp_need_bigjoiner(intel_dp, adjusted_mode->crtc_hdisplay,
|
||||
adjusted_mode->crtc_clock))
|
||||
pipe_config->bigjoiner = true;
|
||||
pipe_config->bigjoiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
|
||||
|
||||
/*
|
||||
* Pipe joiner needs compression up to display 12 due to bandwidth
|
||||
* limitation. DG2 onwards pipe joiner can be enabled without
|
||||
* compression.
|
||||
*/
|
||||
joiner_needs_dsc = DISPLAY_VER(i915) < 13 && pipe_config->bigjoiner_pipes;
|
||||
|
||||
/*
|
||||
* Optimize for slow and wide for everything, because there are some
|
||||
|
@ -1545,13 +1585,10 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
|
|||
*/
|
||||
ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config, &limits);
|
||||
|
||||
/*
|
||||
* Pipe joiner needs compression upto display12 due to BW limitation. DG2
|
||||
* onwards pipe joiner can be enabled without compression.
|
||||
*/
|
||||
drm_dbg_kms(&i915->drm, "Force DSC en = %d\n", intel_dp->force_dsc_en);
|
||||
if (ret || intel_dp->force_dsc_en || (DISPLAY_VER(i915) < 13 &&
|
||||
pipe_config->bigjoiner)) {
|
||||
if (ret || joiner_needs_dsc || intel_dp->force_dsc_en) {
|
||||
drm_dbg_kms(&i915->drm, "Try DSC (fallback=%s, joiner=%s, force=%s)\n",
|
||||
str_yes_no(ret), str_yes_no(joiner_needs_dsc),
|
||||
str_yes_no(intel_dp->force_dsc_en));
|
||||
ret = intel_dp_dsc_compute_config(intel_dp, pipe_config,
|
||||
conn_state, &limits);
|
||||
if (ret < 0)
|
||||
|
@ -1786,6 +1823,137 @@ intel_dp_compute_hdr_metadata_infoframe_sdp(struct intel_dp *intel_dp,
|
|||
intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GAMUT_METADATA);
|
||||
}
|
||||
|
||||
static bool cpu_transcoder_has_drrs(struct drm_i915_private *i915,
|
||||
enum transcoder cpu_transcoder)
|
||||
{
|
||||
/* M1/N1 is double buffered */
|
||||
if (DISPLAY_VER(i915) >= 9 || IS_BROADWELL(i915))
|
||||
return true;
|
||||
|
||||
return intel_cpu_transcoder_has_m2_n2(i915, cpu_transcoder);
|
||||
}
|
||||
|
||||
static bool can_enable_drrs(struct intel_connector *connector,
|
||||
const struct intel_crtc_state *pipe_config,
|
||||
const struct drm_display_mode *downclock_mode)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
|
||||
if (pipe_config->vrr.enable)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* DRRS and PSR can't be enable together, so giving preference to PSR
|
||||
* as it allows more power-savings by complete shutting down display,
|
||||
* so to guarantee this, intel_drrs_compute_config() must be called
|
||||
* after intel_psr_compute_config().
|
||||
*/
|
||||
if (pipe_config->has_psr)
|
||||
return false;
|
||||
|
||||
/* FIXME missing FDI M2/N2 etc. */
|
||||
if (pipe_config->has_pch_encoder)
|
||||
return false;
|
||||
|
||||
if (!cpu_transcoder_has_drrs(i915, pipe_config->cpu_transcoder))
|
||||
return false;
|
||||
|
||||
return downclock_mode &&
|
||||
intel_panel_drrs_type(connector) == DRRS_TYPE_SEAMLESS;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_drrs_compute_config(struct intel_connector *connector,
|
||||
struct intel_crtc_state *pipe_config,
|
||||
int output_bpp, bool constant_n)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
const struct drm_display_mode *downclock_mode =
|
||||
intel_panel_downclock_mode(connector, &pipe_config->hw.adjusted_mode);
|
||||
int pixel_clock;
|
||||
|
||||
if (!can_enable_drrs(connector, pipe_config, downclock_mode)) {
|
||||
if (intel_cpu_transcoder_has_m2_n2(i915, pipe_config->cpu_transcoder))
|
||||
intel_zero_m_n(&pipe_config->dp_m2_n2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (IS_IRONLAKE(i915) || IS_SANDYBRIDGE(i915) || IS_IVYBRIDGE(i915))
|
||||
pipe_config->msa_timing_delay = i915->vbt.edp.drrs_msa_timing_delay;
|
||||
|
||||
pipe_config->has_drrs = true;
|
||||
|
||||
pixel_clock = downclock_mode->clock;
|
||||
if (pipe_config->splitter.enable)
|
||||
pixel_clock /= pipe_config->splitter.link_count;
|
||||
|
||||
intel_link_compute_m_n(output_bpp, pipe_config->lane_count, pixel_clock,
|
||||
pipe_config->port_clock, &pipe_config->dp_m2_n2,
|
||||
constant_n, pipe_config->fec_enable);
|
||||
|
||||
/* FIXME: abstract this better */
|
||||
if (pipe_config->splitter.enable)
|
||||
pipe_config->dp_m2_n2.data_m *= pipe_config->splitter.link_count;
|
||||
}
|
||||
|
||||
static bool intel_dp_has_audio(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
const struct intel_digital_connector_state *intel_conn_state =
|
||||
to_intel_digital_connector_state(conn_state);
|
||||
|
||||
if (!intel_dp_port_has_audio(i915, encoder->port))
|
||||
return false;
|
||||
|
||||
if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
|
||||
return intel_dp->has_audio;
|
||||
else
|
||||
return intel_conn_state->force_audio == HDMI_AUDIO_ON;
|
||||
}
|
||||
|
||||
static int
|
||||
intel_dp_compute_output_format(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state,
|
||||
bool respect_downstream_limits)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
struct intel_connector *connector = intel_dp->attached_connector;
|
||||
const struct drm_display_info *info = &connector->base.display_info;
|
||||
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
|
||||
bool ycbcr_420_only;
|
||||
int ret;
|
||||
|
||||
ycbcr_420_only = drm_mode_is_420_only(info, adjusted_mode);
|
||||
|
||||
crtc_state->output_format = intel_dp_output_format(connector, ycbcr_420_only);
|
||||
|
||||
if (ycbcr_420_only && !intel_dp_is_ycbcr420(intel_dp, crtc_state)) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n");
|
||||
crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
|
||||
}
|
||||
|
||||
ret = intel_dp_compute_link_config(encoder, crtc_state, conn_state,
|
||||
respect_downstream_limits);
|
||||
if (ret) {
|
||||
if (intel_dp_is_ycbcr420(intel_dp, crtc_state) ||
|
||||
!connector->base.ycbcr_420_allowed ||
|
||||
!drm_mode_is_420_also(info, adjusted_mode))
|
||||
return ret;
|
||||
|
||||
crtc_state->output_format = intel_dp_output_format(connector, true);
|
||||
ret = intel_dp_compute_link_config(encoder, crtc_state, conn_state,
|
||||
respect_downstream_limits);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
intel_dp_compute_config(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config,
|
||||
|
@ -1794,38 +1962,19 @@ intel_dp_compute_config(struct intel_encoder *encoder,
|
|||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
enum port port = encoder->port;
|
||||
struct intel_connector *intel_connector = intel_dp->attached_connector;
|
||||
struct intel_digital_connector_state *intel_conn_state =
|
||||
to_intel_digital_connector_state(conn_state);
|
||||
const struct drm_display_mode *fixed_mode;
|
||||
struct intel_connector *connector = intel_dp->attached_connector;
|
||||
bool constant_n = drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_CONSTANT_N);
|
||||
int ret = 0, output_bpp;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && port != PORT_A)
|
||||
if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && encoder->port != PORT_A)
|
||||
pipe_config->has_pch_encoder = true;
|
||||
|
||||
pipe_config->output_format = intel_dp_output_format(&intel_connector->base,
|
||||
adjusted_mode);
|
||||
pipe_config->has_audio = intel_dp_has_audio(encoder, pipe_config, conn_state);
|
||||
|
||||
if (pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) {
|
||||
ret = intel_panel_fitting(pipe_config, conn_state);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!intel_dp_port_has_audio(dev_priv, port))
|
||||
pipe_config->has_audio = false;
|
||||
else if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
|
||||
pipe_config->has_audio = intel_dp->has_audio;
|
||||
else
|
||||
pipe_config->has_audio = intel_conn_state->force_audio == HDMI_AUDIO_ON;
|
||||
|
||||
if (intel_dp_is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
|
||||
ret = intel_panel_compute_config(intel_connector, adjusted_mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = intel_panel_fitting(pipe_config, conn_state);
|
||||
fixed_mode = intel_panel_fixed_mode(connector, adjusted_mode);
|
||||
if (intel_dp_is_edp(intel_dp) && fixed_mode) {
|
||||
ret = intel_panel_compute_config(connector, adjusted_mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -1843,10 +1992,23 @@ intel_dp_compute_config(struct intel_encoder *encoder,
|
|||
if (intel_dp_hdisplay_bad(dev_priv, adjusted_mode->crtc_hdisplay))
|
||||
return -EINVAL;
|
||||
|
||||
ret = intel_dp_compute_link_config(encoder, pipe_config, conn_state);
|
||||
if (ret < 0)
|
||||
/*
|
||||
* Try to respect downstream TMDS clock limits first, if
|
||||
* that fails assume the user might know something we don't.
|
||||
*/
|
||||
ret = intel_dp_compute_output_format(encoder, pipe_config, conn_state, true);
|
||||
if (ret)
|
||||
ret = intel_dp_compute_output_format(encoder, pipe_config, conn_state, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((intel_dp_is_edp(intel_dp) && fixed_mode) ||
|
||||
pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) {
|
||||
ret = intel_panel_fitting(pipe_config, conn_state);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
pipe_config->limited_color_range =
|
||||
intel_dp_limited_color_range(pipe_config, conn_state);
|
||||
|
||||
|
@ -1892,8 +2054,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
|
|||
|
||||
intel_vrr_compute_config(pipe_config, conn_state);
|
||||
intel_psr_compute_config(intel_dp, pipe_config, conn_state);
|
||||
intel_drrs_compute_config(intel_dp, pipe_config, output_bpp,
|
||||
constant_n);
|
||||
intel_dp_drrs_compute_config(connector, pipe_config,
|
||||
output_bpp, constant_n);
|
||||
intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state);
|
||||
intel_dp_compute_hdr_metadata_infoframe_sdp(intel_dp, pipe_config, conn_state);
|
||||
|
||||
|
@ -1976,7 +2138,7 @@ void intel_dp_sink_set_decompression_state(struct intel_dp *intel_dp,
|
|||
if (ret < 0)
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"Failed to %s sink decompression state\n",
|
||||
enabledisable(enable));
|
||||
str_enable_disable(enable));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2452,7 +2614,7 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp,
|
|||
if (drm_dp_dpcd_writeb(&intel_dp->aux,
|
||||
DP_PROTOCOL_CONVERTER_CONTROL_0, tmp) != 1)
|
||||
drm_dbg_kms(&i915->drm, "Failed to %s protocol converter HDMI mode\n",
|
||||
enabledisable(intel_dp->has_hdmi_sink));
|
||||
str_enable_disable(intel_dp->has_hdmi_sink));
|
||||
|
||||
tmp = crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444 &&
|
||||
intel_dp->dfp.ycbcr_444_to_420 ? DP_CONVERSION_TO_YCBCR420_ENABLE : 0;
|
||||
|
@ -2461,45 +2623,15 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp,
|
|||
DP_PROTOCOL_CONVERTER_CONTROL_1, tmp) != 1)
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"Failed to %s protocol converter YCbCr 4:2:0 conversion mode\n",
|
||||
enabledisable(intel_dp->dfp.ycbcr_444_to_420));
|
||||
str_enable_disable(intel_dp->dfp.ycbcr_444_to_420));
|
||||
|
||||
tmp = 0;
|
||||
if (intel_dp->dfp.rgb_to_ycbcr) {
|
||||
bool bt2020, bt709;
|
||||
|
||||
/*
|
||||
* FIXME: Currently if userspace selects BT2020 or BT709, but PCON supports only
|
||||
* RGB->YCbCr for BT601 colorspace, we go ahead with BT601, as default.
|
||||
*
|
||||
*/
|
||||
tmp = DP_CONVERSION_BT601_RGB_YCBCR_ENABLE;
|
||||
|
||||
bt2020 = drm_dp_downstream_rgb_to_ycbcr_conversion(intel_dp->dpcd,
|
||||
intel_dp->downstream_ports,
|
||||
DP_DS_HDMI_BT2020_RGB_YCBCR_CONV);
|
||||
bt709 = drm_dp_downstream_rgb_to_ycbcr_conversion(intel_dp->dpcd,
|
||||
intel_dp->downstream_ports,
|
||||
DP_DS_HDMI_BT709_RGB_YCBCR_CONV);
|
||||
switch (crtc_state->infoframes.vsc.colorimetry) {
|
||||
case DP_COLORIMETRY_BT2020_RGB:
|
||||
case DP_COLORIMETRY_BT2020_YCC:
|
||||
if (bt2020)
|
||||
tmp = DP_CONVERSION_BT2020_RGB_YCBCR_ENABLE;
|
||||
break;
|
||||
case DP_COLORIMETRY_BT709_YCC:
|
||||
case DP_COLORIMETRY_XVYCC_709:
|
||||
if (bt709)
|
||||
tmp = DP_CONVERSION_BT709_RGB_YCBCR_ENABLE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
tmp = intel_dp->dfp.rgb_to_ycbcr ?
|
||||
DP_CONVERSION_BT709_RGB_YCBCR_ENABLE : 0;
|
||||
|
||||
if (drm_dp_pcon_convert_rgb_to_ycbcr(&intel_dp->aux, tmp) < 0)
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"Failed to %s protocol converter RGB->YCbCr conversion mode\n",
|
||||
enabledisable(tmp));
|
||||
str_enable_disable(tmp));
|
||||
}
|
||||
|
||||
|
||||
|
@ -2572,9 +2704,9 @@ static void intel_edp_mso_mode_fixup(struct intel_connector *connector,
|
|||
drm_mode_set_name(mode);
|
||||
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"[CONNECTOR:%d:%s] using generated MSO mode: ",
|
||||
connector->base.base.id, connector->base.name);
|
||||
drm_mode_debug_printmodeline(mode);
|
||||
"[CONNECTOR:%d:%s] using generated MSO mode: " DRM_MODE_FMT "\n",
|
||||
connector->base.base.id, connector->base.name,
|
||||
DRM_MODE_ARG(mode));
|
||||
}
|
||||
|
||||
static void intel_edp_mso_init(struct intel_dp *intel_dp)
|
||||
|
@ -2787,8 +2919,9 @@ intel_dp_configure_mst(struct intel_dp *intel_dp)
|
|||
drm_dbg_kms(&i915->drm,
|
||||
"[ENCODER:%d:%s] MST support: port: %s, sink: %s, modparam: %s\n",
|
||||
encoder->base.base.id, encoder->base.name,
|
||||
yesno(intel_dp_mst_source_support(intel_dp)), yesno(sink_can_mst),
|
||||
yesno(i915->params.enable_dp_mst));
|
||||
str_yes_no(intel_dp_mst_source_support(intel_dp)),
|
||||
str_yes_no(sink_can_mst),
|
||||
str_yes_no(i915->params.enable_dp_mst));
|
||||
|
||||
if (!intel_dp_mst_source_support(intel_dp))
|
||||
return;
|
||||
|
@ -4347,9 +4480,7 @@ intel_dp_update_420(struct intel_dp *intel_dp)
|
|||
intel_dp->downstream_ports);
|
||||
rgb_to_ycbcr = drm_dp_downstream_rgb_to_ycbcr_conversion(intel_dp->dpcd,
|
||||
intel_dp->downstream_ports,
|
||||
DP_DS_HDMI_BT601_RGB_YCBCR_CONV |
|
||||
DP_DS_HDMI_BT709_RGB_YCBCR_CONV |
|
||||
DP_DS_HDMI_BT2020_RGB_YCBCR_CONV);
|
||||
DP_DS_HDMI_BT709_RGB_YCBCR_CONV);
|
||||
|
||||
if (DISPLAY_VER(i915) >= 11) {
|
||||
/* Let PCON convert from RGB->YCbCr if possible */
|
||||
|
@ -4375,21 +4506,28 @@ intel_dp_update_420(struct intel_dp *intel_dp)
|
|||
drm_dbg_kms(&i915->drm,
|
||||
"[CONNECTOR:%d:%s] RGB->YcbCr conversion? %s, YCbCr 4:2:0 allowed? %s, YCbCr 4:4:4->4:2:0 conversion? %s\n",
|
||||
connector->base.base.id, connector->base.name,
|
||||
yesno(intel_dp->dfp.rgb_to_ycbcr),
|
||||
yesno(connector->base.ycbcr_420_allowed),
|
||||
yesno(intel_dp->dfp.ycbcr_444_to_420));
|
||||
str_yes_no(intel_dp->dfp.rgb_to_ycbcr),
|
||||
str_yes_no(connector->base.ycbcr_420_allowed),
|
||||
str_yes_no(intel_dp->dfp.ycbcr_444_to_420));
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_set_edid(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
|
||||
struct intel_connector *connector = intel_dp->attached_connector;
|
||||
struct edid *edid;
|
||||
bool vrr_capable;
|
||||
|
||||
intel_dp_unset_edid(intel_dp);
|
||||
edid = intel_dp_get_edid(intel_dp);
|
||||
connector->detect_edid = edid;
|
||||
|
||||
vrr_capable = intel_vrr_is_capable(&connector->base);
|
||||
drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] VRR capable: %s\n",
|
||||
connector->base.base.id, connector->base.name, str_yes_no(vrr_capable));
|
||||
drm_connector_set_vrr_capable_property(&connector->base, vrr_capable);
|
||||
|
||||
intel_dp_update_dfp(intel_dp, edid);
|
||||
intel_dp_update_420(intel_dp);
|
||||
|
||||
|
@ -4422,6 +4560,9 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
|
|||
|
||||
intel_dp->dfp.ycbcr_444_to_420 = false;
|
||||
connector->base.ycbcr_420_allowed = false;
|
||||
|
||||
drm_connector_set_vrr_capable_property(&connector->base,
|
||||
false);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -4572,26 +4713,12 @@ static int intel_dp_get_modes(struct drm_connector *connector)
|
|||
int num_modes = 0;
|
||||
|
||||
edid = intel_connector->detect_edid;
|
||||
if (edid) {
|
||||
if (edid)
|
||||
num_modes = intel_connector_update_modes(connector, edid);
|
||||
|
||||
if (intel_vrr_is_capable(connector))
|
||||
drm_connector_set_vrr_capable_property(connector,
|
||||
true);
|
||||
}
|
||||
|
||||
/* Also add fixed mode, which may or may not be present in EDID */
|
||||
if (intel_dp_is_edp(intel_attached_dp(intel_connector)) &&
|
||||
intel_connector->panel.fixed_mode) {
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev,
|
||||
intel_connector->panel.fixed_mode);
|
||||
if (mode) {
|
||||
drm_mode_probed_add(connector, mode);
|
||||
num_modes++;
|
||||
}
|
||||
}
|
||||
if (intel_dp_is_edp(intel_attached_dp(intel_connector)))
|
||||
num_modes += intel_panel_get_modes(intel_connector);
|
||||
|
||||
if (num_modes)
|
||||
return num_modes;
|
||||
|
@ -4643,9 +4770,7 @@ intel_dp_connector_register(struct drm_connector *connector)
|
|||
if (lspcon_init(dig_port)) {
|
||||
lspcon_detect_hdr_capability(lspcon);
|
||||
if (lspcon->hdr_supported)
|
||||
drm_object_attach_property(&connector->base,
|
||||
connector->dev->mode_config.hdr_output_metadata_property,
|
||||
0);
|
||||
drm_connector_attach_hdr_output_metadata_property(connector);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -4914,6 +5039,25 @@ bool intel_dp_is_port_edp(struct drm_i915_private *dev_priv, enum port port)
|
|||
return intel_bios_is_port_edp(dev_priv, port);
|
||||
}
|
||||
|
||||
static bool
|
||||
has_gamut_metadata_dip(struct drm_i915_private *i915, enum port port)
|
||||
{
|
||||
if (intel_bios_is_lspcon_present(i915, port))
|
||||
return false;
|
||||
|
||||
if (DISPLAY_VER(i915) >= 11)
|
||||
return true;
|
||||
|
||||
if (port == PORT_A)
|
||||
return false;
|
||||
|
||||
if (IS_HASWELL(i915) || IS_BROADWELL(i915) ||
|
||||
DISPLAY_VER(i915) >= 9)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector)
|
||||
{
|
||||
|
@ -4940,10 +5084,8 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
|
|||
intel_attach_dp_colorspace_property(connector);
|
||||
}
|
||||
|
||||
if (IS_GEMINILAKE(dev_priv) || DISPLAY_VER(dev_priv) >= 11)
|
||||
drm_object_attach_property(&connector->base,
|
||||
connector->dev->mode_config.hdr_output_metadata_property,
|
||||
0);
|
||||
if (has_gamut_metadata_dip(dev_priv, port))
|
||||
drm_connector_attach_hdr_output_metadata_property(connector);
|
||||
|
||||
if (intel_dp_is_edp(intel_dp)) {
|
||||
u32 allowed_scalers;
|
||||
|
@ -4962,14 +5104,30 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
|
|||
drm_connector_attach_vrr_capable_property(connector);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_edp_add_properties(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_connector *connector = intel_dp->attached_connector;
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
const struct drm_display_mode *fixed_mode =
|
||||
intel_panel_preferred_fixed_mode(connector);
|
||||
|
||||
if (!fixed_mode)
|
||||
return;
|
||||
|
||||
drm_connector_set_panel_orientation_with_quirk(&connector->base,
|
||||
i915->vbt.orientation,
|
||||
fixed_mode->hdisplay,
|
||||
fixed_mode->vdisplay);
|
||||
}
|
||||
|
||||
static bool intel_edp_init_connector(struct intel_dp *intel_dp,
|
||||
struct intel_connector *intel_connector)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
struct drm_device *dev = &dev_priv->drm;
|
||||
struct drm_connector *connector = &intel_connector->base;
|
||||
struct drm_display_mode *fixed_mode = NULL;
|
||||
struct drm_display_mode *downclock_mode = NULL;
|
||||
struct drm_display_mode *fixed_mode;
|
||||
bool has_dpcd;
|
||||
enum pipe pipe = INVALID_PIPE;
|
||||
struct edid *edid;
|
||||
|
@ -5026,20 +5184,20 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
|
|||
}
|
||||
intel_connector->edid = edid;
|
||||
|
||||
fixed_mode = intel_panel_edid_fixed_mode(intel_connector);
|
||||
if (fixed_mode)
|
||||
downclock_mode = intel_drrs_init(intel_connector, fixed_mode);
|
||||
intel_panel_add_edid_fixed_modes(intel_connector,
|
||||
dev_priv->vbt.drrs_type != DRRS_TYPE_NONE);
|
||||
|
||||
/* MSO requires information from the EDID */
|
||||
intel_edp_mso_init(intel_dp);
|
||||
|
||||
/* multiply the mode clock and horizontal timings for MSO */
|
||||
intel_edp_mso_mode_fixup(intel_connector, fixed_mode);
|
||||
intel_edp_mso_mode_fixup(intel_connector, downclock_mode);
|
||||
list_for_each_entry(fixed_mode, &intel_connector->panel.fixed_modes, head)
|
||||
intel_edp_mso_mode_fixup(intel_connector, fixed_mode);
|
||||
|
||||
/* fallback to VBT if available for eDP */
|
||||
if (!fixed_mode)
|
||||
fixed_mode = intel_panel_vbt_fixed_mode(intel_connector);
|
||||
if (!intel_panel_preferred_fixed_mode(intel_connector))
|
||||
intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
|
||||
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
|
||||
|
@ -5061,16 +5219,13 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
|
|||
pipe_name(pipe));
|
||||
}
|
||||
|
||||
intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
|
||||
intel_panel_init(intel_connector);
|
||||
|
||||
if (!(dev_priv->quirks & QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK))
|
||||
intel_connector->panel.backlight.power = intel_pps_backlight_power;
|
||||
intel_backlight_setup(intel_connector, pipe);
|
||||
|
||||
if (fixed_mode) {
|
||||
drm_connector_set_panel_orientation_with_quirk(connector,
|
||||
dev_priv->vbt.orientation,
|
||||
fixed_mode->hdisplay, fixed_mode->vdisplay);
|
||||
}
|
||||
intel_edp_add_properties(intel_dp);
|
||||
|
||||
return true;
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ static u8 *intel_dp_lttpr_phy_caps(struct intel_dp *intel_dp,
|
|||
}
|
||||
|
||||
static void intel_dp_read_lttpr_phy_caps(struct intel_dp *intel_dp,
|
||||
const u8 dpcd[DP_RECEIVER_CAP_SIZE],
|
||||
enum drm_dp_phy dp_phy)
|
||||
{
|
||||
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
|
||||
|
@ -63,7 +64,7 @@ static void intel_dp_read_lttpr_phy_caps(struct intel_dp *intel_dp,
|
|||
|
||||
intel_dp_phy_name(dp_phy, phy_name, sizeof(phy_name));
|
||||
|
||||
if (drm_dp_read_lttpr_phy_caps(&intel_dp->aux, dp_phy, phy_caps) < 0) {
|
||||
if (drm_dp_read_lttpr_phy_caps(&intel_dp->aux, dpcd, dp_phy, phy_caps) < 0) {
|
||||
drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
|
||||
"[ENCODER:%d:%s][%s] failed to read the PHY caps\n",
|
||||
encoder->base.base.id, encoder->base.name, phy_name);
|
||||
|
@ -77,10 +78,12 @@ static void intel_dp_read_lttpr_phy_caps(struct intel_dp *intel_dp,
|
|||
phy_caps);
|
||||
}
|
||||
|
||||
static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp)
|
||||
static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp,
|
||||
const u8 dpcd[DP_RECEIVER_CAP_SIZE])
|
||||
{
|
||||
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
int ret;
|
||||
|
||||
if (intel_dp_is_edp(intel_dp))
|
||||
return false;
|
||||
|
@ -92,8 +95,9 @@ static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp)
|
|||
if (DISPLAY_VER(i915) < 10 || IS_GEMINILAKE(i915))
|
||||
return false;
|
||||
|
||||
if (drm_dp_read_lttpr_common_caps(&intel_dp->aux,
|
||||
intel_dp->lttpr_common_caps) < 0)
|
||||
ret = drm_dp_read_lttpr_common_caps(&intel_dp->aux, dpcd,
|
||||
intel_dp->lttpr_common_caps);
|
||||
if (ret < 0)
|
||||
goto reset_caps;
|
||||
|
||||
drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
|
||||
|
@ -122,14 +126,14 @@ intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable)
|
|||
return drm_dp_dpcd_write(&intel_dp->aux, DP_PHY_REPEATER_MODE, &val, 1) == 1;
|
||||
}
|
||||
|
||||
static int intel_dp_init_lttpr(struct intel_dp *intel_dp)
|
||||
static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEIVER_CAP_SIZE])
|
||||
{
|
||||
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
int lttpr_count;
|
||||
int i;
|
||||
|
||||
if (!intel_dp_read_lttpr_common_caps(intel_dp))
|
||||
if (!intel_dp_read_lttpr_common_caps(intel_dp, dpcd))
|
||||
return 0;
|
||||
|
||||
lttpr_count = drm_dp_lttpr_count(intel_dp->lttpr_common_caps);
|
||||
|
@ -168,7 +172,7 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp)
|
|||
}
|
||||
|
||||
for (i = 0; i < lttpr_count; i++)
|
||||
intel_dp_read_lttpr_phy_caps(intel_dp, DP_PHY_LTTPR(i));
|
||||
intel_dp_read_lttpr_phy_caps(intel_dp, dpcd, DP_PHY_LTTPR(i));
|
||||
|
||||
return lttpr_count;
|
||||
}
|
||||
|
@ -193,9 +197,18 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp)
|
|||
*/
|
||||
int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp)
|
||||
{
|
||||
int lttpr_count = intel_dp_init_lttpr(intel_dp);
|
||||
u8 dpcd[DP_RECEIVER_CAP_SIZE];
|
||||
int lttpr_count;
|
||||
|
||||
/* The DPTX shall read the DPRX caps after LTTPR detection. */
|
||||
if (drm_dp_read_dpcd_caps(&intel_dp->aux, dpcd))
|
||||
return -EIO;
|
||||
|
||||
lttpr_count = intel_dp_init_lttpr(intel_dp, dpcd);
|
||||
|
||||
/*
|
||||
* The DPTX shall read the DPRX caps after LTTPR detection, so re-read
|
||||
* it here.
|
||||
*/
|
||||
if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd)) {
|
||||
intel_dp_reset_lttpr_common_caps(intel_dp);
|
||||
return -EIO;
|
||||
|
|
|
@ -398,9 +398,8 @@ 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);
|
||||
|
||||
intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
|
||||
}
|
||||
|
||||
static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
|
||||
|
@ -599,8 +598,7 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
|
|||
|
||||
intel_crtc_vblank_on(pipe_config);
|
||||
|
||||
if (pipe_config->has_audio)
|
||||
intel_audio_codec_enable(encoder, pipe_config, conn_state);
|
||||
intel_audio_codec_enable(encoder, pipe_config, conn_state);
|
||||
|
||||
/* Enable hdcp if it's desired */
|
||||
if (conn_state->content_protection ==
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include "intel_crtc.h"
|
||||
#include "intel_de.h"
|
||||
|
@ -253,12 +254,12 @@ static const struct intel_limit ilk_limits_dual_lvds_100m = {
|
|||
|
||||
static const struct intel_limit intel_limits_vlv = {
|
||||
/*
|
||||
* These are the data rate limits (measured in fast clocks)
|
||||
* These are based on the data rate limits (measured in fast clocks)
|
||||
* since those are the strictest limits we have. The fast
|
||||
* clock and actual rate limits are more relaxed, so checking
|
||||
* them would make no difference.
|
||||
*/
|
||||
.dot = { .min = 25000 * 5, .max = 270000 * 5 },
|
||||
.dot = { .min = 25000, .max = 270000 },
|
||||
.vco = { .min = 4000000, .max = 6000000 },
|
||||
.n = { .min = 1, .max = 7 },
|
||||
.m1 = { .min = 2, .max = 3 },
|
||||
|
@ -269,12 +270,12 @@ static const struct intel_limit intel_limits_vlv = {
|
|||
|
||||
static const struct intel_limit intel_limits_chv = {
|
||||
/*
|
||||
* These are the data rate limits (measured in fast clocks)
|
||||
* These are based on the data rate limits (measured in fast clocks)
|
||||
* since those are the strictest limits we have. The fast
|
||||
* clock and actual rate limits are more relaxed, so checking
|
||||
* them would make no difference.
|
||||
*/
|
||||
.dot = { .min = 25000 * 5, .max = 540000 * 5},
|
||||
.dot = { .min = 25000, .max = 540000 },
|
||||
.vco = { .min = 4800000, .max = 6480000 },
|
||||
.n = { .min = 1, .max = 1 },
|
||||
.m1 = { .min = 2, .max = 2 },
|
||||
|
@ -284,8 +285,7 @@ static const struct intel_limit intel_limits_chv = {
|
|||
};
|
||||
|
||||
static const struct intel_limit intel_limits_bxt = {
|
||||
/* FIXME: find real dot limits */
|
||||
.dot = { .min = 0, .max = INT_MAX },
|
||||
.dot = { .min = 25000, .max = 594000 },
|
||||
.vco = { .min = 4800000, .max = 6700000 },
|
||||
.n = { .min = 1, .max = 1 },
|
||||
.m1 = { .min = 2, .max = 2 },
|
||||
|
@ -336,26 +336,26 @@ int i9xx_calc_dpll_params(int refclk, struct dpll *clock)
|
|||
int vlv_calc_dpll_params(int refclk, struct dpll *clock)
|
||||
{
|
||||
clock->m = clock->m1 * clock->m2;
|
||||
clock->p = clock->p1 * clock->p2;
|
||||
clock->p = clock->p1 * clock->p2 * 5;
|
||||
if (WARN_ON(clock->n == 0 || clock->p == 0))
|
||||
return 0;
|
||||
clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
|
||||
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
|
||||
|
||||
return clock->dot / 5;
|
||||
return clock->dot;
|
||||
}
|
||||
|
||||
int chv_calc_dpll_params(int refclk, struct dpll *clock)
|
||||
{
|
||||
clock->m = clock->m1 * clock->m2;
|
||||
clock->p = clock->p1 * clock->p2;
|
||||
clock->p = clock->p1 * clock->p2 * 5;
|
||||
if (WARN_ON(clock->n == 0 || clock->p == 0))
|
||||
return 0;
|
||||
clock->vco = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, clock->m),
|
||||
clock->n << 22);
|
||||
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
|
||||
|
||||
return clock->dot / 5;
|
||||
return clock->dot;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -424,8 +424,7 @@ i9xx_select_p2_div(const struct intel_limit *limit,
|
|||
|
||||
/*
|
||||
* Returns a set of divisors for the desired target clock with the given
|
||||
* refclk, or FALSE. The returned values represent the clock equation:
|
||||
* reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
|
||||
* refclk, or FALSE.
|
||||
*
|
||||
* Target and reference clocks are specified in kHz.
|
||||
*
|
||||
|
@ -483,8 +482,7 @@ i9xx_find_best_dpll(const struct intel_limit *limit,
|
|||
|
||||
/*
|
||||
* Returns a set of divisors for the desired target clock with the given
|
||||
* refclk, or FALSE. The returned values represent the clock equation:
|
||||
* reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
|
||||
* refclk, or FALSE.
|
||||
*
|
||||
* Target and reference clocks are specified in kHz.
|
||||
*
|
||||
|
@ -540,8 +538,7 @@ pnv_find_best_dpll(const struct intel_limit *limit,
|
|||
|
||||
/*
|
||||
* Returns a set of divisors for the desired target clock with the given
|
||||
* refclk, or FALSE. The returned values represent the clock equation:
|
||||
* reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
|
||||
* refclk, or FALSE.
|
||||
*
|
||||
* Target and reference clocks are specified in kHz.
|
||||
*
|
||||
|
@ -640,8 +637,7 @@ static bool vlv_PLL_is_optimal(struct drm_device *dev, int target_freq,
|
|||
|
||||
/*
|
||||
* Returns a set of divisors for the desired target clock with the given
|
||||
* refclk, or FALSE. The returned values represent the clock equation:
|
||||
* reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
|
||||
* refclk, or FALSE.
|
||||
*/
|
||||
static bool
|
||||
vlv_find_best_dpll(const struct intel_limit *limit,
|
||||
|
@ -658,8 +654,6 @@ vlv_find_best_dpll(const struct intel_limit *limit,
|
|||
int max_n = min(limit->n.max, refclk / 19200);
|
||||
bool found = false;
|
||||
|
||||
target *= 5; /* fast clock */
|
||||
|
||||
memset(best_clock, 0, sizeof(*best_clock));
|
||||
|
||||
/* based on hardware requirement, prefer smaller n to precision */
|
||||
|
@ -667,7 +661,7 @@ vlv_find_best_dpll(const struct intel_limit *limit,
|
|||
for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
|
||||
for (clock.p2 = limit->p2.p2_fast; clock.p2 >= limit->p2.p2_slow;
|
||||
clock.p2 -= clock.p2 > 10 ? 2 : 1) {
|
||||
clock.p = clock.p1 * clock.p2;
|
||||
clock.p = clock.p1 * clock.p2 * 5;
|
||||
/* based on hardware requirement, prefer bigger m1,m2 values */
|
||||
for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) {
|
||||
unsigned int ppm;
|
||||
|
@ -701,8 +695,7 @@ vlv_find_best_dpll(const struct intel_limit *limit,
|
|||
|
||||
/*
|
||||
* Returns a set of divisors for the desired target clock with the given
|
||||
* refclk, or FALSE. The returned values represent the clock equation:
|
||||
* reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
|
||||
* refclk, or FALSE.
|
||||
*/
|
||||
static bool
|
||||
chv_find_best_dpll(const struct intel_limit *limit,
|
||||
|
@ -728,7 +721,6 @@ chv_find_best_dpll(const struct intel_limit *limit,
|
|||
*/
|
||||
clock.n = 1;
|
||||
clock.m1 = 2;
|
||||
target *= 5; /* fast clock */
|
||||
|
||||
for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
|
||||
for (clock.p2 = limit->p2.p2_fast;
|
||||
|
@ -736,7 +728,7 @@ chv_find_best_dpll(const struct intel_limit *limit,
|
|||
clock.p2 -= clock.p2 > 10 ? 2 : 1) {
|
||||
unsigned int error_ppm;
|
||||
|
||||
clock.p = clock.p1 * clock.p2;
|
||||
clock.p = clock.p1 * clock.p2 * 5;
|
||||
|
||||
m2 = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(target, clock.p * clock.n) << 22,
|
||||
refclk * clock.m1);
|
||||
|
@ -1945,7 +1937,7 @@ static void assert_pll(struct drm_i915_private *dev_priv,
|
|||
cur_state = intel_de_read(dev_priv, DPLL(pipe)) & DPLL_VCO_ENABLE;
|
||||
I915_STATE_WARN(cur_state != state,
|
||||
"PLL state assertion failure (expected %s, current %s)\n",
|
||||
onoff(state), onoff(cur_state));
|
||||
str_on_off(state), str_on_off(cur_state));
|
||||
}
|
||||
|
||||
void assert_pll_enabled(struct drm_i915_private *i915, enum pipe pipe)
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dpio_phy.h"
|
||||
|
@ -178,13 +180,14 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv,
|
|||
struct intel_dpll_hw_state hw_state;
|
||||
|
||||
if (drm_WARN(&dev_priv->drm, !pll,
|
||||
"asserting DPLL %s with no DPLL\n", onoff(state)))
|
||||
"asserting DPLL %s with no DPLL\n", str_on_off(state)))
|
||||
return;
|
||||
|
||||
cur_state = intel_dpll_get_hw_state(dev_priv, pll, &hw_state);
|
||||
I915_STATE_WARN(cur_state != state,
|
||||
"%s assertion failure (expected %s, current %s)\n",
|
||||
pll->info->name, onoff(state), onoff(cur_state));
|
||||
pll->info->name, str_on_off(state),
|
||||
str_on_off(cur_state));
|
||||
}
|
||||
|
||||
static enum tc_port icl_pll_id_to_tc_port(enum intel_dpll_id id)
|
||||
|
@ -832,7 +835,7 @@ hsw_ddi_calculate_wrpll(int clock /* in Hz */,
|
|||
{
|
||||
u64 freq2k;
|
||||
unsigned p, n2, r2;
|
||||
struct hsw_wrpll_rnp best = { 0, 0, 0 };
|
||||
struct hsw_wrpll_rnp best = {};
|
||||
unsigned budget;
|
||||
|
||||
freq2k = clock / 100;
|
||||
|
@ -1330,13 +1333,6 @@ struct skl_wrpll_context {
|
|||
unsigned int p; /* chosen divider */
|
||||
};
|
||||
|
||||
static void skl_wrpll_context_init(struct skl_wrpll_context *ctx)
|
||||
{
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
ctx->min_deviation = U64_MAX;
|
||||
}
|
||||
|
||||
/* DCO freq must be within +1%/-6% of the DCO central freq */
|
||||
#define SKL_DCO_MAX_PDEVIATION 100
|
||||
#define SKL_DCO_MAX_NDEVIATION 600
|
||||
|
@ -1502,28 +1498,28 @@ skl_ddi_calculate_wrpll(int clock /* in Hz */,
|
|||
int ref_clock,
|
||||
struct skl_wrpll_params *wrpll_params)
|
||||
{
|
||||
u64 afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
|
||||
u64 dco_central_freq[3] = { 8400000000ULL,
|
||||
9000000000ULL,
|
||||
9600000000ULL };
|
||||
static const int even_dividers[] = { 4, 6, 8, 10, 12, 14, 16, 18, 20,
|
||||
24, 28, 30, 32, 36, 40, 42, 44,
|
||||
48, 52, 54, 56, 60, 64, 66, 68,
|
||||
70, 72, 76, 78, 80, 84, 88, 90,
|
||||
92, 96, 98 };
|
||||
static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 };
|
||||
static const u64 dco_central_freq[3] = { 8400000000ULL,
|
||||
9000000000ULL,
|
||||
9600000000ULL };
|
||||
static const u8 even_dividers[] = { 4, 6, 8, 10, 12, 14, 16, 18, 20,
|
||||
24, 28, 30, 32, 36, 40, 42, 44,
|
||||
48, 52, 54, 56, 60, 64, 66, 68,
|
||||
70, 72, 76, 78, 80, 84, 88, 90,
|
||||
92, 96, 98 };
|
||||
static const u8 odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 };
|
||||
static const struct {
|
||||
const int *list;
|
||||
const u8 *list;
|
||||
int n_dividers;
|
||||
} dividers[] = {
|
||||
{ even_dividers, ARRAY_SIZE(even_dividers) },
|
||||
{ odd_dividers, ARRAY_SIZE(odd_dividers) },
|
||||
};
|
||||
struct skl_wrpll_context ctx;
|
||||
struct skl_wrpll_context ctx = {
|
||||
.min_deviation = U64_MAX,
|
||||
};
|
||||
unsigned int dco, d, i;
|
||||
unsigned int p0, p1, p2;
|
||||
|
||||
skl_wrpll_context_init(&ctx);
|
||||
u64 afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
|
||||
|
||||
for (d = 0; d < ARRAY_SIZE(dividers); d++) {
|
||||
for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) {
|
||||
|
@ -1574,8 +1570,8 @@ skl_ddi_calculate_wrpll(int clock /* in Hz */,
|
|||
static bool skl_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
|
||||
struct skl_wrpll_params wrpll_params = {};
|
||||
u32 ctrl1, cfgcr1, cfgcr2;
|
||||
struct skl_wrpll_params wrpll_params = { 0, };
|
||||
|
||||
/*
|
||||
* See comment in intel_dpll_hw_state to understand why we always use 0
|
||||
|
@ -1902,7 +1898,7 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
|
|||
|
||||
/* Write M2 integer */
|
||||
temp = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 0));
|
||||
temp &= ~PORT_PLL_M2_MASK;
|
||||
temp &= ~PORT_PLL_M2_INT_MASK;
|
||||
temp |= pll->state.hw_state.pll0;
|
||||
intel_de_write(dev_priv, BXT_PORT_PLL(phy, ch, 0), temp);
|
||||
|
||||
|
@ -2038,7 +2034,7 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
|
|||
hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
|
||||
|
||||
hw_state->pll0 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 0));
|
||||
hw_state->pll0 &= PORT_PLL_M2_MASK;
|
||||
hw_state->pll0 &= PORT_PLL_M2_INT_MASK;
|
||||
|
||||
hw_state->pll1 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 1));
|
||||
hw_state->pll1 &= PORT_PLL_N_MASK;
|
||||
|
@ -2087,82 +2083,64 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* bxt clock parameters */
|
||||
struct bxt_clk_div {
|
||||
int clock;
|
||||
u32 p1;
|
||||
u32 p2;
|
||||
u32 m2_int;
|
||||
u32 m2_frac;
|
||||
bool m2_frac_en;
|
||||
u32 n;
|
||||
|
||||
int vco;
|
||||
};
|
||||
|
||||
/* pre-calculated values for DP linkrates */
|
||||
static const struct bxt_clk_div bxt_dp_clk_val[] = {
|
||||
{162000, 4, 2, 32, 1677722, 1, 1},
|
||||
{270000, 4, 1, 27, 0, 0, 1},
|
||||
{540000, 2, 1, 27, 0, 0, 1},
|
||||
{216000, 3, 2, 32, 1677722, 1, 1},
|
||||
{243000, 4, 1, 24, 1258291, 1, 1},
|
||||
{324000, 4, 1, 32, 1677722, 1, 1},
|
||||
{432000, 3, 1, 32, 1677722, 1, 1}
|
||||
static const struct dpll bxt_dp_clk_val[] = {
|
||||
/* m2 is .22 binary fixed point */
|
||||
{ .dot = 162000, .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a /* 32.4 */ },
|
||||
{ .dot = 270000, .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 /* 27.0 */ },
|
||||
{ .dot = 540000, .p1 = 2, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 /* 27.0 */ },
|
||||
{ .dot = 216000, .p1 = 3, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a /* 32.4 */ },
|
||||
{ .dot = 243000, .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6133333 /* 24.3 */ },
|
||||
{ .dot = 324000, .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x819999a /* 32.4 */ },
|
||||
{ .dot = 432000, .p1 = 3, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x819999a /* 32.4 */ },
|
||||
};
|
||||
|
||||
static bool
|
||||
bxt_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state,
|
||||
struct bxt_clk_div *clk_div)
|
||||
struct dpll *clk_div)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct dpll best_clock;
|
||||
|
||||
/* Calculate HDMI div */
|
||||
/*
|
||||
* FIXME: tie the following calculation into
|
||||
* i9xx_crtc_compute_clock
|
||||
*/
|
||||
if (!bxt_find_best_dpll(crtc_state, &best_clock)) {
|
||||
if (!bxt_find_best_dpll(crtc_state, clk_div)) {
|
||||
drm_dbg(&i915->drm, "no PLL dividers found for clock %d pipe %c\n",
|
||||
crtc_state->port_clock,
|
||||
pipe_name(crtc->pipe));
|
||||
return false;
|
||||
}
|
||||
|
||||
clk_div->p1 = best_clock.p1;
|
||||
clk_div->p2 = best_clock.p2;
|
||||
drm_WARN_ON(&i915->drm, best_clock.m1 != 2);
|
||||
clk_div->n = best_clock.n;
|
||||
clk_div->m2_int = best_clock.m2 >> 22;
|
||||
clk_div->m2_frac = best_clock.m2 & ((1 << 22) - 1);
|
||||
clk_div->m2_frac_en = clk_div->m2_frac != 0;
|
||||
|
||||
clk_div->vco = best_clock.vco;
|
||||
drm_WARN_ON(&i915->drm, clk_div->m1 != 2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void bxt_ddi_dp_pll_dividers(struct intel_crtc_state *crtc_state,
|
||||
struct bxt_clk_div *clk_div)
|
||||
struct dpll *clk_div)
|
||||
{
|
||||
int clock = crtc_state->port_clock;
|
||||
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
|
||||
int i;
|
||||
|
||||
*clk_div = bxt_dp_clk_val[0];
|
||||
for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) {
|
||||
if (bxt_dp_clk_val[i].clock == clock) {
|
||||
if (crtc_state->port_clock == bxt_dp_clk_val[i].dot) {
|
||||
*clk_div = bxt_dp_clk_val[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
clk_div->vco = clock * 10 / 2 * clk_div->p1 * clk_div->p2;
|
||||
chv_calc_dpll_params(i915->dpll.ref_clks.nssc, clk_div);
|
||||
|
||||
drm_WARN_ON(&i915->drm, clk_div->vco == 0 ||
|
||||
clk_div->dot != crtc_state->port_clock);
|
||||
}
|
||||
|
||||
static bool bxt_ddi_set_dpll_hw_state(struct intel_crtc_state *crtc_state,
|
||||
const struct bxt_clk_div *clk_div)
|
||||
const struct dpll *clk_div)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
|
||||
struct intel_dpll_hw_state *dpll_hw_state = &crtc_state->dpll_hw_state;
|
||||
|
@ -2206,23 +2184,23 @@ static bool bxt_ddi_set_dpll_hw_state(struct intel_crtc_state *crtc_state,
|
|||
lanestagger = 0x02;
|
||||
|
||||
dpll_hw_state->ebb0 = PORT_PLL_P1(clk_div->p1) | PORT_PLL_P2(clk_div->p2);
|
||||
dpll_hw_state->pll0 = clk_div->m2_int;
|
||||
dpll_hw_state->pll0 = PORT_PLL_M2_INT(clk_div->m2 >> 22);
|
||||
dpll_hw_state->pll1 = PORT_PLL_N(clk_div->n);
|
||||
dpll_hw_state->pll2 = clk_div->m2_frac;
|
||||
dpll_hw_state->pll2 = PORT_PLL_M2_FRAC(clk_div->m2 & 0x3fffff);
|
||||
|
||||
if (clk_div->m2_frac_en)
|
||||
if (clk_div->m2 & 0x3fffff)
|
||||
dpll_hw_state->pll3 = PORT_PLL_M2_FRAC_ENABLE;
|
||||
|
||||
dpll_hw_state->pll6 = prop_coef | PORT_PLL_INT_COEFF(int_coef);
|
||||
dpll_hw_state->pll6 |= PORT_PLL_GAIN_CTL(gain_ctl);
|
||||
dpll_hw_state->pll6 = PORT_PLL_PROP_COEFF(prop_coef) |
|
||||
PORT_PLL_INT_COEFF(int_coef) |
|
||||
PORT_PLL_GAIN_CTL(gain_ctl);
|
||||
|
||||
dpll_hw_state->pll8 = targ_cnt;
|
||||
dpll_hw_state->pll8 = PORT_PLL_TARGET_CNT(targ_cnt);
|
||||
|
||||
dpll_hw_state->pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT;
|
||||
dpll_hw_state->pll9 = PORT_PLL_LOCK_THRESHOLD(5);
|
||||
|
||||
dpll_hw_state->pll10 =
|
||||
PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT)
|
||||
| PORT_PLL_DCO_AMP_OVR_EN_H;
|
||||
dpll_hw_state->pll10 = PORT_PLL_DCO_AMP(15) |
|
||||
PORT_PLL_DCO_AMP_OVR_EN_H;
|
||||
|
||||
dpll_hw_state->ebb4 = PORT_PLL_10BIT_CLK_ENABLE;
|
||||
|
||||
|
@ -2234,7 +2212,7 @@ static bool bxt_ddi_set_dpll_hw_state(struct intel_crtc_state *crtc_state,
|
|||
static bool
|
||||
bxt_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct bxt_clk_div clk_div = {};
|
||||
struct dpll clk_div = {};
|
||||
|
||||
bxt_ddi_dp_pll_dividers(crtc_state, &clk_div);
|
||||
|
||||
|
@ -2244,7 +2222,7 @@ bxt_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state)
|
|||
static bool
|
||||
bxt_ddi_hdmi_set_dpll_hw_state(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct bxt_clk_div clk_div = {};
|
||||
struct dpll clk_div = {};
|
||||
|
||||
bxt_ddi_hdmi_pll_dividers(crtc_state, &clk_div);
|
||||
|
||||
|
@ -2258,12 +2236,12 @@ static int bxt_ddi_pll_get_freq(struct drm_i915_private *i915,
|
|||
struct dpll clock;
|
||||
|
||||
clock.m1 = 2;
|
||||
clock.m2 = (pll_state->pll0 & PORT_PLL_M2_MASK) << 22;
|
||||
clock.m2 = REG_FIELD_GET(PORT_PLL_M2_INT_MASK, pll_state->pll0) << 22;
|
||||
if (pll_state->pll3 & PORT_PLL_M2_FRAC_ENABLE)
|
||||
clock.m2 |= pll_state->pll2 & PORT_PLL_M2_FRAC_MASK;
|
||||
clock.n = (pll_state->pll1 & PORT_PLL_N_MASK) >> PORT_PLL_N_SHIFT;
|
||||
clock.p1 = (pll_state->ebb0 & PORT_PLL_P1_MASK) >> PORT_PLL_P1_SHIFT;
|
||||
clock.p2 = (pll_state->ebb0 & PORT_PLL_P2_MASK) >> PORT_PLL_P2_SHIFT;
|
||||
clock.m2 |= REG_FIELD_GET(PORT_PLL_M2_FRAC_MASK, pll_state->pll2);
|
||||
clock.n = REG_FIELD_GET(PORT_PLL_N_MASK, pll_state->pll1);
|
||||
clock.p1 = REG_FIELD_GET(PORT_PLL_P1_MASK, pll_state->ebb0);
|
||||
clock.p2 = REG_FIELD_GET(PORT_PLL_P2_MASK, pll_state->ebb0);
|
||||
|
||||
return chv_calc_dpll_params(i915->dpll.ref_clks.nssc, &clock);
|
||||
}
|
||||
|
@ -2758,8 +2736,8 @@ static bool icl_mg_pll_find_divisors(int clock_khz, bool is_dp, bool use_ssc,
|
|||
struct intel_dpll_hw_state *state,
|
||||
bool is_dkl)
|
||||
{
|
||||
static const u8 div1_vals[] = { 7, 5, 3, 2 };
|
||||
u32 dco_min_freq, dco_max_freq;
|
||||
int div1_vals[] = {7, 5, 3, 2};
|
||||
unsigned int i;
|
||||
int div2;
|
||||
|
||||
|
|
|
@ -249,7 +249,7 @@ intel_dpt_create(struct intel_framebuffer *fb)
|
|||
size = round_up(size * sizeof(gen8_pte_t), I915_GTT_PAGE_SIZE);
|
||||
|
||||
if (HAS_LMEM(i915))
|
||||
dpt_obj = i915_gem_object_create_lmem(i915, size, 0);
|
||||
dpt_obj = i915_gem_object_create_lmem(i915, size, I915_BO_ALLOC_CONTIGUOUS);
|
||||
else
|
||||
dpt_obj = i915_gem_object_create_stolen(i915, size);
|
||||
if (IS_ERR(dpt_obj))
|
||||
|
|
|
@ -47,74 +47,36 @@
|
|||
* requested by userspace.
|
||||
*/
|
||||
|
||||
static bool can_enable_drrs(struct intel_connector *connector,
|
||||
const struct intel_crtc_state *pipe_config)
|
||||
const char *intel_drrs_type_str(enum drrs_type drrs_type)
|
||||
{
|
||||
const struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
static const char * const str[] = {
|
||||
[DRRS_TYPE_NONE] = "none",
|
||||
[DRRS_TYPE_STATIC] = "static",
|
||||
[DRRS_TYPE_SEAMLESS] = "seamless",
|
||||
};
|
||||
|
||||
if (pipe_config->vrr.enable)
|
||||
return false;
|
||||
if (drrs_type >= ARRAY_SIZE(str))
|
||||
return "<invalid>";
|
||||
|
||||
/*
|
||||
* DRRS and PSR can't be enable together, so giving preference to PSR
|
||||
* as it allows more power-savings by complete shutting down display,
|
||||
* so to guarantee this, intel_drrs_compute_config() must be called
|
||||
* after intel_psr_compute_config().
|
||||
*/
|
||||
if (pipe_config->has_psr)
|
||||
return false;
|
||||
|
||||
return connector->panel.downclock_mode &&
|
||||
i915->drrs.type == SEAMLESS_DRRS_SUPPORT;
|
||||
}
|
||||
|
||||
void
|
||||
intel_drrs_compute_config(struct intel_dp *intel_dp,
|
||||
struct intel_crtc_state *pipe_config,
|
||||
int output_bpp, bool constant_n)
|
||||
{
|
||||
struct intel_connector *connector = intel_dp->attached_connector;
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
int pixel_clock;
|
||||
|
||||
if (!can_enable_drrs(connector, pipe_config)) {
|
||||
if (intel_cpu_transcoder_has_m2_n2(i915, pipe_config->cpu_transcoder))
|
||||
intel_zero_m_n(&pipe_config->dp_m2_n2);
|
||||
return;
|
||||
}
|
||||
|
||||
pipe_config->has_drrs = true;
|
||||
|
||||
pixel_clock = connector->panel.downclock_mode->clock;
|
||||
if (pipe_config->splitter.enable)
|
||||
pixel_clock /= pipe_config->splitter.link_count;
|
||||
|
||||
intel_link_compute_m_n(output_bpp, pipe_config->lane_count, pixel_clock,
|
||||
pipe_config->port_clock, &pipe_config->dp_m2_n2,
|
||||
constant_n, pipe_config->fec_enable);
|
||||
|
||||
/* FIXME: abstract this better */
|
||||
if (pipe_config->splitter.enable)
|
||||
pipe_config->dp_m2_n2.data_m *= pipe_config->splitter.link_count;
|
||||
return str[drrs_type];
|
||||
}
|
||||
|
||||
static void
|
||||
intel_drrs_set_refresh_rate_pipeconf(const struct intel_crtc_state *crtc_state,
|
||||
enum drrs_refresh_rate_type refresh_type)
|
||||
intel_drrs_set_refresh_rate_pipeconf(struct intel_crtc *crtc,
|
||||
enum drrs_refresh_rate refresh_rate)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
||||
enum transcoder cpu_transcoder = crtc->drrs.cpu_transcoder;
|
||||
u32 val, bit;
|
||||
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
bit = PIPECONF_EDP_RR_MODE_SWITCH_VLV;
|
||||
bit = PIPECONF_REFRESH_RATE_ALT_VLV;
|
||||
else
|
||||
bit = PIPECONF_EDP_RR_MODE_SWITCH;
|
||||
bit = PIPECONF_REFRESH_RATE_ALT_ILK;
|
||||
|
||||
val = intel_de_read(dev_priv, PIPECONF(cpu_transcoder));
|
||||
|
||||
if (refresh_type == DRRS_LOW_RR)
|
||||
if (refresh_rate == DRRS_REFRESH_RATE_LOW)
|
||||
val |= bit;
|
||||
else
|
||||
val &= ~bit;
|
||||
|
@ -123,244 +85,171 @@ intel_drrs_set_refresh_rate_pipeconf(const struct intel_crtc_state *crtc_state,
|
|||
}
|
||||
|
||||
static void
|
||||
intel_drrs_set_refresh_rate_m_n(const struct intel_crtc_state *crtc_state,
|
||||
enum drrs_refresh_rate_type refresh_type)
|
||||
intel_drrs_set_refresh_rate_m_n(struct intel_crtc *crtc,
|
||||
enum drrs_refresh_rate refresh_rate)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
||||
intel_cpu_transcoder_set_m1_n1(crtc, crtc_state->cpu_transcoder,
|
||||
refresh_type == DRRS_LOW_RR ?
|
||||
&crtc_state->dp_m2_n2 : &crtc_state->dp_m_n);
|
||||
intel_cpu_transcoder_set_m1_n1(crtc, crtc->drrs.cpu_transcoder,
|
||||
refresh_rate == DRRS_REFRESH_RATE_LOW ?
|
||||
&crtc->drrs.m2_n2 : &crtc->drrs.m_n);
|
||||
}
|
||||
|
||||
static void intel_drrs_set_state(struct drm_i915_private *dev_priv,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
enum drrs_refresh_rate_type refresh_type)
|
||||
bool intel_drrs_is_active(struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_dp *intel_dp = dev_priv->drrs.dp;
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_display_mode *mode;
|
||||
return crtc->drrs.cpu_transcoder != INVALID_TRANSCODER;
|
||||
}
|
||||
|
||||
if (!intel_dp) {
|
||||
drm_dbg_kms(&dev_priv->drm, "DRRS not supported.\n");
|
||||
return;
|
||||
}
|
||||
static void intel_drrs_set_state(struct intel_crtc *crtc,
|
||||
enum drrs_refresh_rate refresh_rate)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
|
||||
if (!crtc) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"DRRS: intel_crtc not initialized\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev_priv->drrs.type < SEAMLESS_DRRS_SUPPORT) {
|
||||
drm_dbg_kms(&dev_priv->drm, "Only Seamless DRRS supported.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (refresh_type == dev_priv->drrs.refresh_rate_type)
|
||||
if (refresh_rate == crtc->drrs.refresh_rate)
|
||||
return;
|
||||
|
||||
if (!crtc_state->hw.active) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"eDP encoder disabled. CRTC not Active\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 8 && !IS_CHERRYVIEW(dev_priv))
|
||||
intel_drrs_set_refresh_rate_m_n(crtc_state, refresh_type);
|
||||
else if (DISPLAY_VER(dev_priv) > 6)
|
||||
intel_drrs_set_refresh_rate_pipeconf(crtc_state, refresh_type);
|
||||
|
||||
dev_priv->drrs.refresh_rate_type = refresh_type;
|
||||
|
||||
if (refresh_type == DRRS_LOW_RR)
|
||||
mode = intel_dp->attached_connector->panel.downclock_mode;
|
||||
if (intel_cpu_transcoder_has_m2_n2(dev_priv, crtc->drrs.cpu_transcoder))
|
||||
intel_drrs_set_refresh_rate_pipeconf(crtc, refresh_rate);
|
||||
else
|
||||
mode = intel_dp->attached_connector->panel.fixed_mode;
|
||||
drm_dbg_kms(&dev_priv->drm, "eDP Refresh Rate set to : %dHz\n",
|
||||
drm_mode_vrefresh(mode));
|
||||
intel_drrs_set_refresh_rate_m_n(crtc, refresh_rate);
|
||||
|
||||
crtc->drrs.refresh_rate = refresh_rate;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_drrs_enable_locked(struct intel_dp *intel_dp)
|
||||
static void intel_drrs_schedule_work(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
mod_delayed_work(system_wq, &crtc->drrs.work, msecs_to_jiffies(1000));
|
||||
}
|
||||
|
||||
dev_priv->drrs.busy_frontbuffer_bits = 0;
|
||||
dev_priv->drrs.dp = intel_dp;
|
||||
static unsigned int intel_drrs_frontbuffer_bits(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
unsigned int frontbuffer_bits;
|
||||
|
||||
frontbuffer_bits = INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe);
|
||||
|
||||
for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc,
|
||||
crtc_state->bigjoiner_pipes)
|
||||
frontbuffer_bits |= INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe);
|
||||
|
||||
return frontbuffer_bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_drrs_enable - init drrs struct if supported
|
||||
* @intel_dp: DP struct
|
||||
* @crtc_state: A pointer to the active crtc state.
|
||||
* intel_drrs_activate - activate DRRS
|
||||
* @crtc_state: the crtc state
|
||||
*
|
||||
* Initializes frontbuffer_bits and drrs.dp
|
||||
* Activates DRRS on the crtc.
|
||||
*/
|
||||
void intel_drrs_enable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
void intel_drrs_activate(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
||||
if (!crtc_state->has_drrs)
|
||||
return;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "Enabling DRRS\n");
|
||||
if (!crtc_state->hw.active)
|
||||
return;
|
||||
|
||||
mutex_lock(&dev_priv->drrs.mutex);
|
||||
if (intel_crtc_is_bigjoiner_slave(crtc_state))
|
||||
return;
|
||||
|
||||
if (dev_priv->drrs.dp) {
|
||||
drm_warn(&dev_priv->drm, "DRRS already enabled\n");
|
||||
goto unlock;
|
||||
}
|
||||
mutex_lock(&crtc->drrs.mutex);
|
||||
|
||||
intel_drrs_enable_locked(intel_dp);
|
||||
crtc->drrs.cpu_transcoder = crtc_state->cpu_transcoder;
|
||||
crtc->drrs.m_n = crtc_state->dp_m_n;
|
||||
crtc->drrs.m2_n2 = crtc_state->dp_m2_n2;
|
||||
crtc->drrs.frontbuffer_bits = intel_drrs_frontbuffer_bits(crtc_state);
|
||||
crtc->drrs.busy_frontbuffer_bits = 0;
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
}
|
||||
intel_drrs_schedule_work(crtc);
|
||||
|
||||
static void
|
||||
intel_drrs_disable_locked(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
|
||||
intel_drrs_set_state(dev_priv, crtc_state, DRRS_HIGH_RR);
|
||||
dev_priv->drrs.dp = NULL;
|
||||
mutex_unlock(&crtc->drrs.mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_drrs_disable - Disable DRRS
|
||||
* @intel_dp: DP struct
|
||||
* @old_crtc_state: Pointer to old crtc_state.
|
||||
* intel_drrs_deactivate - deactivate DRRS
|
||||
* @old_crtc_state: the old crtc state
|
||||
*
|
||||
* Deactivates DRRS on the crtc.
|
||||
*/
|
||||
void intel_drrs_disable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *old_crtc_state)
|
||||
void intel_drrs_deactivate(const struct intel_crtc_state *old_crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
|
||||
|
||||
if (!old_crtc_state->has_drrs)
|
||||
return;
|
||||
|
||||
mutex_lock(&dev_priv->drrs.mutex);
|
||||
if (!dev_priv->drrs.dp) {
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
intel_drrs_disable_locked(intel_dp, old_crtc_state);
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
|
||||
cancel_delayed_work_sync(&dev_priv->drrs.work);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_drrs_update - Update DRRS state
|
||||
* @intel_dp: Intel DP
|
||||
* @crtc_state: new CRTC state
|
||||
*
|
||||
* This function will update DRRS states, disabling or enabling DRRS when
|
||||
* executing fastsets. For full modeset, intel_drrs_disable() and
|
||||
* intel_drrs_enable() should be called instead.
|
||||
*/
|
||||
void
|
||||
intel_drrs_update(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
|
||||
if (dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT)
|
||||
if (!old_crtc_state->hw.active)
|
||||
return;
|
||||
|
||||
mutex_lock(&dev_priv->drrs.mutex);
|
||||
if (intel_crtc_is_bigjoiner_slave(old_crtc_state))
|
||||
return;
|
||||
|
||||
/* New state matches current one? */
|
||||
if (crtc_state->has_drrs == !!dev_priv->drrs.dp)
|
||||
goto unlock;
|
||||
mutex_lock(&crtc->drrs.mutex);
|
||||
|
||||
if (crtc_state->has_drrs)
|
||||
intel_drrs_enable_locked(intel_dp);
|
||||
else
|
||||
intel_drrs_disable_locked(intel_dp, crtc_state);
|
||||
if (intel_drrs_is_active(crtc))
|
||||
intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_HIGH);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
crtc->drrs.cpu_transcoder = INVALID_TRANSCODER;
|
||||
crtc->drrs.frontbuffer_bits = 0;
|
||||
crtc->drrs.busy_frontbuffer_bits = 0;
|
||||
|
||||
mutex_unlock(&crtc->drrs.mutex);
|
||||
|
||||
cancel_delayed_work_sync(&crtc->drrs.work);
|
||||
}
|
||||
|
||||
static void intel_drrs_downclock_work(struct work_struct *work)
|
||||
{
|
||||
struct drm_i915_private *dev_priv =
|
||||
container_of(work, typeof(*dev_priv), drrs.work.work);
|
||||
struct intel_dp *intel_dp;
|
||||
struct drm_crtc *crtc;
|
||||
struct intel_crtc *crtc = container_of(work, typeof(*crtc), drrs.work.work);
|
||||
|
||||
mutex_lock(&dev_priv->drrs.mutex);
|
||||
mutex_lock(&crtc->drrs.mutex);
|
||||
|
||||
intel_dp = dev_priv->drrs.dp;
|
||||
if (intel_drrs_is_active(crtc) && !crtc->drrs.busy_frontbuffer_bits)
|
||||
intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_LOW);
|
||||
|
||||
if (!intel_dp)
|
||||
goto unlock;
|
||||
|
||||
/*
|
||||
* The delayed work can race with an invalidate hence we need to
|
||||
* recheck.
|
||||
*/
|
||||
|
||||
if (dev_priv->drrs.busy_frontbuffer_bits)
|
||||
goto unlock;
|
||||
|
||||
crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
|
||||
intel_drrs_set_state(dev_priv, to_intel_crtc(crtc)->config, DRRS_LOW_RR);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
mutex_unlock(&crtc->drrs.mutex);
|
||||
}
|
||||
|
||||
static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv,
|
||||
unsigned int frontbuffer_bits,
|
||||
unsigned int all_frontbuffer_bits,
|
||||
bool invalidate)
|
||||
{
|
||||
struct intel_dp *intel_dp;
|
||||
struct drm_crtc *crtc;
|
||||
enum pipe pipe;
|
||||
struct intel_crtc *crtc;
|
||||
|
||||
if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED)
|
||||
if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS)
|
||||
return;
|
||||
|
||||
cancel_delayed_work(&dev_priv->drrs.work);
|
||||
for_each_intel_crtc(&dev_priv->drm, crtc) {
|
||||
unsigned int frontbuffer_bits;
|
||||
|
||||
mutex_lock(&dev_priv->drrs.mutex);
|
||||
mutex_lock(&crtc->drrs.mutex);
|
||||
|
||||
intel_dp = dev_priv->drrs.dp;
|
||||
if (!intel_dp) {
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
return;
|
||||
frontbuffer_bits = all_frontbuffer_bits & crtc->drrs.frontbuffer_bits;
|
||||
if (!frontbuffer_bits) {
|
||||
mutex_unlock(&crtc->drrs.mutex);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (invalidate)
|
||||
crtc->drrs.busy_frontbuffer_bits |= frontbuffer_bits;
|
||||
else
|
||||
crtc->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits;
|
||||
|
||||
/* flush/invalidate means busy screen hence upclock */
|
||||
intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_HIGH);
|
||||
|
||||
/*
|
||||
* flush also means no more activity hence schedule downclock, if all
|
||||
* other fbs are quiescent too
|
||||
*/
|
||||
if (!crtc->drrs.busy_frontbuffer_bits)
|
||||
intel_drrs_schedule_work(crtc);
|
||||
else
|
||||
cancel_delayed_work(&crtc->drrs.work);
|
||||
|
||||
mutex_unlock(&crtc->drrs.mutex);
|
||||
}
|
||||
|
||||
crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
|
||||
pipe = to_intel_crtc(crtc)->pipe;
|
||||
|
||||
frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
|
||||
if (invalidate)
|
||||
dev_priv->drrs.busy_frontbuffer_bits |= frontbuffer_bits;
|
||||
else
|
||||
dev_priv->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits;
|
||||
|
||||
/* flush/invalidate means busy screen hence upclock */
|
||||
if (frontbuffer_bits)
|
||||
intel_drrs_set_state(dev_priv, to_intel_crtc(crtc)->config,
|
||||
DRRS_HIGH_RR);
|
||||
|
||||
/*
|
||||
* flush also means no more activity hence schedule downclock, if all
|
||||
* other fbs are quiescent too
|
||||
*/
|
||||
if (!invalidate && !dev_priv->drrs.busy_frontbuffer_bits)
|
||||
schedule_delayed_work(&dev_priv->drrs.work,
|
||||
msecs_to_jiffies(1000));
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -397,68 +286,17 @@ void intel_drrs_flush(struct drm_i915_private *dev_priv,
|
|||
intel_drrs_frontbuffer_update(dev_priv, frontbuffer_bits, false);
|
||||
}
|
||||
|
||||
void intel_drrs_page_flip(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
|
||||
unsigned int frontbuffer_bits = INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe);
|
||||
|
||||
intel_drrs_frontbuffer_update(dev_priv, frontbuffer_bits, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_drrs_init - Init basic DRRS work and mutex.
|
||||
* @connector: eDP connector
|
||||
* @fixed_mode: preferred mode of panel
|
||||
* intel_crtc_drrs_init - Init DRRS for CRTC
|
||||
* @crtc: crtc
|
||||
*
|
||||
* This function is called only once at driver load to initialize basic
|
||||
* This function is called only once at driver load to initialize basic
|
||||
* DRRS stuff.
|
||||
*
|
||||
* Returns:
|
||||
* Downclock mode if panel supports it, else return NULL.
|
||||
* DRRS support is determined by the presence of downclock mode (apart
|
||||
* from VBT setting).
|
||||
*/
|
||||
struct drm_display_mode *
|
||||
intel_drrs_init(struct intel_connector *connector,
|
||||
struct drm_display_mode *fixed_mode)
|
||||
void intel_crtc_drrs_init(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_encoder *encoder = connector->encoder;
|
||||
struct drm_display_mode *downclock_mode = NULL;
|
||||
|
||||
INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_drrs_downclock_work);
|
||||
mutex_init(&dev_priv->drrs.mutex);
|
||||
|
||||
if (DISPLAY_VER(dev_priv) <= 6) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"DRRS supported for Gen7 and above\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((DISPLAY_VER(dev_priv) < 8 && !HAS_GMCH(dev_priv)) &&
|
||||
encoder->port != PORT_A) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"DRRS only supported on eDP port A\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) {
|
||||
drm_dbg_kms(&dev_priv->drm, "VBT doesn't support DRRS\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
downclock_mode = intel_panel_edid_downclock_mode(connector, fixed_mode);
|
||||
if (!downclock_mode) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Downclock mode is not found. DRRS not supported\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dev_priv->drrs.type = dev_priv->vbt.drrs_type;
|
||||
|
||||
dev_priv->drrs.refresh_rate_type = DRRS_HIGH_RR;
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"seamless DRRS supported for eDP panel.\n");
|
||||
return downclock_mode;
|
||||
INIT_DELAYED_WORK(&crtc->drrs.work, intel_drrs_downclock_work);
|
||||
mutex_init(&crtc->drrs.mutex);
|
||||
crtc->drrs.cpu_transcoder = INVALID_TRANSCODER;
|
||||
}
|
||||
|
|
|
@ -8,29 +8,21 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
|
||||
enum drrs_type;
|
||||
struct drm_i915_private;
|
||||
struct intel_atomic_state;
|
||||
struct intel_crtc;
|
||||
struct intel_crtc_state;
|
||||
struct intel_connector;
|
||||
struct intel_dp;
|
||||
|
||||
void intel_drrs_enable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void intel_drrs_disable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void intel_drrs_update(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
const char *intel_drrs_type_str(enum drrs_type drrs_type);
|
||||
bool intel_drrs_is_active(struct intel_crtc *crtc);
|
||||
void intel_drrs_activate(const struct intel_crtc_state *crtc_state);
|
||||
void intel_drrs_deactivate(const struct intel_crtc_state *crtc_state);
|
||||
void intel_drrs_invalidate(struct drm_i915_private *dev_priv,
|
||||
unsigned int frontbuffer_bits);
|
||||
void intel_drrs_flush(struct drm_i915_private *dev_priv,
|
||||
unsigned int frontbuffer_bits);
|
||||
void intel_drrs_page_flip(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc);
|
||||
void intel_drrs_compute_config(struct intel_dp *intel_dp,
|
||||
struct intel_crtc_state *pipe_config,
|
||||
int output_bpp, bool constant_n);
|
||||
struct drm_display_mode *intel_drrs_init(struct intel_connector *connector,
|
||||
struct drm_display_mode *fixed_mode);
|
||||
void intel_crtc_drrs_init(struct intel_crtc *crtc);
|
||||
|
||||
#endif /* __INTEL_DRRS_H__ */
|
||||
|
|
|
@ -283,14 +283,12 @@ void intel_dsb_prepare(struct intel_crtc_state *crtc_state)
|
|||
|
||||
obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE);
|
||||
if (IS_ERR(obj)) {
|
||||
drm_err(&i915->drm, "Gem object creation failed\n");
|
||||
kfree(dsb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
|
||||
if (IS_ERR(vma)) {
|
||||
drm_err(&i915->drm, "Vma creation failed\n");
|
||||
i915_gem_object_put(obj);
|
||||
kfree(dsb);
|
||||
goto out;
|
||||
|
@ -298,7 +296,6 @@ void intel_dsb_prepare(struct intel_crtc_state *crtc_state)
|
|||
|
||||
buf = i915_gem_object_pin_map_unlocked(vma->obj, I915_MAP_WC);
|
||||
if (IS_ERR(buf)) {
|
||||
drm_err(&i915->drm, "Command buffer creation failed\n");
|
||||
i915_vma_unpin_and_release(&vma, I915_VMA_RELEASE_MAP);
|
||||
kfree(dsb);
|
||||
goto out;
|
||||
|
@ -311,6 +308,10 @@ void intel_dsb_prepare(struct intel_crtc_state *crtc_state)
|
|||
dsb->ins_start_offset = 0;
|
||||
crtc_state->dsb = dsb;
|
||||
out:
|
||||
if (!crtc_state->dsb)
|
||||
drm_info(&i915->drm,
|
||||
"DSB queue setup failed, will fallback to MMIO for display HW programming\n");
|
||||
|
||||
intel_runtime_pm_put(&i915->runtime_pm, wakeref);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,26 +34,7 @@ int intel_dsi_tlpx_ns(const struct intel_dsi *intel_dsi)
|
|||
|
||||
int intel_dsi_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(connector->dev);
|
||||
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
drm_dbg_kms(&i915->drm, "\n");
|
||||
|
||||
if (!intel_connector->panel.fixed_mode) {
|
||||
drm_dbg_kms(&i915->drm, "no fixed mode\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev,
|
||||
intel_connector->panel.fixed_mode);
|
||||
if (!mode) {
|
||||
drm_dbg_kms(&i915->drm, "drm_mode_duplicate failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
drm_mode_probed_add(connector, mode);
|
||||
return 1;
|
||||
return intel_panel_get_modes(to_intel_connector(connector));
|
||||
}
|
||||
|
||||
enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector,
|
||||
|
@ -61,7 +42,8 @@ enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector,
|
|||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
||||
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||
const struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
|
||||
const struct drm_display_mode *fixed_mode =
|
||||
intel_panel_fixed_mode(intel_connector, mode);
|
||||
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
|
||||
enum drm_mode_status status;
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
|
@ -686,9 +687,9 @@ void intel_dsi_log_params(struct intel_dsi *intel_dsi)
|
|||
intel_dsi->burst_mode_ratio);
|
||||
drm_dbg_kms(&i915->drm, "Reset timer %d\n", intel_dsi->rst_timer_val);
|
||||
drm_dbg_kms(&i915->drm, "Eot %s\n",
|
||||
enableddisabled(intel_dsi->eotp_pkt));
|
||||
str_enabled_disabled(intel_dsi->eotp_pkt));
|
||||
drm_dbg_kms(&i915->drm, "Clockstop %s\n",
|
||||
enableddisabled(!intel_dsi->clock_stop));
|
||||
str_enabled_disabled(!intel_dsi->clock_stop));
|
||||
drm_dbg_kms(&i915->drm, "Mode %s\n",
|
||||
intel_dsi->operation_mode ? "command" : "video");
|
||||
if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK)
|
||||
|
@ -715,7 +716,7 @@ void intel_dsi_log_params(struct intel_dsi *intel_dsi)
|
|||
drm_dbg_kms(&i915->drm, "HS to LP Clock Count 0x%x\n",
|
||||
intel_dsi->clk_hs_to_lp_count);
|
||||
drm_dbg_kms(&i915->drm, "BTA %s\n",
|
||||
enableddisabled(!(intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA)));
|
||||
str_enabled_disabled(!(intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA)));
|
||||
}
|
||||
|
||||
bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
|
||||
|
|
|
@ -226,7 +226,7 @@ intel_dvo_mode_valid(struct drm_connector *connector,
|
|||
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||
struct intel_dvo *intel_dvo = intel_attached_dvo(intel_connector);
|
||||
const struct drm_display_mode *fixed_mode =
|
||||
intel_connector->panel.fixed_mode;
|
||||
intel_panel_fixed_mode(intel_connector, mode);
|
||||
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
|
||||
int target_clock = mode->clock;
|
||||
|
||||
|
@ -257,9 +257,9 @@ static int intel_dvo_compute_config(struct intel_encoder *encoder,
|
|||
{
|
||||
struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
|
||||
struct intel_connector *connector = to_intel_connector(conn_state->connector);
|
||||
const struct drm_display_mode *fixed_mode =
|
||||
intel_dvo->attached_connector->panel.fixed_mode;
|
||||
struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
|
||||
const struct drm_display_mode *fixed_mode =
|
||||
intel_panel_fixed_mode(intel_dvo->attached_connector, adjusted_mode);
|
||||
|
||||
/*
|
||||
* If we have timings from the BIOS for the panel, put them in
|
||||
|
@ -333,8 +333,6 @@ intel_dvo_detect(struct drm_connector *connector, bool force)
|
|||
static int intel_dvo_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
||||
const struct drm_display_mode *fixed_mode =
|
||||
to_intel_connector(connector)->panel.fixed_mode;
|
||||
int num_modes;
|
||||
|
||||
/*
|
||||
|
@ -348,17 +346,7 @@ static int intel_dvo_get_modes(struct drm_connector *connector)
|
|||
if (num_modes)
|
||||
return num_modes;
|
||||
|
||||
if (fixed_mode) {
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, fixed_mode);
|
||||
if (mode) {
|
||||
drm_mode_probed_add(connector, mode);
|
||||
num_modes++;
|
||||
}
|
||||
}
|
||||
|
||||
return num_modes;
|
||||
return intel_panel_get_modes(to_intel_connector(connector));
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs intel_dvo_connector_funcs = {
|
||||
|
@ -390,27 +378,6 @@ static const struct drm_encoder_funcs intel_dvo_enc_funcs = {
|
|||
.destroy = intel_dvo_enc_destroy,
|
||||
};
|
||||
|
||||
/*
|
||||
* Attempts to get a fixed panel timing for LVDS (currently only the i830).
|
||||
*
|
||||
* Other chips with DVO LVDS will need to extend this to deal with the LVDS
|
||||
* chip being on DVOB/C and having multiple pipes.
|
||||
*/
|
||||
static struct drm_display_mode *
|
||||
intel_dvo_get_current_mode(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = intel_encoder_current_mode(encoder);
|
||||
if (mode) {
|
||||
DRM_DEBUG_KMS("using current (BIOS) mode: ");
|
||||
drm_mode_debug_printmodeline(mode);
|
||||
mode->type |= DRM_MODE_TYPE_PREFERRED;
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
static enum port intel_dvo_port(i915_reg_t dvo_reg)
|
||||
{
|
||||
if (i915_mmio_reg_equal(dvo_reg, DVOA))
|
||||
|
@ -561,9 +528,11 @@ void intel_dvo_init(struct drm_i915_private *dev_priv)
|
|||
* headers, likely), so for now, just get the current
|
||||
* mode being output through DVO.
|
||||
*/
|
||||
intel_panel_init(&intel_connector->panel,
|
||||
intel_dvo_get_current_mode(intel_encoder),
|
||||
NULL);
|
||||
intel_panel_add_encoder_fixed_mode(intel_connector,
|
||||
intel_encoder);
|
||||
|
||||
intel_panel_init(intel_connector);
|
||||
|
||||
intel_dvo->panel_wants_dither = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -107,6 +107,21 @@ static const struct drm_format_info gen12_ccs_cc_formats[] = {
|
|||
.hsub = 1, .vsub = 1, .has_alpha = true },
|
||||
};
|
||||
|
||||
static const struct drm_format_info gen12_flat_ccs_cc_formats[] = {
|
||||
{ .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2,
|
||||
.char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
|
||||
.hsub = 1, .vsub = 1, },
|
||||
{ .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2,
|
||||
.char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
|
||||
.hsub = 1, .vsub = 1, },
|
||||
{ .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2,
|
||||
.char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
|
||||
.hsub = 1, .vsub = 1, .has_alpha = true },
|
||||
{ .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2,
|
||||
.char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
|
||||
.hsub = 1, .vsub = 1, .has_alpha = true },
|
||||
};
|
||||
|
||||
struct intel_modifier_desc {
|
||||
u64 modifier;
|
||||
struct {
|
||||
|
@ -135,11 +150,32 @@ struct intel_modifier_desc {
|
|||
INTEL_PLANE_CAP_CCS_MC)
|
||||
#define INTEL_PLANE_CAP_TILING_MASK (INTEL_PLANE_CAP_TILING_X | \
|
||||
INTEL_PLANE_CAP_TILING_Y | \
|
||||
INTEL_PLANE_CAP_TILING_Yf)
|
||||
INTEL_PLANE_CAP_TILING_Yf | \
|
||||
INTEL_PLANE_CAP_TILING_4)
|
||||
#define INTEL_PLANE_CAP_TILING_NONE 0
|
||||
|
||||
static const struct intel_modifier_desc intel_modifiers[] = {
|
||||
{
|
||||
.modifier = I915_FORMAT_MOD_4_TILED_DG2_MC_CCS,
|
||||
.display_ver = { 13, 13 },
|
||||
.plane_caps = INTEL_PLANE_CAP_TILING_4 | INTEL_PLANE_CAP_CCS_MC,
|
||||
}, {
|
||||
.modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC,
|
||||
.display_ver = { 13, 13 },
|
||||
.plane_caps = INTEL_PLANE_CAP_TILING_4 | INTEL_PLANE_CAP_CCS_RC_CC,
|
||||
|
||||
.ccs.cc_planes = BIT(1),
|
||||
|
||||
FORMAT_OVERRIDE(gen12_flat_ccs_cc_formats),
|
||||
}, {
|
||||
.modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS,
|
||||
.display_ver = { 13, 13 },
|
||||
.plane_caps = INTEL_PLANE_CAP_TILING_4 | INTEL_PLANE_CAP_CCS_RC,
|
||||
}, {
|
||||
.modifier = I915_FORMAT_MOD_4_TILED,
|
||||
.display_ver = { 13, 13 },
|
||||
.plane_caps = INTEL_PLANE_CAP_TILING_4,
|
||||
}, {
|
||||
.modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS,
|
||||
.display_ver = { 12, 13 },
|
||||
.plane_caps = INTEL_PLANE_CAP_TILING_Y | INTEL_PLANE_CAP_CCS_MC,
|
||||
|
@ -380,17 +416,13 @@ bool intel_fb_plane_supports_modifier(struct intel_plane *plane, u64 modifier)
|
|||
static bool format_is_yuv_semiplanar(const struct intel_modifier_desc *md,
|
||||
const struct drm_format_info *info)
|
||||
{
|
||||
int yuv_planes;
|
||||
|
||||
if (!info->is_yuv)
|
||||
return false;
|
||||
|
||||
if (plane_caps_contain_any(md->plane_caps, INTEL_PLANE_CAP_CCS_MASK))
|
||||
yuv_planes = 4;
|
||||
if (hweight8(md->ccs.planar_aux_planes) == 2)
|
||||
return info->num_planes == 4;
|
||||
else
|
||||
yuv_planes = 2;
|
||||
|
||||
return info->num_planes == yuv_planes;
|
||||
return info->num_planes == 2;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -515,12 +547,13 @@ static unsigned int gen12_ccs_aux_stride(struct intel_framebuffer *fb, int ccs_p
|
|||
|
||||
int skl_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane)
|
||||
{
|
||||
const struct intel_modifier_desc *md = lookup_modifier(fb->modifier);
|
||||
struct drm_i915_private *i915 = to_i915(fb->dev);
|
||||
|
||||
if (intel_fb_is_ccs_modifier(fb->modifier))
|
||||
if (md->ccs.packed_aux_planes | md->ccs.planar_aux_planes)
|
||||
return main_to_ccs_plane(fb, main_plane);
|
||||
else if (DISPLAY_VER(i915) < 11 &&
|
||||
intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
|
||||
format_is_yuv_semiplanar(md, fb->format))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
|
@ -545,6 +578,15 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)
|
|||
return 128;
|
||||
else
|
||||
return 512;
|
||||
case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
|
||||
case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
|
||||
case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
|
||||
case I915_FORMAT_MOD_4_TILED:
|
||||
/*
|
||||
* Each 4K tile consists of 64B(8*8) subtiles, with
|
||||
* same shape as Y Tile(i.e 4*16B OWords)
|
||||
*/
|
||||
return 128;
|
||||
case I915_FORMAT_MOD_Y_TILED_CCS:
|
||||
if (intel_fb_is_ccs_aux_plane(fb, color_plane))
|
||||
return 128;
|
||||
|
@ -650,6 +692,7 @@ static unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier)
|
|||
return I915_TILING_Y;
|
||||
case INTEL_PLANE_CAP_TILING_X:
|
||||
return I915_TILING_X;
|
||||
case INTEL_PLANE_CAP_TILING_4:
|
||||
case INTEL_PLANE_CAP_TILING_Yf:
|
||||
case INTEL_PLANE_CAP_TILING_NONE:
|
||||
return I915_TILING_NONE;
|
||||
|
@ -737,8 +780,13 @@ unsigned int intel_surf_alignment(const struct drm_framebuffer *fb,
|
|||
case I915_FORMAT_MOD_Y_TILED_CCS:
|
||||
case I915_FORMAT_MOD_Yf_TILED_CCS:
|
||||
case I915_FORMAT_MOD_Y_TILED:
|
||||
case I915_FORMAT_MOD_4_TILED:
|
||||
case I915_FORMAT_MOD_Yf_TILED:
|
||||
return 1 * 1024 * 1024;
|
||||
case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
|
||||
case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
|
||||
case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
|
||||
return 16 * 1024;
|
||||
default:
|
||||
MISSING_CASE(fb->modifier);
|
||||
return 0;
|
||||
|
|
|
@ -27,6 +27,7 @@ struct intel_plane_state;
|
|||
#define INTEL_PLANE_CAP_TILING_X BIT(3)
|
||||
#define INTEL_PLANE_CAP_TILING_Y BIT(4)
|
||||
#define INTEL_PLANE_CAP_TILING_Yf BIT(5)
|
||||
#define INTEL_PLANE_CAP_TILING_4 BIT(6)
|
||||
|
||||
bool intel_fb_is_ccs_modifier(u64 modifier);
|
||||
bool intel_fb_is_rc_ccs_cc_modifier(u64 modifier);
|
||||
|
|
|
@ -38,9 +38,12 @@
|
|||
* forcibly disable it to allow proper screen updates.
|
||||
*/
|
||||
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include <drm/drm_fourcc.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_utils.h"
|
||||
#include "i915_vgpu.h"
|
||||
#include "intel_cdclk.h"
|
||||
#include "intel_de.h"
|
||||
|
@ -87,7 +90,6 @@ struct intel_fbc {
|
|||
* with stolen_lock.
|
||||
*/
|
||||
struct mutex lock;
|
||||
unsigned int possible_framebuffer_bits;
|
||||
unsigned int busy_bits;
|
||||
|
||||
struct drm_mm_node compressed_fb;
|
||||
|
@ -665,6 +667,10 @@ static bool intel_fbc_is_compressing(struct intel_fbc *fbc)
|
|||
|
||||
static void intel_fbc_nuke(struct intel_fbc *fbc)
|
||||
{
|
||||
struct drm_i915_private *i915 = fbc->i915;
|
||||
|
||||
drm_WARN_ON(&i915->drm, fbc->flip_pending);
|
||||
|
||||
trace_intel_fbc_nuke(fbc->state.plane);
|
||||
|
||||
fbc->funcs->nuke(fbc);
|
||||
|
@ -946,6 +952,7 @@ static bool tiling_is_valid(const struct intel_plane_state *plane_state)
|
|||
case I915_FORMAT_MOD_Y_TILED:
|
||||
case I915_FORMAT_MOD_Yf_TILED:
|
||||
return DISPLAY_VER(i915) >= 9;
|
||||
case I915_FORMAT_MOD_4_TILED:
|
||||
case I915_FORMAT_MOD_X_TILED:
|
||||
return true;
|
||||
default:
|
||||
|
@ -966,6 +973,7 @@ static void intel_fbc_update_state(struct intel_atomic_state *state,
|
|||
struct intel_fbc_state *fbc_state = &fbc->state;
|
||||
|
||||
WARN_ON(plane_state->no_fbc_reason);
|
||||
WARN_ON(fbc_state->plane && fbc_state->plane != plane);
|
||||
|
||||
fbc_state->plane = plane;
|
||||
|
||||
|
@ -1270,6 +1278,8 @@ static void __intel_fbc_disable(struct intel_fbc *fbc)
|
|||
__intel_fbc_cleanup_cfb(fbc);
|
||||
|
||||
fbc->state.plane = NULL;
|
||||
fbc->flip_pending = false;
|
||||
fbc->busy_bits = 0;
|
||||
}
|
||||
|
||||
static void __intel_fbc_post_update(struct intel_fbc *fbc)
|
||||
|
@ -1313,7 +1323,7 @@ static unsigned int intel_fbc_get_frontbuffer_bit(struct intel_fbc *fbc)
|
|||
if (fbc->state.plane)
|
||||
return fbc->state.plane->frontbuffer_bit;
|
||||
else
|
||||
return fbc->possible_framebuffer_bits;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __intel_fbc_invalidate(struct intel_fbc *fbc,
|
||||
|
@ -1325,11 +1335,14 @@ static void __intel_fbc_invalidate(struct intel_fbc *fbc,
|
|||
|
||||
mutex_lock(&fbc->lock);
|
||||
|
||||
fbc->busy_bits |= intel_fbc_get_frontbuffer_bit(fbc) & frontbuffer_bits;
|
||||
frontbuffer_bits &= intel_fbc_get_frontbuffer_bit(fbc);
|
||||
if (!frontbuffer_bits)
|
||||
goto out;
|
||||
|
||||
if (fbc->state.plane && fbc->busy_bits)
|
||||
intel_fbc_deactivate(fbc, "frontbuffer write");
|
||||
fbc->busy_bits |= frontbuffer_bits;
|
||||
intel_fbc_deactivate(fbc, "frontbuffer write");
|
||||
|
||||
out:
|
||||
mutex_unlock(&fbc->lock);
|
||||
}
|
||||
|
||||
|
@ -1351,18 +1364,22 @@ static void __intel_fbc_flush(struct intel_fbc *fbc,
|
|||
{
|
||||
mutex_lock(&fbc->lock);
|
||||
|
||||
frontbuffer_bits &= intel_fbc_get_frontbuffer_bit(fbc);
|
||||
if (!frontbuffer_bits)
|
||||
goto out;
|
||||
|
||||
fbc->busy_bits &= ~frontbuffer_bits;
|
||||
|
||||
if (origin == ORIGIN_FLIP || origin == ORIGIN_CURSOR_UPDATE)
|
||||
goto out;
|
||||
|
||||
if (!fbc->busy_bits && fbc->state.plane &&
|
||||
(frontbuffer_bits & intel_fbc_get_frontbuffer_bit(fbc))) {
|
||||
if (fbc->active)
|
||||
intel_fbc_nuke(fbc);
|
||||
else if (!fbc->flip_pending)
|
||||
__intel_fbc_post_update(fbc);
|
||||
}
|
||||
if (fbc->busy_bits || fbc->flip_pending)
|
||||
goto out;
|
||||
|
||||
if (fbc->active)
|
||||
intel_fbc_nuke(fbc);
|
||||
else
|
||||
intel_fbc_activate(fbc);
|
||||
|
||||
out:
|
||||
mutex_unlock(&fbc->lock);
|
||||
|
@ -1500,25 +1517,6 @@ void intel_fbc_update(struct intel_atomic_state *state,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_fbc_global_disable - globally disable FBC
|
||||
* @i915: i915 device instance
|
||||
*
|
||||
* This function disables FBC regardless of which CRTC is associated with it.
|
||||
*/
|
||||
void intel_fbc_global_disable(struct drm_i915_private *i915)
|
||||
{
|
||||
struct intel_fbc *fbc;
|
||||
enum intel_fbc_id fbc_id;
|
||||
|
||||
for_each_intel_fbc(i915, fbc, fbc_id) {
|
||||
mutex_lock(&fbc->lock);
|
||||
if (fbc->state.plane)
|
||||
__intel_fbc_disable(fbc);
|
||||
mutex_unlock(&fbc->lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void intel_fbc_underrun_work_fn(struct work_struct *work)
|
||||
{
|
||||
struct intel_fbc *fbc = container_of(work, typeof(*fbc), underrun_work);
|
||||
|
@ -1640,7 +1638,7 @@ static int intel_sanitize_fbc_option(struct drm_i915_private *i915)
|
|||
static bool need_fbc_vtd_wa(struct drm_i915_private *i915)
|
||||
{
|
||||
/* WaFbcTurnOffFbcWhenHyperVisorIsUsed:skl,bxt */
|
||||
if (intel_vtd_active(i915) &&
|
||||
if (i915_vtd_active(i915) &&
|
||||
(IS_SKYLAKE(i915) || IS_BROXTON(i915))) {
|
||||
drm_info(&i915->drm,
|
||||
"Disabling framebuffer compression (FBC) to prevent screen flicker with VT-d enabled\n");
|
||||
|
@ -1652,11 +1650,7 @@ static bool need_fbc_vtd_wa(struct drm_i915_private *i915)
|
|||
|
||||
void intel_fbc_add_plane(struct intel_fbc *fbc, struct intel_plane *plane)
|
||||
{
|
||||
if (!fbc)
|
||||
return;
|
||||
|
||||
plane->fbc = fbc;
|
||||
fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
|
||||
}
|
||||
|
||||
static struct intel_fbc *intel_fbc_create(struct drm_i915_private *i915,
|
||||
|
@ -1709,22 +1703,26 @@ void intel_fbc_init(struct drm_i915_private *i915)
|
|||
drm_dbg_kms(&i915->drm, "Sanitized enable_fbc value: %d\n",
|
||||
i915->params.enable_fbc);
|
||||
|
||||
for_each_fbc_id(i915, fbc_id) {
|
||||
struct intel_fbc *fbc;
|
||||
for_each_fbc_id(i915, fbc_id)
|
||||
i915->fbc[fbc_id] = intel_fbc_create(i915, fbc_id);
|
||||
}
|
||||
|
||||
fbc = intel_fbc_create(i915, fbc_id);
|
||||
if (!fbc)
|
||||
continue;
|
||||
/**
|
||||
* intel_fbc_sanitize - Sanitize FBC
|
||||
* @i915: the i915 device
|
||||
*
|
||||
* Make sure FBC is initially disabled since we have no
|
||||
* idea eg. into which parts of stolen it might be scribbling
|
||||
* into.
|
||||
*/
|
||||
void intel_fbc_sanitize(struct drm_i915_private *i915)
|
||||
{
|
||||
struct intel_fbc *fbc;
|
||||
enum intel_fbc_id fbc_id;
|
||||
|
||||
/*
|
||||
* We still don't have any sort of hardware state readout
|
||||
* for FBC, so deactivate it in case the BIOS activated it
|
||||
* to make sure software matches the hardware state.
|
||||
*/
|
||||
for_each_intel_fbc(i915, fbc, fbc_id) {
|
||||
if (intel_fbc_hw_is_active(fbc))
|
||||
intel_fbc_hw_deactivate(fbc);
|
||||
|
||||
i915->fbc[fbc->id] = fbc;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1743,7 +1741,7 @@ static int intel_fbc_debugfs_status_show(struct seq_file *m, void *unused)
|
|||
if (fbc->active) {
|
||||
seq_puts(m, "FBC enabled\n");
|
||||
seq_printf(m, "Compressing: %s\n",
|
||||
yesno(intel_fbc_is_compressing(fbc)));
|
||||
str_yes_no(intel_fbc_is_compressing(fbc)));
|
||||
} else {
|
||||
seq_printf(m, "FBC disabled: %s\n", fbc->no_fbc_reason);
|
||||
}
|
||||
|
|
|
@ -30,10 +30,10 @@ void intel_fbc_post_update(struct intel_atomic_state *state,
|
|||
struct intel_crtc *crtc);
|
||||
void intel_fbc_init(struct drm_i915_private *dev_priv);
|
||||
void intel_fbc_cleanup(struct drm_i915_private *dev_priv);
|
||||
void intel_fbc_sanitize(struct drm_i915_private *dev_priv);
|
||||
void intel_fbc_update(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc);
|
||||
void intel_fbc_disable(struct intel_crtc *crtc);
|
||||
void intel_fbc_global_disable(struct drm_i915_private *dev_priv);
|
||||
void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
|
||||
unsigned int frontbuffer_bits,
|
||||
enum fb_op_origin origin);
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
* Copyright © 2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_crtc.h"
|
||||
#include "intel_ddi.h"
|
||||
|
@ -34,7 +36,7 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv,
|
|||
}
|
||||
I915_STATE_WARN(cur_state != state,
|
||||
"FDI TX state assertion failure (expected %s, current %s)\n",
|
||||
onoff(state), onoff(cur_state));
|
||||
str_on_off(state), str_on_off(cur_state));
|
||||
}
|
||||
|
||||
void assert_fdi_tx_enabled(struct drm_i915_private *i915, enum pipe pipe)
|
||||
|
@ -55,7 +57,7 @@ static void assert_fdi_rx(struct drm_i915_private *dev_priv,
|
|||
cur_state = intel_de_read(dev_priv, FDI_RX_CTL(pipe)) & FDI_RX_ENABLE;
|
||||
I915_STATE_WARN(cur_state != state,
|
||||
"FDI RX state assertion failure (expected %s, current %s)\n",
|
||||
onoff(state), onoff(cur_state));
|
||||
str_on_off(state), str_on_off(cur_state));
|
||||
}
|
||||
|
||||
void assert_fdi_rx_enabled(struct drm_i915_private *i915, enum pipe pipe)
|
||||
|
@ -93,7 +95,7 @@ static void assert_fdi_rx_pll(struct drm_i915_private *i915,
|
|||
cur_state = intel_de_read(i915, FDI_RX_CTL(pipe)) & FDI_RX_PLL_ENABLE;
|
||||
I915_STATE_WARN(cur_state != state,
|
||||
"FDI RX PLL assertion failure (expected %s, current %s)\n",
|
||||
onoff(state), onoff(cur_state));
|
||||
str_on_off(state), str_on_off(cur_state));
|
||||
}
|
||||
|
||||
void assert_fdi_rx_pll_enabled(struct drm_i915_private *i915, enum pipe pipe)
|
||||
|
|
|
@ -38,6 +38,16 @@
|
|||
#include "intel_display_types.h"
|
||||
#include "intel_gmbus.h"
|
||||
|
||||
struct intel_gmbus {
|
||||
struct i2c_adapter adapter;
|
||||
#define GMBUS_FORCE_BIT_RETRY (1U << 31)
|
||||
u32 force_bit;
|
||||
u32 reg0;
|
||||
i915_reg_t gpio_reg;
|
||||
struct i2c_algo_bit_data bit_algo;
|
||||
struct drm_i915_private *dev_priv;
|
||||
};
|
||||
|
||||
struct gmbus_pin {
|
||||
const char *name;
|
||||
enum i915_gpio gpio;
|
||||
|
@ -106,51 +116,47 @@ static const struct gmbus_pin gmbus_pins_dg2[] = {
|
|||
[GMBUS_PIN_9_TC1_ICP] = { "tc1", GPIOJ },
|
||||
};
|
||||
|
||||
/* pin is expected to be valid */
|
||||
static const struct gmbus_pin *get_gmbus_pin(struct drm_i915_private *dev_priv,
|
||||
static const struct gmbus_pin *get_gmbus_pin(struct drm_i915_private *i915,
|
||||
unsigned int pin)
|
||||
{
|
||||
if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG2)
|
||||
return &gmbus_pins_dg2[pin];
|
||||
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
|
||||
return &gmbus_pins_dg1[pin];
|
||||
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
|
||||
return &gmbus_pins_icp[pin];
|
||||
else if (HAS_PCH_CNP(dev_priv))
|
||||
return &gmbus_pins_cnp[pin];
|
||||
else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
|
||||
return &gmbus_pins_bxt[pin];
|
||||
else if (DISPLAY_VER(dev_priv) == 9)
|
||||
return &gmbus_pins_skl[pin];
|
||||
else if (IS_BROADWELL(dev_priv))
|
||||
return &gmbus_pins_bdw[pin];
|
||||
else
|
||||
return &gmbus_pins[pin];
|
||||
const struct gmbus_pin *pins;
|
||||
size_t size;
|
||||
|
||||
if (INTEL_PCH_TYPE(i915) >= PCH_DG2) {
|
||||
pins = gmbus_pins_dg2;
|
||||
size = ARRAY_SIZE(gmbus_pins_dg2);
|
||||
} else if (INTEL_PCH_TYPE(i915) >= PCH_DG1) {
|
||||
pins = gmbus_pins_dg1;
|
||||
size = ARRAY_SIZE(gmbus_pins_dg1);
|
||||
} else if (INTEL_PCH_TYPE(i915) >= PCH_ICP) {
|
||||
pins = gmbus_pins_icp;
|
||||
size = ARRAY_SIZE(gmbus_pins_icp);
|
||||
} else if (HAS_PCH_CNP(i915)) {
|
||||
pins = gmbus_pins_cnp;
|
||||
size = ARRAY_SIZE(gmbus_pins_cnp);
|
||||
} else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) {
|
||||
pins = gmbus_pins_bxt;
|
||||
size = ARRAY_SIZE(gmbus_pins_bxt);
|
||||
} else if (DISPLAY_VER(i915) == 9) {
|
||||
pins = gmbus_pins_skl;
|
||||
size = ARRAY_SIZE(gmbus_pins_skl);
|
||||
} else if (IS_BROADWELL(i915)) {
|
||||
pins = gmbus_pins_bdw;
|
||||
size = ARRAY_SIZE(gmbus_pins_bdw);
|
||||
} else {
|
||||
pins = gmbus_pins;
|
||||
size = ARRAY_SIZE(gmbus_pins);
|
||||
}
|
||||
|
||||
if (pin >= size || !pins[pin].name)
|
||||
return NULL;
|
||||
|
||||
return &pins[pin];
|
||||
}
|
||||
|
||||
bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv,
|
||||
unsigned int pin)
|
||||
bool intel_gmbus_is_valid_pin(struct drm_i915_private *i915, unsigned int pin)
|
||||
{
|
||||
unsigned int size;
|
||||
|
||||
if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG2)
|
||||
size = ARRAY_SIZE(gmbus_pins_dg2);
|
||||
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
|
||||
size = ARRAY_SIZE(gmbus_pins_dg1);
|
||||
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
|
||||
size = ARRAY_SIZE(gmbus_pins_icp);
|
||||
else if (HAS_PCH_CNP(dev_priv))
|
||||
size = ARRAY_SIZE(gmbus_pins_cnp);
|
||||
else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
|
||||
size = ARRAY_SIZE(gmbus_pins_bxt);
|
||||
else if (DISPLAY_VER(dev_priv) == 9)
|
||||
size = ARRAY_SIZE(gmbus_pins_skl);
|
||||
else if (IS_BROADWELL(dev_priv))
|
||||
size = ARRAY_SIZE(gmbus_pins_bdw);
|
||||
else
|
||||
size = ARRAY_SIZE(gmbus_pins);
|
||||
|
||||
return pin < size && get_gmbus_pin(dev_priv, pin)->name;
|
||||
return get_gmbus_pin(i915, pin);
|
||||
}
|
||||
|
||||
/* Intel GPIO access functions */
|
||||
|
@ -294,9 +300,7 @@ static void set_data(void *data, int state_high)
|
|||
static int
|
||||
intel_gpio_pre_xfer(struct i2c_adapter *adapter)
|
||||
{
|
||||
struct intel_gmbus *bus = container_of(adapter,
|
||||
struct intel_gmbus,
|
||||
adapter);
|
||||
struct intel_gmbus *bus = to_intel_gmbus(adapter);
|
||||
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||
|
||||
intel_gmbus_reset(dev_priv);
|
||||
|
@ -313,9 +317,7 @@ intel_gpio_pre_xfer(struct i2c_adapter *adapter)
|
|||
static void
|
||||
intel_gpio_post_xfer(struct i2c_adapter *adapter)
|
||||
{
|
||||
struct intel_gmbus *bus = container_of(adapter,
|
||||
struct intel_gmbus,
|
||||
adapter);
|
||||
struct intel_gmbus *bus = to_intel_gmbus(adapter);
|
||||
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||
|
||||
set_data(bus, 1);
|
||||
|
@ -326,14 +328,13 @@ intel_gpio_post_xfer(struct i2c_adapter *adapter)
|
|||
}
|
||||
|
||||
static void
|
||||
intel_gpio_setup(struct intel_gmbus *bus, unsigned int pin)
|
||||
intel_gpio_setup(struct intel_gmbus *bus, i915_reg_t gpio_reg)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||
struct i2c_algo_bit_data *algo;
|
||||
|
||||
algo = &bus->bit_algo;
|
||||
|
||||
bus->gpio_reg = GPIO(get_gmbus_pin(dev_priv, pin)->gpio);
|
||||
bus->gpio_reg = gpio_reg;
|
||||
bus->adapter.algo_data = algo;
|
||||
algo->setsda = set_data;
|
||||
algo->setscl = set_clock;
|
||||
|
@ -614,9 +615,7 @@ static int
|
|||
do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
|
||||
u32 gmbus0_source)
|
||||
{
|
||||
struct intel_gmbus *bus = container_of(adapter,
|
||||
struct intel_gmbus,
|
||||
adapter);
|
||||
struct intel_gmbus *bus = to_intel_gmbus(adapter);
|
||||
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||
int i = 0, inc, try = 0;
|
||||
int ret = 0;
|
||||
|
@ -746,8 +745,7 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
|
|||
static int
|
||||
gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
|
||||
{
|
||||
struct intel_gmbus *bus =
|
||||
container_of(adapter, struct intel_gmbus, adapter);
|
||||
struct intel_gmbus *bus = to_intel_gmbus(adapter);
|
||||
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||
intel_wakeref_t wakeref;
|
||||
int ret;
|
||||
|
@ -771,8 +769,7 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
|
|||
|
||||
int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
|
||||
{
|
||||
struct intel_gmbus *bus =
|
||||
container_of(adapter, struct intel_gmbus, adapter);
|
||||
struct intel_gmbus *bus = to_intel_gmbus(adapter);
|
||||
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||
u8 cmd = DRM_HDCP_DDC_AKSV;
|
||||
u8 buf[DRM_HDCP_KSV_LEN] = { 0 };
|
||||
|
@ -863,7 +860,6 @@ static const struct i2c_lock_operations gmbus_lock_ops = {
|
|||
int intel_gmbus_setup(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
|
||||
struct intel_gmbus *bus;
|
||||
unsigned int pin;
|
||||
int ret;
|
||||
|
||||
|
@ -880,17 +876,24 @@ int intel_gmbus_setup(struct drm_i915_private *dev_priv)
|
|||
init_waitqueue_head(&dev_priv->gmbus_wait_queue);
|
||||
|
||||
for (pin = 0; pin < ARRAY_SIZE(dev_priv->gmbus); pin++) {
|
||||
if (!intel_gmbus_is_valid_pin(dev_priv, pin))
|
||||
const struct gmbus_pin *gmbus_pin;
|
||||
struct intel_gmbus *bus;
|
||||
|
||||
gmbus_pin = get_gmbus_pin(dev_priv, pin);
|
||||
if (!gmbus_pin)
|
||||
continue;
|
||||
|
||||
bus = &dev_priv->gmbus[pin];
|
||||
bus = kzalloc(sizeof(*bus), GFP_KERNEL);
|
||||
if (!bus) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
bus->adapter.owner = THIS_MODULE;
|
||||
bus->adapter.class = I2C_CLASS_DDC;
|
||||
snprintf(bus->adapter.name,
|
||||
sizeof(bus->adapter.name),
|
||||
"i915 gmbus %s",
|
||||
get_gmbus_pin(dev_priv, pin)->name);
|
||||
"i915 gmbus %s", gmbus_pin->name);
|
||||
|
||||
bus->adapter.dev.parent = &pdev->dev;
|
||||
bus->dev_priv = dev_priv;
|
||||
|
@ -911,11 +914,15 @@ int intel_gmbus_setup(struct drm_i915_private *dev_priv)
|
|||
if (IS_I830(dev_priv))
|
||||
bus->force_bit = 1;
|
||||
|
||||
intel_gpio_setup(bus, pin);
|
||||
intel_gpio_setup(bus, GPIO(gmbus_pin->gpio));
|
||||
|
||||
ret = i2c_add_adapter(&bus->adapter);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
kfree(bus);
|
||||
goto err;
|
||||
}
|
||||
|
||||
dev_priv->gmbus[pin] = bus;
|
||||
}
|
||||
|
||||
intel_gmbus_reset(dev_priv);
|
||||
|
@ -923,24 +930,19 @@ int intel_gmbus_setup(struct drm_i915_private *dev_priv)
|
|||
return 0;
|
||||
|
||||
err:
|
||||
while (pin--) {
|
||||
if (!intel_gmbus_is_valid_pin(dev_priv, pin))
|
||||
continue;
|
||||
intel_gmbus_teardown(dev_priv);
|
||||
|
||||
bus = &dev_priv->gmbus[pin];
|
||||
i2c_del_adapter(&bus->adapter);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct i2c_adapter *intel_gmbus_get_adapter(struct drm_i915_private *dev_priv,
|
||||
unsigned int pin)
|
||||
{
|
||||
if (drm_WARN_ON(&dev_priv->drm,
|
||||
!intel_gmbus_is_valid_pin(dev_priv, pin)))
|
||||
if (drm_WARN_ON(&dev_priv->drm, pin >= ARRAY_SIZE(dev_priv->gmbus) ||
|
||||
!dev_priv->gmbus[pin]))
|
||||
return NULL;
|
||||
|
||||
return &dev_priv->gmbus[pin].adapter;
|
||||
return &dev_priv->gmbus[pin]->adapter;
|
||||
}
|
||||
|
||||
void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)
|
||||
|
@ -968,14 +970,18 @@ bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
|
|||
|
||||
void intel_gmbus_teardown(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct intel_gmbus *bus;
|
||||
unsigned int pin;
|
||||
|
||||
for (pin = 0; pin < ARRAY_SIZE(dev_priv->gmbus); pin++) {
|
||||
if (!intel_gmbus_is_valid_pin(dev_priv, pin))
|
||||
struct intel_gmbus *bus;
|
||||
|
||||
bus = dev_priv->gmbus[pin];
|
||||
if (!bus)
|
||||
continue;
|
||||
|
||||
bus = &dev_priv->gmbus[pin];
|
||||
i2c_del_adapter(&bus->adapter);
|
||||
|
||||
kfree(bus);
|
||||
dev_priv->gmbus[pin] = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "intel_connector.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_power.h"
|
||||
#include "intel_display_power_well.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_hdcp.h"
|
||||
#include "intel_pcode.h"
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <linux/hdmi.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
|
@ -2637,7 +2638,7 @@ bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder,
|
|||
drm_dbg_kms(&dev_priv->drm,
|
||||
"[CONNECTOR:%d:%s] scrambling=%s, TMDS bit clock ratio=1/%d\n",
|
||||
connector->base.id, connector->name,
|
||||
yesno(scrambling), high_tmds_clock_ratio ? 40 : 10);
|
||||
str_yes_no(scrambling), high_tmds_clock_ratio ? 40 : 10);
|
||||
|
||||
/* Set TMDS bit clock ratio to 1/40 or 1/10, and enable/disable scrambling */
|
||||
return drm_scdc_set_high_tmds_clock_ratio(adapter,
|
||||
|
|
|
@ -389,7 +389,8 @@ intel_lvds_mode_valid(struct drm_connector *connector,
|
|||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||
struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
|
||||
const struct drm_display_mode *fixed_mode =
|
||||
intel_panel_fixed_mode(intel_connector, mode);
|
||||
int max_pixclk = to_i915(connector->dev)->max_dotclk_freq;
|
||||
enum drm_mode_status status;
|
||||
|
||||
|
@ -475,19 +476,12 @@ static int intel_lvds_compute_config(struct intel_encoder *intel_encoder,
|
|||
static int intel_lvds_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
/* use cached edid if we have one */
|
||||
if (!IS_ERR_OR_NULL(intel_connector->edid))
|
||||
return drm_add_edid_modes(connector, intel_connector->edid);
|
||||
|
||||
mode = drm_mode_duplicate(dev, intel_connector->panel.fixed_mode);
|
||||
if (mode == NULL)
|
||||
return 0;
|
||||
|
||||
drm_mode_probed_add(connector, mode);
|
||||
return 1;
|
||||
return intel_panel_get_modes(intel_connector);
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
|
||||
|
@ -786,16 +780,18 @@ bool intel_is_dual_link_lvds(struct drm_i915_private *dev_priv)
|
|||
|
||||
static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)
|
||||
{
|
||||
struct drm_device *dev = lvds_encoder->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(lvds_encoder->base.base.dev);
|
||||
struct intel_connector *connector = lvds_encoder->attached_connector;
|
||||
const struct drm_display_mode *fixed_mode =
|
||||
intel_panel_preferred_fixed_mode(connector);
|
||||
unsigned int val;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
|
||||
/* use the module option value if specified */
|
||||
if (dev_priv->params.lvds_channel_mode > 0)
|
||||
return dev_priv->params.lvds_channel_mode == 2;
|
||||
|
||||
/* single channel LVDS is limited to 112 MHz */
|
||||
if (lvds_encoder->attached_connector->panel.fixed_mode->clock > 112999)
|
||||
if (fixed_mode->clock > 112999)
|
||||
return true;
|
||||
|
||||
if (dmi_check_system(intel_dual_link_lvds))
|
||||
|
@ -833,8 +829,6 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
|
|||
struct intel_connector *intel_connector;
|
||||
struct drm_connector *connector;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_display_mode *fixed_mode = NULL;
|
||||
struct drm_display_mode *downclock_mode = NULL;
|
||||
struct edid *edid;
|
||||
i915_reg_t lvds_reg;
|
||||
u32 lvds;
|
||||
|
@ -973,35 +967,30 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
|
|||
}
|
||||
intel_connector->edid = edid;
|
||||
|
||||
fixed_mode = intel_panel_edid_fixed_mode(intel_connector);
|
||||
if (fixed_mode)
|
||||
goto out;
|
||||
/* Try EDID first */
|
||||
intel_panel_add_edid_fixed_modes(intel_connector,
|
||||
dev_priv->vbt.drrs_type != DRRS_TYPE_NONE);
|
||||
|
||||
/* Failed to get EDID, what about VBT? */
|
||||
fixed_mode = intel_panel_vbt_fixed_mode(intel_connector);
|
||||
if (fixed_mode)
|
||||
goto out;
|
||||
if (!intel_panel_preferred_fixed_mode(intel_connector))
|
||||
intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
|
||||
|
||||
/*
|
||||
* If we didn't get EDID, try checking if the panel is already turned
|
||||
* on. If so, assume that whatever is currently programmed is the
|
||||
* correct mode.
|
||||
* If we didn't get a fixed mode from EDID or VBT, try checking
|
||||
* if the panel is already turned on. If so, assume that
|
||||
* whatever is currently programmed is the correct mode.
|
||||
*/
|
||||
fixed_mode = intel_encoder_current_mode(intel_encoder);
|
||||
if (fixed_mode) {
|
||||
drm_dbg_kms(&dev_priv->drm, "using current (BIOS) mode: ");
|
||||
drm_mode_debug_printmodeline(fixed_mode);
|
||||
fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
|
||||
}
|
||||
if (!intel_panel_preferred_fixed_mode(intel_connector))
|
||||
intel_panel_add_encoder_fixed_mode(intel_connector, intel_encoder);
|
||||
|
||||
/* If we still don't have a mode after all that, give up. */
|
||||
if (!fixed_mode)
|
||||
goto failed;
|
||||
|
||||
out:
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
|
||||
intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
|
||||
/* If we still don't have a mode after all that, give up. */
|
||||
if (!intel_panel_preferred_fixed_mode(intel_connector))
|
||||
goto failed;
|
||||
|
||||
intel_panel_init(intel_connector);
|
||||
|
||||
intel_backlight_setup(intel_connector, INVALID_PIPE);
|
||||
|
||||
lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
|
||||
|
@ -1013,8 +1002,6 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
|
|||
return;
|
||||
|
||||
failed:
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "No LVDS modes found, disabling.\n");
|
||||
drm_connector_cleanup(connector);
|
||||
drm_encoder_cleanup(encoder);
|
||||
|
|
|
@ -958,19 +958,21 @@ static void update_pfit_vscale_ratio(struct intel_overlay *overlay)
|
|||
static int check_overlay_dst(struct intel_overlay *overlay,
|
||||
struct drm_intel_overlay_put_image *rec)
|
||||
{
|
||||
const struct intel_crtc_state *pipe_config =
|
||||
const struct intel_crtc_state *crtc_state =
|
||||
overlay->crtc->config;
|
||||
struct drm_rect req, clipped;
|
||||
|
||||
if (rec->dst_height == 0 || rec->dst_width == 0)
|
||||
drm_rect_init(&req, rec->dst_x, rec->dst_y,
|
||||
rec->dst_width, rec->dst_height);
|
||||
|
||||
clipped = req;
|
||||
drm_rect_intersect(&clipped, &crtc_state->pipe_src);
|
||||
|
||||
if (!drm_rect_visible(&clipped) ||
|
||||
!drm_rect_equals(&clipped, &req))
|
||||
return -EINVAL;
|
||||
|
||||
if (rec->dst_x < pipe_config->pipe_src_w &&
|
||||
rec->dst_x + rec->dst_width <= pipe_config->pipe_src_w &&
|
||||
rec->dst_y < pipe_config->pipe_src_h &&
|
||||
rec->dst_y + rec->dst_height <= pipe_config->pipe_src_h)
|
||||
return 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_overlay_scaling(struct drm_intel_overlay_put_image *rec)
|
||||
|
@ -1160,7 +1162,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
|
|||
crtc->overlay = overlay;
|
||||
|
||||
/* line too wide, i.e. one-line-mode */
|
||||
if (crtc->config->pipe_src_w > 1024 &&
|
||||
if (drm_rect_width(&crtc->config->pipe_src) > 1024 &&
|
||||
crtc->config->gmch_pfit.control & PFIT_ENABLE) {
|
||||
overlay->pfit_active = true;
|
||||
update_pfit_vscale_ratio(overlay);
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "intel_connector.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_drrs.h"
|
||||
#include "intel_panel.h"
|
||||
|
||||
bool intel_panel_use_ssc(struct drm_i915_private *i915)
|
||||
|
@ -45,10 +46,83 @@ bool intel_panel_use_ssc(struct drm_i915_private *i915)
|
|||
&& !(i915->quirks & QUIRK_LVDS_SSC_DISABLE);
|
||||
}
|
||||
|
||||
const struct drm_display_mode *
|
||||
intel_panel_preferred_fixed_mode(struct intel_connector *connector)
|
||||
{
|
||||
return list_first_entry_or_null(&connector->panel.fixed_modes,
|
||||
struct drm_display_mode, head);
|
||||
}
|
||||
|
||||
const struct drm_display_mode *
|
||||
intel_panel_fixed_mode(struct intel_connector *connector,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
const struct drm_display_mode *fixed_mode, *best_mode = NULL;
|
||||
int vrefresh = drm_mode_vrefresh(mode);
|
||||
|
||||
/* pick the fixed_mode that is closest in terms of vrefresh */
|
||||
list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) {
|
||||
if (!best_mode ||
|
||||
abs(drm_mode_vrefresh(fixed_mode) - vrefresh) <
|
||||
abs(drm_mode_vrefresh(best_mode) - vrefresh))
|
||||
best_mode = fixed_mode;
|
||||
}
|
||||
|
||||
return best_mode;
|
||||
}
|
||||
|
||||
const struct drm_display_mode *
|
||||
intel_panel_downclock_mode(struct intel_connector *connector,
|
||||
const struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
const struct drm_display_mode *fixed_mode, *best_mode = NULL;
|
||||
int vrefresh = drm_mode_vrefresh(adjusted_mode);
|
||||
|
||||
/* pick the fixed_mode with the lowest refresh rate */
|
||||
list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) {
|
||||
if (drm_mode_vrefresh(fixed_mode) < vrefresh) {
|
||||
vrefresh = drm_mode_vrefresh(fixed_mode);
|
||||
best_mode = fixed_mode;
|
||||
}
|
||||
}
|
||||
|
||||
return best_mode;
|
||||
}
|
||||
|
||||
int intel_panel_get_modes(struct intel_connector *connector)
|
||||
{
|
||||
const struct drm_display_mode *fixed_mode;
|
||||
int num_modes = 0;
|
||||
|
||||
list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) {
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(connector->base.dev, fixed_mode);
|
||||
if (mode) {
|
||||
drm_mode_probed_add(&connector->base, mode);
|
||||
num_modes++;
|
||||
}
|
||||
}
|
||||
|
||||
return num_modes;
|
||||
}
|
||||
|
||||
enum drrs_type intel_panel_drrs_type(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
|
||||
if (list_empty(&connector->panel.fixed_modes) ||
|
||||
list_is_singular(&connector->panel.fixed_modes))
|
||||
return DRRS_TYPE_NONE;
|
||||
|
||||
return i915->vbt.drrs_type;
|
||||
}
|
||||
|
||||
int intel_panel_compute_config(struct intel_connector *connector,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
const struct drm_display_mode *fixed_mode = connector->panel.fixed_mode;
|
||||
const struct drm_display_mode *fixed_mode =
|
||||
intel_panel_fixed_mode(connector, adjusted_mode);
|
||||
|
||||
if (!fixed_mode)
|
||||
return 0;
|
||||
|
@ -75,128 +149,142 @@ int intel_panel_compute_config(struct intel_connector *connector,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool is_downclock_mode(const struct drm_display_mode *downclock_mode,
|
||||
const struct drm_display_mode *fixed_mode)
|
||||
static bool is_alt_fixed_mode(const struct drm_display_mode *mode,
|
||||
const struct drm_display_mode *preferred_mode)
|
||||
{
|
||||
return drm_mode_match(downclock_mode, fixed_mode,
|
||||
return drm_mode_match(mode, preferred_mode,
|
||||
DRM_MODE_MATCH_TIMINGS |
|
||||
DRM_MODE_MATCH_FLAGS |
|
||||
DRM_MODE_MATCH_3D_FLAGS) &&
|
||||
downclock_mode->clock < fixed_mode->clock;
|
||||
mode->clock != preferred_mode->clock;
|
||||
}
|
||||
|
||||
struct drm_display_mode *
|
||||
intel_panel_edid_downclock_mode(struct intel_connector *connector,
|
||||
const struct drm_display_mode *fixed_mode)
|
||||
static void intel_panel_add_edid_alt_fixed_modes(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
const struct drm_display_mode *scan, *best_mode = NULL;
|
||||
struct drm_display_mode *downclock_mode;
|
||||
int best_clock = fixed_mode->clock;
|
||||
const struct drm_display_mode *preferred_mode =
|
||||
intel_panel_preferred_fixed_mode(connector);
|
||||
struct drm_display_mode *mode, *next;
|
||||
|
||||
list_for_each_entry_safe(mode, next, &connector->base.probed_modes, head) {
|
||||
if (!is_alt_fixed_mode(mode, preferred_mode))
|
||||
continue;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"[CONNECTOR:%d:%s] using alternate EDID fixed mode: " DRM_MODE_FMT "\n",
|
||||
connector->base.base.id, connector->base.name,
|
||||
DRM_MODE_ARG(mode));
|
||||
|
||||
list_move_tail(&mode->head, &connector->panel.fixed_modes);
|
||||
}
|
||||
}
|
||||
|
||||
static void intel_panel_add_edid_preferred_mode(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct drm_display_mode *scan, *fixed_mode = NULL;
|
||||
|
||||
if (list_empty(&connector->base.probed_modes))
|
||||
return;
|
||||
|
||||
/* make sure the preferred mode is first */
|
||||
list_for_each_entry(scan, &connector->base.probed_modes, head) {
|
||||
/*
|
||||
* If one mode has the same resolution with the fixed_panel
|
||||
* mode while they have the different refresh rate, it means
|
||||
* that the reduced downclock is found. In such
|
||||
* case we can set the different FPx0/1 to dynamically select
|
||||
* between low and high frequency.
|
||||
*/
|
||||
if (is_downclock_mode(scan, fixed_mode) &&
|
||||
scan->clock < best_clock) {
|
||||
/*
|
||||
* The downclock is already found. But we
|
||||
* expect to find the lower downclock.
|
||||
*/
|
||||
best_clock = scan->clock;
|
||||
best_mode = scan;
|
||||
if (scan->type & DRM_MODE_TYPE_PREFERRED) {
|
||||
fixed_mode = scan;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!best_mode)
|
||||
return NULL;
|
||||
|
||||
downclock_mode = drm_mode_duplicate(&dev_priv->drm, best_mode);
|
||||
if (!downclock_mode)
|
||||
return NULL;
|
||||
if (!fixed_mode)
|
||||
fixed_mode = list_first_entry(&connector->base.probed_modes,
|
||||
typeof(*fixed_mode), head);
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"[CONNECTOR:%d:%s] using downclock mode from EDID: ",
|
||||
connector->base.base.id, connector->base.name);
|
||||
drm_mode_debug_printmodeline(downclock_mode);
|
||||
"[CONNECTOR:%d:%s] using %s EDID fixed mode: " DRM_MODE_FMT "\n",
|
||||
connector->base.base.id, connector->base.name,
|
||||
fixed_mode->type & DRM_MODE_TYPE_PREFERRED ? "preferred" : "first",
|
||||
DRM_MODE_ARG(fixed_mode));
|
||||
|
||||
return downclock_mode;
|
||||
fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
|
||||
|
||||
list_move_tail(&fixed_mode->head, &connector->panel.fixed_modes);
|
||||
}
|
||||
|
||||
struct drm_display_mode *
|
||||
intel_panel_edid_fixed_mode(struct intel_connector *connector)
|
||||
static void intel_panel_destroy_probed_modes(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
const struct drm_display_mode *scan;
|
||||
struct drm_display_mode *fixed_mode;
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
struct drm_display_mode *mode, *next;
|
||||
|
||||
if (list_empty(&connector->base.probed_modes))
|
||||
return NULL;
|
||||
|
||||
/* prefer fixed mode from EDID if available */
|
||||
list_for_each_entry(scan, &connector->base.probed_modes, head) {
|
||||
if ((scan->type & DRM_MODE_TYPE_PREFERRED) == 0)
|
||||
continue;
|
||||
|
||||
fixed_mode = drm_mode_duplicate(&dev_priv->drm, scan);
|
||||
if (!fixed_mode)
|
||||
return NULL;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"[CONNECTOR:%d:%s] using preferred mode from EDID: ",
|
||||
connector->base.base.id, connector->base.name);
|
||||
drm_mode_debug_printmodeline(fixed_mode);
|
||||
|
||||
return fixed_mode;
|
||||
list_for_each_entry_safe(mode, next, &connector->base.probed_modes, head) {
|
||||
list_del(&mode->head);
|
||||
drm_mode_destroy(&i915->drm, mode);
|
||||
}
|
||||
|
||||
scan = list_first_entry(&connector->base.probed_modes,
|
||||
typeof(*scan), head);
|
||||
|
||||
fixed_mode = drm_mode_duplicate(&dev_priv->drm, scan);
|
||||
if (!fixed_mode)
|
||||
return NULL;
|
||||
|
||||
fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"[CONNECTOR:%d:%s] using first mode from EDID: ",
|
||||
connector->base.base.id, connector->base.name);
|
||||
drm_mode_debug_printmodeline(fixed_mode);
|
||||
|
||||
return fixed_mode;
|
||||
}
|
||||
|
||||
struct drm_display_mode *
|
||||
intel_panel_vbt_fixed_mode(struct intel_connector *connector)
|
||||
void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, bool has_drrs)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
intel_panel_add_edid_preferred_mode(connector);
|
||||
if (intel_panel_preferred_fixed_mode(connector) && has_drrs)
|
||||
intel_panel_add_edid_alt_fixed_modes(connector);
|
||||
intel_panel_destroy_probed_modes(connector);
|
||||
}
|
||||
|
||||
static void intel_panel_add_fixed_mode(struct intel_connector *connector,
|
||||
struct drm_display_mode *fixed_mode,
|
||||
const char *type)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
struct drm_display_info *info = &connector->base.display_info;
|
||||
struct drm_display_mode *fixed_mode;
|
||||
|
||||
if (!dev_priv->vbt.lfp_lvds_vbt_mode)
|
||||
return NULL;
|
||||
|
||||
fixed_mode = drm_mode_duplicate(&dev_priv->drm,
|
||||
dev_priv->vbt.lfp_lvds_vbt_mode);
|
||||
if (!fixed_mode)
|
||||
return NULL;
|
||||
return;
|
||||
|
||||
fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] using mode from VBT: ",
|
||||
connector->base.base.id, connector->base.name);
|
||||
drm_mode_debug_printmodeline(fixed_mode);
|
||||
fixed_mode->type |= DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
|
||||
|
||||
info->width_mm = fixed_mode->width_mm;
|
||||
info->height_mm = fixed_mode->height_mm;
|
||||
|
||||
return fixed_mode;
|
||||
drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] using %s fixed mode: " DRM_MODE_FMT "\n",
|
||||
connector->base.base.id, connector->base.name, type,
|
||||
DRM_MODE_ARG(fixed_mode));
|
||||
|
||||
list_add_tail(&fixed_mode->head, &connector->panel.fixed_modes);
|
||||
}
|
||||
|
||||
void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
const struct drm_display_mode *mode;
|
||||
|
||||
mode = i915->vbt.lfp_lvds_vbt_mode;
|
||||
if (!mode)
|
||||
return;
|
||||
|
||||
intel_panel_add_fixed_mode(connector,
|
||||
drm_mode_duplicate(&i915->drm, mode),
|
||||
"VBT LFP");
|
||||
}
|
||||
|
||||
void intel_panel_add_vbt_sdvo_fixed_mode(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
const struct drm_display_mode *mode;
|
||||
|
||||
mode = i915->vbt.sdvo_lvds_vbt_mode;
|
||||
if (!mode)
|
||||
return;
|
||||
|
||||
intel_panel_add_fixed_mode(connector,
|
||||
drm_mode_duplicate(&i915->drm, mode),
|
||||
"VBT SDVO");
|
||||
}
|
||||
|
||||
void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector,
|
||||
struct intel_encoder *encoder)
|
||||
{
|
||||
intel_panel_add_fixed_mode(connector,
|
||||
intel_encoder_current_mode(encoder),
|
||||
"current (BIOS)");
|
||||
}
|
||||
|
||||
/* adjusted_mode has been preset to be the panel's fixed mode */
|
||||
|
@ -205,18 +293,20 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state,
|
|||
{
|
||||
const struct drm_display_mode *adjusted_mode =
|
||||
&crtc_state->hw.adjusted_mode;
|
||||
int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
|
||||
int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
|
||||
int x, y, width, height;
|
||||
|
||||
/* Native modes don't need fitting */
|
||||
if (adjusted_mode->crtc_hdisplay == crtc_state->pipe_src_w &&
|
||||
adjusted_mode->crtc_vdisplay == crtc_state->pipe_src_h &&
|
||||
if (adjusted_mode->crtc_hdisplay == pipe_src_w &&
|
||||
adjusted_mode->crtc_vdisplay == pipe_src_h &&
|
||||
crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420)
|
||||
return 0;
|
||||
|
||||
switch (conn_state->scaling_mode) {
|
||||
case DRM_MODE_SCALE_CENTER:
|
||||
width = crtc_state->pipe_src_w;
|
||||
height = crtc_state->pipe_src_h;
|
||||
width = pipe_src_w;
|
||||
height = pipe_src_h;
|
||||
x = (adjusted_mode->crtc_hdisplay - width + 1)/2;
|
||||
y = (adjusted_mode->crtc_vdisplay - height + 1)/2;
|
||||
break;
|
||||
|
@ -224,19 +314,17 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state,
|
|||
case DRM_MODE_SCALE_ASPECT:
|
||||
/* Scale but preserve the aspect ratio */
|
||||
{
|
||||
u32 scaled_width = adjusted_mode->crtc_hdisplay
|
||||
* crtc_state->pipe_src_h;
|
||||
u32 scaled_height = crtc_state->pipe_src_w
|
||||
* adjusted_mode->crtc_vdisplay;
|
||||
u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h;
|
||||
u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay;
|
||||
if (scaled_width > scaled_height) { /* pillar */
|
||||
width = scaled_height / crtc_state->pipe_src_h;
|
||||
width = scaled_height / pipe_src_h;
|
||||
if (width & 1)
|
||||
width++;
|
||||
x = (adjusted_mode->crtc_hdisplay - width + 1) / 2;
|
||||
y = 0;
|
||||
height = adjusted_mode->crtc_vdisplay;
|
||||
} else if (scaled_width < scaled_height) { /* letter */
|
||||
height = scaled_width / crtc_state->pipe_src_w;
|
||||
height = scaled_width / pipe_src_w;
|
||||
if (height & 1)
|
||||
height++;
|
||||
y = (adjusted_mode->crtc_vdisplay - height + 1) / 2;
|
||||
|
@ -251,8 +339,8 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state,
|
|||
break;
|
||||
|
||||
case DRM_MODE_SCALE_NONE:
|
||||
WARN_ON(adjusted_mode->crtc_hdisplay != crtc_state->pipe_src_w);
|
||||
WARN_ON(adjusted_mode->crtc_vdisplay != crtc_state->pipe_src_h);
|
||||
WARN_ON(adjusted_mode->crtc_hdisplay != pipe_src_w);
|
||||
WARN_ON(adjusted_mode->crtc_vdisplay != pipe_src_h);
|
||||
fallthrough;
|
||||
case DRM_MODE_SCALE_FULLSCREEN:
|
||||
x = y = 0;
|
||||
|
@ -333,10 +421,10 @@ static void i965_scale_aspect(struct intel_crtc_state *crtc_state,
|
|||
{
|
||||
const struct drm_display_mode *adjusted_mode =
|
||||
&crtc_state->hw.adjusted_mode;
|
||||
u32 scaled_width = adjusted_mode->crtc_hdisplay *
|
||||
crtc_state->pipe_src_h;
|
||||
u32 scaled_height = crtc_state->pipe_src_w *
|
||||
adjusted_mode->crtc_vdisplay;
|
||||
int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
|
||||
int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
|
||||
u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h;
|
||||
u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay;
|
||||
|
||||
/* 965+ is easy, it does everything in hw */
|
||||
if (scaled_width > scaled_height)
|
||||
|
@ -345,7 +433,7 @@ static void i965_scale_aspect(struct intel_crtc_state *crtc_state,
|
|||
else if (scaled_width < scaled_height)
|
||||
*pfit_control |= PFIT_ENABLE |
|
||||
PFIT_SCALING_LETTER;
|
||||
else if (adjusted_mode->crtc_hdisplay != crtc_state->pipe_src_w)
|
||||
else if (adjusted_mode->crtc_hdisplay != pipe_src_w)
|
||||
*pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
|
||||
}
|
||||
|
||||
|
@ -354,10 +442,10 @@ static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state,
|
|||
u32 *border)
|
||||
{
|
||||
struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
|
||||
u32 scaled_width = adjusted_mode->crtc_hdisplay *
|
||||
crtc_state->pipe_src_h;
|
||||
u32 scaled_height = crtc_state->pipe_src_w *
|
||||
adjusted_mode->crtc_vdisplay;
|
||||
int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
|
||||
int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
|
||||
u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h;
|
||||
u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay;
|
||||
u32 bits;
|
||||
|
||||
/*
|
||||
|
@ -367,12 +455,11 @@ static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state,
|
|||
*/
|
||||
if (scaled_width > scaled_height) { /* pillar */
|
||||
centre_horizontally(adjusted_mode,
|
||||
scaled_height /
|
||||
crtc_state->pipe_src_h);
|
||||
scaled_height / pipe_src_h);
|
||||
|
||||
*border = LVDS_BORDER_ENABLE;
|
||||
if (crtc_state->pipe_src_h != adjusted_mode->crtc_vdisplay) {
|
||||
bits = panel_fitter_scaling(crtc_state->pipe_src_h,
|
||||
if (pipe_src_h != adjusted_mode->crtc_vdisplay) {
|
||||
bits = panel_fitter_scaling(pipe_src_h,
|
||||
adjusted_mode->crtc_vdisplay);
|
||||
|
||||
*pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
|
||||
|
@ -383,12 +470,11 @@ static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state,
|
|||
}
|
||||
} else if (scaled_width < scaled_height) { /* letter */
|
||||
centre_vertically(adjusted_mode,
|
||||
scaled_width /
|
||||
crtc_state->pipe_src_w);
|
||||
scaled_width / pipe_src_w);
|
||||
|
||||
*border = LVDS_BORDER_ENABLE;
|
||||
if (crtc_state->pipe_src_w != adjusted_mode->crtc_hdisplay) {
|
||||
bits = panel_fitter_scaling(crtc_state->pipe_src_w,
|
||||
if (pipe_src_w != adjusted_mode->crtc_hdisplay) {
|
||||
bits = panel_fitter_scaling(pipe_src_w,
|
||||
adjusted_mode->crtc_hdisplay);
|
||||
|
||||
*pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
|
||||
|
@ -413,10 +499,12 @@ static int gmch_panel_fitting(struct intel_crtc_state *crtc_state,
|
|||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
|
||||
struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
|
||||
int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
|
||||
int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
|
||||
|
||||
/* Native modes don't need fitting */
|
||||
if (adjusted_mode->crtc_hdisplay == crtc_state->pipe_src_w &&
|
||||
adjusted_mode->crtc_vdisplay == crtc_state->pipe_src_h)
|
||||
if (adjusted_mode->crtc_hdisplay == pipe_src_w &&
|
||||
adjusted_mode->crtc_vdisplay == pipe_src_h)
|
||||
goto out;
|
||||
|
||||
switch (conn_state->scaling_mode) {
|
||||
|
@ -425,8 +513,8 @@ static int gmch_panel_fitting(struct intel_crtc_state *crtc_state,
|
|||
* For centered modes, we have to calculate border widths &
|
||||
* heights and modify the values programmed into the CRTC.
|
||||
*/
|
||||
centre_horizontally(adjusted_mode, crtc_state->pipe_src_w);
|
||||
centre_vertically(adjusted_mode, crtc_state->pipe_src_h);
|
||||
centre_horizontally(adjusted_mode, pipe_src_w);
|
||||
centre_vertically(adjusted_mode, pipe_src_h);
|
||||
border = LVDS_BORDER_ENABLE;
|
||||
break;
|
||||
case DRM_MODE_SCALE_ASPECT:
|
||||
|
@ -442,8 +530,8 @@ static int gmch_panel_fitting(struct intel_crtc_state *crtc_state,
|
|||
* Full scaling, even if it changes the aspect ratio.
|
||||
* Fortunately this is all done for us in hw.
|
||||
*/
|
||||
if (crtc_state->pipe_src_h != adjusted_mode->crtc_vdisplay ||
|
||||
crtc_state->pipe_src_w != adjusted_mode->crtc_hdisplay) {
|
||||
if (pipe_src_h != adjusted_mode->crtc_vdisplay ||
|
||||
pipe_src_w != adjusted_mode->crtc_hdisplay) {
|
||||
pfit_control |= PFIT_ENABLE;
|
||||
if (DISPLAY_VER(dev_priv) >= 4)
|
||||
pfit_control |= PFIT_SCALING_AUTO;
|
||||
|
@ -508,7 +596,8 @@ enum drm_mode_status
|
|||
intel_panel_mode_valid(struct intel_connector *connector,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
const struct drm_display_mode *fixed_mode = connector->panel.fixed_mode;
|
||||
const struct drm_display_mode *fixed_mode =
|
||||
intel_panel_fixed_mode(connector, mode);
|
||||
|
||||
if (!fixed_mode)
|
||||
return MODE_OK;
|
||||
|
@ -525,29 +614,29 @@ intel_panel_mode_valid(struct intel_connector *connector,
|
|||
return MODE_OK;
|
||||
}
|
||||
|
||||
int intel_panel_init(struct intel_panel *panel,
|
||||
struct drm_display_mode *fixed_mode,
|
||||
struct drm_display_mode *downclock_mode)
|
||||
int intel_panel_init(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
|
||||
intel_backlight_init_funcs(panel);
|
||||
|
||||
panel->fixed_mode = fixed_mode;
|
||||
panel->downclock_mode = downclock_mode;
|
||||
drm_dbg_kms(connector->base.dev,
|
||||
"[CONNECTOR:%d:%s] DRRS type: %s\n",
|
||||
connector->base.base.id, connector->base.name,
|
||||
intel_drrs_type_str(intel_panel_drrs_type(connector)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void intel_panel_fini(struct intel_panel *panel)
|
||||
void intel_panel_fini(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_connector *intel_connector =
|
||||
container_of(panel, struct intel_connector, panel);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
struct drm_display_mode *fixed_mode, *next;
|
||||
|
||||
intel_backlight_destroy(panel);
|
||||
|
||||
if (panel->fixed_mode)
|
||||
drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
|
||||
|
||||
if (panel->downclock_mode)
|
||||
drm_mode_destroy(intel_connector->base.dev,
|
||||
panel->downclock_mode);
|
||||
list_for_each_entry_safe(fixed_mode, next, &panel->fixed_modes, head) {
|
||||
list_del(&fixed_mode->head);
|
||||
drm_mode_destroy(connector->base.dev, fixed_mode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,23 +9,30 @@
|
|||
#include <linux/types.h>
|
||||
|
||||
enum drm_connector_status;
|
||||
enum drrs_type;
|
||||
struct drm_connector;
|
||||
struct drm_connector_state;
|
||||
struct drm_display_mode;
|
||||
struct drm_i915_private;
|
||||
struct intel_connector;
|
||||
struct intel_crtc_state;
|
||||
struct intel_panel;
|
||||
struct intel_encoder;
|
||||
|
||||
int intel_panel_init(struct intel_panel *panel,
|
||||
struct drm_display_mode *fixed_mode,
|
||||
struct drm_display_mode *downclock_mode);
|
||||
void intel_panel_fini(struct intel_panel *panel);
|
||||
int intel_panel_init(struct intel_connector *connector);
|
||||
void intel_panel_fini(struct intel_connector *connector);
|
||||
enum drm_connector_status
|
||||
intel_panel_detect(struct drm_connector *connector, bool force);
|
||||
bool intel_panel_use_ssc(struct drm_i915_private *i915);
|
||||
void intel_panel_fixed_mode(const struct drm_display_mode *fixed_mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
const struct drm_display_mode *
|
||||
intel_panel_preferred_fixed_mode(struct intel_connector *connector);
|
||||
const struct drm_display_mode *
|
||||
intel_panel_fixed_mode(struct intel_connector *connector,
|
||||
const struct drm_display_mode *mode);
|
||||
const struct drm_display_mode *
|
||||
intel_panel_downclock_mode(struct intel_connector *connector,
|
||||
const struct drm_display_mode *adjusted_mode);
|
||||
int intel_panel_get_modes(struct intel_connector *connector);
|
||||
enum drrs_type intel_panel_drrs_type(struct intel_connector *connector);
|
||||
enum drm_mode_status
|
||||
intel_panel_mode_valid(struct intel_connector *connector,
|
||||
const struct drm_display_mode *mode);
|
||||
|
@ -33,12 +40,10 @@ int intel_panel_fitting(struct intel_crtc_state *crtc_state,
|
|||
const struct drm_connector_state *conn_state);
|
||||
int intel_panel_compute_config(struct intel_connector *connector,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
struct drm_display_mode *
|
||||
intel_panel_edid_downclock_mode(struct intel_connector *connector,
|
||||
const struct drm_display_mode *fixed_mode);
|
||||
struct drm_display_mode *
|
||||
intel_panel_edid_fixed_mode(struct intel_connector *connector);
|
||||
struct drm_display_mode *
|
||||
intel_panel_vbt_fixed_mode(struct intel_connector *connector);
|
||||
void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, bool has_drrs);
|
||||
void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector);
|
||||
void intel_panel_add_vbt_sdvo_fixed_mode(struct intel_connector *connector);
|
||||
void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector,
|
||||
struct intel_encoder *encoder);
|
||||
|
||||
#endif /* __INTEL_PANEL_H__ */
|
||||
|
|
|
@ -14,6 +14,23 @@
|
|||
#include "intel_pps.h"
|
||||
#include "intel_sdvo.h"
|
||||
|
||||
bool intel_has_pch_trancoder(struct drm_i915_private *i915,
|
||||
enum pipe pch_transcoder)
|
||||
{
|
||||
return HAS_PCH_IBX(i915) || HAS_PCH_CPT(i915) ||
|
||||
(HAS_PCH_LPT_H(i915) && pch_transcoder == PIPE_A);
|
||||
}
|
||||
|
||||
enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
|
||||
if (HAS_PCH_LPT(i915))
|
||||
return PIPE_A;
|
||||
else
|
||||
return crtc->pipe;
|
||||
}
|
||||
|
||||
static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
|
||||
enum pipe pipe, enum port port,
|
||||
i915_reg_t dp_reg)
|
||||
|
@ -88,6 +105,67 @@ static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
|
|||
pipe_name(pipe));
|
||||
}
|
||||
|
||||
static void ibx_sanitize_pch_hdmi_port(struct drm_i915_private *dev_priv,
|
||||
enum port port, i915_reg_t hdmi_reg)
|
||||
{
|
||||
u32 val = intel_de_read(dev_priv, hdmi_reg);
|
||||
|
||||
if (val & SDVO_ENABLE ||
|
||||
(val & SDVO_PIPE_SEL_MASK) == SDVO_PIPE_SEL(PIPE_A))
|
||||
return;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Sanitizing transcoder select for HDMI %c\n",
|
||||
port_name(port));
|
||||
|
||||
val &= ~SDVO_PIPE_SEL_MASK;
|
||||
val |= SDVO_PIPE_SEL(PIPE_A);
|
||||
|
||||
intel_de_write(dev_priv, hdmi_reg, val);
|
||||
}
|
||||
|
||||
static void ibx_sanitize_pch_dp_port(struct drm_i915_private *dev_priv,
|
||||
enum port port, i915_reg_t dp_reg)
|
||||
{
|
||||
u32 val = intel_de_read(dev_priv, dp_reg);
|
||||
|
||||
if (val & DP_PORT_EN ||
|
||||
(val & DP_PIPE_SEL_MASK) == DP_PIPE_SEL(PIPE_A))
|
||||
return;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Sanitizing transcoder select for DP %c\n",
|
||||
port_name(port));
|
||||
|
||||
val &= ~DP_PIPE_SEL_MASK;
|
||||
val |= DP_PIPE_SEL(PIPE_A);
|
||||
|
||||
intel_de_write(dev_priv, dp_reg, val);
|
||||
}
|
||||
|
||||
static void ibx_sanitize_pch_ports(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
/*
|
||||
* The BIOS may select transcoder B on some of the PCH
|
||||
* ports even it doesn't enable the port. This would trip
|
||||
* assert_pch_dp_disabled() and assert_pch_hdmi_disabled().
|
||||
* Sanitize the transcoder select bits to prevent that. We
|
||||
* assume that the BIOS never actually enabled the port,
|
||||
* because if it did we'd actually have to toggle the port
|
||||
* on and back off to make the transcoder A select stick
|
||||
* (see. intel_dp_link_down(), intel_disable_hdmi(),
|
||||
* intel_disable_sdvo()).
|
||||
*/
|
||||
ibx_sanitize_pch_dp_port(dev_priv, PORT_B, PCH_DP_B);
|
||||
ibx_sanitize_pch_dp_port(dev_priv, PORT_C, PCH_DP_C);
|
||||
ibx_sanitize_pch_dp_port(dev_priv, PORT_D, PCH_DP_D);
|
||||
|
||||
/* PCH SDVOB multiplex with HDMIB */
|
||||
ibx_sanitize_pch_hdmi_port(dev_priv, PORT_B, PCH_HDMIB);
|
||||
ibx_sanitize_pch_hdmi_port(dev_priv, PORT_C, PCH_HDMIC);
|
||||
ibx_sanitize_pch_hdmi_port(dev_priv, PORT_D, PCH_HDMID);
|
||||
}
|
||||
|
||||
static void intel_pch_transcoder_set_m1_n1(struct intel_crtc *crtc,
|
||||
const struct intel_link_m_n *m_n)
|
||||
{
|
||||
|
@ -181,7 +259,7 @@ static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state)
|
|||
val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
|
||||
/* Configure frame start delay to match the CPU */
|
||||
val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
|
||||
val |= TRANS_CHICKEN2_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
|
||||
val |= TRANS_CHICKEN2_FRAME_START_DELAY(crtc_state->framestart_delay - 1);
|
||||
intel_de_write(dev_priv, reg, val);
|
||||
}
|
||||
|
||||
|
@ -192,7 +270,7 @@ static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state)
|
|||
if (HAS_PCH_IBX(dev_priv)) {
|
||||
/* Configure frame start delay to match the CPU */
|
||||
val &= ~TRANS_FRAME_START_DELAY_MASK;
|
||||
val |= TRANS_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
|
||||
val |= TRANS_FRAME_START_DELAY(crtc_state->framestart_delay - 1);
|
||||
|
||||
/*
|
||||
* Make the BPC in transcoder be consistent with
|
||||
|
@ -466,9 +544,11 @@ void ilk_pch_get_config(struct intel_crtc_state *crtc_state)
|
|||
ilk_pch_clock_get(crtc_state);
|
||||
}
|
||||
|
||||
static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
|
||||
enum transcoder cpu_transcoder)
|
||||
static void lpt_enable_pch_transcoder(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
||||
u32 val, pipeconf_val;
|
||||
|
||||
/* FDI must be feeding us bits for PCH ports */
|
||||
|
@ -480,7 +560,7 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
|
|||
val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
|
||||
/* Configure frame start delay to match the CPU */
|
||||
val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
|
||||
val |= TRANS_CHICKEN2_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
|
||||
val |= TRANS_CHICKEN2_FRAME_START_DELAY(crtc_state->framestart_delay - 1);
|
||||
intel_de_write(dev_priv, TRANS_CHICKEN2(PIPE_A), val);
|
||||
|
||||
val = TRANS_ENABLE;
|
||||
|
@ -521,7 +601,6 @@ void lpt_pch_enable(struct intel_atomic_state *state,
|
|||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
const struct intel_crtc_state *crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
||||
|
||||
assert_pch_transcoder_disabled(dev_priv, PIPE_A);
|
||||
|
||||
|
@ -530,7 +609,7 @@ void lpt_pch_enable(struct intel_atomic_state *state,
|
|||
/* Set transcoder timing. */
|
||||
ilk_pch_transcoder_set_timings(crtc_state, PIPE_A);
|
||||
|
||||
lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);
|
||||
lpt_enable_pch_transcoder(crtc_state);
|
||||
}
|
||||
|
||||
void lpt_pch_disable(struct intel_atomic_state *state,
|
||||
|
@ -563,3 +642,9 @@ void lpt_pch_get_config(struct intel_crtc_state *crtc_state)
|
|||
|
||||
crtc_state->hw.adjusted_mode.crtc_clock = lpt_get_iclkip(dev_priv);
|
||||
}
|
||||
|
||||
void intel_pch_sanitize(struct drm_i915_private *i915)
|
||||
{
|
||||
if (HAS_PCH_IBX(i915))
|
||||
ibx_sanitize_pch_ports(i915);
|
||||
}
|
||||
|
|
|
@ -6,11 +6,19 @@
|
|||
#ifndef _INTEL_PCH_DISPLAY_H_
|
||||
#define _INTEL_PCH_DISPLAY_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
enum pipe;
|
||||
struct drm_i915_private;
|
||||
struct intel_atomic_state;
|
||||
struct intel_crtc;
|
||||
struct intel_crtc_state;
|
||||
struct intel_link_m_n;
|
||||
|
||||
bool intel_has_pch_trancoder(struct drm_i915_private *i915,
|
||||
enum pipe pch_transcoder);
|
||||
enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc);
|
||||
|
||||
void ilk_pch_pre_enable(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc);
|
||||
void ilk_pch_enable(struct intel_atomic_state *state,
|
||||
|
@ -32,4 +40,6 @@ void intel_pch_transcoder_get_m1_n1(struct intel_crtc *crtc,
|
|||
void intel_pch_transcoder_get_m2_n2(struct intel_crtc *crtc,
|
||||
struct intel_link_m_n *m_n);
|
||||
|
||||
void intel_pch_sanitize(struct drm_i915_private *i915);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -171,6 +171,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
|
|||
case DRM_FORMAT_MOD_LINEAR:
|
||||
case I915_FORMAT_MOD_X_TILED:
|
||||
case I915_FORMAT_MOD_Y_TILED:
|
||||
case I915_FORMAT_MOD_4_TILED:
|
||||
break;
|
||||
default:
|
||||
drm_dbg(&dev_priv->drm,
|
||||
|
|
|
@ -100,11 +100,15 @@ static bool psr_global_enabled(struct intel_dp *intel_dp)
|
|||
|
||||
static bool psr2_global_enabled(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
|
||||
|
||||
switch (intel_dp->psr.debug & I915_PSR_DEBUG_MODE_MASK) {
|
||||
case I915_PSR_DEBUG_DISABLE:
|
||||
case I915_PSR_DEBUG_FORCE_PSR1:
|
||||
return false;
|
||||
default:
|
||||
if (i915->params.enable_psr == 1)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1217,6 +1221,7 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp,
|
|||
intel_dp->psr.dc3co_exit_delay = val;
|
||||
intel_dp->psr.dc3co_exitline = crtc_state->dc3co_exitline;
|
||||
intel_dp->psr.psr2_sel_fetch_enabled = crtc_state->enable_psr2_sel_fetch;
|
||||
intel_dp->psr.psr2_sel_fetch_cff_enabled = false;
|
||||
intel_dp->psr.req_psr2_sdp_prior_scanline =
|
||||
crtc_state->req_psr2_sdp_prior_scanline;
|
||||
|
||||
|
@ -1432,28 +1437,42 @@ void intel_psr_resume(struct intel_dp *intel_dp)
|
|||
mutex_unlock(&psr->lock);
|
||||
}
|
||||
|
||||
static inline u32 man_trk_ctl_single_full_frame_bit_get(struct drm_i915_private *dev_priv)
|
||||
static u32 man_trk_ctl_enable_bit_get(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
return IS_ALDERLAKE_P(dev_priv) ? 0 : PSR2_MAN_TRK_CTL_ENABLE;
|
||||
}
|
||||
|
||||
static u32 man_trk_ctl_single_full_frame_bit_get(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
return IS_ALDERLAKE_P(dev_priv) ?
|
||||
ADLP_PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME :
|
||||
PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME;
|
||||
}
|
||||
|
||||
static inline u32 man_trk_ctl_partial_frame_bit_get(struct drm_i915_private *dev_priv)
|
||||
static u32 man_trk_ctl_partial_frame_bit_get(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
return IS_ALDERLAKE_P(dev_priv) ?
|
||||
ADLP_PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE :
|
||||
PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE;
|
||||
}
|
||||
|
||||
static u32 man_trk_ctl_continuos_full_frame(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
return IS_ALDERLAKE_P(dev_priv) ?
|
||||
ADLP_PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME :
|
||||
PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME;
|
||||
}
|
||||
|
||||
static void psr_force_hw_tracking_exit(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
|
||||
if (intel_dp->psr.psr2_sel_fetch_enabled)
|
||||
intel_de_rmw(dev_priv,
|
||||
PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder), 0,
|
||||
man_trk_ctl_single_full_frame_bit_get(dev_priv));
|
||||
intel_de_write(dev_priv,
|
||||
PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder),
|
||||
man_trk_ctl_enable_bit_get(dev_priv) |
|
||||
man_trk_ctl_partial_frame_bit_get(dev_priv) |
|
||||
man_trk_ctl_single_full_frame_bit_get(dev_priv));
|
||||
|
||||
/*
|
||||
* Display WA #0884: skl+
|
||||
|
@ -1537,10 +1556,21 @@ void intel_psr2_program_plane_sel_fetch(struct intel_plane *plane,
|
|||
void intel_psr2_program_trans_man_trk_ctl(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
|
||||
struct intel_encoder *encoder;
|
||||
|
||||
if (!crtc_state->enable_psr2_sel_fetch)
|
||||
return;
|
||||
|
||||
for_each_intel_encoder_mask_with_psr(&dev_priv->drm, encoder,
|
||||
crtc_state->uapi.encoder_mask) {
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
|
||||
lockdep_assert_held(&intel_dp->psr.lock);
|
||||
if (intel_dp->psr.psr2_sel_fetch_cff_enabled)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(crtc_state->cpu_transcoder),
|
||||
crtc_state->psr2_man_track_ctl);
|
||||
}
|
||||
|
@ -1550,10 +1580,7 @@ static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state,
|
|||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
u32 val = 0;
|
||||
|
||||
if (!IS_ALDERLAKE_P(dev_priv))
|
||||
val = PSR2_MAN_TRK_CTL_ENABLE;
|
||||
u32 val = man_trk_ctl_enable_bit_get(dev_priv);
|
||||
|
||||
/* SF partial frame enable has to be set even on full update */
|
||||
val |= man_trk_ctl_partial_frame_bit_get(dev_priv);
|
||||
|
@ -1911,13 +1938,13 @@ static int _psr1_ready_for_pipe_update_locked(struct intel_dp *intel_dp)
|
|||
}
|
||||
|
||||
/**
|
||||
* intel_psr_wait_for_idle - wait for PSR be ready for a pipe update
|
||||
* intel_psr_wait_for_idle_locked - wait for PSR be ready for a pipe update
|
||||
* @new_crtc_state: new CRTC state
|
||||
*
|
||||
* This function is expected to be called from pipe_update_start() where it is
|
||||
* not expected to race with PSR enable or disable.
|
||||
*/
|
||||
void intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state)
|
||||
void intel_psr_wait_for_idle_locked(const struct intel_crtc_state *new_crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(new_crtc_state->uapi.crtc->dev);
|
||||
struct intel_encoder *encoder;
|
||||
|
@ -1930,12 +1957,10 @@ void intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state)
|
|||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&intel_dp->psr.lock);
|
||||
lockdep_assert_held(&intel_dp->psr.lock);
|
||||
|
||||
if (!intel_dp->psr.enabled) {
|
||||
mutex_unlock(&intel_dp->psr.lock);
|
||||
if (!intel_dp->psr.enabled)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (intel_dp->psr.psr2_enabled)
|
||||
ret = _psr2_ready_for_pipe_update_locked(intel_dp);
|
||||
|
@ -1944,8 +1969,6 @@ void intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state)
|
|||
|
||||
if (ret)
|
||||
drm_err(&dev_priv->drm, "PSR wait timed out, atomic update may fail\n");
|
||||
|
||||
mutex_unlock(&intel_dp->psr.lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2122,6 +2145,27 @@ static void intel_psr_work(struct work_struct *work)
|
|||
mutex_unlock(&intel_dp->psr.lock);
|
||||
}
|
||||
|
||||
static void _psr_invalidate_handle(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
|
||||
if (intel_dp->psr.psr2_sel_fetch_enabled) {
|
||||
u32 val;
|
||||
|
||||
if (intel_dp->psr.psr2_sel_fetch_cff_enabled)
|
||||
return;
|
||||
|
||||
val = man_trk_ctl_enable_bit_get(dev_priv) |
|
||||
man_trk_ctl_partial_frame_bit_get(dev_priv) |
|
||||
man_trk_ctl_continuos_full_frame(dev_priv);
|
||||
intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder), val);
|
||||
intel_de_write(dev_priv, CURSURFLIVE(intel_dp->psr.pipe), 0);
|
||||
intel_dp->psr.psr2_sel_fetch_cff_enabled = true;
|
||||
} else {
|
||||
intel_psr_exit(intel_dp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_psr_invalidate - Invalidade PSR
|
||||
* @dev_priv: i915 device
|
||||
|
@ -2158,7 +2202,7 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv,
|
|||
intel_dp->psr.busy_frontbuffer_bits |= pipe_frontbuffer_bits;
|
||||
|
||||
if (pipe_frontbuffer_bits)
|
||||
intel_psr_exit(intel_dp);
|
||||
_psr_invalidate_handle(intel_dp);
|
||||
|
||||
mutex_unlock(&intel_dp->psr.lock);
|
||||
}
|
||||
|
@ -2190,6 +2234,42 @@ tgl_dc3co_flush_locked(struct intel_dp *intel_dp, unsigned int frontbuffer_bits,
|
|||
intel_dp->psr.dc3co_exit_delay);
|
||||
}
|
||||
|
||||
static void _psr_flush_handle(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
|
||||
if (intel_dp->psr.psr2_sel_fetch_enabled) {
|
||||
if (intel_dp->psr.psr2_sel_fetch_cff_enabled) {
|
||||
/* can we turn CFF off? */
|
||||
if (intel_dp->psr.busy_frontbuffer_bits == 0) {
|
||||
u32 val = man_trk_ctl_enable_bit_get(dev_priv) |
|
||||
man_trk_ctl_partial_frame_bit_get(dev_priv) |
|
||||
man_trk_ctl_single_full_frame_bit_get(dev_priv);
|
||||
|
||||
/*
|
||||
* turn continuous full frame off and do a single
|
||||
* full frame
|
||||
*/
|
||||
intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder),
|
||||
val);
|
||||
intel_de_write(dev_priv, CURSURFLIVE(intel_dp->psr.pipe), 0);
|
||||
intel_dp->psr.psr2_sel_fetch_cff_enabled = false;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* continuous full frame is disabled, only a single full
|
||||
* frame is required
|
||||
*/
|
||||
psr_force_hw_tracking_exit(intel_dp);
|
||||
}
|
||||
} else {
|
||||
psr_force_hw_tracking_exit(intel_dp);
|
||||
|
||||
if (!intel_dp->psr.active && !intel_dp->psr.busy_frontbuffer_bits)
|
||||
schedule_work(&intel_dp->psr.work);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_psr_flush - Flush PSR
|
||||
* @dev_priv: i915 device
|
||||
|
@ -2227,25 +2307,22 @@ void intel_psr_flush(struct drm_i915_private *dev_priv,
|
|||
* we have to ensure that the PSR is not activated until
|
||||
* intel_psr_resume() is called.
|
||||
*/
|
||||
if (intel_dp->psr.paused) {
|
||||
mutex_unlock(&intel_dp->psr.lock);
|
||||
continue;
|
||||
}
|
||||
if (intel_dp->psr.paused)
|
||||
goto unlock;
|
||||
|
||||
if (origin == ORIGIN_FLIP ||
|
||||
(origin == ORIGIN_CURSOR_UPDATE &&
|
||||
!intel_dp->psr.psr2_sel_fetch_enabled)) {
|
||||
tgl_dc3co_flush_locked(intel_dp, frontbuffer_bits, origin);
|
||||
mutex_unlock(&intel_dp->psr.lock);
|
||||
continue;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* By definition flush = invalidate + flush */
|
||||
if (pipe_frontbuffer_bits)
|
||||
psr_force_hw_tracking_exit(intel_dp);
|
||||
if (pipe_frontbuffer_bits == 0)
|
||||
goto unlock;
|
||||
|
||||
if (!intel_dp->psr.active && !intel_dp->psr.busy_frontbuffer_bits)
|
||||
schedule_work(&intel_dp->psr.work);
|
||||
/* By definition flush = invalidate + flush */
|
||||
_psr_flush_handle(intel_dp);
|
||||
unlock:
|
||||
mutex_unlock(&intel_dp->psr.lock);
|
||||
}
|
||||
}
|
||||
|
@ -2436,3 +2513,51 @@ bool intel_psr_enabled(struct intel_dp *intel_dp)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_psr_lock - grab PSR lock
|
||||
* @crtc_state: the crtc state
|
||||
*
|
||||
* This is initially meant to be used by around CRTC update, when
|
||||
* vblank sensitive registers are updated and we need grab the lock
|
||||
* before it to avoid vblank evasion.
|
||||
*/
|
||||
void intel_psr_lock(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
|
||||
struct intel_encoder *encoder;
|
||||
|
||||
if (!crtc_state->has_psr)
|
||||
return;
|
||||
|
||||
for_each_intel_encoder_mask_with_psr(&i915->drm, encoder,
|
||||
crtc_state->uapi.encoder_mask) {
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
|
||||
mutex_lock(&intel_dp->psr.lock);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_psr_unlock - release PSR lock
|
||||
* @crtc_state: the crtc state
|
||||
*
|
||||
* Release the PSR lock that was held during pipe update.
|
||||
*/
|
||||
void intel_psr_unlock(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
|
||||
struct intel_encoder *encoder;
|
||||
|
||||
if (!crtc_state->has_psr)
|
||||
return;
|
||||
|
||||
for_each_intel_encoder_mask_with_psr(&i915->drm, encoder,
|
||||
crtc_state->uapi.encoder_mask) {
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
|
||||
mutex_unlock(&intel_dp->psr.lock);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ void intel_psr_get_config(struct intel_encoder *encoder,
|
|||
struct intel_crtc_state *pipe_config);
|
||||
void intel_psr_irq_handler(struct intel_dp *intel_dp, u32 psr_iir);
|
||||
void intel_psr_short_pulse(struct intel_dp *intel_dp);
|
||||
void intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state);
|
||||
void intel_psr_wait_for_idle_locked(const struct intel_crtc_state *new_crtc_state);
|
||||
bool intel_psr_enabled(struct intel_dp *intel_dp);
|
||||
int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc);
|
||||
|
@ -55,4 +55,7 @@ void intel_psr2_disable_plane_sel_fetch(struct intel_plane *plane,
|
|||
void intel_psr_pause(struct intel_dp *intel_dp);
|
||||
void intel_psr_resume(struct intel_dp *intel_dp);
|
||||
|
||||
void intel_psr_lock(const struct intel_crtc_state *crtc_state);
|
||||
void intel_psr_unlock(const struct intel_crtc_state *crtc_state);
|
||||
|
||||
#endif /* __INTEL_PSR_H__ */
|
||||
|
|
|
@ -283,7 +283,7 @@ static bool intel_sdvo_read_byte(struct intel_sdvo *intel_sdvo, u8 addr, u8 *ch)
|
|||
static const struct {
|
||||
u8 cmd;
|
||||
const char *name;
|
||||
} __attribute__ ((packed)) sdvo_cmd_names[] = {
|
||||
} __packed sdvo_cmd_names[] = {
|
||||
SDVO_CMD_NAME_ENTRY(RESET),
|
||||
SDVO_CMD_NAME_ENTRY(GET_DEVICE_CAPS),
|
||||
SDVO_CMD_NAME_ENTRY(GET_FIRMWARE_REV),
|
||||
|
@ -783,24 +783,22 @@ static bool intel_sdvo_get_input_timing(struct intel_sdvo *intel_sdvo,
|
|||
static bool
|
||||
intel_sdvo_create_preferred_input_timing(struct intel_sdvo *intel_sdvo,
|
||||
struct intel_sdvo_connector *intel_sdvo_connector,
|
||||
u16 clock,
|
||||
u16 width,
|
||||
u16 height)
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct intel_sdvo_preferred_input_timing_args args;
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.clock = clock;
|
||||
args.width = width;
|
||||
args.height = height;
|
||||
args.clock = mode->clock / 10;
|
||||
args.width = mode->hdisplay;
|
||||
args.height = mode->vdisplay;
|
||||
args.interlace = 0;
|
||||
|
||||
if (IS_LVDS(intel_sdvo_connector)) {
|
||||
const struct drm_display_mode *fixed_mode =
|
||||
intel_sdvo_connector->base.panel.fixed_mode;
|
||||
intel_panel_fixed_mode(&intel_sdvo_connector->base, mode);
|
||||
|
||||
if (fixed_mode->hdisplay != width ||
|
||||
fixed_mode->vdisplay != height)
|
||||
if (fixed_mode->hdisplay != args.width ||
|
||||
fixed_mode->vdisplay != args.height)
|
||||
args.scaled = 1;
|
||||
}
|
||||
|
||||
|
@ -1236,9 +1234,7 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo,
|
|||
|
||||
if (!intel_sdvo_create_preferred_input_timing(intel_sdvo,
|
||||
intel_sdvo_connector,
|
||||
mode->clock / 10,
|
||||
mode->hdisplay,
|
||||
mode->vdisplay))
|
||||
mode))
|
||||
return false;
|
||||
|
||||
if (!intel_sdvo_get_preferred_input_timing(intel_sdvo,
|
||||
|
@ -1335,6 +1331,8 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
|
|||
adjusted_mode);
|
||||
pipe_config->sdvo_tv_clock = true;
|
||||
} else if (IS_LVDS(intel_sdvo_connector)) {
|
||||
const struct drm_display_mode *fixed_mode =
|
||||
intel_panel_fixed_mode(&intel_sdvo_connector->base, mode);
|
||||
int ret;
|
||||
|
||||
ret = intel_panel_compute_config(&intel_sdvo_connector->base,
|
||||
|
@ -1342,8 +1340,7 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo,
|
||||
intel_sdvo_connector->base.panel.fixed_mode))
|
||||
if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, fixed_mode))
|
||||
return -EINVAL;
|
||||
|
||||
(void) intel_sdvo_get_preferred_input_mode(intel_sdvo,
|
||||
|
@ -1465,7 +1462,7 @@ static void intel_sdvo_pre_enable(struct intel_atomic_state *state,
|
|||
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
|
||||
const struct intel_sdvo_connector_state *sdvo_state =
|
||||
to_intel_sdvo_connector_state(conn_state);
|
||||
const struct intel_sdvo_connector *intel_sdvo_connector =
|
||||
struct intel_sdvo_connector *intel_sdvo_connector =
|
||||
to_intel_sdvo_connector(conn_state->connector);
|
||||
const struct drm_display_mode *mode = &crtc_state->hw.mode;
|
||||
struct intel_sdvo *intel_sdvo = to_sdvo(intel_encoder);
|
||||
|
@ -1496,11 +1493,14 @@ static void intel_sdvo_pre_enable(struct intel_atomic_state *state,
|
|||
return;
|
||||
|
||||
/* lvds has a special fixed output timing. */
|
||||
if (IS_LVDS(intel_sdvo_connector))
|
||||
intel_sdvo_get_dtd_from_mode(&output_dtd,
|
||||
intel_sdvo_connector->base.panel.fixed_mode);
|
||||
else
|
||||
if (IS_LVDS(intel_sdvo_connector)) {
|
||||
const struct drm_display_mode *fixed_mode =
|
||||
intel_panel_fixed_mode(&intel_sdvo_connector->base, mode);
|
||||
|
||||
intel_sdvo_get_dtd_from_mode(&output_dtd, fixed_mode);
|
||||
} else {
|
||||
intel_sdvo_get_dtd_from_mode(&output_dtd, mode);
|
||||
}
|
||||
if (!intel_sdvo_set_output_timing(intel_sdvo, &output_dtd))
|
||||
drm_info(&dev_priv->drm,
|
||||
"Setting output timings on %s failed\n",
|
||||
|
@ -2291,33 +2291,12 @@ static int intel_sdvo_get_lvds_modes(struct drm_connector *connector)
|
|||
{
|
||||
struct intel_sdvo *intel_sdvo = intel_attached_sdvo(to_intel_connector(connector));
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
||||
struct drm_display_mode *newmode;
|
||||
int num_modes = 0;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s]\n",
|
||||
connector->base.id, connector->name);
|
||||
|
||||
/*
|
||||
* Fetch modes from VBT. For SDVO prefer the VBT mode since some
|
||||
* SDVO->LVDS transcoders can't cope with the EDID mode.
|
||||
*/
|
||||
if (dev_priv->vbt.sdvo_lvds_vbt_mode != NULL) {
|
||||
newmode = drm_mode_duplicate(connector->dev,
|
||||
dev_priv->vbt.sdvo_lvds_vbt_mode);
|
||||
if (newmode != NULL) {
|
||||
/* Guarantee the mode is preferred */
|
||||
newmode->type = (DRM_MODE_TYPE_PREFERRED |
|
||||
DRM_MODE_TYPE_DRIVER);
|
||||
drm_mode_probed_add(connector, newmode);
|
||||
num_modes++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to get the mode list from DDC.
|
||||
* Assume that the preferred modes are
|
||||
* arranged in priority order.
|
||||
*/
|
||||
num_modes += intel_panel_get_modes(to_intel_connector(connector));
|
||||
num_modes += intel_ddc_get_modes(connector, &intel_sdvo->ddc);
|
||||
|
||||
return num_modes;
|
||||
|
@ -2747,6 +2726,8 @@ static struct intel_sdvo_connector *intel_sdvo_connector_alloc(void)
|
|||
__drm_atomic_helper_connector_reset(&sdvo_connector->base.base,
|
||||
&conn_state->base.base);
|
||||
|
||||
INIT_LIST_HEAD(&sdvo_connector->base.panel.fixed_modes);
|
||||
|
||||
return sdvo_connector;
|
||||
}
|
||||
|
||||
|
@ -2890,7 +2871,6 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
|
|||
struct drm_connector *connector;
|
||||
struct intel_connector *intel_connector;
|
||||
struct intel_sdvo_connector *intel_sdvo_connector;
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
DRM_DEBUG_KMS("initialising LVDS device %d\n", device);
|
||||
|
||||
|
@ -2919,20 +2899,20 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
|
|||
if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
|
||||
goto err;
|
||||
|
||||
intel_sdvo_get_lvds_modes(connector);
|
||||
/*
|
||||
* Fetch modes from VBT. For SDVO prefer the VBT mode since some
|
||||
* SDVO->LVDS transcoders can't cope with the EDID mode.
|
||||
*/
|
||||
intel_panel_add_vbt_sdvo_fixed_mode(intel_connector);
|
||||
|
||||
list_for_each_entry(mode, &connector->probed_modes, head) {
|
||||
if (mode->type & DRM_MODE_TYPE_PREFERRED) {
|
||||
struct drm_display_mode *fixed_mode =
|
||||
drm_mode_duplicate(connector->dev, mode);
|
||||
|
||||
intel_panel_init(&intel_connector->panel,
|
||||
fixed_mode, NULL);
|
||||
break;
|
||||
}
|
||||
if (!intel_panel_preferred_fixed_mode(intel_connector)) {
|
||||
intel_ddc_get_modes(connector, &intel_sdvo->ddc);
|
||||
intel_panel_add_edid_fixed_modes(intel_connector, false);
|
||||
}
|
||||
|
||||
if (!intel_connector->panel.fixed_mode)
|
||||
intel_panel_init(intel_connector);
|
||||
|
||||
if (!intel_panel_preferred_fixed_mode(intel_connector))
|
||||
goto err;
|
||||
|
||||
return true;
|
||||
|
|
|
@ -32,10 +32,14 @@ void intel_snps_phy_wait_for_calibration(struct drm_i915_private *i915)
|
|||
if (!intel_phy_is_snps(i915, phy))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If calibration does not complete successfully, we'll remember
|
||||
* which phy was affected and skip setup of the corresponding
|
||||
* output later.
|
||||
*/
|
||||
if (intel_de_wait_for_clear(i915, DG2_PHY_MISC(phy),
|
||||
DG2_PHY_DP_TX_ACK_MASK, 25))
|
||||
drm_err(&i915->drm, "SNPS PHY %c failed to calibrate after 25ms.\n",
|
||||
phy_name(phy));
|
||||
i915->snps_phy_failed_calibration |= BIT(phy);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
* support.
|
||||
*/
|
||||
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_color_mgmt.h>
|
||||
|
@ -96,13 +98,13 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
|
|||
|
||||
if (src_x % hsub || src_w % hsub) {
|
||||
drm_dbg_kms(&i915->drm, "src x/w (%u, %u) must be a multiple of %u (rotated: %s)\n",
|
||||
src_x, src_w, hsub, yesno(rotated));
|
||||
src_x, src_w, hsub, str_yes_no(rotated));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (src_y % vsub || src_h % vsub) {
|
||||
drm_dbg_kms(&i915->drm, "src y/h (%u, %u) must be a multiple of %u (rotated: %s)\n",
|
||||
src_y, src_h, vsub, yesno(rotated));
|
||||
src_y, src_h, vsub, str_yes_no(rotated));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -430,9 +432,6 @@ vlv_sprite_update_noarm(struct intel_plane *plane,
|
|||
int crtc_y = plane_state->uapi.dst.y1;
|
||||
u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
|
||||
u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
intel_de_write_fw(dev_priv, SPSTRIDE(pipe, plane_id),
|
||||
plane_state->view.color_plane[0].mapping_stride);
|
||||
|
@ -440,8 +439,6 @@ vlv_sprite_update_noarm(struct intel_plane *plane,
|
|||
SP_POS_Y(crtc_y) | SP_POS_X(crtc_x));
|
||||
intel_de_write_fw(dev_priv, SPSIZE(pipe, plane_id),
|
||||
SP_HEIGHT(crtc_h - 1) | SP_WIDTH(crtc_w - 1));
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -457,14 +454,11 @@ vlv_sprite_update_arm(struct intel_plane *plane,
|
|||
u32 x = plane_state->view.color_plane[0].x;
|
||||
u32 y = plane_state->view.color_plane[0].y;
|
||||
u32 sprctl, linear_offset;
|
||||
unsigned long irqflags;
|
||||
|
||||
sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
|
||||
|
||||
linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
|
||||
chv_sprite_update_csc(plane_state);
|
||||
|
||||
|
@ -494,8 +488,6 @@ vlv_sprite_update_arm(struct intel_plane *plane,
|
|||
|
||||
vlv_sprite_update_clrc(plane_state);
|
||||
vlv_sprite_update_gamma(plane_state);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -505,14 +497,9 @@ vlv_sprite_disable_arm(struct intel_plane *plane,
|
|||
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
||||
enum pipe pipe = plane->pipe;
|
||||
enum plane_id plane_id = plane->id;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), 0);
|
||||
intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id), 0);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -862,15 +849,12 @@ ivb_sprite_update_noarm(struct intel_plane *plane,
|
|||
u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
|
||||
u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
|
||||
u32 sprscale = 0;
|
||||
unsigned long irqflags;
|
||||
|
||||
if (crtc_w != src_w || crtc_h != src_h)
|
||||
sprscale = SPRITE_SCALE_ENABLE |
|
||||
SPRITE_SRC_WIDTH(src_w - 1) |
|
||||
SPRITE_SRC_HEIGHT(src_h - 1);
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
intel_de_write_fw(dev_priv, SPRSTRIDE(pipe),
|
||||
plane_state->view.color_plane[0].mapping_stride);
|
||||
intel_de_write_fw(dev_priv, SPRPOS(pipe),
|
||||
|
@ -879,8 +863,6 @@ ivb_sprite_update_noarm(struct intel_plane *plane,
|
|||
SPRITE_HEIGHT(crtc_h - 1) | SPRITE_WIDTH(crtc_w - 1));
|
||||
if (IS_IVYBRIDGE(dev_priv))
|
||||
intel_de_write_fw(dev_priv, SPRSCALE(pipe), sprscale);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -895,14 +877,11 @@ ivb_sprite_update_arm(struct intel_plane *plane,
|
|||
u32 x = plane_state->view.color_plane[0].x;
|
||||
u32 y = plane_state->view.color_plane[0].y;
|
||||
u32 sprctl, linear_offset;
|
||||
unsigned long irqflags;
|
||||
|
||||
sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
|
||||
|
||||
linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
if (key->flags) {
|
||||
intel_de_write_fw(dev_priv, SPRKEYVAL(pipe), key->min_value);
|
||||
intel_de_write_fw(dev_priv, SPRKEYMSK(pipe),
|
||||
|
@ -931,8 +910,6 @@ ivb_sprite_update_arm(struct intel_plane *plane,
|
|||
intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
|
||||
|
||||
ivb_sprite_update_gamma(plane_state);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -941,17 +918,12 @@ ivb_sprite_disable_arm(struct intel_plane *plane,
|
|||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
||||
enum pipe pipe = plane->pipe;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
intel_de_write_fw(dev_priv, SPRCTL(pipe), 0);
|
||||
/* Disable the scaler */
|
||||
if (IS_IVYBRIDGE(dev_priv))
|
||||
intel_de_write_fw(dev_priv, SPRSCALE(pipe), 0);
|
||||
intel_de_write_fw(dev_priv, SPRSURF(pipe), 0);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -1204,15 +1176,12 @@ g4x_sprite_update_noarm(struct intel_plane *plane,
|
|||
u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
|
||||
u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
|
||||
u32 dvsscale = 0;
|
||||
unsigned long irqflags;
|
||||
|
||||
if (crtc_w != src_w || crtc_h != src_h)
|
||||
dvsscale = DVS_SCALE_ENABLE |
|
||||
DVS_SRC_WIDTH(src_w - 1) |
|
||||
DVS_SRC_HEIGHT(src_h - 1);
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
intel_de_write_fw(dev_priv, DVSSTRIDE(pipe),
|
||||
plane_state->view.color_plane[0].mapping_stride);
|
||||
intel_de_write_fw(dev_priv, DVSPOS(pipe),
|
||||
|
@ -1220,8 +1189,6 @@ g4x_sprite_update_noarm(struct intel_plane *plane,
|
|||
intel_de_write_fw(dev_priv, DVSSIZE(pipe),
|
||||
DVS_HEIGHT(crtc_h - 1) | DVS_WIDTH(crtc_w - 1));
|
||||
intel_de_write_fw(dev_priv, DVSSCALE(pipe), dvsscale);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1236,14 +1203,11 @@ g4x_sprite_update_arm(struct intel_plane *plane,
|
|||
u32 x = plane_state->view.color_plane[0].x;
|
||||
u32 y = plane_state->view.color_plane[0].y;
|
||||
u32 dvscntr, linear_offset;
|
||||
unsigned long irqflags;
|
||||
|
||||
dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
|
||||
|
||||
linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
if (key->flags) {
|
||||
intel_de_write_fw(dev_priv, DVSKEYVAL(pipe), key->min_value);
|
||||
intel_de_write_fw(dev_priv, DVSKEYMSK(pipe),
|
||||
|
@ -1267,8 +1231,6 @@ g4x_sprite_update_arm(struct intel_plane *plane,
|
|||
g4x_sprite_update_gamma(plane_state);
|
||||
else
|
||||
ilk_sprite_update_gamma(plane_state);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1277,16 +1239,11 @@ g4x_sprite_disable_arm(struct intel_plane *plane,
|
|||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
||||
enum pipe pipe = plane->pipe;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
intel_de_write_fw(dev_priv, DVSCNTR(pipe), 0);
|
||||
/* Disable the scaler */
|
||||
intel_de_write_fw(dev_priv, DVSSCALE(pipe), 0);
|
||||
intel_de_write_fw(dev_priv, DVSSURF(pipe), 0);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
|
@ -1145,8 +1145,8 @@ intel_tv_get_config(struct intel_encoder *encoder,
|
|||
|
||||
intel_tv_mode_to_mode(&mode, &tv_mode);
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "TV mode:\n");
|
||||
drm_mode_debug_printmodeline(&mode);
|
||||
drm_dbg_kms(&dev_priv->drm, "TV mode: " DRM_MODE_FMT "\n",
|
||||
DRM_MODE_ARG(&mode));
|
||||
|
||||
intel_tv_scale_mode_horiz(&mode, hdisplay,
|
||||
xpos, mode.hdisplay - xsize - xpos);
|
||||
|
@ -1250,8 +1250,8 @@ intel_tv_compute_config(struct intel_encoder *encoder,
|
|||
tv_conn_state->bypass_vfilter = false;
|
||||
}
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "TV mode:\n");
|
||||
drm_mode_debug_printmodeline(adjusted_mode);
|
||||
drm_dbg_kms(&dev_priv->drm, "TV mode: " DRM_MODE_FMT "\n",
|
||||
DRM_MODE_ARG(adjusted_mode));
|
||||
|
||||
/*
|
||||
* The pipe scanline counter behaviour looks as follows when
|
||||
|
@ -1806,8 +1806,8 @@ intel_tv_get_modes(struct drm_connector *connector)
|
|||
*/
|
||||
intel_tv_mode_to_mode(mode, tv_mode);
|
||||
if (count == 0) {
|
||||
drm_dbg_kms(&dev_priv->drm, "TV mode:\n");
|
||||
drm_mode_debug_printmodeline(mode);
|
||||
drm_dbg_kms(&dev_priv->drm, "TV mode: " DRM_MODE_FMT "\n",
|
||||
DRM_MODE_ARG(mode));
|
||||
}
|
||||
intel_tv_scale_mode_horiz(mode, input->w, 0, 0);
|
||||
intel_tv_scale_mode_vert(mode, input->h, 0, 0);
|
||||
|
|
|
@ -289,6 +289,9 @@ struct bdb_general_features {
|
|||
#define HDMI_MAX_DATA_RATE_PLATFORM 0 /* 204 */
|
||||
#define HDMI_MAX_DATA_RATE_297 1 /* 204 */
|
||||
#define HDMI_MAX_DATA_RATE_165 2 /* 204 */
|
||||
#define HDMI_MAX_DATA_RATE_594 3 /* 249 */
|
||||
#define HDMI_MAX_DATA_RATE_340 4 /* 249 */
|
||||
#define HDMI_MAX_DATA_RATE_300 5 /* 249 */
|
||||
|
||||
#define LEGACY_CHILD_DEVICE_CONFIG_SIZE 33
|
||||
|
||||
|
@ -719,20 +722,22 @@ struct bdb_lvds_options {
|
|||
/*
|
||||
* Block 41 - LFP Data Table Pointers
|
||||
*/
|
||||
struct lvds_lfp_data_ptr_table {
|
||||
u16 offset; /* offsets are from start of bdb */
|
||||
u8 table_size;
|
||||
} __packed;
|
||||
|
||||
/* LFP pointer table contains entries to the struct below */
|
||||
struct lvds_lfp_data_ptr {
|
||||
u16 fp_timing_offset; /* offsets are from start of bdb */
|
||||
u8 fp_table_size;
|
||||
u16 dvo_timing_offset;
|
||||
u8 dvo_table_size;
|
||||
u16 panel_pnp_id_offset;
|
||||
u8 pnp_table_size;
|
||||
struct lvds_lfp_data_ptr_table fp_timing;
|
||||
struct lvds_lfp_data_ptr_table dvo_timing;
|
||||
struct lvds_lfp_data_ptr_table panel_pnp_id;
|
||||
} __packed;
|
||||
|
||||
struct bdb_lvds_lfp_data_ptrs {
|
||||
u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
|
||||
struct lvds_lfp_data_ptr ptr[16];
|
||||
struct lvds_lfp_data_ptr_table panel_name; /* 156-163? */
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
|
@ -774,6 +779,10 @@ struct bdb_lvds_lfp_data {
|
|||
struct lvds_lfp_data_entry data[16];
|
||||
} __packed;
|
||||
|
||||
struct lvds_lfp_panel_name {
|
||||
u8 name[13];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Block 43 - LFP Backlight Control Data Block
|
||||
*/
|
||||
|
|
|
@ -378,10 +378,18 @@ calculate_rc_params(struct rc_parameters *rc,
|
|||
{
|
||||
int bpc = vdsc_cfg->bits_per_component;
|
||||
int bpp = vdsc_cfg->bits_per_pixel >> 4;
|
||||
int ofs_und6[] = { 0, -2, -2, -4, -6, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 };
|
||||
int ofs_und8[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 };
|
||||
int ofs_und12[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 };
|
||||
int ofs_und15[] = { 10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12 };
|
||||
static const s8 ofs_und6[] = {
|
||||
0, -2, -2, -4, -6, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12
|
||||
};
|
||||
static const s8 ofs_und8[] = {
|
||||
2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12
|
||||
};
|
||||
static const s8 ofs_und12[] = {
|
||||
2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12
|
||||
};
|
||||
static const s8 ofs_und15[] = {
|
||||
10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12
|
||||
};
|
||||
int qp_bpc_modifier = (bpc - 8) * 2;
|
||||
u32 res, buf_i, bpp_i;
|
||||
|
||||
|
@ -579,7 +587,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
|
|||
u8 num_vdsc_instances = (crtc_state->dsc.dsc_split) ? 2 : 1;
|
||||
int i = 0;
|
||||
|
||||
if (crtc_state->bigjoiner)
|
||||
if (crtc_state->bigjoiner_pipes)
|
||||
num_vdsc_instances *= 2;
|
||||
|
||||
/* Populate PICTURE_PARAMETER_SET_0 registers */
|
||||
|
@ -1113,7 +1121,7 @@ void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state)
|
|||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
u32 dss_ctl1_val = 0;
|
||||
|
||||
if (crtc_state->bigjoiner && !crtc_state->dsc.compression_enable) {
|
||||
if (crtc_state->bigjoiner_pipes && !crtc_state->dsc.compression_enable) {
|
||||
if (intel_crtc_is_bigjoiner_slave(crtc_state))
|
||||
dss_ctl1_val |= UNCOMPRESSED_JOINER_SLAVE;
|
||||
else
|
||||
|
@ -1140,7 +1148,7 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
|
|||
dss_ctl2_val |= RIGHT_BRANCH_VDSC_ENABLE;
|
||||
dss_ctl1_val |= JOINER_ENABLE;
|
||||
}
|
||||
if (crtc_state->bigjoiner) {
|
||||
if (crtc_state->bigjoiner_pipes) {
|
||||
dss_ctl1_val |= BIG_JOINER_ENABLE;
|
||||
if (!intel_crtc_is_bigjoiner_slave(crtc_state))
|
||||
dss_ctl1_val |= MASTER_BIG_JOINER_ENABLE;
|
||||
|
@ -1156,7 +1164,7 @@ void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state)
|
|||
|
||||
/* Disable only if either of them is enabled */
|
||||
if (old_crtc_state->dsc.compression_enable ||
|
||||
old_crtc_state->bigjoiner) {
|
||||
old_crtc_state->bigjoiner_pipes) {
|
||||
intel_de_write(dev_priv, dss_ctl1_reg(crtc, old_crtc_state->cpu_transcoder), 0);
|
||||
intel_de_write(dev_priv, dss_ctl2_reg(crtc, old_crtc_state->cpu_transcoder), 0);
|
||||
}
|
||||
|
|
|
@ -69,9 +69,9 @@ static int intel_vrr_vblank_exit_length(const struct intel_crtc_state *crtc_stat
|
|||
|
||||
/* The hw imposes the extra scanline before frame start */
|
||||
if (DISPLAY_VER(i915) >= 13)
|
||||
return crtc_state->vrr.guardband + i915->framestart_delay + 1;
|
||||
return crtc_state->vrr.guardband + crtc_state->framestart_delay + 1;
|
||||
else
|
||||
return crtc_state->vrr.pipeline_full + i915->framestart_delay + 1;
|
||||
return crtc_state->vrr.pipeline_full + crtc_state->framestart_delay + 1;
|
||||
}
|
||||
|
||||
int intel_vrr_vmin_vblank_start(const struct intel_crtc_state *crtc_state)
|
||||
|
|
|
@ -197,7 +197,8 @@ int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state)
|
|||
return skl_update_scaler(crtc_state, !crtc_state->hw.active,
|
||||
SKL_CRTC_INDEX,
|
||||
&crtc_state->scaler_state.scaler_id,
|
||||
crtc_state->pipe_src_w, crtc_state->pipe_src_h,
|
||||
drm_rect_width(&crtc_state->pipe_src),
|
||||
drm_rect_height(&crtc_state->pipe_src),
|
||||
width, height, NULL, 0,
|
||||
crtc_state->pch_pfit.enabled);
|
||||
}
|
||||
|
@ -400,10 +401,6 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
|
|||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
const struct intel_crtc_scaler_state *scaler_state =
|
||||
&crtc_state->scaler_state;
|
||||
struct drm_rect src = {
|
||||
.x2 = crtc_state->pipe_src_w << 16,
|
||||
.y2 = crtc_state->pipe_src_h << 16,
|
||||
};
|
||||
const struct drm_rect *dst = &crtc_state->pch_pfit.dst;
|
||||
u16 uv_rgb_hphase, uv_rgb_vphase;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
@ -412,7 +409,7 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
|
|||
int x = dst->x1;
|
||||
int y = dst->y1;
|
||||
int hscale, vscale;
|
||||
unsigned long irqflags;
|
||||
struct drm_rect src;
|
||||
int id;
|
||||
u32 ps_ctrl;
|
||||
|
||||
|
@ -423,6 +420,10 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
|
|||
crtc_state->scaler_state.scaler_id < 0))
|
||||
return;
|
||||
|
||||
drm_rect_init(&src, 0, 0,
|
||||
drm_rect_width(&crtc_state->pipe_src) << 16,
|
||||
drm_rect_height(&crtc_state->pipe_src) << 16);
|
||||
|
||||
hscale = drm_rect_calc_hscale(&src, dst, 0, INT_MAX);
|
||||
vscale = drm_rect_calc_vscale(&src, dst, 0, INT_MAX);
|
||||
|
||||
|
@ -434,8 +435,6 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
|
|||
ps_ctrl = skl_scaler_get_filter_select(crtc_state->hw.scaling_filter, 0);
|
||||
ps_ctrl |= PS_SCALER_EN | scaler_state->scalers[id].mode;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
skl_scaler_setup_filter(dev_priv, pipe, id, 0,
|
||||
crtc_state->hw.scaling_filter);
|
||||
|
||||
|
@ -449,8 +448,6 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
|
|||
x << 16 | y);
|
||||
intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(pipe, id),
|
||||
width << 16 | height);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -519,15 +516,10 @@ static void skl_detach_scaler(struct intel_crtc *crtc, int id)
|
|||
{
|
||||
struct drm_device *dev = crtc->base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
intel_de_write_fw(dev_priv, SKL_PS_CTRL(crtc->pipe, id), 0);
|
||||
intel_de_write_fw(dev_priv, SKL_PS_WIN_POS(crtc->pipe, id), 0);
|
||||
intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(crtc->pipe, id), 0);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -615,9 +615,20 @@ skl_plane_disable_arm(struct intel_plane *plane,
|
|||
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
||||
enum plane_id plane_id = plane->id;
|
||||
enum pipe pipe = plane->pipe;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
skl_write_plane_wm(plane, crtc_state);
|
||||
|
||||
intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0);
|
||||
intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0);
|
||||
}
|
||||
|
||||
static void
|
||||
icl_plane_disable_arm(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
||||
enum plane_id plane_id = plane->id;
|
||||
enum pipe pipe = plane->pipe;
|
||||
|
||||
if (icl_is_hdr_plane(dev_priv, plane_id))
|
||||
intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), 0);
|
||||
|
@ -627,8 +638,6 @@ skl_plane_disable_arm(struct intel_plane *plane,
|
|||
intel_psr2_disable_plane_sel_fetch(plane, crtc_state);
|
||||
intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0);
|
||||
intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -762,6 +771,18 @@ static u32 skl_plane_ctl_tiling(u64 fb_modifier)
|
|||
return PLANE_CTL_TILED_X;
|
||||
case I915_FORMAT_MOD_Y_TILED:
|
||||
return PLANE_CTL_TILED_Y;
|
||||
case I915_FORMAT_MOD_4_TILED:
|
||||
return PLANE_CTL_TILED_4;
|
||||
case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
|
||||
return PLANE_CTL_TILED_4 |
|
||||
PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
|
||||
PLANE_CTL_CLEAR_COLOR_DISABLE;
|
||||
case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
|
||||
return PLANE_CTL_TILED_4 |
|
||||
PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE |
|
||||
PLANE_CTL_CLEAR_COLOR_DISABLE;
|
||||
case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
|
||||
return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
|
||||
case I915_FORMAT_MOD_Y_TILED_CCS:
|
||||
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
|
||||
return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
|
||||
|
@ -1065,7 +1086,7 @@ static void icl_plane_csc_load_black(struct intel_plane *plane)
|
|||
intel_de_write_fw(i915, PLANE_CSC_POSTOFF(pipe, plane_id, 2), 0);
|
||||
}
|
||||
|
||||
static int skl_plane_color_plane(const struct intel_plane_state *plane_state)
|
||||
static int icl_plane_color_plane(const struct intel_plane_state *plane_state)
|
||||
{
|
||||
/* Program the UV plane on planar master */
|
||||
if (plane_state->planar_linked_plane && !plane_state->planar_slave)
|
||||
|
@ -1082,14 +1103,11 @@ skl_plane_update_noarm(struct intel_plane *plane,
|
|||
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
||||
enum plane_id plane_id = plane->id;
|
||||
enum pipe pipe = plane->pipe;
|
||||
int color_plane = skl_plane_color_plane(plane_state);
|
||||
u32 stride = skl_plane_stride(plane_state, color_plane);
|
||||
const struct drm_framebuffer *fb = plane_state->hw.fb;
|
||||
u32 stride = skl_plane_stride(plane_state, 0);
|
||||
int crtc_x = plane_state->uapi.dst.x1;
|
||||
int crtc_y = plane_state->uapi.dst.y1;
|
||||
u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
|
||||
u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
|
||||
unsigned long irqflags;
|
||||
|
||||
/* The scaler will handle the output position */
|
||||
if (plane_state->scaler_id >= 0) {
|
||||
|
@ -1097,15 +1115,6 @@ skl_plane_update_noarm(struct intel_plane *plane,
|
|||
crtc_y = 0;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
/*
|
||||
* FIXME: pxp session invalidation can hit any time even at time of commit
|
||||
* or after the commit, display content will be garbage.
|
||||
*/
|
||||
if (plane_state->force_black)
|
||||
icl_plane_csc_load_black(plane);
|
||||
|
||||
intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id),
|
||||
PLANE_STRIDE_(stride));
|
||||
intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id),
|
||||
|
@ -1113,25 +1122,7 @@ skl_plane_update_noarm(struct intel_plane *plane,
|
|||
intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),
|
||||
PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1));
|
||||
|
||||
if (intel_fb_is_rc_ccs_cc_modifier(fb->modifier)) {
|
||||
intel_de_write_fw(dev_priv, PLANE_CC_VAL(pipe, plane_id, 0),
|
||||
lower_32_bits(plane_state->ccval));
|
||||
intel_de_write_fw(dev_priv, PLANE_CC_VAL(pipe, plane_id, 1),
|
||||
upper_32_bits(plane_state->ccval));
|
||||
}
|
||||
|
||||
if (icl_is_hdr_plane(dev_priv, plane_id))
|
||||
intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id),
|
||||
plane_state->cus_ctl);
|
||||
|
||||
if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
|
||||
icl_program_input_csc(plane, crtc_state, plane_state);
|
||||
|
||||
skl_write_plane_wm(plane, crtc_state);
|
||||
|
||||
intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1142,21 +1133,17 @@ skl_plane_update_arm(struct intel_plane *plane,
|
|||
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
||||
enum plane_id plane_id = plane->id;
|
||||
enum pipe pipe = plane->pipe;
|
||||
int color_plane = skl_plane_color_plane(plane_state);
|
||||
u32 x = plane_state->view.color_plane[color_plane].x;
|
||||
u32 y = plane_state->view.color_plane[color_plane].y;
|
||||
u32 plane_color_ctl = 0;
|
||||
u32 plane_ctl = plane_state->ctl;
|
||||
unsigned long irqflags;
|
||||
u32 x = plane_state->view.color_plane[0].x;
|
||||
u32 y = plane_state->view.color_plane[0].y;
|
||||
u32 plane_ctl, plane_color_ctl = 0;
|
||||
|
||||
plane_ctl |= skl_plane_ctl_crtc(crtc_state);
|
||||
plane_ctl = plane_state->ctl |
|
||||
skl_plane_ctl_crtc(crtc_state);
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 10)
|
||||
plane_color_ctl = plane_state->color_ctl |
|
||||
glk_plane_color_ctl_crtc(crtc_state);
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id), skl_plane_keyval(plane_state));
|
||||
intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), skl_plane_keymsk(plane_state));
|
||||
intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), skl_plane_keymax(plane_state));
|
||||
|
@ -1165,12 +1152,11 @@ skl_plane_update_arm(struct intel_plane *plane,
|
|||
PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x));
|
||||
|
||||
intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id),
|
||||
skl_plane_aux_dist(plane_state, color_plane));
|
||||
skl_plane_aux_dist(plane_state, 0));
|
||||
|
||||
if (DISPLAY_VER(dev_priv) < 11)
|
||||
intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id),
|
||||
PLANE_OFFSET_Y(plane_state->view.color_plane[1].y) |
|
||||
PLANE_OFFSET_X(plane_state->view.color_plane[1].x));
|
||||
intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id),
|
||||
PLANE_OFFSET_Y(plane_state->view.color_plane[1].y) |
|
||||
PLANE_OFFSET_X(plane_state->view.color_plane[1].x));
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 10)
|
||||
intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
|
||||
|
@ -1192,9 +1178,116 @@ skl_plane_update_arm(struct intel_plane *plane,
|
|||
*/
|
||||
intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
|
||||
intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
|
||||
skl_plane_surf(plane_state, color_plane));
|
||||
skl_plane_surf(plane_state, 0));
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
static void
|
||||
icl_plane_update_noarm(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
||||
enum plane_id plane_id = plane->id;
|
||||
enum pipe pipe = plane->pipe;
|
||||
int color_plane = icl_plane_color_plane(plane_state);
|
||||
u32 stride = skl_plane_stride(plane_state, color_plane);
|
||||
const struct drm_framebuffer *fb = plane_state->hw.fb;
|
||||
int crtc_x = plane_state->uapi.dst.x1;
|
||||
int crtc_y = plane_state->uapi.dst.y1;
|
||||
int x = plane_state->view.color_plane[color_plane].x;
|
||||
int y = plane_state->view.color_plane[color_plane].y;
|
||||
int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
|
||||
int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
|
||||
u32 plane_color_ctl;
|
||||
|
||||
plane_color_ctl = plane_state->color_ctl |
|
||||
glk_plane_color_ctl_crtc(crtc_state);
|
||||
|
||||
/* The scaler will handle the output position */
|
||||
if (plane_state->scaler_id >= 0) {
|
||||
crtc_x = 0;
|
||||
crtc_y = 0;
|
||||
}
|
||||
|
||||
intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id),
|
||||
PLANE_STRIDE_(stride));
|
||||
intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id),
|
||||
PLANE_POS_Y(crtc_y) | PLANE_POS_X(crtc_x));
|
||||
intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),
|
||||
PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1));
|
||||
|
||||
intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id), skl_plane_keyval(plane_state));
|
||||
intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), skl_plane_keymsk(plane_state));
|
||||
intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), skl_plane_keymax(plane_state));
|
||||
|
||||
intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id),
|
||||
PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x));
|
||||
|
||||
if (intel_fb_is_rc_ccs_cc_modifier(fb->modifier)) {
|
||||
intel_de_write_fw(dev_priv, PLANE_CC_VAL(pipe, plane_id, 0),
|
||||
lower_32_bits(plane_state->ccval));
|
||||
intel_de_write_fw(dev_priv, PLANE_CC_VAL(pipe, plane_id, 1),
|
||||
upper_32_bits(plane_state->ccval));
|
||||
}
|
||||
|
||||
/* FLAT CCS doesn't need to program AUX_DIST */
|
||||
if (!HAS_FLAT_CCS(dev_priv))
|
||||
intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id),
|
||||
skl_plane_aux_dist(plane_state, color_plane));
|
||||
|
||||
if (icl_is_hdr_plane(dev_priv, plane_id))
|
||||
intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id),
|
||||
plane_state->cus_ctl);
|
||||
|
||||
intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
|
||||
|
||||
if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
|
||||
icl_program_input_csc(plane, crtc_state, plane_state);
|
||||
|
||||
skl_write_plane_wm(plane, crtc_state);
|
||||
|
||||
/*
|
||||
* FIXME: pxp session invalidation can hit any time even at time of commit
|
||||
* or after the commit, display content will be garbage.
|
||||
*/
|
||||
if (plane_state->force_black)
|
||||
icl_plane_csc_load_black(plane);
|
||||
|
||||
intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane);
|
||||
}
|
||||
|
||||
static void
|
||||
icl_plane_update_arm(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
||||
enum plane_id plane_id = plane->id;
|
||||
enum pipe pipe = plane->pipe;
|
||||
int color_plane = icl_plane_color_plane(plane_state);
|
||||
u32 plane_ctl;
|
||||
|
||||
plane_ctl = plane_state->ctl |
|
||||
skl_plane_ctl_crtc(crtc_state);
|
||||
|
||||
/*
|
||||
* Enable the scaler before the plane so that we don't
|
||||
* get a catastrophic underrun even if the two operations
|
||||
* end up happening in two different frames.
|
||||
*
|
||||
* TODO: split into noarm+arm pair
|
||||
*/
|
||||
if (plane_state->scaler_id >= 0)
|
||||
skl_program_plane_scaler(plane, crtc_state, plane_state);
|
||||
|
||||
/*
|
||||
* The control register self-arms if the plane was previously
|
||||
* disabled. Try to make the plane enable atomic by writing
|
||||
* the control register just before the surface register.
|
||||
*/
|
||||
intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
|
||||
intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
|
||||
skl_plane_surf(plane_state, color_plane));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1204,7 +1297,6 @@ skl_plane_async_flip(struct intel_plane *plane,
|
|||
bool async_flip)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
||||
unsigned long irqflags;
|
||||
enum plane_id plane_id = plane->id;
|
||||
enum pipe pipe = plane->pipe;
|
||||
u32 plane_ctl = plane_state->ctl;
|
||||
|
@ -1214,13 +1306,9 @@ skl_plane_async_flip(struct intel_plane *plane,
|
|||
if (async_flip)
|
||||
plane_ctl |= PLANE_CTL_ASYNC_FLIP;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
|
||||
intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
|
||||
skl_plane_surf(plane_state, 0));
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static bool intel_format_is_p01x(u32 format)
|
||||
|
@ -1325,7 +1413,7 @@ static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_s
|
|||
to_i915(plane_state->uapi.plane->dev);
|
||||
int crtc_x = plane_state->uapi.dst.x1;
|
||||
int crtc_w = drm_rect_width(&plane_state->uapi.dst);
|
||||
int pipe_src_w = crtc_state->pipe_src_w;
|
||||
int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
|
||||
|
||||
/*
|
||||
* Display WA #1175: glk
|
||||
|
@ -1545,9 +1633,10 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
|
|||
|
||||
/*
|
||||
* CCS AUX surface doesn't have its own x/y offsets, we must make sure
|
||||
* they match with the main surface x/y offsets.
|
||||
* they match with the main surface x/y offsets. On DG2
|
||||
* there's no aux plane on fb so skip this checking.
|
||||
*/
|
||||
if (intel_fb_is_ccs_modifier(fb->modifier)) {
|
||||
if (intel_fb_is_ccs_modifier(fb->modifier) && aux_plane) {
|
||||
while (!skl_check_main_ccs_coordinates(plane_state, x, y,
|
||||
offset, aux_plane)) {
|
||||
if (offset == 0)
|
||||
|
@ -1591,6 +1680,8 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
|
|||
const struct drm_framebuffer *fb = plane_state->hw.fb;
|
||||
unsigned int rotation = plane_state->hw.rotation;
|
||||
int uv_plane = 1;
|
||||
int ccs_plane = intel_fb_is_ccs_modifier(fb->modifier) ?
|
||||
skl_main_to_aux_plane(fb, uv_plane) : 0;
|
||||
int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation);
|
||||
int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation);
|
||||
int x = plane_state->uapi.src.x1 >> 17;
|
||||
|
@ -1611,8 +1702,7 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
|
|||
offset = intel_plane_compute_aligned_offset(&x, &y,
|
||||
plane_state, uv_plane);
|
||||
|
||||
if (intel_fb_is_ccs_modifier(fb->modifier)) {
|
||||
int ccs_plane = main_to_ccs_plane(fb, uv_plane);
|
||||
if (ccs_plane) {
|
||||
u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
|
||||
u32 alignment = intel_surf_alignment(fb, uv_plane);
|
||||
|
||||
|
@ -2011,9 +2101,7 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
|
|||
case DRM_FORMAT_Y216:
|
||||
case DRM_FORMAT_XVYU12_16161616:
|
||||
case DRM_FORMAT_XVYU16161616:
|
||||
if (modifier == DRM_FORMAT_MOD_LINEAR ||
|
||||
modifier == I915_FORMAT_MOD_X_TILED ||
|
||||
modifier == I915_FORMAT_MOD_Y_TILED)
|
||||
if (!intel_fb_is_ccs_modifier(modifier))
|
||||
return true;
|
||||
fallthrough;
|
||||
default:
|
||||
|
@ -2094,6 +2182,10 @@ static bool gen12_plane_has_mc_ccs(struct drm_i915_private *i915,
|
|||
if (IS_ADLP_DISPLAY_STEP(i915, STEP_A0, STEP_B0))
|
||||
return false;
|
||||
|
||||
/* Wa_14013215631 */
|
||||
if (IS_DG2_DISPLAY_STEP(i915, STEP_A0, STEP_C0))
|
||||
return false;
|
||||
|
||||
return plane_id < PLANE_SPRITE4;
|
||||
}
|
||||
|
||||
|
@ -2106,6 +2198,8 @@ static u8 skl_get_plane_caps(struct drm_i915_private *i915,
|
|||
caps |= INTEL_PLANE_CAP_TILING_Y;
|
||||
if (DISPLAY_VER(i915) < 12)
|
||||
caps |= INTEL_PLANE_CAP_TILING_Yf;
|
||||
if (HAS_4TILE(i915))
|
||||
caps |= INTEL_PLANE_CAP_TILING_4;
|
||||
|
||||
if (skl_plane_has_rc_ccs(i915, pipe, plane_id)) {
|
||||
caps |= INTEL_PLANE_CAP_CCS_RC;
|
||||
|
@ -2162,9 +2256,15 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
|
|||
}
|
||||
|
||||
plane->max_stride = skl_plane_max_stride;
|
||||
plane->update_noarm = skl_plane_update_noarm;
|
||||
plane->update_arm = skl_plane_update_arm;
|
||||
plane->disable_arm = skl_plane_disable_arm;
|
||||
if (DISPLAY_VER(dev_priv) >= 11) {
|
||||
plane->update_noarm = icl_plane_update_noarm;
|
||||
plane->update_arm = icl_plane_update_arm;
|
||||
plane->disable_arm = icl_plane_disable_arm;
|
||||
} else {
|
||||
plane->update_noarm = skl_plane_update_noarm;
|
||||
plane->update_arm = skl_plane_update_arm;
|
||||
plane->disable_arm = skl_plane_disable_arm;
|
||||
}
|
||||
plane->get_hw_state = skl_plane_get_hw_state;
|
||||
plane->check_plane = skl_plane_check;
|
||||
|
||||
|
@ -2278,13 +2378,14 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
|
|||
unsigned int aligned_height;
|
||||
struct drm_framebuffer *fb;
|
||||
struct intel_framebuffer *intel_fb;
|
||||
static_assert(PLANE_CTL_TILED_YF == PLANE_CTL_TILED_4);
|
||||
|
||||
if (!plane->get_hw_state(plane, &pipe))
|
||||
return;
|
||||
|
||||
drm_WARN_ON(dev, pipe != crtc->pipe);
|
||||
|
||||
if (crtc_state->bigjoiner) {
|
||||
if (crtc_state->bigjoiner_pipes) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Unsupported bigjoiner configuration for initial FB\n");
|
||||
return;
|
||||
|
@ -2332,19 +2433,34 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
|
|||
case PLANE_CTL_TILED_Y:
|
||||
plane_config->tiling = I915_TILING_Y;
|
||||
if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
|
||||
fb->modifier = DISPLAY_VER(dev_priv) >= 12 ?
|
||||
I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS :
|
||||
I915_FORMAT_MOD_Y_TILED_CCS;
|
||||
if (DISPLAY_VER(dev_priv) >= 12)
|
||||
fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS;
|
||||
else
|
||||
fb->modifier = I915_FORMAT_MOD_Y_TILED_CCS;
|
||||
else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
|
||||
fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
|
||||
else
|
||||
fb->modifier = I915_FORMAT_MOD_Y_TILED;
|
||||
break;
|
||||
case PLANE_CTL_TILED_YF:
|
||||
if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
|
||||
fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS;
|
||||
else
|
||||
fb->modifier = I915_FORMAT_MOD_Yf_TILED;
|
||||
case PLANE_CTL_TILED_YF: /* aka PLANE_CTL_TILED_4 on XE_LPD+ */
|
||||
if (HAS_4TILE(dev_priv)) {
|
||||
u32 rc_mask = PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
|
||||
PLANE_CTL_CLEAR_COLOR_DISABLE;
|
||||
|
||||
if ((val & rc_mask) == rc_mask)
|
||||
fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS;
|
||||
else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
|
||||
fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_MC_CCS;
|
||||
else if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
|
||||
fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC;
|
||||
else
|
||||
fb->modifier = I915_FORMAT_MOD_4_TILED;
|
||||
} else {
|
||||
if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
|
||||
fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS;
|
||||
else
|
||||
fb->modifier = I915_FORMAT_MOD_Yf_TILED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(tiling);
|
||||
|
|
|
@ -1660,6 +1660,8 @@ static const struct drm_connector_funcs intel_dsi_connector_funcs = {
|
|||
static void vlv_dsi_add_properties(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
const struct drm_display_mode *fixed_mode =
|
||||
intel_panel_preferred_fixed_mode(connector);
|
||||
u32 allowed_scalers;
|
||||
|
||||
allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT) | BIT(DRM_MODE_SCALE_FULLSCREEN);
|
||||
|
@ -1673,8 +1675,8 @@ static void vlv_dsi_add_properties(struct intel_connector *connector)
|
|||
|
||||
drm_connector_set_panel_orientation_with_quirk(&connector->base,
|
||||
intel_dsi_get_panel_orientation(connector),
|
||||
connector->panel.fixed_mode->hdisplay,
|
||||
connector->panel.fixed_mode->vdisplay);
|
||||
fixed_mode->hdisplay,
|
||||
fixed_mode->vdisplay);
|
||||
}
|
||||
|
||||
#define NS_KHZ_RATIO 1000000
|
||||
|
@ -1857,7 +1859,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
|
|||
struct drm_encoder *encoder;
|
||||
struct intel_connector *intel_connector;
|
||||
struct drm_connector *connector;
|
||||
struct drm_display_mode *current_mode, *fixed_mode;
|
||||
struct drm_display_mode *current_mode;
|
||||
enum port port;
|
||||
enum pipe pipe;
|
||||
|
||||
|
@ -1978,15 +1980,16 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
|
|||
intel_connector_attach_encoder(intel_connector, intel_encoder);
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
fixed_mode = intel_panel_vbt_fixed_mode(intel_connector);
|
||||
intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
|
||||
if (!fixed_mode) {
|
||||
if (!intel_panel_preferred_fixed_mode(intel_connector)) {
|
||||
drm_dbg_kms(&dev_priv->drm, "no fixed mode\n");
|
||||
goto err_cleanup_connector;
|
||||
}
|
||||
|
||||
intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
|
||||
intel_panel_init(intel_connector);
|
||||
|
||||
intel_backlight_setup(intel_connector, INVALID_PIPE);
|
||||
|
||||
vlv_dsi_add_properties(intel_connector);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_de.h"
|
||||
|
@ -393,10 +394,7 @@ static void glk_dsi_program_esc_clock(struct drm_device *dev,
|
|||
/* Calculate TXESC2 divider */
|
||||
div2_value = DIV_ROUND_UP(div1_value, txesc1_div);
|
||||
|
||||
if (div2_value < 10)
|
||||
txesc2_div = div2_value;
|
||||
else
|
||||
txesc2_div = 10;
|
||||
txesc2_div = min_t(u32, div2_value, 10);
|
||||
|
||||
intel_de_write(dev_priv, MIPIO_TXESC_CLK_DIV1,
|
||||
(1 << (txesc1_div - 1)) & GLK_TX_ESC_CLK_DIV1_MASK);
|
||||
|
@ -581,7 +579,7 @@ static void assert_dsi_pll(struct drm_i915_private *i915, bool state)
|
|||
|
||||
I915_STATE_WARN(cur_state != state,
|
||||
"DSI PLL state assertion failure (expected %s, current %s)\n",
|
||||
onoff(state), onoff(cur_state));
|
||||
str_on_off(state), str_on_off(cur_state));
|
||||
}
|
||||
|
||||
void assert_dsi_pll_enabled(struct drm_i915_private *i915)
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/nospec.h>
|
||||
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
* Copyright © 2008,2010 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/intel-iommu.h>
|
||||
#include <linux/dma-resv.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/intel-iommu.h>
|
||||
#include <linux/sync_file.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <uapi/drm/i915_drm.h>
|
||||
|
||||
#include "intel_memory_region.h"
|
||||
#include "gem/i915_gem_region.h"
|
||||
#include "gem/i915_gem_lmem.h"
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/sched/mm.h>
|
||||
|
||||
#include <drm/drm_cache.h>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "i915_drv.h"
|
||||
#include "i915_gem_object.h"
|
||||
#include "i915_gem_region.h"
|
||||
#include "i915_gem_tiling.h"
|
||||
#include "i915_scatterlist.h"
|
||||
|
||||
static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <uapi/drm/i915_drm.h>
|
||||
|
||||
#include "intel_memory_region.h"
|
||||
#include "i915_gem_region.h"
|
||||
#include "i915_drv.h"
|
||||
|
|
|
@ -12,8 +12,9 @@
|
|||
|
||||
#include "gem/i915_gem_region.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_gemfs.h"
|
||||
#include "i915_gem_object.h"
|
||||
#include "i915_gem_tiling.h"
|
||||
#include "i915_gemfs.h"
|
||||
#include "i915_scatterlist.h"
|
||||
#include "i915_trace.h"
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "i915_drv.h"
|
||||
#include "i915_gem_stolen.h"
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
#include "i915_vgpu.h"
|
||||
#include "intel_mchbar_regs.h"
|
||||
|
||||
|
@ -403,7 +404,7 @@ static int i915_gem_init_stolen(struct intel_memory_region *mem)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (intel_vtd_active(i915) && GRAPHICS_VER(i915) < 8) {
|
||||
if (i915_vtd_active(i915) && GRAPHICS_VER(i915) < 8) {
|
||||
drm_notice(&i915->drm,
|
||||
"%s, disabling use of stolen memory\n",
|
||||
"DMAR active");
|
||||
|
|
|
@ -219,6 +219,14 @@ i915_gem_object_fence_prepare(struct drm_i915_gem_object *obj,
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(obj->base.dev);
|
||||
|
||||
return to_gt(i915)->ggtt->bit_6_swizzle_x == I915_BIT_6_SWIZZLE_9_10_17 &&
|
||||
i915_gem_object_is_tiled(obj);
|
||||
}
|
||||
|
||||
int
|
||||
i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
|
||||
unsigned int tiling, unsigned int stride)
|
||||
|
|
|
@ -8,8 +8,10 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct drm_i915_gem_object;
|
||||
struct drm_i915_private;
|
||||
|
||||
bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj);
|
||||
u32 i915_gem_fence_size(struct drm_i915_private *i915, u32 size,
|
||||
unsigned int tiling, unsigned int stride);
|
||||
u32 i915_gem_fence_alignment(struct drm_i915_private *i915, u32 size,
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_gemfs.h"
|
||||
#include "i915_utils.h"
|
||||
|
||||
int i915_gemfs_init(struct drm_i915_private *i915)
|
||||
{
|
||||
|
@ -32,7 +33,7 @@ int i915_gemfs_init(struct drm_i915_private *i915)
|
|||
*/
|
||||
|
||||
opts = NULL;
|
||||
if (intel_vtd_active(i915)) {
|
||||
if (i915_vtd_active(i915)) {
|
||||
if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {
|
||||
opts = huge_opt;
|
||||
drm_info(&i915->drm,
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
*/
|
||||
|
||||
#include <linux/prime_numbers.h>
|
||||
#include <linux/string_helpers.h>
|
||||
#include <linux/swap.h>
|
||||
|
||||
#include "i915_selftest.h"
|
||||
|
||||
|
@ -804,7 +806,7 @@ static int igt_mock_ppgtt_huge_fill(void *arg)
|
|||
if (vma->resource->page_sizes_gtt != expected_gtt) {
|
||||
pr_err("gtt=%u, expected=%u, size=%zd, single=%s\n",
|
||||
vma->resource->page_sizes_gtt, expected_gtt,
|
||||
obj->base.size, yesno(!!single));
|
||||
obj->base.size, str_yes_no(!!single));
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
@ -960,7 +962,7 @@ static int igt_mock_ppgtt_64K(void *arg)
|
|||
if (vma->resource->page_sizes_gtt != expected_gtt) {
|
||||
pr_err("gtt=%u, expected=%u, i=%d, single=%s\n",
|
||||
vma->resource->page_sizes_gtt,
|
||||
expected_gtt, i, yesno(!!single));
|
||||
expected_gtt, i, str_yes_no(!!single));
|
||||
err = -EINVAL;
|
||||
goto out_vma_unpin;
|
||||
}
|
||||
|
@ -1706,14 +1708,14 @@ static int igt_shrink_thp(void *arg)
|
|||
I915_SHRINK_WRITEBACK);
|
||||
if (should_swap == i915_gem_object_has_pages(obj)) {
|
||||
pr_err("unexpected pages mismatch, should_swap=%s\n",
|
||||
yesno(should_swap));
|
||||
str_yes_no(should_swap));
|
||||
err = -EINVAL;
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
if (should_swap == (obj->mm.page_sizes.sg || obj->mm.page_sizes.phys)) {
|
||||
pr_err("unexpected residual page-size bits, should_swap=%s\n",
|
||||
yesno(should_swap));
|
||||
str_yes_no(should_swap));
|
||||
err = -EINVAL;
|
||||
goto out_put;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/prime_numbers.h>
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include "gem/i915_gem_internal.h"
|
||||
#include "gem/i915_gem_pm.h"
|
||||
|
@ -700,7 +701,7 @@ static int igt_ctx_exec(void *arg)
|
|||
pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) [full-ppgtt? %s], err=%d\n",
|
||||
ndwords, dw, max_dwords(obj),
|
||||
engine->name,
|
||||
yesno(i915_gem_context_has_full_ppgtt(ctx)),
|
||||
str_yes_no(i915_gem_context_has_full_ppgtt(ctx)),
|
||||
err);
|
||||
intel_context_put(ce);
|
||||
kernel_context_close(ctx);
|
||||
|
@ -834,7 +835,7 @@ static int igt_shared_ctx_exec(void *arg)
|
|||
pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) [full-ppgtt? %s], err=%d\n",
|
||||
ndwords, dw, max_dwords(obj),
|
||||
engine->name,
|
||||
yesno(i915_gem_context_has_full_ppgtt(ctx)),
|
||||
str_yes_no(i915_gem_context_has_full_ppgtt(ctx)),
|
||||
err);
|
||||
intel_context_put(ce);
|
||||
kernel_context_close(ctx);
|
||||
|
@ -1415,7 +1416,7 @@ static int igt_ctx_readonly(void *arg)
|
|||
pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) [full-ppgtt? %s], err=%d\n",
|
||||
ndwords, dw, max_dwords(obj),
|
||||
ce->engine->name,
|
||||
yesno(i915_gem_context_has_full_ppgtt(ctx)),
|
||||
str_yes_no(i915_gem_context_has_full_ppgtt(ctx)),
|
||||
err);
|
||||
i915_gem_context_unlock_engines(ctx);
|
||||
goto out_file;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Copyright © 2016 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/prime_numbers.h>
|
||||
|
||||
#include "gem/i915_gem_internal.h"
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/string_helpers.h>
|
||||
#include <trace/events/dma_fence.h>
|
||||
#include <uapi/linux/sched/types.h>
|
||||
|
||||
|
@ -512,7 +513,7 @@ void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine,
|
|||
if (!b)
|
||||
return;
|
||||
|
||||
drm_printf(p, "IRQ: %s\n", enableddisabled(b->irq_armed));
|
||||
drm_printf(p, "IRQ: %s\n", str_enabled_disabled(b->irq_armed));
|
||||
if (!list_empty(&b->signalers))
|
||||
print_signals(b, p);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
* Copyright © 2016 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "gem/i915_gem_context.h"
|
||||
|
@ -1730,9 +1732,8 @@ static void intel_engine_print_registers(struct intel_engine_cs *engine,
|
|||
u8 read, write;
|
||||
|
||||
drm_printf(m, "\tExeclist tasklet queued? %s (%s), preempt? %s, timeslice? %s\n",
|
||||
yesno(test_bit(TASKLET_STATE_SCHED,
|
||||
&engine->sched_engine->tasklet.state)),
|
||||
enableddisabled(!atomic_read(&engine->sched_engine->tasklet.count)),
|
||||
str_yes_no(test_bit(TASKLET_STATE_SCHED, &engine->sched_engine->tasklet.state)),
|
||||
str_enabled_disabled(!atomic_read(&engine->sched_engine->tasklet.count)),
|
||||
repr_timer(&engine->execlists.preempt),
|
||||
repr_timer(&engine->execlists.timer));
|
||||
|
||||
|
@ -1993,7 +1994,7 @@ void intel_engine_dump(struct intel_engine_cs *engine,
|
|||
|
||||
drm_printf(m, "\tAwake? %d\n", atomic_read(&engine->wakeref.count));
|
||||
drm_printf(m, "\tBarriers?: %s\n",
|
||||
yesno(!llist_empty(&engine->barrier_tasks)));
|
||||
str_yes_no(!llist_empty(&engine->barrier_tasks)));
|
||||
drm_printf(m, "\tLatency: %luus\n",
|
||||
ewma__engine_latency_read(&engine->latency));
|
||||
if (intel_engine_supports_stats(engine))
|
||||
|
@ -2035,7 +2036,7 @@ void intel_engine_dump(struct intel_engine_cs *engine,
|
|||
drm_printf(m, "HWSP:\n");
|
||||
hexdump(m, engine->status_page.addr, PAGE_SIZE);
|
||||
|
||||
drm_printf(m, "Idle? %s\n", yesno(intel_engine_is_idle(engine)));
|
||||
drm_printf(m, "Idle? %s\n", str_yes_no(intel_engine_is_idle(engine)));
|
||||
|
||||
intel_engine_print_breadcrumbs(engine, m);
|
||||
}
|
||||
|
|
|
@ -107,6 +107,7 @@
|
|||
*
|
||||
*/
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_trace.h"
|
||||
|
@ -1333,11 +1334,11 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
|
|||
} else if (timeslice_expired(engine, last)) {
|
||||
ENGINE_TRACE(engine,
|
||||
"expired:%s last=%llx:%lld, prio=%d, hint=%d, yield?=%s\n",
|
||||
yesno(timer_expired(&execlists->timer)),
|
||||
str_yes_no(timer_expired(&execlists->timer)),
|
||||
last->fence.context, last->fence.seqno,
|
||||
rq_prio(last),
|
||||
sched_engine->queue_priority_hint,
|
||||
yesno(timeslice_yield(execlists, last)));
|
||||
str_yes_no(timeslice_yield(execlists, last)));
|
||||
|
||||
/*
|
||||
* Consume this timeslice; ensure we start a new one.
|
||||
|
@ -1425,7 +1426,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
|
|||
__i915_request_is_complete(rq) ? "!" :
|
||||
__i915_request_has_started(rq) ? "*" :
|
||||
"",
|
||||
yesno(engine != ve->siblings[0]));
|
||||
str_yes_no(engine != ve->siblings[0]));
|
||||
|
||||
WRITE_ONCE(ve->request, NULL);
|
||||
WRITE_ONCE(ve->base.sched_engine->queue_priority_hint, INT_MIN);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "intel_gt_regs.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_scatterlist.h"
|
||||
#include "i915_utils.h"
|
||||
#include "i915_vgpu.h"
|
||||
|
||||
#include "intel_gtt.h"
|
||||
|
@ -626,7 +627,7 @@ int i915_ggtt_probe_hw(struct drm_i915_private *i915)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (intel_vtd_active(i915))
|
||||
if (i915_vtd_active(i915))
|
||||
drm_info(&i915->drm, "VT-d active for gfx access\n");
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
* Copyright © 2008-2015 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/highmem.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "i915_scatterlist.h"
|
||||
|
|
|
@ -385,7 +385,7 @@ static bool needs_idle_maps(struct drm_i915_private *i915)
|
|||
* Query intel_iommu to see if we need the workaround. Presumably that
|
||||
* was loaded first.
|
||||
*/
|
||||
if (!intel_vtd_active(i915))
|
||||
if (!i915_vtd_active(i915))
|
||||
return false;
|
||||
|
||||
if (GRAPHICS_VER(i915) == 5 && IS_MOBILE(i915))
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/string_helpers.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
|
@ -164,7 +165,7 @@ static void gt_sanitize(struct intel_gt *gt, bool force)
|
|||
enum intel_engine_id id;
|
||||
intel_wakeref_t wakeref;
|
||||
|
||||
GT_TRACE(gt, "force:%s", yesno(force));
|
||||
GT_TRACE(gt, "force:%s", str_yes_no(force));
|
||||
|
||||
/* Use a raw wakeref to avoid calling intel_display_power_get early */
|
||||
wakeref = intel_runtime_pm_get(gt->uncore->rpm);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
|
@ -105,14 +106,14 @@ static int vlv_drpc(struct seq_file *m)
|
|||
rcctl1 = intel_uncore_read(uncore, GEN6_RC_CONTROL);
|
||||
|
||||
seq_printf(m, "RC6 Enabled: %s\n",
|
||||
yesno(rcctl1 & (GEN7_RC_CTL_TO_MODE |
|
||||
str_yes_no(rcctl1 & (GEN7_RC_CTL_TO_MODE |
|
||||
GEN6_RC_CTL_EI_MODE(1))));
|
||||
seq_printf(m, "Render Power Well: %s\n",
|
||||
(pw_status & VLV_GTLC_PW_RENDER_STATUS_MASK) ? "Up" : "Down");
|
||||
seq_printf(m, "Media Power Well: %s\n",
|
||||
(pw_status & VLV_GTLC_PW_MEDIA_STATUS_MASK) ? "Up" : "Down");
|
||||
|
||||
print_rc6_res(m, "Render RC6 residency since boot:", VLV_GT_RENDER_RC6);
|
||||
print_rc6_res(m, "Render RC6 residency since boot:", GEN6_GT_GFX_RC6);
|
||||
print_rc6_res(m, "Media RC6 residency since boot:", VLV_GT_MEDIA_RC6);
|
||||
|
||||
return fw_domains_show(m, NULL);
|
||||
|
@ -140,19 +141,19 @@ static int gen6_drpc(struct seq_file *m)
|
|||
snb_pcode_read(i915, GEN6_PCODE_READ_RC6VIDS, &rc6vids, NULL);
|
||||
|
||||
seq_printf(m, "RC1e Enabled: %s\n",
|
||||
yesno(rcctl1 & GEN6_RC_CTL_RC1e_ENABLE));
|
||||
str_yes_no(rcctl1 & GEN6_RC_CTL_RC1e_ENABLE));
|
||||
seq_printf(m, "RC6 Enabled: %s\n",
|
||||
yesno(rcctl1 & GEN6_RC_CTL_RC6_ENABLE));
|
||||
str_yes_no(rcctl1 & GEN6_RC_CTL_RC6_ENABLE));
|
||||
if (GRAPHICS_VER(i915) >= 9) {
|
||||
seq_printf(m, "Render Well Gating Enabled: %s\n",
|
||||
yesno(gen9_powergate_enable & GEN9_RENDER_PG_ENABLE));
|
||||
str_yes_no(gen9_powergate_enable & GEN9_RENDER_PG_ENABLE));
|
||||
seq_printf(m, "Media Well Gating Enabled: %s\n",
|
||||
yesno(gen9_powergate_enable & GEN9_MEDIA_PG_ENABLE));
|
||||
str_yes_no(gen9_powergate_enable & GEN9_MEDIA_PG_ENABLE));
|
||||
}
|
||||
seq_printf(m, "Deep RC6 Enabled: %s\n",
|
||||
yesno(rcctl1 & GEN6_RC_CTL_RC6p_ENABLE));
|
||||
str_yes_no(rcctl1 & GEN6_RC_CTL_RC6p_ENABLE));
|
||||
seq_printf(m, "Deepest RC6 Enabled: %s\n",
|
||||
yesno(rcctl1 & GEN6_RC_CTL_RC6pp_ENABLE));
|
||||
str_yes_no(rcctl1 & GEN6_RC_CTL_RC6pp_ENABLE));
|
||||
seq_puts(m, "Current RC state: ");
|
||||
switch (gt_core_status & GEN6_RCn_MASK) {
|
||||
case GEN6_RC0:
|
||||
|
@ -176,7 +177,7 @@ static int gen6_drpc(struct seq_file *m)
|
|||
}
|
||||
|
||||
seq_printf(m, "Core Power Down: %s\n",
|
||||
yesno(gt_core_status & GEN6_CORE_CPD_STATE_MASK));
|
||||
str_yes_no(gt_core_status & GEN6_CORE_CPD_STATE_MASK));
|
||||
if (GRAPHICS_VER(i915) >= 9) {
|
||||
seq_printf(m, "Render Power Well: %s\n",
|
||||
(gen9_powergate_status &
|
||||
|
@ -216,16 +217,17 @@ static int ilk_drpc(struct seq_file *m)
|
|||
rstdbyctl = intel_uncore_read(uncore, RSTDBYCTL);
|
||||
crstandvid = intel_uncore_read16(uncore, CRSTANDVID);
|
||||
|
||||
seq_printf(m, "HD boost: %s\n", yesno(rgvmodectl & MEMMODE_BOOST_EN));
|
||||
seq_printf(m, "HD boost: %s\n",
|
||||
str_yes_no(rgvmodectl & MEMMODE_BOOST_EN));
|
||||
seq_printf(m, "Boost freq: %d\n",
|
||||
(rgvmodectl & MEMMODE_BOOST_FREQ_MASK) >>
|
||||
MEMMODE_BOOST_FREQ_SHIFT);
|
||||
seq_printf(m, "HW control enabled: %s\n",
|
||||
yesno(rgvmodectl & MEMMODE_HWIDLE_EN));
|
||||
str_yes_no(rgvmodectl & MEMMODE_HWIDLE_EN));
|
||||
seq_printf(m, "SW control enabled: %s\n",
|
||||
yesno(rgvmodectl & MEMMODE_SWMODE_EN));
|
||||
str_yes_no(rgvmodectl & MEMMODE_SWMODE_EN));
|
||||
seq_printf(m, "Gated voltage change: %s\n",
|
||||
yesno(rgvmodectl & MEMMODE_RCLK_GATE));
|
||||
str_yes_no(rgvmodectl & MEMMODE_RCLK_GATE));
|
||||
seq_printf(m, "Starting frequency: P%d\n",
|
||||
(rgvmodectl & MEMMODE_FSTART_MASK) >> MEMMODE_FSTART_SHIFT);
|
||||
seq_printf(m, "Max P-state: P%d\n",
|
||||
|
@ -234,7 +236,7 @@ static int ilk_drpc(struct seq_file *m)
|
|||
seq_printf(m, "RS1 VID: %d\n", (crstandvid & 0x3f));
|
||||
seq_printf(m, "RS2 VID: %d\n", ((crstandvid >> 8) & 0x3f));
|
||||
seq_printf(m, "Render standby enabled: %s\n",
|
||||
yesno(!(rstdbyctl & RCX_SW_EXIT)));
|
||||
str_yes_no(!(rstdbyctl & RCX_SW_EXIT)));
|
||||
seq_puts(m, "Current RS state: ");
|
||||
switch (rstdbyctl & RSX_STATUS_MASK) {
|
||||
case RSX_STATUS_ON:
|
||||
|
@ -307,12 +309,11 @@ void intel_gt_pm_frequency_dump(struct intel_gt *gt, struct drm_printer *p)
|
|||
|
||||
rpmodectl = intel_uncore_read(uncore, GEN6_RP_CONTROL);
|
||||
drm_printf(p, "Video Turbo Mode: %s\n",
|
||||
yesno(rpmodectl & GEN6_RP_MEDIA_TURBO));
|
||||
str_yes_no(rpmodectl & GEN6_RP_MEDIA_TURBO));
|
||||
drm_printf(p, "HW control enabled: %s\n",
|
||||
yesno(rpmodectl & GEN6_RP_ENABLE));
|
||||
str_yes_no(rpmodectl & GEN6_RP_ENABLE));
|
||||
drm_printf(p, "SW control enabled: %s\n",
|
||||
yesno((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) ==
|
||||
GEN6_RP_MEDIA_SW_MODE));
|
||||
str_yes_no((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) == GEN6_RP_MEDIA_SW_MODE));
|
||||
|
||||
vlv_punit_get(i915);
|
||||
freq_sts = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS);
|
||||
|
@ -416,12 +417,11 @@ void intel_gt_pm_frequency_dump(struct intel_gt *gt, struct drm_printer *p)
|
|||
pm_mask = intel_uncore_read(uncore, GEN6_PMINTRMSK);
|
||||
|
||||
drm_printf(p, "Video Turbo Mode: %s\n",
|
||||
yesno(rpmodectl & GEN6_RP_MEDIA_TURBO));
|
||||
str_yes_no(rpmodectl & GEN6_RP_MEDIA_TURBO));
|
||||
drm_printf(p, "HW control enabled: %s\n",
|
||||
yesno(rpmodectl & GEN6_RP_ENABLE));
|
||||
str_yes_no(rpmodectl & GEN6_RP_ENABLE));
|
||||
drm_printf(p, "SW control enabled: %s\n",
|
||||
yesno((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) ==
|
||||
GEN6_RP_MEDIA_SW_MODE));
|
||||
str_yes_no((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) == GEN6_RP_MEDIA_SW_MODE));
|
||||
|
||||
drm_printf(p, "PM IER=0x%08x IMR=0x%08x, MASK=0x%08x\n",
|
||||
pm_ier, pm_imr, pm_mask);
|
||||
|
@ -528,7 +528,7 @@ static int llc_show(struct seq_file *m, void *data)
|
|||
intel_wakeref_t wakeref;
|
||||
int gpu_freq, ia_freq;
|
||||
|
||||
seq_printf(m, "LLC: %s\n", yesno(HAS_LLC(i915)));
|
||||
seq_printf(m, "LLC: %s\n", str_yes_no(HAS_LLC(i915)));
|
||||
seq_printf(m, "%s: %uMB\n", edram ? "eDRAM" : "eLLC",
|
||||
i915->edram_size_mb);
|
||||
|
||||
|
@ -590,10 +590,12 @@ static int rps_boost_show(struct seq_file *m, void *data)
|
|||
struct drm_i915_private *i915 = gt->i915;
|
||||
struct intel_rps *rps = >->rps;
|
||||
|
||||
seq_printf(m, "RPS enabled? %s\n", yesno(intel_rps_is_enabled(rps)));
|
||||
seq_printf(m, "RPS active? %s\n", yesno(intel_rps_is_active(rps)));
|
||||
seq_printf(m, "RPS enabled? %s\n",
|
||||
str_yes_no(intel_rps_is_enabled(rps)));
|
||||
seq_printf(m, "RPS active? %s\n",
|
||||
str_yes_no(intel_rps_is_active(rps)));
|
||||
seq_printf(m, "GPU busy? %s, %llums\n",
|
||||
yesno(gt->awake),
|
||||
str_yes_no(gt->awake),
|
||||
ktime_to_ms(intel_gt_get_awake_time(gt)));
|
||||
seq_printf(m, "Boosts outstanding? %d\n",
|
||||
atomic_read(&rps->num_waiters));
|
||||
|
|
|
@ -1460,7 +1460,6 @@
|
|||
#define VLV_MEDIA_RC6_COUNT_EN (1 << 1)
|
||||
#define VLV_RENDER_RC6_COUNT_EN (1 << 0)
|
||||
#define GEN6_GT_GFX_RC6 _MMIO(0x138108)
|
||||
#define VLV_GT_RENDER_RC6 _MMIO(0x138108)
|
||||
#define VLV_GT_MEDIA_RC6 _MMIO(0x13810c)
|
||||
|
||||
#define GEN6_GT_GFX_RC6p _MMIO(0x13810c)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue