Merge tag 'drm-intel-next-2023-09-29' of git://anongit.freedesktop.org/drm/drm-intel into drm-next
drm/i915 feature pull for v6.7: Features and functionality: - Early Xe2 LPD / Lunarlake (LNL) display enabling (Lucas, Matt, Gustavo, Stanislav, Luca, Clint, Juha-Pekka, Balasubramani, Ravi) - Plenty of various DSC improvements and fixes (Ankit) - Add DSC PPS state readout and verification (Suraj) - Improve fastsets for VRR, LRR and M/N updates (Ville) - Use connector->ddc to create (non-DP MST) connector sysfs ddc symlinks (Ville) - Various DSB improvements, load LUTs using DSB (Ville) - Improve shared link bandwidth management, starting with FDI (Imre) - Optimize get param ioctl for PXP status (Alan) - Remove DG2 pre-production hardware workarounds (Matt) - Add more RPL P/U PCI IDs (Dnyaneshwar) - Add new DG2-G12 stepping (Swati) - Add PSR sink error status to debugfs (Jouni) - Add DP enhanced framing to crtc state checker (Ville) Refactoring and cleanups: - Simplify TileY/Tile4 tiling selftest enumeration (Matt) - Remove some unused power domain code (Gustavo) - Check stepping of display IP version rather than MTL platform (Matt) - DP audio compute config cleanups (Vinod) - SDVO cleanups and refactoring, more robust failure handling (Ville) - Color register definition and readout cleanups (Jani) - Reduce header interdependencies for frontbuffer tracking (Jani) - Continue replacing struct edid with struct drm_edid (Jani) - Use source physical address instead of EDID for CEC (Jani) - Clean up Type-C port lane count functions (Luca) - Clean up DSC PPS register definitions and readout (Jani) - Stop using GEM_BUG_ON()/GEM_WARN_ON() in display code (Jani) - Move more of the display probe to display code (Jani) - Remove redundant runtime suspended state flag (Jouni) - Move display info printing to display code (Balasubramani) - Frontbuffer tracking improvements (Jouni) - Add trailing newlines to debug logging (Jim Cromie) - Separate display workarounds from clock gating init (Matt) - Reduce dmesg log spamming for combo PHY, PLL state, FEC, DP MST (Ville, Imre) Fixes: - Fix hotplug poll detect loops via suspend/resume (Imre) - Fix hotplug detect for forced connectors (Imre) - Fix DSC first_line_bpg_offset calculation (Suraj) - Fix debug prints for SDP CRC16 (Arun) - Fix PXP runtime resume (Alan) - Fix cx0 PHY lane handling (Gustavo) - Fix frontbuffer tracking locking in debugfs (Juha-Pekka) - Fix SDVO detect on some models (Ville) - Fix SDP split configuration for DP MST (Vinod) - Fix AUX usage and reads for HDCP on DP MST (Suraj) - Fix PSR workaround (Jouni) - Fix redundant AUX power get/put in DP force (Imre) - Fix ICL DSI TCLK POST by letting hardware handle it (William) - Fix IRQ reset for XE LP+ (Gustavo) - Fix h/vsync_end instead of h/vtotal in VBT (Ville) - Fix C20 PHY msgbus timeout issues (Gustavo) - Fix pre-TGL FEC pipe A vs. DDI A mixup (Ville) - Fix FEC state readout for DP MST (Ville) DRM subsystem core changes: - Assume sink supports 8 bpc when DSC is supported (Ankit) - Add drm_edid_is_digital() helper (Jani) - Parse source physical address from EDID (Jani) - Add function to attach CEC without EDID (Jani) - Reorder connector sysfs/debugfs remove (Ville) - Register connector sysfs ddc symlink later (Ville) Media subsystem changes: - Add comments about CEC source physical address usage (Jani) Merges: - Backmerge drm-next to get v6.6-rc1 (Jani) Signed-off-by: Dave Airlie <airlied@redhat.com> # Conflicts: # drivers/gpu/drm/i915/i915_drv.h From: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/87r0mhi7a6.fsf@intel.com
This commit is contained in:
commit
389af786f9
|
|
@ -14,6 +14,7 @@
|
|||
#include <drm/display/drm_dp_helper.h>
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_edid.h>
|
||||
|
||||
/*
|
||||
* Unfortunately it turns out that we have a chicken-and-egg situation
|
||||
|
|
@ -297,7 +298,7 @@ static void drm_dp_cec_unregister_work(struct work_struct *work)
|
|||
* were unchanged and just update the CEC physical address. Otherwise
|
||||
* unregister the old CEC adapter and create a new one.
|
||||
*/
|
||||
void drm_dp_cec_set_edid(struct drm_dp_aux *aux, const struct edid *edid)
|
||||
void drm_dp_cec_attach(struct drm_dp_aux *aux, u16 source_physical_address)
|
||||
{
|
||||
struct drm_connector *connector = aux->cec.connector;
|
||||
u32 cec_caps = CEC_CAP_DEFAULTS | CEC_CAP_NEEDS_HPD |
|
||||
|
|
@ -339,7 +340,7 @@ void drm_dp_cec_set_edid(struct drm_dp_aux *aux, const struct edid *edid)
|
|||
if (aux->cec.adap->capabilities == cec_caps &&
|
||||
aux->cec.adap->available_log_addrs == num_las) {
|
||||
/* Unchanged, so just set the phys addr */
|
||||
cec_s_phys_addr_from_edid(aux->cec.adap, edid);
|
||||
cec_s_phys_addr(aux->cec.adap, source_physical_address, false);
|
||||
goto unlock;
|
||||
}
|
||||
/*
|
||||
|
|
@ -370,11 +371,27 @@ void drm_dp_cec_set_edid(struct drm_dp_aux *aux, const struct edid *edid)
|
|||
* from drm_dp_cec_register_connector() edid == NULL, so in
|
||||
* that case the phys addr is just invalidated.
|
||||
*/
|
||||
cec_s_phys_addr_from_edid(aux->cec.adap, edid);
|
||||
cec_s_phys_addr(aux->cec.adap, source_physical_address, false);
|
||||
}
|
||||
unlock:
|
||||
mutex_unlock(&aux->cec.lock);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_cec_attach);
|
||||
|
||||
/*
|
||||
* Note: Prefer calling drm_dp_cec_attach() with
|
||||
* connector->display_info.source_physical_address if possible.
|
||||
*/
|
||||
void drm_dp_cec_set_edid(struct drm_dp_aux *aux, const struct edid *edid)
|
||||
{
|
||||
u16 pa = CEC_PHYS_ADDR_INVALID;
|
||||
|
||||
if (edid && edid->extensions)
|
||||
pa = cec_get_edid_phys_addr((const u8 *)edid,
|
||||
EDID_LENGTH * (edid->extensions + 1), NULL);
|
||||
|
||||
drm_dp_cec_attach(aux, pa);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_cec_set_edid);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -2449,12 +2449,16 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_S
|
|||
int num_bpc = 0;
|
||||
u8 color_depth = dsc_dpcd[DP_DSC_DEC_COLOR_DEPTH_CAP - DP_DSC_SUPPORT];
|
||||
|
||||
if (!drm_dp_sink_supports_dsc(dsc_dpcd))
|
||||
return 0;
|
||||
|
||||
if (color_depth & DP_DSC_12_BPC)
|
||||
dsc_bpc[num_bpc++] = 12;
|
||||
if (color_depth & DP_DSC_10_BPC)
|
||||
dsc_bpc[num_bpc++] = 10;
|
||||
if (color_depth & DP_DSC_8_BPC)
|
||||
dsc_bpc[num_bpc++] = 8;
|
||||
|
||||
/* A DP DSC Sink device shall support 8 bpc. */
|
||||
dsc_bpc[num_bpc++] = 8;
|
||||
|
||||
return num_bpc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -631,6 +631,10 @@ int drm_connector_register(struct drm_connector *connector)
|
|||
goto err_debugfs;
|
||||
}
|
||||
|
||||
ret = drm_sysfs_connector_add_late(connector);
|
||||
if (ret)
|
||||
goto err_late_register;
|
||||
|
||||
drm_mode_object_register(connector->dev, &connector->base);
|
||||
|
||||
connector->registration_state = DRM_CONNECTOR_REGISTERED;
|
||||
|
|
@ -647,6 +651,9 @@ int drm_connector_register(struct drm_connector *connector)
|
|||
mutex_unlock(&connector_list_lock);
|
||||
goto unlock;
|
||||
|
||||
err_late_register:
|
||||
if (connector->funcs->early_unregister)
|
||||
connector->funcs->early_unregister(connector);
|
||||
err_debugfs:
|
||||
drm_debugfs_connector_remove(connector);
|
||||
drm_sysfs_connector_remove(connector);
|
||||
|
|
@ -681,11 +688,13 @@ void drm_connector_unregister(struct drm_connector *connector)
|
|||
connector->privacy_screen,
|
||||
&connector->privacy_screen_notifier);
|
||||
|
||||
drm_sysfs_connector_remove_early(connector);
|
||||
|
||||
if (connector->funcs->early_unregister)
|
||||
connector->funcs->early_unregister(connector);
|
||||
|
||||
drm_sysfs_connector_remove(connector);
|
||||
drm_debugfs_connector_remove(connector);
|
||||
drm_sysfs_connector_remove(connector);
|
||||
|
||||
connector->registration_state = DRM_CONNECTOR_UNREGISTERED;
|
||||
mutex_unlock(&connector->mutex);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/cec.h>
|
||||
#include <linux/hdmi.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/kernel.h>
|
||||
|
|
@ -3110,7 +3111,7 @@ drm_monitor_supports_rb(const struct drm_edid *drm_edid)
|
|||
return ret;
|
||||
}
|
||||
|
||||
return ((drm_edid->edid->input & DRM_EDID_INPUT_DIGITAL) != 0);
|
||||
return drm_edid_is_digital(drm_edid);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -6200,6 +6201,8 @@ drm_parse_hdmi_vsdb_video(struct drm_connector *connector, const u8 *db)
|
|||
|
||||
info->is_hdmi = true;
|
||||
|
||||
info->source_physical_address = (db[4] << 8) | db[5];
|
||||
|
||||
if (len >= 6)
|
||||
info->dvi_dual = db[6] & 1;
|
||||
if (len >= 7)
|
||||
|
|
@ -6478,6 +6481,8 @@ static void drm_reset_display_info(struct drm_connector *connector)
|
|||
info->vics_len = 0;
|
||||
|
||||
info->quirks = 0;
|
||||
|
||||
info->source_physical_address = CEC_PHYS_ADDR_INVALID;
|
||||
}
|
||||
|
||||
static void update_displayid_info(struct drm_connector *connector,
|
||||
|
|
@ -6527,7 +6532,7 @@ static void update_display_info(struct drm_connector *connector,
|
|||
if (edid->revision < 3)
|
||||
goto out;
|
||||
|
||||
if (!(edid->input & DRM_EDID_INPUT_DIGITAL))
|
||||
if (!drm_edid_is_digital(drm_edid))
|
||||
goto out;
|
||||
|
||||
info->color_formats |= DRM_COLOR_FORMAT_RGB444;
|
||||
|
|
@ -7343,3 +7348,16 @@ static void _drm_update_tile_info(struct drm_connector *connector,
|
|||
connector->tile_group = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_edid_is_digital - is digital?
|
||||
* @drm_edid: The EDID
|
||||
*
|
||||
* Return true if input is digital.
|
||||
*/
|
||||
bool drm_edid_is_digital(const struct drm_edid *drm_edid)
|
||||
{
|
||||
return drm_edid && drm_edid->edid &&
|
||||
drm_edid->edid->input & DRM_EDID_INPUT_DIGITAL;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_edid_is_digital);
|
||||
|
|
|
|||
|
|
@ -153,6 +153,8 @@ int drm_sysfs_init(void);
|
|||
void drm_sysfs_destroy(void);
|
||||
struct device *drm_sysfs_minor_alloc(struct drm_minor *minor);
|
||||
int drm_sysfs_connector_add(struct drm_connector *connector);
|
||||
int drm_sysfs_connector_add_late(struct drm_connector *connector);
|
||||
void drm_sysfs_connector_remove_early(struct drm_connector *connector);
|
||||
void drm_sysfs_connector_remove(struct drm_connector *connector);
|
||||
|
||||
void drm_sysfs_lease_event(struct drm_device *dev);
|
||||
|
|
|
|||
|
|
@ -400,10 +400,6 @@ int drm_sysfs_connector_add(struct drm_connector *connector)
|
|||
drm_err(dev, "failed to add component to create link to typec connector\n");
|
||||
}
|
||||
|
||||
if (connector->ddc)
|
||||
return sysfs_create_link(&connector->kdev->kobj,
|
||||
&connector->ddc->dev.kobj, "ddc");
|
||||
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
|
|
@ -411,14 +407,26 @@ err_free:
|
|||
return r;
|
||||
}
|
||||
|
||||
int drm_sysfs_connector_add_late(struct drm_connector *connector)
|
||||
{
|
||||
if (connector->ddc)
|
||||
return sysfs_create_link(&connector->kdev->kobj,
|
||||
&connector->ddc->dev.kobj, "ddc");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void drm_sysfs_connector_remove_early(struct drm_connector *connector)
|
||||
{
|
||||
if (connector->ddc)
|
||||
sysfs_remove_link(&connector->kdev->kobj, "ddc");
|
||||
}
|
||||
|
||||
void drm_sysfs_connector_remove(struct drm_connector *connector)
|
||||
{
|
||||
if (!connector->kdev)
|
||||
return;
|
||||
|
||||
if (connector->ddc)
|
||||
sysfs_remove_link(&connector->kdev->kobj, "ddc");
|
||||
|
||||
if (dev_fwnode(connector->kdev))
|
||||
component_del(connector->kdev, &typec_connector_ops);
|
||||
|
||||
|
|
|
|||
|
|
@ -248,6 +248,7 @@ i915-y += \
|
|||
display/intel_display_power_well.o \
|
||||
display/intel_display_reset.o \
|
||||
display/intel_display_rps.o \
|
||||
display/intel_display_wa.o \
|
||||
display/intel_dmc.o \
|
||||
display/intel_dpio_phy.o \
|
||||
display/intel_dpll.o \
|
||||
|
|
@ -267,6 +268,7 @@ i915-y += \
|
|||
display/intel_hotplug.o \
|
||||
display/intel_hotplug_irq.o \
|
||||
display/intel_hti.o \
|
||||
display/intel_link_bw.o \
|
||||
display/intel_load_detect.o \
|
||||
display/intel_lpe_audio.o \
|
||||
display/intel_modeset_lock.o \
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
|
|||
|
||||
intel_de_rmw(dev_priv, TRANS_DP_CTL(crtc->pipe),
|
||||
TRANS_DP_ENH_FRAMING,
|
||||
drm_dp_enhanced_frame_cap(intel_dp->dpcd) ?
|
||||
pipe_config->enhanced_framing ?
|
||||
TRANS_DP_ENH_FRAMING : 0);
|
||||
} else {
|
||||
if (IS_G4X(dev_priv) && pipe_config->limited_color_range)
|
||||
|
|
@ -153,7 +153,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
|
|||
intel_dp->DP |= DP_SYNC_VS_HIGH;
|
||||
intel_dp->DP |= DP_LINK_TRAIN_OFF;
|
||||
|
||||
if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
|
||||
if (pipe_config->enhanced_framing)
|
||||
intel_dp->DP |= DP_ENHANCED_FRAMING;
|
||||
|
||||
if (IS_CHERRYVIEW(dev_priv))
|
||||
|
|
@ -351,6 +351,9 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
|
|||
u32 trans_dp = intel_de_read(dev_priv,
|
||||
TRANS_DP_CTL(crtc->pipe));
|
||||
|
||||
if (trans_dp & TRANS_DP_ENH_FRAMING)
|
||||
pipe_config->enhanced_framing = true;
|
||||
|
||||
if (trans_dp & TRANS_DP_HSYNC_ACTIVE_HIGH)
|
||||
flags |= DRM_MODE_FLAG_PHSYNC;
|
||||
else
|
||||
|
|
@ -361,6 +364,9 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
|
|||
else
|
||||
flags |= DRM_MODE_FLAG_NVSYNC;
|
||||
} else {
|
||||
if (tmp & DP_ENHANCED_FRAMING)
|
||||
pipe_config->enhanced_framing = true;
|
||||
|
||||
if (tmp & DP_SYNC_HS_HIGH)
|
||||
flags |= DRM_MODE_FLAG_PHSYNC;
|
||||
else
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "intel_display_types.h"
|
||||
#include "intel_dp_aux.h"
|
||||
#include "intel_dpio_phy.h"
|
||||
#include "intel_fdi.h"
|
||||
#include "intel_fifo_underrun.h"
|
||||
#include "intel_hdmi.h"
|
||||
#include "intel_hotplug.h"
|
||||
|
|
@ -133,8 +134,11 @@ static int g4x_hdmi_compute_config(struct intel_encoder *encoder,
|
|||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
|
||||
if (HAS_PCH_SPLIT(i915))
|
||||
if (HAS_PCH_SPLIT(i915)) {
|
||||
crtc_state->has_pch_encoder = true;
|
||||
if (!intel_fdi_compute_pipe_bpp(crtc_state))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (IS_G4X(i915))
|
||||
crtc_state->has_hdmi_sink = g4x_compute_has_hdmi_sink(state, crtc);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "hsw_ips.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "intel_color_regs.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_pcode.h"
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "intel_display_types.h"
|
||||
#include "intel_fb.h"
|
||||
#include "intel_fbc.h"
|
||||
#include "intel_frontbuffer.h"
|
||||
#include "intel_sprite.h"
|
||||
|
||||
/* Primary plane formats for gen <= 3 */
|
||||
|
|
|
|||
|
|
@ -1822,7 +1822,7 @@ static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
|
|||
u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt;
|
||||
u32 ths_prepare_ns, tclk_trail_ns;
|
||||
u32 hs_zero_cnt;
|
||||
u32 tclk_pre_cnt, tclk_post_cnt;
|
||||
u32 tclk_pre_cnt;
|
||||
|
||||
tlpx_ns = intel_dsi_tlpx_ns(intel_dsi);
|
||||
|
||||
|
|
@ -1869,15 +1869,6 @@ static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
|
|||
tclk_pre_cnt = ICL_TCLK_PRE_CNT_MAX;
|
||||
}
|
||||
|
||||
/* tclk post count in escape clocks */
|
||||
tclk_post_cnt = DIV_ROUND_UP(mipi_config->tclk_post, tlpx_ns);
|
||||
if (tclk_post_cnt > ICL_TCLK_POST_CNT_MAX) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"tclk_post_cnt out of range (%d)\n",
|
||||
tclk_post_cnt);
|
||||
tclk_post_cnt = ICL_TCLK_POST_CNT_MAX;
|
||||
}
|
||||
|
||||
/* hs zero cnt in escape clocks */
|
||||
hs_zero_cnt = DIV_ROUND_UP(mipi_config->ths_prepare_hszero -
|
||||
ths_prepare_ns, tlpx_ns);
|
||||
|
|
@ -1903,8 +1894,6 @@ static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
|
|||
CLK_ZERO(clk_zero_cnt) |
|
||||
CLK_PRE_OVERRIDE |
|
||||
CLK_PRE(tclk_pre_cnt) |
|
||||
CLK_POST_OVERRIDE |
|
||||
CLK_POST(tclk_post_cnt) |
|
||||
CLK_TRAIL_OVERRIDE |
|
||||
CLK_TRAIL(trail_cnt));
|
||||
|
||||
|
|
|
|||
|
|
@ -259,6 +259,8 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
|
|||
drm_property_blob_get(crtc_state->post_csc_lut);
|
||||
|
||||
crtc_state->update_pipe = false;
|
||||
crtc_state->update_m_n = false;
|
||||
crtc_state->update_lrr = false;
|
||||
crtc_state->disable_lp_wm = false;
|
||||
crtc_state->disable_cxsr = false;
|
||||
crtc_state->update_wm_pre = false;
|
||||
|
|
|
|||
|
|
@ -214,9 +214,6 @@ intel_plane_relative_data_rate(const struct intel_crtc_state *crtc_state,
|
|||
int width, height;
|
||||
unsigned int rel_data_rate;
|
||||
|
||||
if (plane->id == PLANE_CURSOR)
|
||||
return 0;
|
||||
|
||||
if (!plane_state->uapi.visible)
|
||||
return 0;
|
||||
|
||||
|
|
@ -244,6 +241,9 @@ intel_plane_relative_data_rate(const struct intel_crtc_state *crtc_state,
|
|||
|
||||
rel_data_rate = width * height * fb->format->cpp[color_plane];
|
||||
|
||||
if (plane->id == PLANE_CURSOR)
|
||||
return rel_data_rate;
|
||||
|
||||
return intel_adjusted_rate(&plane_state->uapi.src,
|
||||
&plane_state->uapi.dst,
|
||||
rel_data_rate);
|
||||
|
|
@ -981,6 +981,14 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
|
|||
if (fb->format->format == DRM_FORMAT_RGB565 && rotated) {
|
||||
hsub = 2;
|
||||
vsub = 2;
|
||||
} else if (DISPLAY_VER(i915) >= 20 &&
|
||||
intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) {
|
||||
/*
|
||||
* This allows NV12 and P0xx formats to have odd size and/or odd
|
||||
* source coordinates on DISPLAY_VER(i915) >= 20
|
||||
*/
|
||||
hsub = 1;
|
||||
vsub = 1;
|
||||
} else {
|
||||
hsub = fb->format->hsub;
|
||||
vsub = fb->format->vsub;
|
||||
|
|
|
|||
|
|
@ -759,10 +759,10 @@ static void ibx_audio_codec_enable(struct intel_encoder *encoder,
|
|||
mutex_unlock(&i915->display.audio.mutex);
|
||||
}
|
||||
|
||||
void intel_audio_sdp_split_update(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
void intel_audio_sdp_split_update(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
enum transcoder trans = crtc_state->cpu_transcoder;
|
||||
|
||||
if (HAS_DP20(i915))
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ void intel_audio_cdclk_change_pre(struct drm_i915_private *dev_priv);
|
|||
void intel_audio_cdclk_change_post(struct drm_i915_private *dev_priv);
|
||||
void intel_audio_init(struct drm_i915_private *dev_priv);
|
||||
void intel_audio_deinit(struct drm_i915_private *dev_priv);
|
||||
void intel_audio_sdp_split_update(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void intel_audio_sdp_split_update(const struct intel_crtc_state *crtc_state);
|
||||
|
||||
#endif /* __INTEL_AUDIO_H__ */
|
||||
|
|
|
|||
|
|
@ -521,7 +521,8 @@ static void init_bdb_blocks(struct drm_i915_private *i915,
|
|||
}
|
||||
|
||||
static void
|
||||
fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
|
||||
fill_detail_timing_data(struct drm_i915_private *i915,
|
||||
struct drm_display_mode *panel_fixed_mode,
|
||||
const struct lvds_dvo_timing *dvo_timing)
|
||||
{
|
||||
panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
|
||||
|
|
@ -561,11 +562,17 @@ fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
|
|||
panel_fixed_mode->height_mm = (dvo_timing->vimage_hi << 8) |
|
||||
dvo_timing->vimage_lo;
|
||||
|
||||
/* Some VBTs have bogus h/vtotal values */
|
||||
if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
|
||||
panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
|
||||
if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
|
||||
panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;
|
||||
/* Some VBTs have bogus h/vsync_end values */
|
||||
if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) {
|
||||
drm_dbg_kms(&i915->drm, "reducing hsync_end %d->%d\n",
|
||||
panel_fixed_mode->hsync_end, panel_fixed_mode->htotal);
|
||||
panel_fixed_mode->hsync_end = panel_fixed_mode->htotal;
|
||||
}
|
||||
if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) {
|
||||
drm_dbg_kms(&i915->drm, "reducing vsync_end %d->%d\n",
|
||||
panel_fixed_mode->vsync_end, panel_fixed_mode->vtotal);
|
||||
panel_fixed_mode->vsync_end = panel_fixed_mode->vtotal;
|
||||
}
|
||||
|
||||
drm_mode_set_name(panel_fixed_mode);
|
||||
}
|
||||
|
|
@ -849,7 +856,7 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
|
|||
if (!panel_fixed_mode)
|
||||
return;
|
||||
|
||||
fill_detail_timing_data(panel_fixed_mode, panel_dvo_timing);
|
||||
fill_detail_timing_data(i915, panel_fixed_mode, panel_dvo_timing);
|
||||
|
||||
panel->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
|
||||
|
||||
|
|
@ -1134,7 +1141,7 @@ parse_sdvo_panel_data(struct drm_i915_private *i915,
|
|||
if (!panel_fixed_mode)
|
||||
return;
|
||||
|
||||
fill_detail_timing_data(panel_fixed_mode, &dtds->dtds[index]);
|
||||
fill_detail_timing_data(i915, panel_fixed_mode, &dtds->dtds[index]);
|
||||
|
||||
panel->vbt.sdvo_lvds_vbt_mode = panel_fixed_mode;
|
||||
|
||||
|
|
@ -2194,7 +2201,8 @@ static u8 map_ddc_pin(struct drm_i915_private *i915, u8 vbt_pin)
|
|||
const u8 *ddc_pin_map;
|
||||
int i, n_entries;
|
||||
|
||||
if (HAS_PCH_MTP(i915) || IS_ALDERLAKE_P(i915)) {
|
||||
if (INTEL_PCH_TYPE(i915) >= PCH_LNL || HAS_PCH_MTP(i915) ||
|
||||
IS_ALDERLAKE_P(i915)) {
|
||||
ddc_pin_map = adlp_ddc_pin_map;
|
||||
n_entries = ARRAY_SIZE(adlp_ddc_pin_map);
|
||||
} else if (IS_ALDERLAKE_S(i915)) {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "intel_cdclk.h"
|
||||
#include "intel_crtc.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_dp.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_mchbar_regs.h"
|
||||
#include "intel_pci_config.h"
|
||||
|
|
@ -1381,6 +1382,31 @@ static const struct intel_cdclk_vals mtl_cdclk_table[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
static const struct intel_cdclk_vals lnl_cdclk_table[] = {
|
||||
{ .refclk = 38400, .cdclk = 153600, .divider = 2, .ratio = 16, .waveform = 0xaaaa },
|
||||
{ .refclk = 38400, .cdclk = 172800, .divider = 2, .ratio = 16, .waveform = 0xad5a },
|
||||
{ .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 16, .waveform = 0xb6b6 },
|
||||
{ .refclk = 38400, .cdclk = 211200, .divider = 2, .ratio = 16, .waveform = 0xdbb6 },
|
||||
{ .refclk = 38400, .cdclk = 230400, .divider = 2, .ratio = 16, .waveform = 0xeeee },
|
||||
{ .refclk = 38400, .cdclk = 249600, .divider = 2, .ratio = 16, .waveform = 0xf7de },
|
||||
{ .refclk = 38400, .cdclk = 268800, .divider = 2, .ratio = 16, .waveform = 0xfefe },
|
||||
{ .refclk = 38400, .cdclk = 288000, .divider = 2, .ratio = 16, .waveform = 0xfffe },
|
||||
{ .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16, .waveform = 0xffff },
|
||||
{ .refclk = 38400, .cdclk = 330000, .divider = 2, .ratio = 25, .waveform = 0xdbb6 },
|
||||
{ .refclk = 38400, .cdclk = 360000, .divider = 2, .ratio = 25, .waveform = 0xeeee },
|
||||
{ .refclk = 38400, .cdclk = 390000, .divider = 2, .ratio = 25, .waveform = 0xf7de },
|
||||
{ .refclk = 38400, .cdclk = 420000, .divider = 2, .ratio = 25, .waveform = 0xfefe },
|
||||
{ .refclk = 38400, .cdclk = 450000, .divider = 2, .ratio = 25, .waveform = 0xfffe },
|
||||
{ .refclk = 38400, .cdclk = 480000, .divider = 2, .ratio = 25, .waveform = 0xffff },
|
||||
{ .refclk = 38400, .cdclk = 487200, .divider = 2, .ratio = 29, .waveform = 0xfefe },
|
||||
{ .refclk = 38400, .cdclk = 522000, .divider = 2, .ratio = 29, .waveform = 0xfffe },
|
||||
{ .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29, .waveform = 0xffff },
|
||||
{ .refclk = 38400, .cdclk = 571200, .divider = 2, .ratio = 34, .waveform = 0xfefe },
|
||||
{ .refclk = 38400, .cdclk = 612000, .divider = 2, .ratio = 34, .waveform = 0xfffe },
|
||||
{ .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34, .waveform = 0xffff },
|
||||
{}
|
||||
};
|
||||
|
||||
static int bxt_calc_cdclk(struct drm_i915_private *dev_priv, int min_cdclk)
|
||||
{
|
||||
const struct intel_cdclk_vals *table = dev_priv->display.cdclk.table;
|
||||
|
|
@ -1840,9 +1866,10 @@ static bool cdclk_compute_crawl_and_squash_midpoint(struct drm_i915_private *i91
|
|||
|
||||
static bool pll_enable_wa_needed(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
return ((IS_DG2(dev_priv) || IS_METEORLAKE(dev_priv)) &&
|
||||
dev_priv->display.cdclk.hw.vco > 0 &&
|
||||
HAS_CDCLK_SQUASH(dev_priv));
|
||||
return (DISPLAY_VER_FULL(dev_priv) == IP_VER(20, 0) ||
|
||||
DISPLAY_VER_FULL(dev_priv) == IP_VER(14, 0) ||
|
||||
IS_DG2(dev_priv)) &&
|
||||
dev_priv->display.cdclk.hw.vco > 0;
|
||||
}
|
||||
|
||||
static void _bxt_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
|
|
@ -1879,8 +1906,7 @@ static void _bxt_set_cdclk(struct drm_i915_private *dev_priv,
|
|||
dg2_cdclk_squash_program(dev_priv, waveform);
|
||||
|
||||
val = bxt_cdclk_cd2x_div_sel(dev_priv, clock, vco) |
|
||||
bxt_cdclk_cd2x_pipe(dev_priv, pipe) |
|
||||
skl_cdclk_decimal(cdclk);
|
||||
bxt_cdclk_cd2x_pipe(dev_priv, pipe);
|
||||
|
||||
/*
|
||||
* Disable SSA Precharge when CD clock frequency < 500 MHz,
|
||||
|
|
@ -1889,6 +1915,12 @@ static void _bxt_set_cdclk(struct drm_i915_private *dev_priv,
|
|||
if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
|
||||
cdclk >= 500000)
|
||||
val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 20)
|
||||
val |= MDCLK_SOURCE_SEL_CDCLK_PLL;
|
||||
else
|
||||
val |= skl_cdclk_decimal(cdclk);
|
||||
|
||||
intel_de_write(dev_priv, CDCLK_CTL, val);
|
||||
|
||||
if (pipe != INVALID_PIPE)
|
||||
|
|
@ -2533,6 +2565,48 @@ static int intel_planes_min_cdclk(const struct intel_crtc_state *crtc_state)
|
|||
return min_cdclk;
|
||||
}
|
||||
|
||||
static int intel_vdsc_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);
|
||||
int num_vdsc_instances = intel_dsc_get_num_vdsc_instances(crtc_state);
|
||||
int min_cdclk = 0;
|
||||
|
||||
/*
|
||||
* When we decide to use only one VDSC engine, since
|
||||
* each VDSC operates with 1 ppc throughput, pixel clock
|
||||
* cannot be higher than the VDSC clock (cdclk)
|
||||
* If there 2 VDSC engines, then pixel clock can't be higher than
|
||||
* VDSC clock(cdclk) * 2 and so on.
|
||||
*/
|
||||
min_cdclk = max_t(int, min_cdclk,
|
||||
DIV_ROUND_UP(crtc_state->pixel_rate, num_vdsc_instances));
|
||||
|
||||
if (crtc_state->bigjoiner_pipes) {
|
||||
int pixel_clock = intel_dp_mode_to_fec_clock(crtc_state->hw.adjusted_mode.clock);
|
||||
|
||||
/*
|
||||
* According to Bigjoiner bw check:
|
||||
* compressed_bpp <= PPC * CDCLK * Big joiner Interface bits / Pixel clock
|
||||
*
|
||||
* We have already computed compressed_bpp, so now compute the min CDCLK that
|
||||
* is required to support this compressed_bpp.
|
||||
*
|
||||
* => CDCLK >= compressed_bpp * Pixel clock / (PPC * Bigjoiner Interface bits)
|
||||
*
|
||||
* Since PPC = 2 with bigjoiner
|
||||
* => CDCLK >= compressed_bpp * Pixel clock / 2 * Bigjoiner Interface bits
|
||||
*/
|
||||
int bigjoiner_interface_bits = DISPLAY_VER(i915) > 13 ? 36 : 24;
|
||||
int min_cdclk_bj = (crtc_state->dsc.compressed_bpp * pixel_clock) /
|
||||
(2 * bigjoiner_interface_bits);
|
||||
|
||||
min_cdclk = max(min_cdclk, min_cdclk_bj);
|
||||
}
|
||||
|
||||
return min_cdclk;
|
||||
}
|
||||
|
||||
int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv =
|
||||
|
|
@ -2604,20 +2678,8 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
|
|||
/* Account for additional needs from the planes */
|
||||
min_cdclk = max(intel_planes_min_cdclk(crtc_state), min_cdclk);
|
||||
|
||||
/*
|
||||
* When we decide to use only one VDSC engine, since
|
||||
* each VDSC operates with 1 ppc throughput, pixel clock
|
||||
* cannot be higher than the VDSC clock (cdclk)
|
||||
* If there 2 VDSC engines, then pixel clock can't be higher than
|
||||
* VDSC clock(cdclk) * 2 and so on.
|
||||
*/
|
||||
if (crtc_state->dsc.compression_enable) {
|
||||
int num_vdsc_instances = intel_dsc_get_num_vdsc_instances(crtc_state);
|
||||
|
||||
min_cdclk = max_t(int, min_cdclk,
|
||||
DIV_ROUND_UP(crtc_state->pixel_rate,
|
||||
num_vdsc_instances));
|
||||
}
|
||||
if (crtc_state->dsc.compression_enable)
|
||||
min_cdclk = max(min_cdclk, intel_vdsc_min_cdclk(crtc_state));
|
||||
|
||||
/*
|
||||
* HACK. Currently for TGL/DG2 platforms we calculate
|
||||
|
|
@ -3108,7 +3170,7 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
|
|||
} else if (intel_cdclk_needs_modeset(&old_cdclk_state->actual,
|
||||
&new_cdclk_state->actual)) {
|
||||
/* All pipes must be switched off while we change the cdclk. */
|
||||
ret = intel_modeset_all_pipes(state, "CDCLK change");
|
||||
ret = intel_modeset_all_pipes_late(state, "CDCLK change");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -3559,7 +3621,10 @@ static const struct intel_cdclk_funcs i830_cdclk_funcs = {
|
|||
*/
|
||||
void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
if (IS_METEORLAKE(dev_priv)) {
|
||||
if (DISPLAY_VER(dev_priv) >= 20) {
|
||||
dev_priv->display.funcs.cdclk = &mtl_cdclk_funcs;
|
||||
dev_priv->display.cdclk.table = lnl_cdclk_table;
|
||||
} else if (DISPLAY_VER(dev_priv) >= 14) {
|
||||
dev_priv->display.funcs.cdclk = &mtl_cdclk_funcs;
|
||||
dev_priv->display.cdclk.table = mtl_cdclk_table;
|
||||
} else if (IS_DG2(dev_priv)) {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "i915_reg.h"
|
||||
#include "intel_color.h"
|
||||
#include "intel_color_regs.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dsb.h"
|
||||
|
|
@ -75,6 +76,10 @@ struct intel_color_funcs {
|
|||
* software state. Used by eg. the hardware state checker.
|
||||
*/
|
||||
void (*read_csc)(struct intel_crtc_state *crtc_state);
|
||||
/*
|
||||
* Read config other than LUTs and CSCs, before them. Optional.
|
||||
*/
|
||||
void (*get_config)(struct intel_crtc_state *crtc_state);
|
||||
};
|
||||
|
||||
#define CTM_COEFF_SIGN (1ULL << 63)
|
||||
|
|
@ -1013,6 +1018,65 @@ static void hsw_color_commit_arm(const struct intel_crtc_state *crtc_state)
|
|||
crtc_state->csc_mode);
|
||||
}
|
||||
|
||||
static u32 hsw_read_gamma_mode(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
|
||||
return intel_de_read(i915, GAMMA_MODE(crtc->pipe));
|
||||
}
|
||||
|
||||
static u32 ilk_read_csc_mode(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
|
||||
return intel_de_read(i915, PIPE_CSC_MODE(crtc->pipe));
|
||||
}
|
||||
|
||||
static void i9xx_get_config(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct intel_plane *plane = to_intel_plane(crtc->base.primary);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
|
||||
u32 tmp;
|
||||
|
||||
tmp = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
|
||||
|
||||
if (tmp & DISP_PIPE_GAMMA_ENABLE)
|
||||
crtc_state->gamma_enable = true;
|
||||
|
||||
if (!HAS_GMCH(dev_priv) && tmp & DISP_PIPE_CSC_ENABLE)
|
||||
crtc_state->csc_enable = true;
|
||||
}
|
||||
|
||||
static void hsw_get_config(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
||||
crtc_state->gamma_mode = hsw_read_gamma_mode(crtc);
|
||||
crtc_state->csc_mode = ilk_read_csc_mode(crtc);
|
||||
|
||||
i9xx_get_config(crtc_state);
|
||||
}
|
||||
|
||||
static void skl_get_config(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);
|
||||
u32 tmp;
|
||||
|
||||
crtc_state->gamma_mode = hsw_read_gamma_mode(crtc);
|
||||
crtc_state->csc_mode = ilk_read_csc_mode(crtc);
|
||||
|
||||
tmp = intel_de_read(i915, SKL_BOTTOM_COLOR(crtc->pipe));
|
||||
|
||||
if (tmp & SKL_BOTTOM_COLOR_GAMMA_ENABLE)
|
||||
crtc_state->gamma_enable = true;
|
||||
|
||||
if (tmp & SKL_BOTTOM_COLOR_CSC_ENABLE)
|
||||
crtc_state->csc_enable = true;
|
||||
}
|
||||
|
||||
static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
|
@ -1265,9 +1329,20 @@ static void ilk_load_lut_8(const struct intel_crtc_state *crtc_state,
|
|||
|
||||
lut = blob->data;
|
||||
|
||||
/*
|
||||
* DSB fails to correctly load the legacy LUT
|
||||
* unless we either write each entry twice,
|
||||
* or use non-posted writes
|
||||
*/
|
||||
if (crtc_state->dsb)
|
||||
intel_dsb_nonpost_start(crtc_state->dsb);
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
ilk_lut_write(crtc_state, LGC_PALETTE(pipe, i),
|
||||
i9xx_lut_8(&lut[i]));
|
||||
|
||||
if (crtc_state->dsb)
|
||||
intel_dsb_nonpost_end(crtc_state->dsb);
|
||||
}
|
||||
|
||||
static void ilk_load_lut_10(const struct intel_crtc_state *crtc_state,
|
||||
|
|
@ -1677,12 +1752,6 @@ static void icl_load_luts(const struct intel_crtc_state *crtc_state)
|
|||
MISSING_CASE(crtc_state->gamma_mode);
|
||||
break;
|
||||
}
|
||||
|
||||
if (crtc_state->dsb) {
|
||||
intel_dsb_finish(crtc_state->dsb);
|
||||
intel_dsb_commit(crtc_state->dsb, false);
|
||||
intel_dsb_wait(crtc_state->dsb);
|
||||
}
|
||||
}
|
||||
|
||||
static void vlv_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
|
|
@ -1789,6 +1858,9 @@ void intel_color_load_luts(const struct intel_crtc_state *crtc_state)
|
|||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
|
||||
|
||||
if (crtc_state->dsb)
|
||||
return;
|
||||
|
||||
i915->display.funcs.color->load_luts(crtc_state);
|
||||
}
|
||||
|
||||
|
|
@ -1805,6 +1877,9 @@ void intel_color_commit_arm(const struct intel_crtc_state *crtc_state)
|
|||
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
|
||||
|
||||
i915->display.funcs.color->color_commit_arm(crtc_state);
|
||||
|
||||
if (crtc_state->dsb)
|
||||
intel_dsb_commit(crtc_state->dsb, true);
|
||||
}
|
||||
|
||||
void intel_color_post_update(const struct intel_crtc_state *crtc_state)
|
||||
|
|
@ -1818,14 +1893,25 @@ void intel_color_post_update(const struct intel_crtc_state *crtc_state)
|
|||
void intel_color_prepare_commit(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);
|
||||
|
||||
/* FIXME DSB has issues loading LUTs, disable it for now */
|
||||
return;
|
||||
|
||||
if (!crtc_state->hw.active ||
|
||||
intel_crtc_needs_modeset(crtc_state))
|
||||
return;
|
||||
|
||||
if (!crtc_state->pre_csc_lut && !crtc_state->post_csc_lut)
|
||||
return;
|
||||
|
||||
crtc_state->dsb = intel_dsb_prepare(crtc, 1024);
|
||||
crtc_state->dsb = intel_dsb_prepare(crtc_state, 1024);
|
||||
if (!crtc_state->dsb)
|
||||
return;
|
||||
|
||||
i915->display.funcs.color->load_luts(crtc_state);
|
||||
|
||||
intel_dsb_finish(crtc_state->dsb);
|
||||
}
|
||||
|
||||
void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state)
|
||||
|
|
@ -1837,6 +1923,17 @@ void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state)
|
|||
crtc_state->dsb = NULL;
|
||||
}
|
||||
|
||||
void intel_color_wait_commit(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
if (crtc_state->dsb)
|
||||
intel_dsb_wait(crtc_state->dsb);
|
||||
}
|
||||
|
||||
bool intel_color_uses_dsb(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
return crtc_state->dsb;
|
||||
}
|
||||
|
||||
static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
|
||||
|
|
@ -1891,6 +1988,9 @@ void intel_color_get_config(struct intel_crtc_state *crtc_state)
|
|||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
|
||||
|
||||
if (i915->display.funcs.color->get_config)
|
||||
i915->display.funcs.color->get_config(crtc_state);
|
||||
|
||||
i915->display.funcs.color->read_luts(crtc_state);
|
||||
|
||||
if (i915->display.funcs.color->read_csc)
|
||||
|
|
@ -2865,16 +2965,16 @@ static int icl_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state)
|
|||
return 16;
|
||||
}
|
||||
|
||||
static bool err_check(struct drm_color_lut *lut1,
|
||||
struct drm_color_lut *lut2, u32 err)
|
||||
static bool err_check(const struct drm_color_lut *lut1,
|
||||
const struct drm_color_lut *lut2, u32 err)
|
||||
{
|
||||
return ((abs((long)lut2->red - lut1->red)) <= err) &&
|
||||
((abs((long)lut2->blue - lut1->blue)) <= err) &&
|
||||
((abs((long)lut2->green - lut1->green)) <= err);
|
||||
}
|
||||
|
||||
static bool intel_lut_entries_equal(struct drm_color_lut *lut1,
|
||||
struct drm_color_lut *lut2,
|
||||
static bool intel_lut_entries_equal(const struct drm_color_lut *lut1,
|
||||
const struct drm_color_lut *lut2,
|
||||
int lut_size, u32 err)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -2891,7 +2991,7 @@ static bool intel_lut_equal(const struct drm_property_blob *blob1,
|
|||
const struct drm_property_blob *blob2,
|
||||
int check_size, int precision)
|
||||
{
|
||||
struct drm_color_lut *lut1, *lut2;
|
||||
const struct drm_color_lut *lut1, *lut2;
|
||||
int lut_size1, lut_size2;
|
||||
u32 err;
|
||||
|
||||
|
|
@ -3204,6 +3304,16 @@ static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc)
|
|||
return blob;
|
||||
}
|
||||
|
||||
static void chv_get_config(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);
|
||||
|
||||
crtc_state->cgm_mode = intel_de_read(i915, CGM_PIPE_MODE(crtc->pipe));
|
||||
|
||||
i9xx_get_config(crtc_state);
|
||||
}
|
||||
|
||||
static void chv_read_luts(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
|
@ -3267,6 +3377,15 @@ static struct drm_property_blob *ilk_read_lut_10(struct intel_crtc *crtc)
|
|||
return blob;
|
||||
}
|
||||
|
||||
static void ilk_get_config(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
||||
crtc_state->csc_mode = ilk_read_csc_mode(crtc);
|
||||
|
||||
i9xx_get_config(crtc_state);
|
||||
}
|
||||
|
||||
static void ilk_read_luts(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
|
@ -3573,6 +3692,7 @@ static const struct intel_color_funcs chv_color_funcs = {
|
|||
.read_luts = chv_read_luts,
|
||||
.lut_equal = chv_lut_equal,
|
||||
.read_csc = chv_read_csc,
|
||||
.get_config = chv_get_config,
|
||||
};
|
||||
|
||||
static const struct intel_color_funcs vlv_color_funcs = {
|
||||
|
|
@ -3590,6 +3710,7 @@ static const struct intel_color_funcs i965_color_funcs = {
|
|||
.load_luts = i965_load_luts,
|
||||
.read_luts = i965_read_luts,
|
||||
.lut_equal = i965_lut_equal,
|
||||
.get_config = i9xx_get_config,
|
||||
};
|
||||
|
||||
static const struct intel_color_funcs i9xx_color_funcs = {
|
||||
|
|
@ -3598,6 +3719,7 @@ static const struct intel_color_funcs i9xx_color_funcs = {
|
|||
.load_luts = i9xx_load_luts,
|
||||
.read_luts = i9xx_read_luts,
|
||||
.lut_equal = i9xx_lut_equal,
|
||||
.get_config = i9xx_get_config,
|
||||
};
|
||||
|
||||
static const struct intel_color_funcs tgl_color_funcs = {
|
||||
|
|
@ -3608,6 +3730,7 @@ static const struct intel_color_funcs tgl_color_funcs = {
|
|||
.read_luts = icl_read_luts,
|
||||
.lut_equal = icl_lut_equal,
|
||||
.read_csc = icl_read_csc,
|
||||
.get_config = skl_get_config,
|
||||
};
|
||||
|
||||
static const struct intel_color_funcs icl_color_funcs = {
|
||||
|
|
@ -3619,6 +3742,7 @@ static const struct intel_color_funcs icl_color_funcs = {
|
|||
.read_luts = icl_read_luts,
|
||||
.lut_equal = icl_lut_equal,
|
||||
.read_csc = icl_read_csc,
|
||||
.get_config = skl_get_config,
|
||||
};
|
||||
|
||||
static const struct intel_color_funcs glk_color_funcs = {
|
||||
|
|
@ -3629,6 +3753,7 @@ static const struct intel_color_funcs glk_color_funcs = {
|
|||
.read_luts = glk_read_luts,
|
||||
.lut_equal = glk_lut_equal,
|
||||
.read_csc = skl_read_csc,
|
||||
.get_config = skl_get_config,
|
||||
};
|
||||
|
||||
static const struct intel_color_funcs skl_color_funcs = {
|
||||
|
|
@ -3639,6 +3764,7 @@ static const struct intel_color_funcs skl_color_funcs = {
|
|||
.read_luts = bdw_read_luts,
|
||||
.lut_equal = ivb_lut_equal,
|
||||
.read_csc = skl_read_csc,
|
||||
.get_config = skl_get_config,
|
||||
};
|
||||
|
||||
static const struct intel_color_funcs bdw_color_funcs = {
|
||||
|
|
@ -3649,6 +3775,7 @@ static const struct intel_color_funcs bdw_color_funcs = {
|
|||
.read_luts = bdw_read_luts,
|
||||
.lut_equal = ivb_lut_equal,
|
||||
.read_csc = ilk_read_csc,
|
||||
.get_config = hsw_get_config,
|
||||
};
|
||||
|
||||
static const struct intel_color_funcs hsw_color_funcs = {
|
||||
|
|
@ -3659,6 +3786,7 @@ static const struct intel_color_funcs hsw_color_funcs = {
|
|||
.read_luts = ivb_read_luts,
|
||||
.lut_equal = ivb_lut_equal,
|
||||
.read_csc = ilk_read_csc,
|
||||
.get_config = hsw_get_config,
|
||||
};
|
||||
|
||||
static const struct intel_color_funcs ivb_color_funcs = {
|
||||
|
|
@ -3669,6 +3797,7 @@ static const struct intel_color_funcs ivb_color_funcs = {
|
|||
.read_luts = ivb_read_luts,
|
||||
.lut_equal = ivb_lut_equal,
|
||||
.read_csc = ilk_read_csc,
|
||||
.get_config = ilk_get_config,
|
||||
};
|
||||
|
||||
static const struct intel_color_funcs ilk_color_funcs = {
|
||||
|
|
@ -3679,6 +3808,7 @@ static const struct intel_color_funcs ilk_color_funcs = {
|
|||
.read_luts = ilk_read_luts,
|
||||
.lut_equal = ilk_lut_equal,
|
||||
.read_csc = ilk_read_csc,
|
||||
.get_config = ilk_get_config,
|
||||
};
|
||||
|
||||
void intel_color_crtc_init(struct intel_crtc *crtc)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ void intel_color_crtc_init(struct intel_crtc *crtc);
|
|||
int intel_color_check(struct intel_crtc_state *crtc_state);
|
||||
void intel_color_prepare_commit(struct intel_crtc_state *crtc_state);
|
||||
void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state);
|
||||
bool intel_color_uses_dsb(const struct intel_crtc_state *crtc_state);
|
||||
void intel_color_wait_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_post_update(const struct intel_crtc_state *crtc_state);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,286 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2023 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_COLOR_REGS_H__
|
||||
#define __INTEL_COLOR_REGS_H__
|
||||
|
||||
#include "intel_display_reg_defs.h"
|
||||
|
||||
/* legacy palette */
|
||||
#define _LGC_PALETTE_A 0x4a000
|
||||
#define _LGC_PALETTE_B 0x4a800
|
||||
/* see PALETTE_* for the bits */
|
||||
#define LGC_PALETTE(pipe, i) _MMIO(_PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B) + (i) * 4)
|
||||
|
||||
/* ilk/snb precision palette */
|
||||
#define _PREC_PALETTE_A 0x4b000
|
||||
#define _PREC_PALETTE_B 0x4c000
|
||||
/* 10bit mode */
|
||||
#define PREC_PALETTE_10_RED_MASK REG_GENMASK(29, 20)
|
||||
#define PREC_PALETTE_10_GREEN_MASK REG_GENMASK(19, 10)
|
||||
#define PREC_PALETTE_10_BLUE_MASK REG_GENMASK(9, 0)
|
||||
/* 12.4 interpolated mode ldw */
|
||||
#define PREC_PALETTE_12P4_RED_LDW_MASK REG_GENMASK(29, 24)
|
||||
#define PREC_PALETTE_12P4_GREEN_LDW_MASK REG_GENMASK(19, 14)
|
||||
#define PREC_PALETTE_12P4_BLUE_LDW_MASK REG_GENMASK(9, 4)
|
||||
/* 12.4 interpolated mode udw */
|
||||
#define PREC_PALETTE_12P4_RED_UDW_MASK REG_GENMASK(29, 20)
|
||||
#define PREC_PALETTE_12P4_GREEN_UDW_MASK REG_GENMASK(19, 10)
|
||||
#define PREC_PALETTE_12P4_BLUE_UDW_MASK REG_GENMASK(9, 0)
|
||||
#define PREC_PALETTE(pipe, i) _MMIO(_PIPE(pipe, _PREC_PALETTE_A, _PREC_PALETTE_B) + (i) * 4)
|
||||
|
||||
#define _PREC_PIPEAGCMAX 0x4d000
|
||||
#define _PREC_PIPEBGCMAX 0x4d010
|
||||
#define PREC_PIPEGCMAX(pipe, i) _MMIO(_PIPE(pipe, _PIPEAGCMAX, _PIPEBGCMAX) + (i) * 4) /* u1.16 */
|
||||
|
||||
#define _GAMMA_MODE_A 0x4a480
|
||||
#define _GAMMA_MODE_B 0x4ac80
|
||||
#define GAMMA_MODE(pipe) _MMIO_PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B)
|
||||
#define PRE_CSC_GAMMA_ENABLE REG_BIT(31) /* icl+ */
|
||||
#define POST_CSC_GAMMA_ENABLE REG_BIT(30) /* icl+ */
|
||||
#define PALETTE_ANTICOL_DISABLE REG_BIT(15) /* skl+ */
|
||||
#define GAMMA_MODE_MODE_MASK REG_GENMASK(1, 0)
|
||||
#define GAMMA_MODE_MODE_8BIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 0)
|
||||
#define GAMMA_MODE_MODE_10BIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 1)
|
||||
#define GAMMA_MODE_MODE_12BIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 2)
|
||||
#define GAMMA_MODE_MODE_SPLIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 3) /* ivb-bdw */
|
||||
#define GAMMA_MODE_MODE_12BIT_MULTI_SEG REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 3) /* icl-tgl */
|
||||
|
||||
/* pipe CSC */
|
||||
#define _PIPE_A_CSC_COEFF_RY_GY 0x49010
|
||||
#define _PIPE_A_CSC_COEFF_BY 0x49014
|
||||
#define _PIPE_A_CSC_COEFF_RU_GU 0x49018
|
||||
#define _PIPE_A_CSC_COEFF_BU 0x4901c
|
||||
#define _PIPE_A_CSC_COEFF_RV_GV 0x49020
|
||||
#define _PIPE_A_CSC_COEFF_BV 0x49024
|
||||
|
||||
#define _PIPE_A_CSC_MODE 0x49028
|
||||
#define ICL_CSC_ENABLE (1 << 31) /* icl+ */
|
||||
#define ICL_OUTPUT_CSC_ENABLE (1 << 30) /* icl+ */
|
||||
#define CSC_BLACK_SCREEN_OFFSET (1 << 2) /* ilk/snb */
|
||||
#define CSC_POSITION_BEFORE_GAMMA (1 << 1) /* pre-glk */
|
||||
#define CSC_MODE_YUV_TO_RGB (1 << 0) /* ilk/snb */
|
||||
|
||||
#define _PIPE_A_CSC_PREOFF_HI 0x49030
|
||||
#define _PIPE_A_CSC_PREOFF_ME 0x49034
|
||||
#define _PIPE_A_CSC_PREOFF_LO 0x49038
|
||||
#define _PIPE_A_CSC_POSTOFF_HI 0x49040
|
||||
#define _PIPE_A_CSC_POSTOFF_ME 0x49044
|
||||
#define _PIPE_A_CSC_POSTOFF_LO 0x49048
|
||||
|
||||
#define _PIPE_B_CSC_COEFF_RY_GY 0x49110
|
||||
#define _PIPE_B_CSC_COEFF_BY 0x49114
|
||||
#define _PIPE_B_CSC_COEFF_RU_GU 0x49118
|
||||
#define _PIPE_B_CSC_COEFF_BU 0x4911c
|
||||
#define _PIPE_B_CSC_COEFF_RV_GV 0x49120
|
||||
#define _PIPE_B_CSC_COEFF_BV 0x49124
|
||||
#define _PIPE_B_CSC_MODE 0x49128
|
||||
#define _PIPE_B_CSC_PREOFF_HI 0x49130
|
||||
#define _PIPE_B_CSC_PREOFF_ME 0x49134
|
||||
#define _PIPE_B_CSC_PREOFF_LO 0x49138
|
||||
#define _PIPE_B_CSC_POSTOFF_HI 0x49140
|
||||
#define _PIPE_B_CSC_POSTOFF_ME 0x49144
|
||||
#define _PIPE_B_CSC_POSTOFF_LO 0x49148
|
||||
|
||||
#define PIPE_CSC_COEFF_RY_GY(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_RY_GY, _PIPE_B_CSC_COEFF_RY_GY)
|
||||
#define PIPE_CSC_COEFF_BY(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_BY, _PIPE_B_CSC_COEFF_BY)
|
||||
#define PIPE_CSC_COEFF_RU_GU(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_RU_GU, _PIPE_B_CSC_COEFF_RU_GU)
|
||||
#define PIPE_CSC_COEFF_BU(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_BU, _PIPE_B_CSC_COEFF_BU)
|
||||
#define PIPE_CSC_COEFF_RV_GV(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_RV_GV, _PIPE_B_CSC_COEFF_RV_GV)
|
||||
#define PIPE_CSC_COEFF_BV(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_BV, _PIPE_B_CSC_COEFF_BV)
|
||||
#define PIPE_CSC_MODE(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_MODE, _PIPE_B_CSC_MODE)
|
||||
#define PIPE_CSC_PREOFF_HI(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_PREOFF_HI, _PIPE_B_CSC_PREOFF_HI)
|
||||
#define PIPE_CSC_PREOFF_ME(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_PREOFF_ME, _PIPE_B_CSC_PREOFF_ME)
|
||||
#define PIPE_CSC_PREOFF_LO(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_PREOFF_LO, _PIPE_B_CSC_PREOFF_LO)
|
||||
#define PIPE_CSC_POSTOFF_HI(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_HI, _PIPE_B_CSC_POSTOFF_HI)
|
||||
#define PIPE_CSC_POSTOFF_ME(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_ME, _PIPE_B_CSC_POSTOFF_ME)
|
||||
#define PIPE_CSC_POSTOFF_LO(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_LO, _PIPE_B_CSC_POSTOFF_LO)
|
||||
|
||||
/* Pipe Output CSC */
|
||||
#define _PIPE_A_OUTPUT_CSC_COEFF_RY_GY 0x49050
|
||||
#define _PIPE_A_OUTPUT_CSC_COEFF_BY 0x49054
|
||||
#define _PIPE_A_OUTPUT_CSC_COEFF_RU_GU 0x49058
|
||||
#define _PIPE_A_OUTPUT_CSC_COEFF_BU 0x4905c
|
||||
#define _PIPE_A_OUTPUT_CSC_COEFF_RV_GV 0x49060
|
||||
#define _PIPE_A_OUTPUT_CSC_COEFF_BV 0x49064
|
||||
#define _PIPE_A_OUTPUT_CSC_PREOFF_HI 0x49068
|
||||
#define _PIPE_A_OUTPUT_CSC_PREOFF_ME 0x4906c
|
||||
#define _PIPE_A_OUTPUT_CSC_PREOFF_LO 0x49070
|
||||
#define _PIPE_A_OUTPUT_CSC_POSTOFF_HI 0x49074
|
||||
#define _PIPE_A_OUTPUT_CSC_POSTOFF_ME 0x49078
|
||||
#define _PIPE_A_OUTPUT_CSC_POSTOFF_LO 0x4907c
|
||||
|
||||
#define _PIPE_B_OUTPUT_CSC_COEFF_RY_GY 0x49150
|
||||
#define _PIPE_B_OUTPUT_CSC_COEFF_BY 0x49154
|
||||
#define _PIPE_B_OUTPUT_CSC_COEFF_RU_GU 0x49158
|
||||
#define _PIPE_B_OUTPUT_CSC_COEFF_BU 0x4915c
|
||||
#define _PIPE_B_OUTPUT_CSC_COEFF_RV_GV 0x49160
|
||||
#define _PIPE_B_OUTPUT_CSC_COEFF_BV 0x49164
|
||||
#define _PIPE_B_OUTPUT_CSC_PREOFF_HI 0x49168
|
||||
#define _PIPE_B_OUTPUT_CSC_PREOFF_ME 0x4916c
|
||||
#define _PIPE_B_OUTPUT_CSC_PREOFF_LO 0x49170
|
||||
#define _PIPE_B_OUTPUT_CSC_POSTOFF_HI 0x49174
|
||||
#define _PIPE_B_OUTPUT_CSC_POSTOFF_ME 0x49178
|
||||
#define _PIPE_B_OUTPUT_CSC_POSTOFF_LO 0x4917c
|
||||
|
||||
#define PIPE_CSC_OUTPUT_COEFF_RY_GY(pipe) _MMIO_PIPE(pipe,\
|
||||
_PIPE_A_OUTPUT_CSC_COEFF_RY_GY,\
|
||||
_PIPE_B_OUTPUT_CSC_COEFF_RY_GY)
|
||||
#define PIPE_CSC_OUTPUT_COEFF_BY(pipe) _MMIO_PIPE(pipe, \
|
||||
_PIPE_A_OUTPUT_CSC_COEFF_BY, \
|
||||
_PIPE_B_OUTPUT_CSC_COEFF_BY)
|
||||
#define PIPE_CSC_OUTPUT_COEFF_RU_GU(pipe) _MMIO_PIPE(pipe, \
|
||||
_PIPE_A_OUTPUT_CSC_COEFF_RU_GU, \
|
||||
_PIPE_B_OUTPUT_CSC_COEFF_RU_GU)
|
||||
#define PIPE_CSC_OUTPUT_COEFF_BU(pipe) _MMIO_PIPE(pipe, \
|
||||
_PIPE_A_OUTPUT_CSC_COEFF_BU, \
|
||||
_PIPE_B_OUTPUT_CSC_COEFF_BU)
|
||||
#define PIPE_CSC_OUTPUT_COEFF_RV_GV(pipe) _MMIO_PIPE(pipe, \
|
||||
_PIPE_A_OUTPUT_CSC_COEFF_RV_GV, \
|
||||
_PIPE_B_OUTPUT_CSC_COEFF_RV_GV)
|
||||
#define PIPE_CSC_OUTPUT_COEFF_BV(pipe) _MMIO_PIPE(pipe, \
|
||||
_PIPE_A_OUTPUT_CSC_COEFF_BV, \
|
||||
_PIPE_B_OUTPUT_CSC_COEFF_BV)
|
||||
#define PIPE_CSC_OUTPUT_PREOFF_HI(pipe) _MMIO_PIPE(pipe, \
|
||||
_PIPE_A_OUTPUT_CSC_PREOFF_HI, \
|
||||
_PIPE_B_OUTPUT_CSC_PREOFF_HI)
|
||||
#define PIPE_CSC_OUTPUT_PREOFF_ME(pipe) _MMIO_PIPE(pipe, \
|
||||
_PIPE_A_OUTPUT_CSC_PREOFF_ME, \
|
||||
_PIPE_B_OUTPUT_CSC_PREOFF_ME)
|
||||
#define PIPE_CSC_OUTPUT_PREOFF_LO(pipe) _MMIO_PIPE(pipe, \
|
||||
_PIPE_A_OUTPUT_CSC_PREOFF_LO, \
|
||||
_PIPE_B_OUTPUT_CSC_PREOFF_LO)
|
||||
#define PIPE_CSC_OUTPUT_POSTOFF_HI(pipe) _MMIO_PIPE(pipe, \
|
||||
_PIPE_A_OUTPUT_CSC_POSTOFF_HI, \
|
||||
_PIPE_B_OUTPUT_CSC_POSTOFF_HI)
|
||||
#define PIPE_CSC_OUTPUT_POSTOFF_ME(pipe) _MMIO_PIPE(pipe, \
|
||||
_PIPE_A_OUTPUT_CSC_POSTOFF_ME, \
|
||||
_PIPE_B_OUTPUT_CSC_POSTOFF_ME)
|
||||
#define PIPE_CSC_OUTPUT_POSTOFF_LO(pipe) _MMIO_PIPE(pipe, \
|
||||
_PIPE_A_OUTPUT_CSC_POSTOFF_LO, \
|
||||
_PIPE_B_OUTPUT_CSC_POSTOFF_LO)
|
||||
|
||||
/* pipe degamma/gamma LUTs on IVB+ */
|
||||
#define _PAL_PREC_INDEX_A 0x4A400
|
||||
#define _PAL_PREC_INDEX_B 0x4AC00
|
||||
#define _PAL_PREC_INDEX_C 0x4B400
|
||||
#define PAL_PREC_SPLIT_MODE REG_BIT(31)
|
||||
#define PAL_PREC_AUTO_INCREMENT REG_BIT(15)
|
||||
#define PAL_PREC_INDEX_VALUE_MASK REG_GENMASK(9, 0)
|
||||
#define PAL_PREC_INDEX_VALUE(x) REG_FIELD_PREP(PAL_PREC_INDEX_VALUE_MASK, (x))
|
||||
#define _PAL_PREC_DATA_A 0x4A404
|
||||
#define _PAL_PREC_DATA_B 0x4AC04
|
||||
#define _PAL_PREC_DATA_C 0x4B404
|
||||
/* see PREC_PALETTE_* for the bits */
|
||||
#define _PAL_PREC_GC_MAX_A 0x4A410
|
||||
#define _PAL_PREC_GC_MAX_B 0x4AC10
|
||||
#define _PAL_PREC_GC_MAX_C 0x4B410
|
||||
#define _PAL_PREC_EXT_GC_MAX_A 0x4A420
|
||||
#define _PAL_PREC_EXT_GC_MAX_B 0x4AC20
|
||||
#define _PAL_PREC_EXT_GC_MAX_C 0x4B420
|
||||
#define _PAL_PREC_EXT2_GC_MAX_A 0x4A430
|
||||
#define _PAL_PREC_EXT2_GC_MAX_B 0x4AC30
|
||||
#define _PAL_PREC_EXT2_GC_MAX_C 0x4B430
|
||||
|
||||
#define PREC_PAL_INDEX(pipe) _MMIO_PIPE(pipe, _PAL_PREC_INDEX_A, _PAL_PREC_INDEX_B)
|
||||
#define PREC_PAL_DATA(pipe) _MMIO_PIPE(pipe, _PAL_PREC_DATA_A, _PAL_PREC_DATA_B)
|
||||
#define PREC_PAL_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_GC_MAX_A, _PAL_PREC_GC_MAX_B) + (i) * 4) /* u1.16 */
|
||||
#define PREC_PAL_EXT_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT_GC_MAX_A, _PAL_PREC_EXT_GC_MAX_B) + (i) * 4) /* u3.16 */
|
||||
#define PREC_PAL_EXT2_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT2_GC_MAX_A, _PAL_PREC_EXT2_GC_MAX_B) + (i) * 4) /* glk+, u3.16 */
|
||||
|
||||
#define _PRE_CSC_GAMC_INDEX_A 0x4A484
|
||||
#define _PRE_CSC_GAMC_INDEX_B 0x4AC84
|
||||
#define _PRE_CSC_GAMC_INDEX_C 0x4B484
|
||||
#define PRE_CSC_GAMC_AUTO_INCREMENT REG_BIT(10)
|
||||
#define PRE_CSC_GAMC_INDEX_VALUE_MASK REG_GENMASK(7, 0)
|
||||
#define PRE_CSC_GAMC_INDEX_VALUE(x) REG_FIELD_PREP(PRE_CSC_GAMC_INDEX_VALUE_MASK, (x))
|
||||
#define _PRE_CSC_GAMC_DATA_A 0x4A488
|
||||
#define _PRE_CSC_GAMC_DATA_B 0x4AC88
|
||||
#define _PRE_CSC_GAMC_DATA_C 0x4B488
|
||||
|
||||
#define PRE_CSC_GAMC_INDEX(pipe) _MMIO_PIPE(pipe, _PRE_CSC_GAMC_INDEX_A, _PRE_CSC_GAMC_INDEX_B)
|
||||
#define PRE_CSC_GAMC_DATA(pipe) _MMIO_PIPE(pipe, _PRE_CSC_GAMC_DATA_A, _PRE_CSC_GAMC_DATA_B)
|
||||
|
||||
/* ICL Multi segmented gamma */
|
||||
#define _PAL_PREC_MULTI_SEG_INDEX_A 0x4A408
|
||||
#define _PAL_PREC_MULTI_SEG_INDEX_B 0x4AC08
|
||||
#define PAL_PREC_MULTI_SEG_AUTO_INCREMENT REG_BIT(15)
|
||||
#define PAL_PREC_MULTI_SEG_INDEX_VALUE_MASK REG_GENMASK(4, 0)
|
||||
#define PAL_PREC_MULTI_SEG_INDEX_VALUE(x) REG_FIELD_PREP(PAL_PREC_MULTI_SEG_INDEX_VALUE_MASK, (x))
|
||||
|
||||
#define _PAL_PREC_MULTI_SEG_DATA_A 0x4A40C
|
||||
#define _PAL_PREC_MULTI_SEG_DATA_B 0x4AC0C
|
||||
/* see PREC_PALETTE_12P4_* for the bits */
|
||||
|
||||
#define PREC_PAL_MULTI_SEG_INDEX(pipe) _MMIO_PIPE(pipe, \
|
||||
_PAL_PREC_MULTI_SEG_INDEX_A, \
|
||||
_PAL_PREC_MULTI_SEG_INDEX_B)
|
||||
#define PREC_PAL_MULTI_SEG_DATA(pipe) _MMIO_PIPE(pipe, \
|
||||
_PAL_PREC_MULTI_SEG_DATA_A, \
|
||||
_PAL_PREC_MULTI_SEG_DATA_B)
|
||||
|
||||
#define _PIPE_A_WGC_C01_C00 0x600B0 /* s2.10 */
|
||||
#define _PIPE_A_WGC_C02 0x600B4 /* s2.10 */
|
||||
#define _PIPE_A_WGC_C11_C10 0x600B8 /* s2.10 */
|
||||
#define _PIPE_A_WGC_C12 0x600BC /* s2.10 */
|
||||
#define _PIPE_A_WGC_C21_C20 0x600C0 /* s2.10 */
|
||||
#define _PIPE_A_WGC_C22 0x600C4 /* s2.10 */
|
||||
|
||||
#define PIPE_WGC_C01_C00(pipe) _MMIO_TRANS2(pipe, _PIPE_A_WGC_C01_C00)
|
||||
#define PIPE_WGC_C02(pipe) _MMIO_TRANS2(pipe, _PIPE_A_WGC_C02)
|
||||
#define PIPE_WGC_C11_C10(pipe) _MMIO_TRANS2(pipe, _PIPE_A_WGC_C11_C10)
|
||||
#define PIPE_WGC_C12(pipe) _MMIO_TRANS2(pipe, _PIPE_A_WGC_C12)
|
||||
#define PIPE_WGC_C21_C20(pipe) _MMIO_TRANS2(pipe, _PIPE_A_WGC_C21_C20)
|
||||
#define PIPE_WGC_C22(pipe) _MMIO_TRANS2(pipe, _PIPE_A_WGC_C22)
|
||||
|
||||
/* pipe CSC & degamma/gamma LUTs on CHV */
|
||||
#define _CGM_PIPE_A_CSC_COEFF01 (VLV_DISPLAY_BASE + 0x67900)
|
||||
#define _CGM_PIPE_A_CSC_COEFF23 (VLV_DISPLAY_BASE + 0x67904)
|
||||
#define _CGM_PIPE_A_CSC_COEFF45 (VLV_DISPLAY_BASE + 0x67908)
|
||||
#define _CGM_PIPE_A_CSC_COEFF67 (VLV_DISPLAY_BASE + 0x6790C)
|
||||
#define _CGM_PIPE_A_CSC_COEFF8 (VLV_DISPLAY_BASE + 0x67910)
|
||||
#define _CGM_PIPE_A_DEGAMMA (VLV_DISPLAY_BASE + 0x66000)
|
||||
/* cgm degamma ldw */
|
||||
#define CGM_PIPE_DEGAMMA_GREEN_LDW_MASK REG_GENMASK(29, 16)
|
||||
#define CGM_PIPE_DEGAMMA_BLUE_LDW_MASK REG_GENMASK(13, 0)
|
||||
/* cgm degamma udw */
|
||||
#define CGM_PIPE_DEGAMMA_RED_UDW_MASK REG_GENMASK(13, 0)
|
||||
#define _CGM_PIPE_A_GAMMA (VLV_DISPLAY_BASE + 0x67000)
|
||||
/* cgm gamma ldw */
|
||||
#define CGM_PIPE_GAMMA_GREEN_LDW_MASK REG_GENMASK(25, 16)
|
||||
#define CGM_PIPE_GAMMA_BLUE_LDW_MASK REG_GENMASK(9, 0)
|
||||
/* cgm gamma udw */
|
||||
#define CGM_PIPE_GAMMA_RED_UDW_MASK REG_GENMASK(9, 0)
|
||||
#define _CGM_PIPE_A_MODE (VLV_DISPLAY_BASE + 0x67A00)
|
||||
#define CGM_PIPE_MODE_GAMMA (1 << 2)
|
||||
#define CGM_PIPE_MODE_CSC (1 << 1)
|
||||
#define CGM_PIPE_MODE_DEGAMMA (1 << 0)
|
||||
|
||||
#define _CGM_PIPE_B_CSC_COEFF01 (VLV_DISPLAY_BASE + 0x69900)
|
||||
#define _CGM_PIPE_B_CSC_COEFF23 (VLV_DISPLAY_BASE + 0x69904)
|
||||
#define _CGM_PIPE_B_CSC_COEFF45 (VLV_DISPLAY_BASE + 0x69908)
|
||||
#define _CGM_PIPE_B_CSC_COEFF67 (VLV_DISPLAY_BASE + 0x6990C)
|
||||
#define _CGM_PIPE_B_CSC_COEFF8 (VLV_DISPLAY_BASE + 0x69910)
|
||||
#define _CGM_PIPE_B_DEGAMMA (VLV_DISPLAY_BASE + 0x68000)
|
||||
#define _CGM_PIPE_B_GAMMA (VLV_DISPLAY_BASE + 0x69000)
|
||||
#define _CGM_PIPE_B_MODE (VLV_DISPLAY_BASE + 0x69A00)
|
||||
|
||||
#define CGM_PIPE_CSC_COEFF01(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF01, _CGM_PIPE_B_CSC_COEFF01)
|
||||
#define CGM_PIPE_CSC_COEFF23(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF23, _CGM_PIPE_B_CSC_COEFF23)
|
||||
#define CGM_PIPE_CSC_COEFF45(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF45, _CGM_PIPE_B_CSC_COEFF45)
|
||||
#define CGM_PIPE_CSC_COEFF67(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF67, _CGM_PIPE_B_CSC_COEFF67)
|
||||
#define CGM_PIPE_CSC_COEFF8(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF8, _CGM_PIPE_B_CSC_COEFF8)
|
||||
#define CGM_PIPE_DEGAMMA(pipe, i, w) _MMIO(_PIPE(pipe, _CGM_PIPE_A_DEGAMMA, _CGM_PIPE_B_DEGAMMA) + (i) * 8 + (w) * 4)
|
||||
#define CGM_PIPE_GAMMA(pipe, i, w) _MMIO(_PIPE(pipe, _CGM_PIPE_A_GAMMA, _CGM_PIPE_B_GAMMA) + (i) * 8 + (w) * 4)
|
||||
#define CGM_PIPE_MODE(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_MODE, _CGM_PIPE_B_MODE)
|
||||
|
||||
/* Skylake+ pipe bottom (background) color */
|
||||
#define _SKL_BOTTOM_COLOR_A 0x70034
|
||||
#define _SKL_BOTTOM_COLOR_B 0x71034
|
||||
#define SKL_BOTTOM_COLOR_GAMMA_ENABLE REG_BIT(31)
|
||||
#define SKL_BOTTOM_COLOR_CSC_ENABLE REG_BIT(30)
|
||||
#define SKL_BOTTOM_COLOR(pipe) _MMIO_PIPE(pipe, _SKL_BOTTOM_COLOR_A, _SKL_BOTTOM_COLOR_B)
|
||||
|
||||
#endif /* __INTEL_COLOR_REGS_H__ */
|
||||
|
|
@ -114,10 +114,6 @@ 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),
|
||||
|
|
@ -312,14 +308,17 @@ static void icl_combo_phys_init(struct drm_i915_private *dev_priv)
|
|||
enum phy phy;
|
||||
|
||||
for_each_combo_phy(dev_priv, phy) {
|
||||
const struct icl_procmon *procmon;
|
||||
u32 val;
|
||||
|
||||
if (icl_combo_phy_verify_state(dev_priv, phy)) {
|
||||
drm_dbg(&dev_priv->drm,
|
||||
"Combo PHY %c already enabled, won't reprogram it.\n",
|
||||
phy_name(phy));
|
||||
if (icl_combo_phy_verify_state(dev_priv, phy))
|
||||
continue;
|
||||
}
|
||||
|
||||
procmon = icl_get_procmon_ref_values(dev_priv, phy);
|
||||
|
||||
drm_dbg(&dev_priv->drm,
|
||||
"Initializing combo PHY %c (Voltage/Process Info : %s)\n",
|
||||
phy_name(phy), procmon->name);
|
||||
|
||||
if (!has_phy_misc(dev_priv, phy))
|
||||
goto skip_phy_misc;
|
||||
|
|
|
|||
|
|
@ -192,17 +192,17 @@ int intel_connector_update_modes(struct drm_connector *connector,
|
|||
/**
|
||||
* intel_ddc_get_modes - get modelist from monitor
|
||||
* @connector: DRM connector device to use
|
||||
* @adapter: i2c adapter
|
||||
* @ddc: DDC bus i2c adapter
|
||||
*
|
||||
* Fetch the EDID information from @connector using the DDC bus.
|
||||
*/
|
||||
int intel_ddc_get_modes(struct drm_connector *connector,
|
||||
struct i2c_adapter *adapter)
|
||||
struct i2c_adapter *ddc)
|
||||
{
|
||||
const struct drm_edid *drm_edid;
|
||||
int ret;
|
||||
|
||||
drm_edid = drm_edid_read_ddc(connector, adapter);
|
||||
drm_edid = drm_edid_read_ddc(connector, ddc);
|
||||
if (!drm_edid)
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ bool intel_connector_get_hw_state(struct intel_connector *connector);
|
|||
enum pipe intel_connector_get_pipe(struct intel_connector *connector);
|
||||
int intel_connector_update_modes(struct drm_connector *connector,
|
||||
const struct drm_edid *drm_edid);
|
||||
int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
|
||||
int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *ddc);
|
||||
void intel_attach_force_audio_property(struct drm_connector *connector);
|
||||
void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
|
||||
void intel_attach_aspect_ratio_property(struct drm_connector *connector);
|
||||
|
|
|
|||
|
|
@ -413,6 +413,9 @@ static int pch_crt_compute_config(struct intel_encoder *encoder,
|
|||
return -EINVAL;
|
||||
|
||||
pipe_config->has_pch_encoder = true;
|
||||
if (!intel_fdi_compute_pipe_bpp(pipe_config))
|
||||
return -EINVAL;
|
||||
|
||||
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
|
||||
|
||||
return 0;
|
||||
|
|
@ -435,10 +438,14 @@ static int hsw_crt_compute_config(struct intel_encoder *encoder,
|
|||
return -EINVAL;
|
||||
|
||||
pipe_config->has_pch_encoder = true;
|
||||
if (!intel_fdi_compute_pipe_bpp(pipe_config))
|
||||
return -EINVAL;
|
||||
|
||||
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
|
||||
|
||||
/* LPT FDI RX only supports 8bpc. */
|
||||
if (HAS_PCH_LPT(dev_priv)) {
|
||||
/* TODO: Check crtc_state->max_link_bpp_x16 instead of bw_constrained */
|
||||
if (pipe_config->bw_constrained && pipe_config->pipe_bpp < 24) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"LPT only supports 24bpp\n");
|
||||
|
|
@ -451,6 +458,8 @@ static int hsw_crt_compute_config(struct intel_encoder *encoder,
|
|||
/* FDI must always be 2.7 GHz */
|
||||
pipe_config->port_clock = 135000 * 2;
|
||||
|
||||
pipe_config->enhanced_framing = true;
|
||||
|
||||
adjusted_mode->crtc_clock = lpt_iclkip(pipe_config);
|
||||
|
||||
return 0;
|
||||
|
|
@ -610,18 +619,18 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
|
|||
}
|
||||
|
||||
static const struct drm_edid *intel_crt_get_edid(struct drm_connector *connector,
|
||||
struct i2c_adapter *i2c)
|
||||
struct i2c_adapter *ddc)
|
||||
{
|
||||
const struct drm_edid *drm_edid;
|
||||
|
||||
drm_edid = drm_edid_read_ddc(connector, i2c);
|
||||
drm_edid = drm_edid_read_ddc(connector, ddc);
|
||||
|
||||
if (!drm_edid && !intel_gmbus_is_forced_bit(i2c)) {
|
||||
if (!drm_edid && !intel_gmbus_is_forced_bit(ddc)) {
|
||||
drm_dbg_kms(connector->dev,
|
||||
"CRT GMBUS EDID read failed, retry using GPIO bit-banging\n");
|
||||
intel_gmbus_force_bit(i2c, true);
|
||||
drm_edid = drm_edid_read_ddc(connector, i2c);
|
||||
intel_gmbus_force_bit(i2c, false);
|
||||
intel_gmbus_force_bit(ddc, true);
|
||||
drm_edid = drm_edid_read_ddc(connector, ddc);
|
||||
intel_gmbus_force_bit(ddc, false);
|
||||
}
|
||||
|
||||
return drm_edid;
|
||||
|
|
@ -629,12 +638,12 @@ static const struct drm_edid *intel_crt_get_edid(struct drm_connector *connector
|
|||
|
||||
/* local version of intel_ddc_get_modes() to use intel_crt_get_edid() */
|
||||
static int intel_crt_ddc_get_modes(struct drm_connector *connector,
|
||||
struct i2c_adapter *adapter)
|
||||
struct i2c_adapter *ddc)
|
||||
{
|
||||
const struct drm_edid *drm_edid;
|
||||
int ret;
|
||||
|
||||
drm_edid = intel_crt_get_edid(connector, adapter);
|
||||
drm_edid = intel_crt_get_edid(connector, ddc);
|
||||
if (!drm_edid)
|
||||
return 0;
|
||||
|
||||
|
|
@ -650,28 +659,23 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
|
|||
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
|
||||
struct drm_i915_private *dev_priv = to_i915(crt->base.base.dev);
|
||||
const struct drm_edid *drm_edid;
|
||||
struct i2c_adapter *i2c;
|
||||
bool ret = false;
|
||||
|
||||
i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->display.vbt.crt_ddc_pin);
|
||||
drm_edid = intel_crt_get_edid(connector, i2c);
|
||||
drm_edid = intel_crt_get_edid(connector, connector->ddc);
|
||||
|
||||
if (drm_edid) {
|
||||
const struct edid *edid = drm_edid_raw(drm_edid);
|
||||
bool is_digital = edid->input & DRM_EDID_INPUT_DIGITAL;
|
||||
|
||||
/*
|
||||
* This may be a DVI-I connector with a shared DDC
|
||||
* link between analog and digital outputs, so we
|
||||
* have to check the EDID input spec of the attached device.
|
||||
*/
|
||||
if (!is_digital) {
|
||||
if (drm_edid_is_digital(drm_edid)) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
|
||||
} else {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"CRT detected via DDC:0x50 [EDID]\n");
|
||||
ret = true;
|
||||
} else {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
|
||||
}
|
||||
} else {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
|
|
@ -907,12 +911,6 @@ load_detect:
|
|||
out:
|
||||
intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
|
||||
|
||||
/*
|
||||
* Make sure the refs for power wells enabled during detect are
|
||||
* dropped to avoid a new detect cycle triggered by HPD polling.
|
||||
*/
|
||||
intel_display_power_flush_work(dev_priv);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -923,20 +921,19 @@ static int intel_crt_get_modes(struct drm_connector *connector)
|
|||
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
|
||||
struct intel_encoder *intel_encoder = &crt->base;
|
||||
intel_wakeref_t wakeref;
|
||||
struct i2c_adapter *i2c;
|
||||
struct i2c_adapter *ddc;
|
||||
int ret;
|
||||
|
||||
wakeref = intel_display_power_get(dev_priv,
|
||||
intel_encoder->power_domain);
|
||||
|
||||
i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->display.vbt.crt_ddc_pin);
|
||||
ret = intel_crt_ddc_get_modes(connector, i2c);
|
||||
ret = intel_crt_ddc_get_modes(connector, connector->ddc);
|
||||
if (ret || !IS_G4X(dev_priv))
|
||||
goto out;
|
||||
|
||||
/* Try to probe digital port for output in DVI-I -> VGA mode. */
|
||||
i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PIN_DPB);
|
||||
ret = intel_crt_ddc_get_modes(connector, i2c);
|
||||
ddc = intel_gmbus_get_adapter(dev_priv, GMBUS_PIN_DPB);
|
||||
ret = intel_crt_ddc_get_modes(connector, ddc);
|
||||
|
||||
out:
|
||||
intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
|
||||
|
|
@ -994,6 +991,7 @@ void intel_crt_init(struct drm_i915_private *dev_priv)
|
|||
struct intel_crt *crt;
|
||||
struct intel_connector *intel_connector;
|
||||
i915_reg_t adpa_reg;
|
||||
u8 ddc_pin;
|
||||
u32 adpa;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev_priv))
|
||||
|
|
@ -1030,10 +1028,14 @@ void intel_crt_init(struct drm_i915_private *dev_priv)
|
|||
return;
|
||||
}
|
||||
|
||||
ddc_pin = dev_priv->display.vbt.crt_ddc_pin;
|
||||
|
||||
connector = &intel_connector->base;
|
||||
crt->connector = intel_connector;
|
||||
drm_connector_init(&dev_priv->drm, &intel_connector->base,
|
||||
&intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
|
||||
drm_connector_init_with_ddc(&dev_priv->drm, connector,
|
||||
&intel_crt_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_VGA,
|
||||
intel_gmbus_get_adapter(dev_priv, ddc_pin));
|
||||
|
||||
drm_encoder_init(&dev_priv->drm, &crt->base.base, &intel_crt_enc_funcs,
|
||||
DRM_MODE_ENCODER_DAC, "CRT");
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "intel_display_trace.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_drrs.h"
|
||||
#include "intel_dsb.h"
|
||||
#include "intel_dsi.h"
|
||||
#include "intel_fifo_underrun.h"
|
||||
#include "intel_pipe_crc.h"
|
||||
|
|
@ -175,6 +176,7 @@ void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
|
|||
crtc_state->hsw_workaround_pipe = INVALID_PIPE;
|
||||
crtc_state->scaler_state.scaler_id = -1;
|
||||
crtc_state->mst_master_transcoder = INVALID_TRANSCODER;
|
||||
crtc_state->max_link_bpp_x16 = INT_MAX;
|
||||
}
|
||||
|
||||
static struct intel_crtc *intel_crtc_alloc(void)
|
||||
|
|
@ -394,7 +396,8 @@ static bool intel_crtc_needs_vblank_work(const struct intel_crtc_state *crtc_sta
|
|||
return crtc_state->hw.active &&
|
||||
!intel_crtc_needs_modeset(crtc_state) &&
|
||||
!crtc_state->preload_luts &&
|
||||
intel_crtc_needs_color_update(crtc_state);
|
||||
intel_crtc_needs_color_update(crtc_state) &&
|
||||
!intel_color_uses_dsb(crtc_state);
|
||||
}
|
||||
|
||||
static void intel_crtc_vblank_work(struct kthread_work *base)
|
||||
|
|
@ -468,9 +471,64 @@ static int intel_mode_vblank_start(const struct drm_display_mode *mode)
|
|||
return vblank_start;
|
||||
}
|
||||
|
||||
static void intel_crtc_vblank_evade_scanlines(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc,
|
||||
int *min, int *max, int *vblank_start)
|
||||
{
|
||||
const struct intel_crtc_state *old_crtc_state =
|
||||
intel_atomic_get_old_crtc_state(state, crtc);
|
||||
const struct intel_crtc_state *new_crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
const struct intel_crtc_state *crtc_state;
|
||||
const struct drm_display_mode *adjusted_mode;
|
||||
|
||||
/*
|
||||
* During fastsets/etc. the transcoder is still
|
||||
* running with the old timings at this point.
|
||||
*
|
||||
* TODO: maybe just use the active timings here?
|
||||
*/
|
||||
if (intel_crtc_needs_modeset(new_crtc_state))
|
||||
crtc_state = new_crtc_state;
|
||||
else
|
||||
crtc_state = old_crtc_state;
|
||||
|
||||
adjusted_mode = &crtc_state->hw.adjusted_mode;
|
||||
|
||||
if (crtc->mode_flags & I915_MODE_FLAG_VRR) {
|
||||
/* timing changes should happen with VRR disabled */
|
||||
drm_WARN_ON(state->base.dev, intel_crtc_needs_modeset(new_crtc_state) ||
|
||||
new_crtc_state->update_m_n || new_crtc_state->update_lrr);
|
||||
|
||||
if (intel_vrr_is_push_sent(crtc_state))
|
||||
*vblank_start = intel_vrr_vmin_vblank_start(crtc_state);
|
||||
else
|
||||
*vblank_start = intel_vrr_vmax_vblank_start(crtc_state);
|
||||
} else {
|
||||
*vblank_start = intel_mode_vblank_start(adjusted_mode);
|
||||
}
|
||||
|
||||
/* FIXME needs to be calibrated sensibly */
|
||||
*min = *vblank_start - intel_usecs_to_scanlines(adjusted_mode,
|
||||
VBLANK_EVASION_TIME_US);
|
||||
*max = *vblank_start - 1;
|
||||
|
||||
/*
|
||||
* M/N and TRANS_VTOTAL are double buffered on the transcoder's
|
||||
* undelayed vblank, so with seamless M/N and LRR we must evade
|
||||
* both vblanks.
|
||||
*
|
||||
* DSB execution waits for the transcoder's undelayed vblank,
|
||||
* hence we must kick off the commit before that.
|
||||
*/
|
||||
if (new_crtc_state->dsb || new_crtc_state->update_m_n || new_crtc_state->update_lrr)
|
||||
*min -= adjusted_mode->crtc_vblank_start - adjusted_mode->crtc_vdisplay;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_pipe_update_start() - start update of a set of display registers
|
||||
* @new_crtc_state: the new crtc state
|
||||
* @state: the atomic state
|
||||
* @crtc: the crtc
|
||||
*
|
||||
* Mark the start of an update to pipe registers that should be updated
|
||||
* atomically regarding vblank. If the next vblank will happens within
|
||||
|
|
@ -480,11 +538,12 @@ static int intel_mode_vblank_start(const struct drm_display_mode *mode)
|
|||
* until a subsequent call to intel_pipe_update_end(). That is done to
|
||||
* avoid random delays.
|
||||
*/
|
||||
void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state)
|
||||
void intel_pipe_update_start(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
const struct drm_display_mode *adjusted_mode = &new_crtc_state->hw.adjusted_mode;
|
||||
struct intel_crtc_state *new_crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
long timeout = msecs_to_jiffies_timeout(1);
|
||||
int scanline, min, max, vblank_start;
|
||||
wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
|
||||
|
|
@ -500,27 +559,7 @@ void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state)
|
|||
if (intel_crtc_needs_vblank_work(new_crtc_state))
|
||||
intel_crtc_vblank_work_init(new_crtc_state);
|
||||
|
||||
if (new_crtc_state->vrr.enable) {
|
||||
if (intel_vrr_is_push_sent(new_crtc_state))
|
||||
vblank_start = intel_vrr_vmin_vblank_start(new_crtc_state);
|
||||
else
|
||||
vblank_start = intel_vrr_vmax_vblank_start(new_crtc_state);
|
||||
} else {
|
||||
vblank_start = intel_mode_vblank_start(adjusted_mode);
|
||||
}
|
||||
|
||||
/* FIXME needs to be calibrated sensibly */
|
||||
min = vblank_start - intel_usecs_to_scanlines(adjusted_mode,
|
||||
VBLANK_EVASION_TIME_US);
|
||||
max = vblank_start - 1;
|
||||
|
||||
/*
|
||||
* M/N is double buffered on the transcoder's undelayed vblank,
|
||||
* so with seamless M/N we must evade both vblanks.
|
||||
*/
|
||||
if (new_crtc_state->seamless_m_n && intel_crtc_needs_fastset(new_crtc_state))
|
||||
min -= adjusted_mode->crtc_vblank_start - adjusted_mode->crtc_vdisplay;
|
||||
|
||||
intel_crtc_vblank_evade_scanlines(state, crtc, &min, &max, &vblank_start);
|
||||
if (min <= 0 || max <= 0)
|
||||
goto irq_disable;
|
||||
|
||||
|
|
@ -631,25 +670,26 @@ static void dbg_vblank_evade(struct intel_crtc *crtc, ktime_t end) {}
|
|||
|
||||
/**
|
||||
* intel_pipe_update_end() - end update of a set of display registers
|
||||
* @new_crtc_state: the new crtc state
|
||||
* @state: the atomic state
|
||||
* @crtc: the crtc
|
||||
*
|
||||
* Mark the end of an update started with intel_pipe_update_start(). This
|
||||
* re-enables interrupts and verifies the update was actually completed
|
||||
* before a vblank.
|
||||
*/
|
||||
void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
|
||||
void intel_pipe_update_end(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
|
||||
struct intel_crtc_state *new_crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
int scanline_end = intel_get_crtc_scanline(crtc);
|
||||
u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
|
||||
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;
|
||||
goto out;
|
||||
|
||||
trace_intel_pipe_update_end(crtc, end_vbl_count, scanline_end);
|
||||
|
||||
|
|
@ -697,19 +737,10 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
|
|||
*/
|
||||
intel_vrr_send_push(new_crtc_state);
|
||||
|
||||
/*
|
||||
* Seamless M/N update may need to update frame timings.
|
||||
*
|
||||
* FIXME Should be synchronized with the start of vblank somehow...
|
||||
*/
|
||||
if (new_crtc_state->seamless_m_n && intel_crtc_needs_fastset(new_crtc_state))
|
||||
intel_crtc_update_active_timings(new_crtc_state,
|
||||
new_crtc_state->vrr.enable);
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
if (intel_vgpu_active(dev_priv))
|
||||
return;
|
||||
goto out;
|
||||
|
||||
if (crtc->debug.start_vbl_count &&
|
||||
crtc->debug.start_vbl_count != end_vbl_count) {
|
||||
|
|
@ -724,4 +755,7 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
|
|||
}
|
||||
|
||||
dbg_vblank_evade(crtc, end_vbl_time);
|
||||
|
||||
out:
|
||||
intel_psr_unlock(new_crtc_state);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,8 +36,10 @@ void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
|
|||
u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc);
|
||||
void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state);
|
||||
void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state);
|
||||
void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state);
|
||||
void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state);
|
||||
void intel_pipe_update_start(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc);
|
||||
void intel_pipe_update_end(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc);
|
||||
void intel_wait_for_vblank_workers(struct intel_atomic_state *state);
|
||||
struct intel_crtc *intel_first_crtc(struct drm_i915_private *i915);
|
||||
struct intel_crtc *intel_crtc_for_pipe(struct drm_i915_private *i915,
|
||||
|
|
|
|||
|
|
@ -258,6 +258,9 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config,
|
|||
intel_dump_m_n_config(pipe_config, "dp m2_n2",
|
||||
pipe_config->lane_count,
|
||||
&pipe_config->dp_m2_n2);
|
||||
drm_dbg_kms(&i915->drm, "fec: %s, enhanced framing: %s\n",
|
||||
str_enabled_disabled(pipe_config->fec_enable),
|
||||
str_enabled_disabled(pipe_config->enhanced_framing));
|
||||
}
|
||||
|
||||
drm_dbg_kms(&i915->drm, "framestart delay: %d, MSA timing delay: %d\n",
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
bool intel_is_c10phy(struct drm_i915_private *i915, enum phy phy)
|
||||
{
|
||||
if (IS_METEORLAKE(i915) && (phy < PHY_C))
|
||||
if (DISPLAY_VER_FULL(i915) == IP_VER(14, 0) && phy < PHY_C)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
|
@ -46,6 +46,22 @@ static int lane_mask_to_lane(u8 lane_mask)
|
|||
return ilog2(lane_mask);
|
||||
}
|
||||
|
||||
static u8 intel_cx0_get_owned_lane_mask(struct drm_i915_private *i915,
|
||||
struct intel_encoder *encoder)
|
||||
{
|
||||
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
|
||||
|
||||
if (!intel_tc_port_in_dp_alt_mode(dig_port))
|
||||
return INTEL_CX0_BOTH_LANES;
|
||||
|
||||
/*
|
||||
* In DP-alt with pin assignment D, only PHY lane 0 is owned
|
||||
* by display and lane 1 is owned by USB.
|
||||
*/
|
||||
return intel_tc_port_max_lane_count(dig_port) > 2
|
||||
? INTEL_CX0_BOTH_LANES : INTEL_CX0_LANE0;
|
||||
}
|
||||
|
||||
static void
|
||||
assert_dc_off(struct drm_i915_private *i915)
|
||||
{
|
||||
|
|
@ -55,19 +71,38 @@ assert_dc_off(struct drm_i915_private *i915)
|
|||
drm_WARN_ON(&i915->drm, !enabled);
|
||||
}
|
||||
|
||||
static void intel_cx0_program_msgbus_timer(struct intel_encoder *encoder)
|
||||
{
|
||||
int lane;
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
|
||||
for_each_cx0_lane_in_mask(INTEL_CX0_BOTH_LANES, lane)
|
||||
intel_de_rmw(i915,
|
||||
XELPDP_PORT_MSGBUS_TIMER(encoder->port, lane),
|
||||
XELPDP_PORT_MSGBUS_TIMER_VAL_MASK,
|
||||
XELPDP_PORT_MSGBUS_TIMER_VAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare HW for CX0 phy transactions.
|
||||
*
|
||||
* It is required that PSR and DC5/6 are disabled before any CX0 message
|
||||
* bus transaction is executed.
|
||||
*
|
||||
* We also do the msgbus timer programming here to ensure that the timer
|
||||
* is already programmed before any access to the msgbus.
|
||||
*/
|
||||
static intel_wakeref_t intel_cx0_phy_transaction_begin(struct intel_encoder *encoder)
|
||||
{
|
||||
intel_wakeref_t wakeref;
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
|
||||
intel_psr_pause(intel_dp);
|
||||
return intel_display_power_get(i915, POWER_DOMAIN_DC_OFF);
|
||||
wakeref = intel_display_power_get(i915, POWER_DOMAIN_DC_OFF);
|
||||
intel_cx0_program_msgbus_timer(encoder);
|
||||
|
||||
return wakeref;
|
||||
}
|
||||
|
||||
static void intel_cx0_phy_transaction_end(struct intel_encoder *encoder, intel_wakeref_t wakeref)
|
||||
|
|
@ -116,6 +151,13 @@ static int intel_cx0_wait_for_ack(struct drm_i915_private *i915, enum port port,
|
|||
XELPDP_MSGBUS_TIMEOUT_SLOW, val)) {
|
||||
drm_dbg_kms(&i915->drm, "PHY %c Timeout waiting for message ACK. Status: 0x%x\n",
|
||||
phy_name(phy), *val);
|
||||
|
||||
if (!(intel_de_read(i915, XELPDP_PORT_MSGBUS_TIMER(port, lane)) &
|
||||
XELPDP_PORT_MSGBUS_TIMER_TIMED_OUT))
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"PHY %c Hardware did not detect a timeout\n",
|
||||
phy_name(phy));
|
||||
|
||||
intel_cx0_bus_reset(i915, port, lane);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
|
@ -359,6 +401,7 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
|
|||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
const struct intel_ddi_buf_trans *trans;
|
||||
enum phy phy = intel_port_to_phy(i915, encoder->port);
|
||||
u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(i915, encoder);
|
||||
intel_wakeref_t wakeref;
|
||||
int n_entries, ln;
|
||||
|
||||
|
|
@ -371,13 +414,13 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
|
|||
}
|
||||
|
||||
if (intel_is_c10phy(i915, phy)) {
|
||||
intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
|
||||
intel_cx0_rmw(i915, encoder->port, owned_lane_mask, PHY_C10_VDR_CONTROL(1),
|
||||
0, C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED);
|
||||
intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CMN(3),
|
||||
intel_cx0_rmw(i915, encoder->port, owned_lane_mask, PHY_C10_VDR_CMN(3),
|
||||
C10_CMN3_TXVBOOST_MASK,
|
||||
C10_CMN3_TXVBOOST(intel_c10_get_tx_vboost_lvl(crtc_state)),
|
||||
MB_WRITE_UNCOMMITTED);
|
||||
intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_TX(1),
|
||||
intel_cx0_rmw(i915, encoder->port, owned_lane_mask, PHY_C10_VDR_TX(1),
|
||||
C10_TX1_TERMCTL_MASK,
|
||||
C10_TX1_TERMCTL(intel_c10_get_tx_term_ctl(crtc_state)),
|
||||
MB_WRITE_COMMITTED);
|
||||
|
|
@ -385,32 +428,34 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
|
|||
|
||||
for (ln = 0; ln < crtc_state->lane_count; ln++) {
|
||||
int level = intel_ddi_level(encoder, crtc_state, ln);
|
||||
int lane, tx;
|
||||
int lane = ln / 2;
|
||||
int tx = ln % 2;
|
||||
u8 lane_mask = lane == 0 ? INTEL_CX0_LANE0 : INTEL_CX0_LANE1;
|
||||
|
||||
lane = ln / 2;
|
||||
tx = ln % 2;
|
||||
if (!(lane_mask & owned_lane_mask))
|
||||
continue;
|
||||
|
||||
intel_cx0_rmw(i915, encoder->port, BIT(lane), PHY_CX0_VDROVRD_CTL(lane, tx, 0),
|
||||
intel_cx0_rmw(i915, encoder->port, lane_mask, PHY_CX0_VDROVRD_CTL(lane, tx, 0),
|
||||
C10_PHY_OVRD_LEVEL_MASK,
|
||||
C10_PHY_OVRD_LEVEL(trans->entries[level].snps.pre_cursor),
|
||||
MB_WRITE_COMMITTED);
|
||||
intel_cx0_rmw(i915, encoder->port, BIT(lane), PHY_CX0_VDROVRD_CTL(lane, tx, 1),
|
||||
intel_cx0_rmw(i915, encoder->port, lane_mask, PHY_CX0_VDROVRD_CTL(lane, tx, 1),
|
||||
C10_PHY_OVRD_LEVEL_MASK,
|
||||
C10_PHY_OVRD_LEVEL(trans->entries[level].snps.vswing),
|
||||
MB_WRITE_COMMITTED);
|
||||
intel_cx0_rmw(i915, encoder->port, BIT(lane), PHY_CX0_VDROVRD_CTL(lane, tx, 2),
|
||||
intel_cx0_rmw(i915, encoder->port, lane_mask, PHY_CX0_VDROVRD_CTL(lane, tx, 2),
|
||||
C10_PHY_OVRD_LEVEL_MASK,
|
||||
C10_PHY_OVRD_LEVEL(trans->entries[level].snps.post_cursor),
|
||||
MB_WRITE_COMMITTED);
|
||||
}
|
||||
|
||||
/* Write Override enables in 0xD71 */
|
||||
intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_OVRD,
|
||||
intel_cx0_rmw(i915, encoder->port, owned_lane_mask, PHY_C10_VDR_OVRD,
|
||||
0, PHY_C10_VDR_OVRD_TX1 | PHY_C10_VDR_OVRD_TX2,
|
||||
MB_WRITE_COMMITTED);
|
||||
|
||||
if (intel_is_c10phy(i915, phy))
|
||||
intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
|
||||
intel_cx0_rmw(i915, encoder->port, owned_lane_mask, PHY_C10_VDR_CONTROL(1),
|
||||
0, C10_VDR_CTRL_UPDATE_CFG, MB_WRITE_COMMITTED);
|
||||
|
||||
intel_cx0_phy_transaction_end(encoder, wakeref);
|
||||
|
|
@ -2534,17 +2579,15 @@ static void intel_cx0_phy_lane_reset(struct drm_i915_private *i915,
|
|||
{
|
||||
enum port port = encoder->port;
|
||||
enum phy phy = intel_port_to_phy(i915, port);
|
||||
bool both_lanes = intel_tc_port_fia_max_lane_count(enc_to_dig_port(encoder)) > 2;
|
||||
u8 lane_mask = lane_reversal ? INTEL_CX0_LANE1 :
|
||||
INTEL_CX0_LANE0;
|
||||
u32 lane_pipe_reset = both_lanes ?
|
||||
XELPDP_LANE_PIPE_RESET(0) |
|
||||
XELPDP_LANE_PIPE_RESET(1) :
|
||||
XELPDP_LANE_PIPE_RESET(0);
|
||||
u32 lane_phy_current_status = both_lanes ?
|
||||
XELPDP_LANE_PHY_CURRENT_STATUS(0) |
|
||||
XELPDP_LANE_PHY_CURRENT_STATUS(1) :
|
||||
XELPDP_LANE_PHY_CURRENT_STATUS(0);
|
||||
u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(i915, encoder);
|
||||
u8 lane_mask = lane_reversal ? INTEL_CX0_LANE1 : INTEL_CX0_LANE0;
|
||||
u32 lane_pipe_reset = owned_lane_mask == INTEL_CX0_BOTH_LANES
|
||||
? XELPDP_LANE_PIPE_RESET(0) | XELPDP_LANE_PIPE_RESET(1)
|
||||
: XELPDP_LANE_PIPE_RESET(0);
|
||||
u32 lane_phy_current_status = owned_lane_mask == INTEL_CX0_BOTH_LANES
|
||||
? (XELPDP_LANE_PHY_CURRENT_STATUS(0) |
|
||||
XELPDP_LANE_PHY_CURRENT_STATUS(1))
|
||||
: XELPDP_LANE_PHY_CURRENT_STATUS(0);
|
||||
|
||||
if (__intel_de_wait_for_register(i915, XELPDP_PORT_BUF_CTL1(port),
|
||||
XELPDP_PORT_BUF_SOC_PHY_READY,
|
||||
|
|
@ -2564,15 +2607,11 @@ static void intel_cx0_phy_lane_reset(struct drm_i915_private *i915,
|
|||
phy_name(phy), XELPDP_PORT_RESET_START_TIMEOUT_US);
|
||||
|
||||
intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(port),
|
||||
intel_cx0_get_pclk_refclk_request(both_lanes ?
|
||||
INTEL_CX0_BOTH_LANES :
|
||||
INTEL_CX0_LANE0),
|
||||
intel_cx0_get_pclk_refclk_request(owned_lane_mask),
|
||||
intel_cx0_get_pclk_refclk_request(lane_mask));
|
||||
|
||||
if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(port),
|
||||
intel_cx0_get_pclk_refclk_ack(both_lanes ?
|
||||
INTEL_CX0_BOTH_LANES :
|
||||
INTEL_CX0_LANE0),
|
||||
intel_cx0_get_pclk_refclk_ack(owned_lane_mask),
|
||||
intel_cx0_get_pclk_refclk_ack(lane_mask),
|
||||
XELPDP_REFCLK_ENABLE_TIMEOUT_US, 0, NULL))
|
||||
drm_warn(&i915->drm, "PHY %c failed to request refclk after %dus.\n",
|
||||
|
|
@ -2594,79 +2633,43 @@ static void intel_cx0_program_phy_lane(struct drm_i915_private *i915,
|
|||
struct intel_encoder *encoder, int lane_count,
|
||||
bool lane_reversal)
|
||||
{
|
||||
u8 l0t1, l0t2, l1t1, l1t2;
|
||||
int i;
|
||||
u8 disables;
|
||||
bool dp_alt_mode = intel_tc_port_in_dp_alt_mode(enc_to_dig_port(encoder));
|
||||
u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(i915, encoder);
|
||||
enum port port = encoder->port;
|
||||
|
||||
if (intel_is_c10phy(i915, intel_port_to_phy(i915, port)))
|
||||
intel_cx0_rmw(i915, port, INTEL_CX0_BOTH_LANES,
|
||||
intel_cx0_rmw(i915, port, owned_lane_mask,
|
||||
PHY_C10_VDR_CONTROL(1), 0,
|
||||
C10_VDR_CTRL_MSGBUS_ACCESS,
|
||||
MB_WRITE_COMMITTED);
|
||||
|
||||
/* TODO: DP-alt MFD case where only one PHY lane should be programmed. */
|
||||
l0t1 = intel_cx0_read(i915, port, INTEL_CX0_LANE0, PHY_CX0_TX_CONTROL(1, 2));
|
||||
l0t2 = intel_cx0_read(i915, port, INTEL_CX0_LANE0, PHY_CX0_TX_CONTROL(2, 2));
|
||||
l1t1 = intel_cx0_read(i915, port, INTEL_CX0_LANE1, PHY_CX0_TX_CONTROL(1, 2));
|
||||
l1t2 = intel_cx0_read(i915, port, INTEL_CX0_LANE1, PHY_CX0_TX_CONTROL(2, 2));
|
||||
if (lane_reversal)
|
||||
disables = REG_GENMASK8(3, 0) >> lane_count;
|
||||
else
|
||||
disables = REG_GENMASK8(3, 0) << lane_count;
|
||||
|
||||
l0t1 |= CONTROL2_DISABLE_SINGLE_TX;
|
||||
l0t2 |= CONTROL2_DISABLE_SINGLE_TX;
|
||||
l1t1 |= CONTROL2_DISABLE_SINGLE_TX;
|
||||
l1t2 |= CONTROL2_DISABLE_SINGLE_TX;
|
||||
|
||||
if (lane_reversal) {
|
||||
switch (lane_count) {
|
||||
case 4:
|
||||
l0t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
|
||||
fallthrough;
|
||||
case 3:
|
||||
l0t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
|
||||
fallthrough;
|
||||
case 2:
|
||||
l1t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
|
||||
fallthrough;
|
||||
case 1:
|
||||
l1t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(lane_count);
|
||||
}
|
||||
} else {
|
||||
switch (lane_count) {
|
||||
case 4:
|
||||
l1t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
|
||||
fallthrough;
|
||||
case 3:
|
||||
l1t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
|
||||
fallthrough;
|
||||
case 2:
|
||||
l0t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
|
||||
l0t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
|
||||
break;
|
||||
case 1:
|
||||
if (dp_alt_mode)
|
||||
l0t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
|
||||
else
|
||||
l0t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(lane_count);
|
||||
}
|
||||
if (dp_alt_mode && lane_count == 1) {
|
||||
disables &= ~REG_GENMASK8(1, 0);
|
||||
disables |= REG_FIELD_PREP8(REG_GENMASK8(1, 0), 0x1);
|
||||
}
|
||||
|
||||
/* disable MLs */
|
||||
intel_cx0_write(i915, port, INTEL_CX0_LANE0, PHY_CX0_TX_CONTROL(1, 2),
|
||||
l0t1, MB_WRITE_COMMITTED);
|
||||
intel_cx0_write(i915, port, INTEL_CX0_LANE0, PHY_CX0_TX_CONTROL(2, 2),
|
||||
l0t2, MB_WRITE_COMMITTED);
|
||||
intel_cx0_write(i915, port, INTEL_CX0_LANE1, PHY_CX0_TX_CONTROL(1, 2),
|
||||
l1t1, MB_WRITE_COMMITTED);
|
||||
intel_cx0_write(i915, port, INTEL_CX0_LANE1, PHY_CX0_TX_CONTROL(2, 2),
|
||||
l1t2, MB_WRITE_COMMITTED);
|
||||
for (i = 0; i < 4; i++) {
|
||||
int tx = i % 2 + 1;
|
||||
u8 lane_mask = i < 2 ? INTEL_CX0_LANE0 : INTEL_CX0_LANE1;
|
||||
|
||||
if (!(owned_lane_mask & lane_mask))
|
||||
continue;
|
||||
|
||||
intel_cx0_rmw(i915, port, lane_mask, PHY_CX0_TX_CONTROL(tx, 2),
|
||||
CONTROL2_DISABLE_SINGLE_TX,
|
||||
disables & BIT(i) ? CONTROL2_DISABLE_SINGLE_TX : 0,
|
||||
MB_WRITE_COMMITTED);
|
||||
}
|
||||
|
||||
if (intel_is_c10phy(i915, intel_port_to_phy(i915, port)))
|
||||
intel_cx0_rmw(i915, port, INTEL_CX0_BOTH_LANES,
|
||||
intel_cx0_rmw(i915, port, owned_lane_mask,
|
||||
PHY_C10_VDR_CONTROL(1), 0,
|
||||
C10_VDR_CTRL_UPDATE_CFG,
|
||||
MB_WRITE_COMMITTED);
|
||||
|
|
@ -2721,39 +2724,45 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
|
|||
intel_cx0_powerdown_change_sequence(i915, encoder->port, INTEL_CX0_BOTH_LANES,
|
||||
CX0_P2_STATE_READY);
|
||||
|
||||
/* 4. Program PHY internal PLL internal registers. */
|
||||
/*
|
||||
* 4. Program PORT_MSGBUS_TIMER register's Message Bus Timer field to 0xA000.
|
||||
* (This is done inside intel_cx0_phy_transaction_begin(), since we would need
|
||||
* the right timer thresholds for readouts too.)
|
||||
*/
|
||||
|
||||
/* 5. Program PHY internal PLL internal registers. */
|
||||
if (intel_is_c10phy(i915, phy))
|
||||
intel_c10_pll_program(i915, crtc_state, encoder);
|
||||
else
|
||||
intel_c20_pll_program(i915, crtc_state, encoder);
|
||||
|
||||
/*
|
||||
* 5. Program the enabled and disabled owned PHY lane
|
||||
* 6. Program the enabled and disabled owned PHY lane
|
||||
* transmitters over message bus
|
||||
*/
|
||||
intel_cx0_program_phy_lane(i915, encoder, crtc_state->lane_count, lane_reversal);
|
||||
|
||||
/*
|
||||
* 6. Follow the Display Voltage Frequency Switching - Sequence
|
||||
* 7. Follow the Display Voltage Frequency Switching - Sequence
|
||||
* Before Frequency Change. We handle this step in bxt_set_cdclk().
|
||||
*/
|
||||
|
||||
/*
|
||||
* 7. Program DDI_CLK_VALFREQ to match intended DDI
|
||||
* 8. Program DDI_CLK_VALFREQ to match intended DDI
|
||||
* clock frequency.
|
||||
*/
|
||||
intel_de_write(i915, DDI_CLK_VALFREQ(encoder->port),
|
||||
crtc_state->port_clock);
|
||||
|
||||
/*
|
||||
* 8. Set PORT_CLOCK_CTL register PCLK PLL Request
|
||||
* 9. Set PORT_CLOCK_CTL register PCLK PLL Request
|
||||
* LN<Lane for maxPCLK> to "1" to enable PLL.
|
||||
*/
|
||||
intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
|
||||
intel_cx0_get_pclk_pll_request(INTEL_CX0_BOTH_LANES),
|
||||
intel_cx0_get_pclk_pll_request(maxpclk_lane));
|
||||
|
||||
/* 9. Poll on PORT_CLOCK_CTL PCLK PLL Ack LN<Lane for maxPCLK> == "1". */
|
||||
/* 10. Poll on PORT_CLOCK_CTL PCLK PLL Ack LN<Lane for maxPCLK> == "1". */
|
||||
if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
|
||||
intel_cx0_get_pclk_pll_ack(INTEL_CX0_BOTH_LANES),
|
||||
intel_cx0_get_pclk_pll_ack(maxpclk_lane),
|
||||
|
|
@ -2762,7 +2771,7 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
|
|||
phy_name(phy), XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US);
|
||||
|
||||
/*
|
||||
* 10. Follow the Display Voltage Frequency Switching Sequence After
|
||||
* 11. Follow the Display Voltage Frequency Switching Sequence After
|
||||
* Frequency Change. We handle this step in bxt_set_cdclk().
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -10,14 +10,15 @@
|
|||
#include <linux/bitfield.h>
|
||||
#include <linux/bits.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_display_types.h"
|
||||
|
||||
struct drm_i915_private;
|
||||
struct intel_encoder;
|
||||
struct intel_crtc_state;
|
||||
enum icl_port_dpll_id;
|
||||
enum phy;
|
||||
struct drm_i915_private;
|
||||
struct intel_atomic_state;
|
||||
struct intel_c10pll_state;
|
||||
struct intel_c20pll_state;
|
||||
struct intel_crtc_state;
|
||||
struct intel_encoder;
|
||||
struct intel_hdmi;
|
||||
|
||||
bool intel_is_c10phy(struct drm_i915_private *dev_priv, enum phy phy);
|
||||
void intel_mtl_pll_enable(struct intel_encoder *encoder,
|
||||
|
|
@ -44,4 +45,5 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
|
|||
const struct intel_crtc_state *crtc_state);
|
||||
int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi *hdmi, int clock);
|
||||
int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder);
|
||||
|
||||
#endif /* __INTEL_CX0_PHY_H__ */
|
||||
|
|
|
|||
|
|
@ -110,6 +110,19 @@
|
|||
#define CX0_P4PG_STATE_DISABLE 0xC
|
||||
#define CX0_P2_STATE_RESET 0x2
|
||||
|
||||
#define _XELPDP_PORT_MSGBUS_TIMER_LN0_A 0x640d8
|
||||
#define _XELPDP_PORT_MSGBUS_TIMER_LN0_B 0x641d8
|
||||
#define _XELPDP_PORT_MSGBUS_TIMER_LN0_USBC1 0x16f258
|
||||
#define _XELPDP_PORT_MSGBUS_TIMER_LN0_USBC2 0x16f458
|
||||
#define XELPDP_PORT_MSGBUS_TIMER(port, lane) _MMIO(_PICK_EVEN_2RANGES(port, PORT_TC1, \
|
||||
_XELPDP_PORT_MSGBUS_TIMER_LN0_A, \
|
||||
_XELPDP_PORT_MSGBUS_TIMER_LN0_B, \
|
||||
_XELPDP_PORT_MSGBUS_TIMER_LN0_USBC1, \
|
||||
_XELPDP_PORT_MSGBUS_TIMER_LN0_USBC2) + (lane) * 4)
|
||||
#define XELPDP_PORT_MSGBUS_TIMER_TIMED_OUT REG_BIT(31)
|
||||
#define XELPDP_PORT_MSGBUS_TIMER_VAL_MASK REG_GENMASK(23, 0)
|
||||
#define XELPDP_PORT_MSGBUS_TIMER_VAL REG_FIELD_PREP(XELPDP_PORT_MSGBUS_TIMER_VAL_MASK, 0xa000)
|
||||
|
||||
#define _XELPDP_PORT_CLOCK_CTL_A 0x640E0
|
||||
#define _XELPDP_PORT_CLOCK_CTL_B 0x641E0
|
||||
#define _XELPDP_PORT_CLOCK_CTL_USBC1 0x16F260
|
||||
|
|
|
|||
|
|
@ -3248,7 +3248,7 @@ static void intel_enable_ddi(struct intel_atomic_state *state,
|
|||
intel_ddi_enable_transcoder_func(encoder, crtc_state);
|
||||
|
||||
/* Enable/Disable DP2.0 SDP split config before transcoder */
|
||||
intel_audio_sdp_split_update(encoder, crtc_state);
|
||||
intel_audio_sdp_split_update(crtc_state);
|
||||
|
||||
intel_enable_transcoder(crtc_state);
|
||||
|
||||
|
|
@ -3432,7 +3432,7 @@ static void mtl_ddi_prepare_link_retrain(struct intel_dp *intel_dp,
|
|||
dp_tp_ctl |= DP_TP_CTL_MODE_MST;
|
||||
} else {
|
||||
dp_tp_ctl |= DP_TP_CTL_MODE_SST;
|
||||
if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
|
||||
if (crtc_state->enhanced_framing)
|
||||
dp_tp_ctl |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
|
||||
}
|
||||
intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), dp_tp_ctl);
|
||||
|
|
@ -3489,7 +3489,7 @@ static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp,
|
|||
dp_tp_ctl |= DP_TP_CTL_MODE_MST;
|
||||
} else {
|
||||
dp_tp_ctl |= DP_TP_CTL_MODE_SST;
|
||||
if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
|
||||
if (crtc_state->enhanced_framing)
|
||||
dp_tp_ctl |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
|
||||
}
|
||||
intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), dp_tp_ctl);
|
||||
|
|
@ -3724,17 +3724,14 @@ static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
|
|||
intel_cpu_transcoder_get_m2_n2(crtc, cpu_transcoder,
|
||||
&pipe_config->dp_m2_n2);
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 11) {
|
||||
i915_reg_t dp_tp_ctl = dp_tp_ctl_reg(encoder, pipe_config);
|
||||
pipe_config->enhanced_framing =
|
||||
intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, pipe_config)) &
|
||||
DP_TP_CTL_ENHANCED_FRAME_ENABLE;
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 11)
|
||||
pipe_config->fec_enable =
|
||||
intel_de_read(dev_priv, dp_tp_ctl) & DP_TP_CTL_FEC_ENABLE;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"[ENCODER:%d:%s] Fec status: %u\n",
|
||||
encoder->base.base.id, encoder->base.name,
|
||||
pipe_config->fec_enable);
|
||||
}
|
||||
intel_de_read(dev_priv,
|
||||
dp_tp_ctl_reg(encoder, pipe_config)) & DP_TP_CTL_FEC_ENABLE;
|
||||
|
||||
if (dig_port->lspcon.active && intel_dp_has_hdmi_sink(&dig_port->dp))
|
||||
pipe_config->infoframes.enable |=
|
||||
|
|
@ -3747,6 +3744,9 @@ static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
|
|||
if (!HAS_DP20(dev_priv)) {
|
||||
/* FDI */
|
||||
pipe_config->output_types |= BIT(INTEL_OUTPUT_ANALOG);
|
||||
pipe_config->enhanced_framing =
|
||||
intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, pipe_config)) &
|
||||
DP_TP_CTL_ENHANCED_FRAME_ENABLE;
|
||||
break;
|
||||
}
|
||||
fallthrough; /* 128b/132b */
|
||||
|
|
@ -3762,6 +3762,11 @@ static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
|
|||
intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder,
|
||||
&pipe_config->dp_m_n);
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 11)
|
||||
pipe_config->fec_enable =
|
||||
intel_de_read(dev_priv,
|
||||
dp_tp_ctl_reg(encoder, pipe_config)) & DP_TP_CTL_FEC_ENABLE;
|
||||
|
||||
pipe_config->infoframes.enable |=
|
||||
intel_hdmi_infoframes_enabled(encoder, pipe_config);
|
||||
break;
|
||||
|
|
@ -3857,11 +3862,9 @@ static void mtl_ddi_get_config(struct intel_encoder *encoder,
|
|||
crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder);
|
||||
} else if (intel_is_c10phy(i915, phy)) {
|
||||
intel_c10pll_readout_hw_state(encoder, &crtc_state->cx0pll_state.c10);
|
||||
intel_c10pll_dump_hw_state(i915, &crtc_state->cx0pll_state.c10);
|
||||
crtc_state->port_clock = intel_c10pll_calc_port_clock(encoder, &crtc_state->cx0pll_state.c10);
|
||||
} else {
|
||||
intel_c20pll_readout_hw_state(encoder, &crtc_state->cx0pll_state.c20);
|
||||
intel_c20pll_dump_hw_state(i915, &crtc_state->cx0pll_state.c20);
|
||||
crtc_state->port_clock = intel_c20pll_calc_port_clock(encoder, &crtc_state->cx0pll_state.c20);
|
||||
}
|
||||
|
||||
|
|
@ -4173,7 +4176,7 @@ static int intel_ddi_compute_config_late(struct intel_encoder *encoder,
|
|||
struct drm_connector *connector = conn_state->connector;
|
||||
u8 port_sync_transcoders = 0;
|
||||
|
||||
drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] [CRTC:%d:%s]",
|
||||
drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] [CRTC:%d:%s]\n",
|
||||
encoder->base.base.id, encoder->base.name,
|
||||
crtc_state->uapi.crtc->base.id, crtc_state->uapi.crtc->name);
|
||||
|
||||
|
|
@ -4323,8 +4326,7 @@ static int intel_hdmi_reset_link(struct intel_encoder *encoder,
|
|||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_hdmi *hdmi = enc_to_intel_hdmi(encoder);
|
||||
struct intel_connector *connector = hdmi->attached_connector;
|
||||
struct i2c_adapter *adapter =
|
||||
intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus);
|
||||
struct i2c_adapter *ddc = connector->base.ddc;
|
||||
struct drm_connector_state *conn_state;
|
||||
struct intel_crtc_state *crtc_state;
|
||||
struct intel_crtc *crtc;
|
||||
|
|
@ -4365,7 +4367,7 @@ static int intel_hdmi_reset_link(struct intel_encoder *encoder,
|
|||
!try_wait_for_completion(&conn_state->commit->hw_done))
|
||||
return 0;
|
||||
|
||||
ret = drm_scdc_readb(adapter, SCDC_TMDS_CONFIG, &config);
|
||||
ret = drm_scdc_readb(ddc, SCDC_TMDS_CONFIG, &config);
|
||||
if (ret < 0) {
|
||||
drm_err(&dev_priv->drm, "[CONNECTOR:%d:%s] Failed to read TMDS config: %d\n",
|
||||
connector->base.base.id, connector->base.name, ret);
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@
|
|||
#include "intel_dpll_mgr.h"
|
||||
#include "intel_dpt.h"
|
||||
#include "intel_drrs.h"
|
||||
#include "intel_dsb.h"
|
||||
#include "intel_dsi.h"
|
||||
#include "intel_dvo.h"
|
||||
#include "intel_fb.h"
|
||||
|
|
@ -87,6 +88,7 @@
|
|||
#include "intel_frontbuffer.h"
|
||||
#include "intel_hdmi.h"
|
||||
#include "intel_hotplug.h"
|
||||
#include "intel_link_bw.h"
|
||||
#include "intel_lvds.h"
|
||||
#include "intel_lvds_regs.h"
|
||||
#include "intel_modeset_setup.h"
|
||||
|
|
@ -726,7 +728,7 @@ static void icl_set_pipe_chicken(const struct intel_crtc_state *crtc_state)
|
|||
tmp |= UNDERRUN_RECOVERY_DISABLE_ADLP;
|
||||
|
||||
/* Wa_14010547955:dg2 */
|
||||
if (IS_DG2_DISPLAY_STEP(dev_priv, STEP_B0, STEP_FOREVER))
|
||||
if (IS_DG2(dev_priv))
|
||||
tmp |= DG2_RENDER_CCSTAG_4_3_EN;
|
||||
|
||||
intel_de_write(dev_priv, PIPE_CHICKEN(pipe), tmp);
|
||||
|
|
@ -913,16 +915,32 @@ static bool planes_disabling(const struct intel_crtc_state *old_crtc_state,
|
|||
return is_disabling(active_planes, old_crtc_state, new_crtc_state);
|
||||
}
|
||||
|
||||
static bool vrr_params_changed(const struct intel_crtc_state *old_crtc_state,
|
||||
const struct intel_crtc_state *new_crtc_state)
|
||||
{
|
||||
return old_crtc_state->vrr.flipline != new_crtc_state->vrr.flipline ||
|
||||
old_crtc_state->vrr.vmin != new_crtc_state->vrr.vmin ||
|
||||
old_crtc_state->vrr.vmax != new_crtc_state->vrr.vmax ||
|
||||
old_crtc_state->vrr.guardband != new_crtc_state->vrr.guardband ||
|
||||
old_crtc_state->vrr.pipeline_full != new_crtc_state->vrr.pipeline_full;
|
||||
}
|
||||
|
||||
static bool vrr_enabling(const struct intel_crtc_state *old_crtc_state,
|
||||
const struct intel_crtc_state *new_crtc_state)
|
||||
{
|
||||
return is_enabling(vrr.enable, old_crtc_state, new_crtc_state);
|
||||
return is_enabling(vrr.enable, old_crtc_state, new_crtc_state) ||
|
||||
(new_crtc_state->vrr.enable &&
|
||||
(new_crtc_state->update_m_n || new_crtc_state->update_lrr ||
|
||||
vrr_params_changed(old_crtc_state, new_crtc_state)));
|
||||
}
|
||||
|
||||
static bool vrr_disabling(const struct intel_crtc_state *old_crtc_state,
|
||||
const struct intel_crtc_state *new_crtc_state)
|
||||
{
|
||||
return is_disabling(vrr.enable, old_crtc_state, new_crtc_state);
|
||||
return is_disabling(vrr.enable, old_crtc_state, new_crtc_state) ||
|
||||
(old_crtc_state->vrr.enable &&
|
||||
(new_crtc_state->update_m_n || new_crtc_state->update_lrr ||
|
||||
vrr_params_changed(old_crtc_state, new_crtc_state)));
|
||||
}
|
||||
|
||||
#undef is_disabling
|
||||
|
|
@ -1767,7 +1785,7 @@ bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy)
|
|||
if (IS_DG2(dev_priv))
|
||||
/* DG2's "TC1" output uses a SNPS PHY */
|
||||
return false;
|
||||
else if (IS_ALDERLAKE_P(dev_priv) || IS_METEORLAKE(dev_priv))
|
||||
else if (IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER_FULL(dev_priv) == IP_VER(14, 0))
|
||||
return phy >= PHY_F && phy <= PHY_I;
|
||||
else if (IS_TIGERLAKE(dev_priv))
|
||||
return phy >= PHY_D && phy <= PHY_I;
|
||||
|
|
@ -2570,6 +2588,37 @@ static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_sta
|
|||
VTOTAL(crtc_vtotal - 1));
|
||||
}
|
||||
|
||||
static void intel_set_transcoder_timings_lrr(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;
|
||||
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
|
||||
u32 crtc_vdisplay, crtc_vtotal, crtc_vblank_start, crtc_vblank_end;
|
||||
|
||||
crtc_vdisplay = adjusted_mode->crtc_vdisplay;
|
||||
crtc_vtotal = adjusted_mode->crtc_vtotal;
|
||||
crtc_vblank_start = adjusted_mode->crtc_vblank_start;
|
||||
crtc_vblank_end = adjusted_mode->crtc_vblank_end;
|
||||
|
||||
drm_WARN_ON(&dev_priv->drm, adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE);
|
||||
|
||||
/*
|
||||
* The hardware actually ignores TRANS_VBLANK.VBLANK_END in DP mode.
|
||||
* But let's write it anyway to keep the state checker happy.
|
||||
*/
|
||||
intel_de_write(dev_priv, TRANS_VBLANK(cpu_transcoder),
|
||||
VBLANK_START(crtc_vblank_start - 1) |
|
||||
VBLANK_END(crtc_vblank_end - 1));
|
||||
/*
|
||||
* The double buffer latch point for TRANS_VTOTAL
|
||||
* is the transcoder's undelayed vblank.
|
||||
*/
|
||||
intel_de_write(dev_priv, TRANS_VTOTAL(cpu_transcoder),
|
||||
VACTIVE(crtc_vdisplay - 1) |
|
||||
VTOTAL(crtc_vtotal - 1));
|
||||
}
|
||||
|
||||
static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
|
@ -2869,24 +2918,6 @@ bdw_get_pipe_misc_output_format(struct intel_crtc *crtc)
|
|||
}
|
||||
}
|
||||
|
||||
static void i9xx_get_pipe_color_config(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct intel_plane *plane = to_intel_plane(crtc->base.primary);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
|
||||
u32 tmp;
|
||||
|
||||
tmp = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
|
||||
|
||||
if (tmp & DISP_PIPE_GAMMA_ENABLE)
|
||||
crtc_state->gamma_enable = true;
|
||||
|
||||
if (!HAS_GMCH(dev_priv) &&
|
||||
tmp & DISP_PIPE_CSC_ENABLE)
|
||||
crtc_state->csc_enable = true;
|
||||
}
|
||||
|
||||
static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
|
|
@ -2942,11 +2973,6 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
|
|||
(tmp & TRANSCONF_WGC_ENABLE))
|
||||
pipe_config->wgc_enable = true;
|
||||
|
||||
if (IS_CHERRYVIEW(dev_priv))
|
||||
pipe_config->cgm_mode = intel_de_read(dev_priv,
|
||||
CGM_PIPE_MODE(crtc->pipe));
|
||||
|
||||
i9xx_get_pipe_color_config(pipe_config);
|
||||
intel_color_get_config(pipe_config);
|
||||
|
||||
if (DISPLAY_VER(dev_priv) < 4)
|
||||
|
|
@ -3344,10 +3370,6 @@ static bool ilk_get_pipe_config(struct intel_crtc *crtc,
|
|||
|
||||
pipe_config->msa_timing_delay = REG_FIELD_GET(TRANSCONF_MSA_TIMING_DELAY_MASK, tmp);
|
||||
|
||||
pipe_config->csc_mode = intel_de_read(dev_priv,
|
||||
PIPE_CSC_MODE(crtc->pipe));
|
||||
|
||||
i9xx_get_pipe_color_config(pipe_config);
|
||||
intel_color_get_config(pipe_config);
|
||||
|
||||
pipe_config->pixel_multiplier = 1;
|
||||
|
|
@ -3738,24 +3760,6 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
|
|||
|
||||
pipe_config->sink_format = pipe_config->output_format;
|
||||
|
||||
pipe_config->gamma_mode = intel_de_read(dev_priv,
|
||||
GAMMA_MODE(crtc->pipe));
|
||||
|
||||
pipe_config->csc_mode = intel_de_read(dev_priv,
|
||||
PIPE_CSC_MODE(crtc->pipe));
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 9) {
|
||||
tmp = intel_de_read(dev_priv, SKL_BOTTOM_COLOR(crtc->pipe));
|
||||
|
||||
if (tmp & SKL_BOTTOM_COLOR_GAMMA_ENABLE)
|
||||
pipe_config->gamma_enable = true;
|
||||
|
||||
if (tmp & SKL_BOTTOM_COLOR_CSC_ENABLE)
|
||||
pipe_config->csc_enable = true;
|
||||
} else {
|
||||
i9xx_get_pipe_color_config(pipe_config);
|
||||
}
|
||||
|
||||
intel_color_get_config(pipe_config);
|
||||
|
||||
tmp = intel_de_read(dev_priv, WM_LINETIME(crtc->pipe));
|
||||
|
|
@ -4641,7 +4645,8 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,
|
|||
|
||||
static int
|
||||
intel_modeset_pipe_config(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
struct intel_crtc *crtc,
|
||||
const struct intel_link_bw_limits *limits)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
struct intel_crtc_state *crtc_state =
|
||||
|
|
@ -4650,7 +4655,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
|
|||
struct drm_connector_state *connector_state;
|
||||
int pipe_src_w, pipe_src_h;
|
||||
int base_bpp, ret, i;
|
||||
bool retry = true;
|
||||
|
||||
crtc_state->cpu_transcoder = (enum transcoder) crtc->pipe;
|
||||
|
||||
|
|
@ -4673,6 +4677,16 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
crtc_state->max_link_bpp_x16 = limits->max_bpp_x16[crtc->pipe];
|
||||
|
||||
if (crtc_state->pipe_bpp > to_bpp_int(crtc_state->max_link_bpp_x16)) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"[CRTC:%d:%s] Link bpp limited to " BPP_X16_FMT "\n",
|
||||
crtc->base.base.id, crtc->base.name,
|
||||
BPP_X16_ARGS(crtc_state->max_link_bpp_x16));
|
||||
crtc_state->bw_constrained = true;
|
||||
}
|
||||
|
||||
base_bpp = crtc_state->pipe_bpp;
|
||||
|
||||
/*
|
||||
|
|
@ -4714,7 +4728,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
|
|||
crtc_state->output_types |= BIT(encoder->type);
|
||||
}
|
||||
|
||||
encoder_retry:
|
||||
/* Ensure the port clock defaults are reset when retrying. */
|
||||
crtc_state->port_clock = 0;
|
||||
crtc_state->pixel_multiplier = 1;
|
||||
|
|
@ -4754,17 +4767,6 @@ encoder_retry:
|
|||
ret = intel_crtc_compute_config(state, crtc);
|
||||
if (ret == -EDEADLK)
|
||||
return ret;
|
||||
if (ret == -EAGAIN) {
|
||||
if (drm_WARN(&i915->drm, !retry,
|
||||
"[CRTC:%d:%s] loop in pipe configuration computation\n",
|
||||
crtc->base.base.id, crtc->base.name))
|
||||
return -EINVAL;
|
||||
|
||||
drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] bw constrained, retrying\n",
|
||||
crtc->base.base.id, crtc->base.name);
|
||||
retry = false;
|
||||
goto encoder_retry;
|
||||
}
|
||||
if (ret < 0) {
|
||||
drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] config failure: %d\n",
|
||||
crtc->base.base.id, crtc->base.name, ret);
|
||||
|
|
@ -5111,11 +5113,13 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
|
|||
PIPE_CONF_CHECK_I(name.crtc_hsync_start); \
|
||||
PIPE_CONF_CHECK_I(name.crtc_hsync_end); \
|
||||
PIPE_CONF_CHECK_I(name.crtc_vdisplay); \
|
||||
PIPE_CONF_CHECK_I(name.crtc_vtotal); \
|
||||
PIPE_CONF_CHECK_I(name.crtc_vblank_start); \
|
||||
PIPE_CONF_CHECK_I(name.crtc_vblank_end); \
|
||||
PIPE_CONF_CHECK_I(name.crtc_vsync_start); \
|
||||
PIPE_CONF_CHECK_I(name.crtc_vsync_end); \
|
||||
if (!fastset || !pipe_config->update_lrr) { \
|
||||
PIPE_CONF_CHECK_I(name.crtc_vtotal); \
|
||||
PIPE_CONF_CHECK_I(name.crtc_vblank_end); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define PIPE_CONF_CHECK_RECT(name) do { \
|
||||
|
|
@ -5215,7 +5219,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
|
|||
PIPE_CONF_CHECK_X(lane_lat_optim_mask);
|
||||
|
||||
if (HAS_DOUBLE_BUFFERED_M_N(dev_priv)) {
|
||||
if (!fastset || !pipe_config->seamless_m_n)
|
||||
if (!fastset || !pipe_config->update_m_n)
|
||||
PIPE_CONF_CHECK_M_N(dp_m_n);
|
||||
} else {
|
||||
PIPE_CONF_CHECK_M_N(dp_m_n);
|
||||
|
|
@ -5255,6 +5259,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
|
|||
PIPE_CONF_CHECK_BOOL(hdmi_scrambling);
|
||||
PIPE_CONF_CHECK_BOOL(hdmi_high_tmds_clock_ratio);
|
||||
PIPE_CONF_CHECK_BOOL(has_infoframe);
|
||||
PIPE_CONF_CHECK_BOOL(enhanced_framing);
|
||||
PIPE_CONF_CHECK_BOOL(fec_enable);
|
||||
|
||||
PIPE_CONF_CHECK_BOOL_INCOMPLETE(has_audio);
|
||||
|
|
@ -5352,7 +5357,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
|
|||
if (IS_G4X(dev_priv) || DISPLAY_VER(dev_priv) >= 5)
|
||||
PIPE_CONF_CHECK_I(pipe_bpp);
|
||||
|
||||
if (!fastset || !pipe_config->seamless_m_n) {
|
||||
if (!fastset || !pipe_config->update_m_n) {
|
||||
PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_clock);
|
||||
PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_clock);
|
||||
}
|
||||
|
|
@ -5377,6 +5382,37 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
|
|||
PIPE_CONF_CHECK_I(master_transcoder);
|
||||
PIPE_CONF_CHECK_X(bigjoiner_pipes);
|
||||
|
||||
PIPE_CONF_CHECK_BOOL(dsc.config.block_pred_enable);
|
||||
PIPE_CONF_CHECK_BOOL(dsc.config.convert_rgb);
|
||||
PIPE_CONF_CHECK_BOOL(dsc.config.simple_422);
|
||||
PIPE_CONF_CHECK_BOOL(dsc.config.native_422);
|
||||
PIPE_CONF_CHECK_BOOL(dsc.config.native_420);
|
||||
PIPE_CONF_CHECK_BOOL(dsc.config.vbr_enable);
|
||||
PIPE_CONF_CHECK_I(dsc.config.line_buf_depth);
|
||||
PIPE_CONF_CHECK_I(dsc.config.bits_per_component);
|
||||
PIPE_CONF_CHECK_I(dsc.config.pic_width);
|
||||
PIPE_CONF_CHECK_I(dsc.config.pic_height);
|
||||
PIPE_CONF_CHECK_I(dsc.config.slice_width);
|
||||
PIPE_CONF_CHECK_I(dsc.config.slice_height);
|
||||
PIPE_CONF_CHECK_I(dsc.config.initial_dec_delay);
|
||||
PIPE_CONF_CHECK_I(dsc.config.initial_xmit_delay);
|
||||
PIPE_CONF_CHECK_I(dsc.config.scale_decrement_interval);
|
||||
PIPE_CONF_CHECK_I(dsc.config.scale_increment_interval);
|
||||
PIPE_CONF_CHECK_I(dsc.config.initial_scale_value);
|
||||
PIPE_CONF_CHECK_I(dsc.config.first_line_bpg_offset);
|
||||
PIPE_CONF_CHECK_I(dsc.config.flatness_min_qp);
|
||||
PIPE_CONF_CHECK_I(dsc.config.flatness_max_qp);
|
||||
PIPE_CONF_CHECK_I(dsc.config.slice_bpg_offset);
|
||||
PIPE_CONF_CHECK_I(dsc.config.nfl_bpg_offset);
|
||||
PIPE_CONF_CHECK_I(dsc.config.initial_offset);
|
||||
PIPE_CONF_CHECK_I(dsc.config.final_offset);
|
||||
PIPE_CONF_CHECK_I(dsc.config.rc_model_size);
|
||||
PIPE_CONF_CHECK_I(dsc.config.rc_quant_incr_limit0);
|
||||
PIPE_CONF_CHECK_I(dsc.config.rc_quant_incr_limit1);
|
||||
PIPE_CONF_CHECK_I(dsc.config.slice_chunk_size);
|
||||
PIPE_CONF_CHECK_I(dsc.config.second_line_bpg_offset);
|
||||
PIPE_CONF_CHECK_I(dsc.config.nsl_bpg_offset);
|
||||
|
||||
PIPE_CONF_CHECK_I(dsc.compression_enable);
|
||||
PIPE_CONF_CHECK_I(dsc.dsc_split);
|
||||
PIPE_CONF_CHECK_I(dsc.compressed_bpp);
|
||||
|
|
@ -5385,13 +5421,14 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
|
|||
PIPE_CONF_CHECK_I(splitter.link_count);
|
||||
PIPE_CONF_CHECK_I(splitter.pixel_overlap);
|
||||
|
||||
if (!fastset)
|
||||
if (!fastset) {
|
||||
PIPE_CONF_CHECK_BOOL(vrr.enable);
|
||||
PIPE_CONF_CHECK_I(vrr.vmin);
|
||||
PIPE_CONF_CHECK_I(vrr.vmax);
|
||||
PIPE_CONF_CHECK_I(vrr.flipline);
|
||||
PIPE_CONF_CHECK_I(vrr.pipeline_full);
|
||||
PIPE_CONF_CHECK_I(vrr.guardband);
|
||||
PIPE_CONF_CHECK_I(vrr.vmin);
|
||||
PIPE_CONF_CHECK_I(vrr.vmax);
|
||||
PIPE_CONF_CHECK_I(vrr.flipline);
|
||||
PIPE_CONF_CHECK_I(vrr.pipeline_full);
|
||||
PIPE_CONF_CHECK_I(vrr.guardband);
|
||||
}
|
||||
|
||||
#undef PIPE_CONF_CHECK_X
|
||||
#undef PIPE_CONF_CHECK_I
|
||||
|
|
@ -5420,16 +5457,90 @@ intel_verify_planes(struct intel_atomic_state *state)
|
|||
plane_state->uapi.visible);
|
||||
}
|
||||
|
||||
int intel_modeset_all_pipes(struct intel_atomic_state *state,
|
||||
const char *reason)
|
||||
static int intel_modeset_pipe(struct intel_atomic_state *state,
|
||||
struct intel_crtc_state *crtc_state,
|
||||
const char *reason)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(state->base.dev);
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
int ret;
|
||||
|
||||
drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] Full modeset due to %s\n",
|
||||
crtc->base.base.id, crtc->base.name, reason);
|
||||
|
||||
ret = drm_atomic_add_affected_connectors(&state->base,
|
||||
&crtc->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = intel_dp_mst_add_topology_state_for_crtc(state, crtc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = intel_atomic_add_affected_planes(state, crtc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
crtc_state->uapi.mode_changed = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_modeset_pipes_in_mask_early - force a full modeset on a set of pipes
|
||||
* @state: intel atomic state
|
||||
* @reason: the reason for the full modeset
|
||||
* @mask: mask of pipes to modeset
|
||||
*
|
||||
* Add pipes in @mask to @state and force a full modeset on the enabled ones
|
||||
* due to the description in @reason.
|
||||
* This function can be called only before new plane states are computed.
|
||||
*
|
||||
* Returns 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
|
||||
const char *reason, u8 mask)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(state->base.dev);
|
||||
struct intel_crtc *crtc;
|
||||
|
||||
for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, mask) {
|
||||
struct intel_crtc_state *crtc_state;
|
||||
int ret;
|
||||
|
||||
crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
|
||||
if (IS_ERR(crtc_state))
|
||||
return PTR_ERR(crtc_state);
|
||||
|
||||
if (!crtc_state->hw.enable ||
|
||||
intel_crtc_needs_modeset(crtc_state))
|
||||
continue;
|
||||
|
||||
ret = intel_modeset_pipe(state, crtc_state, reason);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_modeset_all_pipes_late - force a full modeset on all pipes
|
||||
* @state: intel atomic state
|
||||
* @reason: the reason for the full modeset
|
||||
*
|
||||
* Add all pipes to @state and force a full modeset on the active ones due to
|
||||
* the description in @reason.
|
||||
* This function can be called only after new plane states are computed already.
|
||||
*
|
||||
* Returns 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int intel_modeset_all_pipes_late(struct intel_atomic_state *state,
|
||||
const char *reason)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
|
||||
struct intel_crtc *crtc;
|
||||
|
||||
/*
|
||||
* Add all pipes to the state, and force
|
||||
* a modeset on all the active ones.
|
||||
*/
|
||||
for_each_intel_crtc(&dev_priv->drm, crtc) {
|
||||
struct intel_crtc_state *crtc_state;
|
||||
int ret;
|
||||
|
|
@ -5442,25 +5553,13 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state,
|
|||
intel_crtc_needs_modeset(crtc_state))
|
||||
continue;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] Full modeset due to %s\n",
|
||||
crtc->base.base.id, crtc->base.name, reason);
|
||||
ret = intel_modeset_pipe(state, crtc_state, reason);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
crtc_state->uapi.mode_changed = true;
|
||||
crtc_state->update_pipe = false;
|
||||
|
||||
ret = drm_atomic_add_affected_connectors(&state->base,
|
||||
&crtc->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = intel_dp_mst_add_topology_state_for_crtc(state, crtc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = intel_atomic_add_affected_planes(state, crtc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
crtc_state->update_m_n = false;
|
||||
crtc_state->update_lrr = false;
|
||||
crtc_state->update_planes |= crtc_state->active_planes;
|
||||
crtc_state->async_flip_planes = 0;
|
||||
crtc_state->do_async_flip = false;
|
||||
|
|
@ -5564,13 +5663,25 @@ static void intel_crtc_check_fastset(const struct intel_crtc_state *old_crtc_sta
|
|||
{
|
||||
struct drm_i915_private *i915 = to_i915(old_crtc_state->uapi.crtc->dev);
|
||||
|
||||
if (!intel_pipe_config_compare(old_crtc_state, new_crtc_state, true)) {
|
||||
/* only allow LRR when the timings stay within the VRR range */
|
||||
if (old_crtc_state->vrr.in_range != new_crtc_state->vrr.in_range)
|
||||
new_crtc_state->update_lrr = false;
|
||||
|
||||
if (!intel_pipe_config_compare(old_crtc_state, new_crtc_state, true))
|
||||
drm_dbg_kms(&i915->drm, "fastset requirement not met, forcing full modeset\n");
|
||||
else
|
||||
new_crtc_state->uapi.mode_changed = false;
|
||||
|
||||
return;
|
||||
}
|
||||
if (intel_crtc_needs_modeset(new_crtc_state) ||
|
||||
intel_compare_link_m_n(&old_crtc_state->dp_m_n,
|
||||
&new_crtc_state->dp_m_n))
|
||||
new_crtc_state->update_m_n = false;
|
||||
|
||||
if (intel_crtc_needs_modeset(new_crtc_state) ||
|
||||
(old_crtc_state->hw.adjusted_mode.crtc_vtotal == new_crtc_state->hw.adjusted_mode.crtc_vtotal &&
|
||||
old_crtc_state->hw.adjusted_mode.crtc_vblank_end == new_crtc_state->hw.adjusted_mode.crtc_vblank_end))
|
||||
new_crtc_state->update_lrr = false;
|
||||
|
||||
new_crtc_state->uapi.mode_changed = false;
|
||||
if (!intel_crtc_needs_modeset(new_crtc_state))
|
||||
new_crtc_state->update_pipe = true;
|
||||
}
|
||||
|
|
@ -6171,6 +6282,101 @@ static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int intel_atomic_check_config(struct intel_atomic_state *state,
|
||||
struct intel_link_bw_limits *limits,
|
||||
enum pipe *failed_pipe)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(state->base.dev);
|
||||
struct intel_crtc_state *new_crtc_state;
|
||||
struct intel_crtc *crtc;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
*failed_pipe = INVALID_PIPE;
|
||||
|
||||
ret = intel_bigjoiner_add_affected_crtcs(state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = intel_fdi_add_affected_crtcs(state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
|
||||
if (!intel_crtc_needs_modeset(new_crtc_state)) {
|
||||
if (intel_crtc_is_bigjoiner_slave(new_crtc_state))
|
||||
copy_bigjoiner_crtc_state_nomodeset(state, crtc);
|
||||
else
|
||||
intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) {
|
||||
drm_WARN_ON(&i915->drm, new_crtc_state->uapi.enable);
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = intel_crtc_prepare_cleared_state(state, crtc);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
if (!new_crtc_state->hw.enable)
|
||||
continue;
|
||||
|
||||
ret = intel_modeset_pipe_config(state, crtc, limits);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
ret = intel_atomic_check_bigjoiner(state, crtc);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
*failed_pipe = crtc->pipe;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int intel_atomic_check_config_and_link(struct intel_atomic_state *state)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(state->base.dev);
|
||||
struct intel_link_bw_limits new_limits;
|
||||
struct intel_link_bw_limits old_limits;
|
||||
int ret;
|
||||
|
||||
intel_link_bw_init_limits(i915, &new_limits);
|
||||
old_limits = new_limits;
|
||||
|
||||
while (true) {
|
||||
enum pipe failed_pipe;
|
||||
|
||||
ret = intel_atomic_check_config(state, &new_limits,
|
||||
&failed_pipe);
|
||||
if (ret) {
|
||||
/*
|
||||
* The bpp limit for a pipe is below the minimum it supports, set the
|
||||
* limit to the minimum and recalculate the config.
|
||||
*/
|
||||
if (ret == -EINVAL &&
|
||||
intel_link_bw_set_bpp_limit_for_pipe(state,
|
||||
&old_limits,
|
||||
&new_limits,
|
||||
failed_pipe))
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
old_limits = new_limits;
|
||||
|
||||
ret = intel_link_bw_atomic_check(state, &new_limits);
|
||||
if (ret != -EAGAIN)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* intel_atomic_check - validate state object
|
||||
* @dev: drm device
|
||||
|
|
@ -6215,41 +6421,10 @@ int intel_atomic_check(struct drm_device *dev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = intel_bigjoiner_add_affected_crtcs(state);
|
||||
ret = intel_atomic_check_config_and_link(state);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
|
||||
new_crtc_state, i) {
|
||||
if (!intel_crtc_needs_modeset(new_crtc_state)) {
|
||||
if (intel_crtc_is_bigjoiner_slave(new_crtc_state))
|
||||
copy_bigjoiner_crtc_state_nomodeset(state, crtc);
|
||||
else
|
||||
intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) {
|
||||
drm_WARN_ON(&dev_priv->drm, new_crtc_state->uapi.enable);
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = intel_crtc_prepare_cleared_state(state, crtc);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
if (!new_crtc_state->hw.enable)
|
||||
continue;
|
||||
|
||||
ret = intel_modeset_pipe_config(state, crtc);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
ret = intel_atomic_check_bigjoiner(state, crtc);
|
||||
if (ret)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
|
||||
new_crtc_state, i) {
|
||||
if (!intel_crtc_needs_modeset(new_crtc_state))
|
||||
|
|
@ -6285,6 +6460,8 @@ int intel_atomic_check(struct drm_device *dev,
|
|||
if (intel_cpu_transcoders_need_modeset(state, BIT(master))) {
|
||||
new_crtc_state->uapi.mode_changed = true;
|
||||
new_crtc_state->update_pipe = false;
|
||||
new_crtc_state->update_m_n = false;
|
||||
new_crtc_state->update_lrr = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6297,6 +6474,8 @@ int intel_atomic_check(struct drm_device *dev,
|
|||
if (intel_cpu_transcoders_need_modeset(state, trans)) {
|
||||
new_crtc_state->uapi.mode_changed = true;
|
||||
new_crtc_state->update_pipe = false;
|
||||
new_crtc_state->update_m_n = false;
|
||||
new_crtc_state->update_lrr = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6304,6 +6483,8 @@ int intel_atomic_check(struct drm_device *dev,
|
|||
if (intel_pipes_need_modeset(state, new_crtc_state->bigjoiner_pipes)) {
|
||||
new_crtc_state->uapi.mode_changed = true;
|
||||
new_crtc_state->update_pipe = false;
|
||||
new_crtc_state->update_m_n = false;
|
||||
new_crtc_state->update_lrr = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6482,9 +6663,12 @@ static void intel_pipe_fastset(const struct intel_crtc_state *old_crtc_state,
|
|||
IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
|
||||
hsw_set_linetime_wm(new_crtc_state);
|
||||
|
||||
if (new_crtc_state->seamless_m_n)
|
||||
if (new_crtc_state->update_m_n)
|
||||
intel_cpu_transcoder_set_m1_n1(crtc, new_crtc_state->cpu_transcoder,
|
||||
&new_crtc_state->dp_m_n);
|
||||
|
||||
if (new_crtc_state->update_lrr)
|
||||
intel_set_transcoder_timings_lrr(new_crtc_state);
|
||||
}
|
||||
|
||||
static void commit_pipe_pre_planes(struct intel_atomic_state *state,
|
||||
|
|
@ -6521,6 +6705,8 @@ static void commit_pipe_post_planes(struct intel_atomic_state *state,
|
|||
struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
|
||||
const struct intel_crtc_state *old_crtc_state =
|
||||
intel_atomic_get_old_crtc_state(state, crtc);
|
||||
const struct intel_crtc_state *new_crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
|
||||
|
|
@ -6532,6 +6718,9 @@ static void commit_pipe_post_planes(struct intel_atomic_state *state,
|
|||
if (DISPLAY_VER(dev_priv) >= 9 &&
|
||||
!intel_crtc_needs_modeset(new_crtc_state))
|
||||
skl_detach_scalers(new_crtc_state);
|
||||
|
||||
if (vrr_enabling(old_crtc_state, new_crtc_state))
|
||||
intel_vrr_enable(new_crtc_state);
|
||||
}
|
||||
|
||||
static void intel_enable_crtc(struct intel_atomic_state *state,
|
||||
|
|
@ -6572,12 +6761,6 @@ static void intel_update_crtc(struct intel_atomic_state *state,
|
|||
intel_dpt_configure(crtc);
|
||||
}
|
||||
|
||||
if (vrr_enabling(old_crtc_state, new_crtc_state)) {
|
||||
intel_vrr_enable(new_crtc_state);
|
||||
intel_crtc_update_active_timings(new_crtc_state,
|
||||
new_crtc_state->vrr.enable);
|
||||
}
|
||||
|
||||
if (!modeset) {
|
||||
if (new_crtc_state->preload_luts &&
|
||||
intel_crtc_needs_color_update(new_crtc_state))
|
||||
|
|
@ -6591,6 +6774,9 @@ static void intel_update_crtc(struct intel_atomic_state *state,
|
|||
if (DISPLAY_VER(i915) >= 11 &&
|
||||
intel_crtc_needs_fastset(new_crtc_state))
|
||||
icl_set_pipe_chicken(new_crtc_state);
|
||||
|
||||
if (vrr_params_changed(old_crtc_state, new_crtc_state))
|
||||
intel_vrr_set_transcoder_timings(new_crtc_state);
|
||||
}
|
||||
|
||||
intel_fbc_update(state, crtc);
|
||||
|
|
@ -6604,7 +6790,7 @@ static void intel_update_crtc(struct intel_atomic_state *state,
|
|||
intel_crtc_planes_update_noarm(state, crtc);
|
||||
|
||||
/* Perform vblank evasion around commit operation */
|
||||
intel_pipe_update_start(new_crtc_state);
|
||||
intel_pipe_update_start(state, crtc);
|
||||
|
||||
commit_pipe_pre_planes(state, crtc);
|
||||
|
||||
|
|
@ -6612,7 +6798,17 @@ static void intel_update_crtc(struct intel_atomic_state *state,
|
|||
|
||||
commit_pipe_post_planes(state, crtc);
|
||||
|
||||
intel_pipe_update_end(new_crtc_state);
|
||||
intel_pipe_update_end(state, crtc);
|
||||
|
||||
/*
|
||||
* VRR/Seamless M/N update may need to update frame timings.
|
||||
*
|
||||
* FIXME Should be synchronized with the start of vblank somehow...
|
||||
*/
|
||||
if (vrr_enabling(old_crtc_state, new_crtc_state) ||
|
||||
new_crtc_state->update_m_n || new_crtc_state->update_lrr)
|
||||
intel_crtc_update_active_timings(new_crtc_state,
|
||||
new_crtc_state->vrr.enable);
|
||||
|
||||
/*
|
||||
* We usually enable FIFO underrun interrupts as part of the
|
||||
|
|
@ -7072,6 +7268,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
|
|||
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
|
||||
if (new_crtc_state->do_async_flip)
|
||||
intel_crtc_disable_flip_done(state, crtc);
|
||||
|
||||
intel_color_wait_commit(new_crtc_state);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -190,8 +190,6 @@ enum aux_ch {
|
|||
AUX_CH_E_XELPD,
|
||||
};
|
||||
|
||||
#define aux_ch_name(a) ((a) + 'A')
|
||||
|
||||
enum phy {
|
||||
PHY_NONE = -1,
|
||||
|
||||
|
|
@ -513,8 +511,10 @@ void intel_plane_fixup_bitmasks(struct intel_crtc_state *crtc_state);
|
|||
void intel_update_watermarks(struct drm_i915_private *i915);
|
||||
|
||||
/* modesetting */
|
||||
int intel_modeset_all_pipes(struct intel_atomic_state *state,
|
||||
const char *reason);
|
||||
int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
|
||||
const char *reason, u8 pipe_mask);
|
||||
int intel_modeset_all_pipes_late(struct intel_atomic_state *state,
|
||||
const char *reason);
|
||||
void intel_modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state,
|
||||
struct intel_power_domain_mask *old_domains);
|
||||
void intel_modeset_put_crtc_power_domains(struct intel_crtc *crtc,
|
||||
|
|
|
|||
|
|
@ -43,12 +43,16 @@ static int i915_frontbuffer_tracking(struct seq_file *m, void *unused)
|
|||
{
|
||||
struct drm_i915_private *dev_priv = node_to_i915(m->private);
|
||||
|
||||
spin_lock(&dev_priv->display.fb_tracking.lock);
|
||||
|
||||
seq_printf(m, "FB tracking busy bits: 0x%08x\n",
|
||||
dev_priv->display.fb_tracking.busy_bits);
|
||||
|
||||
seq_printf(m, "FB tracking flip bits: 0x%08x\n",
|
||||
dev_priv->display.fb_tracking.flip_bits);
|
||||
|
||||
spin_unlock(&dev_priv->display.fb_tracking.lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -710,18 +710,61 @@ static const struct intel_display_device_info xe_hpd_display = {
|
|||
BIT(PORT_TC1),
|
||||
};
|
||||
|
||||
static const struct intel_display_device_info xe_lpdp_display = {
|
||||
XE_LPD_FEATURES,
|
||||
.has_cdclk_crawl = 1,
|
||||
.has_cdclk_squash = 1,
|
||||
#define XE_LPDP_FEATURES \
|
||||
.abox_mask = GENMASK(1, 0), \
|
||||
.color = { \
|
||||
.degamma_lut_size = 129, .gamma_lut_size = 1024, \
|
||||
.degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING | \
|
||||
DRM_COLOR_LUT_EQUAL_CHANNELS, \
|
||||
}, \
|
||||
.dbuf.size = 4096, \
|
||||
.dbuf.slice_mask = BIT(DBUF_S1) | BIT(DBUF_S2) | BIT(DBUF_S3) | \
|
||||
BIT(DBUF_S4), \
|
||||
.has_cdclk_crawl = 1, \
|
||||
.has_cdclk_squash = 1, \
|
||||
.has_ddi = 1, \
|
||||
.has_dp_mst = 1, \
|
||||
.has_dsb = 1, \
|
||||
.has_fpga_dbg = 1, \
|
||||
.has_hotplug = 1, \
|
||||
.has_ipc = 1, \
|
||||
.has_psr = 1, \
|
||||
.pipe_offsets = { \
|
||||
[TRANSCODER_A] = PIPE_A_OFFSET, \
|
||||
[TRANSCODER_B] = PIPE_B_OFFSET, \
|
||||
[TRANSCODER_C] = PIPE_C_OFFSET, \
|
||||
[TRANSCODER_D] = PIPE_D_OFFSET, \
|
||||
}, \
|
||||
.trans_offsets = { \
|
||||
[TRANSCODER_A] = TRANSCODER_A_OFFSET, \
|
||||
[TRANSCODER_B] = TRANSCODER_B_OFFSET, \
|
||||
[TRANSCODER_C] = TRANSCODER_C_OFFSET, \
|
||||
[TRANSCODER_D] = TRANSCODER_D_OFFSET, \
|
||||
}, \
|
||||
TGL_CURSOR_OFFSETS, \
|
||||
\
|
||||
.__runtime_defaults.cpu_transcoder_mask = \
|
||||
BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \
|
||||
BIT(TRANSCODER_C) | BIT(TRANSCODER_D), \
|
||||
.__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A) | BIT(INTEL_FBC_B), \
|
||||
.__runtime_defaults.has_dmc = 1, \
|
||||
.__runtime_defaults.has_dsc = 1, \
|
||||
.__runtime_defaults.has_hdcp = 1, \
|
||||
.__runtime_defaults.pipe_mask = \
|
||||
BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), \
|
||||
.__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | \
|
||||
BIT(PORT_TC1) | BIT(PORT_TC2) | BIT(PORT_TC3) | BIT(PORT_TC4)
|
||||
|
||||
.__runtime_defaults.ip.ver = 14,
|
||||
.__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A) | BIT(INTEL_FBC_B),
|
||||
.__runtime_defaults.cpu_transcoder_mask =
|
||||
BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
|
||||
BIT(TRANSCODER_C) | BIT(TRANSCODER_D),
|
||||
.__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) |
|
||||
BIT(PORT_TC1) | BIT(PORT_TC2) | BIT(PORT_TC3) | BIT(PORT_TC4),
|
||||
static const struct intel_display_device_info xe_lpdp_display = {
|
||||
XE_LPDP_FEATURES,
|
||||
};
|
||||
|
||||
static const struct intel_display_device_info xe2_lpd_display = {
|
||||
XE_LPDP_FEATURES,
|
||||
|
||||
.__runtime_defaults.fbc_mask =
|
||||
BIT(INTEL_FBC_A) | BIT(INTEL_FBC_B) |
|
||||
BIT(INTEL_FBC_C) | BIT(INTEL_FBC_D),
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -803,6 +846,7 @@ static const struct {
|
|||
const struct intel_display_device_info *display;
|
||||
} gmdid_display_map[] = {
|
||||
{ 14, 0, &xe_lpdp_display },
|
||||
{ 20, 0, &xe2_lpd_display },
|
||||
};
|
||||
|
||||
static const struct intel_display_device_info *
|
||||
|
|
@ -850,16 +894,12 @@ probe_gmdid_display(struct drm_i915_private *i915, u16 *ver, u16 *rel, u16 *step
|
|||
return &no_display;
|
||||
}
|
||||
|
||||
const struct intel_display_device_info *
|
||||
intel_display_device_probe(struct drm_i915_private *i915, bool has_gmdid,
|
||||
u16 *gmdid_ver, u16 *gmdid_rel, u16 *gmdid_step)
|
||||
static const struct intel_display_device_info *
|
||||
probe_display(struct drm_i915_private *i915)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
|
||||
int i;
|
||||
|
||||
if (has_gmdid)
|
||||
return probe_gmdid_display(i915, gmdid_ver, gmdid_rel, gmdid_step);
|
||||
|
||||
if (has_no_display(pdev)) {
|
||||
drm_dbg_kms(&i915->drm, "Device doesn't have display\n");
|
||||
return &no_display;
|
||||
|
|
@ -876,6 +916,29 @@ intel_display_device_probe(struct drm_i915_private *i915, bool has_gmdid,
|
|||
return &no_display;
|
||||
}
|
||||
|
||||
void intel_display_device_probe(struct drm_i915_private *i915)
|
||||
{
|
||||
const struct intel_display_device_info *info;
|
||||
u16 ver, rel, step;
|
||||
|
||||
if (HAS_GMD_ID(i915))
|
||||
info = probe_gmdid_display(i915, &ver, &rel, &step);
|
||||
else
|
||||
info = probe_display(i915);
|
||||
|
||||
i915->display.info.__device_info = info;
|
||||
|
||||
memcpy(DISPLAY_RUNTIME_INFO(i915),
|
||||
&DISPLAY_INFO(i915)->__runtime_defaults,
|
||||
sizeof(*DISPLAY_RUNTIME_INFO(i915)));
|
||||
|
||||
if (HAS_GMD_ID(i915)) {
|
||||
DISPLAY_RUNTIME_INFO(i915)->ip.ver = ver;
|
||||
DISPLAY_RUNTIME_INFO(i915)->ip.rel = rel;
|
||||
DISPLAY_RUNTIME_INFO(i915)->ip.step = step;
|
||||
}
|
||||
}
|
||||
|
||||
void intel_display_device_info_runtime_init(struct drm_i915_private *i915)
|
||||
{
|
||||
struct intel_display_runtime_info *display_runtime = DISPLAY_RUNTIME_INFO(i915);
|
||||
|
|
@ -970,16 +1033,19 @@ void intel_display_device_info_runtime_init(struct drm_i915_private *i915)
|
|||
if (dfsm & SKL_DFSM_PIPE_B_DISABLE) {
|
||||
display_runtime->pipe_mask &= ~BIT(PIPE_B);
|
||||
display_runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_B);
|
||||
display_runtime->fbc_mask &= ~BIT(INTEL_FBC_B);
|
||||
}
|
||||
if (dfsm & SKL_DFSM_PIPE_C_DISABLE) {
|
||||
display_runtime->pipe_mask &= ~BIT(PIPE_C);
|
||||
display_runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_C);
|
||||
display_runtime->fbc_mask &= ~BIT(INTEL_FBC_C);
|
||||
}
|
||||
|
||||
if (DISPLAY_VER(i915) >= 12 &&
|
||||
(dfsm & TGL_DFSM_PIPE_D_DISABLE)) {
|
||||
display_runtime->pipe_mask &= ~BIT(PIPE_D);
|
||||
display_runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_D);
|
||||
display_runtime->fbc_mask &= ~BIT(INTEL_FBC_D);
|
||||
}
|
||||
|
||||
if (!display_runtime->pipe_mask)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ struct drm_printer;
|
|||
func(overlay_needs_physical); \
|
||||
func(supports_tv);
|
||||
|
||||
#define HAS_4TILE(i915) (IS_DG2(i915) || DISPLAY_VER(i915) >= 14)
|
||||
#define HAS_ASYNC_FLIPS(i915) (DISPLAY_VER(i915) >= 5)
|
||||
#define HAS_CDCLK_CRAWL(i915) (DISPLAY_INFO(i915)->has_cdclk_crawl)
|
||||
#define HAS_CDCLK_SQUASH(i915) (DISPLAY_INFO(i915)->has_cdclk_squash)
|
||||
|
|
@ -55,6 +56,7 @@ struct drm_printer;
|
|||
#define HAS_HW_SAGV_WM(i915) (DISPLAY_VER(i915) >= 13 && !IS_DGFX(i915))
|
||||
#define HAS_IPC(i915) (DISPLAY_INFO(i915)->has_ipc)
|
||||
#define HAS_IPS(i915) (IS_HASWELL_ULT(i915) || IS_BROADWELL(i915))
|
||||
#define HAS_LRR(i915) (DISPLAY_VER(i915) >= 12)
|
||||
#define HAS_LSPCON(i915) (IS_DISPLAY_VER(i915, 9, 10))
|
||||
#define HAS_MBUS_JOINING(i915) (IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14)
|
||||
#define HAS_MSO(i915) (DISPLAY_VER(i915) >= 12)
|
||||
|
|
@ -71,6 +73,31 @@ struct drm_printer;
|
|||
#define OVERLAY_NEEDS_PHYSICAL(i915) (DISPLAY_INFO(i915)->overlay_needs_physical)
|
||||
#define SUPPORTS_TV(i915) (DISPLAY_INFO(i915)->supports_tv)
|
||||
|
||||
/* Check that device has a display IP version within the specific range. */
|
||||
#define IS_DISPLAY_IP_RANGE(__i915, from, until) ( \
|
||||
BUILD_BUG_ON_ZERO((from) < IP_VER(2, 0)) + \
|
||||
(DISPLAY_VER_FULL(__i915) >= (from) && \
|
||||
DISPLAY_VER_FULL(__i915) <= (until)))
|
||||
|
||||
/*
|
||||
* Check if a device has a specific IP version as well as a stepping within the
|
||||
* specified range [from, until). The lower bound is inclusive, the upper
|
||||
* bound is exclusive. The most common use-case of this macro is for checking
|
||||
* bounds for workarounds, which usually have a stepping ("from") at which the
|
||||
* hardware issue is first present and another stepping ("until") at which a
|
||||
* hardware fix is present and the software workaround is no longer necessary.
|
||||
* E.g.,
|
||||
*
|
||||
* IS_DISPLAY_IP_STEP(i915, IP_VER(14, 0), STEP_A0, STEP_B2)
|
||||
* IS_DISPLAY_IP_STEP(i915, IP_VER(14, 0), STEP_C0, STEP_FOREVER)
|
||||
*
|
||||
* "STEP_FOREVER" can be passed as "until" for workarounds that have no upper
|
||||
* stepping bound for the specified IP version.
|
||||
*/
|
||||
#define IS_DISPLAY_IP_STEP(__i915, ipver, from, until) \
|
||||
(IS_DISPLAY_IP_RANGE((__i915), (ipver), (ipver)) && \
|
||||
IS_DISPLAY_STEP((__i915), (from), (until)))
|
||||
|
||||
struct intel_display_runtime_info {
|
||||
struct {
|
||||
u16 ver;
|
||||
|
|
@ -123,9 +150,7 @@ struct intel_display_device_info {
|
|||
} color;
|
||||
};
|
||||
|
||||
const struct intel_display_device_info *
|
||||
intel_display_device_probe(struct drm_i915_private *i915, bool has_gmdid,
|
||||
u16 *ver, u16 *rel, u16 *step);
|
||||
void intel_display_device_probe(struct drm_i915_private *i915);
|
||||
void intel_display_device_info_runtime_init(struct drm_i915_private *i915);
|
||||
|
||||
void intel_display_device_info_print(const struct intel_display_device_info *info,
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "intel_display_irq.h"
|
||||
#include "intel_display_power.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_display_wa.h"
|
||||
#include "intel_dkl_phy.h"
|
||||
#include "intel_dmc.h"
|
||||
#include "intel_dp.h"
|
||||
|
|
@ -88,6 +89,8 @@ void intel_display_driver_init_hw(struct drm_i915_private *i915)
|
|||
intel_update_cdclk(i915);
|
||||
intel_cdclk_dump_config(i915, &i915->display.cdclk.hw, "Current CDCLK");
|
||||
cdclk_state->logical = cdclk_state->actual = i915->display.cdclk.hw;
|
||||
|
||||
intel_display_wa_apply(i915);
|
||||
}
|
||||
|
||||
static const struct drm_mode_config_funcs intel_mode_funcs = {
|
||||
|
|
@ -377,6 +380,8 @@ int intel_display_driver_probe(struct drm_i915_private *i915)
|
|||
|
||||
void intel_display_driver_register(struct drm_i915_private *i915)
|
||||
{
|
||||
struct drm_printer p = drm_debug_printer("i915 display info:");
|
||||
|
||||
if (!HAS_DISPLAY(i915))
|
||||
return;
|
||||
|
||||
|
|
@ -404,6 +409,9 @@ void intel_display_driver_register(struct drm_i915_private *i915)
|
|||
* fbdev->async_cookie.
|
||||
*/
|
||||
drm_kms_helper_poll_init(&i915->drm);
|
||||
|
||||
intel_display_device_info_print(DISPLAY_INFO(i915),
|
||||
DISPLAY_RUNTIME_INFO(i915), &p);
|
||||
}
|
||||
|
||||
/* part #1: call before irq uninstall */
|
||||
|
|
|
|||
|
|
@ -792,7 +792,9 @@ static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv)
|
|||
{
|
||||
u32 mask;
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 14)
|
||||
if (DISPLAY_VER(dev_priv) >= 20)
|
||||
return 0;
|
||||
else if (DISPLAY_VER(dev_priv) >= 14)
|
||||
return TGL_DE_PORT_AUX_DDIA |
|
||||
TGL_DE_PORT_AUX_DDIB;
|
||||
else if (DISPLAY_VER(dev_priv) >= 13)
|
||||
|
|
|
|||
|
|
@ -186,8 +186,6 @@ intel_display_power_domain_str(enum intel_display_power_domain domain)
|
|||
return "GMBUS";
|
||||
case POWER_DOMAIN_INIT:
|
||||
return "INIT";
|
||||
case POWER_DOMAIN_MODESET:
|
||||
return "MODESET";
|
||||
case POWER_DOMAIN_GT_IRQ:
|
||||
return "GT_IRQ";
|
||||
case POWER_DOMAIN_DC_OFF:
|
||||
|
|
@ -218,7 +216,7 @@ bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
|
|||
struct i915_power_well *power_well;
|
||||
bool is_enabled;
|
||||
|
||||
if (dev_priv->runtime_pm.suspended)
|
||||
if (pm_runtime_suspended(dev_priv->drm.dev))
|
||||
return false;
|
||||
|
||||
is_enabled = true;
|
||||
|
|
@ -338,8 +336,6 @@ unlock:
|
|||
mutex_unlock(&power_domains->lock);
|
||||
}
|
||||
|
||||
#define POWER_DOMAIN_MASK (GENMASK_ULL(POWER_DOMAIN_NUM - 1, 0))
|
||||
|
||||
static void __async_put_domains_mask(struct i915_power_domains *power_domains,
|
||||
struct intel_power_domain_mask *mask)
|
||||
{
|
||||
|
|
@ -947,7 +943,9 @@ static u32 get_allowed_dc_mask(const struct drm_i915_private *dev_priv,
|
|||
if (!HAS_DISPLAY(dev_priv))
|
||||
return 0;
|
||||
|
||||
if (IS_DG2(dev_priv))
|
||||
if (DISPLAY_VER(dev_priv) >= 20)
|
||||
max_dc = 2;
|
||||
else if (IS_DG2(dev_priv))
|
||||
max_dc = 1;
|
||||
else if (IS_DG1(dev_priv))
|
||||
max_dc = 3;
|
||||
|
|
|
|||
|
|
@ -108,7 +108,6 @@ enum intel_display_power_domain {
|
|||
POWER_DOMAIN_AUX_TBT6,
|
||||
|
||||
POWER_DOMAIN_GMBUS,
|
||||
POWER_DOMAIN_MODESET,
|
||||
POWER_DOMAIN_GT_IRQ,
|
||||
POWER_DOMAIN_DC_OFF,
|
||||
POWER_DOMAIN_TC_COLD_OFF,
|
||||
|
|
|
|||
|
|
@ -332,7 +332,6 @@ I915_DECL_PW_DOMAINS(skl_pwdoms_pw_2,
|
|||
I915_DECL_PW_DOMAINS(skl_pwdoms_dc_off,
|
||||
SKL_PW_2_POWER_DOMAINS,
|
||||
POWER_DOMAIN_AUX_A,
|
||||
POWER_DOMAIN_MODESET,
|
||||
POWER_DOMAIN_GT_IRQ,
|
||||
POWER_DOMAIN_DC_OFF,
|
||||
POWER_DOMAIN_INIT);
|
||||
|
|
@ -437,7 +436,6 @@ I915_DECL_PW_DOMAINS(bxt_pwdoms_dc_off,
|
|||
BXT_PW_2_POWER_DOMAINS,
|
||||
POWER_DOMAIN_AUX_A,
|
||||
POWER_DOMAIN_GMBUS,
|
||||
POWER_DOMAIN_MODESET,
|
||||
POWER_DOMAIN_GT_IRQ,
|
||||
POWER_DOMAIN_DC_OFF,
|
||||
POWER_DOMAIN_INIT);
|
||||
|
|
@ -519,7 +517,6 @@ I915_DECL_PW_DOMAINS(glk_pwdoms_dc_off,
|
|||
GLK_PW_2_POWER_DOMAINS,
|
||||
POWER_DOMAIN_AUX_A,
|
||||
POWER_DOMAIN_GMBUS,
|
||||
POWER_DOMAIN_MODESET,
|
||||
POWER_DOMAIN_GT_IRQ,
|
||||
POWER_DOMAIN_DC_OFF,
|
||||
POWER_DOMAIN_INIT);
|
||||
|
|
@ -685,7 +682,6 @@ I915_DECL_PW_DOMAINS(icl_pwdoms_pw_2,
|
|||
I915_DECL_PW_DOMAINS(icl_pwdoms_dc_off,
|
||||
ICL_PW_2_POWER_DOMAINS,
|
||||
POWER_DOMAIN_AUX_A,
|
||||
POWER_DOMAIN_MODESET,
|
||||
POWER_DOMAIN_DC_OFF,
|
||||
POWER_DOMAIN_INIT);
|
||||
|
||||
|
|
@ -861,7 +857,6 @@ I915_DECL_PW_DOMAINS(tgl_pwdoms_dc_off,
|
|||
POWER_DOMAIN_AUX_A,
|
||||
POWER_DOMAIN_AUX_B,
|
||||
POWER_DOMAIN_AUX_C,
|
||||
POWER_DOMAIN_MODESET,
|
||||
POWER_DOMAIN_DC_OFF,
|
||||
POWER_DOMAIN_INIT);
|
||||
|
||||
|
|
@ -1058,7 +1053,6 @@ I915_DECL_PW_DOMAINS(rkl_pwdoms_dc_off,
|
|||
RKL_PW_3_POWER_DOMAINS,
|
||||
POWER_DOMAIN_AUX_A,
|
||||
POWER_DOMAIN_AUX_B,
|
||||
POWER_DOMAIN_MODESET,
|
||||
POWER_DOMAIN_DC_OFF,
|
||||
POWER_DOMAIN_INIT);
|
||||
|
||||
|
|
@ -1141,7 +1135,6 @@ I915_DECL_PW_DOMAINS(dg1_pwdoms_dc_off,
|
|||
POWER_DOMAIN_AUDIO_MMIO,
|
||||
POWER_DOMAIN_AUX_A,
|
||||
POWER_DOMAIN_AUX_B,
|
||||
POWER_DOMAIN_MODESET,
|
||||
POWER_DOMAIN_DC_OFF,
|
||||
POWER_DOMAIN_INIT);
|
||||
|
||||
|
|
@ -1311,7 +1304,6 @@ I915_DECL_PW_DOMAINS(xelpd_pwdoms_dc_off,
|
|||
POWER_DOMAIN_AUDIO_MMIO,
|
||||
POWER_DOMAIN_AUX_A,
|
||||
POWER_DOMAIN_AUX_B,
|
||||
POWER_DOMAIN_MODESET,
|
||||
POWER_DOMAIN_DC_OFF,
|
||||
POWER_DOMAIN_INIT);
|
||||
|
||||
|
|
@ -1426,7 +1418,6 @@ I915_DECL_PW_DOMAINS(xehpd_pwdoms_dc_off,
|
|||
POWER_DOMAIN_AUDIO_MMIO,
|
||||
POWER_DOMAIN_AUX_A,
|
||||
POWER_DOMAIN_AUX_B,
|
||||
POWER_DOMAIN_MODESET,
|
||||
POWER_DOMAIN_DC_OFF,
|
||||
POWER_DOMAIN_INIT);
|
||||
|
||||
|
|
@ -1545,6 +1536,56 @@ static const struct i915_power_well_desc_list xelpdp_power_wells[] = {
|
|||
I915_PW_DESCRIPTORS(xelpdp_power_wells_main),
|
||||
};
|
||||
|
||||
I915_DECL_PW_DOMAINS(xe2lpd_pwdoms_pica_tc,
|
||||
POWER_DOMAIN_PORT_DDI_LANES_TC1,
|
||||
POWER_DOMAIN_PORT_DDI_LANES_TC2,
|
||||
POWER_DOMAIN_PORT_DDI_LANES_TC3,
|
||||
POWER_DOMAIN_PORT_DDI_LANES_TC4,
|
||||
POWER_DOMAIN_AUX_USBC1,
|
||||
POWER_DOMAIN_AUX_USBC2,
|
||||
POWER_DOMAIN_AUX_USBC3,
|
||||
POWER_DOMAIN_AUX_USBC4,
|
||||
POWER_DOMAIN_AUX_TBT1,
|
||||
POWER_DOMAIN_AUX_TBT2,
|
||||
POWER_DOMAIN_AUX_TBT3,
|
||||
POWER_DOMAIN_AUX_TBT4,
|
||||
POWER_DOMAIN_INIT);
|
||||
|
||||
static const struct i915_power_well_desc xe2lpd_power_wells_pica[] = {
|
||||
{
|
||||
.instances = &I915_PW_INSTANCES(I915_PW("PICA_TC",
|
||||
&xe2lpd_pwdoms_pica_tc,
|
||||
.id = DISP_PW_ID_NONE),
|
||||
),
|
||||
.ops = &xe2lpd_pica_power_well_ops,
|
||||
},
|
||||
};
|
||||
|
||||
I915_DECL_PW_DOMAINS(xe2lpd_pwdoms_dc_off,
|
||||
POWER_DOMAIN_DC_OFF,
|
||||
XELPD_PW_C_POWER_DOMAINS,
|
||||
XELPD_PW_D_POWER_DOMAINS,
|
||||
POWER_DOMAIN_AUDIO_MMIO,
|
||||
POWER_DOMAIN_INIT);
|
||||
|
||||
static const struct i915_power_well_desc xe2lpd_power_wells_dcoff[] = {
|
||||
{
|
||||
.instances = &I915_PW_INSTANCES(
|
||||
I915_PW("DC_off", &xe2lpd_pwdoms_dc_off,
|
||||
.id = SKL_DISP_DC_OFF),
|
||||
),
|
||||
.ops = &gen9_dc_off_power_well_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct i915_power_well_desc_list xe2lpd_power_wells[] = {
|
||||
I915_PW_DESCRIPTORS(i9xx_power_wells_always_on),
|
||||
I915_PW_DESCRIPTORS(icl_power_wells_pw_1),
|
||||
I915_PW_DESCRIPTORS(xe2lpd_power_wells_dcoff),
|
||||
I915_PW_DESCRIPTORS(xelpdp_power_wells_main),
|
||||
I915_PW_DESCRIPTORS(xe2lpd_power_wells_pica),
|
||||
};
|
||||
|
||||
static void init_power_well_domains(const struct i915_power_well_instance *inst,
|
||||
struct i915_power_well *power_well)
|
||||
{
|
||||
|
|
@ -1652,7 +1693,9 @@ int intel_display_power_map_init(struct i915_power_domains *power_domains)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (DISPLAY_VER(i915) >= 14)
|
||||
if (DISPLAY_VER(i915) >= 20)
|
||||
return set_power_wells(power_domains, xe2lpd_power_wells);
|
||||
else if (DISPLAY_VER(i915) >= 14)
|
||||
return set_power_wells(power_domains, xelpdp_power_wells);
|
||||
else if (IS_DG2(i915))
|
||||
return set_power_wells(power_domains, xehpd_power_wells);
|
||||
|
|
|
|||
|
|
@ -1794,8 +1794,13 @@ static void xelpdp_aux_power_well_enable(struct drm_i915_private *dev_priv,
|
|||
struct i915_power_well *power_well)
|
||||
{
|
||||
enum aux_ch aux_ch = i915_power_well_instance(power_well)->xelpdp.aux_ch;
|
||||
enum phy phy = icl_aux_pw_to_phy(dev_priv, power_well);
|
||||
|
||||
intel_de_rmw(dev_priv, XELPDP_DP_AUX_CH_CTL(aux_ch),
|
||||
if (intel_phy_is_tc(dev_priv, phy))
|
||||
icl_tc_port_assert_ref_held(dev_priv, power_well,
|
||||
aux_ch_to_digital_port(dev_priv, aux_ch));
|
||||
|
||||
intel_de_rmw(dev_priv, XELPDP_DP_AUX_CH_CTL(dev_priv, aux_ch),
|
||||
XELPDP_DP_AUX_CH_CTL_POWER_REQUEST,
|
||||
XELPDP_DP_AUX_CH_CTL_POWER_REQUEST);
|
||||
|
||||
|
|
@ -1813,7 +1818,7 @@ static void xelpdp_aux_power_well_disable(struct drm_i915_private *dev_priv,
|
|||
{
|
||||
enum aux_ch aux_ch = i915_power_well_instance(power_well)->xelpdp.aux_ch;
|
||||
|
||||
intel_de_rmw(dev_priv, XELPDP_DP_AUX_CH_CTL(aux_ch),
|
||||
intel_de_rmw(dev_priv, XELPDP_DP_AUX_CH_CTL(dev_priv, aux_ch),
|
||||
XELPDP_DP_AUX_CH_CTL_POWER_REQUEST,
|
||||
0);
|
||||
usleep_range(10, 30);
|
||||
|
|
@ -1824,10 +1829,44 @@ static bool xelpdp_aux_power_well_enabled(struct drm_i915_private *dev_priv,
|
|||
{
|
||||
enum aux_ch aux_ch = i915_power_well_instance(power_well)->xelpdp.aux_ch;
|
||||
|
||||
return intel_de_read(dev_priv, XELPDP_DP_AUX_CH_CTL(aux_ch)) &
|
||||
return intel_de_read(dev_priv, XELPDP_DP_AUX_CH_CTL(dev_priv, aux_ch)) &
|
||||
XELPDP_DP_AUX_CH_CTL_POWER_STATUS;
|
||||
}
|
||||
|
||||
static void xe2lpd_pica_power_well_enable(struct drm_i915_private *dev_priv,
|
||||
struct i915_power_well *power_well)
|
||||
{
|
||||
intel_de_write(dev_priv, XE2LPD_PICA_PW_CTL,
|
||||
XE2LPD_PICA_CTL_POWER_REQUEST);
|
||||
|
||||
if (intel_de_wait_for_set(dev_priv, XE2LPD_PICA_PW_CTL,
|
||||
XE2LPD_PICA_CTL_POWER_STATUS, 1)) {
|
||||
drm_dbg_kms(&dev_priv->drm, "pica power well enable timeout\n");
|
||||
|
||||
drm_WARN(&dev_priv->drm, 1, "Power well PICA timeout when enabled");
|
||||
}
|
||||
}
|
||||
|
||||
static void xe2lpd_pica_power_well_disable(struct drm_i915_private *dev_priv,
|
||||
struct i915_power_well *power_well)
|
||||
{
|
||||
intel_de_write(dev_priv, XE2LPD_PICA_PW_CTL, 0);
|
||||
|
||||
if (intel_de_wait_for_clear(dev_priv, XE2LPD_PICA_PW_CTL,
|
||||
XE2LPD_PICA_CTL_POWER_STATUS, 1)) {
|
||||
drm_dbg_kms(&dev_priv->drm, "pica power well disable timeout\n");
|
||||
|
||||
drm_WARN(&dev_priv->drm, 1, "Power well PICA timeout when disabled");
|
||||
}
|
||||
}
|
||||
|
||||
static bool xe2lpd_pica_power_well_enabled(struct drm_i915_private *dev_priv,
|
||||
struct i915_power_well *power_well)
|
||||
{
|
||||
return intel_de_read(dev_priv, XE2LPD_PICA_PW_CTL) &
|
||||
XE2LPD_PICA_CTL_POWER_STATUS;
|
||||
}
|
||||
|
||||
const struct i915_power_well_ops i9xx_always_on_power_well_ops = {
|
||||
.sync_hw = i9xx_power_well_sync_hw_noop,
|
||||
.enable = i9xx_always_on_power_well_noop,
|
||||
|
|
@ -1947,3 +1986,10 @@ const struct i915_power_well_ops xelpdp_aux_power_well_ops = {
|
|||
.disable = xelpdp_aux_power_well_disable,
|
||||
.is_enabled = xelpdp_aux_power_well_enabled,
|
||||
};
|
||||
|
||||
const struct i915_power_well_ops xe2lpd_pica_power_well_ops = {
|
||||
.sync_hw = i9xx_power_well_sync_hw_noop,
|
||||
.enable = xe2lpd_pica_power_well_enable,
|
||||
.disable = xe2lpd_pica_power_well_disable,
|
||||
.is_enabled = xe2lpd_pica_power_well_enabled,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -176,5 +176,6 @@ extern const struct i915_power_well_ops icl_aux_power_well_ops;
|
|||
extern const struct i915_power_well_ops icl_ddi_power_well_ops;
|
||||
extern const struct i915_power_well_ops tgl_tc_cold_off_ops;
|
||||
extern const struct i915_power_well_ops xelpdp_aux_power_well_ops;
|
||||
extern const struct i915_power_well_ops xe2lpd_pica_power_well_ops;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -500,15 +500,15 @@ struct intel_hdcp_shim {
|
|||
enum hdcp_wired_protocol protocol;
|
||||
|
||||
/* Detects whether sink is HDCP2.2 capable */
|
||||
int (*hdcp_2_2_capable)(struct intel_digital_port *dig_port,
|
||||
int (*hdcp_2_2_capable)(struct intel_connector *connector,
|
||||
bool *capable);
|
||||
|
||||
/* Write HDCP2.2 messages */
|
||||
int (*write_2_2_msg)(struct intel_digital_port *dig_port,
|
||||
int (*write_2_2_msg)(struct intel_connector *connector,
|
||||
void *buf, size_t size);
|
||||
|
||||
/* Read HDCP2.2 messages */
|
||||
int (*read_2_2_msg)(struct intel_digital_port *dig_port,
|
||||
int (*read_2_2_msg)(struct intel_connector *connector,
|
||||
u8 msg_id, void *buf, size_t size);
|
||||
|
||||
/*
|
||||
|
|
@ -516,7 +516,7 @@ struct intel_hdcp_shim {
|
|||
* type to Receivers. In DP HDCP2.2 Stream type is one of the input to
|
||||
* the HDCP2.2 Cipher for En/De-Cryption. Not applicable for HDMI.
|
||||
*/
|
||||
int (*config_stream_type)(struct intel_digital_port *dig_port,
|
||||
int (*config_stream_type)(struct intel_connector *connector,
|
||||
bool is_repeater, u8 type);
|
||||
|
||||
/* Enable/Disable HDCP 2.2 stream encryption on DP MST Transport Link */
|
||||
|
|
@ -1083,6 +1083,8 @@ struct intel_crtc_state {
|
|||
|
||||
unsigned fb_bits; /* framebuffers to flip */
|
||||
bool update_pipe; /* can a fast modeset be performed? */
|
||||
bool update_m_n; /* update M/N seamlessly during fastset? */
|
||||
bool update_lrr; /* update TRANS_VTOTAL/etc. during fastset? */
|
||||
bool disable_cxsr;
|
||||
bool update_wm_pre, update_wm_post; /* watermarks are updated */
|
||||
bool fifo_changed; /* FIFO split is changed */
|
||||
|
|
@ -1189,13 +1191,13 @@ struct intel_crtc_state {
|
|||
u32 ctrl, div;
|
||||
} dsi_pll;
|
||||
|
||||
int pipe_bpp;
|
||||
int max_link_bpp_x16; /* in 1/16 bpp units */
|
||||
int pipe_bpp; /* in 1 bpp units */
|
||||
struct intel_link_m_n dp_m_n;
|
||||
|
||||
/* m2_n2 for eDP downclock */
|
||||
struct intel_link_m_n dp_m2_n2;
|
||||
bool has_drrs;
|
||||
bool seamless_m_n;
|
||||
|
||||
/* PSR is supported but might not be enabled due the lack of enabled planes */
|
||||
bool has_psr;
|
||||
|
|
@ -1362,7 +1364,14 @@ struct intel_crtc_state {
|
|||
u16 linetime;
|
||||
u16 ips_linetime;
|
||||
|
||||
/* Forward Error correction State */
|
||||
bool enhanced_framing;
|
||||
|
||||
/*
|
||||
* Forward Error Correction.
|
||||
*
|
||||
* Note: This will be false for 128b/132b, which will always have FEC
|
||||
* enabled automatically.
|
||||
*/
|
||||
bool fec_enable;
|
||||
|
||||
bool sdp_split_enable;
|
||||
|
|
@ -1383,7 +1392,7 @@ struct intel_crtc_state {
|
|||
|
||||
/* Variable Refresh Rate state */
|
||||
struct {
|
||||
bool enable;
|
||||
bool enable, in_range;
|
||||
u8 pipeline_full;
|
||||
u16 flipline, vmin, vmax, guardband;
|
||||
} vrr;
|
||||
|
|
@ -1581,7 +1590,6 @@ struct intel_watermark_params {
|
|||
|
||||
struct intel_hdmi {
|
||||
i915_reg_t hdmi_reg;
|
||||
int ddc_bus;
|
||||
struct {
|
||||
enum drm_dp_dual_mode_type type;
|
||||
int max_tmds_clock;
|
||||
|
|
@ -2108,4 +2116,27 @@ to_intel_frontbuffer(struct drm_framebuffer *fb)
|
|||
return fb ? to_intel_framebuffer(fb)->frontbuffer : NULL;
|
||||
}
|
||||
|
||||
static inline int to_bpp_int(int bpp_x16)
|
||||
{
|
||||
return bpp_x16 >> 4;
|
||||
}
|
||||
|
||||
static inline int to_bpp_frac(int bpp_x16)
|
||||
{
|
||||
return bpp_x16 & 0xf;
|
||||
}
|
||||
|
||||
#define BPP_X16_FMT "%d.%04d"
|
||||
#define BPP_X16_ARGS(bpp_x16) to_bpp_int(bpp_x16), (to_bpp_frac(bpp_x16) * 625)
|
||||
|
||||
static inline int to_bpp_int_roundup(int bpp_x16)
|
||||
{
|
||||
return (bpp_x16 + 0xf) >> 4;
|
||||
}
|
||||
|
||||
static inline int to_bpp_x16(int bpp)
|
||||
{
|
||||
return bpp << 4;
|
||||
}
|
||||
|
||||
#endif /* __INTEL_DISPLAY_TYPES_H__ */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright © 2023 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_wa.h"
|
||||
|
||||
static void gen11_display_wa_apply(struct drm_i915_private *i915)
|
||||
{
|
||||
/* Wa_1409120013 */
|
||||
intel_de_write(i915, ILK_DPFC_CHICKEN(INTEL_FBC_A),
|
||||
DPFC_CHICKEN_COMP_DUMMY_PIXEL);
|
||||
|
||||
/* Wa_14010594013 */
|
||||
intel_de_rmw(i915, GEN8_CHICKEN_DCPR_1, 0, ICL_DELAY_PMRSP);
|
||||
}
|
||||
|
||||
static void xe_d_display_wa_apply(struct drm_i915_private *i915)
|
||||
{
|
||||
/* Wa_1409120013 */
|
||||
intel_de_write(i915, ILK_DPFC_CHICKEN(INTEL_FBC_A),
|
||||
DPFC_CHICKEN_COMP_DUMMY_PIXEL);
|
||||
|
||||
/* Wa_14013723622 */
|
||||
intel_de_rmw(i915, CLKREQ_POLICY, CLKREQ_POLICY_MEM_UP_OVRD, 0);
|
||||
}
|
||||
|
||||
static void adlp_display_wa_apply(struct drm_i915_private *i915)
|
||||
{
|
||||
/* Wa_22011091694:adlp */
|
||||
intel_de_rmw(i915, GEN9_CLKGATE_DIS_5, 0, DPCE_GATING_DIS);
|
||||
|
||||
/* Bspec/49189 Initialize Sequence */
|
||||
intel_de_rmw(i915, GEN8_CHICKEN_DCPR_1, DDI_CLOCK_REG_ACCESS, 0);
|
||||
}
|
||||
|
||||
void intel_display_wa_apply(struct drm_i915_private *i915)
|
||||
{
|
||||
if (IS_ALDERLAKE_P(i915))
|
||||
adlp_display_wa_apply(i915);
|
||||
else if (DISPLAY_VER(i915) == 12)
|
||||
xe_d_display_wa_apply(i915);
|
||||
else if (DISPLAY_VER(i915) == 11)
|
||||
gen11_display_wa_apply(i915);
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2023 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_DISPLAY_WA_H__
|
||||
#define __INTEL_DISPLAY_WA_H__
|
||||
|
||||
struct drm_i915_private;
|
||||
|
||||
void intel_display_wa_apply(struct drm_i915_private *i915);
|
||||
|
||||
#endif
|
||||
|
|
@ -998,7 +998,7 @@ void intel_dmc_init(struct drm_i915_private *i915)
|
|||
|
||||
INIT_WORK(&dmc->work, dmc_load_work_fn);
|
||||
|
||||
if (IS_METEORLAKE(i915)) {
|
||||
if (DISPLAY_VER_FULL(i915) == IP_VER(14, 0)) {
|
||||
dmc->fw_path = MTL_DMC_PATH;
|
||||
dmc->max_fw_size = XELPDP_DMC_MAX_FW_SIZE;
|
||||
} else if (IS_DG2(i915)) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -26,7 +26,14 @@ struct intel_encoder;
|
|||
struct link_config_limits {
|
||||
int min_rate, max_rate;
|
||||
int min_lane_count, max_lane_count;
|
||||
int min_bpp, max_bpp;
|
||||
struct {
|
||||
/* Uncompressed DSC input or link output bpp in 1 bpp units */
|
||||
int min_bpp, max_bpp;
|
||||
} pipe;
|
||||
struct {
|
||||
/* Compressed or uncompressed link output bpp in 1/16 bpp units */
|
||||
int min_bpp_x16, max_bpp_x16;
|
||||
} link;
|
||||
};
|
||||
|
||||
void intel_edp_fixup_vbt_bpp(struct intel_encoder *encoder, int pipe_bpp);
|
||||
|
|
@ -65,6 +72,9 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
|
|||
struct link_config_limits *limits,
|
||||
int timeslots,
|
||||
bool recompute_pipe_bpp);
|
||||
void intel_dp_audio_compute_config(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config,
|
||||
struct drm_connector_state *conn_state);
|
||||
bool intel_dp_has_hdmi_sink(struct intel_dp *intel_dp);
|
||||
bool intel_dp_is_edp(struct intel_dp *intel_dp);
|
||||
bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state);
|
||||
|
|
@ -106,13 +116,14 @@ 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);
|
||||
int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc);
|
||||
u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915,
|
||||
u32 link_clock, u32 lane_count,
|
||||
u32 mode_clock, u32 mode_hdisplay,
|
||||
bool bigjoiner,
|
||||
u32 pipe_bpp,
|
||||
u32 timeslots);
|
||||
int intel_dp_dsc_compute_max_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc);
|
||||
u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
|
||||
u32 link_clock, u32 lane_count,
|
||||
u32 mode_clock, u32 mode_hdisplay,
|
||||
bool bigjoiner,
|
||||
enum intel_output_format output_format,
|
||||
u32 pipe_bpp,
|
||||
u32 timeslots);
|
||||
u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
|
||||
int mode_clock, int mode_hdisplay,
|
||||
bool bigjoiner);
|
||||
|
|
@ -143,5 +154,12 @@ void intel_dp_pcon_dsc_configure(struct intel_dp *intel_dp,
|
|||
void intel_dp_phy_test(struct intel_encoder *encoder);
|
||||
|
||||
void intel_dp_wait_source_oui(struct intel_dp *intel_dp);
|
||||
int intel_dp_output_bpp(enum intel_output_format output_format, int bpp);
|
||||
|
||||
bool
|
||||
intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
bool dsc,
|
||||
struct link_config_limits *limits);
|
||||
|
||||
#endif /* __INTEL_DP_H__ */
|
||||
|
|
|
|||
|
|
@ -14,6 +14,21 @@
|
|||
#include "intel_pps.h"
|
||||
#include "intel_tc.h"
|
||||
|
||||
#define AUX_CH_NAME_BUFSIZE 6
|
||||
|
||||
static const char *aux_ch_name(struct drm_i915_private *i915,
|
||||
char *buf, int size, enum aux_ch aux_ch)
|
||||
{
|
||||
if (DISPLAY_VER(i915) >= 13 && aux_ch >= AUX_CH_D_XELPD)
|
||||
snprintf(buf, size, "%c", 'A' + aux_ch - AUX_CH_D_XELPD + AUX_CH_D);
|
||||
else if (DISPLAY_VER(i915) >= 12 && aux_ch >= AUX_CH_USBC1)
|
||||
snprintf(buf, size, "USBC%c", '1' + aux_ch - AUX_CH_USBC1);
|
||||
else
|
||||
snprintf(buf, size, "%c", 'A' + aux_ch);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
u32 intel_dp_aux_pack(const u8 *src, int src_bytes)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -687,10 +702,10 @@ static i915_reg_t xelpdp_aux_ctl_reg(struct intel_dp *intel_dp)
|
|||
case AUX_CH_USBC2:
|
||||
case AUX_CH_USBC3:
|
||||
case AUX_CH_USBC4:
|
||||
return XELPDP_DP_AUX_CH_CTL(aux_ch);
|
||||
return XELPDP_DP_AUX_CH_CTL(dev_priv, aux_ch);
|
||||
default:
|
||||
MISSING_CASE(aux_ch);
|
||||
return XELPDP_DP_AUX_CH_CTL(AUX_CH_A);
|
||||
return XELPDP_DP_AUX_CH_CTL(dev_priv, AUX_CH_A);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -707,10 +722,10 @@ static i915_reg_t xelpdp_aux_data_reg(struct intel_dp *intel_dp, int index)
|
|||
case AUX_CH_USBC2:
|
||||
case AUX_CH_USBC3:
|
||||
case AUX_CH_USBC4:
|
||||
return XELPDP_DP_AUX_CH_DATA(aux_ch, index);
|
||||
return XELPDP_DP_AUX_CH_DATA(dev_priv, aux_ch, index);
|
||||
default:
|
||||
MISSING_CASE(aux_ch);
|
||||
return XELPDP_DP_AUX_CH_DATA(AUX_CH_A, index);
|
||||
return XELPDP_DP_AUX_CH_DATA(dev_priv, AUX_CH_A, index);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -728,6 +743,7 @@ void intel_dp_aux_init(struct intel_dp *intel_dp)
|
|||
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
|
||||
struct intel_encoder *encoder = &dig_port->base;
|
||||
enum aux_ch aux_ch = dig_port->aux_ch;
|
||||
char buf[AUX_CH_NAME_BUFSIZE];
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 14) {
|
||||
intel_dp->aux_ch_ctl_reg = xelpdp_aux_ctl_reg;
|
||||
|
|
@ -764,18 +780,9 @@ void intel_dp_aux_init(struct intel_dp *intel_dp)
|
|||
drm_dp_aux_init(&intel_dp->aux);
|
||||
|
||||
/* Failure to allocate our preferred name is not critical */
|
||||
if (DISPLAY_VER(dev_priv) >= 13 && aux_ch >= AUX_CH_D_XELPD)
|
||||
intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX %c/%s",
|
||||
aux_ch_name(aux_ch - AUX_CH_D_XELPD + AUX_CH_D),
|
||||
encoder->base.name);
|
||||
else if (DISPLAY_VER(dev_priv) >= 12 && aux_ch >= AUX_CH_USBC1)
|
||||
intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX USBC%c/%s",
|
||||
aux_ch - AUX_CH_USBC1 + '1',
|
||||
encoder->base.name);
|
||||
else
|
||||
intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX %c/%s",
|
||||
aux_ch_name(aux_ch),
|
||||
encoder->base.name);
|
||||
intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX %s/%s",
|
||||
aux_ch_name(dev_priv, buf, sizeof(buf), aux_ch),
|
||||
encoder->base.name);
|
||||
|
||||
intel_dp->aux.transfer = intel_dp_aux_transfer;
|
||||
cpu_latency_qos_add_request(&intel_dp->pm_qos, PM_QOS_DEFAULT_VALUE);
|
||||
|
|
@ -819,6 +826,7 @@ enum aux_ch intel_dp_aux_ch(struct intel_encoder *encoder)
|
|||
struct intel_encoder *other;
|
||||
const char *source;
|
||||
enum aux_ch aux_ch;
|
||||
char buf[AUX_CH_NAME_BUFSIZE];
|
||||
|
||||
aux_ch = intel_bios_dp_aux_ch(encoder->devdata);
|
||||
source = "VBT";
|
||||
|
|
@ -836,16 +844,17 @@ enum aux_ch intel_dp_aux_ch(struct intel_encoder *encoder)
|
|||
other = get_encoder_by_aux_ch(encoder, aux_ch);
|
||||
if (other) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"[ENCODER:%d:%s] AUX CH %c already claimed by [ENCODER:%d:%s]\n",
|
||||
encoder->base.base.id, encoder->base.name, aux_ch_name(aux_ch),
|
||||
"[ENCODER:%d:%s] AUX CH %s already claimed by [ENCODER:%d:%s]\n",
|
||||
encoder->base.base.id, encoder->base.name,
|
||||
aux_ch_name(i915, buf, sizeof(buf), aux_ch),
|
||||
other->base.base.id, other->base.name);
|
||||
return AUX_CH_NONE;
|
||||
}
|
||||
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"[ENCODER:%d:%s] Using AUX CH %c (%s)\n",
|
||||
"[ENCODER:%d:%s] Using AUX CH %s (%s)\n",
|
||||
encoder->base.base.id, encoder->base.name,
|
||||
aux_ch_name(aux_ch), source);
|
||||
aux_ch_name(i915, buf, sizeof(buf), aux_ch), source);
|
||||
|
||||
return aux_ch;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,48 +13,34 @@
|
|||
* packet size supported is 20 bytes in each direction, hence the 5 fixed data
|
||||
* registers
|
||||
*/
|
||||
#define _DPA_AUX_CH_CTL (DISPLAY_MMIO_BASE(dev_priv) + 0x64010)
|
||||
#define _DPA_AUX_CH_DATA1 (DISPLAY_MMIO_BASE(dev_priv) + 0x64014)
|
||||
|
||||
#define _DPB_AUX_CH_CTL (DISPLAY_MMIO_BASE(dev_priv) + 0x64110)
|
||||
#define _DPB_AUX_CH_DATA1 (DISPLAY_MMIO_BASE(dev_priv) + 0x64114)
|
||||
|
||||
#define DP_AUX_CH_CTL(aux_ch) _MMIO_PORT(aux_ch, _DPA_AUX_CH_CTL, _DPB_AUX_CH_CTL)
|
||||
#define DP_AUX_CH_DATA(aux_ch, i) _MMIO(_PORT(aux_ch, _DPA_AUX_CH_DATA1, _DPB_AUX_CH_DATA1) + (i) * 4) /* 5 registers */
|
||||
|
||||
#define _XELPDP_USBC1_AUX_CH_CTL 0x16F210
|
||||
#define _XELPDP_USBC2_AUX_CH_CTL 0x16F410
|
||||
#define _XELPDP_USBC3_AUX_CH_CTL 0x16F610
|
||||
#define _XELPDP_USBC4_AUX_CH_CTL 0x16F810
|
||||
|
||||
#define XELPDP_DP_AUX_CH_CTL(aux_ch) _MMIO(_PICK(aux_ch, \
|
||||
_DPA_AUX_CH_CTL, \
|
||||
_DPB_AUX_CH_CTL, \
|
||||
0, /* port/aux_ch C is non-existent */ \
|
||||
_XELPDP_USBC1_AUX_CH_CTL, \
|
||||
_XELPDP_USBC2_AUX_CH_CTL, \
|
||||
_XELPDP_USBC3_AUX_CH_CTL, \
|
||||
_XELPDP_USBC4_AUX_CH_CTL))
|
||||
|
||||
#define _XELPDP_USBC1_AUX_CH_DATA1 0x16F214
|
||||
#define _XELPDP_USBC2_AUX_CH_DATA1 0x16F414
|
||||
#define _XELPDP_USBC3_AUX_CH_DATA1 0x16F614
|
||||
#define _XELPDP_USBC4_AUX_CH_DATA1 0x16F814
|
||||
|
||||
#define XELPDP_DP_AUX_CH_DATA(aux_ch, i) _MMIO(_PICK(aux_ch, \
|
||||
_DPA_AUX_CH_DATA1, \
|
||||
_DPB_AUX_CH_DATA1, \
|
||||
0, /* port/aux_ch C is non-existent */ \
|
||||
_XELPDP_USBC1_AUX_CH_DATA1, \
|
||||
_XELPDP_USBC2_AUX_CH_DATA1, \
|
||||
_XELPDP_USBC3_AUX_CH_DATA1, \
|
||||
_XELPDP_USBC4_AUX_CH_DATA1) + (i) * 4)
|
||||
/*
|
||||
* Wrapper macro to convert from aux_ch to the index used in some of the
|
||||
* registers.
|
||||
*/
|
||||
#define __xe2lpd_aux_ch_idx(aux_ch) \
|
||||
(aux_ch >= AUX_CH_USBC1 ? aux_ch : AUX_CH_USBC4 + 1 + (aux_ch) - AUX_CH_A)
|
||||
|
||||
/* TODO: Remove implicit dev_priv */
|
||||
#define _DPA_AUX_CH_CTL (DISPLAY_MMIO_BASE(dev_priv) + 0x64010)
|
||||
#define _DPB_AUX_CH_CTL (DISPLAY_MMIO_BASE(dev_priv) + 0x64110)
|
||||
#define _XELPDP_USBC1_AUX_CH_CTL 0x16f210
|
||||
#define _XELPDP_USBC2_AUX_CH_CTL 0x16f410
|
||||
#define DP_AUX_CH_CTL(aux_ch) _MMIO_PORT(aux_ch, _DPA_AUX_CH_CTL, \
|
||||
_DPB_AUX_CH_CTL)
|
||||
#define _XELPDP_DP_AUX_CH_CTL(aux_ch) \
|
||||
_MMIO(_PICK_EVEN_2RANGES(aux_ch, AUX_CH_USBC1, \
|
||||
_DPA_AUX_CH_CTL, _DPB_AUX_CH_CTL, \
|
||||
_XELPDP_USBC1_AUX_CH_CTL, \
|
||||
_XELPDP_USBC2_AUX_CH_CTL))
|
||||
#define XELPDP_DP_AUX_CH_CTL(i915__, aux_ch) \
|
||||
(DISPLAY_VER(i915__) >= 20 ? \
|
||||
_XELPDP_DP_AUX_CH_CTL(__xe2lpd_aux_ch_idx(aux_ch)) : \
|
||||
_XELPDP_DP_AUX_CH_CTL(aux_ch))
|
||||
#define DP_AUX_CH_CTL_SEND_BUSY REG_BIT(31)
|
||||
#define DP_AUX_CH_CTL_DONE REG_BIT(30)
|
||||
#define DP_AUX_CH_CTL_INTERRUPT REG_BIT(29)
|
||||
#define DP_AUX_CH_CTL_TIME_OUT_ERROR REG_BIT(28)
|
||||
|
||||
#define DP_AUX_CH_CTL_TIME_OUT_MASK REG_GENMASK(27, 26)
|
||||
#define DP_AUX_CH_CTL_TIME_OUT_400us REG_FIELD_PREP(DP_AUX_CH_CTL_TIME_OUT_MASK, 0)
|
||||
#define DP_AUX_CH_CTL_TIME_OUT_600us REG_FIELD_PREP(DP_AUX_CH_CTL_TIME_OUT_MASK, 1)
|
||||
|
|
@ -83,4 +69,26 @@
|
|||
#define DP_AUX_CH_CTL_SYNC_PULSE_SKL_MASK REG_GENMASK(4, 0) /* skl+ */
|
||||
#define DP_AUX_CH_CTL_SYNC_PULSE_SKL(c) REG_FIELD_PREP(DP_AUX_CH_CTL_SYNC_PULSE_SKL_MASK, (c) - 1)
|
||||
|
||||
/* TODO: Remove implicit dev_priv */
|
||||
#define _DPA_AUX_CH_DATA1 (DISPLAY_MMIO_BASE(dev_priv) + 0x64014)
|
||||
#define _DPB_AUX_CH_DATA1 (DISPLAY_MMIO_BASE(dev_priv) + 0x64114)
|
||||
#define _XELPDP_USBC1_AUX_CH_DATA1 0x16f214
|
||||
#define _XELPDP_USBC2_AUX_CH_DATA1 0x16f414
|
||||
#define DP_AUX_CH_DATA(aux_ch, i) _MMIO(_PORT(aux_ch, _DPA_AUX_CH_DATA1, \
|
||||
_DPB_AUX_CH_DATA1) + (i) * 4) /* 5 registers */
|
||||
#define _XELPDP_DP_AUX_CH_DATA(aux_ch, i) \
|
||||
_MMIO(_PICK_EVEN_2RANGES(aux_ch, AUX_CH_USBC1, \
|
||||
_DPA_AUX_CH_DATA1, _DPB_AUX_CH_DATA1, \
|
||||
_XELPDP_USBC1_AUX_CH_DATA1, \
|
||||
_XELPDP_USBC2_AUX_CH_DATA1) + (i) * 4) /* 5 registers */
|
||||
#define XELPDP_DP_AUX_CH_DATA(i915__, aux_ch, i) \
|
||||
(DISPLAY_VER(i915__) >= 20 ? \
|
||||
_XELPDP_DP_AUX_CH_DATA(__xe2lpd_aux_ch_idx(aux_ch), i) : \
|
||||
_XELPDP_DP_AUX_CH_DATA(aux_ch, i))
|
||||
|
||||
/* PICA Power Well Control */
|
||||
#define XE2LPD_PICA_PW_CTL _MMIO(0x16fe04)
|
||||
#define XE2LPD_PICA_CTL_POWER_REQUEST REG_BIT(31)
|
||||
#define XE2LPD_PICA_CTL_POWER_STATUS REG_BIT(30)
|
||||
|
||||
#endif /* __INTEL_DP_AUX_REGS_H__ */
|
||||
|
|
|
|||
|
|
@ -330,14 +330,26 @@ static const struct hdcp2_dp_msg_data hdcp2_dp_msg_data[] = {
|
|||
0, 0 },
|
||||
};
|
||||
|
||||
static struct drm_dp_aux *
|
||||
intel_dp_hdcp_get_aux(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
|
||||
|
||||
if (intel_encoder_is_mst(connector->encoder))
|
||||
return &connector->port->aux;
|
||||
else
|
||||
return &dig_port->dp.aux;
|
||||
}
|
||||
|
||||
static int
|
||||
intel_dp_hdcp2_read_rx_status(struct intel_digital_port *dig_port,
|
||||
intel_dp_hdcp2_read_rx_status(struct intel_connector *connector,
|
||||
u8 *rx_status)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
struct drm_dp_aux *aux = intel_dp_hdcp_get_aux(connector);
|
||||
ssize_t ret;
|
||||
|
||||
ret = drm_dp_dpcd_read(&dig_port->dp.aux,
|
||||
ret = drm_dp_dpcd_read(aux,
|
||||
DP_HDCP_2_2_REG_RXSTATUS_OFFSET, rx_status,
|
||||
HDCP_2_2_DP_RXSTATUS_LEN);
|
||||
if (ret != HDCP_2_2_DP_RXSTATUS_LEN) {
|
||||
|
|
@ -350,14 +362,14 @@ intel_dp_hdcp2_read_rx_status(struct intel_digital_port *dig_port,
|
|||
}
|
||||
|
||||
static
|
||||
int hdcp2_detect_msg_availability(struct intel_digital_port *dig_port,
|
||||
int hdcp2_detect_msg_availability(struct intel_connector *connector,
|
||||
u8 msg_id, bool *msg_ready)
|
||||
{
|
||||
u8 rx_status;
|
||||
int ret;
|
||||
|
||||
*msg_ready = false;
|
||||
ret = intel_dp_hdcp2_read_rx_status(dig_port, &rx_status);
|
||||
ret = intel_dp_hdcp2_read_rx_status(connector, &rx_status);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
@ -383,12 +395,11 @@ int hdcp2_detect_msg_availability(struct intel_digital_port *dig_port,
|
|||
}
|
||||
|
||||
static ssize_t
|
||||
intel_dp_hdcp2_wait_for_msg(struct intel_digital_port *dig_port,
|
||||
intel_dp_hdcp2_wait_for_msg(struct intel_connector *connector,
|
||||
const struct hdcp2_dp_msg_data *hdcp2_msg_data)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
|
||||
struct intel_dp *dp = &dig_port->dp;
|
||||
struct intel_hdcp *hdcp = &dp->attached_connector->hdcp;
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
struct intel_hdcp *hdcp = &connector->hdcp;
|
||||
u8 msg_id = hdcp2_msg_data->msg_id;
|
||||
int ret, timeout;
|
||||
bool msg_ready = false;
|
||||
|
|
@ -411,8 +422,8 @@ intel_dp_hdcp2_wait_for_msg(struct intel_digital_port *dig_port,
|
|||
* the timeout at wait for CP_IRQ.
|
||||
*/
|
||||
intel_dp_hdcp_wait_for_cp_irq(hdcp, timeout);
|
||||
ret = hdcp2_detect_msg_availability(dig_port,
|
||||
msg_id, &msg_ready);
|
||||
ret = hdcp2_detect_msg_availability(connector, msg_id,
|
||||
&msg_ready);
|
||||
if (!msg_ready)
|
||||
ret = -ETIMEDOUT;
|
||||
}
|
||||
|
|
@ -437,13 +448,14 @@ static const struct hdcp2_dp_msg_data *get_hdcp2_dp_msg_data(u8 msg_id)
|
|||
}
|
||||
|
||||
static
|
||||
int intel_dp_hdcp2_write_msg(struct intel_digital_port *dig_port,
|
||||
int intel_dp_hdcp2_write_msg(struct intel_connector *connector,
|
||||
void *buf, size_t size)
|
||||
{
|
||||
unsigned int offset;
|
||||
u8 *byte = buf;
|
||||
ssize_t ret, bytes_to_write, len;
|
||||
const struct hdcp2_dp_msg_data *hdcp2_msg_data;
|
||||
struct drm_dp_aux *aux;
|
||||
|
||||
hdcp2_msg_data = get_hdcp2_dp_msg_data(*byte);
|
||||
if (!hdcp2_msg_data)
|
||||
|
|
@ -451,6 +463,8 @@ int intel_dp_hdcp2_write_msg(struct intel_digital_port *dig_port,
|
|||
|
||||
offset = hdcp2_msg_data->offset;
|
||||
|
||||
aux = intel_dp_hdcp_get_aux(connector);
|
||||
|
||||
/* No msg_id in DP HDCP2.2 msgs */
|
||||
bytes_to_write = size - 1;
|
||||
byte++;
|
||||
|
|
@ -459,7 +473,7 @@ int intel_dp_hdcp2_write_msg(struct intel_digital_port *dig_port,
|
|||
len = bytes_to_write > DP_AUX_MAX_PAYLOAD_BYTES ?
|
||||
DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_write;
|
||||
|
||||
ret = drm_dp_dpcd_write(&dig_port->dp.aux,
|
||||
ret = drm_dp_dpcd_write(aux,
|
||||
offset, (void *)byte, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
@ -473,12 +487,14 @@ int intel_dp_hdcp2_write_msg(struct intel_digital_port *dig_port,
|
|||
}
|
||||
|
||||
static
|
||||
ssize_t get_receiver_id_list_rx_info(struct intel_digital_port *dig_port, u32 *dev_cnt, u8 *byte)
|
||||
ssize_t get_receiver_id_list_rx_info(struct intel_connector *connector,
|
||||
u32 *dev_cnt, u8 *byte)
|
||||
{
|
||||
struct drm_dp_aux *aux = intel_dp_hdcp_get_aux(connector);
|
||||
ssize_t ret;
|
||||
u8 *rx_info = byte;
|
||||
|
||||
ret = drm_dp_dpcd_read(&dig_port->dp.aux,
|
||||
ret = drm_dp_dpcd_read(aux,
|
||||
DP_HDCP_2_2_REG_RXINFO_OFFSET,
|
||||
(void *)rx_info, HDCP_2_2_RXINFO_LEN);
|
||||
if (ret != HDCP_2_2_RXINFO_LEN)
|
||||
|
|
@ -494,12 +510,13 @@ ssize_t get_receiver_id_list_rx_info(struct intel_digital_port *dig_port, u32 *d
|
|||
}
|
||||
|
||||
static
|
||||
int intel_dp_hdcp2_read_msg(struct intel_digital_port *dig_port,
|
||||
int intel_dp_hdcp2_read_msg(struct intel_connector *connector,
|
||||
u8 msg_id, void *buf, size_t size)
|
||||
{
|
||||
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
|
||||
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
|
||||
struct intel_dp *dp = &dig_port->dp;
|
||||
struct intel_hdcp *hdcp = &dp->attached_connector->hdcp;
|
||||
struct intel_hdcp *hdcp = &connector->hdcp;
|
||||
struct drm_dp_aux *aux;
|
||||
unsigned int offset;
|
||||
u8 *byte = buf;
|
||||
ssize_t ret, bytes_to_recv, len;
|
||||
|
|
@ -513,7 +530,9 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port *dig_port,
|
|||
return -EINVAL;
|
||||
offset = hdcp2_msg_data->offset;
|
||||
|
||||
ret = intel_dp_hdcp2_wait_for_msg(dig_port, hdcp2_msg_data);
|
||||
aux = intel_dp_hdcp_get_aux(connector);
|
||||
|
||||
ret = intel_dp_hdcp2_wait_for_msg(connector, hdcp2_msg_data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
@ -523,7 +542,7 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port *dig_port,
|
|||
byte++;
|
||||
|
||||
if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST) {
|
||||
ret = get_receiver_id_list_rx_info(dig_port, &dev_cnt, byte);
|
||||
ret = get_receiver_id_list_rx_info(connector, &dev_cnt, byte);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
@ -541,11 +560,17 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port *dig_port,
|
|||
DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_recv;
|
||||
|
||||
/* Entire msg read timeout since initiate of msg read */
|
||||
if (bytes_to_recv == size - 1 && hdcp2_msg_data->msg_read_timeout > 0)
|
||||
msg_end = ktime_add_ms(ktime_get_raw(),
|
||||
hdcp2_msg_data->msg_read_timeout);
|
||||
if (bytes_to_recv == size - 1 && hdcp2_msg_data->msg_read_timeout > 0) {
|
||||
if (intel_encoder_is_mst(connector->encoder))
|
||||
msg_end = ktime_add_ms(ktime_get_raw(),
|
||||
hdcp2_msg_data->msg_read_timeout *
|
||||
connector->port->parent->num_ports);
|
||||
else
|
||||
msg_end = ktime_add_ms(ktime_get_raw(),
|
||||
hdcp2_msg_data->msg_read_timeout);
|
||||
}
|
||||
|
||||
ret = drm_dp_dpcd_read(&dig_port->dp.aux, offset,
|
||||
ret = drm_dp_dpcd_read(aux, offset,
|
||||
(void *)byte, len);
|
||||
if (ret < 0) {
|
||||
drm_dbg_kms(&i915->drm, "msg_id %d, ret %zd\n",
|
||||
|
|
@ -574,7 +599,7 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port *dig_port,
|
|||
}
|
||||
|
||||
static
|
||||
int intel_dp_hdcp2_config_stream_type(struct intel_digital_port *dig_port,
|
||||
int intel_dp_hdcp2_config_stream_type(struct intel_connector *connector,
|
||||
bool is_repeater, u8 content_type)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -593,7 +618,7 @@ int intel_dp_hdcp2_config_stream_type(struct intel_digital_port *dig_port,
|
|||
stream_type_msg.msg_id = HDCP_2_2_ERRATA_DP_STREAM_TYPE;
|
||||
stream_type_msg.stream_type = content_type;
|
||||
|
||||
ret = intel_dp_hdcp2_write_msg(dig_port, &stream_type_msg,
|
||||
ret = intel_dp_hdcp2_write_msg(connector, &stream_type_msg,
|
||||
sizeof(stream_type_msg));
|
||||
|
||||
return ret < 0 ? ret : 0;
|
||||
|
|
@ -607,7 +632,8 @@ int intel_dp_hdcp2_check_link(struct intel_digital_port *dig_port,
|
|||
u8 rx_status;
|
||||
int ret;
|
||||
|
||||
ret = intel_dp_hdcp2_read_rx_status(dig_port, &rx_status);
|
||||
ret = intel_dp_hdcp2_read_rx_status(connector,
|
||||
&rx_status);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -622,14 +648,17 @@ int intel_dp_hdcp2_check_link(struct intel_digital_port *dig_port,
|
|||
}
|
||||
|
||||
static
|
||||
int intel_dp_hdcp2_capable(struct intel_digital_port *dig_port,
|
||||
int intel_dp_hdcp2_capable(struct intel_connector *connector,
|
||||
bool *capable)
|
||||
{
|
||||
struct drm_dp_aux *aux;
|
||||
u8 rx_caps[3];
|
||||
int ret;
|
||||
|
||||
aux = intel_dp_hdcp_get_aux(connector);
|
||||
|
||||
*capable = false;
|
||||
ret = drm_dp_dpcd_read(&dig_port->dp.aux,
|
||||
ret = drm_dp_dpcd_read(aux,
|
||||
DP_HDCP_2_2_REG_RX_CAPS_OFFSET,
|
||||
rx_caps, HDCP_2_2_RXCAPS_LEN);
|
||||
if (ret != HDCP_2_2_RXCAPS_LEN)
|
||||
|
|
|
|||
|
|
@ -655,7 +655,7 @@ intel_dp_update_link_bw_set(struct intel_dp *intel_dp,
|
|||
/* Write the link configuration data */
|
||||
link_config[0] = link_bw;
|
||||
link_config[1] = crtc_state->lane_count;
|
||||
if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
|
||||
if (crtc_state->enhanced_framing)
|
||||
link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
|
||||
drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2);
|
||||
|
||||
|
|
@ -1390,11 +1390,13 @@ void intel_dp_128b132b_sdp_crc16(struct intel_dp *intel_dp,
|
|||
* Default value of bit 31 is '0' hence discarding the write
|
||||
* TODO: Corrective actions on SDP corruption yet to be defined
|
||||
*/
|
||||
if (intel_dp_is_uhbr(crtc_state))
|
||||
/* DP v2.0 SCR on SDP CRC16 for 128b/132b Link Layer */
|
||||
drm_dp_dpcd_writeb(&intel_dp->aux,
|
||||
DP_SDP_ERROR_DETECTION_CONFIGURATION,
|
||||
DP_SDP_CRC16_128B132B_EN);
|
||||
if (!intel_dp_is_uhbr(crtc_state))
|
||||
return;
|
||||
|
||||
/* DP v2.0 SCR on SDP CRC16 for 128b/132b Link Layer */
|
||||
drm_dp_dpcd_writeb(&intel_dp->aux,
|
||||
DP_SDP_ERROR_DETECTION_CONFIGURATION,
|
||||
DP_SDP_CRC16_128B132B_EN);
|
||||
|
||||
lt_dbg(intel_dp, DP_PHY_DPRX, "DP2.0 SDP CRC16 for 128b/132b enabled\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,15 +155,24 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
|
|||
const struct drm_display_mode *adjusted_mode =
|
||||
&crtc_state->hw.adjusted_mode;
|
||||
int slots = -EINVAL;
|
||||
int link_bpp;
|
||||
|
||||
slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state, limits->max_bpp,
|
||||
limits->min_bpp, limits,
|
||||
/*
|
||||
* FIXME: allocate the BW according to link_bpp, which in the case of
|
||||
* YUV420 is only half of the pipe bpp value.
|
||||
*/
|
||||
slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state,
|
||||
to_bpp_int(limits->link.max_bpp_x16),
|
||||
to_bpp_int(limits->link.min_bpp_x16),
|
||||
limits,
|
||||
conn_state, 2 * 3, false);
|
||||
|
||||
if (slots < 0)
|
||||
return slots;
|
||||
|
||||
intel_link_compute_m_n(crtc_state->pipe_bpp,
|
||||
link_bpp = intel_dp_output_bpp(crtc_state->output_format, crtc_state->pipe_bpp);
|
||||
|
||||
intel_link_compute_m_n(link_bpp,
|
||||
crtc_state->lane_count,
|
||||
adjusted_mode->crtc_clock,
|
||||
crtc_state->port_clock,
|
||||
|
|
@ -200,8 +209,8 @@ static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder,
|
|||
else
|
||||
dsc_max_bpc = min_t(u8, 10, conn_state->max_requested_bpc);
|
||||
|
||||
max_bpp = min_t(u8, dsc_max_bpc * 3, limits->max_bpp);
|
||||
min_bpp = limits->min_bpp;
|
||||
max_bpp = min_t(u8, dsc_max_bpc * 3, limits->pipe.max_bpp);
|
||||
min_bpp = limits->pipe.min_bpp;
|
||||
|
||||
num_bpc = drm_dp_dsc_sink_supported_input_bpcs(intel_dp->dsc_dpcd,
|
||||
dsc_bpc);
|
||||
|
|
@ -228,6 +237,9 @@ static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder,
|
|||
if (max_bpp > sink_max_bpp)
|
||||
max_bpp = sink_max_bpp;
|
||||
|
||||
min_bpp = max(min_bpp, to_bpp_int_roundup(limits->link.min_bpp_x16));
|
||||
max_bpp = min(max_bpp, to_bpp_int(limits->link.max_bpp_x16));
|
||||
|
||||
slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state, max_bpp,
|
||||
min_bpp, limits,
|
||||
conn_state, 2 * 3, true);
|
||||
|
|
@ -290,17 +302,39 @@ static int intel_dp_mst_update_slots(struct intel_encoder *encoder,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool intel_dp_mst_has_audio(const struct drm_connector_state *conn_state)
|
||||
static bool
|
||||
intel_dp_mst_compute_config_limits(struct intel_dp *intel_dp,
|
||||
struct intel_crtc_state *crtc_state,
|
||||
bool dsc,
|
||||
struct link_config_limits *limits)
|
||||
{
|
||||
const struct intel_digital_connector_state *intel_conn_state =
|
||||
to_intel_digital_connector_state(conn_state);
|
||||
struct intel_connector *connector =
|
||||
to_intel_connector(conn_state->connector);
|
||||
/*
|
||||
* for MST we always configure max link bw - the spec doesn't
|
||||
* seem to suggest we should do otherwise.
|
||||
*/
|
||||
limits->min_rate = limits->max_rate =
|
||||
intel_dp_max_link_rate(intel_dp);
|
||||
|
||||
if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
|
||||
return connector->base.display_info.has_audio;
|
||||
else
|
||||
return intel_conn_state->force_audio == HDMI_AUDIO_ON;
|
||||
limits->min_lane_count = limits->max_lane_count =
|
||||
intel_dp_max_lane_count(intel_dp);
|
||||
|
||||
limits->pipe.min_bpp = intel_dp_min_bpp(crtc_state->output_format);
|
||||
/*
|
||||
* FIXME: If all the streams can't fit into the link with
|
||||
* their current pipe_bpp we should reduce pipe_bpp across
|
||||
* the board until things start to fit. Until then we
|
||||
* limit to <= 8bpc since that's what was hardcoded for all
|
||||
* MST streams previously. This hack should be removed once
|
||||
* we have the proper retry logic in place.
|
||||
*/
|
||||
limits->pipe.max_bpp = min(crtc_state->pipe_bpp, 24);
|
||||
|
||||
intel_dp_adjust_compliance_config(intel_dp, crtc_state, limits);
|
||||
|
||||
return intel_dp_compute_config_link_bpp_limits(intel_dp,
|
||||
crtc_state,
|
||||
dsc,
|
||||
limits);
|
||||
}
|
||||
|
||||
static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
|
||||
|
|
@ -313,7 +347,8 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
|
|||
const struct drm_display_mode *adjusted_mode =
|
||||
&pipe_config->hw.adjusted_mode;
|
||||
struct link_config_limits limits;
|
||||
int ret;
|
||||
bool dsc_needed;
|
||||
int ret = 0;
|
||||
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
return -EINVAL;
|
||||
|
|
@ -322,42 +357,40 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
|
|||
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
|
||||
pipe_config->has_pch_encoder = false;
|
||||
|
||||
pipe_config->has_audio =
|
||||
intel_dp_mst_has_audio(conn_state) &&
|
||||
intel_audio_compute_config(encoder, pipe_config, conn_state);
|
||||
dsc_needed = intel_dp->force_dsc_en ||
|
||||
!intel_dp_mst_compute_config_limits(intel_dp,
|
||||
pipe_config,
|
||||
false,
|
||||
&limits);
|
||||
|
||||
/*
|
||||
* for MST we always configure max link bw - the spec doesn't
|
||||
* seem to suggest we should do otherwise.
|
||||
*/
|
||||
limits.min_rate =
|
||||
limits.max_rate = intel_dp_max_link_rate(intel_dp);
|
||||
if (!dsc_needed) {
|
||||
ret = intel_dp_mst_compute_link_config(encoder, pipe_config,
|
||||
conn_state, &limits);
|
||||
|
||||
limits.min_lane_count =
|
||||
limits.max_lane_count = intel_dp_max_lane_count(intel_dp);
|
||||
if (ret == -EDEADLK)
|
||||
return ret;
|
||||
|
||||
limits.min_bpp = intel_dp_min_bpp(pipe_config->output_format);
|
||||
/*
|
||||
* FIXME: If all the streams can't fit into the link with
|
||||
* their current pipe_bpp we should reduce pipe_bpp across
|
||||
* the board until things start to fit. Until then we
|
||||
* limit to <= 8bpc since that's what was hardcoded for all
|
||||
* MST streams previously. This hack should be removed once
|
||||
* we have the proper retry logic in place.
|
||||
*/
|
||||
limits.max_bpp = min(pipe_config->pipe_bpp, 24);
|
||||
|
||||
intel_dp_adjust_compliance_config(intel_dp, pipe_config, &limits);
|
||||
|
||||
ret = intel_dp_mst_compute_link_config(encoder, pipe_config,
|
||||
conn_state, &limits);
|
||||
|
||||
if (ret == -EDEADLK)
|
||||
return ret;
|
||||
if (ret)
|
||||
dsc_needed = true;
|
||||
}
|
||||
|
||||
/* enable compression if the mode doesn't fit available BW */
|
||||
drm_dbg_kms(&dev_priv->drm, "Force DSC en = %d\n", intel_dp->force_dsc_en);
|
||||
if (ret || intel_dp->force_dsc_en) {
|
||||
if (dsc_needed) {
|
||||
drm_dbg_kms(&dev_priv->drm, "Try DSC (fallback=%s, force=%s)\n",
|
||||
str_yes_no(ret),
|
||||
str_yes_no(intel_dp->force_dsc_en));
|
||||
|
||||
if (!intel_dp_mst_compute_config_limits(intel_dp,
|
||||
pipe_config,
|
||||
true,
|
||||
&limits))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* FIXME: As bpc is hardcoded to 8, as mentioned above,
|
||||
* WARN and ignore the debug flag force_dsc_bpc for now.
|
||||
*/
|
||||
drm_WARN(&dev_priv->drm, intel_dp->force_dsc_bpc, "Cannot Force BPC for MST\n");
|
||||
/*
|
||||
* Try to get at least some timeslots and then see, if
|
||||
* we can fit there with DSC.
|
||||
|
|
@ -388,6 +421,8 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
|
|||
pipe_config->lane_lat_optim_mask =
|
||||
bxt_ddi_phy_calc_lane_lat_optim_mask(pipe_config->lane_count);
|
||||
|
||||
intel_dp_audio_compute_config(encoder, pipe_config, conn_state);
|
||||
|
||||
intel_ddi_compute_min_voltage_level(dev_priv, pipe_config);
|
||||
|
||||
return 0;
|
||||
|
|
@ -733,8 +768,8 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state,
|
|||
ret = drm_dp_add_payload_part1(&intel_dp->mst_mgr, mst_state,
|
||||
drm_atomic_get_mst_payload_state(mst_state, connector->port));
|
||||
if (ret < 0)
|
||||
drm_err(&dev_priv->drm, "Failed to create MST payload for %s: %d\n",
|
||||
connector->base.name, ret);
|
||||
drm_dbg_kms(&dev_priv->drm, "Failed to create MST payload for %s: %d\n",
|
||||
connector->base.name, ret);
|
||||
|
||||
/*
|
||||
* Before Gen 12 this is not done as part of
|
||||
|
|
@ -798,6 +833,8 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
|
|||
intel_de_rmw(dev_priv, CHICKEN_TRANS(trans), 0,
|
||||
FECSTALL_DIS_DPTSTREAM_DPTTG);
|
||||
|
||||
intel_audio_sdp_split_update(pipe_config);
|
||||
|
||||
intel_enable_transcoder(pipe_config);
|
||||
|
||||
intel_crtc_vblank_on(pipe_config);
|
||||
|
|
@ -918,7 +955,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
|
|||
int max_rate, mode_rate, max_lanes, max_link_clock;
|
||||
int ret;
|
||||
bool dsc = false, bigjoiner = false;
|
||||
u16 dsc_max_output_bpp = 0;
|
||||
u16 dsc_max_compressed_bpp = 0;
|
||||
u8 dsc_slice_count = 0;
|
||||
int target_clock = mode->clock;
|
||||
|
||||
|
|
@ -969,17 +1006,18 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
|
|||
* TBD pass the connector BPC,
|
||||
* for now U8_MAX so that max BPC on that platform would be picked
|
||||
*/
|
||||
int pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, U8_MAX);
|
||||
int pipe_bpp = intel_dp_dsc_compute_max_bpp(intel_dp, U8_MAX);
|
||||
|
||||
if (drm_dp_sink_supports_fec(intel_dp->fec_capable)) {
|
||||
dsc_max_output_bpp =
|
||||
intel_dp_dsc_get_output_bpp(dev_priv,
|
||||
max_link_clock,
|
||||
max_lanes,
|
||||
target_clock,
|
||||
mode->hdisplay,
|
||||
bigjoiner,
|
||||
pipe_bpp, 64) >> 4;
|
||||
dsc_max_compressed_bpp =
|
||||
intel_dp_dsc_get_max_compressed_bpp(dev_priv,
|
||||
max_link_clock,
|
||||
max_lanes,
|
||||
target_clock,
|
||||
mode->hdisplay,
|
||||
bigjoiner,
|
||||
INTEL_OUTPUT_FORMAT_RGB,
|
||||
pipe_bpp, 64);
|
||||
dsc_slice_count =
|
||||
intel_dp_dsc_get_slice_count(intel_dp,
|
||||
target_clock,
|
||||
|
|
@ -987,7 +1025,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
|
|||
bigjoiner);
|
||||
}
|
||||
|
||||
dsc = dsc_max_output_bpp && dsc_slice_count;
|
||||
dsc = dsc_max_compressed_bpp && dsc_slice_count;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -314,10 +314,11 @@ int pnv_calc_dpll_params(int refclk, struct dpll *clock)
|
|||
{
|
||||
clock->m = clock->m2 + 2;
|
||||
clock->p = clock->p1 * clock->p2;
|
||||
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);
|
||||
|
||||
clock->vco = clock->n == 0 ? 0 :
|
||||
DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
|
||||
clock->dot = clock->p == 0 ? 0 :
|
||||
DIV_ROUND_CLOSEST(clock->vco, clock->p);
|
||||
|
||||
return clock->dot;
|
||||
}
|
||||
|
|
@ -331,10 +332,11 @@ int i9xx_calc_dpll_params(int refclk, struct dpll *clock)
|
|||
{
|
||||
clock->m = i9xx_dpll_compute_m(clock);
|
||||
clock->p = clock->p1 * clock->p2;
|
||||
if (WARN_ON(clock->n + 2 == 0 || clock->p == 0))
|
||||
return 0;
|
||||
clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n + 2);
|
||||
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
|
||||
|
||||
clock->vco = clock->n + 2 == 0 ? 0 :
|
||||
DIV_ROUND_CLOSEST(refclk * clock->m, clock->n + 2);
|
||||
clock->dot = clock->p == 0 ? 0 :
|
||||
DIV_ROUND_CLOSEST(clock->vco, clock->p);
|
||||
|
||||
return clock->dot;
|
||||
}
|
||||
|
|
@ -343,10 +345,11 @@ int vlv_calc_dpll_params(int refclk, struct dpll *clock)
|
|||
{
|
||||
clock->m = clock->m1 * clock->m2;
|
||||
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);
|
||||
|
||||
clock->vco = clock->n == 0 ? 0 :
|
||||
DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
|
||||
clock->dot = clock->p == 0 ? 0 :
|
||||
DIV_ROUND_CLOSEST(clock->vco, clock->p);
|
||||
|
||||
return clock->dot;
|
||||
}
|
||||
|
|
@ -355,11 +358,11 @@ int chv_calc_dpll_params(int refclk, struct dpll *clock)
|
|||
{
|
||||
clock->m = clock->m1 * clock->m2;
|
||||
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);
|
||||
|
||||
clock->vco = clock->n == 0 ? 0 :
|
||||
DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, clock->m), clock->n << 22);
|
||||
clock->dot = clock->p == 0 ? 0 :
|
||||
DIV_ROUND_CLOSEST(clock->vco, clock->p);
|
||||
|
||||
return clock->dot;
|
||||
}
|
||||
|
|
@ -1179,6 +1182,8 @@ static int ilk_crtc_compute_clock(struct intel_atomic_state *state,
|
|||
refclk, NULL, &crtc_state->dpll))
|
||||
return -EINVAL;
|
||||
|
||||
i9xx_calc_dpll_params(refclk, &crtc_state->dpll);
|
||||
|
||||
ilk_compute_dpll(crtc_state, &crtc_state->dpll,
|
||||
&crtc_state->dpll);
|
||||
|
||||
|
|
@ -1253,6 +1258,8 @@ static int chv_crtc_compute_clock(struct intel_atomic_state *state,
|
|||
refclk, NULL, &crtc_state->dpll))
|
||||
return -EINVAL;
|
||||
|
||||
chv_calc_dpll_params(refclk, &crtc_state->dpll);
|
||||
|
||||
chv_compute_dpll(crtc_state);
|
||||
|
||||
/* FIXME this is a mess */
|
||||
|
|
@ -1275,9 +1282,10 @@ static int vlv_crtc_compute_clock(struct intel_atomic_state *state,
|
|||
|
||||
if (!crtc_state->clock_set &&
|
||||
!vlv_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
|
||||
refclk, NULL, &crtc_state->dpll)) {
|
||||
refclk, NULL, &crtc_state->dpll))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vlv_calc_dpll_params(refclk, &crtc_state->dpll);
|
||||
|
||||
vlv_compute_dpll(crtc_state);
|
||||
|
||||
|
|
@ -1327,6 +1335,8 @@ static int g4x_crtc_compute_clock(struct intel_atomic_state *state,
|
|||
refclk, NULL, &crtc_state->dpll))
|
||||
return -EINVAL;
|
||||
|
||||
i9xx_calc_dpll_params(refclk, &crtc_state->dpll);
|
||||
|
||||
i9xx_compute_dpll(crtc_state, &crtc_state->dpll,
|
||||
&crtc_state->dpll);
|
||||
|
||||
|
|
@ -1365,6 +1375,8 @@ static int pnv_crtc_compute_clock(struct intel_atomic_state *state,
|
|||
refclk, NULL, &crtc_state->dpll))
|
||||
return -EINVAL;
|
||||
|
||||
pnv_calc_dpll_params(refclk, &crtc_state->dpll);
|
||||
|
||||
i9xx_compute_dpll(crtc_state, &crtc_state->dpll,
|
||||
&crtc_state->dpll);
|
||||
|
||||
|
|
@ -1401,6 +1413,8 @@ static int i9xx_crtc_compute_clock(struct intel_atomic_state *state,
|
|||
refclk, NULL, &crtc_state->dpll))
|
||||
return -EINVAL;
|
||||
|
||||
i9xx_calc_dpll_params(refclk, &crtc_state->dpll);
|
||||
|
||||
i9xx_compute_dpll(crtc_state, &crtc_state->dpll,
|
||||
&crtc_state->dpll);
|
||||
|
||||
|
|
@ -1441,6 +1455,8 @@ static int i8xx_crtc_compute_clock(struct intel_atomic_state *state,
|
|||
refclk, NULL, &crtc_state->dpll))
|
||||
return -EINVAL;
|
||||
|
||||
i9xx_calc_dpll_params(refclk, &crtc_state->dpll);
|
||||
|
||||
i8xx_compute_dpll(crtc_state, &crtc_state->dpll,
|
||||
&crtc_state->dpll);
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ static inline struct i915_dpt *
|
|||
i915_vm_to_dpt(struct i915_address_space *vm)
|
||||
{
|
||||
BUILD_BUG_ON(offsetof(struct i915_dpt, vm));
|
||||
GEM_BUG_ON(!i915_is_dpt(vm));
|
||||
drm_WARN_ON(&vm->i915->drm, !i915_is_dpt(vm));
|
||||
return container_of(vm, struct i915_dpt, vm);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "intel_de.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_drrs.h"
|
||||
#include "intel_frontbuffer.h"
|
||||
#include "intel_panel.h"
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7,11 +7,16 @@
|
|||
#include "gem/i915_gem_internal.h"
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_irq.h"
|
||||
#include "i915_reg.h"
|
||||
#include "intel_crtc.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dsb.h"
|
||||
#include "intel_dsb_regs.h"
|
||||
#include "intel_vblank.h"
|
||||
#include "intel_vrr.h"
|
||||
#include "skl_watermark.h"
|
||||
|
||||
struct i915_vma;
|
||||
|
||||
|
|
@ -47,6 +52,8 @@ struct intel_dsb {
|
|||
* register.
|
||||
*/
|
||||
unsigned int ins_start_offset;
|
||||
|
||||
int dewake_scanline;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -70,17 +77,21 @@ struct intel_dsb {
|
|||
#define DSB_OPCODE_SHIFT 24
|
||||
#define DSB_OPCODE_NOOP 0x0
|
||||
#define DSB_OPCODE_MMIO_WRITE 0x1
|
||||
#define DSB_BYTE_EN 0xf
|
||||
#define DSB_BYTE_EN_SHIFT 20
|
||||
#define DSB_REG_VALUE_MASK 0xfffff
|
||||
#define DSB_OPCODE_WAIT_USEC 0x2
|
||||
#define DSB_OPCODE_WAIT_LINES 0x3
|
||||
#define DSB_OPCODE_WAIT_SCANLINE 0x3
|
||||
#define DSB_OPCODE_WAIT_VBLANKS 0x4
|
||||
#define DSB_OPCODE_WAIT_DSL_IN 0x5
|
||||
#define DSB_OPCODE_WAIT_DSL_OUT 0x6
|
||||
#define DSB_SCANLINE_UPPER_SHIFT 20
|
||||
#define DSB_SCANLINE_LOWER_SHIFT 0
|
||||
#define DSB_OPCODE_INTERRUPT 0x7
|
||||
#define DSB_OPCODE_INDEXED_WRITE 0x9
|
||||
/* see DSB_REG_VALUE_MASK */
|
||||
#define DSB_OPCODE_POLL 0xA
|
||||
#define DSB_BYTE_EN 0xF
|
||||
#define DSB_BYTE_EN_SHIFT 20
|
||||
#define DSB_REG_VALUE_MASK 0xfffff
|
||||
/* see DSB_REG_VALUE_MASK */
|
||||
|
||||
static bool assert_dsb_has_room(struct intel_dsb *dsb)
|
||||
{
|
||||
|
|
@ -93,10 +104,26 @@ static bool assert_dsb_has_room(struct intel_dsb *dsb)
|
|||
crtc->base.base.id, crtc->base.name, dsb->id);
|
||||
}
|
||||
|
||||
static void intel_dsb_dump(struct intel_dsb *dsb)
|
||||
{
|
||||
struct intel_crtc *crtc = dsb->crtc;
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
const u32 *buf = dsb->cmd_buf;
|
||||
int i;
|
||||
|
||||
drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] DSB %d commands {\n",
|
||||
crtc->base.base.id, crtc->base.name, dsb->id);
|
||||
for (i = 0; i < ALIGN(dsb->free_pos, 64 / 4); i += 4)
|
||||
drm_dbg_kms(&i915->drm,
|
||||
" 0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||
i * 4, buf[i], buf[i+1], buf[i+2], buf[i+3]);
|
||||
drm_dbg_kms(&i915->drm, "}\n");
|
||||
}
|
||||
|
||||
static bool is_dsb_busy(struct drm_i915_private *i915, enum pipe pipe,
|
||||
enum dsb_id id)
|
||||
{
|
||||
return intel_de_read(i915, DSB_CTRL(pipe, id)) & DSB_STATUS_BUSY;
|
||||
return intel_de_read_fw(i915, DSB_CTRL(pipe, id)) & DSB_STATUS_BUSY;
|
||||
}
|
||||
|
||||
static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw)
|
||||
|
|
@ -121,7 +148,15 @@ static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb,
|
|||
const u32 *buf = dsb->cmd_buf;
|
||||
u32 prev_opcode, prev_reg;
|
||||
|
||||
prev_opcode = buf[dsb->ins_start_offset + 1] >> DSB_OPCODE_SHIFT;
|
||||
/*
|
||||
* Nothing emitted yet? Must check before looking
|
||||
* at the actual data since i915_gem_object_create_internal()
|
||||
* does *not* give you zeroed memory!
|
||||
*/
|
||||
if (dsb->free_pos == 0)
|
||||
return false;
|
||||
|
||||
prev_opcode = buf[dsb->ins_start_offset + 1] & ~DSB_REG_VALUE_MASK;
|
||||
prev_reg = buf[dsb->ins_start_offset + 1] & DSB_REG_VALUE_MASK;
|
||||
|
||||
return prev_opcode == opcode && prev_reg == i915_mmio_reg_offset(reg);
|
||||
|
|
@ -129,12 +164,18 @@ static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb,
|
|||
|
||||
static bool intel_dsb_prev_ins_is_mmio_write(struct intel_dsb *dsb, i915_reg_t reg)
|
||||
{
|
||||
return intel_dsb_prev_ins_is_write(dsb, DSB_OPCODE_MMIO_WRITE, reg);
|
||||
/* only full byte-enables can be converted to indexed writes */
|
||||
return intel_dsb_prev_ins_is_write(dsb,
|
||||
DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT |
|
||||
DSB_BYTE_EN << DSB_BYTE_EN_SHIFT,
|
||||
reg);
|
||||
}
|
||||
|
||||
static bool intel_dsb_prev_ins_is_indexed_write(struct intel_dsb *dsb, i915_reg_t reg)
|
||||
{
|
||||
return intel_dsb_prev_ins_is_write(dsb, DSB_OPCODE_INDEXED_WRITE, reg);
|
||||
return intel_dsb_prev_ins_is_write(dsb,
|
||||
DSB_OPCODE_INDEXED_WRITE << DSB_OPCODE_SHIFT,
|
||||
reg);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -200,6 +241,53 @@ void intel_dsb_reg_write(struct intel_dsb *dsb,
|
|||
}
|
||||
}
|
||||
|
||||
static u32 intel_dsb_mask_to_byte_en(u32 mask)
|
||||
{
|
||||
return (!!(mask & 0xff000000) << 3 |
|
||||
!!(mask & 0x00ff0000) << 2 |
|
||||
!!(mask & 0x0000ff00) << 1 |
|
||||
!!(mask & 0x000000ff) << 0);
|
||||
}
|
||||
|
||||
/* Note: mask implemented via byte enables! */
|
||||
void intel_dsb_reg_write_masked(struct intel_dsb *dsb,
|
||||
i915_reg_t reg, u32 mask, u32 val)
|
||||
{
|
||||
intel_dsb_emit(dsb, val,
|
||||
(DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) |
|
||||
(intel_dsb_mask_to_byte_en(mask) << DSB_BYTE_EN_SHIFT) |
|
||||
i915_mmio_reg_offset(reg));
|
||||
}
|
||||
|
||||
void intel_dsb_noop(struct intel_dsb *dsb, int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
intel_dsb_emit(dsb, 0,
|
||||
DSB_OPCODE_NOOP << DSB_OPCODE_SHIFT);
|
||||
}
|
||||
|
||||
void intel_dsb_nonpost_start(struct intel_dsb *dsb)
|
||||
{
|
||||
struct intel_crtc *crtc = dsb->crtc;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
intel_dsb_reg_write_masked(dsb, DSB_CTRL(pipe, dsb->id),
|
||||
DSB_NON_POSTED, DSB_NON_POSTED);
|
||||
intel_dsb_noop(dsb, 4);
|
||||
}
|
||||
|
||||
void intel_dsb_nonpost_end(struct intel_dsb *dsb)
|
||||
{
|
||||
struct intel_crtc *crtc = dsb->crtc;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
intel_dsb_reg_write_masked(dsb, DSB_CTRL(pipe, dsb->id),
|
||||
DSB_NON_POSTED, 0);
|
||||
intel_dsb_noop(dsb, 4);
|
||||
}
|
||||
|
||||
static void intel_dsb_align_tail(struct intel_dsb *dsb)
|
||||
{
|
||||
u32 aligned_tail, tail;
|
||||
|
|
@ -216,17 +304,40 @@ static void intel_dsb_align_tail(struct intel_dsb *dsb)
|
|||
|
||||
void intel_dsb_finish(struct intel_dsb *dsb)
|
||||
{
|
||||
struct intel_crtc *crtc = dsb->crtc;
|
||||
|
||||
/*
|
||||
* DSB_FORCE_DEWAKE remains active even after DSB is
|
||||
* disabled, so make sure to clear it (if set during
|
||||
* intel_dsb_commit()).
|
||||
*/
|
||||
intel_dsb_reg_write_masked(dsb, DSB_PMCTRL_2(crtc->pipe, dsb->id),
|
||||
DSB_FORCE_DEWAKE, 0);
|
||||
|
||||
intel_dsb_align_tail(dsb);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_dsb_commit() - Trigger workload execution of DSB.
|
||||
* @dsb: DSB context
|
||||
* @wait_for_vblank: wait for vblank before executing
|
||||
*
|
||||
* This function is used to do actual write to hardware using DSB.
|
||||
*/
|
||||
void intel_dsb_commit(struct intel_dsb *dsb, bool wait_for_vblank)
|
||||
static int intel_dsb_dewake_scanline(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
|
||||
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
|
||||
unsigned int latency = skl_watermark_max_latency(i915);
|
||||
int vblank_start;
|
||||
|
||||
if (crtc_state->vrr.enable) {
|
||||
vblank_start = intel_vrr_vmin_vblank_start(crtc_state);
|
||||
} else {
|
||||
vblank_start = adjusted_mode->crtc_vblank_start;
|
||||
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
vblank_start = DIV_ROUND_UP(vblank_start, 2);
|
||||
}
|
||||
|
||||
return max(0, vblank_start - intel_usecs_to_scanlines(adjusted_mode, latency));
|
||||
}
|
||||
|
||||
static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl,
|
||||
unsigned int dewake_scanline)
|
||||
{
|
||||
struct intel_crtc *crtc = dsb->crtc;
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
|
|
@ -243,13 +354,48 @@ void intel_dsb_commit(struct intel_dsb *dsb, bool wait_for_vblank)
|
|||
return;
|
||||
}
|
||||
|
||||
intel_de_write(dev_priv, DSB_CTRL(pipe, dsb->id),
|
||||
(wait_for_vblank ? DSB_WAIT_FOR_VBLANK : 0) |
|
||||
DSB_ENABLE);
|
||||
intel_de_write(dev_priv, DSB_HEAD(pipe, dsb->id),
|
||||
i915_ggtt_offset(dsb->vma));
|
||||
intel_de_write(dev_priv, DSB_TAIL(pipe, dsb->id),
|
||||
i915_ggtt_offset(dsb->vma) + tail);
|
||||
intel_de_write_fw(dev_priv, DSB_CTRL(pipe, dsb->id),
|
||||
ctrl | DSB_ENABLE);
|
||||
|
||||
intel_de_write_fw(dev_priv, DSB_HEAD(pipe, dsb->id),
|
||||
i915_ggtt_offset(dsb->vma));
|
||||
|
||||
if (dewake_scanline >= 0) {
|
||||
int diff, hw_dewake_scanline;
|
||||
|
||||
hw_dewake_scanline = intel_crtc_scanline_to_hw(crtc, dewake_scanline);
|
||||
|
||||
intel_de_write_fw(dev_priv, DSB_PMCTRL(pipe, dsb->id),
|
||||
DSB_ENABLE_DEWAKE |
|
||||
DSB_SCANLINE_FOR_DEWAKE(hw_dewake_scanline));
|
||||
|
||||
/*
|
||||
* Force DEwake immediately if we're already past
|
||||
* or close to racing past the target scanline.
|
||||
*/
|
||||
diff = dewake_scanline - intel_get_crtc_scanline(crtc);
|
||||
intel_de_write_fw(dev_priv, DSB_PMCTRL_2(pipe, dsb->id),
|
||||
(diff >= 0 && diff < 5 ? DSB_FORCE_DEWAKE : 0) |
|
||||
DSB_BLOCK_DEWAKE_EXTENSION);
|
||||
}
|
||||
|
||||
intel_de_write_fw(dev_priv, DSB_TAIL(pipe, dsb->id),
|
||||
i915_ggtt_offset(dsb->vma) + tail);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_dsb_commit() - Trigger workload execution of DSB.
|
||||
* @dsb: DSB context
|
||||
* @wait_for_vblank: wait for vblank before executing
|
||||
*
|
||||
* This function is used to do actual write to hardware using DSB.
|
||||
*/
|
||||
void intel_dsb_commit(struct intel_dsb *dsb,
|
||||
bool wait_for_vblank)
|
||||
{
|
||||
_intel_dsb_commit(dsb,
|
||||
wait_for_vblank ? DSB_WAIT_FOR_VBLANK : 0,
|
||||
wait_for_vblank ? dsb->dewake_scanline : -1);
|
||||
}
|
||||
|
||||
void intel_dsb_wait(struct intel_dsb *dsb)
|
||||
|
|
@ -258,20 +404,31 @@ void intel_dsb_wait(struct intel_dsb *dsb)
|
|||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
if (wait_for(!is_dsb_busy(dev_priv, pipe, dsb->id), 1))
|
||||
if (wait_for(!is_dsb_busy(dev_priv, pipe, dsb->id), 1)) {
|
||||
u32 offset = i915_ggtt_offset(dsb->vma);
|
||||
|
||||
intel_de_write_fw(dev_priv, DSB_CTRL(pipe, dsb->id),
|
||||
DSB_ENABLE | DSB_HALT);
|
||||
|
||||
drm_err(&dev_priv->drm,
|
||||
"[CRTC:%d:%s] DSB %d timed out waiting for idle\n",
|
||||
crtc->base.base.id, crtc->base.name, dsb->id);
|
||||
"[CRTC:%d:%s] DSB %d timed out waiting for idle (current head=0x%x, head=0x%x, tail=0x%x)\n",
|
||||
crtc->base.base.id, crtc->base.name, dsb->id,
|
||||
intel_de_read_fw(dev_priv, DSB_CURRENT_HEAD(pipe, dsb->id)) - offset,
|
||||
intel_de_read_fw(dev_priv, DSB_HEAD(pipe, dsb->id)) - offset,
|
||||
intel_de_read_fw(dev_priv, DSB_TAIL(pipe, dsb->id)) - offset);
|
||||
|
||||
intel_dsb_dump(dsb);
|
||||
}
|
||||
|
||||
/* Attempt to reset it */
|
||||
dsb->free_pos = 0;
|
||||
dsb->ins_start_offset = 0;
|
||||
intel_de_write(dev_priv, DSB_CTRL(pipe, dsb->id), 0);
|
||||
intel_de_write_fw(dev_priv, DSB_CTRL(pipe, dsb->id), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_dsb_prepare() - Allocate, pin and map the DSB command buffer.
|
||||
* @crtc: the CRTC
|
||||
* @crtc_state: the CRTC state
|
||||
* @max_cmds: number of commands we need to fit into command buffer
|
||||
*
|
||||
* This function prepare the command buffer which is used to store dsb
|
||||
|
|
@ -280,9 +437,10 @@ void intel_dsb_wait(struct intel_dsb *dsb)
|
|||
* Returns:
|
||||
* DSB context, NULL on failure
|
||||
*/
|
||||
struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc,
|
||||
struct intel_dsb *intel_dsb_prepare(const struct intel_crtc_state *crtc_state,
|
||||
unsigned int max_cmds)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
struct drm_i915_gem_object *obj;
|
||||
intel_wakeref_t wakeref;
|
||||
|
|
@ -328,6 +486,7 @@ struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc,
|
|||
dsb->size = size / 4; /* in dwords */
|
||||
dsb->free_pos = 0;
|
||||
dsb->ins_start_offset = 0;
|
||||
dsb->dewake_scanline = intel_dsb_dewake_scanline(crtc_state);
|
||||
|
||||
return dsb;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,14 +11,21 @@
|
|||
#include "i915_reg_defs.h"
|
||||
|
||||
struct intel_crtc;
|
||||
struct intel_crtc_state;
|
||||
struct intel_dsb;
|
||||
|
||||
struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc,
|
||||
struct intel_dsb *intel_dsb_prepare(const struct intel_crtc_state *crtc_state,
|
||||
unsigned int max_cmds);
|
||||
void intel_dsb_finish(struct intel_dsb *dsb);
|
||||
void intel_dsb_cleanup(struct intel_dsb *dsb);
|
||||
void intel_dsb_reg_write(struct intel_dsb *dsb,
|
||||
i915_reg_t reg, u32 val);
|
||||
void intel_dsb_reg_write_masked(struct intel_dsb *dsb,
|
||||
i915_reg_t reg, u32 mask, u32 val);
|
||||
void intel_dsb_noop(struct intel_dsb *dsb, int count);
|
||||
void intel_dsb_nonpost_start(struct intel_dsb *dsb);
|
||||
void intel_dsb_nonpost_end(struct intel_dsb *dsb);
|
||||
|
||||
void intel_dsb_commit(struct intel_dsb *dsb,
|
||||
bool wait_for_vblank);
|
||||
void intel_dsb_wait(struct intel_dsb *dsb);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,19 @@
|
|||
#define DSB_DEBUG(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x14)
|
||||
#define DSB_POLLMASK(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x1c)
|
||||
#define DSB_STATUS(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x24)
|
||||
#define DSB_HP_IDLE_STATUS REG_BIT(31)
|
||||
#define DSB_DEWAKE_STATUS REG_BIT(30)
|
||||
#define DSB_REQARB_SM_STATE_MASK REG_GENMASK(29, 27)
|
||||
#define DSB_SAFE_WINDOW_LIVE REG_BIT(26)
|
||||
#define DSB_VTDFAULT_ARB_SM_STATE_MASK REG_GENMASK(25, 23)
|
||||
#define DSB_TLBTRANS_SM_STATE_MASK REG_GENMASK(21, 20)
|
||||
#define DSB_SAFE_WINDOW REG_BIT(19)
|
||||
#define DSB_POINTERS_SM_STATE_MASK REG_GENMASK(18, 17)
|
||||
#define DSB_BUSY_ON_DELAYED_VBLANK REG_BIT(16)
|
||||
#define DSB_MMIO_ARB_SM_STATE_MASK REG_GENMASK(15, 13)
|
||||
#define DSB_MMIO_INST_SM_STATE_MASK REG_GENMASK(11, 7)
|
||||
#define DSB_RESET_SM_STATE_MASK REG_GENMASK(5, 4)
|
||||
#define DSB_RUN_SM_STATE_MASK REG_GENMASK(2, 0)
|
||||
#define DSB_INTERRUPT(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x28)
|
||||
#define DSB_ATS_FAULT_INT_EN REG_BIT(20)
|
||||
#define DSB_GTT_FAULT_INT_EN REG_BIT(19)
|
||||
|
|
@ -58,10 +71,28 @@
|
|||
#define DSB_RM_READY_TIMEOUT_VALUE(x) REG_FIELD_PREP(DSB_RM_READY_TIMEOUT_VALUE, (x)) /* usec */
|
||||
#define DSB_RMTIMEOUTREG_CAPTURE(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x34)
|
||||
#define DSB_PMCTRL(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x38)
|
||||
#define DSB_ENABLE_DEWAKE REG_BIT(31)
|
||||
#define DSB_SCANLINE_FOR_DEWAKE_MASK REG_GENMASK(30, 0)
|
||||
#define DSB_SCANLINE_FOR_DEWAKE(x) REG_FIELD_PREP(DSB_SCANLINE_FOR_DEWAKE_MASK, (x))
|
||||
#define DSB_PMCTRL_2(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x3c)
|
||||
#define DSB_MMIOGEN_DEWAKE_DIS REG_BIT(31)
|
||||
#define DSB_FORCE_DEWAKE REG_BIT(23)
|
||||
#define DSB_BLOCK_DEWAKE_EXTENSION REG_BIT(15)
|
||||
#define DSB_OVERRIDE_DC5_DC6_OK REG_BIT(7)
|
||||
#define DSB_PF_LN_LOWER(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x40)
|
||||
#define DSB_PF_LN_UPPER(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x44)
|
||||
#define DSB_BUFRPT_CNT(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x48)
|
||||
#define DSB_CHICKEN(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0xf0)
|
||||
#define DSB_FORCE_DMA_SYNC_RESET REG_BIT(31)
|
||||
#define DSB_FORCE_VTD_ENGIE_RESET REG_BIT(30)
|
||||
#define DSB_DISABLE_IPC_DEMOTE REG_BIT(29)
|
||||
#define DSB_SKIP_WAITS_EN REG_BIT(23)
|
||||
#define DSB_EXTEND_HP_IDLE REG_BIT(16)
|
||||
#define DSB_CTRL_WAIT_SAFE_WINDOW REG_BIT(15)
|
||||
#define DSB_CTRL_NO_WAIT_VBLANK REG_BIT(14)
|
||||
#define DSB_INST_WAIT_SAFE_WINDOW REG_BIT(7)
|
||||
#define DSB_INST_NO_WAIT_VBLANK REG_BIT(6)
|
||||
#define DSB_MMIOGEN_DEWAKE_DIS_CHICKEN REG_BIT(2)
|
||||
#define DSB_DISABLE_MMIO_COUNT_FOR_INDEXED REG_BIT(0)
|
||||
|
||||
#endif /* __INTEL_DSB_REGS_H__ */
|
||||
|
|
|
|||
|
|
@ -328,7 +328,6 @@ intel_dvo_detect(struct drm_connector *_connector, bool force)
|
|||
static int intel_dvo_get_modes(struct drm_connector *_connector)
|
||||
{
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
int num_modes;
|
||||
|
||||
/*
|
||||
|
|
@ -337,8 +336,7 @@ static int intel_dvo_get_modes(struct drm_connector *_connector)
|
|||
* (TV-out, for example), but for now with just TMDS and LVDS,
|
||||
* that's not the case.
|
||||
*/
|
||||
num_modes = intel_ddc_get_modes(&connector->base,
|
||||
intel_gmbus_get_adapter(i915, GMBUS_PIN_DPC));
|
||||
num_modes = intel_ddc_get_modes(&connector->base, connector->base.ddc);
|
||||
if (num_modes)
|
||||
return num_modes;
|
||||
|
||||
|
|
@ -533,9 +531,10 @@ void intel_dvo_init(struct drm_i915_private *i915)
|
|||
connector->polled = DRM_CONNECTOR_POLL_CONNECT |
|
||||
DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
|
||||
drm_connector_init(&i915->drm, &connector->base,
|
||||
&intel_dvo_connector_funcs,
|
||||
intel_dvo_connector_type(&intel_dvo->dev));
|
||||
drm_connector_init_with_ddc(&i915->drm, &connector->base,
|
||||
&intel_dvo_connector_funcs,
|
||||
intel_dvo_connector_type(&intel_dvo->dev),
|
||||
intel_gmbus_get_adapter(i915, GMBUS_PIN_DPC));
|
||||
|
||||
drm_connector_helper_add(&connector->base,
|
||||
&intel_dvo_connector_helper_funcs);
|
||||
|
|
|
|||
|
|
@ -7,11 +7,15 @@
|
|||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_modeset_helper.h>
|
||||
|
||||
#include <linux/dma-fence.h>
|
||||
#include <linux/dma-resv.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_display.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dpt.h"
|
||||
#include "intel_fb.h"
|
||||
#include "intel_frontbuffer.h"
|
||||
|
||||
#define check_array_bounds(i915, a, i) drm_WARN_ON(&(i915)->drm, (i) >= ARRAY_SIZE(a))
|
||||
|
||||
|
|
@ -1896,6 +1900,21 @@ static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb,
|
|||
return drm_gem_handle_create(file, &obj->base, handle);
|
||||
}
|
||||
|
||||
struct frontbuffer_fence_cb {
|
||||
struct dma_fence_cb base;
|
||||
struct intel_frontbuffer *front;
|
||||
};
|
||||
|
||||
static void intel_user_framebuffer_fence_wake(struct dma_fence *dma,
|
||||
struct dma_fence_cb *data)
|
||||
{
|
||||
struct frontbuffer_fence_cb *cb = container_of(data, typeof(*cb), base);
|
||||
|
||||
intel_frontbuffer_queue_flush(cb->front);
|
||||
kfree(cb);
|
||||
dma_fence_put(dma);
|
||||
}
|
||||
|
||||
static int intel_user_framebuffer_dirty(struct drm_framebuffer *fb,
|
||||
struct drm_file *file,
|
||||
unsigned int flags, unsigned int color,
|
||||
|
|
@ -1903,11 +1922,47 @@ static int intel_user_framebuffer_dirty(struct drm_framebuffer *fb,
|
|||
unsigned int num_clips)
|
||||
{
|
||||
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
||||
struct intel_frontbuffer *front = to_intel_frontbuffer(fb);
|
||||
struct dma_fence *fence;
|
||||
struct frontbuffer_fence_cb *cb;
|
||||
int ret = 0;
|
||||
|
||||
if (!atomic_read(&front->bits))
|
||||
return 0;
|
||||
|
||||
if (dma_resv_test_signaled(obj->base.resv, dma_resv_usage_rw(false)))
|
||||
goto flush;
|
||||
|
||||
ret = dma_resv_get_singleton(obj->base.resv, dma_resv_usage_rw(false),
|
||||
&fence);
|
||||
if (ret || !fence)
|
||||
goto flush;
|
||||
|
||||
cb = kmalloc(sizeof(*cb), GFP_KERNEL);
|
||||
if (!cb) {
|
||||
dma_fence_put(fence);
|
||||
ret = -ENOMEM;
|
||||
goto flush;
|
||||
}
|
||||
|
||||
cb->front = front;
|
||||
|
||||
intel_frontbuffer_invalidate(front, ORIGIN_DIRTYFB);
|
||||
|
||||
ret = dma_fence_add_callback(fence, &cb->base,
|
||||
intel_user_framebuffer_fence_wake);
|
||||
if (ret) {
|
||||
intel_user_framebuffer_fence_wake(fence, &cb->base);
|
||||
if (ret == -ENOENT)
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
flush:
|
||||
i915_gem_object_flush_if_display(obj);
|
||||
intel_frontbuffer_flush(to_intel_frontbuffer(fb), ORIGIN_DIRTYFB);
|
||||
|
||||
return 0;
|
||||
intel_frontbuffer_flush(front, ORIGIN_DIRTYFB);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct drm_framebuffer_funcs intel_fb_funcs = {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@ intel_pin_fb_obj_dpt(struct drm_framebuffer *fb,
|
|||
* We are not syncing against the binding (and potential migrations)
|
||||
* below, so this vm must never be async.
|
||||
*/
|
||||
GEM_WARN_ON(vm->bind_async_flags);
|
||||
if (drm_WARN_ON(&dev_priv->drm, vm->bind_async_flags))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (WARN_ON(!i915_gem_object_is_framebuffer(obj)))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
#include "i915_vma.h"
|
||||
#include "intel_cdclk.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_device.h"
|
||||
#include "intel_display_trace.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_fbc.h"
|
||||
|
|
@ -332,12 +333,14 @@ static void i8xx_fbc_program_cfb(struct intel_fbc *fbc)
|
|||
{
|
||||
struct drm_i915_private *i915 = fbc->i915;
|
||||
|
||||
GEM_BUG_ON(range_overflows_end_t(u64, i915_gem_stolen_area_address(i915),
|
||||
i915_gem_stolen_node_offset(&fbc->compressed_fb),
|
||||
U32_MAX));
|
||||
GEM_BUG_ON(range_overflows_end_t(u64, i915_gem_stolen_area_address(i915),
|
||||
i915_gem_stolen_node_offset(&fbc->compressed_llb),
|
||||
U32_MAX));
|
||||
drm_WARN_ON(&i915->drm,
|
||||
range_overflows_end_t(u64, i915_gem_stolen_area_address(i915),
|
||||
i915_gem_stolen_node_offset(&fbc->compressed_fb),
|
||||
U32_MAX));
|
||||
drm_WARN_ON(&i915->drm,
|
||||
range_overflows_end_t(u64, i915_gem_stolen_area_address(i915),
|
||||
i915_gem_stolen_node_offset(&fbc->compressed_llb),
|
||||
U32_MAX));
|
||||
intel_de_write(i915, FBC_CFB_BASE,
|
||||
i915_gem_stolen_node_address(i915, &fbc->compressed_fb));
|
||||
intel_de_write(i915, FBC_LL_BASE,
|
||||
|
|
@ -1100,7 +1103,7 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state,
|
|||
|
||||
/* Wa_14016291713 */
|
||||
if ((IS_DISPLAY_VER(i915, 12, 13) ||
|
||||
IS_MTL_DISPLAY_STEP(i915, STEP_A0, STEP_C0)) &&
|
||||
IS_DISPLAY_IP_STEP(i915, IP_VER(14, 0), STEP_A0, STEP_C0)) &&
|
||||
crtc_state->has_psr) {
|
||||
plane_state->no_fbc_reason = "PSR1 enabled (Wa_14016291713)";
|
||||
return 0;
|
||||
|
|
@ -1306,11 +1309,9 @@ static void __intel_fbc_post_update(struct intel_fbc *fbc)
|
|||
lockdep_assert_held(&fbc->lock);
|
||||
|
||||
fbc->flip_pending = false;
|
||||
fbc->busy_bits = 0;
|
||||
|
||||
if (!fbc->busy_bits)
|
||||
intel_fbc_activate(fbc);
|
||||
else
|
||||
intel_fbc_deactivate(fbc, "frontbuffer write");
|
||||
intel_fbc_activate(fbc);
|
||||
}
|
||||
|
||||
void intel_fbc_post_update(struct intel_atomic_state *state,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ struct intel_plane_state;
|
|||
enum intel_fbc_id {
|
||||
INTEL_FBC_A,
|
||||
INTEL_FBC_B,
|
||||
INTEL_FBC_C,
|
||||
INTEL_FBC_D,
|
||||
|
||||
I915_MAX_FBCS,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include "intel_display_types.h"
|
||||
#include "intel_fdi.h"
|
||||
#include "intel_fdi_regs.h"
|
||||
#include "intel_link_bw.h"
|
||||
|
||||
struct intel_fdi_funcs {
|
||||
void (*fdi_link_train)(struct intel_crtc *crtc,
|
||||
|
|
@ -119,6 +120,53 @@ void intel_fdi_link_train(struct intel_crtc *crtc,
|
|||
dev_priv->display.funcs.fdi->fdi_link_train(crtc, crtc_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_fdi_add_affected_crtcs - add CRTCs on FDI affected by other modeset CRTCs
|
||||
* @state: intel atomic state
|
||||
*
|
||||
* Add a CRTC using FDI to @state if changing another CRTC's FDI BW usage is
|
||||
* known to affect the available FDI BW for the former CRTC. In practice this
|
||||
* means adding CRTC B on IVYBRIDGE if its use of FDI lanes is limited (by
|
||||
* CRTC C) and CRTC C is getting disabled.
|
||||
*
|
||||
* Returns 0 in case of success, or a negative error code otherwise.
|
||||
*/
|
||||
int intel_fdi_add_affected_crtcs(struct intel_atomic_state *state)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(state->base.dev);
|
||||
const struct intel_crtc_state *old_crtc_state;
|
||||
const struct intel_crtc_state *new_crtc_state;
|
||||
struct intel_crtc *crtc;
|
||||
|
||||
if (!IS_IVYBRIDGE(i915) || INTEL_NUM_PIPES(i915) != 3)
|
||||
return 0;
|
||||
|
||||
crtc = intel_crtc_for_pipe(i915, PIPE_C);
|
||||
new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
|
||||
if (!new_crtc_state)
|
||||
return 0;
|
||||
|
||||
if (!intel_crtc_needs_modeset(new_crtc_state))
|
||||
return 0;
|
||||
|
||||
old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
|
||||
if (!old_crtc_state->fdi_lanes)
|
||||
return 0;
|
||||
|
||||
crtc = intel_crtc_for_pipe(i915, PIPE_B);
|
||||
new_crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
|
||||
if (IS_ERR(new_crtc_state))
|
||||
return PTR_ERR(new_crtc_state);
|
||||
|
||||
old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
|
||||
if (!old_crtc_state->fdi_lanes)
|
||||
return 0;
|
||||
|
||||
return intel_modeset_pipes_in_mask_early(state,
|
||||
"FDI link BW decrease on pipe C",
|
||||
BIT(PIPE_B));
|
||||
}
|
||||
|
||||
/* units of 100MHz */
|
||||
static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
|
|
@ -129,13 +177,16 @@ static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
|
|||
}
|
||||
|
||||
static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
struct intel_crtc_state *pipe_config,
|
||||
enum pipe *pipe_to_reduce)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct drm_atomic_state *state = pipe_config->uapi.state;
|
||||
struct intel_crtc *other_crtc;
|
||||
struct intel_crtc_state *other_crtc_state;
|
||||
|
||||
*pipe_to_reduce = pipe;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"checking fdi config on pipe %c, lanes %i\n",
|
||||
pipe_name(pipe), pipe_config->fdi_lanes);
|
||||
|
|
@ -198,6 +249,9 @@ static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
|
|||
if (pipe_required_fdi_lanes(other_crtc_state) > 2) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"fdi link B uses too many lanes to enable link C\n");
|
||||
|
||||
*pipe_to_reduce = PIPE_B;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -232,16 +286,42 @@ int intel_fdi_link_freq(struct drm_i915_private *i915,
|
|||
return i915->display.fdi.pll_freq;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_fdi_compute_pipe_bpp - compute pipe bpp limited by max link bpp
|
||||
* @crtc_state: the crtc state
|
||||
*
|
||||
* Compute the pipe bpp limited by the CRTC's maximum link bpp. Encoders can
|
||||
* call this function during state computation in the simple case where the
|
||||
* link bpp will always match the pipe bpp. This is the case for all non-DP
|
||||
* encoders, while DP encoders will use a link bpp lower than pipe bpp in case
|
||||
* of DSC compression.
|
||||
*
|
||||
* Returns %true in case of success, %false if pipe bpp would need to be
|
||||
* reduced below its valid range.
|
||||
*/
|
||||
bool intel_fdi_compute_pipe_bpp(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
int pipe_bpp = min(crtc_state->pipe_bpp,
|
||||
to_bpp_int(crtc_state->max_link_bpp_x16));
|
||||
|
||||
pipe_bpp = rounddown(pipe_bpp, 2 * 3);
|
||||
|
||||
if (pipe_bpp < 6 * 3)
|
||||
return false;
|
||||
|
||||
crtc_state->pipe_bpp = pipe_bpp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int ilk_fdi_compute_config(struct intel_crtc *crtc,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_device *dev = crtc->base.dev;
|
||||
struct drm_i915_private *i915 = to_i915(dev);
|
||||
const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
|
||||
int lane, link_bw, fdi_dotclock, ret;
|
||||
bool needs_recompute = false;
|
||||
int lane, link_bw, fdi_dotclock;
|
||||
|
||||
retry:
|
||||
/* FDI is a binary signal running at ~2.7GHz, encoding
|
||||
* each output octet as 10 bits. The actual frequency
|
||||
* is stored as a divider into a 100MHz clock, and the
|
||||
|
|
@ -261,25 +341,69 @@ retry:
|
|||
intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock,
|
||||
link_bw, &pipe_config->fdi_m_n, false);
|
||||
|
||||
ret = ilk_check_fdi_lanes(dev, crtc->pipe, pipe_config);
|
||||
if (ret == -EDEADLK)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_fdi_atomic_check_bw(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc,
|
||||
struct intel_crtc_state *pipe_config,
|
||||
struct intel_link_bw_limits *limits)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
enum pipe pipe_to_reduce;
|
||||
int ret;
|
||||
|
||||
ret = ilk_check_fdi_lanes(&i915->drm, crtc->pipe, pipe_config,
|
||||
&pipe_to_reduce);
|
||||
if (ret != -EINVAL)
|
||||
return ret;
|
||||
|
||||
if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) {
|
||||
pipe_config->pipe_bpp -= 2*3;
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"fdi link bw constraint, reducing pipe bpp to %i\n",
|
||||
pipe_config->pipe_bpp);
|
||||
needs_recompute = true;
|
||||
pipe_config->bw_constrained = true;
|
||||
ret = intel_link_bw_reduce_bpp(state, limits,
|
||||
BIT(pipe_to_reduce),
|
||||
"FDI link BW");
|
||||
|
||||
goto retry;
|
||||
return ret ? : -EAGAIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_fdi_atomic_check_link - check all modeset FDI link configuration
|
||||
* @state: intel atomic state
|
||||
* @limits: link BW limits
|
||||
*
|
||||
* Check the link configuration for all modeset FDI outputs. If the
|
||||
* configuration is invalid @limits will be updated if possible to
|
||||
* reduce the total BW, after which the configuration for all CRTCs in
|
||||
* @state must be recomputed with the updated @limits.
|
||||
*
|
||||
* Returns:
|
||||
* - 0 if the confugration is valid
|
||||
* - %-EAGAIN, if the configuration is invalid and @limits got updated
|
||||
* with fallback values with which the configuration of all CRTCs
|
||||
* in @state must be recomputed
|
||||
* - Other negative error, if the configuration is invalid without a
|
||||
* fallback possibility, or the check failed for another reason
|
||||
*/
|
||||
int intel_fdi_atomic_check_link(struct intel_atomic_state *state,
|
||||
struct intel_link_bw_limits *limits)
|
||||
{
|
||||
struct intel_crtc *crtc;
|
||||
struct intel_crtc_state *crtc_state;
|
||||
int i;
|
||||
|
||||
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
|
||||
int ret;
|
||||
|
||||
if (!crtc_state->has_pch_encoder ||
|
||||
!intel_crtc_needs_modeset(crtc_state) ||
|
||||
!crtc_state->hw.enable)
|
||||
continue;
|
||||
|
||||
ret = intel_fdi_atomic_check_bw(state, crtc, crtc_state, limits);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (needs_recompute)
|
||||
return -EAGAIN;
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cpt_set_fdi_bc_bifurcation(struct drm_i915_private *dev_priv, bool enable)
|
||||
|
|
@ -766,7 +890,10 @@ void hsw_fdi_link_train(struct intel_encoder *encoder,
|
|||
* WaFDIAutoLinkSetTimingOverrride:hsw
|
||||
*/
|
||||
intel_de_write(dev_priv, FDI_RX_MISC(PIPE_A),
|
||||
FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2) | FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
|
||||
FDI_RX_PWRDN_LANE1_VAL(2) |
|
||||
FDI_RX_PWRDN_LANE0_VAL(2) |
|
||||
FDI_RX_TP1_TO_TP2_48 |
|
||||
FDI_RX_FDI_DELAY_90);
|
||||
|
||||
/* Enable the PCH Receiver FDI PLL */
|
||||
rx_ctl_val = dev_priv->display.fdi.rx_config | FDI_RX_ENHANCE_FRAME_ENABLE |
|
||||
|
|
@ -799,7 +926,9 @@ void hsw_fdi_link_train(struct intel_encoder *encoder,
|
|||
* achieved on the PCH side in FDI_RX_CTL, so no need to set the
|
||||
* port reversal bit */
|
||||
intel_de_write(dev_priv, DDI_BUF_CTL(PORT_E),
|
||||
DDI_BUF_CTL_ENABLE | ((crtc_state->fdi_lanes - 1) << 1) | DDI_BUF_TRANS_SELECT(i / 2));
|
||||
DDI_BUF_CTL_ENABLE |
|
||||
((crtc_state->fdi_lanes - 1) << 1) |
|
||||
DDI_BUF_TRANS_SELECT(i / 2));
|
||||
intel_de_posting_read(dev_priv, DDI_BUF_CTL(PORT_E));
|
||||
|
||||
udelay(600);
|
||||
|
|
|
|||
|
|
@ -6,16 +6,24 @@
|
|||
#ifndef _INTEL_FDI_H_
|
||||
#define _INTEL_FDI_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
enum pipe;
|
||||
struct drm_i915_private;
|
||||
struct intel_atomic_state;
|
||||
struct intel_crtc;
|
||||
struct intel_crtc_state;
|
||||
struct intel_encoder;
|
||||
struct intel_link_bw_limits;
|
||||
|
||||
int intel_fdi_add_affected_crtcs(struct intel_atomic_state *state);
|
||||
int intel_fdi_link_freq(struct drm_i915_private *i915,
|
||||
const struct intel_crtc_state *pipe_config);
|
||||
bool intel_fdi_compute_pipe_bpp(struct intel_crtc_state *crtc_state);
|
||||
int ilk_fdi_compute_config(struct intel_crtc *intel_crtc,
|
||||
struct intel_crtc_state *pipe_config);
|
||||
int intel_fdi_atomic_check_link(struct intel_atomic_state *state,
|
||||
struct intel_link_bw_limits *limits);
|
||||
void intel_fdi_normal_train(struct intel_crtc *crtc);
|
||||
void ilk_fdi_disable(struct intel_crtc *crtc);
|
||||
void ilk_fdi_pll_disable(struct intel_crtc *intel_crtc);
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@
|
|||
* cancelled as soon as busyness is detected.
|
||||
*/
|
||||
|
||||
#include "gem/i915_gem_object_frontbuffer.h"
|
||||
#include "i915_drv.h"
|
||||
#include "intel_display_trace.h"
|
||||
#include "intel_display_types.h"
|
||||
|
|
@ -202,6 +203,33 @@ void __intel_fb_flush(struct intel_frontbuffer *front,
|
|||
frontbuffer_flush(i915, frontbuffer_bits, origin);
|
||||
}
|
||||
|
||||
static void intel_frontbuffer_flush_work(struct work_struct *work)
|
||||
{
|
||||
struct intel_frontbuffer *front =
|
||||
container_of(work, struct intel_frontbuffer, flush_work);
|
||||
|
||||
i915_gem_object_flush_if_display(front->obj);
|
||||
intel_frontbuffer_flush(front, ORIGIN_DIRTYFB);
|
||||
intel_frontbuffer_put(front);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_frontbuffer_queue_flush - queue flushing frontbuffer object
|
||||
* @front: GEM object to flush
|
||||
*
|
||||
* This function is targeted for our dirty callback for queueing flush when
|
||||
* dma fence is signales
|
||||
*/
|
||||
void intel_frontbuffer_queue_flush(struct intel_frontbuffer *front)
|
||||
{
|
||||
if (!front)
|
||||
return;
|
||||
|
||||
kref_get(&front->ref);
|
||||
if (!schedule_work(&front->flush_work))
|
||||
intel_frontbuffer_put(front);
|
||||
}
|
||||
|
||||
static int frontbuffer_active(struct i915_active *ref)
|
||||
{
|
||||
struct intel_frontbuffer *front =
|
||||
|
|
@ -223,7 +251,7 @@ static void frontbuffer_retire(struct i915_active *ref)
|
|||
static void frontbuffer_release(struct kref *ref)
|
||||
__releases(&intel_bo_to_i915(front->obj)->display.fb_tracking.lock)
|
||||
{
|
||||
struct intel_frontbuffer *front =
|
||||
struct intel_frontbuffer *ret, *front =
|
||||
container_of(ref, typeof(*front), ref);
|
||||
struct drm_i915_gem_object *obj = front->obj;
|
||||
|
||||
|
|
@ -231,7 +259,8 @@ static void frontbuffer_release(struct kref *ref)
|
|||
|
||||
i915_ggtt_clear_scanout(obj);
|
||||
|
||||
i915_gem_object_set_frontbuffer(obj, NULL);
|
||||
ret = i915_gem_object_set_frontbuffer(obj, NULL);
|
||||
drm_WARN_ON(&intel_bo_to_i915(obj)->drm, ret);
|
||||
spin_unlock(&intel_bo_to_i915(obj)->display.fb_tracking.lock);
|
||||
|
||||
i915_active_fini(&front->write);
|
||||
|
|
@ -261,6 +290,7 @@ intel_frontbuffer_get(struct drm_i915_gem_object *obj)
|
|||
frontbuffer_active,
|
||||
frontbuffer_retire,
|
||||
I915_ACTIVE_RETIRE_SLEEPS);
|
||||
INIT_WORK(&front->flush_work, intel_frontbuffer_flush_work);
|
||||
|
||||
spin_lock(&i915->display.fb_tracking.lock);
|
||||
cur = i915_gem_object_set_frontbuffer(obj, front);
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ struct intel_frontbuffer {
|
|||
struct i915_active write;
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct rcu_head rcu;
|
||||
|
||||
struct work_struct flush_work;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -135,6 +137,8 @@ static inline void intel_frontbuffer_flush(struct intel_frontbuffer *front,
|
|||
__intel_fb_flush(front, origin, frontbuffer_bits);
|
||||
}
|
||||
|
||||
void intel_frontbuffer_queue_flush(struct intel_frontbuffer *front);
|
||||
|
||||
void intel_frontbuffer_track(struct intel_frontbuffer *old,
|
||||
struct intel_frontbuffer *new,
|
||||
unsigned int frontbuffer_bits);
|
||||
|
|
|
|||
|
|
@ -155,7 +155,10 @@ static const struct gmbus_pin *get_gmbus_pin(struct drm_i915_private *i915,
|
|||
const struct gmbus_pin *pins;
|
||||
size_t size;
|
||||
|
||||
if (INTEL_PCH_TYPE(i915) >= PCH_DG2) {
|
||||
if (INTEL_PCH_TYPE(i915) >= PCH_LNL) {
|
||||
pins = gmbus_pins_mtp;
|
||||
size = ARRAY_SIZE(gmbus_pins_mtp);
|
||||
} else 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) {
|
||||
|
|
|
|||
|
|
@ -163,7 +163,6 @@ bool intel_hdcp_capable(struct intel_connector *connector)
|
|||
/* Is HDCP2.2 capable on Platform and Sink */
|
||||
bool intel_hdcp2_capable(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
struct intel_hdcp *hdcp = &connector->hdcp;
|
||||
bool capable = false;
|
||||
|
|
@ -193,7 +192,7 @@ bool intel_hdcp2_capable(struct intel_connector *connector)
|
|||
mutex_unlock(&i915->display.hdcp.hdcp_mutex);
|
||||
|
||||
/* Sink's capability for HDCP2.2 */
|
||||
hdcp->shim->hdcp_2_2_capable(dig_port, &capable);
|
||||
hdcp->shim->hdcp_2_2_capable(connector, &capable);
|
||||
|
||||
return capable;
|
||||
}
|
||||
|
|
@ -1415,7 +1414,6 @@ static int hdcp2_deauthenticate_port(struct intel_connector *connector)
|
|||
/* Authentication flow starts from here */
|
||||
static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
struct intel_hdcp *hdcp = &connector->hdcp;
|
||||
union {
|
||||
|
|
@ -1437,12 +1435,12 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = shim->write_2_2_msg(dig_port, &msgs.ake_init,
|
||||
ret = shim->write_2_2_msg(connector, &msgs.ake_init,
|
||||
sizeof(msgs.ake_init));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = shim->read_2_2_msg(dig_port, HDCP_2_2_AKE_SEND_CERT,
|
||||
ret = shim->read_2_2_msg(connector, HDCP_2_2_AKE_SEND_CERT,
|
||||
&msgs.send_cert, sizeof(msgs.send_cert));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
@ -1471,11 +1469,11 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = shim->write_2_2_msg(dig_port, &msgs.no_stored_km, size);
|
||||
ret = shim->write_2_2_msg(connector, &msgs.no_stored_km, size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = shim->read_2_2_msg(dig_port, HDCP_2_2_AKE_SEND_HPRIME,
|
||||
ret = shim->read_2_2_msg(connector, HDCP_2_2_AKE_SEND_HPRIME,
|
||||
&msgs.send_hprime, sizeof(msgs.send_hprime));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
@ -1486,7 +1484,7 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
|
|||
|
||||
if (!hdcp->is_paired) {
|
||||
/* Pairing is required */
|
||||
ret = shim->read_2_2_msg(dig_port,
|
||||
ret = shim->read_2_2_msg(connector,
|
||||
HDCP_2_2_AKE_SEND_PAIRING_INFO,
|
||||
&msgs.pairing_info,
|
||||
sizeof(msgs.pairing_info));
|
||||
|
|
@ -1504,7 +1502,6 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
|
|||
|
||||
static int hdcp2_locality_check(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
|
||||
struct intel_hdcp *hdcp = &connector->hdcp;
|
||||
union {
|
||||
struct hdcp2_lc_init lc_init;
|
||||
|
|
@ -1518,12 +1515,12 @@ static int hdcp2_locality_check(struct intel_connector *connector)
|
|||
if (ret < 0)
|
||||
continue;
|
||||
|
||||
ret = shim->write_2_2_msg(dig_port, &msgs.lc_init,
|
||||
ret = shim->write_2_2_msg(connector, &msgs.lc_init,
|
||||
sizeof(msgs.lc_init));
|
||||
if (ret < 0)
|
||||
continue;
|
||||
|
||||
ret = shim->read_2_2_msg(dig_port,
|
||||
ret = shim->read_2_2_msg(connector,
|
||||
HDCP_2_2_LC_SEND_LPRIME,
|
||||
&msgs.send_lprime,
|
||||
sizeof(msgs.send_lprime));
|
||||
|
|
@ -1540,7 +1537,6 @@ static int hdcp2_locality_check(struct intel_connector *connector)
|
|||
|
||||
static int hdcp2_session_key_exchange(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
|
||||
struct intel_hdcp *hdcp = &connector->hdcp;
|
||||
struct hdcp2_ske_send_eks send_eks;
|
||||
int ret;
|
||||
|
|
@ -1549,7 +1545,7 @@ static int hdcp2_session_key_exchange(struct intel_connector *connector)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = hdcp->shim->write_2_2_msg(dig_port, &send_eks,
|
||||
ret = hdcp->shim->write_2_2_msg(connector, &send_eks,
|
||||
sizeof(send_eks));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
@ -1587,12 +1583,12 @@ int _hdcp2_propagate_stream_management_info(struct intel_connector *connector)
|
|||
streams_size_delta = (HDCP_2_2_MAX_CONTENT_STREAMS_CNT - data->k) *
|
||||
sizeof(struct hdcp2_streamid_type);
|
||||
/* Send it to Repeater */
|
||||
ret = shim->write_2_2_msg(dig_port, &msgs.stream_manage,
|
||||
ret = shim->write_2_2_msg(connector, &msgs.stream_manage,
|
||||
sizeof(msgs.stream_manage) - streams_size_delta);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = shim->read_2_2_msg(dig_port, HDCP_2_2_REP_STREAM_READY,
|
||||
ret = shim->read_2_2_msg(connector, HDCP_2_2_REP_STREAM_READY,
|
||||
&msgs.stream_ready, sizeof(msgs.stream_ready));
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
|
@ -1622,7 +1618,7 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
|
|||
u8 *rx_info;
|
||||
int ret;
|
||||
|
||||
ret = shim->read_2_2_msg(dig_port, HDCP_2_2_REP_SEND_RECVID_LIST,
|
||||
ret = shim->read_2_2_msg(connector, HDCP_2_2_REP_SEND_RECVID_LIST,
|
||||
&msgs.recvid_list, sizeof(msgs.recvid_list));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
@ -1675,7 +1671,7 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
|
|||
return ret;
|
||||
|
||||
hdcp->seq_num_v = seq_num_v;
|
||||
ret = shim->write_2_2_msg(dig_port, &msgs.rep_ack,
|
||||
ret = shim->write_2_2_msg(connector, &msgs.rep_ack,
|
||||
sizeof(msgs.rep_ack));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
@ -1685,7 +1681,6 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
|
|||
|
||||
static int hdcp2_authenticate_sink(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
struct intel_hdcp *hdcp = &connector->hdcp;
|
||||
const struct intel_hdcp_shim *shim = hdcp->shim;
|
||||
|
|
@ -1711,7 +1706,7 @@ static int hdcp2_authenticate_sink(struct intel_connector *connector)
|
|||
}
|
||||
|
||||
if (shim->config_stream_type) {
|
||||
ret = shim->config_stream_type(dig_port,
|
||||
ret = shim->config_stream_type(connector,
|
||||
hdcp->is_repeater,
|
||||
hdcp->content_type);
|
||||
if (ret < 0)
|
||||
|
|
|
|||
|
|
@ -1240,26 +1240,23 @@ static void hsw_set_infoframes(struct intel_encoder *encoder,
|
|||
void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = intel_hdmi_to_i915(hdmi);
|
||||
struct i2c_adapter *adapter;
|
||||
struct i2c_adapter *ddc = hdmi->attached_connector->base.ddc;
|
||||
|
||||
if (hdmi->dp_dual_mode.type < DRM_DP_DUAL_MODE_TYPE2_DVI)
|
||||
return;
|
||||
|
||||
adapter = intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus);
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "%s DP dual mode adaptor TMDS output\n",
|
||||
enable ? "Enabling" : "Disabling");
|
||||
|
||||
drm_dp_dual_mode_set_tmds_output(&dev_priv->drm, hdmi->dp_dual_mode.type, adapter, enable);
|
||||
drm_dp_dual_mode_set_tmds_output(&dev_priv->drm,
|
||||
hdmi->dp_dual_mode.type, ddc, enable);
|
||||
}
|
||||
|
||||
static int intel_hdmi_hdcp_read(struct intel_digital_port *dig_port,
|
||||
unsigned int offset, void *buffer, size_t size)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
|
||||
struct intel_hdmi *hdmi = &dig_port->hdmi;
|
||||
struct i2c_adapter *adapter = intel_gmbus_get_adapter(i915,
|
||||
hdmi->ddc_bus);
|
||||
struct i2c_adapter *ddc = hdmi->attached_connector->base.ddc;
|
||||
int ret;
|
||||
u8 start = offset & 0xff;
|
||||
struct i2c_msg msgs[] = {
|
||||
|
|
@ -1276,7 +1273,7 @@ static int intel_hdmi_hdcp_read(struct intel_digital_port *dig_port,
|
|||
.buf = buffer
|
||||
}
|
||||
};
|
||||
ret = i2c_transfer(adapter, msgs, ARRAY_SIZE(msgs));
|
||||
ret = i2c_transfer(ddc, msgs, ARRAY_SIZE(msgs));
|
||||
if (ret == ARRAY_SIZE(msgs))
|
||||
return 0;
|
||||
return ret >= 0 ? -EIO : ret;
|
||||
|
|
@ -1285,10 +1282,8 @@ static int intel_hdmi_hdcp_read(struct intel_digital_port *dig_port,
|
|||
static int intel_hdmi_hdcp_write(struct intel_digital_port *dig_port,
|
||||
unsigned int offset, void *buffer, size_t size)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
|
||||
struct intel_hdmi *hdmi = &dig_port->hdmi;
|
||||
struct i2c_adapter *adapter = intel_gmbus_get_adapter(i915,
|
||||
hdmi->ddc_bus);
|
||||
struct i2c_adapter *ddc = hdmi->attached_connector->base.ddc;
|
||||
int ret;
|
||||
u8 *write_buf;
|
||||
struct i2c_msg msg;
|
||||
|
|
@ -1305,7 +1300,7 @@ static int intel_hdmi_hdcp_write(struct intel_digital_port *dig_port,
|
|||
msg.len = size + 1,
|
||||
msg.buf = write_buf;
|
||||
|
||||
ret = i2c_transfer(adapter, &msg, 1);
|
||||
ret = i2c_transfer(ddc, &msg, 1);
|
||||
if (ret == 1)
|
||||
ret = 0;
|
||||
else if (ret >= 0)
|
||||
|
|
@ -1321,8 +1316,7 @@ int intel_hdmi_hdcp_write_an_aksv(struct intel_digital_port *dig_port,
|
|||
{
|
||||
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
|
||||
struct intel_hdmi *hdmi = &dig_port->hdmi;
|
||||
struct i2c_adapter *adapter = intel_gmbus_get_adapter(i915,
|
||||
hdmi->ddc_bus);
|
||||
struct i2c_adapter *ddc = hdmi->attached_connector->base.ddc;
|
||||
int ret;
|
||||
|
||||
ret = intel_hdmi_hdcp_write(dig_port, DRM_HDCP_DDC_AN, an,
|
||||
|
|
@ -1333,7 +1327,7 @@ int intel_hdmi_hdcp_write_an_aksv(struct intel_digital_port *dig_port,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = intel_gmbus_output_aksv(adapter);
|
||||
ret = intel_gmbus_output_aksv(ddc);
|
||||
if (ret < 0) {
|
||||
drm_dbg_kms(&i915->drm, "Failed to output aksv (%d)\n", ret);
|
||||
return ret;
|
||||
|
|
@ -1665,9 +1659,10 @@ intel_hdmi_hdcp2_wait_for_msg(struct intel_digital_port *dig_port,
|
|||
}
|
||||
|
||||
static
|
||||
int intel_hdmi_hdcp2_write_msg(struct intel_digital_port *dig_port,
|
||||
int intel_hdmi_hdcp2_write_msg(struct intel_connector *connector,
|
||||
void *buf, size_t size)
|
||||
{
|
||||
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
|
||||
unsigned int offset;
|
||||
|
||||
offset = HDCP_2_2_HDMI_REG_WR_MSG_OFFSET;
|
||||
|
|
@ -1675,9 +1670,10 @@ int intel_hdmi_hdcp2_write_msg(struct intel_digital_port *dig_port,
|
|||
}
|
||||
|
||||
static
|
||||
int intel_hdmi_hdcp2_read_msg(struct intel_digital_port *dig_port,
|
||||
int intel_hdmi_hdcp2_read_msg(struct intel_connector *connector,
|
||||
u8 msg_id, void *buf, size_t size)
|
||||
{
|
||||
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
|
||||
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
|
||||
struct intel_hdmi *hdmi = &dig_port->hdmi;
|
||||
struct intel_hdcp *hdcp = &hdmi->attached_connector->hdcp;
|
||||
|
|
@ -1733,9 +1729,10 @@ int intel_hdmi_hdcp2_check_link(struct intel_digital_port *dig_port,
|
|||
}
|
||||
|
||||
static
|
||||
int intel_hdmi_hdcp2_capable(struct intel_digital_port *dig_port,
|
||||
int intel_hdmi_hdcp2_capable(struct intel_connector *connector,
|
||||
bool *capable)
|
||||
{
|
||||
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
|
||||
u8 hdcp2_version;
|
||||
int ret;
|
||||
|
||||
|
|
@ -2400,9 +2397,10 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector)
|
|||
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
||||
struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector));
|
||||
struct intel_encoder *encoder = &hdmi_to_dig_port(hdmi)->base;
|
||||
struct i2c_adapter *adapter =
|
||||
intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus);
|
||||
enum drm_dp_dual_mode_type type = drm_dp_dual_mode_detect(&dev_priv->drm, adapter);
|
||||
struct i2c_adapter *ddc = connector->ddc;
|
||||
enum drm_dp_dual_mode_type type;
|
||||
|
||||
type = drm_dp_dual_mode_detect(&dev_priv->drm, ddc);
|
||||
|
||||
/*
|
||||
* Type 1 DVI adaptors are not required to implement any
|
||||
|
|
@ -2429,7 +2427,7 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector)
|
|||
|
||||
hdmi->dp_dual_mode.type = type;
|
||||
hdmi->dp_dual_mode.max_tmds_clock =
|
||||
drm_dp_dual_mode_max_tmds_clock(&dev_priv->drm, type, adapter);
|
||||
drm_dp_dual_mode_max_tmds_clock(&dev_priv->drm, type, ddc);
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"DP dual mode adaptor (%s) detected (max TMDS clock: %d kHz)\n",
|
||||
|
|
@ -2450,24 +2448,21 @@ intel_hdmi_set_edid(struct drm_connector *connector)
|
|||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
||||
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector));
|
||||
struct i2c_adapter *ddc = connector->ddc;
|
||||
intel_wakeref_t wakeref;
|
||||
const struct drm_edid *drm_edid;
|
||||
const struct edid *edid;
|
||||
bool connected = false;
|
||||
struct i2c_adapter *i2c;
|
||||
|
||||
wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
|
||||
|
||||
i2c = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
|
||||
drm_edid = drm_edid_read_ddc(connector, ddc);
|
||||
|
||||
drm_edid = drm_edid_read_ddc(connector, i2c);
|
||||
|
||||
if (!drm_edid && !intel_gmbus_is_forced_bit(i2c)) {
|
||||
if (!drm_edid && !intel_gmbus_is_forced_bit(ddc)) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"HDMI GMBUS EDID read failed, retry using GPIO bit-banging\n");
|
||||
intel_gmbus_force_bit(i2c, true);
|
||||
drm_edid = drm_edid_read_ddc(connector, i2c);
|
||||
intel_gmbus_force_bit(i2c, false);
|
||||
intel_gmbus_force_bit(ddc, true);
|
||||
drm_edid = drm_edid_read_ddc(connector, ddc);
|
||||
intel_gmbus_force_bit(ddc, false);
|
||||
}
|
||||
|
||||
/* Below we depend on display info having been updated */
|
||||
|
|
@ -2475,9 +2470,7 @@ intel_hdmi_set_edid(struct drm_connector *connector)
|
|||
|
||||
to_intel_connector(connector)->detect_edid = drm_edid;
|
||||
|
||||
/* FIXME: Get rid of drm_edid_raw() */
|
||||
edid = drm_edid_raw(drm_edid);
|
||||
if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
|
||||
if (drm_edid_is_digital(drm_edid)) {
|
||||
intel_hdmi_dp_dual_mode_detect(connector);
|
||||
|
||||
connected = true;
|
||||
|
|
@ -2485,7 +2478,8 @@ intel_hdmi_set_edid(struct drm_connector *connector)
|
|||
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
|
||||
|
||||
cec_notifier_set_phys_addr_from_edid(intel_hdmi->cec_notifier, edid);
|
||||
cec_notifier_set_phys_addr(intel_hdmi->cec_notifier,
|
||||
connector->display_info.source_physical_address);
|
||||
|
||||
return connected;
|
||||
}
|
||||
|
|
@ -2522,12 +2516,6 @@ out:
|
|||
if (status != connector_status_connected)
|
||||
cec_notifier_phys_addr_invalidate(intel_hdmi->cec_notifier);
|
||||
|
||||
/*
|
||||
* Make sure the refs for power wells enabled during detect are
|
||||
* dropped to avoid a new detect cycle triggered by HPD polling.
|
||||
*/
|
||||
intel_display_power_flush_work(dev_priv);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -2553,37 +2541,6 @@ static int intel_hdmi_get_modes(struct drm_connector *connector)
|
|||
return drm_edid_connector_add_modes(connector);
|
||||
}
|
||||
|
||||
static struct i2c_adapter *
|
||||
intel_hdmi_get_i2c_adapter(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
||||
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector));
|
||||
|
||||
return intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
|
||||
}
|
||||
|
||||
static void intel_hdmi_create_i2c_symlink(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(connector->dev);
|
||||
struct i2c_adapter *adapter = intel_hdmi_get_i2c_adapter(connector);
|
||||
struct kobject *i2c_kobj = &adapter->dev.kobj;
|
||||
struct kobject *connector_kobj = &connector->kdev->kobj;
|
||||
int ret;
|
||||
|
||||
ret = sysfs_create_link(connector_kobj, i2c_kobj, i2c_kobj->name);
|
||||
if (ret)
|
||||
drm_err(&i915->drm, "Failed to create i2c symlink (%d)\n", ret);
|
||||
}
|
||||
|
||||
static void intel_hdmi_remove_i2c_symlink(struct drm_connector *connector)
|
||||
{
|
||||
struct i2c_adapter *adapter = intel_hdmi_get_i2c_adapter(connector);
|
||||
struct kobject *i2c_kobj = &adapter->dev.kobj;
|
||||
struct kobject *connector_kobj = &connector->kdev->kobj;
|
||||
|
||||
sysfs_remove_link(connector_kobj, i2c_kobj->name);
|
||||
}
|
||||
|
||||
static int
|
||||
intel_hdmi_connector_register(struct drm_connector *connector)
|
||||
{
|
||||
|
|
@ -2593,8 +2550,6 @@ intel_hdmi_connector_register(struct drm_connector *connector)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
intel_hdmi_create_i2c_symlink(connector);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -2604,7 +2559,6 @@ static void intel_hdmi_connector_unregister(struct drm_connector *connector)
|
|||
|
||||
cec_notifier_conn_unregister(n);
|
||||
|
||||
intel_hdmi_remove_i2c_symlink(connector);
|
||||
intel_connector_unregister(connector);
|
||||
}
|
||||
|
||||
|
|
@ -2918,13 +2872,17 @@ get_encoder_by_ddc_pin(struct intel_encoder *encoder, u8 ddc_pin)
|
|||
struct intel_encoder *other;
|
||||
|
||||
for_each_intel_encoder(&i915->drm, other) {
|
||||
struct intel_connector *connector;
|
||||
|
||||
if (other == encoder)
|
||||
continue;
|
||||
|
||||
if (!intel_encoder_is_dig_port(other))
|
||||
continue;
|
||||
|
||||
if (enc_to_dig_port(other)->hdmi.ddc_bus == ddc_pin)
|
||||
connector = enc_to_dig_port(other)->hdmi.attached_connector;
|
||||
|
||||
if (connector && connector->base.ddc == intel_gmbus_get_adapter(i915, ddc_pin))
|
||||
return other;
|
||||
}
|
||||
|
||||
|
|
@ -3016,9 +2974,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port,
|
|||
struct intel_encoder *intel_encoder = &dig_port->base;
|
||||
struct drm_device *dev = intel_encoder->base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct i2c_adapter *ddc;
|
||||
enum port port = intel_encoder->port;
|
||||
struct cec_connector_info conn_info;
|
||||
u8 ddc_pin;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Adding HDMI connector on [ENCODER:%d:%s]\n",
|
||||
|
|
@ -3033,16 +2991,15 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port,
|
|||
intel_encoder->base.name))
|
||||
return;
|
||||
|
||||
intel_hdmi->ddc_bus = intel_hdmi_ddc_pin(intel_encoder);
|
||||
if (!intel_hdmi->ddc_bus)
|
||||
ddc_pin = intel_hdmi_ddc_pin(intel_encoder);
|
||||
if (!ddc_pin)
|
||||
return;
|
||||
|
||||
ddc = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
|
||||
|
||||
drm_connector_init_with_ddc(dev, connector,
|
||||
&intel_hdmi_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_HDMIA,
|
||||
ddc);
|
||||
intel_gmbus_get_adapter(dev_priv, ddc_pin));
|
||||
|
||||
drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs);
|
||||
|
||||
if (DISPLAY_VER(dev_priv) < 12)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_irq.h"
|
||||
#include "intel_display_power.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_hotplug.h"
|
||||
#include "intel_hotplug_irq.h"
|
||||
|
|
@ -259,21 +260,22 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
|
|||
intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
|
||||
}
|
||||
|
||||
enum intel_hotplug_state
|
||||
intel_encoder_hotplug(struct intel_encoder *encoder,
|
||||
struct intel_connector *connector)
|
||||
static enum intel_hotplug_state
|
||||
intel_hotplug_detect_connector(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
enum drm_connector_status old_status;
|
||||
u64 old_epoch_counter;
|
||||
int status;
|
||||
bool ret = false;
|
||||
|
||||
drm_WARN_ON(dev, !mutex_is_locked(&dev->mode_config.mutex));
|
||||
old_status = connector->base.status;
|
||||
old_epoch_counter = connector->base.epoch_counter;
|
||||
|
||||
connector->base.status =
|
||||
drm_helper_probe_detect(&connector->base, NULL, false);
|
||||
status = drm_helper_probe_detect(&connector->base, NULL, false);
|
||||
if (!connector->base.force)
|
||||
connector->base.status = status;
|
||||
|
||||
if (old_epoch_counter != connector->base.epoch_counter)
|
||||
ret = true;
|
||||
|
|
@ -291,6 +293,13 @@ intel_encoder_hotplug(struct intel_encoder *encoder,
|
|||
return INTEL_HOTPLUG_UNCHANGED;
|
||||
}
|
||||
|
||||
enum intel_hotplug_state
|
||||
intel_encoder_hotplug(struct intel_encoder *encoder,
|
||||
struct intel_connector *connector)
|
||||
{
|
||||
return intel_hotplug_detect_connector(connector);
|
||||
}
|
||||
|
||||
static bool intel_encoder_has_hpd_pulse(struct intel_encoder *encoder)
|
||||
{
|
||||
return intel_encoder_is_dig_port(encoder) &&
|
||||
|
|
@ -631,6 +640,49 @@ void intel_hpd_init(struct drm_i915_private *dev_priv)
|
|||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
}
|
||||
|
||||
static void i915_hpd_poll_detect_connectors(struct drm_i915_private *i915)
|
||||
{
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
struct intel_connector *connector;
|
||||
struct intel_connector *first_changed_connector = NULL;
|
||||
int changed = 0;
|
||||
|
||||
mutex_lock(&i915->drm.mode_config.mutex);
|
||||
|
||||
if (!i915->drm.mode_config.poll_enabled)
|
||||
goto out;
|
||||
|
||||
drm_connector_list_iter_begin(&i915->drm, &conn_iter);
|
||||
for_each_intel_connector_iter(connector, &conn_iter) {
|
||||
if (!(connector->base.polled & DRM_CONNECTOR_POLL_HPD))
|
||||
continue;
|
||||
|
||||
if (intel_hotplug_detect_connector(connector) != INTEL_HOTPLUG_CHANGED)
|
||||
continue;
|
||||
|
||||
changed++;
|
||||
|
||||
if (changed == 1) {
|
||||
drm_connector_get(&connector->base);
|
||||
first_changed_connector = connector;
|
||||
}
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
|
||||
out:
|
||||
mutex_unlock(&i915->drm.mode_config.mutex);
|
||||
|
||||
if (!changed)
|
||||
return;
|
||||
|
||||
if (changed == 1)
|
||||
drm_kms_helper_connector_hotplug_event(&first_changed_connector->base);
|
||||
else
|
||||
drm_kms_helper_hotplug_event(&i915->drm);
|
||||
|
||||
drm_connector_put(&first_changed_connector->base);
|
||||
}
|
||||
|
||||
static void i915_hpd_poll_init_work(struct work_struct *work)
|
||||
{
|
||||
struct drm_i915_private *dev_priv =
|
||||
|
|
@ -638,11 +690,25 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
|
|||
display.hotplug.poll_init_work);
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
struct intel_connector *connector;
|
||||
intel_wakeref_t wakeref;
|
||||
bool enabled;
|
||||
|
||||
mutex_lock(&dev_priv->drm.mode_config.mutex);
|
||||
|
||||
enabled = READ_ONCE(dev_priv->display.hotplug.poll_enabled);
|
||||
/*
|
||||
* Prevent taking a power reference from this sequence of
|
||||
* i915_hpd_poll_init_work() -> drm_helper_hpd_irq_event() ->
|
||||
* connector detect which would requeue i915_hpd_poll_init_work()
|
||||
* and so risk an endless loop of this same sequence.
|
||||
*/
|
||||
if (!enabled) {
|
||||
wakeref = intel_display_power_get(dev_priv,
|
||||
POWER_DOMAIN_DISPLAY_CORE);
|
||||
drm_WARN_ON(&dev_priv->drm,
|
||||
READ_ONCE(dev_priv->display.hotplug.poll_enabled));
|
||||
cancel_work(&dev_priv->display.hotplug.poll_init_work);
|
||||
}
|
||||
|
||||
drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
|
||||
for_each_intel_connector_iter(connector, &conn_iter) {
|
||||
|
|
@ -669,8 +735,13 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
|
|||
* We might have missed any hotplugs that happened while we were
|
||||
* in the middle of disabling polling
|
||||
*/
|
||||
if (!enabled)
|
||||
drm_helper_hpd_irq_event(&dev_priv->drm);
|
||||
if (!enabled) {
|
||||
i915_hpd_poll_detect_connectors(dev_priv);
|
||||
|
||||
intel_display_power_put(dev_priv,
|
||||
POWER_DOMAIN_DISPLAY_CORE,
|
||||
wakeref);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -163,7 +163,9 @@ static void intel_hpd_init_pins(struct drm_i915_private *dev_priv)
|
|||
(!HAS_PCH_SPLIT(dev_priv) || HAS_PCH_NOP(dev_priv)))
|
||||
return;
|
||||
|
||||
if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
|
||||
if (INTEL_PCH_TYPE(dev_priv) >= PCH_LNL)
|
||||
hpd->pch_hpd = hpd_mtp;
|
||||
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
|
||||
hpd->pch_hpd = hpd_sde_dg1;
|
||||
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_MTP)
|
||||
hpd->pch_hpd = hpd_mtp;
|
||||
|
|
@ -514,6 +516,9 @@ void xelpdp_pica_irq_handler(struct drm_i915_private *i915, u32 iir)
|
|||
u32 trigger_aux = iir & XELPDP_AUX_TC_MASK;
|
||||
u32 pin_mask = 0, long_mask = 0;
|
||||
|
||||
if (DISPLAY_VER(i915) >= 20)
|
||||
trigger_aux |= iir & XE2LPD_AUX_DDI_MASK;
|
||||
|
||||
for (pin = HPD_PORT_TC1; pin <= HPD_PORT_TC4; pin++) {
|
||||
u32 val;
|
||||
|
||||
|
|
@ -1060,6 +1065,19 @@ static void mtp_hpd_irq_setup(struct drm_i915_private *i915)
|
|||
mtp_tc_hpd_detection_setup(i915);
|
||||
}
|
||||
|
||||
static void xe2lpd_sde_hpd_irq_setup(struct drm_i915_private *i915)
|
||||
{
|
||||
u32 hotplug_irqs, enabled_irqs;
|
||||
|
||||
enabled_irqs = intel_hpd_enabled_irqs(i915, i915->display.hotplug.pch_hpd);
|
||||
hotplug_irqs = intel_hpd_hotplug_irqs(i915, i915->display.hotplug.pch_hpd);
|
||||
|
||||
ibx_display_interrupt_update(i915, hotplug_irqs, enabled_irqs);
|
||||
|
||||
mtp_ddi_hpd_detection_setup(i915);
|
||||
mtp_tc_hpd_detection_setup(i915);
|
||||
}
|
||||
|
||||
static bool is_xelpdp_pica_hpd_pin(enum hpd_pin hpd_pin)
|
||||
{
|
||||
return hpd_pin >= HPD_PORT_TC1 && hpd_pin <= HPD_PORT_TC4;
|
||||
|
|
@ -1119,7 +1137,9 @@ static void xelpdp_hpd_irq_setup(struct drm_i915_private *i915)
|
|||
|
||||
xelpdp_pica_hpd_detection_setup(i915);
|
||||
|
||||
if (INTEL_PCH_TYPE(i915) >= PCH_MTP)
|
||||
if (INTEL_PCH_TYPE(i915) >= PCH_LNL)
|
||||
xe2lpd_sde_hpd_irq_setup(i915);
|
||||
else if (INTEL_PCH_TYPE(i915) >= PCH_MTP)
|
||||
mtp_hpd_irq_setup(i915);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,212 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright © 2023 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "i915_drv.h"
|
||||
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_fdi.h"
|
||||
#include "intel_link_bw.h"
|
||||
|
||||
/**
|
||||
* intel_link_bw_init_limits - initialize BW limits
|
||||
* @i915: device instance
|
||||
* @limits: link BW limits
|
||||
*
|
||||
* Initialize @limits.
|
||||
*/
|
||||
void intel_link_bw_init_limits(struct drm_i915_private *i915, struct intel_link_bw_limits *limits)
|
||||
{
|
||||
enum pipe pipe;
|
||||
|
||||
limits->bpp_limit_reached_pipes = 0;
|
||||
for_each_pipe(i915, pipe)
|
||||
limits->max_bpp_x16[pipe] = INT_MAX;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_link_bw_reduce_bpp - reduce maximum link bpp for a selected pipe
|
||||
* @state: atomic state
|
||||
* @limits: link BW limits
|
||||
* @pipe_mask: mask of pipes to select from
|
||||
* @reason: explanation of why bpp reduction is needed
|
||||
*
|
||||
* Select the pipe from @pipe_mask with the biggest link bpp value and set the
|
||||
* maximum of link bpp in @limits below this value. Modeset the selected pipe,
|
||||
* so that its state will get recomputed.
|
||||
*
|
||||
* This function can be called to resolve a link's BW overallocation by reducing
|
||||
* the link bpp of one pipe on the link and hence reducing the total link BW.
|
||||
*
|
||||
* Returns
|
||||
* - 0 in case of success
|
||||
* - %-ENOSPC if no pipe can further reduce its link bpp
|
||||
* - Other negative error, if modesetting the selected pipe failed
|
||||
*/
|
||||
int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
|
||||
struct intel_link_bw_limits *limits,
|
||||
u8 pipe_mask,
|
||||
const char *reason)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(state->base.dev);
|
||||
enum pipe max_bpp_pipe = INVALID_PIPE;
|
||||
struct intel_crtc *crtc;
|
||||
int max_bpp = 0;
|
||||
|
||||
for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, pipe_mask) {
|
||||
struct intel_crtc_state *crtc_state;
|
||||
int link_bpp;
|
||||
|
||||
if (limits->bpp_limit_reached_pipes & BIT(crtc->pipe))
|
||||
continue;
|
||||
|
||||
crtc_state = intel_atomic_get_crtc_state(&state->base,
|
||||
crtc);
|
||||
if (IS_ERR(crtc_state))
|
||||
return PTR_ERR(crtc_state);
|
||||
|
||||
if (crtc_state->dsc.compression_enable)
|
||||
link_bpp = crtc_state->dsc.compressed_bpp;
|
||||
else
|
||||
/*
|
||||
* TODO: for YUV420 the actual link bpp is only half
|
||||
* of the pipe bpp value. The MST encoder's BW allocation
|
||||
* is based on the pipe bpp value, set the actual link bpp
|
||||
* limit here once the MST BW allocation is fixed.
|
||||
*/
|
||||
link_bpp = crtc_state->pipe_bpp;
|
||||
|
||||
if (link_bpp > max_bpp) {
|
||||
max_bpp = link_bpp;
|
||||
max_bpp_pipe = crtc->pipe;
|
||||
}
|
||||
}
|
||||
|
||||
if (max_bpp_pipe == INVALID_PIPE)
|
||||
return -ENOSPC;
|
||||
|
||||
limits->max_bpp_x16[max_bpp_pipe] = to_bpp_x16(max_bpp) - 1;
|
||||
|
||||
return intel_modeset_pipes_in_mask_early(state, reason,
|
||||
BIT(max_bpp_pipe));
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_link_bw_set_bpp_limit_for_pipe - set link bpp limit for a pipe to its minimum
|
||||
* @state: atomic state
|
||||
* @old_limits: link BW limits
|
||||
* @new_limits: link BW limits
|
||||
* @pipe: pipe
|
||||
*
|
||||
* Set the link bpp limit for @pipe in @new_limits to its value in
|
||||
* @old_limits and mark this limit as the minimum. This function must be
|
||||
* called after a pipe's compute config function failed, @old_limits
|
||||
* containing the bpp limit with which compute config previously passed.
|
||||
*
|
||||
* The function will fail if setting a minimum is not possible, either
|
||||
* because the old and new limits match (and so would lead to a pipe compute
|
||||
* config failure) or the limit is already at the minimum.
|
||||
*
|
||||
* Returns %true in case of success.
|
||||
*/
|
||||
bool
|
||||
intel_link_bw_set_bpp_limit_for_pipe(struct intel_atomic_state *state,
|
||||
const struct intel_link_bw_limits *old_limits,
|
||||
struct intel_link_bw_limits *new_limits,
|
||||
enum pipe pipe)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(state->base.dev);
|
||||
|
||||
if (pipe == INVALID_PIPE)
|
||||
return false;
|
||||
|
||||
if (new_limits->max_bpp_x16[pipe] ==
|
||||
old_limits->max_bpp_x16[pipe])
|
||||
return false;
|
||||
|
||||
if (drm_WARN_ON(&i915->drm,
|
||||
new_limits->bpp_limit_reached_pipes & BIT(pipe)))
|
||||
return false;
|
||||
|
||||
new_limits->max_bpp_x16[pipe] =
|
||||
old_limits->max_bpp_x16[pipe];
|
||||
new_limits->bpp_limit_reached_pipes |= BIT(pipe);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int check_all_link_config(struct intel_atomic_state *state,
|
||||
struct intel_link_bw_limits *limits)
|
||||
{
|
||||
/* TODO: Check additional shared display link configurations like MST */
|
||||
int ret;
|
||||
|
||||
ret = intel_fdi_atomic_check_link(state, limits);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
assert_link_limit_change_valid(struct drm_i915_private *i915,
|
||||
const struct intel_link_bw_limits *old_limits,
|
||||
const struct intel_link_bw_limits *new_limits)
|
||||
{
|
||||
bool bpps_changed = false;
|
||||
enum pipe pipe;
|
||||
|
||||
for_each_pipe(i915, pipe) {
|
||||
/* The bpp limit can only decrease. */
|
||||
if (drm_WARN_ON(&i915->drm,
|
||||
new_limits->max_bpp_x16[pipe] >
|
||||
old_limits->max_bpp_x16[pipe]))
|
||||
return false;
|
||||
|
||||
if (new_limits->max_bpp_x16[pipe] <
|
||||
old_limits->max_bpp_x16[pipe])
|
||||
bpps_changed = true;
|
||||
}
|
||||
|
||||
/* At least one limit must change. */
|
||||
if (drm_WARN_ON(&i915->drm,
|
||||
!bpps_changed))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_link_bw_atomic_check - check display link states and set a fallback config if needed
|
||||
* @state: atomic state
|
||||
* @new_limits: link BW limits
|
||||
*
|
||||
* Check the configuration of all shared display links in @state and set new BW
|
||||
* limits in @new_limits if there is a BW limitation.
|
||||
*
|
||||
* Returns:
|
||||
* - 0 if the confugration is valid
|
||||
* - %-EAGAIN, if the configuration is invalid and @new_limits got updated
|
||||
* with fallback values with which the configuration of all CRTCs
|
||||
* in @state must be recomputed
|
||||
* - Other negative error, if the configuration is invalid without a
|
||||
* fallback possibility, or the check failed for another reason
|
||||
*/
|
||||
int intel_link_bw_atomic_check(struct intel_atomic_state *state,
|
||||
struct intel_link_bw_limits *new_limits)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(state->base.dev);
|
||||
struct intel_link_bw_limits old_limits = *new_limits;
|
||||
int ret;
|
||||
|
||||
ret = check_all_link_config(state, new_limits);
|
||||
if (ret != -EAGAIN)
|
||||
return ret;
|
||||
|
||||
if (!assert_link_limit_change_valid(i915, &old_limits, new_limits))
|
||||
return -EINVAL;
|
||||
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2023 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_LINK_BW_H__
|
||||
#define __INTEL_LINK_BW_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "intel_display_limits.h"
|
||||
|
||||
struct drm_i915_private;
|
||||
|
||||
struct intel_atomic_state;
|
||||
struct intel_crtc_state;
|
||||
|
||||
struct intel_link_bw_limits {
|
||||
u8 bpp_limit_reached_pipes;
|
||||
/* in 1/16 bpp units */
|
||||
int max_bpp_x16[I915_MAX_PIPES];
|
||||
};
|
||||
|
||||
void intel_link_bw_init_limits(struct drm_i915_private *i915,
|
||||
struct intel_link_bw_limits *limits);
|
||||
int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
|
||||
struct intel_link_bw_limits *limits,
|
||||
u8 pipe_mask,
|
||||
const char *reason);
|
||||
bool intel_link_bw_set_bpp_limit_for_pipe(struct intel_atomic_state *state,
|
||||
const struct intel_link_bw_limits *old_limits,
|
||||
struct intel_link_bw_limits *new_limits,
|
||||
enum pipe pipe);
|
||||
int intel_link_bw_atomic_check(struct intel_atomic_state *state,
|
||||
struct intel_link_bw_limits *new_limits);
|
||||
|
||||
#endif
|
||||
|
|
@ -144,9 +144,9 @@ static enum drm_lspcon_mode lspcon_get_current_mode(struct intel_lspcon *lspcon)
|
|||
struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon);
|
||||
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
|
||||
enum drm_lspcon_mode current_mode;
|
||||
struct i2c_adapter *adapter = &intel_dp->aux.ddc;
|
||||
struct i2c_adapter *ddc = &intel_dp->aux.ddc;
|
||||
|
||||
if (drm_lspcon_get_mode(intel_dp->aux.drm_dev, adapter, ¤t_mode)) {
|
||||
if (drm_lspcon_get_mode(intel_dp->aux.drm_dev, ddc, ¤t_mode)) {
|
||||
drm_dbg_kms(&i915->drm, "Error reading LSPCON mode\n");
|
||||
return DRM_LSPCON_MODE_INVALID;
|
||||
}
|
||||
|
|
@ -185,9 +185,9 @@ static int lspcon_change_mode(struct intel_lspcon *lspcon,
|
|||
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
|
||||
int err;
|
||||
enum drm_lspcon_mode current_mode;
|
||||
struct i2c_adapter *adapter = &intel_dp->aux.ddc;
|
||||
struct i2c_adapter *ddc = &intel_dp->aux.ddc;
|
||||
|
||||
err = drm_lspcon_get_mode(intel_dp->aux.drm_dev, adapter, ¤t_mode);
|
||||
err = drm_lspcon_get_mode(intel_dp->aux.drm_dev, ddc, ¤t_mode);
|
||||
if (err) {
|
||||
drm_err(&i915->drm, "Error reading LSPCON mode\n");
|
||||
return err;
|
||||
|
|
@ -198,7 +198,7 @@ static int lspcon_change_mode(struct intel_lspcon *lspcon,
|
|||
return 0;
|
||||
}
|
||||
|
||||
err = drm_lspcon_set_mode(intel_dp->aux.drm_dev, adapter, mode);
|
||||
err = drm_lspcon_set_mode(intel_dp->aux.drm_dev, ddc, mode);
|
||||
if (err < 0) {
|
||||
drm_err(&i915->drm, "LSPCON mode change failed\n");
|
||||
return err;
|
||||
|
|
@ -233,7 +233,7 @@ static bool lspcon_probe(struct intel_lspcon *lspcon)
|
|||
enum drm_dp_dual_mode_type adaptor_type;
|
||||
struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon);
|
||||
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
|
||||
struct i2c_adapter *adapter = &intel_dp->aux.ddc;
|
||||
struct i2c_adapter *ddc = &intel_dp->aux.ddc;
|
||||
enum drm_lspcon_mode expected_mode;
|
||||
|
||||
expected_mode = lspcon_wake_native_aux_ch(lspcon) ?
|
||||
|
|
@ -244,7 +244,7 @@ static bool lspcon_probe(struct intel_lspcon *lspcon)
|
|||
if (retry)
|
||||
usleep_range(500, 1000);
|
||||
|
||||
adaptor_type = drm_dp_dual_mode_detect(intel_dp->aux.drm_dev, adapter);
|
||||
adaptor_type = drm_dp_dual_mode_detect(intel_dp->aux.drm_dev, ddc);
|
||||
if (adaptor_type == DRM_DP_DUAL_MODE_LSPCON)
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -425,11 +425,18 @@ static int intel_lvds_compute_config(struct intel_encoder *encoder,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (HAS_PCH_SPLIT(i915)) {
|
||||
crtc_state->has_pch_encoder = true;
|
||||
if (!intel_fdi_compute_pipe_bpp(crtc_state))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (lvds_encoder->a3_power == LVDS_A3_POWER_UP)
|
||||
lvds_bpp = 8*3;
|
||||
else
|
||||
lvds_bpp = 6*3;
|
||||
|
||||
/* TODO: Check crtc_state->max_link_bpp_x16 instead of bw_constrained */
|
||||
if (lvds_bpp != crtc_state->pipe_bpp && !crtc_state->bw_constrained) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"forcing display bpp (was %d) to LVDS (%d)\n",
|
||||
|
|
@ -453,9 +460,6 @@ static int intel_lvds_compute_config(struct intel_encoder *encoder,
|
|||
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
return -EINVAL;
|
||||
|
||||
if (HAS_PCH_SPLIT(i915))
|
||||
crtc_state->has_pch_encoder = true;
|
||||
|
||||
ret = intel_panel_fitting(crtc_state, conn_state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -837,7 +841,7 @@ void intel_lvds_init(struct drm_i915_private *i915)
|
|||
struct intel_encoder *encoder;
|
||||
i915_reg_t lvds_reg;
|
||||
u32 lvds;
|
||||
u8 pin;
|
||||
u8 ddc_pin;
|
||||
|
||||
/* Skip init on machines we know falsely report LVDS */
|
||||
if (dmi_check_system(intel_no_lvds)) {
|
||||
|
|
@ -864,8 +868,8 @@ void intel_lvds_init(struct drm_i915_private *i915)
|
|||
return;
|
||||
}
|
||||
|
||||
pin = GMBUS_PIN_PANEL;
|
||||
if (!intel_bios_is_lvds_present(i915, &pin)) {
|
||||
ddc_pin = GMBUS_PIN_PANEL;
|
||||
if (!intel_bios_is_lvds_present(i915, &ddc_pin)) {
|
||||
if ((lvds & LVDS_PORT_EN) == 0) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"LVDS is not present in VBT\n");
|
||||
|
|
@ -888,8 +892,10 @@ void intel_lvds_init(struct drm_i915_private *i915)
|
|||
lvds_encoder->attached_connector = connector;
|
||||
encoder = &lvds_encoder->base;
|
||||
|
||||
drm_connector_init(&i915->drm, &connector->base, &intel_lvds_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_LVDS);
|
||||
drm_connector_init_with_ddc(&i915->drm, &connector->base,
|
||||
&intel_lvds_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_LVDS,
|
||||
intel_gmbus_get_adapter(i915, ddc_pin));
|
||||
|
||||
drm_encoder_init(&i915->drm, &encoder->base, &intel_lvds_enc_funcs,
|
||||
DRM_MODE_ENCODER_LVDS, "LVDS");
|
||||
|
|
@ -943,13 +949,10 @@ void intel_lvds_init(struct drm_i915_private *i915)
|
|||
* preferred mode is the right one.
|
||||
*/
|
||||
mutex_lock(&i915->drm.mode_config.mutex);
|
||||
if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC) {
|
||||
drm_edid = drm_edid_read_switcheroo(&connector->base,
|
||||
intel_gmbus_get_adapter(i915, pin));
|
||||
} else {
|
||||
drm_edid = drm_edid_read_ddc(&connector->base,
|
||||
intel_gmbus_get_adapter(i915, pin));
|
||||
}
|
||||
if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC)
|
||||
drm_edid = drm_edid_read_switcheroo(&connector->base, connector->base.ddc);
|
||||
else
|
||||
drm_edid = drm_edid_read_ddc(&connector->base, connector->base.ddc);
|
||||
if (drm_edid) {
|
||||
if (drm_edid_connector_update(&connector->base, drm_edid) ||
|
||||
!drm_edid_connector_add_modes(&connector->base)) {
|
||||
|
|
|
|||
|
|
@ -29,12 +29,14 @@
|
|||
#include <drm/drm_fourcc.h>
|
||||
|
||||
#include "gem/i915_gem_internal.h"
|
||||
#include "gem/i915_gem_object_frontbuffer.h"
|
||||
#include "gem/i915_gem_pm.h"
|
||||
#include "gt/intel_gpu_commands.h"
|
||||
#include "gt/intel_ring.h"
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "intel_color_regs.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_frontbuffer.h"
|
||||
|
|
|
|||
|
|
@ -59,15 +59,6 @@ intel_panel_preferred_fixed_mode(struct intel_connector *connector)
|
|||
struct drm_display_mode, head);
|
||||
}
|
||||
|
||||
static bool is_in_vrr_range(struct intel_connector *connector, int vrefresh)
|
||||
{
|
||||
const struct drm_display_info *info = &connector->base.display_info;
|
||||
|
||||
return intel_vrr_is_capable(connector) &&
|
||||
vrefresh >= info->monitor_range.min_vfreq &&
|
||||
vrefresh <= info->monitor_range.max_vfreq;
|
||||
}
|
||||
|
||||
static bool is_best_fixed_mode(struct intel_connector *connector,
|
||||
int vrefresh, int fixed_mode_vrefresh,
|
||||
const struct drm_display_mode *best_mode)
|
||||
|
|
@ -81,8 +72,8 @@ static bool is_best_fixed_mode(struct intel_connector *connector,
|
|||
* vrefresh, which we can then reduce to match the requested
|
||||
* vrefresh by extending the vblank length.
|
||||
*/
|
||||
if (is_in_vrr_range(connector, vrefresh) &&
|
||||
is_in_vrr_range(connector, fixed_mode_vrefresh) &&
|
||||
if (intel_vrr_is_in_range(connector, vrefresh) &&
|
||||
intel_vrr_is_in_range(connector, fixed_mode_vrefresh) &&
|
||||
fixed_mode_vrefresh < vrefresh)
|
||||
return false;
|
||||
|
||||
|
|
@ -224,8 +215,8 @@ int intel_panel_compute_config(struct intel_connector *connector,
|
|||
* Assume that we shouldn't muck about with the
|
||||
* timings if they don't land in the VRR range.
|
||||
*/
|
||||
is_vrr = is_in_vrr_range(connector, vrefresh) &&
|
||||
is_in_vrr_range(connector, fixed_mode_vrefresh);
|
||||
is_vrr = intel_vrr_is_in_range(connector, vrefresh) &&
|
||||
intel_vrr_is_in_range(connector, fixed_mode_vrefresh);
|
||||
|
||||
if (!is_vrr) {
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "intel_display.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_fb.h"
|
||||
#include "intel_frontbuffer.h"
|
||||
#include "intel_plane_initial.h"
|
||||
|
||||
static bool
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ int intel_pmdemand_init(struct drm_i915_private *i915)
|
|||
&pmdemand_state->base,
|
||||
&intel_pmdemand_funcs);
|
||||
|
||||
if (IS_MTL_DISPLAY_STEP(i915, STEP_A0, STEP_C0))
|
||||
if (IS_DISPLAY_IP_STEP(i915, IP_VER(14, 0), STEP_A0, STEP_C0))
|
||||
/* Wa_14016740474 */
|
||||
intel_de_rmw(i915, XELPD_CHICKEN_DCPR_3, 0, DMD_RSP_TIMEOUT_DISABLE);
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_damage_helper.h>
|
||||
#include <drm/drm_debugfs.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
|
|
@ -32,6 +33,7 @@
|
|||
#include "intel_display_types.h"
|
||||
#include "intel_dp.h"
|
||||
#include "intel_dp_aux.h"
|
||||
#include "intel_frontbuffer.h"
|
||||
#include "intel_hdmi.h"
|
||||
#include "intel_psr.h"
|
||||
#include "intel_psr_regs.h"
|
||||
|
|
@ -1360,8 +1362,7 @@ static void wm_optimization_wa(struct intel_dp *intel_dp,
|
|||
bool set_wa_bit = false;
|
||||
|
||||
/* Wa_14015648006 */
|
||||
if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) ||
|
||||
IS_DISPLAY_VER(dev_priv, 11, 13))
|
||||
if (IS_DISPLAY_VER(dev_priv, 11, 14))
|
||||
set_wa_bit |= crtc_state->wm_level_disabled;
|
||||
|
||||
/* Wa_16013835468 */
|
||||
|
|
@ -1447,7 +1448,7 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
|
|||
* All supported adlp panels have 1-based X granularity, this may
|
||||
* cause issues if non-supported panels are used.
|
||||
*/
|
||||
if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
|
||||
if (IS_DISPLAY_IP_STEP(dev_priv, IP_VER(14, 0), STEP_A0, STEP_B0))
|
||||
intel_de_rmw(dev_priv, MTL_CHICKEN_TRANS(cpu_transcoder), 0,
|
||||
ADLP_1_BASED_X_GRANULARITY);
|
||||
else if (IS_ALDERLAKE_P(dev_priv))
|
||||
|
|
@ -1455,7 +1456,7 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
|
|||
ADLP_1_BASED_X_GRANULARITY);
|
||||
|
||||
/* Wa_16012604467:adlp,mtl[a0,b0] */
|
||||
if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
|
||||
if (IS_DISPLAY_IP_STEP(dev_priv, IP_VER(14, 0), STEP_A0, STEP_B0))
|
||||
intel_de_rmw(dev_priv,
|
||||
MTL_CLKGATE_DIS_TRANS(cpu_transcoder), 0,
|
||||
MTL_CLKGATE_DIS_TRANS_DMASC_GATING_DIS);
|
||||
|
|
@ -1613,7 +1614,7 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
|
|||
|
||||
if (intel_dp->psr.psr2_enabled) {
|
||||
/* Wa_16012604467:adlp,mtl[a0,b0] */
|
||||
if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
|
||||
if (IS_DISPLAY_IP_STEP(dev_priv, IP_VER(14, 0), STEP_A0, STEP_B0))
|
||||
intel_de_rmw(dev_priv,
|
||||
MTL_CLKGATE_DIS_TRANS(cpu_transcoder),
|
||||
MTL_CLKGATE_DIS_TRANS_DMASC_GATING_DIS, 0);
|
||||
|
|
@ -2087,7 +2088,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
|
|||
goto skip_sel_fetch_set_loop;
|
||||
|
||||
/* Wa_14014971492 */
|
||||
if ((IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) ||
|
||||
if ((IS_DISPLAY_IP_STEP(dev_priv, IP_VER(14, 0), STEP_A0, STEP_B0) ||
|
||||
IS_ALDERLAKE_P(dev_priv) || IS_TIGERLAKE(dev_priv)) &&
|
||||
crtc_state->splitter.enable)
|
||||
pipe_clip.y1 = 0;
|
||||
|
|
@ -2230,6 +2231,12 @@ static void _intel_psr_post_plane_update(const struct intel_atomic_state *state,
|
|||
if (crtc_state->crc_enabled && psr->enabled)
|
||||
psr_force_hw_tracking_exit(intel_dp);
|
||||
|
||||
/*
|
||||
* Clear possible busy bits in case we have
|
||||
* invalidate -> flip -> flush sequence.
|
||||
*/
|
||||
intel_dp->psr.busy_frontbuffer_bits = 0;
|
||||
|
||||
mutex_unlock(&psr->lock);
|
||||
}
|
||||
}
|
||||
|
|
@ -3153,7 +3160,7 @@ static int i915_psr_sink_status_show(struct seq_file *m, void *data)
|
|||
};
|
||||
const char *str;
|
||||
int ret;
|
||||
u8 val;
|
||||
u8 status, error_status;
|
||||
|
||||
if (!CAN_PSR(intel_dp)) {
|
||||
seq_puts(m, "PSR Unsupported\n");
|
||||
|
|
@ -3163,19 +3170,34 @@ static int i915_psr_sink_status_show(struct seq_file *m, void *data)
|
|||
if (connector->base.status != connector_status_connected)
|
||||
return -ENODEV;
|
||||
|
||||
ret = drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_STATUS, &val);
|
||||
if (ret != 1)
|
||||
return ret < 0 ? ret : -EIO;
|
||||
ret = psr_get_status_and_error_status(intel_dp, &status, &error_status);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val &= DP_PSR_SINK_STATE_MASK;
|
||||
if (val < ARRAY_SIZE(sink_status))
|
||||
str = sink_status[val];
|
||||
status &= DP_PSR_SINK_STATE_MASK;
|
||||
if (status < ARRAY_SIZE(sink_status))
|
||||
str = sink_status[status];
|
||||
else
|
||||
str = "unknown";
|
||||
|
||||
seq_printf(m, "Sink PSR status: 0x%x [%s]\n", val, str);
|
||||
seq_printf(m, "Sink PSR status: 0x%x [%s]\n", status, str);
|
||||
|
||||
return 0;
|
||||
seq_printf(m, "Sink PSR error status: 0x%x", error_status);
|
||||
|
||||
if (error_status & (DP_PSR_RFB_STORAGE_ERROR |
|
||||
DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR |
|
||||
DP_PSR_LINK_CRC_ERROR))
|
||||
seq_puts(m, ":\n");
|
||||
else
|
||||
seq_puts(m, "\n");
|
||||
if (error_status & DP_PSR_RFB_STORAGE_ERROR)
|
||||
seq_puts(m, "\tPSR RFB storage error\n");
|
||||
if (error_status & DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR)
|
||||
seq_puts(m, "\tPSR VSC SDP uncorrectable error\n");
|
||||
if (error_status & DP_PSR_LINK_CRC_ERROR)
|
||||
seq_puts(m, "\tPSR Link CRC error\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(i915_psr_sink_status);
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include "intel_crtc.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_fdi.h"
|
||||
#include "intel_fifo_underrun.h"
|
||||
#include "intel_gmbus.h"
|
||||
#include "intel_hdmi.h"
|
||||
|
|
@ -57,15 +58,16 @@
|
|||
#define SDVO_LVDS_MASK (SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1)
|
||||
#define SDVO_TV_MASK (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_YPRPB0)
|
||||
|
||||
#define SDVO_OUTPUT_MASK (SDVO_TMDS_MASK | SDVO_RGB_MASK | SDVO_LVDS_MASK |\
|
||||
SDVO_TV_MASK)
|
||||
#define SDVO_OUTPUT_MASK (SDVO_TMDS_MASK | SDVO_RGB_MASK | SDVO_LVDS_MASK | SDVO_TV_MASK)
|
||||
|
||||
#define IS_TV(c) (c->output_flag & SDVO_TV_MASK)
|
||||
#define IS_TMDS(c) (c->output_flag & SDVO_TMDS_MASK)
|
||||
#define IS_LVDS(c) (c->output_flag & SDVO_LVDS_MASK)
|
||||
#define IS_TV_OR_LVDS(c) (c->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK))
|
||||
#define IS_DIGITAL(c) (c->output_flag & (SDVO_TMDS_MASK | SDVO_LVDS_MASK))
|
||||
#define IS_TV(c) ((c)->output_flag & SDVO_TV_MASK)
|
||||
#define IS_TMDS(c) ((c)->output_flag & SDVO_TMDS_MASK)
|
||||
#define IS_LVDS(c) ((c)->output_flag & SDVO_LVDS_MASK)
|
||||
#define IS_TV_OR_LVDS(c) ((c)->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK))
|
||||
#define IS_DIGITAL(c) ((c)->output_flag & (SDVO_TMDS_MASK | SDVO_LVDS_MASK))
|
||||
|
||||
#define HAS_DDC(c) ((c)->output_flag & (SDVO_RGB_MASK | SDVO_TMDS_MASK | \
|
||||
SDVO_LVDS_MASK))
|
||||
|
||||
static const char * const tv_format_names[] = {
|
||||
"NTSC_M" , "NTSC_J" , "NTSC_443",
|
||||
|
|
@ -79,20 +81,25 @@ static const char * const tv_format_names[] = {
|
|||
|
||||
#define TV_FORMAT_NUM ARRAY_SIZE(tv_format_names)
|
||||
|
||||
struct intel_sdvo;
|
||||
|
||||
struct intel_sdvo_ddc {
|
||||
struct i2c_adapter ddc;
|
||||
struct intel_sdvo *sdvo;
|
||||
u8 ddc_bus;
|
||||
};
|
||||
|
||||
struct intel_sdvo {
|
||||
struct intel_encoder base;
|
||||
|
||||
struct i2c_adapter *i2c;
|
||||
u8 slave_addr;
|
||||
|
||||
struct i2c_adapter ddc;
|
||||
struct intel_sdvo_ddc ddc[3];
|
||||
|
||||
/* Register for the SDVO device: SDVOB or SDVOC */
|
||||
i915_reg_t sdvo_reg;
|
||||
|
||||
/* Active outputs controlled by this SDVO output */
|
||||
u16 controlled_output;
|
||||
|
||||
/*
|
||||
* Capabilities of the SDVO device returned by
|
||||
* intel_sdvo_get_capabilities()
|
||||
|
|
@ -104,22 +111,11 @@ struct intel_sdvo {
|
|||
/* Pixel clock limitations reported by the SDVO device, in kHz */
|
||||
int pixel_clock_min, pixel_clock_max;
|
||||
|
||||
/*
|
||||
* For multiple function SDVO device,
|
||||
* this is for current attached outputs.
|
||||
*/
|
||||
u16 attached_output;
|
||||
|
||||
/*
|
||||
* Hotplug activation bits for this device
|
||||
*/
|
||||
u16 hotplug_active;
|
||||
|
||||
enum port port;
|
||||
|
||||
/* DDC bus used by this SDVO encoder */
|
||||
u8 ddc_bus;
|
||||
|
||||
/*
|
||||
* the sdvo flag gets lost in round trip: dtd->adjusted_mode->dtd
|
||||
*/
|
||||
|
|
@ -233,7 +229,7 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val)
|
|||
return;
|
||||
}
|
||||
|
||||
if (intel_sdvo->port == PORT_B)
|
||||
if (intel_sdvo->base.port == PORT_B)
|
||||
cval = intel_de_read(dev_priv, GEN3_SDVOC);
|
||||
else
|
||||
bval = intel_de_read(dev_priv, GEN3_SDVOB);
|
||||
|
|
@ -410,7 +406,7 @@ static const char *sdvo_cmd_name(u8 cmd)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#define SDVO_NAME(svdo) ((svdo)->port == PORT_B ? "SDVOB" : "SDVOC")
|
||||
#define SDVO_NAME(svdo) ((svdo)->base.port == PORT_B ? "SDVOB" : "SDVOC")
|
||||
|
||||
static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd,
|
||||
const void *args, int args_len)
|
||||
|
|
@ -1224,12 +1220,13 @@ static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo,
|
|||
|
||||
static bool
|
||||
intel_sdvo_set_output_timings_from_mode(struct intel_sdvo *intel_sdvo,
|
||||
struct intel_sdvo_connector *intel_sdvo_connector,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct intel_sdvo_dtd output_dtd;
|
||||
|
||||
if (!intel_sdvo_set_target_output(intel_sdvo,
|
||||
intel_sdvo->attached_output))
|
||||
intel_sdvo_connector->output_flag))
|
||||
return false;
|
||||
|
||||
intel_sdvo_get_dtd_from_mode(&output_dtd, mode);
|
||||
|
|
@ -1270,10 +1267,10 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo,
|
|||
return true;
|
||||
}
|
||||
|
||||
static void i9xx_adjust_sdvo_tv_clock(struct intel_crtc_state *pipe_config)
|
||||
static int i9xx_adjust_sdvo_tv_clock(struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(pipe_config->uapi.crtc->dev);
|
||||
unsigned dotclock = pipe_config->port_clock;
|
||||
unsigned int dotclock = pipe_config->hw.adjusted_mode.crtc_clock;
|
||||
struct dpll *clock = &pipe_config->dpll;
|
||||
|
||||
/*
|
||||
|
|
@ -1293,11 +1290,14 @@ static void i9xx_adjust_sdvo_tv_clock(struct intel_crtc_state *pipe_config)
|
|||
clock->m1 = 12;
|
||||
clock->m2 = 8;
|
||||
} else {
|
||||
drm_WARN(&dev_priv->drm, 1,
|
||||
"SDVO TV clock out of range: %i\n", dotclock);
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"SDVO TV clock out of range: %i\n", dotclock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pipe_config->clock_set = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool intel_has_hdmi_sink(struct intel_sdvo_connector *intel_sdvo_connector,
|
||||
|
|
@ -1352,14 +1352,18 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
|
|||
struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
|
||||
struct drm_display_mode *mode = &pipe_config->hw.mode;
|
||||
|
||||
if (HAS_PCH_SPLIT(to_i915(encoder->base.dev))) {
|
||||
pipe_config->has_pch_encoder = true;
|
||||
if (!intel_fdi_compute_pipe_bpp(pipe_config))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("forcing bpc to 8 for SDVO\n");
|
||||
/* FIXME: Don't increase pipe_bpp */
|
||||
pipe_config->pipe_bpp = 8*3;
|
||||
pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
|
||||
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
|
||||
|
||||
if (HAS_PCH_SPLIT(to_i915(encoder->base.dev)))
|
||||
pipe_config->has_pch_encoder = true;
|
||||
|
||||
/*
|
||||
* We need to construct preferred input timings based on our
|
||||
* output timings. To do that, we have to set the output
|
||||
|
|
@ -1367,7 +1371,9 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
|
|||
* the sequence to do it. Oh well.
|
||||
*/
|
||||
if (IS_TV(intel_sdvo_connector)) {
|
||||
if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, mode))
|
||||
if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo,
|
||||
intel_sdvo_connector,
|
||||
mode))
|
||||
return -EINVAL;
|
||||
|
||||
(void) intel_sdvo_get_preferred_input_mode(intel_sdvo,
|
||||
|
|
@ -1385,7 +1391,9 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, fixed_mode))
|
||||
if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo,
|
||||
intel_sdvo_connector,
|
||||
fixed_mode))
|
||||
return -EINVAL;
|
||||
|
||||
(void) intel_sdvo_get_preferred_input_mode(intel_sdvo,
|
||||
|
|
@ -1415,8 +1423,13 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
|
|||
conn_state);
|
||||
|
||||
/* Clock computation needs to happen after pixel multiplier. */
|
||||
if (IS_TV(intel_sdvo_connector))
|
||||
i9xx_adjust_sdvo_tv_clock(pipe_config);
|
||||
if (IS_TV(intel_sdvo_connector)) {
|
||||
int ret;
|
||||
|
||||
ret = i9xx_adjust_sdvo_tv_clock(pipe_config);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (conn_state->picture_aspect_ratio)
|
||||
adjusted_mode->picture_aspect_ratio =
|
||||
|
|
@ -1521,7 +1534,7 @@ static void intel_sdvo_pre_enable(struct intel_atomic_state *state,
|
|||
* channel on the motherboard. In a two-input device, the first input
|
||||
* will be SDVOB and the second SDVOC.
|
||||
*/
|
||||
in_out.in0 = intel_sdvo->attached_output;
|
||||
in_out.in0 = intel_sdvo_connector->output_flag;
|
||||
in_out.in1 = 0;
|
||||
|
||||
intel_sdvo_set_value(intel_sdvo,
|
||||
|
|
@ -1530,7 +1543,7 @@ static void intel_sdvo_pre_enable(struct intel_atomic_state *state,
|
|||
|
||||
/* Set the output timings to the screen */
|
||||
if (!intel_sdvo_set_target_output(intel_sdvo,
|
||||
intel_sdvo->attached_output))
|
||||
intel_sdvo_connector->output_flag))
|
||||
return;
|
||||
|
||||
/* lvds has a special fixed output timing. */
|
||||
|
|
@ -1598,7 +1611,7 @@ static void intel_sdvo_pre_enable(struct intel_atomic_state *state,
|
|||
sdvox |= SDVO_BORDER_ENABLE;
|
||||
} else {
|
||||
sdvox = intel_de_read(dev_priv, intel_sdvo->sdvo_reg);
|
||||
if (intel_sdvo->port == PORT_B)
|
||||
if (intel_sdvo->base.port == PORT_B)
|
||||
sdvox &= SDVOB_PRESERVE_MASK;
|
||||
else
|
||||
sdvox &= SDVOC_PRESERVE_MASK;
|
||||
|
|
@ -1867,6 +1880,8 @@ static void intel_enable_sdvo(struct intel_atomic_state *state,
|
|||
struct drm_device *dev = encoder->base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct intel_sdvo *intel_sdvo = to_sdvo(encoder);
|
||||
struct intel_sdvo_connector *intel_sdvo_connector =
|
||||
to_intel_sdvo_connector(conn_state->connector);
|
||||
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
|
||||
u32 temp;
|
||||
bool input1, input2;
|
||||
|
|
@ -1896,7 +1911,7 @@ static void intel_enable_sdvo(struct intel_atomic_state *state,
|
|||
if (0)
|
||||
intel_sdvo_set_encoder_power_state(intel_sdvo,
|
||||
DRM_MODE_DPMS_ON);
|
||||
intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
|
||||
intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo_connector->output_flag);
|
||||
|
||||
if (pipe_config->has_audio)
|
||||
intel_sdvo_enable_audio(intel_sdvo, pipe_config, conn_state);
|
||||
|
|
@ -1956,7 +1971,7 @@ static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct in
|
|||
" device_rev_id: %d\n"
|
||||
" sdvo_version_major: %d\n"
|
||||
" sdvo_version_minor: %d\n"
|
||||
" sdvo_inputs_mask: %d\n"
|
||||
" sdvo_num_inputs: %d\n"
|
||||
" smooth_scaling: %d\n"
|
||||
" sharp_scaling: %d\n"
|
||||
" up_scaling: %d\n"
|
||||
|
|
@ -1968,7 +1983,7 @@ static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct in
|
|||
caps->device_rev_id,
|
||||
caps->sdvo_version_major,
|
||||
caps->sdvo_version_minor,
|
||||
caps->sdvo_inputs_mask,
|
||||
caps->sdvo_num_inputs,
|
||||
caps->smooth_scaling,
|
||||
caps->sharp_scaling,
|
||||
caps->up_scaling,
|
||||
|
|
@ -2029,18 +2044,15 @@ intel_sdvo_hotplug(struct intel_encoder *encoder,
|
|||
return intel_encoder_hotplug(encoder, connector);
|
||||
}
|
||||
|
||||
static bool
|
||||
intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo)
|
||||
{
|
||||
/* Is there more than one type of output? */
|
||||
return hweight16(intel_sdvo->caps.output_flags) > 1;
|
||||
}
|
||||
|
||||
static const struct drm_edid *
|
||||
intel_sdvo_get_edid(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_sdvo *sdvo = intel_attached_sdvo(to_intel_connector(connector));
|
||||
return drm_edid_read_ddc(connector, &sdvo->ddc);
|
||||
struct i2c_adapter *ddc = connector->ddc;
|
||||
|
||||
if (!ddc)
|
||||
return NULL;
|
||||
|
||||
return drm_edid_read_ddc(connector, ddc);
|
||||
}
|
||||
|
||||
/* Mac mini hack -- use the same DDC as the analog connector */
|
||||
|
|
@ -2048,43 +2060,23 @@ static const struct drm_edid *
|
|||
intel_sdvo_get_analog_edid(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(connector->dev);
|
||||
struct i2c_adapter *i2c;
|
||||
struct i2c_adapter *ddc;
|
||||
|
||||
i2c = intel_gmbus_get_adapter(i915, i915->display.vbt.crt_ddc_pin);
|
||||
ddc = intel_gmbus_get_adapter(i915, i915->display.vbt.crt_ddc_pin);
|
||||
if (!ddc)
|
||||
return NULL;
|
||||
|
||||
return drm_edid_read_ddc(connector, i2c);
|
||||
return drm_edid_read_ddc(connector, ddc);
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_sdvo *intel_sdvo = intel_attached_sdvo(to_intel_connector(connector));
|
||||
enum drm_connector_status status;
|
||||
const struct drm_edid *drm_edid;
|
||||
|
||||
drm_edid = intel_sdvo_get_edid(connector);
|
||||
|
||||
if (!drm_edid && intel_sdvo_multifunc_encoder(intel_sdvo)) {
|
||||
u8 ddc, saved_ddc = intel_sdvo->ddc_bus;
|
||||
|
||||
/*
|
||||
* Don't use the 1 as the argument of DDC bus switch to get
|
||||
* the EDID. It is used for SDVO SPD ROM.
|
||||
*/
|
||||
for (ddc = intel_sdvo->ddc_bus >> 1; ddc > 1; ddc >>= 1) {
|
||||
intel_sdvo->ddc_bus = ddc;
|
||||
drm_edid = intel_sdvo_get_edid(connector);
|
||||
if (drm_edid)
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* If we found the EDID on the other bus,
|
||||
* assume that is the correct DDC bus.
|
||||
*/
|
||||
if (!drm_edid)
|
||||
intel_sdvo->ddc_bus = saved_ddc;
|
||||
}
|
||||
|
||||
/*
|
||||
* When there is no edid and no monitor is connected with VGA
|
||||
* port, try to use the CRT ddc to read the EDID for DVI-connector.
|
||||
|
|
@ -2094,10 +2086,8 @@ intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
|
|||
|
||||
status = connector_status_unknown;
|
||||
if (drm_edid) {
|
||||
const struct edid *edid = drm_edid_raw(drm_edid);
|
||||
|
||||
/* DDC bus is shared, match EDID to connector type */
|
||||
if (edid && edid->input & DRM_EDID_INPUT_DIGITAL)
|
||||
if (drm_edid_is_digital(drm_edid))
|
||||
status = connector_status_connected;
|
||||
else
|
||||
status = connector_status_disconnected;
|
||||
|
|
@ -2111,8 +2101,7 @@ static bool
|
|||
intel_sdvo_connector_matches_edid(struct intel_sdvo_connector *sdvo,
|
||||
const struct drm_edid *drm_edid)
|
||||
{
|
||||
const struct edid *edid = drm_edid_raw(drm_edid);
|
||||
bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL);
|
||||
bool monitor_is_digital = drm_edid_is_digital(drm_edid);
|
||||
bool connector_is_digital = !!IS_DIGITAL(sdvo);
|
||||
|
||||
DRM_DEBUG_KMS("connector_is_digital? %d, monitor_is_digital? %d\n",
|
||||
|
|
@ -2135,6 +2124,10 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
|
|||
if (!INTEL_DISPLAY_ENABLED(i915))
|
||||
return connector_status_disconnected;
|
||||
|
||||
if (!intel_sdvo_set_target_output(intel_sdvo,
|
||||
intel_sdvo_connector->output_flag))
|
||||
return connector_status_unknown;
|
||||
|
||||
if (!intel_sdvo_get_value(intel_sdvo,
|
||||
SDVO_CMD_GET_ATTACHED_DISPLAYS,
|
||||
&response, 2))
|
||||
|
|
@ -2147,8 +2140,6 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
|
|||
if (response == 0)
|
||||
return connector_status_disconnected;
|
||||
|
||||
intel_sdvo->attached_output = response;
|
||||
|
||||
if ((intel_sdvo_connector->output_flag & response) == 0)
|
||||
ret = connector_status_disconnected;
|
||||
else if (IS_TMDS(intel_sdvo_connector))
|
||||
|
|
@ -2276,6 +2267,8 @@ static const struct drm_display_mode sdvo_tv_modes[] = {
|
|||
static int intel_sdvo_get_tv_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_sdvo *intel_sdvo = intel_attached_sdvo(to_intel_connector(connector));
|
||||
struct intel_sdvo_connector *intel_sdvo_connector =
|
||||
to_intel_sdvo_connector(connector);
|
||||
const struct drm_connector_state *conn_state = connector->state;
|
||||
struct intel_sdvo_sdtv_resolution_request tv_res;
|
||||
u32 reply = 0, format_map = 0;
|
||||
|
|
@ -2293,7 +2286,7 @@ static int intel_sdvo_get_tv_modes(struct drm_connector *connector)
|
|||
memcpy(&tv_res, &format_map,
|
||||
min(sizeof(format_map), sizeof(struct intel_sdvo_sdtv_resolution_request)));
|
||||
|
||||
if (!intel_sdvo_set_target_output(intel_sdvo, intel_sdvo->attached_output))
|
||||
if (!intel_sdvo_set_target_output(intel_sdvo, intel_sdvo_connector->output_flag))
|
||||
return 0;
|
||||
|
||||
BUILD_BUG_ON(sizeof(tv_res) != 3);
|
||||
|
|
@ -2458,31 +2451,6 @@ intel_sdvo_connector_atomic_set_property(struct drm_connector *connector,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
intel_sdvo_connector_register(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_sdvo *sdvo = intel_attached_sdvo(to_intel_connector(connector));
|
||||
int ret;
|
||||
|
||||
ret = intel_connector_register(connector);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return sysfs_create_link(&connector->kdev->kobj,
|
||||
&sdvo->ddc.dev.kobj,
|
||||
sdvo->ddc.dev.kobj.name);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_sdvo_connector_unregister(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_sdvo *sdvo = intel_attached_sdvo(to_intel_connector(connector));
|
||||
|
||||
sysfs_remove_link(&connector->kdev->kobj,
|
||||
sdvo->ddc.dev.kobj.name);
|
||||
intel_connector_unregister(connector);
|
||||
}
|
||||
|
||||
static struct drm_connector_state *
|
||||
intel_sdvo_connector_duplicate_state(struct drm_connector *connector)
|
||||
{
|
||||
|
|
@ -2501,8 +2469,8 @@ static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
|
|||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.atomic_get_property = intel_sdvo_connector_atomic_get_property,
|
||||
.atomic_set_property = intel_sdvo_connector_atomic_set_property,
|
||||
.late_register = intel_sdvo_connector_register,
|
||||
.early_unregister = intel_sdvo_connector_unregister,
|
||||
.late_register = intel_connector_register,
|
||||
.early_unregister = intel_connector_unregister,
|
||||
.destroy = intel_connector_destroy,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
.atomic_duplicate_state = intel_sdvo_connector_duplicate_state,
|
||||
|
|
@ -2539,29 +2507,37 @@ static const struct drm_connector_helper_funcs intel_sdvo_connector_helper_funcs
|
|||
.atomic_check = intel_sdvo_atomic_check,
|
||||
};
|
||||
|
||||
static void intel_sdvo_enc_destroy(struct drm_encoder *encoder)
|
||||
static void intel_sdvo_encoder_destroy(struct drm_encoder *_encoder)
|
||||
{
|
||||
struct intel_sdvo *intel_sdvo = to_sdvo(to_intel_encoder(encoder));
|
||||
struct intel_encoder *encoder = to_intel_encoder(_encoder);
|
||||
struct intel_sdvo *sdvo = to_sdvo(encoder);
|
||||
int i;
|
||||
|
||||
i2c_del_adapter(&intel_sdvo->ddc);
|
||||
intel_encoder_destroy(encoder);
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(sdvo->ddc); i++) {
|
||||
if (sdvo->ddc[i].ddc_bus)
|
||||
i2c_del_adapter(&sdvo->ddc[i].ddc);
|
||||
}
|
||||
|
||||
static const struct drm_encoder_funcs intel_sdvo_enc_funcs = {
|
||||
.destroy = intel_sdvo_enc_destroy,
|
||||
drm_encoder_cleanup(&encoder->base);
|
||||
kfree(sdvo);
|
||||
};
|
||||
|
||||
static void
|
||||
intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo)
|
||||
static const struct drm_encoder_funcs intel_sdvo_enc_funcs = {
|
||||
.destroy = intel_sdvo_encoder_destroy,
|
||||
};
|
||||
|
||||
static int
|
||||
intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo,
|
||||
struct intel_sdvo_connector *connector)
|
||||
{
|
||||
u16 mask = 0;
|
||||
unsigned int num_bits;
|
||||
int num_bits;
|
||||
|
||||
/*
|
||||
* Make a mask of outputs less than or equal to our own priority in the
|
||||
* list.
|
||||
*/
|
||||
switch (sdvo->controlled_output) {
|
||||
switch (connector->output_flag) {
|
||||
case SDVO_OUTPUT_LVDS1:
|
||||
mask |= SDVO_OUTPUT_LVDS1;
|
||||
fallthrough;
|
||||
|
|
@ -2590,7 +2566,7 @@ intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo)
|
|||
num_bits = 3;
|
||||
|
||||
/* Corresponds to SDVO_CONTROL_BUS_DDCx */
|
||||
sdvo->ddc_bus = 1 << num_bits;
|
||||
return num_bits;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2600,31 +2576,38 @@ intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo)
|
|||
* DDC bus number assignment is in a priority order of RGB outputs, then TMDS
|
||||
* outputs, then LVDS outputs.
|
||||
*/
|
||||
static void
|
||||
intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv,
|
||||
struct intel_sdvo *sdvo)
|
||||
static struct intel_sdvo_ddc *
|
||||
intel_sdvo_select_ddc_bus(struct intel_sdvo *sdvo,
|
||||
struct intel_sdvo_connector *connector)
|
||||
{
|
||||
struct sdvo_device_mapping *mapping;
|
||||
struct drm_i915_private *dev_priv = to_i915(sdvo->base.base.dev);
|
||||
const struct sdvo_device_mapping *mapping;
|
||||
int ddc_bus;
|
||||
|
||||
if (sdvo->port == PORT_B)
|
||||
if (sdvo->base.port == PORT_B)
|
||||
mapping = &dev_priv->display.vbt.sdvo_mappings[0];
|
||||
else
|
||||
mapping = &dev_priv->display.vbt.sdvo_mappings[1];
|
||||
|
||||
if (mapping->initialized)
|
||||
sdvo->ddc_bus = 1 << ((mapping->ddc_pin & 0xf0) >> 4);
|
||||
ddc_bus = (mapping->ddc_pin & 0xf0) >> 4;
|
||||
else
|
||||
intel_sdvo_guess_ddc_bus(sdvo);
|
||||
ddc_bus = intel_sdvo_guess_ddc_bus(sdvo, connector);
|
||||
|
||||
if (ddc_bus < 1 || ddc_bus > 3)
|
||||
return NULL;
|
||||
|
||||
return &sdvo->ddc[ddc_bus - 1];
|
||||
}
|
||||
|
||||
static void
|
||||
intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
|
||||
struct intel_sdvo *sdvo)
|
||||
intel_sdvo_select_i2c_bus(struct intel_sdvo *sdvo)
|
||||
{
|
||||
struct sdvo_device_mapping *mapping;
|
||||
struct drm_i915_private *dev_priv = to_i915(sdvo->base.base.dev);
|
||||
const struct sdvo_device_mapping *mapping;
|
||||
u8 pin;
|
||||
|
||||
if (sdvo->port == PORT_B)
|
||||
if (sdvo->base.port == PORT_B)
|
||||
mapping = &dev_priv->display.vbt.sdvo_mappings[0];
|
||||
else
|
||||
mapping = &dev_priv->display.vbt.sdvo_mappings[1];
|
||||
|
|
@ -2635,6 +2618,10 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
|
|||
else
|
||||
pin = GMBUS_PIN_DPB;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] I2C pin %d, slave addr 0x%x\n",
|
||||
sdvo->base.base.base.id, sdvo->base.base.name,
|
||||
pin, sdvo->slave_addr);
|
||||
|
||||
sdvo->i2c = intel_gmbus_get_adapter(dev_priv, pin);
|
||||
|
||||
/*
|
||||
|
|
@ -2659,12 +2646,12 @@ intel_sdvo_is_hdmi_connector(struct intel_sdvo *intel_sdvo)
|
|||
}
|
||||
|
||||
static u8
|
||||
intel_sdvo_get_slave_addr(struct drm_i915_private *dev_priv,
|
||||
struct intel_sdvo *sdvo)
|
||||
intel_sdvo_get_slave_addr(struct intel_sdvo *sdvo)
|
||||
{
|
||||
struct sdvo_device_mapping *my_mapping, *other_mapping;
|
||||
struct drm_i915_private *dev_priv = to_i915(sdvo->base.base.dev);
|
||||
const struct sdvo_device_mapping *my_mapping, *other_mapping;
|
||||
|
||||
if (sdvo->port == PORT_B) {
|
||||
if (sdvo->base.port == PORT_B) {
|
||||
my_mapping = &dev_priv->display.vbt.sdvo_mappings[0];
|
||||
other_mapping = &dev_priv->display.vbt.sdvo_mappings[1];
|
||||
} else {
|
||||
|
|
@ -2691,28 +2678,36 @@ intel_sdvo_get_slave_addr(struct drm_i915_private *dev_priv,
|
|||
* No SDVO device info is found for another DVO port,
|
||||
* so use mapping assumption we had before BIOS parsing.
|
||||
*/
|
||||
if (sdvo->port == PORT_B)
|
||||
if (sdvo->base.port == PORT_B)
|
||||
return 0x70;
|
||||
else
|
||||
return 0x72;
|
||||
}
|
||||
|
||||
static int
|
||||
intel_sdvo_init_ddc_proxy(struct intel_sdvo_ddc *ddc,
|
||||
struct intel_sdvo *sdvo, int bit);
|
||||
|
||||
static int
|
||||
intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
|
||||
struct intel_sdvo *encoder)
|
||||
{
|
||||
struct drm_connector *drm_connector;
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.base.dev);
|
||||
struct intel_sdvo_ddc *ddc = NULL;
|
||||
int ret;
|
||||
|
||||
drm_connector = &connector->base.base;
|
||||
ret = drm_connector_init(encoder->base.base.dev,
|
||||
drm_connector,
|
||||
&intel_sdvo_connector_funcs,
|
||||
connector->base.base.connector_type);
|
||||
if (HAS_DDC(connector))
|
||||
ddc = intel_sdvo_select_ddc_bus(encoder, connector);
|
||||
|
||||
ret = drm_connector_init_with_ddc(encoder->base.base.dev,
|
||||
&connector->base.base,
|
||||
&intel_sdvo_connector_funcs,
|
||||
connector->base.base.connector_type,
|
||||
ddc ? &ddc->ddc : NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
drm_connector_helper_add(drm_connector,
|
||||
drm_connector_helper_add(&connector->base.base,
|
||||
&intel_sdvo_connector_helper_funcs);
|
||||
|
||||
connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB;
|
||||
|
|
@ -2721,6 +2716,11 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
|
|||
|
||||
intel_connector_attach_encoder(&connector->base, &encoder->base);
|
||||
|
||||
if (ddc)
|
||||
drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] using %s\n",
|
||||
connector->base.base.base.id, connector->base.base.name,
|
||||
ddc->ddc.name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2918,7 +2918,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, u16 type)
|
|||
if (!intel_panel_preferred_fixed_mode(intel_connector)) {
|
||||
mutex_lock(&i915->drm.mode_config.mutex);
|
||||
|
||||
intel_ddc_get_modes(connector, &intel_sdvo->ddc);
|
||||
intel_ddc_get_modes(connector, connector->ddc);
|
||||
intel_panel_add_edid_fixed_modes(intel_connector, false);
|
||||
|
||||
mutex_unlock(&i915->drm.mode_config.mutex);
|
||||
|
|
@ -2982,7 +2982,6 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo)
|
|||
SDVO_OUTPUT_LVDS0,
|
||||
SDVO_OUTPUT_LVDS1,
|
||||
};
|
||||
struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev);
|
||||
u16 flags;
|
||||
int i;
|
||||
|
||||
|
|
@ -2994,10 +2993,6 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo)
|
|||
return false;
|
||||
}
|
||||
|
||||
intel_sdvo->controlled_output = flags;
|
||||
|
||||
intel_sdvo_select_ddc_bus(i915, intel_sdvo);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(probe_order); i++) {
|
||||
u16 type = flags & probe_order[i];
|
||||
|
||||
|
|
@ -3250,9 +3245,10 @@ static int intel_sdvo_ddc_proxy_xfer(struct i2c_adapter *adapter,
|
|||
struct i2c_msg *msgs,
|
||||
int num)
|
||||
{
|
||||
struct intel_sdvo *sdvo = adapter->algo_data;
|
||||
struct intel_sdvo_ddc *ddc = adapter->algo_data;
|
||||
struct intel_sdvo *sdvo = ddc->sdvo;
|
||||
|
||||
if (!__intel_sdvo_set_control_bus_switch(sdvo, sdvo->ddc_bus))
|
||||
if (!__intel_sdvo_set_control_bus_switch(sdvo, 1 << ddc->ddc_bus))
|
||||
return -EIO;
|
||||
|
||||
return sdvo->i2c->algo->master_xfer(sdvo->i2c, msgs, num);
|
||||
|
|
@ -3260,7 +3256,9 @@ static int intel_sdvo_ddc_proxy_xfer(struct i2c_adapter *adapter,
|
|||
|
||||
static u32 intel_sdvo_ddc_proxy_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
struct intel_sdvo *sdvo = adapter->algo_data;
|
||||
struct intel_sdvo_ddc *ddc = adapter->algo_data;
|
||||
struct intel_sdvo *sdvo = ddc->sdvo;
|
||||
|
||||
return sdvo->i2c->algo->functionality(sdvo->i2c);
|
||||
}
|
||||
|
||||
|
|
@ -3272,21 +3270,27 @@ static const struct i2c_algorithm intel_sdvo_ddc_proxy = {
|
|||
static void proxy_lock_bus(struct i2c_adapter *adapter,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct intel_sdvo *sdvo = adapter->algo_data;
|
||||
struct intel_sdvo_ddc *ddc = adapter->algo_data;
|
||||
struct intel_sdvo *sdvo = ddc->sdvo;
|
||||
|
||||
sdvo->i2c->lock_ops->lock_bus(sdvo->i2c, flags);
|
||||
}
|
||||
|
||||
static int proxy_trylock_bus(struct i2c_adapter *adapter,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct intel_sdvo *sdvo = adapter->algo_data;
|
||||
struct intel_sdvo_ddc *ddc = adapter->algo_data;
|
||||
struct intel_sdvo *sdvo = ddc->sdvo;
|
||||
|
||||
return sdvo->i2c->lock_ops->trylock_bus(sdvo->i2c, flags);
|
||||
}
|
||||
|
||||
static void proxy_unlock_bus(struct i2c_adapter *adapter,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct intel_sdvo *sdvo = adapter->algo_data;
|
||||
struct intel_sdvo_ddc *ddc = adapter->algo_data;
|
||||
struct intel_sdvo *sdvo = ddc->sdvo;
|
||||
|
||||
sdvo->i2c->lock_ops->unlock_bus(sdvo->i2c, flags);
|
||||
}
|
||||
|
||||
|
|
@ -3296,21 +3300,26 @@ static const struct i2c_lock_operations proxy_lock_ops = {
|
|||
.unlock_bus = proxy_unlock_bus,
|
||||
};
|
||||
|
||||
static bool
|
||||
intel_sdvo_init_ddc_proxy(struct intel_sdvo *sdvo,
|
||||
struct drm_i915_private *dev_priv)
|
||||
static int
|
||||
intel_sdvo_init_ddc_proxy(struct intel_sdvo_ddc *ddc,
|
||||
struct intel_sdvo *sdvo, int ddc_bus)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(sdvo->base.base.dev);
|
||||
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
|
||||
|
||||
sdvo->ddc.owner = THIS_MODULE;
|
||||
sdvo->ddc.class = I2C_CLASS_DDC;
|
||||
snprintf(sdvo->ddc.name, I2C_NAME_SIZE, "SDVO DDC proxy");
|
||||
sdvo->ddc.dev.parent = &pdev->dev;
|
||||
sdvo->ddc.algo_data = sdvo;
|
||||
sdvo->ddc.algo = &intel_sdvo_ddc_proxy;
|
||||
sdvo->ddc.lock_ops = &proxy_lock_ops;
|
||||
ddc->sdvo = sdvo;
|
||||
ddc->ddc_bus = ddc_bus;
|
||||
|
||||
return i2c_add_adapter(&sdvo->ddc) == 0;
|
||||
ddc->ddc.owner = THIS_MODULE;
|
||||
ddc->ddc.class = I2C_CLASS_DDC;
|
||||
snprintf(ddc->ddc.name, I2C_NAME_SIZE, "SDVO %c DDC%d",
|
||||
port_name(sdvo->base.port), ddc_bus);
|
||||
ddc->ddc.dev.parent = &pdev->dev;
|
||||
ddc->ddc.algo_data = ddc;
|
||||
ddc->ddc.algo = &intel_sdvo_ddc_proxy;
|
||||
ddc->ddc.lock_ops = &proxy_lock_ops;
|
||||
|
||||
return i2c_add_adapter(&ddc->ddc);
|
||||
}
|
||||
|
||||
static bool is_sdvo_port_valid(struct drm_i915_private *dev_priv, enum port port)
|
||||
|
|
@ -3345,23 +3354,21 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv,
|
|||
if (!intel_sdvo)
|
||||
return false;
|
||||
|
||||
intel_sdvo->sdvo_reg = sdvo_reg;
|
||||
intel_sdvo->port = port;
|
||||
intel_sdvo->slave_addr =
|
||||
intel_sdvo_get_slave_addr(dev_priv, intel_sdvo) >> 1;
|
||||
intel_sdvo_select_i2c_bus(dev_priv, intel_sdvo);
|
||||
if (!intel_sdvo_init_ddc_proxy(intel_sdvo, dev_priv))
|
||||
goto err_i2c_bus;
|
||||
|
||||
/* encoder type will be decided later */
|
||||
intel_encoder = &intel_sdvo->base;
|
||||
intel_encoder->type = INTEL_OUTPUT_SDVO;
|
||||
intel_encoder->power_domain = POWER_DOMAIN_PORT_OTHER;
|
||||
intel_encoder->port = port;
|
||||
|
||||
drm_encoder_init(&dev_priv->drm, &intel_encoder->base,
|
||||
&intel_sdvo_enc_funcs, 0,
|
||||
"SDVO %c", port_name(port));
|
||||
|
||||
intel_sdvo->sdvo_reg = sdvo_reg;
|
||||
intel_sdvo->slave_addr = intel_sdvo_get_slave_addr(intel_sdvo) >> 1;
|
||||
|
||||
intel_sdvo_select_i2c_bus(intel_sdvo);
|
||||
|
||||
/* Read the regs to test if we can talk to the device */
|
||||
for (i = 0; i < 0x40; i++) {
|
||||
u8 byte;
|
||||
|
|
@ -3393,6 +3400,15 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv,
|
|||
intel_sdvo->colorimetry_cap =
|
||||
intel_sdvo_get_colorimetry_cap(intel_sdvo);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(intel_sdvo->ddc); i++) {
|
||||
int ret;
|
||||
|
||||
ret = intel_sdvo_init_ddc_proxy(&intel_sdvo->ddc[i],
|
||||
intel_sdvo, i + 1);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!intel_sdvo_output_setup(intel_sdvo)) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"SDVO output failed to setup on %s\n",
|
||||
|
|
@ -3406,7 +3422,7 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv,
|
|||
* hotplug lines.
|
||||
*/
|
||||
if (intel_sdvo->hotplug_active) {
|
||||
if (intel_sdvo->port == PORT_B)
|
||||
if (intel_sdvo->base.port == PORT_B)
|
||||
intel_encoder->hpd_pin = HPD_SDVO_B;
|
||||
else
|
||||
intel_encoder->hpd_pin = HPD_SDVO_C;
|
||||
|
|
@ -3433,15 +3449,14 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv,
|
|||
|
||||
drm_dbg_kms(&dev_priv->drm, "%s device VID/DID: %02X:%02X.%02X, "
|
||||
"clock range %dMHz - %dMHz, "
|
||||
"input 1: %c, input 2: %c, "
|
||||
"num inputs: %d, "
|
||||
"output 1: %c, output 2: %c\n",
|
||||
SDVO_NAME(intel_sdvo),
|
||||
intel_sdvo->caps.vendor_id, intel_sdvo->caps.device_id,
|
||||
intel_sdvo->caps.device_rev_id,
|
||||
intel_sdvo->pixel_clock_min / 1000,
|
||||
intel_sdvo->pixel_clock_max / 1000,
|
||||
(intel_sdvo->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N',
|
||||
(intel_sdvo->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
|
||||
intel_sdvo->caps.sdvo_num_inputs,
|
||||
/* check currently supported outputs */
|
||||
intel_sdvo->caps.output_flags &
|
||||
(SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0 |
|
||||
|
|
@ -3454,13 +3469,9 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv,
|
|||
|
||||
err_output:
|
||||
intel_sdvo_output_cleanup(intel_sdvo);
|
||||
|
||||
err:
|
||||
drm_encoder_cleanup(&intel_encoder->base);
|
||||
i2c_del_adapter(&intel_sdvo->ddc);
|
||||
err_i2c_bus:
|
||||
intel_sdvo_unselect_i2c_bus(intel_sdvo);
|
||||
kfree(intel_sdvo);
|
||||
intel_sdvo_encoder_destroy(&intel_encoder->base);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ struct intel_sdvo_caps {
|
|||
u8 device_rev_id;
|
||||
u8 sdvo_version_major;
|
||||
u8 sdvo_version_minor;
|
||||
unsigned int sdvo_inputs_mask:2;
|
||||
unsigned int sdvo_num_inputs:2;
|
||||
unsigned int smooth_scaling:1;
|
||||
unsigned int sharp_scaling:1;
|
||||
unsigned int up_scaling:1;
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "intel_de.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_fb.h"
|
||||
#include "intel_frontbuffer.h"
|
||||
#include "intel_sprite.h"
|
||||
|
||||
static void i9xx_plane_linear_gamma(u16 gamma[8])
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ assert_tc_port_power_enabled(struct intel_tc_port *tc)
|
|||
!intel_display_power_is_enabled(i915, tc_port_power_domain(tc)));
|
||||
}
|
||||
|
||||
u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port)
|
||||
static u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
|
||||
struct intel_tc_port *tc = to_tc_port(dig_port);
|
||||
|
|
@ -290,7 +290,32 @@ u32 intel_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_port)
|
|||
DP_PIN_ASSIGNMENT_SHIFT(tc->phy_fia_idx);
|
||||
}
|
||||
|
||||
static int mtl_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_port)
|
||||
static int lnl_tc_port_get_max_lane_count(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);
|
||||
intel_wakeref_t wakeref;
|
||||
u32 val, pin_assignment;
|
||||
|
||||
with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref)
|
||||
val = intel_de_read(i915, TCSS_DDI_STATUS(tc_port));
|
||||
|
||||
pin_assignment =
|
||||
REG_FIELD_GET(TCSS_DDI_STATUS_PIN_ASSIGNMENT_MASK, val);
|
||||
|
||||
switch (pin_assignment) {
|
||||
default:
|
||||
MISSING_CASE(pin_assignment);
|
||||
fallthrough;
|
||||
case DP_PIN_ASSIGNMENT_D:
|
||||
return 2;
|
||||
case DP_PIN_ASSIGNMENT_C:
|
||||
case DP_PIN_ASSIGNMENT_E:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
static int mtl_tc_port_get_max_lane_count(struct intel_digital_port *dig_port)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
|
||||
intel_wakeref_t wakeref;
|
||||
|
|
@ -311,23 +336,12 @@ static int mtl_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_po
|
|||
}
|
||||
}
|
||||
|
||||
int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
|
||||
static int intel_tc_port_get_max_lane_count(struct intel_digital_port *dig_port)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
|
||||
struct intel_tc_port *tc = to_tc_port(dig_port);
|
||||
enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
|
||||
intel_wakeref_t wakeref;
|
||||
u32 lane_mask;
|
||||
u32 lane_mask = 0;
|
||||
|
||||
if (!intel_phy_is_tc(i915, phy) || tc->mode != TC_PORT_DP_ALT)
|
||||
return 4;
|
||||
|
||||
assert_tc_cold_blocked(tc);
|
||||
|
||||
if (DISPLAY_VER(i915) >= 14)
|
||||
return mtl_tc_port_get_pin_assignment_mask(dig_port);
|
||||
|
||||
lane_mask = 0;
|
||||
with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref)
|
||||
lane_mask = intel_tc_port_get_lane_mask(dig_port);
|
||||
|
||||
|
|
@ -348,6 +362,26 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
|
|||
}
|
||||
}
|
||||
|
||||
int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
|
||||
struct intel_tc_port *tc = to_tc_port(dig_port);
|
||||
enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
|
||||
|
||||
if (!intel_phy_is_tc(i915, phy) || tc->mode != TC_PORT_DP_ALT)
|
||||
return 4;
|
||||
|
||||
assert_tc_cold_blocked(tc);
|
||||
|
||||
if (DISPLAY_VER(i915) >= 20)
|
||||
return lnl_tc_port_get_max_lane_count(dig_port);
|
||||
|
||||
if (DISPLAY_VER(i915) >= 14)
|
||||
return mtl_tc_port_get_max_lane_count(dig_port);
|
||||
|
||||
return intel_tc_port_get_max_lane_count(dig_port);
|
||||
}
|
||||
|
||||
void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,
|
||||
int required_lanes)
|
||||
{
|
||||
|
|
@ -583,7 +617,7 @@ static bool tc_phy_verify_legacy_or_dp_alt_mode(struct intel_tc_port *tc,
|
|||
struct intel_digital_port *dig_port = tc->dig_port;
|
||||
int max_lanes;
|
||||
|
||||
max_lanes = intel_tc_port_fia_max_lane_count(dig_port);
|
||||
max_lanes = intel_tc_port_max_lane_count(dig_port);
|
||||
if (tc->mode == TC_PORT_LEGACY) {
|
||||
drm_WARN_ON(&i915->drm, max_lanes != 4);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -19,9 +19,8 @@ bool intel_tc_port_in_legacy_mode(struct intel_digital_port *dig_port);
|
|||
bool intel_tc_port_connected(struct intel_encoder *encoder);
|
||||
bool intel_tc_port_connected_locked(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);
|
||||
int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port);
|
||||
void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,
|
||||
int required_lanes);
|
||||
|
||||
|
|
|
|||
|
|
@ -251,6 +251,20 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
|
|||
return (position + crtc->scanline_offset) % vtotal;
|
||||
}
|
||||
|
||||
int intel_crtc_scanline_to_hw(struct intel_crtc *crtc, int scanline)
|
||||
{
|
||||
const struct drm_vblank_crtc *vblank =
|
||||
&crtc->base.dev->vblank[drm_crtc_index(&crtc->base)];
|
||||
const struct drm_display_mode *mode = &vblank->hwmode;
|
||||
int vtotal;
|
||||
|
||||
vtotal = mode->crtc_vtotal;
|
||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
vtotal /= 2;
|
||||
|
||||
return (scanline + vtotal - crtc->scanline_offset) % vtotal;
|
||||
}
|
||||
|
||||
static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc,
|
||||
bool in_vblank_irq,
|
||||
int *vpos, int *hpos,
|
||||
|
|
|
|||
|
|
@ -22,5 +22,6 @@ void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc);
|
|||
void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc);
|
||||
void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state,
|
||||
bool vrr_enable);
|
||||
int intel_crtc_scanline_to_hw(struct intel_crtc *crtc, int scanline);
|
||||
|
||||
#endif /* __INTEL_VBLANK_H__ */
|
||||
|
|
|
|||
|
|
@ -80,13 +80,19 @@ calculate_rc_params(struct drm_dsc_config *vdsc_cfg)
|
|||
int bpc = vdsc_cfg->bits_per_component;
|
||||
int bpp = vdsc_cfg->bits_per_pixel >> 4;
|
||||
int qp_bpc_modifier = (bpc - 8) * 2;
|
||||
int uncompressed_bpg_rate;
|
||||
int first_line_bpg_offset;
|
||||
u32 res, buf_i, bpp_i;
|
||||
|
||||
if (vdsc_cfg->slice_height >= 8)
|
||||
vdsc_cfg->first_line_bpg_offset =
|
||||
12 + DIV_ROUND_UP((9 * min(34, vdsc_cfg->slice_height - 8)), 100);
|
||||
first_line_bpg_offset =
|
||||
12 + (9 * min(34, vdsc_cfg->slice_height - 8)) / 100;
|
||||
else
|
||||
vdsc_cfg->first_line_bpg_offset = 2 * (vdsc_cfg->slice_height - 1);
|
||||
first_line_bpg_offset = 2 * (vdsc_cfg->slice_height - 1);
|
||||
|
||||
uncompressed_bpg_rate = (3 * bpc + (vdsc_cfg->convert_rgb ? 0 : 2)) * 3;
|
||||
vdsc_cfg->first_line_bpg_offset = clamp(first_line_bpg_offset, 0,
|
||||
uncompressed_bpg_rate - 3 * bpp);
|
||||
|
||||
/*
|
||||
* According to DSC 1.2 spec in Section 4.1 if native_420 is set:
|
||||
|
|
@ -350,9 +356,14 @@ intel_dsc_power_domain(struct intel_crtc *crtc, enum transcoder cpu_transcoder)
|
|||
return POWER_DOMAIN_TRANSCODER_VDSC_PW2;
|
||||
}
|
||||
|
||||
static int intel_dsc_get_vdsc_per_pipe(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
return crtc_state->dsc.dsc_split ? 2 : 1;
|
||||
}
|
||||
|
||||
int intel_dsc_get_num_vdsc_instances(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
int num_vdsc_instances = (crtc_state->dsc.dsc_split) ? 2 : 1;
|
||||
int num_vdsc_instances = intel_dsc_get_vdsc_per_pipe(crtc_state);
|
||||
|
||||
if (crtc_state->bigjoiner_pipes)
|
||||
num_vdsc_instances *= 2;
|
||||
|
|
@ -360,6 +371,43 @@ int intel_dsc_get_num_vdsc_instances(const struct intel_crtc_state *crtc_state)
|
|||
return num_vdsc_instances;
|
||||
}
|
||||
|
||||
static void intel_dsc_get_pps_reg(const struct intel_crtc_state *crtc_state, int pps,
|
||||
i915_reg_t *dsc_reg, int dsc_reg_num)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
bool pipe_dsc;
|
||||
|
||||
pipe_dsc = is_pipe_dsc(crtc, cpu_transcoder);
|
||||
|
||||
if (dsc_reg_num >= 3)
|
||||
MISSING_CASE(dsc_reg_num);
|
||||
if (dsc_reg_num >= 2)
|
||||
dsc_reg[1] = pipe_dsc ? ICL_DSC1_PPS(pipe, pps) : DSCC_PPS(pps);
|
||||
if (dsc_reg_num >= 1)
|
||||
dsc_reg[0] = pipe_dsc ? ICL_DSC0_PPS(pipe, pps) : DSCA_PPS(pps);
|
||||
}
|
||||
|
||||
static void intel_dsc_pps_write(const struct intel_crtc_state *crtc_state,
|
||||
int pps, u32 pps_val)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
i915_reg_t dsc_reg[2];
|
||||
int i, vdsc_per_pipe, dsc_reg_num;
|
||||
|
||||
vdsc_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state);
|
||||
dsc_reg_num = min_t(int, ARRAY_SIZE(dsc_reg), vdsc_per_pipe);
|
||||
|
||||
drm_WARN_ON_ONCE(&i915->drm, dsc_reg_num < vdsc_per_pipe);
|
||||
|
||||
intel_dsc_get_pps_reg(crtc_state, pps, dsc_reg, dsc_reg_num);
|
||||
|
||||
for (i = 0; i < dsc_reg_num; i++)
|
||||
intel_de_write(i915, dsc_reg[i], pps_val);
|
||||
}
|
||||
|
||||
static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
|
@ -367,359 +415,119 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
|
|||
const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
|
||||
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
u32 pps_val = 0;
|
||||
u32 pps_val;
|
||||
u32 rc_buf_thresh_dword[4];
|
||||
u32 rc_range_params_dword[8];
|
||||
int i = 0;
|
||||
int num_vdsc_instances = intel_dsc_get_num_vdsc_instances(crtc_state);
|
||||
int vdsc_instances_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state);
|
||||
|
||||
/* Populate PICTURE_PARAMETER_SET_0 registers */
|
||||
pps_val = DSC_VER_MAJ | vdsc_cfg->dsc_version_minor <<
|
||||
DSC_VER_MIN_SHIFT |
|
||||
vdsc_cfg->bits_per_component << DSC_BPC_SHIFT |
|
||||
vdsc_cfg->line_buf_depth << DSC_LINE_BUF_DEPTH_SHIFT;
|
||||
/* PPS 0 */
|
||||
pps_val = DSC_PPS0_VER_MAJOR(1) |
|
||||
DSC_PPS0_VER_MINOR(vdsc_cfg->dsc_version_minor) |
|
||||
DSC_PPS0_BPC(vdsc_cfg->bits_per_component) |
|
||||
DSC_PPS0_LINE_BUF_DEPTH(vdsc_cfg->line_buf_depth);
|
||||
if (vdsc_cfg->dsc_version_minor == 2) {
|
||||
pps_val |= DSC_ALT_ICH_SEL;
|
||||
pps_val |= DSC_PPS0_ALT_ICH_SEL;
|
||||
if (vdsc_cfg->native_420)
|
||||
pps_val |= DSC_NATIVE_420_ENABLE;
|
||||
pps_val |= DSC_PPS0_NATIVE_420_ENABLE;
|
||||
if (vdsc_cfg->native_422)
|
||||
pps_val |= DSC_NATIVE_422_ENABLE;
|
||||
pps_val |= DSC_PPS0_NATIVE_422_ENABLE;
|
||||
}
|
||||
if (vdsc_cfg->block_pred_enable)
|
||||
pps_val |= DSC_BLOCK_PREDICTION;
|
||||
pps_val |= DSC_PPS0_BLOCK_PREDICTION;
|
||||
if (vdsc_cfg->convert_rgb)
|
||||
pps_val |= DSC_COLOR_SPACE_CONVERSION;
|
||||
pps_val |= DSC_PPS0_COLOR_SPACE_CONVERSION;
|
||||
if (vdsc_cfg->simple_422)
|
||||
pps_val |= DSC_422_ENABLE;
|
||||
pps_val |= DSC_PPS0_422_ENABLE;
|
||||
if (vdsc_cfg->vbr_enable)
|
||||
pps_val |= DSC_VBR_ENABLE;
|
||||
pps_val |= DSC_PPS0_VBR_ENABLE;
|
||||
drm_dbg_kms(&dev_priv->drm, "PPS0 = 0x%08x\n", pps_val);
|
||||
if (!is_pipe_dsc(crtc, cpu_transcoder)) {
|
||||
intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_0,
|
||||
pps_val);
|
||||
/*
|
||||
* If 2 VDSC instances are needed, configure PPS for second
|
||||
* VDSC
|
||||
*/
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_0,
|
||||
pps_val);
|
||||
} else {
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC0_PICTURE_PARAMETER_SET_0(pipe),
|
||||
pps_val);
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC1_PICTURE_PARAMETER_SET_0(pipe),
|
||||
pps_val);
|
||||
}
|
||||
intel_dsc_pps_write(crtc_state, 0, pps_val);
|
||||
|
||||
/* Populate PICTURE_PARAMETER_SET_1 registers */
|
||||
pps_val = 0;
|
||||
pps_val |= DSC_BPP(vdsc_cfg->bits_per_pixel);
|
||||
/* PPS 1 */
|
||||
pps_val = DSC_PPS1_BPP(vdsc_cfg->bits_per_pixel);
|
||||
drm_dbg_kms(&dev_priv->drm, "PPS1 = 0x%08x\n", pps_val);
|
||||
if (!is_pipe_dsc(crtc, cpu_transcoder)) {
|
||||
intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_1,
|
||||
pps_val);
|
||||
/*
|
||||
* If 2 VDSC instances are needed, configure PPS for second
|
||||
* VDSC
|
||||
*/
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_1,
|
||||
pps_val);
|
||||
} else {
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC0_PICTURE_PARAMETER_SET_1(pipe),
|
||||
pps_val);
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC1_PICTURE_PARAMETER_SET_1(pipe),
|
||||
pps_val);
|
||||
}
|
||||
intel_dsc_pps_write(crtc_state, 1, pps_val);
|
||||
|
||||
/* Populate PICTURE_PARAMETER_SET_2 registers */
|
||||
pps_val = 0;
|
||||
pps_val |= DSC_PIC_HEIGHT(vdsc_cfg->pic_height) |
|
||||
DSC_PIC_WIDTH(vdsc_cfg->pic_width / num_vdsc_instances);
|
||||
/* PPS 2 */
|
||||
pps_val = DSC_PPS2_PIC_HEIGHT(vdsc_cfg->pic_height) |
|
||||
DSC_PPS2_PIC_WIDTH(vdsc_cfg->pic_width / num_vdsc_instances);
|
||||
drm_dbg_kms(&dev_priv->drm, "PPS2 = 0x%08x\n", pps_val);
|
||||
if (!is_pipe_dsc(crtc, cpu_transcoder)) {
|
||||
intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_2,
|
||||
pps_val);
|
||||
/*
|
||||
* If 2 VDSC instances are needed, configure PPS for second
|
||||
* VDSC
|
||||
*/
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_2,
|
||||
pps_val);
|
||||
} else {
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC0_PICTURE_PARAMETER_SET_2(pipe),
|
||||
pps_val);
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC1_PICTURE_PARAMETER_SET_2(pipe),
|
||||
pps_val);
|
||||
}
|
||||
intel_dsc_pps_write(crtc_state, 2, pps_val);
|
||||
|
||||
/* Populate PICTURE_PARAMETER_SET_3 registers */
|
||||
pps_val = 0;
|
||||
pps_val |= DSC_SLICE_HEIGHT(vdsc_cfg->slice_height) |
|
||||
DSC_SLICE_WIDTH(vdsc_cfg->slice_width);
|
||||
/* PPS 3 */
|
||||
pps_val = DSC_PPS3_SLICE_HEIGHT(vdsc_cfg->slice_height) |
|
||||
DSC_PPS3_SLICE_WIDTH(vdsc_cfg->slice_width);
|
||||
drm_dbg_kms(&dev_priv->drm, "PPS3 = 0x%08x\n", pps_val);
|
||||
if (!is_pipe_dsc(crtc, cpu_transcoder)) {
|
||||
intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_3,
|
||||
pps_val);
|
||||
/*
|
||||
* If 2 VDSC instances are needed, configure PPS for second
|
||||
* VDSC
|
||||
*/
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_3,
|
||||
pps_val);
|
||||
} else {
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC0_PICTURE_PARAMETER_SET_3(pipe),
|
||||
pps_val);
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC1_PICTURE_PARAMETER_SET_3(pipe),
|
||||
pps_val);
|
||||
}
|
||||
intel_dsc_pps_write(crtc_state, 3, pps_val);
|
||||
|
||||
/* Populate PICTURE_PARAMETER_SET_4 registers */
|
||||
pps_val = 0;
|
||||
pps_val |= DSC_INITIAL_XMIT_DELAY(vdsc_cfg->initial_xmit_delay) |
|
||||
DSC_INITIAL_DEC_DELAY(vdsc_cfg->initial_dec_delay);
|
||||
/* PPS 4 */
|
||||
pps_val = DSC_PPS4_INITIAL_XMIT_DELAY(vdsc_cfg->initial_xmit_delay) |
|
||||
DSC_PPS4_INITIAL_DEC_DELAY(vdsc_cfg->initial_dec_delay);
|
||||
drm_dbg_kms(&dev_priv->drm, "PPS4 = 0x%08x\n", pps_val);
|
||||
if (!is_pipe_dsc(crtc, cpu_transcoder)) {
|
||||
intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_4,
|
||||
pps_val);
|
||||
/*
|
||||
* If 2 VDSC instances are needed, configure PPS for second
|
||||
* VDSC
|
||||
*/
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_4,
|
||||
pps_val);
|
||||
} else {
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC0_PICTURE_PARAMETER_SET_4(pipe),
|
||||
pps_val);
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC1_PICTURE_PARAMETER_SET_4(pipe),
|
||||
pps_val);
|
||||
}
|
||||
intel_dsc_pps_write(crtc_state, 4, pps_val);
|
||||
|
||||
/* Populate PICTURE_PARAMETER_SET_5 registers */
|
||||
pps_val = 0;
|
||||
pps_val |= DSC_SCALE_INC_INT(vdsc_cfg->scale_increment_interval) |
|
||||
DSC_SCALE_DEC_INT(vdsc_cfg->scale_decrement_interval);
|
||||
/* PPS 5 */
|
||||
pps_val = DSC_PPS5_SCALE_INC_INT(vdsc_cfg->scale_increment_interval) |
|
||||
DSC_PPS5_SCALE_DEC_INT(vdsc_cfg->scale_decrement_interval);
|
||||
drm_dbg_kms(&dev_priv->drm, "PPS5 = 0x%08x\n", pps_val);
|
||||
if (!is_pipe_dsc(crtc, cpu_transcoder)) {
|
||||
intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_5,
|
||||
pps_val);
|
||||
/*
|
||||
* If 2 VDSC instances are needed, configure PPS for second
|
||||
* VDSC
|
||||
*/
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_5,
|
||||
pps_val);
|
||||
} else {
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC0_PICTURE_PARAMETER_SET_5(pipe),
|
||||
pps_val);
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC1_PICTURE_PARAMETER_SET_5(pipe),
|
||||
pps_val);
|
||||
}
|
||||
intel_dsc_pps_write(crtc_state, 5, pps_val);
|
||||
|
||||
/* Populate PICTURE_PARAMETER_SET_6 registers */
|
||||
pps_val = 0;
|
||||
pps_val |= DSC_INITIAL_SCALE_VALUE(vdsc_cfg->initial_scale_value) |
|
||||
DSC_FIRST_LINE_BPG_OFFSET(vdsc_cfg->first_line_bpg_offset) |
|
||||
DSC_FLATNESS_MIN_QP(vdsc_cfg->flatness_min_qp) |
|
||||
DSC_FLATNESS_MAX_QP(vdsc_cfg->flatness_max_qp);
|
||||
/* PPS 6 */
|
||||
pps_val = DSC_PPS6_INITIAL_SCALE_VALUE(vdsc_cfg->initial_scale_value) |
|
||||
DSC_PPS6_FIRST_LINE_BPG_OFFSET(vdsc_cfg->first_line_bpg_offset) |
|
||||
DSC_PPS6_FLATNESS_MIN_QP(vdsc_cfg->flatness_min_qp) |
|
||||
DSC_PPS6_FLATNESS_MAX_QP(vdsc_cfg->flatness_max_qp);
|
||||
drm_dbg_kms(&dev_priv->drm, "PPS6 = 0x%08x\n", pps_val);
|
||||
if (!is_pipe_dsc(crtc, cpu_transcoder)) {
|
||||
intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_6,
|
||||
pps_val);
|
||||
/*
|
||||
* If 2 VDSC instances are needed, configure PPS for second
|
||||
* VDSC
|
||||
*/
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_6,
|
||||
pps_val);
|
||||
} else {
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC0_PICTURE_PARAMETER_SET_6(pipe),
|
||||
pps_val);
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC1_PICTURE_PARAMETER_SET_6(pipe),
|
||||
pps_val);
|
||||
}
|
||||
intel_dsc_pps_write(crtc_state, 6, pps_val);
|
||||
|
||||
/* Populate PICTURE_PARAMETER_SET_7 registers */
|
||||
pps_val = 0;
|
||||
pps_val |= DSC_SLICE_BPG_OFFSET(vdsc_cfg->slice_bpg_offset) |
|
||||
DSC_NFL_BPG_OFFSET(vdsc_cfg->nfl_bpg_offset);
|
||||
/* PPS 7 */
|
||||
pps_val = DSC_PPS7_SLICE_BPG_OFFSET(vdsc_cfg->slice_bpg_offset) |
|
||||
DSC_PPS7_NFL_BPG_OFFSET(vdsc_cfg->nfl_bpg_offset);
|
||||
drm_dbg_kms(&dev_priv->drm, "PPS7 = 0x%08x\n", pps_val);
|
||||
if (!is_pipe_dsc(crtc, cpu_transcoder)) {
|
||||
intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_7,
|
||||
pps_val);
|
||||
/*
|
||||
* If 2 VDSC instances are needed, configure PPS for second
|
||||
* VDSC
|
||||
*/
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_7,
|
||||
pps_val);
|
||||
} else {
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC0_PICTURE_PARAMETER_SET_7(pipe),
|
||||
pps_val);
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC1_PICTURE_PARAMETER_SET_7(pipe),
|
||||
pps_val);
|
||||
}
|
||||
intel_dsc_pps_write(crtc_state, 7, pps_val);
|
||||
|
||||
/* Populate PICTURE_PARAMETER_SET_8 registers */
|
||||
pps_val = 0;
|
||||
pps_val |= DSC_FINAL_OFFSET(vdsc_cfg->final_offset) |
|
||||
DSC_INITIAL_OFFSET(vdsc_cfg->initial_offset);
|
||||
/* PPS 8 */
|
||||
pps_val = DSC_PPS8_FINAL_OFFSET(vdsc_cfg->final_offset) |
|
||||
DSC_PPS8_INITIAL_OFFSET(vdsc_cfg->initial_offset);
|
||||
drm_dbg_kms(&dev_priv->drm, "PPS8 = 0x%08x\n", pps_val);
|
||||
if (!is_pipe_dsc(crtc, cpu_transcoder)) {
|
||||
intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_8,
|
||||
pps_val);
|
||||
/*
|
||||
* If 2 VDSC instances are needed, configure PPS for second
|
||||
* VDSC
|
||||
*/
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_8,
|
||||
pps_val);
|
||||
} else {
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC0_PICTURE_PARAMETER_SET_8(pipe),
|
||||
pps_val);
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC1_PICTURE_PARAMETER_SET_8(pipe),
|
||||
pps_val);
|
||||
}
|
||||
intel_dsc_pps_write(crtc_state, 8, pps_val);
|
||||
|
||||
/* Populate PICTURE_PARAMETER_SET_9 registers */
|
||||
pps_val = 0;
|
||||
pps_val |= DSC_RC_MODEL_SIZE(vdsc_cfg->rc_model_size) |
|
||||
DSC_RC_EDGE_FACTOR(DSC_RC_EDGE_FACTOR_CONST);
|
||||
/* PPS 9 */
|
||||
pps_val = DSC_PPS9_RC_MODEL_SIZE(vdsc_cfg->rc_model_size) |
|
||||
DSC_PPS9_RC_EDGE_FACTOR(DSC_RC_EDGE_FACTOR_CONST);
|
||||
drm_dbg_kms(&dev_priv->drm, "PPS9 = 0x%08x\n", pps_val);
|
||||
if (!is_pipe_dsc(crtc, cpu_transcoder)) {
|
||||
intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_9,
|
||||
pps_val);
|
||||
/*
|
||||
* If 2 VDSC instances are needed, configure PPS for second
|
||||
* VDSC
|
||||
*/
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_9,
|
||||
pps_val);
|
||||
} else {
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC0_PICTURE_PARAMETER_SET_9(pipe),
|
||||
pps_val);
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC1_PICTURE_PARAMETER_SET_9(pipe),
|
||||
pps_val);
|
||||
}
|
||||
intel_dsc_pps_write(crtc_state, 9, pps_val);
|
||||
|
||||
/* Populate PICTURE_PARAMETER_SET_10 registers */
|
||||
pps_val = 0;
|
||||
pps_val |= DSC_RC_QUANT_INC_LIMIT0(vdsc_cfg->rc_quant_incr_limit0) |
|
||||
DSC_RC_QUANT_INC_LIMIT1(vdsc_cfg->rc_quant_incr_limit1) |
|
||||
DSC_RC_TARGET_OFF_HIGH(DSC_RC_TGT_OFFSET_HI_CONST) |
|
||||
DSC_RC_TARGET_OFF_LOW(DSC_RC_TGT_OFFSET_LO_CONST);
|
||||
/* PPS 10 */
|
||||
pps_val = DSC_PPS10_RC_QUANT_INC_LIMIT0(vdsc_cfg->rc_quant_incr_limit0) |
|
||||
DSC_PPS10_RC_QUANT_INC_LIMIT1(vdsc_cfg->rc_quant_incr_limit1) |
|
||||
DSC_PPS10_RC_TARGET_OFF_HIGH(DSC_RC_TGT_OFFSET_HI_CONST) |
|
||||
DSC_PPS10_RC_TARGET_OFF_LOW(DSC_RC_TGT_OFFSET_LO_CONST);
|
||||
drm_dbg_kms(&dev_priv->drm, "PPS10 = 0x%08x\n", pps_val);
|
||||
if (!is_pipe_dsc(crtc, cpu_transcoder)) {
|
||||
intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_10,
|
||||
pps_val);
|
||||
/*
|
||||
* If 2 VDSC instances are needed, configure PPS for second
|
||||
* VDSC
|
||||
*/
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv,
|
||||
DSCC_PICTURE_PARAMETER_SET_10, pps_val);
|
||||
} else {
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC0_PICTURE_PARAMETER_SET_10(pipe),
|
||||
pps_val);
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC1_PICTURE_PARAMETER_SET_10(pipe),
|
||||
pps_val);
|
||||
}
|
||||
intel_dsc_pps_write(crtc_state, 10, pps_val);
|
||||
|
||||
/* Populate Picture parameter set 16 */
|
||||
pps_val = 0;
|
||||
pps_val |= DSC_SLICE_CHUNK_SIZE(vdsc_cfg->slice_chunk_size) |
|
||||
DSC_SLICE_PER_LINE((vdsc_cfg->pic_width / num_vdsc_instances) /
|
||||
vdsc_cfg->slice_width) |
|
||||
DSC_SLICE_ROW_PER_FRAME(vdsc_cfg->pic_height /
|
||||
vdsc_cfg->slice_height);
|
||||
/* PPS 16 */
|
||||
pps_val = DSC_PPS16_SLICE_CHUNK_SIZE(vdsc_cfg->slice_chunk_size) |
|
||||
DSC_PPS16_SLICE_PER_LINE((vdsc_cfg->pic_width / num_vdsc_instances) /
|
||||
vdsc_cfg->slice_width) |
|
||||
DSC_PPS16_SLICE_ROW_PER_FRAME(vdsc_cfg->pic_height /
|
||||
vdsc_cfg->slice_height);
|
||||
drm_dbg_kms(&dev_priv->drm, "PPS16 = 0x%08x\n", pps_val);
|
||||
if (!is_pipe_dsc(crtc, cpu_transcoder)) {
|
||||
intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_16,
|
||||
pps_val);
|
||||
/*
|
||||
* If 2 VDSC instances are needed, configure PPS for second
|
||||
* VDSC
|
||||
*/
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv,
|
||||
DSCC_PICTURE_PARAMETER_SET_16, pps_val);
|
||||
} else {
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC0_PICTURE_PARAMETER_SET_16(pipe),
|
||||
pps_val);
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC1_PICTURE_PARAMETER_SET_16(pipe),
|
||||
pps_val);
|
||||
}
|
||||
intel_dsc_pps_write(crtc_state, 16, pps_val);
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 14) {
|
||||
/* Populate PICTURE_PARAMETER_SET_17 registers */
|
||||
pps_val = 0;
|
||||
pps_val |= DSC_SL_BPG_OFFSET(vdsc_cfg->second_line_bpg_offset);
|
||||
/* PPS 17 */
|
||||
pps_val = DSC_PPS17_SL_BPG_OFFSET(vdsc_cfg->second_line_bpg_offset);
|
||||
drm_dbg_kms(&dev_priv->drm, "PPS17 = 0x%08x\n", pps_val);
|
||||
intel_de_write(dev_priv,
|
||||
MTL_DSC0_PICTURE_PARAMETER_SET_17(pipe),
|
||||
pps_val);
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv,
|
||||
MTL_DSC1_PICTURE_PARAMETER_SET_17(pipe),
|
||||
pps_val);
|
||||
intel_dsc_pps_write(crtc_state, 17, pps_val);
|
||||
|
||||
/* Populate PICTURE_PARAMETER_SET_18 registers */
|
||||
pps_val = 0;
|
||||
pps_val |= DSC_NSL_BPG_OFFSET(vdsc_cfg->nsl_bpg_offset) |
|
||||
DSC_SL_OFFSET_ADJ(vdsc_cfg->second_line_offset_adj);
|
||||
/* PPS 18 */
|
||||
pps_val = DSC_PPS18_NSL_BPG_OFFSET(vdsc_cfg->nsl_bpg_offset) |
|
||||
DSC_PPS18_SL_OFFSET_ADJ(vdsc_cfg->second_line_offset_adj);
|
||||
drm_dbg_kms(&dev_priv->drm, "PPS18 = 0x%08x\n", pps_val);
|
||||
intel_de_write(dev_priv,
|
||||
MTL_DSC0_PICTURE_PARAMETER_SET_18(pipe),
|
||||
pps_val);
|
||||
if (crtc_state->dsc.dsc_split)
|
||||
intel_de_write(dev_priv,
|
||||
MTL_DSC1_PICTURE_PARAMETER_SET_18(pipe),
|
||||
pps_val);
|
||||
intel_dsc_pps_write(crtc_state, 18, pps_val);
|
||||
}
|
||||
|
||||
/* Populate the RC_BUF_THRESH registers */
|
||||
|
|
@ -740,7 +548,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
|
|||
rc_buf_thresh_dword[2]);
|
||||
intel_de_write(dev_priv, DSCA_RC_BUF_THRESH_1_UDW,
|
||||
rc_buf_thresh_dword[3]);
|
||||
if (crtc_state->dsc.dsc_split) {
|
||||
if (vdsc_instances_per_pipe > 1) {
|
||||
intel_de_write(dev_priv, DSCC_RC_BUF_THRESH_0,
|
||||
rc_buf_thresh_dword[0]);
|
||||
intel_de_write(dev_priv, DSCC_RC_BUF_THRESH_0_UDW,
|
||||
|
|
@ -759,7 +567,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
|
|||
rc_buf_thresh_dword[2]);
|
||||
intel_de_write(dev_priv, ICL_DSC0_RC_BUF_THRESH_1_UDW(pipe),
|
||||
rc_buf_thresh_dword[3]);
|
||||
if (crtc_state->dsc.dsc_split) {
|
||||
if (vdsc_instances_per_pipe > 1) {
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC1_RC_BUF_THRESH_0(pipe),
|
||||
rc_buf_thresh_dword[0]);
|
||||
|
|
@ -805,7 +613,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
|
|||
rc_range_params_dword[6]);
|
||||
intel_de_write(dev_priv, DSCA_RC_RANGE_PARAMETERS_3_UDW,
|
||||
rc_range_params_dword[7]);
|
||||
if (crtc_state->dsc.dsc_split) {
|
||||
if (vdsc_instances_per_pipe > 1) {
|
||||
intel_de_write(dev_priv, DSCC_RC_RANGE_PARAMETERS_0,
|
||||
rc_range_params_dword[0]);
|
||||
intel_de_write(dev_priv,
|
||||
|
|
@ -848,7 +656,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
|
|||
intel_de_write(dev_priv,
|
||||
ICL_DSC0_RC_RANGE_PARAMETERS_3_UDW(pipe),
|
||||
rc_range_params_dword[7]);
|
||||
if (crtc_state->dsc.dsc_split) {
|
||||
if (vdsc_instances_per_pipe > 1) {
|
||||
intel_de_write(dev_priv,
|
||||
ICL_DSC1_RC_RANGE_PARAMETERS_0(pipe),
|
||||
rc_range_params_dword[0]);
|
||||
|
|
@ -954,6 +762,7 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
|
|||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
u32 dss_ctl1_val = 0;
|
||||
u32 dss_ctl2_val = 0;
|
||||
int vdsc_instances_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state);
|
||||
|
||||
if (!crtc_state->dsc.compression_enable)
|
||||
return;
|
||||
|
|
@ -961,7 +770,7 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
|
|||
intel_dsc_pps_configure(crtc_state);
|
||||
|
||||
dss_ctl2_val |= LEFT_BRANCH_VDSC_ENABLE;
|
||||
if (crtc_state->dsc.dsc_split) {
|
||||
if (vdsc_instances_per_pipe > 1) {
|
||||
dss_ctl2_val |= RIGHT_BRANCH_VDSC_ENABLE;
|
||||
dss_ctl1_val |= JOINER_ENABLE;
|
||||
}
|
||||
|
|
@ -987,16 +796,168 @@ void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state)
|
|||
}
|
||||
}
|
||||
|
||||
static u32 intel_dsc_pps_read(struct intel_crtc_state *crtc_state, int pps,
|
||||
bool *check_equal)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
i915_reg_t dsc_reg[2];
|
||||
int i, vdsc_per_pipe, dsc_reg_num;
|
||||
u32 val = 0;
|
||||
|
||||
vdsc_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state);
|
||||
dsc_reg_num = min_t(int, ARRAY_SIZE(dsc_reg), vdsc_per_pipe);
|
||||
|
||||
drm_WARN_ON_ONCE(&i915->drm, dsc_reg_num < vdsc_per_pipe);
|
||||
|
||||
intel_dsc_get_pps_reg(crtc_state, pps, dsc_reg, dsc_reg_num);
|
||||
|
||||
if (check_equal)
|
||||
*check_equal = true;
|
||||
|
||||
for (i = 0; i < dsc_reg_num; i++) {
|
||||
u32 tmp;
|
||||
|
||||
tmp = intel_de_read(i915, dsc_reg[i]);
|
||||
|
||||
if (i == 0) {
|
||||
val = tmp;
|
||||
} else if (check_equal && tmp != val) {
|
||||
*check_equal = false;
|
||||
break;
|
||||
} else if (!check_equal) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static u32 intel_dsc_pps_read_and_verify(struct intel_crtc_state *crtc_state, int pps)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
u32 val;
|
||||
bool all_equal;
|
||||
|
||||
val = intel_dsc_pps_read(crtc_state, pps, &all_equal);
|
||||
drm_WARN_ON(&i915->drm, !all_equal);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void intel_dsc_get_pps_config(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
int num_vdsc_instances = intel_dsc_get_num_vdsc_instances(crtc_state);
|
||||
u32 pps_temp;
|
||||
|
||||
/* PPS 0 */
|
||||
pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 0);
|
||||
|
||||
vdsc_cfg->bits_per_component = REG_FIELD_GET(DSC_PPS0_BPC_MASK, pps_temp);
|
||||
vdsc_cfg->line_buf_depth = REG_FIELD_GET(DSC_PPS0_LINE_BUF_DEPTH_MASK, pps_temp);
|
||||
vdsc_cfg->block_pred_enable = pps_temp & DSC_PPS0_BLOCK_PREDICTION;
|
||||
vdsc_cfg->convert_rgb = pps_temp & DSC_PPS0_COLOR_SPACE_CONVERSION;
|
||||
vdsc_cfg->simple_422 = pps_temp & DSC_PPS0_422_ENABLE;
|
||||
vdsc_cfg->native_422 = pps_temp & DSC_PPS0_NATIVE_422_ENABLE;
|
||||
vdsc_cfg->native_420 = pps_temp & DSC_PPS0_NATIVE_420_ENABLE;
|
||||
vdsc_cfg->vbr_enable = pps_temp & DSC_PPS0_VBR_ENABLE;
|
||||
|
||||
/* PPS 1 */
|
||||
pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 1);
|
||||
|
||||
vdsc_cfg->bits_per_pixel = REG_FIELD_GET(DSC_PPS1_BPP_MASK, pps_temp);
|
||||
|
||||
if (vdsc_cfg->native_420)
|
||||
vdsc_cfg->bits_per_pixel >>= 1;
|
||||
|
||||
crtc_state->dsc.compressed_bpp = vdsc_cfg->bits_per_pixel >> 4;
|
||||
|
||||
/* PPS 2 */
|
||||
pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 2);
|
||||
|
||||
vdsc_cfg->pic_width = REG_FIELD_GET(DSC_PPS2_PIC_WIDTH_MASK, pps_temp) * num_vdsc_instances;
|
||||
vdsc_cfg->pic_height = REG_FIELD_GET(DSC_PPS2_PIC_HEIGHT_MASK, pps_temp);
|
||||
|
||||
/* PPS 3 */
|
||||
pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 3);
|
||||
|
||||
vdsc_cfg->slice_width = REG_FIELD_GET(DSC_PPS3_SLICE_WIDTH_MASK, pps_temp);
|
||||
vdsc_cfg->slice_height = REG_FIELD_GET(DSC_PPS3_SLICE_HEIGHT_MASK, pps_temp);
|
||||
|
||||
/* PPS 4 */
|
||||
pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 4);
|
||||
|
||||
vdsc_cfg->initial_dec_delay = REG_FIELD_GET(DSC_PPS4_INITIAL_DEC_DELAY_MASK, pps_temp);
|
||||
vdsc_cfg->initial_xmit_delay = REG_FIELD_GET(DSC_PPS4_INITIAL_XMIT_DELAY_MASK, pps_temp);
|
||||
|
||||
/* PPS 5 */
|
||||
pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 5);
|
||||
|
||||
vdsc_cfg->scale_decrement_interval = REG_FIELD_GET(DSC_PPS5_SCALE_DEC_INT_MASK, pps_temp);
|
||||
vdsc_cfg->scale_increment_interval = REG_FIELD_GET(DSC_PPS5_SCALE_INC_INT_MASK, pps_temp);
|
||||
|
||||
/* PPS 6 */
|
||||
pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 6);
|
||||
|
||||
vdsc_cfg->initial_scale_value = REG_FIELD_GET(DSC_PPS6_INITIAL_SCALE_VALUE_MASK, pps_temp);
|
||||
vdsc_cfg->first_line_bpg_offset = REG_FIELD_GET(DSC_PPS6_FIRST_LINE_BPG_OFFSET_MASK, pps_temp);
|
||||
vdsc_cfg->flatness_min_qp = REG_FIELD_GET(DSC_PPS6_FLATNESS_MIN_QP_MASK, pps_temp);
|
||||
vdsc_cfg->flatness_max_qp = REG_FIELD_GET(DSC_PPS6_FLATNESS_MAX_QP_MASK, pps_temp);
|
||||
|
||||
/* PPS 7 */
|
||||
pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 7);
|
||||
|
||||
vdsc_cfg->nfl_bpg_offset = REG_FIELD_GET(DSC_PPS7_NFL_BPG_OFFSET_MASK, pps_temp);
|
||||
vdsc_cfg->slice_bpg_offset = REG_FIELD_GET(DSC_PPS7_SLICE_BPG_OFFSET_MASK, pps_temp);
|
||||
|
||||
/* PPS 8 */
|
||||
pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 8);
|
||||
|
||||
vdsc_cfg->initial_offset = REG_FIELD_GET(DSC_PPS8_INITIAL_OFFSET_MASK, pps_temp);
|
||||
vdsc_cfg->final_offset = REG_FIELD_GET(DSC_PPS8_FINAL_OFFSET_MASK, pps_temp);
|
||||
|
||||
/* PPS 9 */
|
||||
pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 9);
|
||||
|
||||
vdsc_cfg->rc_model_size = REG_FIELD_GET(DSC_PPS9_RC_MODEL_SIZE_MASK, pps_temp);
|
||||
|
||||
/* PPS 10 */
|
||||
pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 10);
|
||||
|
||||
vdsc_cfg->rc_quant_incr_limit0 = REG_FIELD_GET(DSC_PPS10_RC_QUANT_INC_LIMIT0_MASK, pps_temp);
|
||||
vdsc_cfg->rc_quant_incr_limit1 = REG_FIELD_GET(DSC_PPS10_RC_QUANT_INC_LIMIT1_MASK, pps_temp);
|
||||
|
||||
/* PPS 16 */
|
||||
pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 16);
|
||||
|
||||
vdsc_cfg->slice_chunk_size = REG_FIELD_GET(DSC_PPS16_SLICE_CHUNK_SIZE_MASK, pps_temp);
|
||||
|
||||
if (DISPLAY_VER(i915) >= 14) {
|
||||
/* PPS 17 */
|
||||
pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 17);
|
||||
|
||||
vdsc_cfg->second_line_bpg_offset = REG_FIELD_GET(DSC_PPS17_SL_BPG_OFFSET_MASK, pps_temp);
|
||||
|
||||
/* PPS 18 */
|
||||
pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 18);
|
||||
|
||||
vdsc_cfg->nsl_bpg_offset = REG_FIELD_GET(DSC_PPS18_NSL_BPG_OFFSET_MASK, pps_temp);
|
||||
vdsc_cfg->second_line_offset_adj = REG_FIELD_GET(DSC_PPS18_SL_OFFSET_ADJ_MASK, pps_temp);
|
||||
}
|
||||
}
|
||||
|
||||
void intel_dsc_get_config(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);
|
||||
struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
|
||||
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
enum intel_display_power_domain power_domain;
|
||||
intel_wakeref_t wakeref;
|
||||
u32 dss_ctl1, dss_ctl2, pps0 = 0, pps1 = 0;
|
||||
u32 dss_ctl1, dss_ctl2;
|
||||
|
||||
if (!intel_dsc_source_support(crtc_state))
|
||||
return;
|
||||
|
|
@ -1017,24 +978,7 @@ void intel_dsc_get_config(struct intel_crtc_state *crtc_state)
|
|||
crtc_state->dsc.dsc_split = (dss_ctl2 & RIGHT_BRANCH_VDSC_ENABLE) &&
|
||||
(dss_ctl1 & JOINER_ENABLE);
|
||||
|
||||
/* FIXME: add more state readout as needed */
|
||||
|
||||
/* PPS0 & PPS1 */
|
||||
if (!is_pipe_dsc(crtc, cpu_transcoder)) {
|
||||
pps1 = intel_de_read(dev_priv, DSCA_PICTURE_PARAMETER_SET_1);
|
||||
} else {
|
||||
pps0 = intel_de_read(dev_priv,
|
||||
ICL_DSC0_PICTURE_PARAMETER_SET_0(pipe));
|
||||
pps1 = intel_de_read(dev_priv,
|
||||
ICL_DSC0_PICTURE_PARAMETER_SET_1(pipe));
|
||||
}
|
||||
|
||||
vdsc_cfg->bits_per_pixel = pps1;
|
||||
|
||||
if (pps0 & DSC_NATIVE_420_ENABLE)
|
||||
vdsc_cfg->bits_per_pixel >>= 1;
|
||||
|
||||
crtc_state->dsc.compressed_bpp = vdsc_cfg->bits_per_pixel >> 4;
|
||||
intel_dsc_get_pps_config(crtc_state);
|
||||
out:
|
||||
intel_display_power_put(dev_priv, power_domain, wakeref);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,35 +46,13 @@
|
|||
_ICL_PIPE_DSS_CTL2_PB, \
|
||||
_ICL_PIPE_DSS_CTL2_PC)
|
||||
|
||||
/* MTL Display Stream Compression registers */
|
||||
#define _MTL_DSC0_PICTURE_PARAMETER_SET_17_PB 0x782B4
|
||||
#define _MTL_DSC1_PICTURE_PARAMETER_SET_17_PB 0x783B4
|
||||
#define _MTL_DSC0_PICTURE_PARAMETER_SET_17_PC 0x784B4
|
||||
#define _MTL_DSC1_PICTURE_PARAMETER_SET_17_PC 0x785B4
|
||||
#define MTL_DSC0_PICTURE_PARAMETER_SET_17(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_MTL_DSC0_PICTURE_PARAMETER_SET_17_PB, \
|
||||
_MTL_DSC0_PICTURE_PARAMETER_SET_17_PC)
|
||||
#define MTL_DSC1_PICTURE_PARAMETER_SET_17(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_MTL_DSC1_PICTURE_PARAMETER_SET_17_PB, \
|
||||
_MTL_DSC1_PICTURE_PARAMETER_SET_17_PC)
|
||||
#define DSC_SL_BPG_OFFSET(offset) ((offset) << 27)
|
||||
|
||||
#define _MTL_DSC0_PICTURE_PARAMETER_SET_18_PB 0x782B8
|
||||
#define _MTL_DSC1_PICTURE_PARAMETER_SET_18_PB 0x783B8
|
||||
#define _MTL_DSC0_PICTURE_PARAMETER_SET_18_PC 0x784B8
|
||||
#define _MTL_DSC1_PICTURE_PARAMETER_SET_18_PC 0x785B8
|
||||
#define MTL_DSC0_PICTURE_PARAMETER_SET_18(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_MTL_DSC0_PICTURE_PARAMETER_SET_18_PB, \
|
||||
_MTL_DSC0_PICTURE_PARAMETER_SET_18_PC)
|
||||
#define MTL_DSC1_PICTURE_PARAMETER_SET_18(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_MTL_DSC1_PICTURE_PARAMETER_SET_18_PB, \
|
||||
_MTL_DSC1_PICTURE_PARAMETER_SET_18_PC)
|
||||
#define DSC_NSL_BPG_OFFSET(offset) ((offset) << 16)
|
||||
#define DSC_SL_OFFSET_ADJ(offset) ((offset) << 0)
|
||||
|
||||
/* Icelake Display Stream Compression Registers */
|
||||
#define DSCA_PICTURE_PARAMETER_SET_0 _MMIO(0x6B200)
|
||||
#define DSCC_PICTURE_PARAMETER_SET_0 _MMIO(0x6BA00)
|
||||
#define _DSCA_PPS_0 0x6B200
|
||||
#define _DSCC_PPS_0 0x6BA00
|
||||
#define DSCA_PPS(pps) _MMIO(_DSCA_PPS_0 + (pps) * 4)
|
||||
#define DSCC_PPS(pps) _MMIO(_DSCC_PPS_0 + (pps) * 4)
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_0_PB 0x78270
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_0_PB 0x78370
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_0_PC 0x78470
|
||||
|
|
@ -85,251 +63,128 @@
|
|||
#define ICL_DSC1_PICTURE_PARAMETER_SET_0(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_0_PB, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_0_PC)
|
||||
#define DSC_NATIVE_422_ENABLE BIT(23)
|
||||
#define DSC_NATIVE_420_ENABLE BIT(22)
|
||||
#define DSC_ALT_ICH_SEL (1 << 20)
|
||||
#define DSC_VBR_ENABLE (1 << 19)
|
||||
#define DSC_422_ENABLE (1 << 18)
|
||||
#define DSC_COLOR_SPACE_CONVERSION (1 << 17)
|
||||
#define DSC_BLOCK_PREDICTION (1 << 16)
|
||||
#define DSC_LINE_BUF_DEPTH_SHIFT 12
|
||||
#define DSC_BPC_SHIFT 8
|
||||
#define DSC_VER_MIN_SHIFT 4
|
||||
#define DSC_VER_MAJ (0x1 << 0)
|
||||
#define _ICL_DSC0_PPS_0(pipe) _PICK_EVEN((pipe) - PIPE_B, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_0_PB, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_0_PC)
|
||||
#define _ICL_DSC1_PPS_0(pipe) _PICK_EVEN((pipe) - PIPE_B, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_0_PB, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_0_PC)
|
||||
#define ICL_DSC0_PPS(pipe, pps) _MMIO(_ICL_DSC0_PPS_0(pipe) + ((pps) * 4))
|
||||
#define ICL_DSC1_PPS(pipe, pps) _MMIO(_ICL_DSC1_PPS_0(pipe) + ((pps) * 4))
|
||||
|
||||
#define DSCA_PICTURE_PARAMETER_SET_1 _MMIO(0x6B204)
|
||||
#define DSCC_PICTURE_PARAMETER_SET_1 _MMIO(0x6BA04)
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_1_PB 0x78274
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_1_PB 0x78374
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_1_PC 0x78474
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_1_PC 0x78574
|
||||
#define ICL_DSC0_PICTURE_PARAMETER_SET_1(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_1_PB, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_1_PC)
|
||||
#define ICL_DSC1_PICTURE_PARAMETER_SET_1(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_1_PB, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_1_PC)
|
||||
#define DSC_BPP(bpp) ((bpp) << 0)
|
||||
/* PPS 0 */
|
||||
#define DSC_PPS0_NATIVE_422_ENABLE REG_BIT(23)
|
||||
#define DSC_PPS0_NATIVE_420_ENABLE REG_BIT(22)
|
||||
#define DSC_PPS0_ALT_ICH_SEL REG_BIT(20)
|
||||
#define DSC_PPS0_VBR_ENABLE REG_BIT(19)
|
||||
#define DSC_PPS0_422_ENABLE REG_BIT(18)
|
||||
#define DSC_PPS0_COLOR_SPACE_CONVERSION REG_BIT(17)
|
||||
#define DSC_PPS0_BLOCK_PREDICTION REG_BIT(16)
|
||||
#define DSC_PPS0_LINE_BUF_DEPTH_MASK REG_GENMASK(15, 12)
|
||||
#define DSC_PPS0_LINE_BUF_DEPTH(depth) REG_FIELD_PREP(DSC_PPS0_LINE_BUF_DEPTH_MASK, depth)
|
||||
#define DSC_PPS0_BPC_MASK REG_GENMASK(11, 8)
|
||||
#define DSC_PPS0_BPC(bpc) REG_FIELD_PREP(DSC_PPS0_BPC_MASK, bpc)
|
||||
#define DSC_PPS0_VER_MINOR_MASK REG_GENMASK(7, 4)
|
||||
#define DSC_PPS0_VER_MINOR(minor) REG_FIELD_PREP(DSC_PPS0_VER_MINOR_MASK, minor)
|
||||
#define DSC_PPS0_VER_MAJOR_MASK REG_GENMASK(3, 0)
|
||||
#define DSC_PPS0_VER_MAJOR(major) REG_FIELD_PREP(DSC_PPS0_VER_MAJOR_MASK, major)
|
||||
|
||||
#define DSCA_PICTURE_PARAMETER_SET_2 _MMIO(0x6B208)
|
||||
#define DSCC_PICTURE_PARAMETER_SET_2 _MMIO(0x6BA08)
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_2_PB 0x78278
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_2_PB 0x78378
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_2_PC 0x78478
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_2_PC 0x78578
|
||||
#define ICL_DSC0_PICTURE_PARAMETER_SET_2(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_2_PB, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_2_PC)
|
||||
#define ICL_DSC1_PICTURE_PARAMETER_SET_2(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_2_PB, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_2_PC)
|
||||
#define DSC_PIC_WIDTH(pic_width) ((pic_width) << 16)
|
||||
#define DSC_PIC_HEIGHT(pic_height) ((pic_height) << 0)
|
||||
/* PPS 1 */
|
||||
#define DSC_PPS1_BPP_MASK REG_GENMASK(9, 0)
|
||||
#define DSC_PPS1_BPP(bpp) REG_FIELD_PREP(DSC_PPS1_BPP_MASK, bpp)
|
||||
|
||||
#define DSCA_PICTURE_PARAMETER_SET_3 _MMIO(0x6B20C)
|
||||
#define DSCC_PICTURE_PARAMETER_SET_3 _MMIO(0x6BA0C)
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_3_PB 0x7827C
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_3_PB 0x7837C
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_3_PC 0x7847C
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_3_PC 0x7857C
|
||||
#define ICL_DSC0_PICTURE_PARAMETER_SET_3(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_3_PB, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_3_PC)
|
||||
#define ICL_DSC1_PICTURE_PARAMETER_SET_3(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_3_PB, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_3_PC)
|
||||
#define DSC_SLICE_WIDTH(slice_width) ((slice_width) << 16)
|
||||
#define DSC_SLICE_HEIGHT(slice_height) ((slice_height) << 0)
|
||||
/* PPS 2 */
|
||||
#define DSC_PPS2_PIC_WIDTH_MASK REG_GENMASK(31, 16)
|
||||
#define DSC_PPS2_PIC_HEIGHT_MASK REG_GENMASK(15, 0)
|
||||
#define DSC_PPS2_PIC_WIDTH(pic_width) REG_FIELD_PREP(DSC_PPS2_PIC_WIDTH_MASK, pic_width)
|
||||
#define DSC_PPS2_PIC_HEIGHT(pic_height) REG_FIELD_PREP(DSC_PPS2_PIC_HEIGHT_MASK, pic_height)
|
||||
|
||||
#define DSCA_PICTURE_PARAMETER_SET_4 _MMIO(0x6B210)
|
||||
#define DSCC_PICTURE_PARAMETER_SET_4 _MMIO(0x6BA10)
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_4_PB 0x78280
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_4_PB 0x78380
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_4_PC 0x78480
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_4_PC 0x78580
|
||||
#define ICL_DSC0_PICTURE_PARAMETER_SET_4(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_4_PB, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_4_PC)
|
||||
#define ICL_DSC1_PICTURE_PARAMETER_SET_4(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_4_PB, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_4_PC)
|
||||
#define DSC_INITIAL_DEC_DELAY(dec_delay) ((dec_delay) << 16)
|
||||
#define DSC_INITIAL_XMIT_DELAY(xmit_delay) ((xmit_delay) << 0)
|
||||
/* PPS 3 */
|
||||
#define DSC_PPS3_SLICE_WIDTH_MASK REG_GENMASK(31, 16)
|
||||
#define DSC_PPS3_SLICE_HEIGHT_MASK REG_GENMASK(15, 0)
|
||||
#define DSC_PPS3_SLICE_WIDTH(slice_width) REG_FIELD_PREP(DSC_PPS3_SLICE_WIDTH_MASK, slice_width)
|
||||
#define DSC_PPS3_SLICE_HEIGHT(slice_height) REG_FIELD_PREP(DSC_PPS3_SLICE_HEIGHT_MASK, slice_height)
|
||||
|
||||
#define DSCA_PICTURE_PARAMETER_SET_5 _MMIO(0x6B214)
|
||||
#define DSCC_PICTURE_PARAMETER_SET_5 _MMIO(0x6BA14)
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_5_PB 0x78284
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_5_PB 0x78384
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_5_PC 0x78484
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_5_PC 0x78584
|
||||
#define ICL_DSC0_PICTURE_PARAMETER_SET_5(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_5_PB, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_5_PC)
|
||||
#define ICL_DSC1_PICTURE_PARAMETER_SET_5(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_5_PB, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_5_PC)
|
||||
#define DSC_SCALE_DEC_INT(scale_dec) ((scale_dec) << 16)
|
||||
#define DSC_SCALE_INC_INT(scale_inc) ((scale_inc) << 0)
|
||||
/* PPS 4 */
|
||||
#define DSC_PPS4_INITIAL_DEC_DELAY_MASK REG_GENMASK(31, 16)
|
||||
#define DSC_PPS4_INITIAL_XMIT_DELAY_MASK REG_GENMASK(9, 0)
|
||||
#define DSC_PPS4_INITIAL_DEC_DELAY(dec_delay) REG_FIELD_PREP(DSC_PPS4_INITIAL_DEC_DELAY_MASK, \
|
||||
dec_delay)
|
||||
#define DSC_PPS4_INITIAL_XMIT_DELAY(xmit_delay) REG_FIELD_PREP(DSC_PPS4_INITIAL_XMIT_DELAY_MASK, \
|
||||
xmit_delay)
|
||||
|
||||
#define DSCA_PICTURE_PARAMETER_SET_6 _MMIO(0x6B218)
|
||||
#define DSCC_PICTURE_PARAMETER_SET_6 _MMIO(0x6BA18)
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_6_PB 0x78288
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_6_PB 0x78388
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_6_PC 0x78488
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_6_PC 0x78588
|
||||
#define ICL_DSC0_PICTURE_PARAMETER_SET_6(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_6_PB, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_6_PC)
|
||||
#define ICL_DSC1_PICTURE_PARAMETER_SET_6(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_6_PB, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_6_PC)
|
||||
#define DSC_FLATNESS_MAX_QP(max_qp) ((max_qp) << 24)
|
||||
#define DSC_FLATNESS_MIN_QP(min_qp) ((min_qp) << 16)
|
||||
#define DSC_FIRST_LINE_BPG_OFFSET(offset) ((offset) << 8)
|
||||
#define DSC_INITIAL_SCALE_VALUE(value) ((value) << 0)
|
||||
/* PPS 5 */
|
||||
#define DSC_PPS5_SCALE_DEC_INT_MASK REG_GENMASK(27, 16)
|
||||
#define DSC_PPS5_SCALE_INC_INT_MASK REG_GENMASK(15, 0)
|
||||
#define DSC_PPS5_SCALE_DEC_INT(scale_dec) REG_FIELD_PREP(DSC_PPS5_SCALE_DEC_INT_MASK, scale_dec)
|
||||
#define DSC_PPS5_SCALE_INC_INT(scale_inc) REG_FIELD_PREP(DSC_PPS5_SCALE_INC_INT_MASK, scale_inc)
|
||||
|
||||
#define DSCA_PICTURE_PARAMETER_SET_7 _MMIO(0x6B21C)
|
||||
#define DSCC_PICTURE_PARAMETER_SET_7 _MMIO(0x6BA1C)
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_7_PB 0x7828C
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_7_PB 0x7838C
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_7_PC 0x7848C
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_7_PC 0x7858C
|
||||
#define ICL_DSC0_PICTURE_PARAMETER_SET_7(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_7_PB, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_7_PC)
|
||||
#define ICL_DSC1_PICTURE_PARAMETER_SET_7(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_7_PB, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_7_PC)
|
||||
#define DSC_NFL_BPG_OFFSET(bpg_offset) ((bpg_offset) << 16)
|
||||
#define DSC_SLICE_BPG_OFFSET(bpg_offset) ((bpg_offset) << 0)
|
||||
/* PPS 6 */
|
||||
#define DSC_PPS6_FLATNESS_MAX_QP_MASK REG_GENMASK(28, 24)
|
||||
#define DSC_PPS6_FLATNESS_MIN_QP_MASK REG_GENMASK(20, 16)
|
||||
#define DSC_PPS6_FIRST_LINE_BPG_OFFSET_MASK REG_GENMASK(12, 8)
|
||||
#define DSC_PPS6_INITIAL_SCALE_VALUE_MASK REG_GENMASK(5, 0)
|
||||
#define DSC_PPS6_FLATNESS_MAX_QP(max_qp) REG_FIELD_PREP(DSC_PPS6_FLATNESS_MAX_QP_MASK, max_qp)
|
||||
#define DSC_PPS6_FLATNESS_MIN_QP(min_qp) REG_FIELD_PREP(DSC_PPS6_FLATNESS_MIN_QP_MASK, min_qp)
|
||||
#define DSC_PPS6_FIRST_LINE_BPG_OFFSET(offset) REG_FIELD_PREP(DSC_PPS6_FIRST_LINE_BPG_OFFSET_MASK, \
|
||||
offset)
|
||||
#define DSC_PPS6_INITIAL_SCALE_VALUE(value) REG_FIELD_PREP(DSC_PPS6_INITIAL_SCALE_VALUE_MASK, \
|
||||
value)
|
||||
|
||||
#define DSCA_PICTURE_PARAMETER_SET_8 _MMIO(0x6B220)
|
||||
#define DSCC_PICTURE_PARAMETER_SET_8 _MMIO(0x6BA20)
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_8_PB 0x78290
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_8_PB 0x78390
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_8_PC 0x78490
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_8_PC 0x78590
|
||||
#define ICL_DSC0_PICTURE_PARAMETER_SET_8(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_8_PB, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_8_PC)
|
||||
#define ICL_DSC1_PICTURE_PARAMETER_SET_8(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_8_PB, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_8_PC)
|
||||
#define DSC_INITIAL_OFFSET(initial_offset) ((initial_offset) << 16)
|
||||
#define DSC_FINAL_OFFSET(final_offset) ((final_offset) << 0)
|
||||
/* PPS 7 */
|
||||
#define DSC_PPS7_NFL_BPG_OFFSET_MASK REG_GENMASK(31, 16)
|
||||
#define DSC_PPS7_SLICE_BPG_OFFSET_MASK REG_GENMASK(15, 0)
|
||||
#define DSC_PPS7_NFL_BPG_OFFSET(bpg_offset) REG_FIELD_PREP(DSC_PPS7_NFL_BPG_OFFSET_MASK, bpg_offset)
|
||||
#define DSC_PPS7_SLICE_BPG_OFFSET(bpg_offset) REG_FIELD_PREP(DSC_PPS7_SLICE_BPG_OFFSET_MASK, \
|
||||
bpg_offset)
|
||||
/* PPS 8 */
|
||||
#define DSC_PPS8_INITIAL_OFFSET_MASK REG_GENMASK(31, 16)
|
||||
#define DSC_PPS8_FINAL_OFFSET_MASK REG_GENMASK(15, 0)
|
||||
#define DSC_PPS8_INITIAL_OFFSET(initial_offset) REG_FIELD_PREP(DSC_PPS8_INITIAL_OFFSET_MASK, \
|
||||
initial_offset)
|
||||
#define DSC_PPS8_FINAL_OFFSET(final_offset) REG_FIELD_PREP(DSC_PPS8_FINAL_OFFSET_MASK, \
|
||||
final_offset)
|
||||
|
||||
#define DSCA_PICTURE_PARAMETER_SET_9 _MMIO(0x6B224)
|
||||
#define DSCC_PICTURE_PARAMETER_SET_9 _MMIO(0x6BA24)
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_9_PB 0x78294
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_9_PB 0x78394
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_9_PC 0x78494
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_9_PC 0x78594
|
||||
#define ICL_DSC0_PICTURE_PARAMETER_SET_9(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_9_PB, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_9_PC)
|
||||
#define ICL_DSC1_PICTURE_PARAMETER_SET_9(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_9_PB, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_9_PC)
|
||||
#define DSC_RC_EDGE_FACTOR(rc_edge_fact) ((rc_edge_fact) << 16)
|
||||
#define DSC_RC_MODEL_SIZE(rc_model_size) ((rc_model_size) << 0)
|
||||
/* PPS 9 */
|
||||
#define DSC_PPS9_RC_EDGE_FACTOR_MASK REG_GENMASK(19, 16)
|
||||
#define DSC_PPS9_RC_MODEL_SIZE_MASK REG_GENMASK(15, 0)
|
||||
#define DSC_PPS9_RC_EDGE_FACTOR(rc_edge_fact) REG_FIELD_PREP(DSC_PPS9_RC_EDGE_FACTOR_MASK, \
|
||||
rc_edge_fact)
|
||||
#define DSC_PPS9_RC_MODEL_SIZE(rc_model_size) REG_FIELD_PREP(DSC_PPS9_RC_MODEL_SIZE_MASK, \
|
||||
rc_model_size)
|
||||
|
||||
#define DSCA_PICTURE_PARAMETER_SET_10 _MMIO(0x6B228)
|
||||
#define DSCC_PICTURE_PARAMETER_SET_10 _MMIO(0x6BA28)
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_10_PB 0x78298
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_10_PB 0x78398
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_10_PC 0x78498
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_10_PC 0x78598
|
||||
#define ICL_DSC0_PICTURE_PARAMETER_SET_10(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_10_PB, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_10_PC)
|
||||
#define ICL_DSC1_PICTURE_PARAMETER_SET_10(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_10_PB, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_10_PC)
|
||||
#define DSC_RC_TARGET_OFF_LOW(rc_tgt_off_low) ((rc_tgt_off_low) << 20)
|
||||
#define DSC_RC_TARGET_OFF_HIGH(rc_tgt_off_high) ((rc_tgt_off_high) << 16)
|
||||
#define DSC_RC_QUANT_INC_LIMIT1(lim) ((lim) << 8)
|
||||
#define DSC_RC_QUANT_INC_LIMIT0(lim) ((lim) << 0)
|
||||
/* PPS 10 */
|
||||
#define DSC_PPS10_RC_TGT_OFF_LOW_MASK REG_GENMASK(23, 20)
|
||||
#define DSC_PPS10_RC_TGT_OFF_HIGH_MASK REG_GENMASK(19, 16)
|
||||
#define DSC_PPS10_RC_QUANT_INC_LIMIT1_MASK REG_GENMASK(12, 8)
|
||||
#define DSC_PPS10_RC_QUANT_INC_LIMIT0_MASK REG_GENMASK(4, 0)
|
||||
#define DSC_PPS10_RC_TARGET_OFF_LOW(rc_tgt_off_low) REG_FIELD_PREP(DSC_PPS10_RC_TGT_OFF_LOW_MASK, \
|
||||
rc_tgt_off_low)
|
||||
#define DSC_PPS10_RC_TARGET_OFF_HIGH(rc_tgt_off_high) REG_FIELD_PREP(DSC_PPS10_RC_TGT_OFF_HIGH_MASK, \
|
||||
rc_tgt_off_high)
|
||||
#define DSC_PPS10_RC_QUANT_INC_LIMIT1(lim) REG_FIELD_PREP(DSC_PPS10_RC_QUANT_INC_LIMIT1_MASK, lim)
|
||||
#define DSC_PPS10_RC_QUANT_INC_LIMIT0(lim) REG_FIELD_PREP(DSC_PPS10_RC_QUANT_INC_LIMIT0_MASK, lim)
|
||||
|
||||
#define DSCA_PICTURE_PARAMETER_SET_11 _MMIO(0x6B22C)
|
||||
#define DSCC_PICTURE_PARAMETER_SET_11 _MMIO(0x6BA2C)
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_11_PB 0x7829C
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_11_PB 0x7839C
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_11_PC 0x7849C
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_11_PC 0x7859C
|
||||
#define ICL_DSC0_PICTURE_PARAMETER_SET_11(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_11_PB, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_11_PC)
|
||||
#define ICL_DSC1_PICTURE_PARAMETER_SET_11(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_11_PB, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_11_PC)
|
||||
/* PPS 16 */
|
||||
#define DSC_PPS16_SLICE_ROW_PR_FRME_MASK REG_GENMASK(31, 20)
|
||||
#define DSC_PPS16_SLICE_PER_LINE_MASK REG_GENMASK(18, 16)
|
||||
#define DSC_PPS16_SLICE_CHUNK_SIZE_MASK REG_GENMASK(15, 0)
|
||||
#define DSC_PPS16_SLICE_ROW_PER_FRAME(slice_row_per_frame) REG_FIELD_PREP(DSC_PPS16_SLICE_ROW_PR_FRME_MASK, \
|
||||
slice_row_per_frame)
|
||||
#define DSC_PPS16_SLICE_PER_LINE(slice_per_line) REG_FIELD_PREP(DSC_PPS16_SLICE_PER_LINE_MASK, \
|
||||
slice_per_line)
|
||||
#define DSC_PPS16_SLICE_CHUNK_SIZE(slice_chunk_size) REG_FIELD_PREP(DSC_PPS16_SLICE_CHUNK_SIZE_MASK, \
|
||||
slice_chunk_size)
|
||||
|
||||
#define DSCA_PICTURE_PARAMETER_SET_12 _MMIO(0x6B260)
|
||||
#define DSCC_PICTURE_PARAMETER_SET_12 _MMIO(0x6BA60)
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_12_PB 0x782A0
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_12_PB 0x783A0
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_12_PC 0x784A0
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_12_PC 0x785A0
|
||||
#define ICL_DSC0_PICTURE_PARAMETER_SET_12(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_12_PB, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_12_PC)
|
||||
#define ICL_DSC1_PICTURE_PARAMETER_SET_12(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_12_PB, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_12_PC)
|
||||
/* PPS 17 (MTL+) */
|
||||
#define DSC_PPS17_SL_BPG_OFFSET_MASK REG_GENMASK(31, 27)
|
||||
#define DSC_PPS17_SL_BPG_OFFSET(offset) REG_FIELD_PREP(DSC_PPS17_SL_BPG_OFFSET_MASK, offset)
|
||||
|
||||
#define DSCA_PICTURE_PARAMETER_SET_13 _MMIO(0x6B264)
|
||||
#define DSCC_PICTURE_PARAMETER_SET_13 _MMIO(0x6BA64)
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_13_PB 0x782A4
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_13_PB 0x783A4
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_13_PC 0x784A4
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_13_PC 0x785A4
|
||||
#define ICL_DSC0_PICTURE_PARAMETER_SET_13(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_13_PB, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_13_PC)
|
||||
#define ICL_DSC1_PICTURE_PARAMETER_SET_13(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_13_PB, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_13_PC)
|
||||
|
||||
#define DSCA_PICTURE_PARAMETER_SET_14 _MMIO(0x6B268)
|
||||
#define DSCC_PICTURE_PARAMETER_SET_14 _MMIO(0x6BA68)
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_14_PB 0x782A8
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_14_PB 0x783A8
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_14_PC 0x784A8
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_14_PC 0x785A8
|
||||
#define ICL_DSC0_PICTURE_PARAMETER_SET_14(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_14_PB, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_14_PC)
|
||||
#define ICL_DSC1_PICTURE_PARAMETER_SET_14(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_14_PB, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_14_PC)
|
||||
|
||||
#define DSCA_PICTURE_PARAMETER_SET_15 _MMIO(0x6B26C)
|
||||
#define DSCC_PICTURE_PARAMETER_SET_15 _MMIO(0x6BA6C)
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_15_PB 0x782AC
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_15_PB 0x783AC
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_15_PC 0x784AC
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_15_PC 0x785AC
|
||||
#define ICL_DSC0_PICTURE_PARAMETER_SET_15(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_15_PB, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_15_PC)
|
||||
#define ICL_DSC1_PICTURE_PARAMETER_SET_15(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_15_PB, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_15_PC)
|
||||
|
||||
#define DSCA_PICTURE_PARAMETER_SET_16 _MMIO(0x6B270)
|
||||
#define DSCC_PICTURE_PARAMETER_SET_16 _MMIO(0x6BA70)
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_16_PB 0x782B0
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_16_PB 0x783B0
|
||||
#define _ICL_DSC0_PICTURE_PARAMETER_SET_16_PC 0x784B0
|
||||
#define _ICL_DSC1_PICTURE_PARAMETER_SET_16_PC 0x785B0
|
||||
#define ICL_DSC0_PICTURE_PARAMETER_SET_16(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_16_PB, \
|
||||
_ICL_DSC0_PICTURE_PARAMETER_SET_16_PC)
|
||||
#define ICL_DSC1_PICTURE_PARAMETER_SET_16(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_16_PB, \
|
||||
_ICL_DSC1_PICTURE_PARAMETER_SET_16_PC)
|
||||
#define DSC_SLICE_ROW_PER_FRAME(slice_row_per_frame) ((slice_row_per_frame) << 20)
|
||||
#define DSC_SLICE_PER_LINE(slice_per_line) ((slice_per_line) << 16)
|
||||
#define DSC_SLICE_CHUNK_SIZE(slice_chunk_size) ((slice_chunk_size) << 0)
|
||||
/* PPS 18 (MTL+) */
|
||||
#define DSC_PPS18_NSL_BPG_OFFSET_MASK REG_GENMASK(31, 16)
|
||||
#define DSC_PPS18_SL_OFFSET_ADJ_MASK REG_GENMASK(15, 0)
|
||||
#define DSC_PPS18_NSL_BPG_OFFSET(offset) REG_FIELD_PREP(DSC_PPS18_NSL_BPG_OFFSET_MASK, offset)
|
||||
#define DSC_PPS18_SL_OFFSET_ADJ(offset) REG_FIELD_PREP(DSC_PPS18_SL_OFFSET_ADJ_MASK, offset)
|
||||
|
||||
/* Icelake Rate Control Buffer Threshold Registers */
|
||||
#define DSCA_RC_BUF_THRESH_0 _MMIO(0x6B230)
|
||||
|
|
|
|||
|
|
@ -42,6 +42,15 @@ bool intel_vrr_is_capable(struct intel_connector *connector)
|
|||
info->monitor_range.max_vfreq - info->monitor_range.min_vfreq > 10;
|
||||
}
|
||||
|
||||
bool intel_vrr_is_in_range(struct intel_connector *connector, int vrefresh)
|
||||
{
|
||||
const struct drm_display_info *info = &connector->base.display_info;
|
||||
|
||||
return intel_vrr_is_capable(connector) &&
|
||||
vrefresh >= info->monitor_range.min_vfreq &&
|
||||
vrefresh <= info->monitor_range.max_vfreq;
|
||||
}
|
||||
|
||||
void
|
||||
intel_vrr_check_modeset(struct intel_atomic_state *state)
|
||||
{
|
||||
|
|
@ -108,12 +117,17 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
|
|||
const struct drm_display_info *info = &connector->base.display_info;
|
||||
int vmin, vmax;
|
||||
|
||||
if (!intel_vrr_is_capable(connector))
|
||||
return;
|
||||
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
return;
|
||||
|
||||
crtc_state->vrr.in_range =
|
||||
intel_vrr_is_in_range(connector, drm_mode_vrefresh(adjusted_mode));
|
||||
if (!crtc_state->vrr.in_range)
|
||||
return;
|
||||
|
||||
if (HAS_LRR(i915))
|
||||
crtc_state->update_lrr = true;
|
||||
|
||||
vmin = DIV_ROUND_UP(adjusted_mode->crtc_clock * 1000,
|
||||
adjusted_mode->crtc_htotal * info->monitor_range.max_vfreq);
|
||||
vmax = adjusted_mode->crtc_clock * 1000 /
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ struct intel_connector;
|
|||
struct intel_crtc_state;
|
||||
|
||||
bool intel_vrr_is_capable(struct intel_connector *connector);
|
||||
bool intel_vrr_is_in_range(struct intel_connector *connector, int vrefresh);
|
||||
void intel_vrr_check_modeset(struct intel_atomic_state *state);
|
||||
void intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "intel_display_types.h"
|
||||
#include "intel_fb.h"
|
||||
#include "intel_fbc.h"
|
||||
#include "intel_frontbuffer.h"
|
||||
#include "intel_psr.h"
|
||||
#include "skl_scaler.h"
|
||||
#include "skl_universal_plane.h"
|
||||
|
|
@ -1246,7 +1247,7 @@ icl_plane_update_noarm(struct intel_plane *plane,
|
|||
}
|
||||
|
||||
/* FLAT CCS doesn't need to program AUX_DIST */
|
||||
if (!HAS_FLAT_CCS(dev_priv))
|
||||
if (!HAS_FLAT_CCS(dev_priv) && DISPLAY_VER(dev_priv) < 20)
|
||||
intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id),
|
||||
skl_plane_aux_dist(plane_state, color_plane));
|
||||
|
||||
|
|
@ -2199,10 +2200,6 @@ static bool gen12_plane_has_mc_ccs(struct drm_i915_private *i915,
|
|||
if (IS_ALDERLAKE_P(i915) && IS_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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1367,7 +1367,7 @@ skl_total_relative_data_rate(const struct intel_crtc_state *crtc_state)
|
|||
u64 data_rate = 0;
|
||||
|
||||
for_each_plane_id_on_crtc(crtc, plane_id) {
|
||||
if (plane_id == PLANE_CURSOR)
|
||||
if (plane_id == PLANE_CURSOR && DISPLAY_VER(i915) < 20)
|
||||
continue;
|
||||
|
||||
data_rate += crtc_state->rel_data_rate[plane_id];
|
||||
|
|
@ -1514,10 +1514,12 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state,
|
|||
return 0;
|
||||
|
||||
/* Allocate fixed number of blocks for cursor. */
|
||||
cursor_size = skl_cursor_allocation(crtc_state, num_active);
|
||||
iter.size -= cursor_size;
|
||||
skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb[PLANE_CURSOR],
|
||||
alloc->end - cursor_size, alloc->end);
|
||||
if (DISPLAY_VER(i915) < 20) {
|
||||
cursor_size = skl_cursor_allocation(crtc_state, num_active);
|
||||
iter.size -= cursor_size;
|
||||
skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb[PLANE_CURSOR],
|
||||
alloc->end - cursor_size, alloc->end);
|
||||
}
|
||||
|
||||
iter.data_rate = skl_total_relative_data_rate(crtc_state);
|
||||
|
||||
|
|
@ -1531,7 +1533,7 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state,
|
|||
const struct skl_plane_wm *wm =
|
||||
&crtc_state->wm.skl.optimal.planes[plane_id];
|
||||
|
||||
if (plane_id == PLANE_CURSOR) {
|
||||
if (plane_id == PLANE_CURSOR && DISPLAY_VER(i915) < 20) {
|
||||
const struct skl_ddb_entry *ddb =
|
||||
&crtc_state->wm.skl.plane_ddb[plane_id];
|
||||
|
||||
|
|
@ -1579,7 +1581,7 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state,
|
|||
const struct skl_plane_wm *wm =
|
||||
&crtc_state->wm.skl.optimal.planes[plane_id];
|
||||
|
||||
if (plane_id == PLANE_CURSOR)
|
||||
if (plane_id == PLANE_CURSOR && DISPLAY_VER(i915) < 20)
|
||||
continue;
|
||||
|
||||
if (DISPLAY_VER(i915) < 11 &&
|
||||
|
|
@ -2616,7 +2618,7 @@ skl_compute_ddb(struct intel_atomic_state *state)
|
|||
|
||||
if (old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) {
|
||||
/* TODO: Implement vblank synchronized MBUS joining changes */
|
||||
ret = intel_modeset_all_pipes(state, "MBUS joining change");
|
||||
ret = intel_modeset_all_pipes_late(state, "MBUS joining change");
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -3719,3 +3721,17 @@ void skl_watermark_debugfs_register(struct drm_i915_private *i915)
|
|||
debugfs_create_file("i915_sagv_status", 0444, minor->debugfs_root, i915,
|
||||
&intel_sagv_status_fops);
|
||||
}
|
||||
|
||||
unsigned int skl_watermark_max_latency(struct drm_i915_private *i915)
|
||||
{
|
||||
int level;
|
||||
|
||||
for (level = i915->display.wm.num_levels - 1; level >= 0; level--) {
|
||||
unsigned int latency = skl_wm_latency(i915, level, NULL);
|
||||
|
||||
if (latency)
|
||||
return latency;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ void skl_watermark_ipc_update(struct drm_i915_private *i915);
|
|||
bool skl_watermark_ipc_enabled(struct drm_i915_private *i915);
|
||||
void skl_watermark_debugfs_register(struct drm_i915_private *i915);
|
||||
|
||||
unsigned int skl_watermark_max_latency(struct drm_i915_private *i915);
|
||||
|
||||
void skl_wm_init(struct drm_i915_private *i915);
|
||||
|
||||
struct intel_dbuf_state {
|
||||
|
|
|
|||
|
|
@ -6,11 +6,10 @@
|
|||
|
||||
#include <drm/drm_cache.h>
|
||||
|
||||
#include "display/intel_frontbuffer.h"
|
||||
|
||||
#include "i915_config.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_gem_clflush.h"
|
||||
#include "i915_gem_object_frontbuffer.h"
|
||||
#include "i915_sw_fence_work.h"
|
||||
#include "i915_trace.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
|
||||
#include "display/intel_display.h"
|
||||
#include "display/intel_frontbuffer.h"
|
||||
#include "gt/intel_gt.h"
|
||||
|
||||
#include "i915_drv.h"
|
||||
|
|
@ -16,6 +15,7 @@
|
|||
#include "i915_gem_lmem.h"
|
||||
#include "i915_gem_mman.h"
|
||||
#include "i915_gem_object.h"
|
||||
#include "i915_gem_object_frontbuffer.h"
|
||||
#include "i915_vma.h"
|
||||
|
||||
#define VTD_GUARD (168u * I915_GTT_PAGE_SIZE) /* 168 or tile-row PTE padding */
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue