Merge tag 'drm-intel-next-2020-05-15' of git://anongit.freedesktop.org/drm/drm-intel into drm-next
UAPI Changes: - drm/i915: Show per-engine default property values in sysfs By providing the default values configured into the kernel via sysfs, it is much more convenient for userspace to restore those sane defaults, or at least know what are considered good baseline. This is useful, for example, to cleanup after any failed userspace prior to commencing new jobs. Cross-subsystem Changes: - video/hdmi: Add Unpack only function for DRM infoframe - Includes pull request gvt-next-2020-05-12 Driver Changes: - Restore Cherryview back to full-ppgtt (Chris, Mika) - Document locking guidelines for i915 (Chris, Daniel, Joonas) - Fix GitLab #1746: Handle idling during i915_gem_evict_something busy loops (Chris) - Display WA #1105: Require linear fb stride to be multiple of 512 bytes on gen9/glk (Ville) - Add Wa_14010685332 for ICP/ICL (Matt R) - Restrict w/a 1607087056 for EHL/JSL (Swathi) - Fix interrupt handling for DP AUX transactions on Tigerlake (Imre) - Revert "drm/i915/tgl: Include ro parts of l3 to invalidate" (Mika) - Fix HDC pipeline flush hardware bit on Gen12 (Mika) - Flush L3 when flushing render on Gen12 (Mika) - Invalidate aux table entries forcibly between BB on Gen12 (Mika) - Add aux table invalidate for all engines on Gen12 (Mika) - Force pte cacheline to main memory Gen8+ (Mika) - Add and enable TGL+ SAGV support (Stanislav) - Implement vm_ops->access on i915 mmaps for GDB (Chris, Kristian) - Replace zero-length array with flexible-array (Gustavo) - Improve batch buffer pool effectiveness to mitigate soft-rc6 hit (Chris) - Remove wait priority boosting (Chris) - Keep driver module referenced when PMU is active (Chris) - Sanitize RPS interrupts upon resume (Chris) - Extend pcode read timeout to 20 ms (Chris) - Wait for ACT sent before enabling MST pipe (Ville) - Extend support to async relocations to SNB (Chris) - Remove CNL pre-prod workarounds (Ville) - Don't enable WaIncreaseLatencyIPCEnabled when IPC is disabled (Sultan) - Record the active CCID from before reset (Chris) - Mark concurrent submissions with a weak-dependency (Chris) - Peel dma-fence-chains for await to allow engine-to-engine sync (Lionel) - Prevent using semaphores to chain up to external fences (Chris) - Fix GLK watermark calculations (Ville) - Emit await(batch) before MI_BB_START (Chris) - Reset execlists registers before HWSP (Chris) - Drop no-semaphore boosting in favor of fast timeslicing (Chris) - Fix enabled infoframe states of lspcon (Gwan-gyeong) - Program DP SDPs on pipe updates (Gwan-gyeong) - Stop sending DP SDPs on ddi disable (Gwan-gyeong) - Store CS timestamp frequency in Hz (Ville) - Remove unused HAS_FWTABLE macro (Pascal) - Use batchbuffer chaining for relocations to save ring space (Chris) - Try different engines for relocs if MI ops not supported (Chris, Tvrtko) - Lazily acquire the device wakeref for freeing objects (Chris) - Streamline display code arithmetics around rounding etc. (Ville) - Use bw state for per crtc SAGV evaluation (Stanislav) - Track active_pipes in bw_state (Stanislav) - Nuke mode.vrefresh usage (Ville) - Warn if the FBC is still writing to stolen on removal (Chris) - Added new PCode commands prepping for QGV rescricting (Stansilav) - Stop holding onto the pinned_default_state (Chris) - Propagate error from completed fences (Chris) - Ignore submit-fences on the same timeline (Chris) - Pull waiting on an external dma-fence into its routine (Chris) - Replace the hardcoded I915_FENCE_TIMEOUT with Kconfig (Chris) - Mark up the racy read of execlists->context_tag (Chris) - Tidy up the return handling for completed dma-fences (Chris) - Introduce skl_plane_wm_level accessor (Stanislav) - Extract SKL SAGV checking (Stanislav) - Make active_pipes check skl specific (Stanislav) - Suspend tasklets before resume sanitization (Chris) - Remove redundant exec_fence (Chris) - Mark the addition of the initial-breadcrumb in the request (Chris) - Transfer old virtual breadcrumbs to irq_worker (Chris) - Read the DP SDPs from the video DIP (Gwan-gyeong) - Program DP SDPs with computed configs (Gwan-gyeong) - Add state readout for DP VSC and DP HDR Metadata Infoframe SDP (Gwan-gyeong) - Add compute routine for DP PSR VSC SDP (Gwan-gyeong) - Use new DP VSC SDP compute routine on PSR (Gwan-gyeong) - Restrict qgv points which don't have enough bandwidth. (Stanislav) - Nuke pointless div by 64bit (Ville) - Static checker code fixes (Nathan, Mika, Chris) - Add logging function for DP VSC SDP (Gwan-gyeong) - Include HDMI DRM infoframe, DP HDR metadata and DP VSC SDP in the crtc state dump (Gwan-gyeong) - Make timeslicing explicit engine property (Chris, Tvrtko) - Selftest and debugging improvements (Chris) - Align variable names with BSpec (Ville) - Tidy up gen8+ breadcrumb emission code (Chris) - Turn intel_digital_port_connected() in a vfunc (Ville) - Use stashed away hpd isr bits in intel_digital_port_connected() (Ville) - Extract i915_cs_timestamp_{ns_to_ticks,tick_to_ns}() (Ville) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200515160703.GA19043@jlahtine-desk.ger.corp.intel.com
This commit is contained in:
@@ -514,85 +514,67 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder,
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
}
|
||||
|
||||
/* Add a factor to take care of rounding and truncations */
|
||||
#define ROUNDING_FACTOR 10000
|
||||
|
||||
static unsigned int get_hblank_early_enable_config(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
static unsigned int calc_hblank_early_prog(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
unsigned int link_clks_available, link_clks_required;
|
||||
unsigned int tu_data, tu_line, link_clks_active;
|
||||
unsigned int hblank_rise, hblank_early_prog;
|
||||
unsigned int h_active, h_total, hblank_delta, pixel_clk, v_total;
|
||||
unsigned int fec_coeff, refresh_rate, cdclk, vdsc_bpp;
|
||||
unsigned int h_active, h_total, hblank_delta, pixel_clk;
|
||||
unsigned int fec_coeff, cdclk, vdsc_bpp;
|
||||
unsigned int link_clk, lanes;
|
||||
unsigned int hblank_rise;
|
||||
|
||||
h_active = crtc_state->hw.adjusted_mode.crtc_hdisplay;
|
||||
h_total = crtc_state->hw.adjusted_mode.crtc_htotal;
|
||||
v_total = crtc_state->hw.adjusted_mode.crtc_vtotal;
|
||||
pixel_clk = crtc_state->hw.adjusted_mode.crtc_clock;
|
||||
refresh_rate = crtc_state->hw.adjusted_mode.vrefresh;
|
||||
vdsc_bpp = crtc_state->dsc.compressed_bpp;
|
||||
cdclk = i915->cdclk.hw.cdclk;
|
||||
/* fec= 0.972261, using rounding multiplier of 1000000 */
|
||||
fec_coeff = 972261;
|
||||
link_clk = crtc_state->port_clock;
|
||||
lanes = crtc_state->lane_count;
|
||||
|
||||
drm_dbg_kms(&i915->drm, "h_active = %u link_clk = %u :"
|
||||
"lanes = %u vdsc_bpp = %u cdclk = %u\n",
|
||||
h_active, crtc_state->port_clock, crtc_state->lane_count,
|
||||
vdsc_bpp, cdclk);
|
||||
h_active, link_clk, lanes, vdsc_bpp, cdclk);
|
||||
|
||||
if (WARN_ON(!crtc_state->port_clock || !crtc_state->lane_count ||
|
||||
!crtc_state->dsc.compressed_bpp || !i915->cdclk.hw.cdclk))
|
||||
if (WARN_ON(!link_clk || !pixel_clk || !lanes || !vdsc_bpp || !cdclk))
|
||||
return 0;
|
||||
|
||||
link_clks_available = ((((h_total - h_active) *
|
||||
((crtc_state->port_clock * ROUNDING_FACTOR) /
|
||||
pixel_clk)) / ROUNDING_FACTOR) - 28);
|
||||
|
||||
link_clks_required = DIV_ROUND_UP(192000, (refresh_rate *
|
||||
v_total)) * ((48 /
|
||||
crtc_state->lane_count) + 2);
|
||||
link_clks_available = (h_total - h_active) * link_clk / pixel_clk - 28;
|
||||
link_clks_required = DIV_ROUND_UP(192000 * h_total, 1000 * pixel_clk) * (48 / lanes + 2);
|
||||
|
||||
if (link_clks_available > link_clks_required)
|
||||
hblank_delta = 32;
|
||||
else
|
||||
hblank_delta = DIV_ROUND_UP(((((5 * ROUNDING_FACTOR) /
|
||||
crtc_state->port_clock) + ((5 *
|
||||
ROUNDING_FACTOR) /
|
||||
cdclk)) * pixel_clk),
|
||||
ROUNDING_FACTOR);
|
||||
hblank_delta = DIV64_U64_ROUND_UP(mul_u32_u32(5 * (link_clk + cdclk), pixel_clk),
|
||||
mul_u32_u32(link_clk, cdclk));
|
||||
|
||||
tu_data = (pixel_clk * vdsc_bpp * 8) / ((crtc_state->port_clock *
|
||||
crtc_state->lane_count * fec_coeff) / 1000000);
|
||||
tu_line = (((h_active * crtc_state->port_clock * fec_coeff) /
|
||||
1000000) / (64 * pixel_clk));
|
||||
tu_data = div64_u64(mul_u32_u32(pixel_clk * vdsc_bpp * 8, 1000000),
|
||||
mul_u32_u32(link_clk * lanes, fec_coeff));
|
||||
tu_line = div64_u64(h_active * mul_u32_u32(link_clk, fec_coeff),
|
||||
mul_u32_u32(64 * pixel_clk, 1000000));
|
||||
link_clks_active = (tu_line - 1) * 64 + tu_data;
|
||||
|
||||
hblank_rise = ((link_clks_active + 6 * DIV_ROUND_UP(link_clks_active,
|
||||
250) + 4) * ((pixel_clk * ROUNDING_FACTOR) /
|
||||
crtc_state->port_clock)) / ROUNDING_FACTOR;
|
||||
hblank_rise = (link_clks_active + 6 * DIV_ROUND_UP(link_clks_active, 250) + 4) * pixel_clk / link_clk;
|
||||
|
||||
hblank_early_prog = h_active - hblank_rise + hblank_delta;
|
||||
|
||||
return hblank_early_prog;
|
||||
return h_active - hblank_rise + hblank_delta;
|
||||
}
|
||||
|
||||
static unsigned int get_sample_room_req_config(const struct intel_crtc_state *crtc_state)
|
||||
static unsigned int calc_samples_room(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
unsigned int h_active, h_total, pixel_clk;
|
||||
unsigned int samples_room;
|
||||
unsigned int link_clk, lanes;
|
||||
|
||||
h_active = crtc_state->hw.adjusted_mode.hdisplay;
|
||||
h_total = crtc_state->hw.adjusted_mode.htotal;
|
||||
pixel_clk = crtc_state->hw.adjusted_mode.clock;
|
||||
link_clk = crtc_state->port_clock;
|
||||
lanes = crtc_state->lane_count;
|
||||
|
||||
samples_room = ((((h_total - h_active) * ((crtc_state->port_clock *
|
||||
ROUNDING_FACTOR) / pixel_clk)) /
|
||||
ROUNDING_FACTOR) - 12) / ((48 /
|
||||
crtc_state->lane_count) + 2);
|
||||
|
||||
return samples_room;
|
||||
return ((h_total - h_active) * link_clk - 12 * pixel_clk) /
|
||||
(pixel_clk * (48 / lanes + 2));
|
||||
}
|
||||
|
||||
static void enable_audio_dsc_wa(struct intel_encoder *encoder,
|
||||
@@ -618,8 +600,7 @@ static void enable_audio_dsc_wa(struct intel_encoder *encoder,
|
||||
(crtc_state->hw.adjusted_mode.hdisplay >= 3840 &&
|
||||
crtc_state->hw.adjusted_mode.vdisplay >= 2160)) {
|
||||
/* Get hblank early enable value required */
|
||||
hblank_early_prog = get_hblank_early_enable_config(encoder,
|
||||
crtc_state);
|
||||
hblank_early_prog = calc_hblank_early_prog(encoder, crtc_state);
|
||||
if (hblank_early_prog < 32) {
|
||||
val &= ~HBLANK_START_COUNT_MASK(pipe);
|
||||
val |= HBLANK_START_COUNT(pipe, HBLANK_START_COUNT_32);
|
||||
@@ -635,7 +616,7 @@ static void enable_audio_dsc_wa(struct intel_encoder *encoder,
|
||||
}
|
||||
|
||||
/* Get samples room value required */
|
||||
samples_room = get_sample_room_req_config(crtc_state);
|
||||
samples_room = calc_samples_room(crtc_state);
|
||||
if (samples_room < 3) {
|
||||
val &= ~NUMBER_SAMPLES_PER_LINE_MASK(pipe);
|
||||
val |= NUMBER_SAMPLES_PER_LINE(pipe, samples_room);
|
||||
|
@@ -8,6 +8,9 @@
|
||||
#include "intel_bw.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_sideband.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_pm.h"
|
||||
|
||||
|
||||
/* Parameters for Qclk Geyserville (QGV) */
|
||||
struct intel_qgv_point {
|
||||
@@ -113,6 +116,26 @@ static int icl_pcode_read_qgv_point_info(struct drm_i915_private *dev_priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv,
|
||||
u32 points_mask)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* 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,
|
||||
1);
|
||||
|
||||
if (ret < 0) {
|
||||
drm_err(&dev_priv->drm, "Failed to disable qgv points (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int icl_get_qgv_points(struct drm_i915_private *dev_priv,
|
||||
struct intel_qgv_info *qi)
|
||||
{
|
||||
@@ -240,6 +263,16 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* In case if SAGV is disabled in BIOS, we always get 1
|
||||
* SAGV point, but we can't send PCode commands to restrict it
|
||||
* as it will fail and pointless anyway.
|
||||
*/
|
||||
if (qi.num_points == 1)
|
||||
dev_priv->sagv_status = I915_SAGV_NOT_CONTROLLED;
|
||||
else
|
||||
dev_priv->sagv_status = I915_SAGV_ENABLED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -248,6 +281,11 @@ static unsigned int icl_max_bw(struct drm_i915_private *dev_priv,
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Let's return max bw for 0 planes
|
||||
*/
|
||||
num_planes = max(1, num_planes);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev_priv->max_bw); i++) {
|
||||
const struct intel_bw_info *bi =
|
||||
&dev_priv->max_bw[i];
|
||||
@@ -277,34 +315,6 @@ void intel_bw_init_hw(struct drm_i915_private *dev_priv)
|
||||
icl_get_bw_info(dev_priv, &icl_sa_info);
|
||||
}
|
||||
|
||||
static unsigned int intel_max_data_rate(struct drm_i915_private *dev_priv,
|
||||
int num_planes)
|
||||
{
|
||||
if (INTEL_GEN(dev_priv) >= 11) {
|
||||
/*
|
||||
* Any bw group has same amount of QGV points
|
||||
*/
|
||||
const struct intel_bw_info *bi =
|
||||
&dev_priv->max_bw[0];
|
||||
unsigned int min_bw = UINT_MAX;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* FIXME with SAGV disabled maybe we can assume
|
||||
* point 1 will always be used? Seems to match
|
||||
* the behaviour observed in the wild.
|
||||
*/
|
||||
for (i = 0; i < bi->num_qgv_points; i++) {
|
||||
unsigned int bw = icl_max_bw(dev_priv, num_planes, i);
|
||||
|
||||
min_bw = min(bw, min_bw);
|
||||
}
|
||||
return min_bw;
|
||||
} else {
|
||||
return UINT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int intel_bw_crtc_num_active_planes(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
/*
|
||||
@@ -414,11 +424,16 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
|
||||
struct intel_crtc_state *new_crtc_state, *old_crtc_state;
|
||||
struct intel_bw_state *bw_state = NULL;
|
||||
unsigned int data_rate, max_data_rate;
|
||||
struct intel_bw_state *new_bw_state = NULL;
|
||||
const struct intel_bw_state *old_bw_state = NULL;
|
||||
unsigned int data_rate;
|
||||
unsigned int num_active_planes;
|
||||
struct intel_crtc *crtc;
|
||||
int i, ret;
|
||||
u32 allowed_points = 0;
|
||||
unsigned int max_bw_point = 0, max_bw = 0;
|
||||
unsigned int num_qgv_points = dev_priv->max_bw[0].num_qgv_points;
|
||||
u32 mask = (1 << num_qgv_points) - 1;
|
||||
|
||||
/* FIXME earlier gens need some checks too */
|
||||
if (INTEL_GEN(dev_priv) < 11)
|
||||
@@ -443,41 +458,93 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
|
||||
old_active_planes == new_active_planes)
|
||||
continue;
|
||||
|
||||
bw_state = intel_atomic_get_bw_state(state);
|
||||
if (IS_ERR(bw_state))
|
||||
return PTR_ERR(bw_state);
|
||||
new_bw_state = intel_atomic_get_bw_state(state);
|
||||
if (IS_ERR(new_bw_state))
|
||||
return PTR_ERR(new_bw_state);
|
||||
|
||||
bw_state->data_rate[crtc->pipe] = new_data_rate;
|
||||
bw_state->num_active_planes[crtc->pipe] = new_active_planes;
|
||||
new_bw_state->data_rate[crtc->pipe] = new_data_rate;
|
||||
new_bw_state->num_active_planes[crtc->pipe] = new_active_planes;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"pipe %c data rate %u num active planes %u\n",
|
||||
pipe_name(crtc->pipe),
|
||||
bw_state->data_rate[crtc->pipe],
|
||||
bw_state->num_active_planes[crtc->pipe]);
|
||||
new_bw_state->data_rate[crtc->pipe],
|
||||
new_bw_state->num_active_planes[crtc->pipe]);
|
||||
}
|
||||
|
||||
if (!bw_state)
|
||||
if (!new_bw_state)
|
||||
return 0;
|
||||
|
||||
ret = intel_atomic_lock_global_state(&bw_state->base);
|
||||
ret = intel_atomic_lock_global_state(&new_bw_state->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
data_rate = intel_bw_data_rate(dev_priv, bw_state);
|
||||
num_active_planes = intel_bw_num_active_planes(dev_priv, bw_state);
|
||||
|
||||
max_data_rate = intel_max_data_rate(dev_priv, num_active_planes);
|
||||
|
||||
data_rate = intel_bw_data_rate(dev_priv, new_bw_state);
|
||||
data_rate = DIV_ROUND_UP(data_rate, 1000);
|
||||
|
||||
if (data_rate > max_data_rate) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Bandwidth %u MB/s exceeds max available %d MB/s (%d active planes)\n",
|
||||
data_rate, max_data_rate, num_active_planes);
|
||||
num_active_planes = intel_bw_num_active_planes(dev_priv, new_bw_state);
|
||||
|
||||
for (i = 0; i < num_qgv_points; i++) {
|
||||
unsigned int max_data_rate;
|
||||
|
||||
max_data_rate = icl_max_bw(dev_priv, num_active_planes, i);
|
||||
/*
|
||||
* We need to know which qgv point gives us
|
||||
* maximum bandwidth in order to disable SAGV
|
||||
* if we find that we exceed SAGV block time
|
||||
* with watermarks. By that moment we already
|
||||
* have those, as it is calculated earlier in
|
||||
* intel_atomic_check,
|
||||
*/
|
||||
if (max_data_rate > max_bw) {
|
||||
max_bw_point = i;
|
||||
max_bw = max_data_rate;
|
||||
}
|
||||
if (max_data_rate >= data_rate)
|
||||
allowed_points |= BIT(i);
|
||||
drm_dbg_kms(&dev_priv->drm, "QGV point %d: max bw %d required %d\n",
|
||||
i, max_data_rate, data_rate);
|
||||
}
|
||||
|
||||
/*
|
||||
* BSpec states that we always should have at least one allowed point
|
||||
* left, so if we couldn't - simply reject the configuration for obvious
|
||||
* reasons.
|
||||
*/
|
||||
if (allowed_points == 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Leave only single point with highest bandwidth, if
|
||||
* we can't enable SAGV due to the increased memory latency it may
|
||||
* cause.
|
||||
*/
|
||||
if (!intel_can_enable_sagv(dev_priv, new_bw_state)) {
|
||||
allowed_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 & mask;
|
||||
|
||||
old_bw_state = intel_atomic_get_old_bw_state(state);
|
||||
/*
|
||||
* If the actual mask had changed we need to make sure that
|
||||
* the commits are serialized(in case this is a nomodeset, nonblocking)
|
||||
*/
|
||||
if (new_bw_state->qgv_points_mask != old_bw_state->qgv_points_mask) {
|
||||
ret = intel_atomic_serialize_global_state(&new_bw_state->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -18,8 +18,24 @@ struct intel_crtc_state;
|
||||
struct intel_bw_state {
|
||||
struct intel_global_state base;
|
||||
|
||||
/*
|
||||
* Contains a bit mask, used to determine, whether correspondent
|
||||
* pipe allows SAGV or not.
|
||||
*/
|
||||
u8 pipe_sagv_reject;
|
||||
|
||||
/*
|
||||
* Current QGV points mask, which restricts
|
||||
* some particular SAGV states, not to confuse
|
||||
* with pipe_sagv_mask.
|
||||
*/
|
||||
u8 qgv_points_mask;
|
||||
|
||||
unsigned int data_rate[I915_MAX_PIPES];
|
||||
u8 num_active_planes[I915_MAX_PIPES];
|
||||
|
||||
/* bitmask of active pipes */
|
||||
u8 active_pipes;
|
||||
};
|
||||
|
||||
#define to_intel_bw_state(x) container_of((x), struct intel_bw_state, base)
|
||||
@@ -38,5 +54,7 @@ int intel_bw_init(struct drm_i915_private *dev_priv);
|
||||
int intel_bw_atomic_check(struct intel_atomic_state *state);
|
||||
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);
|
||||
|
||||
#endif /* __INTEL_BW_H__ */
|
||||
|
@@ -3472,6 +3472,8 @@ static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
|
||||
INTEL_OUTPUT_DP_MST);
|
||||
enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
|
||||
|
||||
intel_dp_set_infoframes(encoder, false, old_crtc_state, old_conn_state);
|
||||
|
||||
/*
|
||||
* Power down sink before disabling the port, otherwise we end
|
||||
* up getting interrupts from the sink on detecting link loss.
|
||||
@@ -3680,9 +3682,8 @@ static void intel_enable_ddi_dp(struct intel_atomic_state *state,
|
||||
intel_dp_stop_link_train(intel_dp);
|
||||
|
||||
intel_edp_backlight_on(crtc_state, conn_state);
|
||||
intel_psr_enable(intel_dp, crtc_state);
|
||||
intel_dp_vsc_enable(intel_dp, crtc_state, conn_state);
|
||||
intel_dp_hdr_metadata_enable(intel_dp, crtc_state, conn_state);
|
||||
intel_psr_enable(intel_dp, crtc_state, conn_state);
|
||||
intel_dp_set_infoframes(encoder, true, crtc_state, conn_state);
|
||||
intel_edp_drrs_enable(intel_dp, crtc_state);
|
||||
|
||||
if (crtc_state->has_audio)
|
||||
@@ -3864,7 +3865,8 @@ static void intel_ddi_update_pipe_dp(struct intel_atomic_state *state,
|
||||
|
||||
intel_ddi_set_dp_msa(crtc_state, conn_state);
|
||||
|
||||
intel_psr_update(intel_dp, crtc_state);
|
||||
intel_psr_update(intel_dp, crtc_state, conn_state);
|
||||
intel_dp_set_infoframes(encoder, true, crtc_state, conn_state);
|
||||
intel_edp_drrs_enable(intel_dp, crtc_state);
|
||||
|
||||
intel_panel_update_backlight(state, encoder, crtc_state, conn_state);
|
||||
@@ -4235,6 +4237,9 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
|
||||
pipe_config->fec_enable);
|
||||
}
|
||||
|
||||
pipe_config->infoframes.enable |=
|
||||
intel_hdmi_infoframes_enabled(encoder, pipe_config);
|
||||
|
||||
break;
|
||||
case TRANS_DDI_MODE_SELECT_DP_MST:
|
||||
pipe_config->output_types |= BIT(INTEL_OUTPUT_DP_MST);
|
||||
@@ -4246,6 +4251,9 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
|
||||
REG_FIELD_GET(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, temp);
|
||||
|
||||
intel_dp_get_m_n(intel_crtc, pipe_config);
|
||||
|
||||
pipe_config->infoframes.enable |=
|
||||
intel_hdmi_infoframes_enabled(encoder, pipe_config);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -4300,6 +4308,9 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 8)
|
||||
bdw_get_trans_port_sync_config(pipe_config);
|
||||
|
||||
intel_read_dp_sdp(encoder, pipe_config, HDMI_PACKET_TYPE_GAMUT_METADATA);
|
||||
intel_read_dp_sdp(encoder, pipe_config, DP_SDP_VSC);
|
||||
}
|
||||
|
||||
static enum intel_output_type
|
||||
@@ -4689,6 +4700,30 @@ intel_ddi_hotplug(struct intel_encoder *encoder,
|
||||
return state;
|
||||
}
|
||||
|
||||
static bool lpt_digital_port_connected(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
u32 bit = dev_priv->hotplug.pch_hpd[encoder->hpd_pin];
|
||||
|
||||
return intel_de_read(dev_priv, SDEISR) & bit;
|
||||
}
|
||||
|
||||
static bool hsw_digital_port_connected(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
u32 bit = dev_priv->hotplug.hpd[encoder->hpd_pin];
|
||||
|
||||
return intel_de_read(dev_priv, DEISR) & bit;
|
||||
}
|
||||
|
||||
static bool bdw_digital_port_connected(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
u32 bit = dev_priv->hotplug.hpd[encoder->hpd_pin];
|
||||
|
||||
return intel_de_read(dev_priv, GEN8_DE_PORT_ISR) & bit;
|
||||
}
|
||||
|
||||
static struct intel_connector *
|
||||
intel_ddi_init_hdmi_connector(struct intel_digital_port *intel_dig_port)
|
||||
{
|
||||
@@ -4885,6 +4920,23 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
|
||||
port_name(port));
|
||||
}
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 11) {
|
||||
if (intel_phy_is_tc(dev_priv, phy))
|
||||
intel_dig_port->connected = intel_tc_port_connected;
|
||||
else
|
||||
intel_dig_port->connected = lpt_digital_port_connected;
|
||||
} else if (INTEL_GEN(dev_priv) >= 8) {
|
||||
if (port == PORT_A || IS_GEN9_LP(dev_priv))
|
||||
intel_dig_port->connected = bdw_digital_port_connected;
|
||||
else
|
||||
intel_dig_port->connected = lpt_digital_port_connected;
|
||||
} else {
|
||||
if (port == PORT_A)
|
||||
intel_dig_port->connected = hsw_digital_port_connected;
|
||||
else
|
||||
intel_dig_port->connected = lpt_digital_port_connected;
|
||||
}
|
||||
|
||||
intel_infoframe_init(intel_dig_port);
|
||||
|
||||
return;
|
||||
|
@@ -12866,6 +12866,16 @@ intel_dump_infoframe(struct drm_i915_private *dev_priv,
|
||||
hdmi_infoframe_log(KERN_DEBUG, dev_priv->drm.dev, frame);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dump_dp_vsc_sdp(struct drm_i915_private *dev_priv,
|
||||
const struct drm_dp_vsc_sdp *vsc)
|
||||
{
|
||||
if (!drm_debug_enabled(DRM_UT_KMS))
|
||||
return;
|
||||
|
||||
drm_dp_vsc_sdp_log(KERN_DEBUG, dev_priv->drm.dev, vsc);
|
||||
}
|
||||
|
||||
#define OUTPUT_TYPE(x) [INTEL_OUTPUT_ ## x] = #x
|
||||
|
||||
static const char * const output_type_str[] = {
|
||||
@@ -13023,6 +13033,15 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
|
||||
if (pipe_config->infoframes.enable &
|
||||
intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_VENDOR))
|
||||
intel_dump_infoframe(dev_priv, &pipe_config->infoframes.hdmi);
|
||||
if (pipe_config->infoframes.enable &
|
||||
intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_DRM))
|
||||
intel_dump_infoframe(dev_priv, &pipe_config->infoframes.drm);
|
||||
if (pipe_config->infoframes.enable &
|
||||
intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GAMUT_METADATA))
|
||||
intel_dump_infoframe(dev_priv, &pipe_config->infoframes.drm);
|
||||
if (pipe_config->infoframes.enable &
|
||||
intel_hdmi_infoframe_enable(DP_SDP_VSC))
|
||||
intel_dump_dp_vsc_sdp(dev_priv, &pipe_config->infoframes.vsc);
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "requested mode:\n");
|
||||
drm_mode_debug_printmodeline(&pipe_config->hw.mode);
|
||||
@@ -13470,6 +13489,13 @@ intel_compare_infoframe(const union hdmi_infoframe *a,
|
||||
return memcmp(a, b, sizeof(*a)) == 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
intel_compare_dp_vsc_sdp(const struct drm_dp_vsc_sdp *a,
|
||||
const struct drm_dp_vsc_sdp *b)
|
||||
{
|
||||
return memcmp(a, b, sizeof(*a)) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
pipe_config_infoframe_mismatch(struct drm_i915_private *dev_priv,
|
||||
bool fastset, const char *name,
|
||||
@@ -13495,6 +13521,31 @@ pipe_config_infoframe_mismatch(struct drm_i915_private *dev_priv,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pipe_config_dp_vsc_sdp_mismatch(struct drm_i915_private *dev_priv,
|
||||
bool fastset, const char *name,
|
||||
const struct drm_dp_vsc_sdp *a,
|
||||
const struct drm_dp_vsc_sdp *b)
|
||||
{
|
||||
if (fastset) {
|
||||
if (!drm_debug_enabled(DRM_UT_KMS))
|
||||
return;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"fastset mismatch in %s dp sdp\n", name);
|
||||
drm_dbg_kms(&dev_priv->drm, "expected:\n");
|
||||
drm_dp_vsc_sdp_log(KERN_DEBUG, dev_priv->drm.dev, a);
|
||||
drm_dbg_kms(&dev_priv->drm, "found:\n");
|
||||
drm_dp_vsc_sdp_log(KERN_DEBUG, dev_priv->drm.dev, b);
|
||||
} else {
|
||||
drm_err(&dev_priv->drm, "mismatch in %s dp sdp\n", name);
|
||||
drm_err(&dev_priv->drm, "expected:\n");
|
||||
drm_dp_vsc_sdp_log(KERN_ERR, dev_priv->drm.dev, a);
|
||||
drm_err(&dev_priv->drm, "found:\n");
|
||||
drm_dp_vsc_sdp_log(KERN_ERR, dev_priv->drm.dev, b);
|
||||
}
|
||||
}
|
||||
|
||||
static void __printf(4, 5)
|
||||
pipe_config_mismatch(bool fastset, const struct intel_crtc *crtc,
|
||||
const char *name, const char *format, ...)
|
||||
@@ -13696,6 +13747,17 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define PIPE_CONF_CHECK_DP_VSC_SDP(name) do { \
|
||||
if (!current_config->has_psr && !pipe_config->has_psr && \
|
||||
!intel_compare_dp_vsc_sdp(¤t_config->infoframes.name, \
|
||||
&pipe_config->infoframes.name)) { \
|
||||
pipe_config_dp_vsc_sdp_mismatch(dev_priv, fastset, __stringify(name), \
|
||||
¤t_config->infoframes.name, \
|
||||
&pipe_config->infoframes.name); \
|
||||
ret = false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define PIPE_CONF_CHECK_COLOR_LUT(name1, name2, bit_precision) do { \
|
||||
if (current_config->name1 != pipe_config->name1) { \
|
||||
pipe_config_mismatch(fastset, crtc, __stringify(name1), \
|
||||
@@ -13873,6 +13935,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
|
||||
PIPE_CONF_CHECK_INFOFRAME(spd);
|
||||
PIPE_CONF_CHECK_INFOFRAME(hdmi);
|
||||
PIPE_CONF_CHECK_INFOFRAME(drm);
|
||||
PIPE_CONF_CHECK_DP_VSC_SDP(vsc);
|
||||
|
||||
PIPE_CONF_CHECK_X(sync_mode_slaves_mask);
|
||||
PIPE_CONF_CHECK_I(master_transcoder);
|
||||
@@ -13961,7 +14024,9 @@ static void verify_wm_state(struct intel_crtc *crtc,
|
||||
/* Watermarks */
|
||||
for (level = 0; level <= max_level; level++) {
|
||||
if (skl_wm_level_equals(&hw_plane_wm->wm[level],
|
||||
&sw_plane_wm->wm[level]))
|
||||
&sw_plane_wm->wm[level]) ||
|
||||
(level == 0 && skl_wm_level_equals(&hw_plane_wm->wm[level],
|
||||
&sw_plane_wm->sagv_wm0)))
|
||||
continue;
|
||||
|
||||
drm_err(&dev_priv->drm,
|
||||
@@ -14016,7 +14081,9 @@ static void verify_wm_state(struct intel_crtc *crtc,
|
||||
/* Watermarks */
|
||||
for (level = 0; level <= max_level; level++) {
|
||||
if (skl_wm_level_equals(&hw_plane_wm->wm[level],
|
||||
&sw_plane_wm->wm[level]))
|
||||
&sw_plane_wm->wm[level]) ||
|
||||
(level == 0 && skl_wm_level_equals(&hw_plane_wm->wm[level],
|
||||
&sw_plane_wm->sagv_wm0)))
|
||||
continue;
|
||||
|
||||
drm_err(&dev_priv->drm,
|
||||
@@ -15378,11 +15445,11 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
|
||||
|
||||
intel_set_cdclk_pre_plane_update(state);
|
||||
|
||||
intel_sagv_pre_plane_update(state);
|
||||
|
||||
intel_modeset_verify_disabled(dev_priv, state);
|
||||
}
|
||||
|
||||
intel_sagv_pre_plane_update(state);
|
||||
|
||||
/* Complete the events for pipes that have now been disabled */
|
||||
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
|
||||
bool modeset = needs_modeset(new_crtc_state);
|
||||
@@ -15475,11 +15542,10 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
|
||||
intel_check_cpu_fifo_underruns(dev_priv);
|
||||
intel_check_pch_fifo_underruns(dev_priv);
|
||||
|
||||
if (state->modeset) {
|
||||
if (state->modeset)
|
||||
intel_verify_planes(state);
|
||||
|
||||
intel_sagv_post_plane_update(state);
|
||||
}
|
||||
intel_sagv_post_plane_update(state);
|
||||
|
||||
drm_atomic_helper_commit_hw_done(&state->base);
|
||||
|
||||
@@ -15815,7 +15881,7 @@ intel_prepare_plane_fb(struct drm_plane *_plane,
|
||||
if (new_plane_state->uapi.fence) { /* explicit fencing */
|
||||
ret = i915_sw_fence_await_dma_fence(&state->commit_ready,
|
||||
new_plane_state->uapi.fence,
|
||||
I915_FENCE_TIMEOUT,
|
||||
i915_fence_timeout(dev_priv),
|
||||
GFP_KERNEL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -15842,7 +15908,8 @@ intel_prepare_plane_fb(struct drm_plane *_plane,
|
||||
|
||||
ret = i915_sw_fence_await_reservation(&state->commit_ready,
|
||||
obj->base.resv, NULL,
|
||||
false, I915_FENCE_TIMEOUT,
|
||||
false,
|
||||
i915_fence_timeout(dev_priv),
|
||||
GFP_KERNEL);
|
||||
if (ret < 0)
|
||||
goto unpin_fb;
|
||||
|
@@ -688,11 +688,13 @@ struct skl_plane_wm {
|
||||
struct skl_wm_level wm[8];
|
||||
struct skl_wm_level uv_wm[8];
|
||||
struct skl_wm_level trans_wm;
|
||||
struct skl_wm_level sagv_wm0;
|
||||
bool is_planar;
|
||||
};
|
||||
|
||||
struct skl_pipe_wm {
|
||||
struct skl_plane_wm planes[I915_MAX_PLANES];
|
||||
bool use_sagv_wm;
|
||||
};
|
||||
|
||||
enum vlv_wm_level {
|
||||
@@ -1424,6 +1426,7 @@ struct intel_digital_port {
|
||||
const struct drm_connector_state *conn_state);
|
||||
u32 (*infoframes_enabled)(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *pipe_config);
|
||||
bool (*connected)(struct intel_encoder *encoder);
|
||||
};
|
||||
|
||||
struct intel_dp_mst_encoder {
|
||||
|
@@ -2487,8 +2487,8 @@ static void intel_dp_compute_vsc_sdp(struct intel_dp *intel_dp,
|
||||
{
|
||||
struct drm_dp_vsc_sdp *vsc = &crtc_state->infoframes.vsc;
|
||||
|
||||
/* When PSR is enabled, VSC SDP is handled by PSR routine */
|
||||
if (intel_psr_enabled(intel_dp))
|
||||
/* When a crtc state has PSR, VSC SDP will be handled by PSR routine */
|
||||
if (crtc_state->has_psr)
|
||||
return;
|
||||
|
||||
if (!intel_dp_needs_vsc_sdp(crtc_state, conn_state))
|
||||
@@ -2500,6 +2500,42 @@ static void intel_dp_compute_vsc_sdp(struct intel_dp *intel_dp,
|
||||
&crtc_state->infoframes.vsc);
|
||||
}
|
||||
|
||||
void intel_dp_compute_psr_vsc_sdp(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state,
|
||||
struct drm_dp_vsc_sdp *vsc)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
|
||||
vsc->sdp_type = DP_SDP_VSC;
|
||||
|
||||
if (dev_priv->psr.psr2_enabled) {
|
||||
if (dev_priv->psr.colorimetry_support &&
|
||||
intel_dp_needs_vsc_sdp(crtc_state, conn_state)) {
|
||||
/* [PSR2, +Colorimetry] */
|
||||
intel_dp_compute_vsc_colorimetry(crtc_state, conn_state,
|
||||
vsc);
|
||||
} else {
|
||||
/*
|
||||
* [PSR2, -Colorimetry]
|
||||
* Prepare VSC Header for SU as per eDP 1.4 spec, Table 6-11
|
||||
* 3D stereo + PSR/PSR2 + Y-coordinate.
|
||||
*/
|
||||
vsc->revision = 0x4;
|
||||
vsc->length = 0xe;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* [PSR1]
|
||||
* Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118
|
||||
* VSC SDP supporting 3D stereo + PSR (applies to eDP v1.3 or
|
||||
* higher).
|
||||
*/
|
||||
vsc->revision = 0x2;
|
||||
vsc->length = 0x8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_compute_hdr_metadata_infoframe_sdp(struct intel_dp *intel_dp,
|
||||
struct intel_crtc_state *crtc_state,
|
||||
@@ -4791,6 +4827,13 @@ static ssize_t intel_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
|
||||
sdp->sdp_header.HB2 = vsc->revision; /* Revision Number */
|
||||
sdp->sdp_header.HB3 = vsc->length; /* Number of Valid Data Bytes */
|
||||
|
||||
/*
|
||||
* Only revision 0x5 supports Pixel Encoding/Colorimetry Format as
|
||||
* per DP 1.4a spec.
|
||||
*/
|
||||
if (vsc->revision != 0x5)
|
||||
goto out;
|
||||
|
||||
/* VSC SDP Payload for DB16 through DB18 */
|
||||
/* Pixel Encoding and Colorimetry Formats */
|
||||
sdp->db[16] = (vsc->pixelformat & 0xf) << 4; /* DB16[7:4] */
|
||||
@@ -4823,6 +4866,7 @@ static ssize_t intel_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
|
||||
/* Content Type */
|
||||
sdp->db[18] = vsc->content_type & 0x7;
|
||||
|
||||
out:
|
||||
return length;
|
||||
}
|
||||
|
||||
@@ -4935,6 +4979,24 @@ static void intel_write_dp_sdp(struct intel_encoder *encoder,
|
||||
intel_dig_port->write_infoframe(encoder, crtc_state, type, &sdp, len);
|
||||
}
|
||||
|
||||
void intel_write_dp_vsc_sdp(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
struct drm_dp_vsc_sdp *vsc)
|
||||
{
|
||||
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct dp_sdp sdp = {};
|
||||
ssize_t len;
|
||||
|
||||
len = intel_dp_vsc_sdp_pack(vsc, &sdp, sizeof(sdp));
|
||||
|
||||
if (drm_WARN_ON(&dev_priv->drm, len < 0))
|
||||
return;
|
||||
|
||||
intel_dig_port->write_infoframe(encoder, crtc_state, DP_SDP_VSC,
|
||||
&sdp, len);
|
||||
}
|
||||
|
||||
void intel_dp_set_infoframes(struct intel_encoder *encoder,
|
||||
bool enable,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
@@ -4971,233 +5033,191 @@ void intel_dp_set_infoframes(struct intel_encoder *encoder,
|
||||
intel_write_dp_sdp(encoder, crtc_state, HDMI_PACKET_TYPE_GAMUT_METADATA);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_setup_vsc_sdp(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
static int intel_dp_vsc_sdp_unpack(struct drm_dp_vsc_sdp *vsc,
|
||||
const void *buffer, size_t size)
|
||||
{
|
||||
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
|
||||
struct dp_sdp vsc_sdp = {};
|
||||
const struct dp_sdp *sdp = buffer;
|
||||
|
||||
/* Prepare VSC Header for SU as per DP 1.4a spec, Table 2-119 */
|
||||
vsc_sdp.sdp_header.HB0 = 0;
|
||||
vsc_sdp.sdp_header.HB1 = 0x7;
|
||||
if (size < sizeof(struct dp_sdp))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
|
||||
* Colorimetry Format indication.
|
||||
*/
|
||||
vsc_sdp.sdp_header.HB2 = 0x5;
|
||||
memset(vsc, 0, size);
|
||||
|
||||
/*
|
||||
* VSC SDP supporting 3D stereo, + PSR2, + Pixel Encoding/
|
||||
* Colorimetry Format indication (HB2 = 05h).
|
||||
*/
|
||||
vsc_sdp.sdp_header.HB3 = 0x13;
|
||||
if (sdp->sdp_header.HB0 != 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* DP 1.4a spec, Table 2-120 */
|
||||
switch (crtc_state->output_format) {
|
||||
case INTEL_OUTPUT_FORMAT_YCBCR444:
|
||||
vsc_sdp.db[16] = 0x1 << 4; /* YCbCr 444 : DB16[7:4] = 1h */
|
||||
break;
|
||||
case INTEL_OUTPUT_FORMAT_YCBCR420:
|
||||
vsc_sdp.db[16] = 0x3 << 4; /* YCbCr 420 : DB16[7:4] = 3h */
|
||||
break;
|
||||
case INTEL_OUTPUT_FORMAT_RGB:
|
||||
default:
|
||||
/* RGB: DB16[7:4] = 0h */
|
||||
break;
|
||||
if (sdp->sdp_header.HB1 != DP_SDP_VSC)
|
||||
return -EINVAL;
|
||||
|
||||
vsc->sdp_type = sdp->sdp_header.HB1;
|
||||
vsc->revision = sdp->sdp_header.HB2;
|
||||
vsc->length = sdp->sdp_header.HB3;
|
||||
|
||||
if ((sdp->sdp_header.HB2 == 0x2 && sdp->sdp_header.HB3 == 0x8) ||
|
||||
(sdp->sdp_header.HB2 == 0x4 && sdp->sdp_header.HB3 == 0xe)) {
|
||||
/*
|
||||
* - HB2 = 0x2, HB3 = 0x8
|
||||
* VSC SDP supporting 3D stereo + PSR
|
||||
* - HB2 = 0x4, HB3 = 0xe
|
||||
* VSC SDP supporting 3D stereo + PSR2 with Y-coordinate of
|
||||
* first scan line of the SU region (applies to eDP v1.4b
|
||||
* and higher).
|
||||
*/
|
||||
return 0;
|
||||
} else if (sdp->sdp_header.HB2 == 0x5 && sdp->sdp_header.HB3 == 0x13) {
|
||||
/*
|
||||
* - HB2 = 0x5, HB3 = 0x13
|
||||
* VSC SDP supporting 3D stereo + PSR2 + Pixel Encoding/Colorimetry
|
||||
* Format.
|
||||
*/
|
||||
vsc->pixelformat = (sdp->db[16] >> 4) & 0xf;
|
||||
vsc->colorimetry = sdp->db[16] & 0xf;
|
||||
vsc->dynamic_range = (sdp->db[17] >> 7) & 0x1;
|
||||
|
||||
switch (sdp->db[17] & 0x7) {
|
||||
case 0x0:
|
||||
vsc->bpc = 6;
|
||||
break;
|
||||
case 0x1:
|
||||
vsc->bpc = 8;
|
||||
break;
|
||||
case 0x2:
|
||||
vsc->bpc = 10;
|
||||
break;
|
||||
case 0x3:
|
||||
vsc->bpc = 12;
|
||||
break;
|
||||
case 0x4:
|
||||
vsc->bpc = 16;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(sdp->db[17] & 0x7);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vsc->content_type = sdp->db[18] & 0x7;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (conn_state->colorspace) {
|
||||
case DRM_MODE_COLORIMETRY_BT709_YCC:
|
||||
vsc_sdp.db[16] |= 0x1;
|
||||
break;
|
||||
case DRM_MODE_COLORIMETRY_XVYCC_601:
|
||||
vsc_sdp.db[16] |= 0x2;
|
||||
break;
|
||||
case DRM_MODE_COLORIMETRY_XVYCC_709:
|
||||
vsc_sdp.db[16] |= 0x3;
|
||||
break;
|
||||
case DRM_MODE_COLORIMETRY_SYCC_601:
|
||||
vsc_sdp.db[16] |= 0x4;
|
||||
break;
|
||||
case DRM_MODE_COLORIMETRY_OPYCC_601:
|
||||
vsc_sdp.db[16] |= 0x5;
|
||||
break;
|
||||
case DRM_MODE_COLORIMETRY_BT2020_CYCC:
|
||||
case DRM_MODE_COLORIMETRY_BT2020_RGB:
|
||||
vsc_sdp.db[16] |= 0x6;
|
||||
break;
|
||||
case DRM_MODE_COLORIMETRY_BT2020_YCC:
|
||||
vsc_sdp.db[16] |= 0x7;
|
||||
break;
|
||||
case DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65:
|
||||
case DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER:
|
||||
vsc_sdp.db[16] |= 0x4; /* DCI-P3 (SMPTE RP 431-2) */
|
||||
break;
|
||||
default:
|
||||
/* sRGB (IEC 61966-2-1) / ITU-R BT.601: DB16[0:3] = 0h */
|
||||
|
||||
/* RGB->YCBCR color conversion uses the BT.709 color space. */
|
||||
if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
|
||||
vsc_sdp.db[16] |= 0x1; /* 0x1, ITU-R BT.709 */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* For pixel encoding formats YCbCr444, YCbCr422, YCbCr420, and Y Only,
|
||||
* the following Component Bit Depth values are defined:
|
||||
* 001b = 8bpc.
|
||||
* 010b = 10bpc.
|
||||
* 011b = 12bpc.
|
||||
* 100b = 16bpc.
|
||||
*/
|
||||
switch (crtc_state->pipe_bpp) {
|
||||
case 24: /* 8bpc */
|
||||
vsc_sdp.db[17] = 0x1;
|
||||
break;
|
||||
case 30: /* 10bpc */
|
||||
vsc_sdp.db[17] = 0x2;
|
||||
break;
|
||||
case 36: /* 12bpc */
|
||||
vsc_sdp.db[17] = 0x3;
|
||||
break;
|
||||
case 48: /* 16bpc */
|
||||
vsc_sdp.db[17] = 0x4;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(crtc_state->pipe_bpp);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dynamic Range (Bit 7)
|
||||
* 0 = VESA range, 1 = CTA range.
|
||||
* all YCbCr are always limited range
|
||||
*/
|
||||
vsc_sdp.db[17] |= 0x80;
|
||||
|
||||
/*
|
||||
* Content Type (Bits 2:0)
|
||||
* 000b = Not defined.
|
||||
* 001b = Graphics.
|
||||
* 010b = Photo.
|
||||
* 011b = Video.
|
||||
* 100b = Game
|
||||
* All other values are RESERVED.
|
||||
* Note: See CTA-861-G for the definition and expected
|
||||
* processing by a stream sink for the above contect types.
|
||||
*/
|
||||
vsc_sdp.db[18] = 0;
|
||||
|
||||
intel_dig_port->write_infoframe(&intel_dig_port->base,
|
||||
crtc_state, DP_SDP_VSC, &vsc_sdp, sizeof(vsc_sdp));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_setup_hdr_metadata_infoframe_sdp(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
static int
|
||||
intel_dp_hdr_metadata_infoframe_sdp_unpack(struct hdmi_drm_infoframe *drm_infoframe,
|
||||
const void *buffer, size_t size)
|
||||
{
|
||||
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
|
||||
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
|
||||
struct dp_sdp infoframe_sdp = {};
|
||||
struct hdmi_drm_infoframe drm_infoframe = {};
|
||||
const int infoframe_size = HDMI_INFOFRAME_HEADER_SIZE + HDMI_DRM_INFOFRAME_SIZE;
|
||||
unsigned char buf[HDMI_INFOFRAME_HEADER_SIZE + HDMI_DRM_INFOFRAME_SIZE];
|
||||
ssize_t len;
|
||||
int ret;
|
||||
|
||||
ret = drm_hdmi_infoframe_set_hdr_metadata(&drm_infoframe, conn_state);
|
||||
if (ret) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"couldn't set HDR metadata in infoframe\n");
|
||||
return;
|
||||
}
|
||||
const struct dp_sdp *sdp = buffer;
|
||||
|
||||
len = hdmi_drm_infoframe_pack_only(&drm_infoframe, buf, sizeof(buf));
|
||||
if (len < 0) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"buffer size is smaller than hdr metadata infoframe\n");
|
||||
return;
|
||||
}
|
||||
if (size < sizeof(struct dp_sdp))
|
||||
return -EINVAL;
|
||||
|
||||
if (len != infoframe_size) {
|
||||
drm_dbg_kms(&i915->drm, "wrong static hdr metadata size\n");
|
||||
return;
|
||||
}
|
||||
if (sdp->sdp_header.HB0 != 0)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Set up the infoframe sdp packet for HDR static metadata.
|
||||
* Prepare VSC Header for SU as per DP 1.4a spec,
|
||||
* Table 2-100 and Table 2-101
|
||||
*/
|
||||
if (sdp->sdp_header.HB1 != HDMI_INFOFRAME_TYPE_DRM)
|
||||
return -EINVAL;
|
||||
|
||||
/* Packet ID, 00h for non-Audio INFOFRAME */
|
||||
infoframe_sdp.sdp_header.HB0 = 0;
|
||||
/*
|
||||
* Packet Type 80h + Non-audio INFOFRAME Type value
|
||||
* HDMI_INFOFRAME_TYPE_DRM: 0x87,
|
||||
*/
|
||||
infoframe_sdp.sdp_header.HB1 = drm_infoframe.type;
|
||||
/*
|
||||
* Least Significant Eight Bits of (Data Byte Count – 1)
|
||||
* infoframe_size - 1,
|
||||
* 1Dh (i.e., Data Byte Count = 30 bytes).
|
||||
*/
|
||||
infoframe_sdp.sdp_header.HB2 = 0x1D;
|
||||
if (sdp->sdp_header.HB2 != 0x1D)
|
||||
return -EINVAL;
|
||||
|
||||
/* Most Significant Two Bits of (Data Byte Count – 1), Clear to 00b. */
|
||||
if ((sdp->sdp_header.HB3 & 0x3) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* INFOFRAME SDP Version Number */
|
||||
infoframe_sdp.sdp_header.HB3 = (0x13 << 2);
|
||||
if (((sdp->sdp_header.HB3 >> 2) & 0x3f) != 0x13)
|
||||
return -EINVAL;
|
||||
|
||||
/* CTA Header Byte 2 (INFOFRAME Version Number) */
|
||||
infoframe_sdp.db[0] = drm_infoframe.version;
|
||||
if (sdp->db[0] != 1)
|
||||
return -EINVAL;
|
||||
|
||||
/* CTA Header Byte 3 (Length of INFOFRAME): HDMI_DRM_INFOFRAME_SIZE */
|
||||
infoframe_sdp.db[1] = drm_infoframe.length;
|
||||
/*
|
||||
* Copy HDMI_DRM_INFOFRAME_SIZE size from a buffer after
|
||||
* HDMI_INFOFRAME_HEADER_SIZE
|
||||
*/
|
||||
BUILD_BUG_ON(sizeof(infoframe_sdp.db) < HDMI_DRM_INFOFRAME_SIZE + 2);
|
||||
memcpy(&infoframe_sdp.db[2], &buf[HDMI_INFOFRAME_HEADER_SIZE],
|
||||
HDMI_DRM_INFOFRAME_SIZE);
|
||||
if (sdp->db[1] != HDMI_DRM_INFOFRAME_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Size of DP infoframe sdp packet for HDR static metadata is consist of
|
||||
* - DP SDP Header(struct dp_sdp_header): 4 bytes
|
||||
* - Two Data Blocks: 2 bytes
|
||||
* CTA Header Byte2 (INFOFRAME Version Number)
|
||||
* CTA Header Byte3 (Length of INFOFRAME)
|
||||
* - HDMI_DRM_INFOFRAME_SIZE: 26 bytes
|
||||
*
|
||||
* Prior to GEN11's GMP register size is identical to DP HDR static metadata
|
||||
* infoframe size. But GEN11+ has larger than that size, write_infoframe
|
||||
* will pad rest of the size.
|
||||
*/
|
||||
intel_dig_port->write_infoframe(&intel_dig_port->base, crtc_state,
|
||||
HDMI_PACKET_TYPE_GAMUT_METADATA,
|
||||
&infoframe_sdp,
|
||||
sizeof(struct dp_sdp_header) + 2 + HDMI_DRM_INFOFRAME_SIZE);
|
||||
ret = hdmi_drm_infoframe_unpack_only(drm_infoframe, &sdp->db[2],
|
||||
HDMI_DRM_INFOFRAME_SIZE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void intel_dp_vsc_enable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
static void intel_read_dp_vsc_sdp(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *crtc_state,
|
||||
struct drm_dp_vsc_sdp *vsc)
|
||||
{
|
||||
if (!intel_dp_needs_vsc_sdp(crtc_state, conn_state))
|
||||
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
unsigned int type = DP_SDP_VSC;
|
||||
struct dp_sdp sdp = {};
|
||||
int ret;
|
||||
|
||||
/* When PSR is enabled, VSC SDP is handled by PSR routine */
|
||||
if (intel_psr_enabled(intel_dp))
|
||||
return;
|
||||
|
||||
intel_dp_setup_vsc_sdp(intel_dp, crtc_state, conn_state);
|
||||
if ((crtc_state->infoframes.enable &
|
||||
intel_hdmi_infoframe_enable(type)) == 0)
|
||||
return;
|
||||
|
||||
intel_dig_port->read_infoframe(encoder, crtc_state, type, &sdp, sizeof(sdp));
|
||||
|
||||
ret = intel_dp_vsc_sdp_unpack(vsc, &sdp, sizeof(sdp));
|
||||
|
||||
if (ret)
|
||||
drm_dbg_kms(&dev_priv->drm, "Failed to unpack DP VSC SDP\n");
|
||||
}
|
||||
|
||||
void intel_dp_hdr_metadata_enable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
static void intel_read_dp_hdr_metadata_infoframe_sdp(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *crtc_state,
|
||||
struct hdmi_drm_infoframe *drm_infoframe)
|
||||
{
|
||||
if (!conn_state->hdr_output_metadata)
|
||||
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
unsigned int type = HDMI_PACKET_TYPE_GAMUT_METADATA;
|
||||
struct dp_sdp sdp = {};
|
||||
int ret;
|
||||
|
||||
if ((crtc_state->infoframes.enable &
|
||||
intel_hdmi_infoframe_enable(type)) == 0)
|
||||
return;
|
||||
|
||||
intel_dp_setup_hdr_metadata_infoframe_sdp(intel_dp,
|
||||
crtc_state,
|
||||
conn_state);
|
||||
intel_dig_port->read_infoframe(encoder, crtc_state, type, &sdp,
|
||||
sizeof(sdp));
|
||||
|
||||
ret = intel_dp_hdr_metadata_infoframe_sdp_unpack(drm_infoframe, &sdp,
|
||||
sizeof(sdp));
|
||||
|
||||
if (ret)
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Failed to unpack DP HDR Metadata Infoframe SDP\n");
|
||||
}
|
||||
|
||||
void intel_read_dp_sdp(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *crtc_state,
|
||||
unsigned int type)
|
||||
{
|
||||
switch (type) {
|
||||
case DP_SDP_VSC:
|
||||
intel_read_dp_vsc_sdp(encoder, crtc_state,
|
||||
&crtc_state->infoframes.vsc);
|
||||
break;
|
||||
case HDMI_PACKET_TYPE_GAMUT_METADATA:
|
||||
intel_read_dp_hdr_metadata_infoframe_sdp(encoder, crtc_state,
|
||||
&crtc_state->infoframes.drm.drm);
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static u8 intel_dp_autotest_link_training(struct intel_dp *intel_dp)
|
||||
@@ -5998,64 +6018,7 @@ edp_detect(struct intel_dp *intel_dp)
|
||||
static bool ibx_digital_port_connected(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
u32 bit;
|
||||
|
||||
switch (encoder->hpd_pin) {
|
||||
case HPD_PORT_B:
|
||||
bit = SDE_PORTB_HOTPLUG;
|
||||
break;
|
||||
case HPD_PORT_C:
|
||||
bit = SDE_PORTC_HOTPLUG;
|
||||
break;
|
||||
case HPD_PORT_D:
|
||||
bit = SDE_PORTD_HOTPLUG;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(encoder->hpd_pin);
|
||||
return false;
|
||||
}
|
||||
|
||||
return intel_de_read(dev_priv, SDEISR) & bit;
|
||||
}
|
||||
|
||||
static bool cpt_digital_port_connected(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
u32 bit;
|
||||
|
||||
switch (encoder->hpd_pin) {
|
||||
case HPD_PORT_B:
|
||||
bit = SDE_PORTB_HOTPLUG_CPT;
|
||||
break;
|
||||
case HPD_PORT_C:
|
||||
bit = SDE_PORTC_HOTPLUG_CPT;
|
||||
break;
|
||||
case HPD_PORT_D:
|
||||
bit = SDE_PORTD_HOTPLUG_CPT;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(encoder->hpd_pin);
|
||||
return false;
|
||||
}
|
||||
|
||||
return intel_de_read(dev_priv, SDEISR) & bit;
|
||||
}
|
||||
|
||||
static bool spt_digital_port_connected(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
u32 bit;
|
||||
|
||||
switch (encoder->hpd_pin) {
|
||||
case HPD_PORT_A:
|
||||
bit = SDE_PORTA_HOTPLUG_SPT;
|
||||
break;
|
||||
case HPD_PORT_E:
|
||||
bit = SDE_PORTE_HOTPLUG_SPT;
|
||||
break;
|
||||
default:
|
||||
return cpt_digital_port_connected(encoder);
|
||||
}
|
||||
u32 bit = dev_priv->hotplug.pch_hpd[encoder->hpd_pin];
|
||||
|
||||
return intel_de_read(dev_priv, SDEISR) & bit;
|
||||
}
|
||||
@@ -6109,89 +6072,9 @@ static bool gm45_digital_port_connected(struct intel_encoder *encoder)
|
||||
static bool ilk_digital_port_connected(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
u32 bit = dev_priv->hotplug.hpd[encoder->hpd_pin];
|
||||
|
||||
if (encoder->hpd_pin == HPD_PORT_A)
|
||||
return intel_de_read(dev_priv, DEISR) & DE_DP_A_HOTPLUG;
|
||||
else
|
||||
return ibx_digital_port_connected(encoder);
|
||||
}
|
||||
|
||||
static bool snb_digital_port_connected(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
|
||||
if (encoder->hpd_pin == HPD_PORT_A)
|
||||
return intel_de_read(dev_priv, DEISR) & DE_DP_A_HOTPLUG;
|
||||
else
|
||||
return cpt_digital_port_connected(encoder);
|
||||
}
|
||||
|
||||
static bool ivb_digital_port_connected(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
|
||||
if (encoder->hpd_pin == HPD_PORT_A)
|
||||
return intel_de_read(dev_priv, DEISR) & DE_DP_A_HOTPLUG_IVB;
|
||||
else
|
||||
return cpt_digital_port_connected(encoder);
|
||||
}
|
||||
|
||||
static bool bdw_digital_port_connected(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
|
||||
if (encoder->hpd_pin == HPD_PORT_A)
|
||||
return intel_de_read(dev_priv, GEN8_DE_PORT_ISR) & GEN8_PORT_DP_A_HOTPLUG;
|
||||
else
|
||||
return cpt_digital_port_connected(encoder);
|
||||
}
|
||||
|
||||
static bool bxt_digital_port_connected(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
u32 bit;
|
||||
|
||||
switch (encoder->hpd_pin) {
|
||||
case HPD_PORT_A:
|
||||
bit = BXT_DE_PORT_HP_DDIA;
|
||||
break;
|
||||
case HPD_PORT_B:
|
||||
bit = BXT_DE_PORT_HP_DDIB;
|
||||
break;
|
||||
case HPD_PORT_C:
|
||||
bit = BXT_DE_PORT_HP_DDIC;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(encoder->hpd_pin);
|
||||
return false;
|
||||
}
|
||||
|
||||
return intel_de_read(dev_priv, GEN8_DE_PORT_ISR) & bit;
|
||||
}
|
||||
|
||||
static bool intel_combo_phy_connected(struct drm_i915_private *dev_priv,
|
||||
enum phy phy)
|
||||
{
|
||||
if (HAS_PCH_MCC(dev_priv) && phy == PHY_C)
|
||||
return intel_de_read(dev_priv, SDEISR) & SDE_TC_HOTPLUG_ICP(PORT_TC1);
|
||||
|
||||
return intel_de_read(dev_priv, SDEISR) & SDE_DDI_HOTPLUG_ICP(phy);
|
||||
}
|
||||
|
||||
static bool icp_digital_port_connected(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
|
||||
enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
|
||||
|
||||
if (intel_phy_is_combo(dev_priv, phy))
|
||||
return intel_combo_phy_connected(dev_priv, phy);
|
||||
else if (intel_phy_is_tc(dev_priv, phy))
|
||||
return intel_tc_port_connected(dig_port);
|
||||
else
|
||||
MISSING_CASE(encoder->hpd_pin);
|
||||
|
||||
return false;
|
||||
return intel_de_read(dev_priv, DEISR) & bit;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -6205,44 +6088,15 @@ static bool icp_digital_port_connected(struct intel_encoder *encoder)
|
||||
*
|
||||
* Return %true if port is connected, %false otherwise.
|
||||
*/
|
||||
static bool __intel_digital_port_connected(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
|
||||
if (HAS_GMCH(dev_priv)) {
|
||||
if (IS_GM45(dev_priv))
|
||||
return gm45_digital_port_connected(encoder);
|
||||
else
|
||||
return g4x_digital_port_connected(encoder);
|
||||
}
|
||||
|
||||
if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
|
||||
return icp_digital_port_connected(encoder);
|
||||
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT)
|
||||
return spt_digital_port_connected(encoder);
|
||||
else if (IS_GEN9_LP(dev_priv))
|
||||
return bxt_digital_port_connected(encoder);
|
||||
else if (IS_GEN(dev_priv, 8))
|
||||
return bdw_digital_port_connected(encoder);
|
||||
else if (IS_GEN(dev_priv, 7))
|
||||
return ivb_digital_port_connected(encoder);
|
||||
else if (IS_GEN(dev_priv, 6))
|
||||
return snb_digital_port_connected(encoder);
|
||||
else if (IS_GEN(dev_priv, 5))
|
||||
return ilk_digital_port_connected(encoder);
|
||||
|
||||
MISSING_CASE(INTEL_GEN(dev_priv));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool intel_digital_port_connected(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
|
||||
bool is_connected = false;
|
||||
intel_wakeref_t wakeref;
|
||||
|
||||
with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref)
|
||||
is_connected = __intel_digital_port_connected(encoder);
|
||||
is_connected = dig_port->connected(encoder);
|
||||
|
||||
return is_connected;
|
||||
}
|
||||
@@ -8522,6 +8376,18 @@ bool intel_dp_init(struct drm_i915_private *dev_priv,
|
||||
|
||||
intel_dig_port->hpd_pulse = intel_dp_hpd_pulse;
|
||||
|
||||
if (HAS_GMCH(dev_priv)) {
|
||||
if (IS_GM45(dev_priv))
|
||||
intel_dig_port->connected = gm45_digital_port_connected;
|
||||
else
|
||||
intel_dig_port->connected = g4x_digital_port_connected;
|
||||
} else {
|
||||
if (port == PORT_A)
|
||||
intel_dig_port->connected = ilk_digital_port_connected;
|
||||
else
|
||||
intel_dig_port->connected = ibx_digital_port_connected;
|
||||
}
|
||||
|
||||
if (port != PORT_A)
|
||||
intel_infoframe_init(intel_dig_port);
|
||||
|
||||
|
@@ -16,6 +16,7 @@ struct drm_connector_state;
|
||||
struct drm_encoder;
|
||||
struct drm_i915_private;
|
||||
struct drm_modeset_acquire_ctx;
|
||||
struct drm_dp_vsc_sdp;
|
||||
struct intel_connector;
|
||||
struct intel_crtc_state;
|
||||
struct intel_digital_port;
|
||||
@@ -108,15 +109,19 @@ int intel_dp_link_required(int pixel_clock, int bpp);
|
||||
int intel_dp_max_data_rate(int max_link_clock, int max_lanes);
|
||||
bool intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state);
|
||||
void intel_dp_vsc_enable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state);
|
||||
void intel_dp_hdr_metadata_enable(struct intel_dp *intel_dp,
|
||||
void intel_dp_compute_psr_vsc_sdp(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state);
|
||||
const struct drm_connector_state *conn_state,
|
||||
struct drm_dp_vsc_sdp *vsc);
|
||||
void intel_write_dp_vsc_sdp(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
struct drm_dp_vsc_sdp *vsc);
|
||||
void intel_dp_set_infoframes(struct intel_encoder *encoder, bool enable,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state);
|
||||
void intel_read_dp_sdp(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *crtc_state,
|
||||
unsigned int type);
|
||||
bool intel_digital_port_connected(struct intel_encoder *encoder);
|
||||
void intel_dp_process_phy_request(struct intel_dp *intel_dp);
|
||||
|
||||
|
@@ -510,10 +510,6 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
|
||||
|
||||
intel_ddi_enable_transcoder_func(encoder, pipe_config);
|
||||
|
||||
intel_enable_pipe(pipe_config);
|
||||
|
||||
intel_crtc_vblank_on(pipe_config);
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "active links %d\n",
|
||||
intel_dp->active_mst_links);
|
||||
|
||||
@@ -524,6 +520,11 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
|
||||
drm_dp_check_act_status(&intel_dp->mst_mgr);
|
||||
|
||||
drm_dp_update_payload_part2(&intel_dp->mst_mgr);
|
||||
|
||||
intel_enable_pipe(pipe_config);
|
||||
|
||||
intel_crtc_vblank_on(pipe_config);
|
||||
|
||||
if (pipe_config->has_audio)
|
||||
intel_audio_codec_enable(encoder, pipe_config, conn_state);
|
||||
}
|
||||
|
@@ -540,6 +540,9 @@ static void __intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct intel_fbc *fbc = &dev_priv->fbc;
|
||||
|
||||
if (WARN_ON(intel_fbc_hw_is_active(dev_priv)))
|
||||
return;
|
||||
|
||||
if (!drm_mm_node_allocated(&fbc->compressed_fb))
|
||||
return;
|
||||
|
||||
@@ -564,7 +567,7 @@ void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv)
|
||||
}
|
||||
|
||||
static bool stride_is_valid(struct drm_i915_private *dev_priv,
|
||||
unsigned int stride)
|
||||
u64 modifier, unsigned int stride)
|
||||
{
|
||||
/* This should have been caught earlier. */
|
||||
if (drm_WARN_ON_ONCE(&dev_priv->drm, (stride & (64 - 1)) != 0))
|
||||
@@ -580,6 +583,11 @@ static bool stride_is_valid(struct drm_i915_private *dev_priv,
|
||||
if (IS_GEN(dev_priv, 4) && !IS_G4X(dev_priv) && stride < 2048)
|
||||
return false;
|
||||
|
||||
/* Display WA #1105: skl,bxt,kbl,cfl,glk */
|
||||
if (IS_GEN(dev_priv, 9) &&
|
||||
modifier == DRM_FORMAT_MOD_LINEAR && stride & 511)
|
||||
return false;
|
||||
|
||||
if (stride > 16384)
|
||||
return false;
|
||||
|
||||
@@ -810,7 +818,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!stride_is_valid(dev_priv, cache->fb.stride)) {
|
||||
if (!stride_is_valid(dev_priv, cache->fb.modifier, cache->fb.stride)) {
|
||||
fbc->no_fbc_reason = "framebuffer stride not supported";
|
||||
return false;
|
||||
}
|
||||
|
@@ -522,7 +522,7 @@ u32 lspcon_infoframes_enabled(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
/* FIXME actually read this from the hw */
|
||||
return enc_to_intel_lspcon(encoder)->active;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lspcon_resume(struct intel_lspcon *lspcon)
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_psr.h"
|
||||
#include "intel_sprite.h"
|
||||
#include "intel_hdmi.h"
|
||||
|
||||
/**
|
||||
* DOC: Panel Self Refresh (PSR/SRD)
|
||||
@@ -357,39 +358,6 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
|
||||
}
|
||||
}
|
||||
|
||||
static void intel_psr_setup_vsc(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
struct dp_sdp psr_vsc;
|
||||
|
||||
if (dev_priv->psr.psr2_enabled) {
|
||||
/* Prepare VSC Header for SU as per EDP 1.4 spec, Table 6.11 */
|
||||
memset(&psr_vsc, 0, sizeof(psr_vsc));
|
||||
psr_vsc.sdp_header.HB0 = 0;
|
||||
psr_vsc.sdp_header.HB1 = 0x7;
|
||||
if (dev_priv->psr.colorimetry_support) {
|
||||
psr_vsc.sdp_header.HB2 = 0x5;
|
||||
psr_vsc.sdp_header.HB3 = 0x13;
|
||||
} else {
|
||||
psr_vsc.sdp_header.HB2 = 0x4;
|
||||
psr_vsc.sdp_header.HB3 = 0xe;
|
||||
}
|
||||
} else {
|
||||
/* Prepare VSC packet as per EDP 1.3 spec, Table 3.10 */
|
||||
memset(&psr_vsc, 0, sizeof(psr_vsc));
|
||||
psr_vsc.sdp_header.HB0 = 0;
|
||||
psr_vsc.sdp_header.HB1 = 0x7;
|
||||
psr_vsc.sdp_header.HB2 = 0x2;
|
||||
psr_vsc.sdp_header.HB3 = 0x8;
|
||||
}
|
||||
|
||||
intel_dig_port->write_infoframe(&intel_dig_port->base,
|
||||
crtc_state,
|
||||
DP_SDP_VSC, &psr_vsc, sizeof(psr_vsc));
|
||||
}
|
||||
|
||||
static void hsw_psr_setup_aux(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
@@ -756,6 +724,8 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
|
||||
if (intel_dp != dev_priv->psr.dp)
|
||||
return;
|
||||
|
||||
if (!psr_global_enabled(dev_priv))
|
||||
return;
|
||||
/*
|
||||
* HSW spec explicitly says PSR is tied to port A.
|
||||
* BDW+ platforms have a instance of PSR registers per transcoder but
|
||||
@@ -798,6 +768,7 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
|
||||
|
||||
crtc_state->has_psr = true;
|
||||
crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp, crtc_state);
|
||||
crtc_state->infoframes.enable |= intel_hdmi_infoframe_enable(DP_SDP_VSC);
|
||||
}
|
||||
|
||||
static void intel_psr_activate(struct intel_dp *intel_dp)
|
||||
@@ -880,9 +851,12 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
|
||||
}
|
||||
|
||||
static void intel_psr_enable_locked(struct drm_i915_private *dev_priv,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct intel_dp *intel_dp = dev_priv->psr.dp;
|
||||
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
|
||||
struct intel_encoder *encoder = &intel_dig_port->base;
|
||||
u32 val;
|
||||
|
||||
drm_WARN_ON(&dev_priv->drm, dev_priv->psr.enabled);
|
||||
@@ -921,7 +895,9 @@ static void intel_psr_enable_locked(struct drm_i915_private *dev_priv,
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "Enabling PSR%s\n",
|
||||
dev_priv->psr.psr2_enabled ? "2" : "1");
|
||||
intel_psr_setup_vsc(intel_dp, crtc_state);
|
||||
intel_dp_compute_psr_vsc_sdp(intel_dp, crtc_state, conn_state,
|
||||
&dev_priv->psr.vsc);
|
||||
intel_write_dp_vsc_sdp(encoder, crtc_state, &dev_priv->psr.vsc);
|
||||
intel_psr_enable_sink(intel_dp);
|
||||
intel_psr_enable_source(intel_dp, crtc_state);
|
||||
dev_priv->psr.enabled = true;
|
||||
@@ -933,11 +909,13 @@ static void intel_psr_enable_locked(struct drm_i915_private *dev_priv,
|
||||
* intel_psr_enable - Enable PSR
|
||||
* @intel_dp: Intel DP
|
||||
* @crtc_state: new CRTC state
|
||||
* @conn_state: new CONNECTOR state
|
||||
*
|
||||
* This function can only be called after the pipe is fully trained and enabled.
|
||||
*/
|
||||
void intel_psr_enable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
|
||||
@@ -958,7 +936,7 @@ void intel_psr_enable(struct intel_dp *intel_dp,
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
intel_psr_enable_locked(dev_priv, crtc_state);
|
||||
intel_psr_enable_locked(dev_priv, crtc_state, conn_state);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&dev_priv->psr.lock);
|
||||
@@ -1091,13 +1069,15 @@ static void psr_force_hw_tracking_exit(struct drm_i915_private *dev_priv)
|
||||
* intel_psr_update - Update PSR state
|
||||
* @intel_dp: Intel DP
|
||||
* @crtc_state: new CRTC state
|
||||
* @conn_state: new CONNECTOR state
|
||||
*
|
||||
* This functions will update PSR states, disabling, enabling or switching PSR
|
||||
* version when executing fastsets. For full modeset, intel_psr_disable() and
|
||||
* intel_psr_enable() should be called instead.
|
||||
*/
|
||||
void intel_psr_update(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
struct i915_psr *psr = &dev_priv->psr;
|
||||
@@ -1134,7 +1114,7 @@ void intel_psr_update(struct intel_dp *intel_dp,
|
||||
intel_psr_disable_locked(intel_dp);
|
||||
|
||||
if (enable)
|
||||
intel_psr_enable_locked(dev_priv, crtc_state);
|
||||
intel_psr_enable_locked(dev_priv, crtc_state, conn_state);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&dev_priv->psr.lock);
|
||||
|
@@ -17,11 +17,13 @@ struct intel_dp;
|
||||
#define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support)
|
||||
void intel_psr_init_dpcd(struct intel_dp *intel_dp);
|
||||
void intel_psr_enable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state);
|
||||
void intel_psr_disable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *old_crtc_state);
|
||||
void intel_psr_update(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state);
|
||||
int intel_psr_debug_set(struct drm_i915_private *dev_priv, u64 value);
|
||||
void intel_psr_invalidate(struct drm_i915_private *dev_priv,
|
||||
unsigned frontbuffer_bits,
|
||||
|
@@ -238,8 +238,8 @@ static void tc_port_fixup_legacy_flag(struct intel_digital_port *dig_port,
|
||||
static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
|
||||
enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
|
||||
struct intel_uncore *uncore = &i915->uncore;
|
||||
u32 isr_bit = i915->hotplug.pch_hpd[dig_port->base.hpd_pin];
|
||||
u32 mask = 0;
|
||||
u32 val;
|
||||
|
||||
@@ -258,7 +258,7 @@ static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port)
|
||||
if (val & TC_LIVE_STATE_TC(dig_port->tc_phy_fia_idx))
|
||||
mask |= BIT(TC_PORT_DP_ALT);
|
||||
|
||||
if (intel_uncore_read(uncore, SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port))
|
||||
if (intel_uncore_read(uncore, SDEISR) & isr_bit)
|
||||
mask |= BIT(TC_PORT_LEGACY);
|
||||
|
||||
/* The sink can be connected only in a single mode. */
|
||||
@@ -562,8 +562,9 @@ static bool intel_tc_port_needs_reset(struct intel_digital_port *dig_port)
|
||||
* connected ports are usable, and avoids exposing to the users objects they
|
||||
* can't really use.
|
||||
*/
|
||||
bool intel_tc_port_connected(struct intel_digital_port *dig_port)
|
||||
bool intel_tc_port_connected(struct intel_encoder *encoder)
|
||||
{
|
||||
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
|
||||
bool is_connected;
|
||||
intel_wakeref_t tc_cold_wref;
|
||||
|
||||
|
@@ -10,8 +10,9 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
struct intel_digital_port;
|
||||
struct intel_encoder;
|
||||
|
||||
bool intel_tc_port_connected(struct intel_digital_port *dig_port);
|
||||
bool intel_tc_port_connected(struct intel_encoder *encoder);
|
||||
u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port);
|
||||
u32 intel_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_port);
|
||||
int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port);
|
||||
|
@@ -462,7 +462,7 @@ struct bdb_general_definitions {
|
||||
* number = (block_size - sizeof(bdb_general_definitions))/
|
||||
* defs->child_dev_size;
|
||||
*/
|
||||
u8 devices[0];
|
||||
u8 devices[];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
@@ -839,7 +839,7 @@ struct bdb_mipi_config {
|
||||
|
||||
struct bdb_mipi_sequence {
|
||||
u8 version;
|
||||
u8 data[0]; /* up to 6 variable length blocks */
|
||||
u8 data[]; /* up to 6 variable length blocks */
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user