diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index a83fa8be0aba..d4e7764621e1 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -349,6 +349,7 @@ i915-y += \ display/intel_cx0_phy.o \ display/intel_ddi.o \ display/intel_ddi_buf_trans.o \ + display/intel_dip.o \ display/intel_display_device.o \ display/intel_display_trace.o \ display/intel_dkl_phy.o \ diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index f1383764b702..f54b29e193ee 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -375,6 +375,142 @@ static u32 get_pr_alpm_as_sdp_transmission_time(const struct intel_crtc_state *c } } +/* + * Periodic Adaptive-Sync SDP skip frames. + * + * While Panel Replay is active the transcoder timing generator runs at the + * panel's maximum refresh rate. To drive the panel down to its minimum + * refresh rate the Adaptive-Sync SDP only needs to reach the panel once per + * minimum-rate frame, so transmitting it on every (maximum-rate) frame is + * unnecessary and shows up as repeated SDPs on the link. Program the HW skip + * counter so that a single AS SDP is followed by + * (max_vrefresh / min_vrefresh - 1) idle frames, i.e. one AS SDP per slowest + * panel frame. + * + * The maximum and minimum refresh rates come from the panel's adaptive-sync + * monitor range, so this is independent of the current content/flip rate. + */ +static u32 intel_pr_as_sdp_skip_frames(struct intel_dp *intel_dp) +{ + struct intel_display *display = to_intel_display(intel_dp); + const struct drm_display_info *info = + &intel_dp->attached_connector->base.display_info; + int max_vrefresh = info->monitor_range.max_vfreq; + int min_vrefresh = info->monitor_range.min_vfreq; + + /* Off by default; gated by the enable_periodic_assdp debugfs knob. */ + if (!display->params.enable_periodic_assdp) + return 0; + + if (min_vrefresh <= 0 || max_vrefresh <= min_vrefresh) + return 0; + + return min_t(u32, max_vrefresh / min_vrefresh - 1, + REG_FIELD_MAX(PR_ALPM_CTL_AS_SDP_SKIP_FRAMES_MASK)); +} + +/* + * Whether periodic AS SDP transmission (AS SDP skip frames) will be programmed + * for this Panel Replay config. The skip counter needs the AS SDP to keep + * flowing during PR active, which is incompatible with DC3co, so this is used + * to keep DC3co disabled while skip frames is enabled. + */ +bool intel_alpm_pr_as_sdp_skip_frames_enabled(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(intel_dp); + + /* + * The AS SDP skip frames field only exists on Xe3p_LPD+. Periodic AS SDP + * drives the panel down to its minimum refresh rate on its own, so it is + * only used when VRR is not actively driving the refresh rate. + */ + if (DISPLAY_VER(display) < 35 || !intel_dp->as_sdp_supported || + !crtc_state->has_panel_replay || crtc_state->vrr.enable) + return false; + + return intel_pr_as_sdp_skip_frames(intel_dp) > 0; +} + +/* + * Program the AS SDP portion of PR_ALPM_CTL: the transmission position, the + * skip-frame counter and the coupled AS SDP transmission / DC3CO idle-protocol + * bits. This is a full recompute of those fields (the base value is built from + * scratch, not read back), so it can be called both at PR enable time and when + * VRR is toggled seamlessly - which changes whether periodic AS SDP is used. + * + * Caller must hold intel_dp->alpm.lock. + */ +static void intel_alpm_configure_pr_as_sdp(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(intel_dp); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + u32 pr_alpm_ctl = get_pr_alpm_as_sdp_transmission_time(crtc_state); + u32 skip_frames = 0; + + if (intel_alpm_pr_as_sdp_skip_frames_enabled(intel_dp, crtc_state)) + skip_frames = intel_pr_as_sdp_skip_frames(intel_dp); + + if (crtc_state->link_off_after_as_sdp_when_pr_active) + pr_alpm_ctl |= PR_ALPM_CTL_ALLOW_LINK_OFF_BETWEEN_AS_SDP_AND_SU; + + /* + * Skip frames needs the AS SDP to keep flowing during PR active, so it + * is mutually exclusive with disabling AS SDP transmission in active and + * with the DC3CO idle protocol. + */ + if (skip_frames) { + pr_alpm_ctl |= PR_ALPM_CTL_AS_SDP_SKIP_FRAMES(skip_frames); + pr_alpm_ctl &= ~PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE; + pr_alpm_ctl &= ~PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL; + } else { + pr_alpm_ctl &= ~PR_ALPM_CTL_AS_SDP_SKIP_FRAMES_MASK; + + if (crtc_state->disable_as_sdp_when_pr_active) + pr_alpm_ctl |= PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE; + + if (intel_display_power_dc3co_allowed(display)) + pr_alpm_ctl |= PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL; + } + + intel_de_write(display, PR_ALPM_CTL(display, cpu_transcoder), pr_alpm_ctl); +} + +/* + * VRR can be enabled or disabled seamlessly, i.e. without a modeset and without + * cycling Panel Replay, so the AS SDP skip-frame programming done at PR enable + * time would otherwise go stale across a VRR toggle. Reprogram it here so the + * skip counter (and the coupled bits) matches the new VRR state. + */ +void intel_alpm_pr_as_sdp_update(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + struct intel_encoder *encoder; + + /* AS SDP skip frames field only exists on Xe3p_LPD+ */ + if (DISPLAY_VER(display) < 35) + return; + + for_each_intel_encoder_mask(display->drm, encoder, + crtc_state->uapi.encoder_mask) { + struct intel_dp *intel_dp; + + if (!intel_encoder_is_dp(encoder)) + continue; + + intel_dp = enc_to_intel_dp(encoder); + + if (!intel_dp->as_sdp_supported || + !intel_alpm_is_alpm_aux_less(intel_dp, crtc_state)) + continue; + + mutex_lock(&intel_dp->alpm.lock); + intel_alpm_configure_pr_as_sdp(intel_dp, crtc_state); + mutex_unlock(&intel_dp->alpm.lock); + } +} + static void lnl_alpm_configure(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { @@ -397,22 +533,8 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp, ALPM_CTL_AUX_LESS_SLEEP_HOLD_TIME_50_SYMBOLS | ALPM_CTL_AUX_LESS_WAKE_TIME(crtc_state->alpm_state.aux_less_wake_lines); - if (intel_dp->as_sdp_supported) { - u32 pr_alpm_ctl = get_pr_alpm_as_sdp_transmission_time(crtc_state); - - if (crtc_state->link_off_after_as_sdp_when_pr_active) - pr_alpm_ctl |= PR_ALPM_CTL_ALLOW_LINK_OFF_BETWEEN_AS_SDP_AND_SU; - if (crtc_state->disable_as_sdp_when_pr_active) - pr_alpm_ctl |= PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE; - - if (intel_display_power_dc3co_allowed(display)) - pr_alpm_ctl |= PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL; - else - pr_alpm_ctl &= ~PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL; - - intel_de_write(display, PR_ALPM_CTL(display, cpu_transcoder), - pr_alpm_ctl); - } + if (intel_dp->as_sdp_supported) + intel_alpm_configure_pr_as_sdp(intel_dp, crtc_state); } else { alpm_ctl = ALPM_CTL_EXTENDED_FAST_WAKE_ENABLE | @@ -506,7 +628,7 @@ void intel_alpm_enable_sink(struct intel_dp *intel_dp, intel_alpm_aux_less_wake_supported(intel_dp))) val |= DP_ALPM_MODE_AUX_LESS; - drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, val); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, val); } void intel_alpm_lobf_enable(const struct intel_crtc_state *new_crtc_state) @@ -629,12 +751,12 @@ bool intel_alpm_get_error(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); struct drm_dp_aux *aux = &intel_dp->aux; + int ret; u8 val; - int r; - r = drm_dp_dpcd_readb(aux, DP_RECEIVER_ALPM_STATUS, &val); - if (r != 1) { - drm_err(display->drm, "Error reading ALPM status\n"); + ret = drm_dp_dpcd_read_byte(aux, DP_RECEIVER_ALPM_STATUS, &val); + if (ret < 0) { + drm_err(display->drm, "Error reading ALPM status (%pe)\n", ERR_PTR(ret)); return true; } @@ -642,7 +764,7 @@ bool intel_alpm_get_error(struct intel_dp *intel_dp) drm_dbg_kms(display->drm, "ALPM lock timeout error\n"); /* Clearing error */ - drm_dp_dpcd_writeb(aux, DP_RECEIVER_ALPM_STATUS, val); + drm_dp_dpcd_write_byte(aux, DP_RECEIVER_ALPM_STATUS, val); return true; } diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h b/drivers/gpu/drm/i915/display/intel_alpm.h index 1cf70668ab1b..f8f605d94f96 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.h +++ b/drivers/gpu/drm/i915/display/intel_alpm.h @@ -34,6 +34,9 @@ bool intel_alpm_aux_wake_supported(struct intel_dp *intel_dp); bool intel_alpm_aux_less_wake_supported(struct intel_dp *intel_dp); bool intel_alpm_is_alpm_aux_less(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); +bool intel_alpm_pr_as_sdp_skip_frames_enabled(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state); +void intel_alpm_pr_as_sdp_update(const struct intel_crtc_state *crtc_state); void intel_alpm_disable(struct intel_dp *intel_dp); bool intel_alpm_get_error(struct intel_dp *intel_dp); void intel_alpm_lobf_compute_config_late(struct intel_dp *intel_dp, diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 97cbae2e547e..7b6a6f8c3cf1 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -34,6 +34,7 @@ #include #include +#include "intel_ddi_buf_trans.h" #include "intel_display.h" #include "intel_display_core.h" #include "intel_display_rpm.h" @@ -72,6 +73,8 @@ struct intel_bios_encoder_data { struct intel_display *display; + struct intel_ddi_buf_trans *vspeo; + union intel_ddi_buf_trans_entry *entries; struct child_device_config child; struct dsc_compression_parameters_entry *dsc; struct list_head node; @@ -200,6 +203,8 @@ static const struct { .min_size = sizeof(struct bdb_mipi_sequence) }, { .section_id = BDB_COMPRESSION_PARAMETERS, .min_size = sizeof(struct bdb_compression_parameters), }, + { .section_id = BDB_VSWING_PREEMPH, + .min_size = sizeof(struct bdb_vswing_preemph), }, { .section_id = BDB_GENERIC_DTD, .min_size = sizeof(struct bdb_generic_dtd), }, }; @@ -2203,6 +2208,31 @@ parse_compression_parameters(struct intel_display *display) } } +static int vswing_preemph_num_rows(struct intel_display *display) +{ + return DISPLAY_VER(display) >= 14 ? 16 : 10; +} + +static void +parse_vswing_preemph_override(struct intel_display *display) +{ + const struct bdb_vswing_preemph *block; + + if (display->vbt.version < 218) + return; + + block = bdb_find_section(display, BDB_VSWING_PREEMPH); + + /* pre-ICL GOPs don't have VBT #57 */ + if (!block) + return; + + display->vbt.vspeo.tables = block->tables; + display->vbt.vspeo.num_tables = block->num_tables; + display->vbt.vspeo.num_columns = block->num_columns; + display->vbt.vspeo.num_rows = vswing_preemph_num_rows(display); +} + static u8 translate_iboost(struct intel_display *display, u8 val) { static const u8 mapping[] = { 1, 3, 7 }; /* See VBT spec */ @@ -2621,6 +2651,30 @@ static void sanitize_device_type(struct intel_bios_encoder_data *devdata, devdata->child.device_type |= DEVICE_TYPE_NOT_HDMI_OUTPUT; } +static void allocate_vswing_preemph_override(struct intel_bios_encoder_data *devdata) +{ + int num_rows = devdata->display->vbt.vspeo.num_rows; + union intel_ddi_buf_trans_entry *entries; + struct intel_ddi_buf_trans *vspeo; + + if (!intel_bios_encoder_requests_vspeo(devdata)) + return; + + vspeo = kzalloc_obj(*vspeo); + if (!vspeo) + return; + + entries = kzalloc_objs(*entries, num_rows); + if (!entries) { + kfree(vspeo); + return; + } + + devdata->entries = entries; + devdata->vspeo = vspeo; + devdata->vspeo->num_entries = num_rows; +} + static void sanitize_hdmi_level_shift(struct intel_bios_encoder_data *devdata, enum port port) { @@ -2737,7 +2791,6 @@ static bool is_port_valid(struct intel_display *display, enum port port) static void print_ddi_port(const struct intel_bios_encoder_data *devdata) { struct intel_display *display = devdata->display; - const struct child_device_config *child = &devdata->child; bool is_dvi, is_hdmi, is_dp, is_edp, is_dsi, is_crt, supports_typec_usb, supports_tbt; int dp_boost_level, dp_max_link_rate, hdmi_boost_level, hdmi_level_shift, max_tmds_clock; enum port port; @@ -2774,6 +2827,11 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata) "Port %c supports dynamic DDI allocation in TCSS\n", port_name(port)); + if (intel_bios_encoder_requests_vspeo(devdata)) + drm_dbg_kms(display->drm, + "Port %c requests vswing/pre-emphasis override\n", + port_name(port)); + hdmi_level_shift = intel_bios_hdmi_level_shift(devdata); if (hdmi_level_shift >= 0) { drm_dbg_kms(display->drm, @@ -2805,14 +2863,6 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata) drm_dbg_kms(display->drm, "Port %c VBT DP max link rate: %d\n", port_name(port), dp_max_link_rate); - - /* - * FIXME need to implement support for VBT - * vswing/preemph tables should this ever trigger. - */ - drm_WARN(display->drm, child->use_vbt_vswing, - "Port %c asks to use VBT vswing/preemph tables\n", - port_name(port)); } static void parse_ddi_port(struct intel_bios_encoder_data *devdata) @@ -2834,6 +2884,7 @@ static void parse_ddi_port(struct intel_bios_encoder_data *devdata) sanitize_dedicated_external(devdata, port); sanitize_device_type(devdata, port); sanitize_hdmi_level_shift(devdata, port); + allocate_vswing_preemph_override(devdata); } static bool has_ddi_port_info(struct intel_display *display) @@ -3291,6 +3342,7 @@ void intel_bios_init(struct intel_display *display) parse_general_features(display); parse_general_definitions(display); parse_driver_features(display); + parse_vswing_preemph_override(display); /* Depends on child device list */ parse_compression_parameters(display); @@ -3370,6 +3422,9 @@ void intel_bios_driver_remove(struct intel_display *display) list_for_each_entry_safe(devdata, nd, &display->vbt.display_devices, node) { list_del(&devdata->node); + + kfree(devdata->entries); + kfree(devdata->vspeo); kfree(devdata->dsc); kfree(devdata); } @@ -3801,6 +3856,11 @@ int intel_bios_hdmi_ddc_pin(const struct intel_bios_encoder_data *devdata) return map_ddc_pin(devdata->display, devdata->child.ddc_pin); } +bool intel_bios_encoder_requests_vspeo(const struct intel_bios_encoder_data *devdata) +{ + return devdata->display->vbt.version >= 218 && devdata->child.use_vbt_vswing; +} + bool intel_bios_encoder_supports_typec_usb(const struct intel_bios_encoder_data *devdata) { return devdata->display->vbt.version >= 195 && devdata->child.dp_usb_type_c; @@ -3811,6 +3871,190 @@ bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devda return devdata->display->vbt.version >= 209 && devdata->child.tbt; } +static bool +validate_vspeo(const struct intel_bios_encoder_data *devdata, bool has_dp) +{ + struct intel_ddi_buf_trans *vspeo; + + vspeo = devdata->vspeo; + if (!vspeo) + return false; + + if (!has_dp) + return false; + + return true; +} + +const struct intel_ddi_buf_trans * +intel_bios_get_c20_vspeo(const struct intel_bios_encoder_data *devdata, + bool has_dp, bool is_uhbr) +{ + struct intel_display *display = devdata->display; + union intel_ddi_buf_trans_entry *entries = devdata->entries; + struct intel_ddi_buf_trans *vspeo = devdata->vspeo; + const u32 *tables = display->vbt.vspeo.tables; + int num_columns = display->vbt.vspeo.num_columns; + int num_rows = display->vbt.vspeo.num_rows; + int idx = is_uhbr ? 5 : 4; + size_t offset = 0; + int level; + + if (!validate_vspeo(devdata, has_dp)) + return NULL; + + offset += idx * num_rows * num_columns; + + for (level = 0; level < num_rows; level++) { + u32 vswing = tables[offset]; + u32 pre_cursor = tables[offset + 1]; + u32 post_cursor = tables[offset + 2]; + + entries[level].snps.vswing = vswing; + entries[level].snps.pre_cursor = pre_cursor; + entries[level].snps.post_cursor = post_cursor; + + offset += num_columns; + } + + vspeo->entries = entries; + + return vspeo; +} + +const struct intel_ddi_buf_trans * +intel_bios_get_c10_vspeo(const struct intel_bios_encoder_data *devdata, + bool has_dp, int port_clock, bool has_edp) +{ + struct intel_display *display = devdata->display; + union intel_ddi_buf_trans_entry *entries = devdata->entries; + struct intel_ddi_buf_trans *vspeo = devdata->vspeo; + const u32 *tables = display->vbt.vspeo.tables; + int num_columns = display->vbt.vspeo.num_columns; + int num_rows = display->vbt.vspeo.num_rows; + size_t offset = 0; + int level, idx; + + if (!validate_vspeo(devdata, has_dp)) + return NULL; + + if (has_edp) + idx = port_clock > 540000 ? 3 : 2; + else + idx = port_clock > 270000 ? 1 : 0; + + offset += idx * num_rows * num_columns; + + for (level = 0; level < num_rows; level++) { + u32 vswing = tables[offset]; + u32 pre_cursor = tables[offset + 1]; + u32 post_cursor = tables[offset + 2]; + + entries[level].snps.vswing = vswing; + entries[level].snps.pre_cursor = pre_cursor; + entries[level].snps.post_cursor = post_cursor; + + offset += num_columns; + } + + vspeo->entries = entries; + + return vspeo; +} + +const struct intel_ddi_buf_trans * +intel_bios_get_ehl_combo_vspeo(const struct intel_bios_encoder_data *devdata, + bool has_dp, int port_clock, bool low_vswing_edp) +{ + struct intel_display *display = devdata->display; + union intel_ddi_buf_trans_entry *entries = devdata->entries; + struct intel_ddi_buf_trans *vspeo = devdata->vspeo; + const u32 *tables = display->vbt.vspeo.tables; + int num_columns = display->vbt.vspeo.num_columns; + int num_rows = display->vbt.vspeo.num_rows; + size_t offset = 0; + int level, idx; + + if (!validate_vspeo(devdata, has_dp)) + return NULL; + + if (low_vswing_edp) + idx = port_clock > 540000 ? 2 : 1; + else + idx = port_clock > 270000 ? 1 : 0; + + offset += idx * num_rows * num_columns; + + for (level = 0; level < num_rows; level++) { + u32 dw2_swing_sel = tables[offset]; + u32 dw7_n_scalar = tables[offset + 1]; + u32 dw4_cursor_coeff = tables[offset + 2]; + u32 dw4_post_cursor_2 = tables[offset + 3]; + u32 dw4_post_cursor_1 = tables[offset + 4]; + + entries[level].icl.dw2_swing_sel = dw2_swing_sel; + entries[level].icl.dw7_n_scalar = dw7_n_scalar; + entries[level].icl.dw4_cursor_coeff = dw4_cursor_coeff; + entries[level].icl.dw4_post_cursor_2 = dw4_post_cursor_2; + entries[level].icl.dw4_post_cursor_1 = dw4_post_cursor_1; + + offset += num_columns; + } + + vspeo->entries = entries; + + return vspeo; +} + +const struct intel_ddi_buf_trans * +intel_bios_get_jsl_combo_vspeo(const struct intel_bios_encoder_data *devdata, + bool has_dp, int port_clock, bool low_vswing_edp) +{ + struct intel_display *display = devdata->display; + union intel_ddi_buf_trans_entry *entries = devdata->entries; + struct intel_ddi_buf_trans *vspeo = devdata->vspeo; + const u32 *tables = display->vbt.vspeo.tables; + int num_columns = display->vbt.vspeo.num_columns; + int num_rows = display->vbt.vspeo.num_rows; + size_t offset = 0; + int idx = 0; + int level; + + if (!validate_vspeo(devdata, has_dp)) + return NULL; + + if (low_vswing_edp) { + if (port_clock > 540000) + idx = 0; + else if (port_clock > 270000) + idx = 2; + else + idx = 1; + } + + offset += idx * num_rows * num_columns; + + for (level = 0; level < num_rows; level++) { + u32 dw2_swing_sel = tables[offset]; + u32 dw7_n_scalar = tables[offset + 1]; + u32 dw4_cursor_coeff = tables[offset + 2]; + u32 dw4_post_cursor_2 = tables[offset + 3]; + u32 dw4_post_cursor_1 = tables[offset + 4]; + + entries[level].icl.dw2_swing_sel = dw2_swing_sel; + entries[level].icl.dw7_n_scalar = dw7_n_scalar; + entries[level].icl.dw4_cursor_coeff = dw4_cursor_coeff; + entries[level].icl.dw4_post_cursor_2 = dw4_post_cursor_2; + entries[level].icl.dw4_post_cursor_1 = dw4_post_cursor_1; + + offset += num_columns; + } + + vspeo->entries = entries; + + return vspeo; +} + bool intel_bios_encoder_is_dedicated_external(const struct intel_bios_encoder_data *devdata) { return devdata->display->vbt.version >= 264 && diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h index 75dff27b4228..196b8b3f434f 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.h +++ b/drivers/gpu/drm/i915/display/intel_bios.h @@ -73,6 +73,20 @@ bool intel_bios_get_dsc_params(struct intel_encoder *encoder, const struct intel_bios_encoder_data * intel_bios_encoder_data_lookup(struct intel_display *display, enum port port); +const struct intel_ddi_buf_trans * +intel_bios_get_c20_vspeo(const struct intel_bios_encoder_data *devdata, + bool has_dp, bool is_uhbr); +const struct intel_ddi_buf_trans * +intel_bios_get_c10_vspeo(const struct intel_bios_encoder_data *devdata, + bool has_dp, int port_clock, bool has_edp); +const struct intel_ddi_buf_trans * +intel_bios_get_ehl_combo_vspeo(const struct intel_bios_encoder_data *devdata, + bool has_dp, int port_clock, bool low_vswing_edp); +const struct intel_ddi_buf_trans * +intel_bios_get_jsl_combo_vspeo(const struct intel_bios_encoder_data *devdata, + bool has_dp, int port_clock, bool low_vswing_edp); + +bool intel_bios_encoder_requests_vspeo(const struct intel_bios_encoder_data *devdata); bool intel_bios_encoder_supports_dvi(const struct intel_bios_encoder_data *devdata); bool intel_bios_encoder_supports_hdmi(const struct intel_bios_encoder_data *devdata); bool intel_bios_encoder_supports_dp(const struct intel_bios_encoder_data *devdata); diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 87ced9f6ff40..f1df0f9ba762 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -3998,25 +3998,17 @@ xelpd_program_plane_pre_csc_lut(struct intel_dsb *dsb, } static void -xelpd_program_plane_post_csc_lut(struct intel_dsb *dsb, - const struct intel_plane_state *plane_state) +xelpd_load_hdr_post_csc_lut(struct intel_display *display, + struct intel_dsb *dsb, + enum pipe pipe, + enum plane_id plane, + const struct drm_color_lut32 *post_csc_lut) { - struct intel_display *display = to_intel_display(plane_state); - const struct drm_plane_state *state = &plane_state->uapi; - enum pipe pipe = to_intel_plane(state->plane)->pipe; - enum plane_id plane = to_intel_plane(state->plane)->id; - const struct drm_color_lut32 *post_csc_lut = plane_state->hw.gamma_lut->data; int i, lut_size = 32; u32 lut_val; - if (!icl_is_hdr_plane(display, plane)) - return; - intel_de_write_dsb(display, dsb, PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, 0), PLANE_PAL_PREC_AUTO_INCREMENT); - /* TODO: Add macro */ - intel_de_write_dsb(display, dsb, PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH(pipe, plane, 0), - PLANE_PAL_PREC_AUTO_INCREMENT); for (i = 0; i < lut_size + 3; i++) { if (post_csc_lut) { @@ -4036,8 +4028,62 @@ xelpd_program_plane_post_csc_lut(struct intel_dsb *dsb, } intel_de_write_dsb(display, dsb, PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, 0), 0); - intel_de_write_dsb(display, dsb, - PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH(pipe, plane, 0), 0); +} + +static void +xelpd_load_sdr_post_csc_lut(struct intel_display *display, + struct intel_dsb *dsb, + enum pipe pipe, + enum plane_id plane, + const struct drm_color_lut32 *post_csc_lut) +{ + int i, lut_size = 32; + u32 lut_val; + + /* + * First 3 planes are HDR, so reduce by 3 to get to the right + * SDR plane offset + */ + plane = plane - 3; + + intel_de_write_dsb(display, dsb, PLANE_POST_CSC_GAMC_INDEX(pipe, plane, 0), + PLANE_PAL_PREC_AUTO_INCREMENT); + + for (i = 0; i < lut_size + 3; i++) { + if (post_csc_lut) { + if (i < lut_size) + lut_val = drm_color_lut32_extract(post_csc_lut[i].green, 16); + /* else duplicate last lut_val */ + } else { + if (i < lut_size) + lut_val = (i * ((1 << 16) - 1)) / (lut_size - 1); + else + lut_val = 1 << 16; + } + + intel_de_write_dsb(display, dsb, + PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), + lut_val); + } + + intel_de_write_dsb(display, dsb, PLANE_POST_CSC_GAMC_INDEX(pipe, plane, 0), 0); +} + +static void +xelpd_program_plane_post_csc_lut(struct intel_dsb *dsb, + const struct intel_plane_state *plane_state) +{ + struct intel_display *display = to_intel_display(plane_state); + const struct drm_plane_state *state = &plane_state->uapi; + enum pipe pipe = to_intel_plane(state->plane)->pipe; + enum plane_id plane = to_intel_plane(state->plane)->id; + const struct drm_color_lut32 *post_csc_lut = plane_state->hw.gamma_lut ? + plane_state->hw.gamma_lut->data : NULL; + + if (icl_is_hdr_plane(display, plane)) + xelpd_load_hdr_post_csc_lut(display, dsb, pipe, plane, post_csc_lut); + else + xelpd_load_sdr_post_csc_lut(display, dsb, pipe, plane, post_csc_lut); } static void diff --git a/drivers/gpu/drm/i915/display/intel_color_pipeline.c b/drivers/gpu/drm/i915/display/intel_color_pipeline.c index 6cf8080ee800..7fc31fe891a8 100644 --- a/drivers/gpu/drm/i915/display/intel_color_pipeline.c +++ b/drivers/gpu/drm/i915/display/intel_color_pipeline.c @@ -12,7 +12,7 @@ #include "skl_universal_plane.h" #define MAX_COLOR_PIPELINES 1 -#define MAX_COLOROP 4 +#define MAX_COLOROP 5 #define PLANE_DEGAMMA_SIZE 128 #define PLANE_GAMMA_SIZE 32 @@ -31,6 +31,7 @@ static const struct drm_colorop_funcs intel_colorop_funcs = { * the pipeline totally unusable. */ static const enum intel_color_block xe3plpd_primary_plane_pipeline[] = { + INTEL_PLANE_CB_CSC_FF, INTEL_PLANE_CB_PRE_CSC_LUT, INTEL_PLANE_CB_CSC, INTEL_PLANE_CB_3DLUT, @@ -38,11 +39,25 @@ static const enum intel_color_block xe3plpd_primary_plane_pipeline[] = { }; static const enum intel_color_block hdr_plane_pipeline[] = { + INTEL_PLANE_CB_CSC_FF, INTEL_PLANE_CB_PRE_CSC_LUT, INTEL_PLANE_CB_CSC, INTEL_PLANE_CB_POST_CSC_LUT, }; +static const enum intel_color_block sdr_plane_yuv_pipeline[] = { + INTEL_PLANE_CB_CSC_FF, + INTEL_PLANE_CB_POST_CSC_LUT, +}; + +static const u64 intel_plane_supported_csc_ff = + BIT(DRM_COLOROP_FM_YCBCR601_FULL_RGB) | + BIT(DRM_COLOROP_FM_YCBCR601_LIMITED_RGB) | + BIT(DRM_COLOROP_FM_YCBCR709_FULL_RGB) | + BIT(DRM_COLOROP_FM_YCBCR709_LIMITED_RGB) | + BIT(DRM_COLOROP_FM_YCBCR2020_NC_FULL_RGB) | + BIT(DRM_COLOROP_FM_YCBCR2020_NC_LIMITED_RGB); + static bool plane_has_3dlut(struct intel_display *display, enum pipe pipe, struct drm_plane *plane) { @@ -92,6 +107,12 @@ struct intel_colorop *intel_color_pipeline_plane_add_colorop(struct drm_plane *p DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR, DRM_COLOROP_FLAG_ALLOW_BYPASS); break; + case INTEL_PLANE_CB_CSC_FF: + ret = drm_plane_colorop_fixed_matrix_init(dev, &colorop->base, plane, + &intel_colorop_funcs, + intel_plane_supported_csc_ff, + DRM_COLOROP_FLAG_ALLOW_BYPASS); + break; default: drm_err(plane->dev, "Invalid colorop id [%d]", id); ret = -EINVAL; @@ -126,9 +147,12 @@ int _intel_color_pipeline_plane_init(struct drm_plane *plane, struct drm_prop_en if (plane_has_3dlut(display, pipe, plane)) { pipeline = xe3plpd_primary_plane_pipeline; pipeline_len = ARRAY_SIZE(xe3plpd_primary_plane_pipeline); - } else { + } else if (icl_is_hdr_plane(display, to_intel_plane(plane)->id)) { pipeline = hdr_plane_pipeline; pipeline_len = ARRAY_SIZE(hdr_plane_pipeline); + } else { + pipeline = sdr_plane_yuv_pipeline; + pipeline_len = ARRAY_SIZE(sdr_plane_yuv_pipeline); } for (i = 0; i < pipeline_len; i++) { @@ -155,17 +179,11 @@ int _intel_color_pipeline_plane_init(struct drm_plane *plane, struct drm_prop_en int intel_color_pipeline_plane_init(struct drm_plane *plane, enum pipe pipe) { - struct drm_device *dev = plane->dev; - struct intel_display *display = to_intel_display(dev); struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES] = {}; int len = 0; int ret = 0; int i; - /* Currently expose pipeline only for HDR planes */ - if (!icl_is_hdr_plane(display, to_intel_plane(plane)->id)) - return 0; - /* Add pipeline consisting of transfer functions */ ret = _intel_color_pipeline_plane_init(plane, &pipelines[len], pipe); if (ret) diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index ad4f362e0c09..92675a88b969 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -251,6 +251,15 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, str_enabled_disabled(pipe_config->has_panel_replay), str_enabled_disabled(pipe_config->enable_psr2_sel_fetch)); drm_printf(&p, "minimum hblank: %d\n", pipe_config->min_hblank); + + drm_printf(&p, "DIP Transmission Lines: EMP/AS SDP: %u\n", + pipe_config->dip.emp_as_sdp_tl); + drm_printf(&p, "DIP Transmission Lines: Common Base SDP: %u, GMP SDP: %u, PPS SDP: %u, VSC SDP: %u, VSC_EXT SDP: %u\n", + pipe_config->dip.cmn_sdp_tl, + pipe_config->dip.gmp_sdp_tl, + pipe_config->dip.pps_sdp_tl, + pipe_config->dip.vsc_sdp_tl, + pipe_config->dip.vsc_ext_sdp_tl); } drm_printf(&p, "audio: %i, infoframes: %i, infoframes enabled: 0x%x\n", diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index dbebd7210848..b83f0afaa9b5 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -5,6 +5,7 @@ #include #include +#include #include @@ -189,7 +190,7 @@ int intel_cx0_wait_for_ack(struct intel_encoder *encoder, drm_dbg_kms(display->drm, "PHY %c Error occurred during %s command. Status: 0x%x\n", phy_name(phy), - command == XELPDP_PORT_P2M_COMMAND_READ_ACK ? "read" : "write", *val); + str_read_write(command == XELPDP_PORT_P2M_COMMAND_READ_ACK), *val); intel_cx0_bus_reset(encoder, lane); return -EINVAL; } @@ -198,7 +199,7 @@ int intel_cx0_wait_for_ack(struct intel_encoder *encoder, drm_dbg_kms(display->drm, "PHY %c Not a %s response. MSGBUS Status: 0x%x.\n", phy_name(phy), - command == XELPDP_PORT_P2M_COMMAND_READ_ACK ? "read" : "write", *val); + str_read_write(command == XELPDP_PORT_P2M_COMMAND_READ_ACK), *val); intel_cx0_bus_reset(encoder, lane); return -EINVAL; } diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 9b3b526e5e55..a46ab5d3d70f 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -49,6 +49,7 @@ #include "intel_ddi.h" #include "intel_ddi_buf_trans.h" #include "intel_de.h" +#include "intel_dip.h" #include "intel_display_power.h" #include "intel_display_regs.h" #include "intel_display_types.h" @@ -2331,15 +2332,17 @@ static void intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel bool enable) { struct intel_display *display = to_intel_display(intel_dp); + int ret; if (!crtc_state->vrr.enable) return; - if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_DOWNSPREAD_CTRL, - enable ? DP_MSA_TIMING_PAR_IGNORE_EN : 0) <= 0) + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_DOWNSPREAD_CTRL, + enable ? DP_MSA_TIMING_PAR_IGNORE_EN : 0); + if (ret < 0) drm_dbg_kms(display->drm, - "Failed to %s MSA_TIMING_PAR_IGNORE in the sink\n", - str_enable_disable(enable)); + "Failed to %s MSA_TIMING_PAR_IGNORE in the sink (%pe)\n", + str_enable_disable(enable), ERR_PTR(ret)); } static void intel_dp_sink_set_fec_ready(struct intel_dp *intel_dp, @@ -2347,19 +2350,25 @@ static void intel_dp_sink_set_fec_ready(struct intel_dp *intel_dp, bool enable) { struct intel_display *display = to_intel_display(intel_dp); + int ret; if (!crtc_state->fec_enable) return; - if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_FEC_CONFIGURATION, - enable ? DP_FEC_READY : 0) <= 0) - drm_dbg_kms(display->drm, "Failed to set FEC_READY to %s in the sink\n", - str_enabled_disabled(enable)); + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_FEC_CONFIGURATION, + enable ? DP_FEC_READY : 0); + if (ret < 0) + drm_dbg_kms(display->drm, "Failed to set FEC_READY to %s in the sink (%pe)\n", + str_enabled_disabled(enable), ERR_PTR(ret)); - if (enable && - drm_dp_dpcd_writeb(&intel_dp->aux, DP_FEC_STATUS, - DP_FEC_DECODE_EN_DETECTED | DP_FEC_DECODE_DIS_DETECTED) <= 0) - drm_dbg_kms(display->drm, "Failed to clear FEC detected flags\n"); + if (enable) { + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_FEC_STATUS, + DP_FEC_DECODE_EN_DETECTED | + DP_FEC_DECODE_DIS_DETECTED); + if (ret < 0) + drm_dbg_kms(display->drm, "Failed to clear FEC detected flags (%pe)\n", + ERR_PTR(ret)); + } } static int wait_for_fec_detected(struct drm_dp_aux *aux, bool enabled) @@ -2736,6 +2745,8 @@ static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state, /* 6.o Configure and enable FEC if needed */ intel_ddi_enable_fec(encoder, crtc_state); + intel_dip_cmn_sdp_transmission_line_enable(crtc_state); + /* 7.a 128b/132b SST. */ if (!is_mst && intel_dp_is_uhbr(crtc_state)) { /* VCPID 1, start slot 0 for 128b/132b, tu slots */ @@ -3123,6 +3134,7 @@ static void intel_ddi_buf_disable(struct intel_encoder *encoder, DP_TP_CTL_ENABLE, 0); } + intel_dip_cmn_sdp_transmission_line_disable(crtc_state); intel_ddi_disable_fec(encoder, crtc_state); if (DISPLAY_VER(display) < 14) @@ -4235,6 +4247,7 @@ static void intel_ddi_get_config(struct intel_encoder *encoder, intel_read_dp_sdp(encoder, pipe_config, HDMI_PACKET_TYPE_GAMUT_METADATA); intel_read_dp_sdp(encoder, pipe_config, DP_SDP_VSC); intel_read_dp_sdp(encoder, pipe_config, DP_SDP_ADAPTIVE_SYNC); + intel_dip_sdp_transmission_line_get_config(pipe_config); intel_audio_codec_get_config(encoder, pipe_config); } diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c index 4cd1e4d76c7a..cc5912178d9c 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c +++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c @@ -1784,6 +1784,70 @@ xe3plpd_get_lt_buf_trans(struct intel_encoder *encoder, return intel_get_buf_trans(&xe3plpd_lt_trans_dp14, n_entries); } +static const struct intel_ddi_buf_trans * +jsl_get_combo_buf_trans_override(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + int *n_entries) +{ + const struct intel_bios_encoder_data *devdata = encoder->devdata; + bool has_edp, has_dp; + int port_clock; + + has_edp = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP); + has_dp = intel_crtc_has_dp_encoder(crtc_state); + port_clock = crtc_state->port_clock; + + return intel_bios_get_jsl_combo_vspeo(devdata, has_dp, port_clock, + has_edp && use_edp_low_vswing(encoder)); +} + +static const struct intel_ddi_buf_trans * +ehl_get_combo_buf_trans_override(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + int *n_entries) +{ + const struct intel_bios_encoder_data *devdata = encoder->devdata; + bool has_edp, has_dp; + int port_clock; + + has_edp = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP); + has_dp = intel_crtc_has_dp_encoder(crtc_state); + port_clock = crtc_state->port_clock; + + return intel_bios_get_ehl_combo_vspeo(devdata, has_dp, port_clock, + has_edp && use_edp_low_vswing(encoder)); +} + +static const struct intel_ddi_buf_trans * +mtl_get_c10_buf_trans_override(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + int *n_entries) +{ + const struct intel_bios_encoder_data *devdata = encoder->devdata; + bool has_edp, has_dp; + int port_clock; + + has_edp = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP); + has_dp = intel_crtc_has_dp_encoder(crtc_state); + port_clock = crtc_state->port_clock; + + return intel_bios_get_c10_vspeo(devdata, has_dp, port_clock, has_edp); +} + +static const struct intel_ddi_buf_trans * +mtl_get_c20_buf_trans_override(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + int *n_entries) +{ + const struct intel_bios_encoder_data *devdata = encoder->devdata; + bool has_dp, is_uhbr; + + has_dp = intel_crtc_has_dp_encoder(crtc_state); + is_uhbr = intel_dp_is_uhbr(crtc_state); + + return intel_bios_get_c20_vspeo(devdata, has_dp, is_uhbr); +} + void intel_ddi_buf_trans_init(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); @@ -1791,10 +1855,13 @@ void intel_ddi_buf_trans_init(struct intel_encoder *encoder) if (HAS_LT_PHY(display)) { encoder->get_buf_trans = xe3plpd_get_lt_buf_trans; } else if (DISPLAY_VER(display) >= 14) { - if (intel_encoder_is_c10phy(encoder)) + if (intel_encoder_is_c10phy(encoder)) { encoder->get_buf_trans = mtl_get_c10_buf_trans; - else + encoder->get_buf_trans_override = mtl_get_c10_buf_trans_override; + } else { encoder->get_buf_trans = mtl_get_c20_buf_trans; + encoder->get_buf_trans_override = mtl_get_c20_buf_trans_override; + } } else if (display->platform.dg2) { encoder->get_buf_trans = dg2_get_snps_buf_trans; } else if (display->platform.alderlake_p) { @@ -1814,14 +1881,17 @@ void intel_ddi_buf_trans_init(struct intel_encoder *encoder) else encoder->get_buf_trans = tgl_get_dkl_buf_trans; } else if (DISPLAY_VER(display) == 11) { - if (display->platform.jasperlake) + if (display->platform.jasperlake) { encoder->get_buf_trans = jsl_get_combo_buf_trans; - else if (display->platform.elkhartlake) + encoder->get_buf_trans_override = jsl_get_combo_buf_trans_override; + } else if (display->platform.elkhartlake) { encoder->get_buf_trans = ehl_get_combo_buf_trans; - else if (intel_encoder_is_combo(encoder)) + encoder->get_buf_trans_override = ehl_get_combo_buf_trans_override; + } else if (intel_encoder_is_combo(encoder)) { encoder->get_buf_trans = icl_get_combo_buf_trans; - else + } else { encoder->get_buf_trans = icl_get_mg_buf_trans; + } } else if (display->platform.geminilake || display->platform.broxton) { encoder->get_buf_trans = bxt_get_buf_trans; } else if (display->platform.cometlake_ulx || @@ -1857,5 +1927,13 @@ const struct intel_ddi_buf_trans *intel_ddi_buf_trans_get(struct intel_encoder * const struct intel_crtc_state *crtc_state, int *n_entries) { + if (encoder->get_buf_trans_override) { + const struct intel_ddi_buf_trans *override; + + override = encoder->get_buf_trans_override(encoder, crtc_state, n_entries); + if (override) + return intel_get_buf_trans(override, n_entries); + } + return encoder->get_buf_trans(encoder, crtc_state, n_entries); } diff --git a/drivers/gpu/drm/i915/display/intel_dip.c b/drivers/gpu/drm/i915/display/intel_dip.c new file mode 100644 index 000000000000..f447150ff7bc --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dip.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2026 Intel Corporation + * + */ + +#include + +#include "intel_de.h" +#include "intel_dip.h" +#include "intel_dip_regs.h" +#include "intel_display_types.h" +#include "intel_hdmi.h" + +static int intel_dip_get_as_sdp_transmission_line(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + + if (!HAS_EMP_AS_SDP_TL(display)) + return 0; + + /* + * EMP_AS_SDP_TL defines the T1 position as the default AS SDP + * Transmission Line, which corresponds to the start of the + * VSYNC pulse. + * + * Use the T1 position for now. + */ + return crtc_state->vrr.vsync_start; +} + +u16 intel_dip_read_emp_as_sdp_tl(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + u32 val; + + if (!HAS_EMP_AS_SDP_TL(display)) + return 0; + + val = intel_de_read(display, EMP_AS_SDP_TL(display, cpu_transcoder)); + return REG_FIELD_GET(EMP_AS_SDP_DB_TL_MASK, val); +} + +void intel_dip_write_emp_as_sdp_tl(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + + if (!HAS_EMP_AS_SDP_TL(display)) + return; + + intel_de_write(display, + EMP_AS_SDP_TL(display, cpu_transcoder), + EMP_AS_SDP_DB_TL(crtc_state->dip.emp_as_sdp_tl)); +} + +static int intel_dip_sdp_stagger_to_tl(struct intel_crtc_state *crtc_state, + int stagger) +{ + return crtc_state->dip.cmn_sdp_tl + stagger; +} + +static +void intel_dip_cmn_sdp_tl_compute_config_late(struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + bool as_sdp; + + if (!HAS_COMMON_SDP_TL(display)) + return; + + as_sdp = crtc_state->infoframes.enable & + intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC); + /* + * When AS SDP is enabled : + * - The common SDP Transmission Line matches the EMP SDP Transmission Line. + * + * When AS SDP is disabled: + * - Bspec mentions the positions as lines of delayed vblank. + * - Guardband = 1st line of delayed vblank + * - Common SDP Transmission line is set to 2nd line of delayed vblank. + */ + + if (as_sdp) + crtc_state->dip.cmn_sdp_tl = crtc_state->dip.emp_as_sdp_tl; + else + crtc_state->dip.cmn_sdp_tl = crtc_state->vrr.guardband - 1; + + if (drm_WARN_ON(display->drm, + crtc_state->dip.cmn_sdp_tl >= + crtc_state->vrr.guardband + crtc_state->set_context_latency)) + return; + + /* + * Currently we are programming the default stagger values, but these + * can be optimized if required, based on number of SDPs enabled. + * + * Default values of the Transmission lines for SDPs other than AS SDP: + * VSC : CMN SDP Transmission line + * GMP : CMN SDP Transmission line + * PPS : CMN SDP Transmission line + 1 + * VSC_EXT: CMN SDP Transmission line + 2 + */ + crtc_state->dip.vsc_sdp_tl = crtc_state->dip.cmn_sdp_tl; + crtc_state->dip.gmp_sdp_tl = + intel_dip_sdp_stagger_to_tl(crtc_state, GMP_STAGGER_DEFAULT); + crtc_state->dip.pps_sdp_tl = + intel_dip_sdp_stagger_to_tl(crtc_state, PPS_STAGGER_DEFAULT); + crtc_state->dip.vsc_ext_sdp_tl = + intel_dip_sdp_stagger_to_tl(crtc_state, VSC_EXT_STAGGER_DEFAULT); +} + +void intel_dip_sdp_tl_compute_config_late(struct intel_crtc_state *crtc_state) +{ + crtc_state->dip.emp_as_sdp_tl = intel_dip_get_as_sdp_transmission_line(crtc_state); + + intel_dip_cmn_sdp_tl_compute_config_late(crtc_state); +} + +static +void intel_dip_cmn_sdp_transmission_line_get_config(struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + u16 vsc_ext_stagger, pps_stagger, gmp_stagger; + u32 val; + + if (!HAS_COMMON_SDP_TL(display)) + return; + + val = intel_de_read(display, CMN_SDP_TL(display, cpu_transcoder)); + + if (!(val & TRANSMISSION_LINE_ENABLE)) + return; + + crtc_state->dip.cmn_sdp_tl = REG_FIELD_GET(BASE_TRANSMISSION_LINE_MASK, val); + + /* SDP VSC uses same transmission line as CMN base transmission line */ + crtc_state->dip.vsc_sdp_tl = crtc_state->dip.cmn_sdp_tl; + + val = intel_de_read(display, CMN_SDP_TL_STGR_CTL(display, cpu_transcoder)); + + vsc_ext_stagger = REG_FIELD_GET(VSC_EXT_STAGGER_MASK, val); + pps_stagger = REG_FIELD_GET(PPS_STAGGER_MASK, val); + gmp_stagger = REG_FIELD_GET(GMP_STAGGER_MASK, val); + + crtc_state->dip.vsc_ext_sdp_tl = + intel_dip_sdp_stagger_to_tl(crtc_state, vsc_ext_stagger); + crtc_state->dip.pps_sdp_tl = + intel_dip_sdp_stagger_to_tl(crtc_state, pps_stagger); + crtc_state->dip.gmp_sdp_tl = + intel_dip_sdp_stagger_to_tl(crtc_state, gmp_stagger); +} + +void intel_dip_sdp_transmission_line_get_config(struct intel_crtc_state *crtc_state) +{ + crtc_state->dip.emp_as_sdp_tl = intel_dip_read_emp_as_sdp_tl(crtc_state); + + intel_dip_cmn_sdp_transmission_line_get_config(crtc_state); +} + +static int intel_dip_sdp_tl_to_stagger(const struct intel_crtc_state *crtc_state, + u16 sdp_transmission_line) +{ + return sdp_transmission_line - crtc_state->dip.cmn_sdp_tl; +} + +void intel_dip_cmn_sdp_transmission_line_enable(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + int gmp_stagger; + int pps_stagger; + int vsc_ext_stagger; + + if (!HAS_COMMON_SDP_TL(display)) + return; + + gmp_stagger = intel_dip_sdp_tl_to_stagger(crtc_state, + crtc_state->dip.gmp_sdp_tl); + + pps_stagger = intel_dip_sdp_tl_to_stagger(crtc_state, + crtc_state->dip.pps_sdp_tl); + + vsc_ext_stagger = intel_dip_sdp_tl_to_stagger(crtc_state, + crtc_state->dip.vsc_ext_sdp_tl); + + if (drm_WARN_ON(display->drm, gmp_stagger < 0)) + return; + if (drm_WARN_ON(display->drm, pps_stagger < 0)) + return; + if (drm_WARN_ON(display->drm, vsc_ext_stagger < 0)) + return; + + intel_de_write(display, CMN_SDP_TL_STGR_CTL(display, cpu_transcoder), + GMP_STAGGER(gmp_stagger) | + PPS_STAGGER(pps_stagger) | + VSC_EXT_STAGGER(vsc_ext_stagger)); + + intel_de_write(display, CMN_SDP_TL(display, cpu_transcoder), + TRANSMISSION_LINE_ENABLE | + BASE_TRANSMISSION_LINE(crtc_state->dip.cmn_sdp_tl)); +} + +void intel_dip_cmn_sdp_transmission_line_disable(const struct intel_crtc_state *old_crtc_state) +{ + struct intel_display *display = to_intel_display(old_crtc_state); + enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; + + if (!HAS_COMMON_SDP_TL(display)) + return; + + intel_de_write(display, CMN_SDP_TL(display, cpu_transcoder), 0); +} diff --git a/drivers/gpu/drm/i915/display/intel_dip.h b/drivers/gpu/drm/i915/display/intel_dip.h new file mode 100644 index 000000000000..7c64c84cb1be --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dip.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef __INTEL_DIP_H__ +#define __INTEL_DIP_H__ + +#include "intel_display_device.h" + +/* + * Video DIP (Data Island Packet) helpers. + * + * This file contains helpers for programming video DIP related hardware. + * + * TODO: Currently, this is only used for programming EMP_AS_SDP_TL i.e. to + * program Transmission Line for HDMI 2.1 Extended Metadata Packet (EMP) and + * DP Adaptive Sync (AS) Secondary Data Packet (SDP). However, all low level + * DIP buffer read/write and related helpers should be extracted here later. + */ + +struct intel_crtc_state; + +/* + * EMP AS SDP TL: Extended Metadata Packet (EMP) Adaptive Sync (AS) + * Secondary Data Packet (SDP) Transmission Line (TL). + * + * Starting with BMG (display ver 14.01) and LNL+ (display ver 20+), + * the AS SDP transmission line is programmable via the EMP AS SDP TL + * register. + */ +#define HAS_EMP_AS_SDP_TL(__display) (DISPLAY_VERx100(__display) == 1401 || \ + DISPLAY_VER(__display) >= 20) + +/* + * CMN SDP TL: Common Secondary Data Packet Transmission Line. + * + * Xe3p_lpd introduces new register CMN_SDP_TL to program a common SDP + * Transmission line that will be used by the Hardware to position the + * SDPs. Along with this, another new register CMN_SDP_TL_STGR_CTL is + * also added to stagger the different SDPs. + */ +#define HAS_COMMON_SDP_TL(__display) (DISPLAY_VER(__display) >= 35) + +u16 intel_dip_read_emp_as_sdp_tl(const struct intel_crtc_state *crtc_state); +void intel_dip_write_emp_as_sdp_tl(const struct intel_crtc_state *crtc_state); + +void intel_dip_sdp_tl_compute_config_late(struct intel_crtc_state *crtc_state); +void intel_dip_sdp_transmission_line_get_config(struct intel_crtc_state *crtc_state); +void intel_dip_cmn_sdp_transmission_line_enable(const struct intel_crtc_state *crtc_state); +void intel_dip_cmn_sdp_transmission_line_disable(const struct intel_crtc_state *old_crtc_state); + +#endif /* __INTEL_DIP_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dip_regs.h b/drivers/gpu/drm/i915/display/intel_dip_regs.h new file mode 100644 index 000000000000..d7e40a613913 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dip_regs.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef __INTEL_DIP_REGS_H__ +#define __INTEL_DIP_REGS_H__ + +#include "intel_display_reg_defs.h" + +/* EMP (Extended Metadata Packet) AS (Adaptive Sync) SDP Transmission Line */ +#define _EMP_AS_SDP_TL_A 0x60204 +#define EMP_AS_SDP_TL(display, trans) _MMIO_TRANS2((display), (trans), _EMP_AS_SDP_TL_A) +#define EMP_AS_SDP_DB_TL_MASK REG_GENMASK(12, 0) +#define EMP_AS_SDP_DB_TL(db_transmit_line) REG_FIELD_PREP(EMP_AS_SDP_DB_TL_MASK, \ + (db_transmit_line)) + +/* COMMON SDP TRANSMISSION LINE */ +#define _CMN_SDP_TL_A 0x6020c +#define CMN_SDP_TL(display, trans) _MMIO_TRANS2(display, (trans), _CMN_SDP_TL_A) +#define TRANSMISSION_LINE_ENABLE REG_BIT(31) +#define BASE_TRANSMISSION_LINE_MASK REG_GENMASK(12, 0) +#define BASE_TRANSMISSION_LINE(x) REG_FIELD_PREP(BASE_TRANSMISSION_LINE_MASK, x) + +#define _CMN_SDP_TL_STGR_CTL_A 0x60214 +#define CMN_SDP_TL_STGR_CTL(display, trans) _MMIO_TRANS2(display, (trans), \ + _CMN_SDP_TL_STGR_CTL_A) +#define VSC_EXT_STAGGER_MASK REG_GENMASK(11, 8) +#define VSC_EXT_STAGGER(x) REG_FIELD_PREP(VSC_EXT_STAGGER_MASK, x) +#define VSC_EXT_STAGGER_DEFAULT 0x2 +#define PPS_STAGGER_MASK REG_GENMASK(7, 4) +#define PPS_STAGGER(x) REG_FIELD_PREP(PPS_STAGGER_MASK, x) +#define PPS_STAGGER_DEFAULT 0x1 +#define GMP_STAGGER_MASK REG_GENMASK(3, 0) +#define GMP_STAGGER(x) REG_FIELD_PREP(GMP_STAGGER_MASK, x) +#define GMP_STAGGER_DEFAULT 0x0 + +#endif /* __INTEL_DIP_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index fc30a455bed3..d5d4453f283b 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -50,7 +50,6 @@ #include "g4x_dp.h" #include "g4x_hdmi.h" #include "hsw_ips.h" -#include "i915_config.h" #include "i9xx_plane.h" #include "i9xx_plane_regs.h" #include "i9xx_wm.h" @@ -70,6 +69,7 @@ #include "intel_cx0_phy.h" #include "intel_ddi.h" #include "intel_de.h" +#include "intel_dip.h" #include "intel_display_driver.h" #include "intel_display_power.h" #include "intel_display_regs.h" @@ -1000,6 +1000,15 @@ static bool cmrr_params_changed(const struct intel_crtc_state *old_crtc_state, old_crtc_state->vrr.cmrr.cmrr_n != new_crtc_state->vrr.cmrr.cmrr_n; } +static bool cmn_sdp_changed(const struct intel_crtc_state *old_crtc_state, + const struct intel_crtc_state *new_crtc_state) +{ + return old_crtc_state->dip.cmn_sdp_tl != new_crtc_state->dip.cmn_sdp_tl || + old_crtc_state->dip.gmp_sdp_tl != new_crtc_state->dip.gmp_sdp_tl || + old_crtc_state->dip.pps_sdp_tl != new_crtc_state->dip.pps_sdp_tl || + old_crtc_state->dip.vsc_ext_sdp_tl != new_crtc_state->dip.vsc_ext_sdp_tl; +} + static bool intel_crtc_vrr_enabling(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -1232,6 +1241,14 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, intel_vrr_disable(old_crtc_state); intel_vrr_dcb_reset(old_crtc_state, crtc); intel_crtc_update_active_timings(old_crtc_state, false); + + /* + * VRR is being disabled seamlessly (no modeset, Panel Replay + * stays enabled), so re-apply the AS SDP skip-frame programming + * for the new (VRR off) state. + */ + if (!intel_crtc_needs_modeset(new_crtc_state)) + intel_alpm_pr_as_sdp_update(new_crtc_state); } if (audio_disabling(old_crtc_state, new_crtc_state)) @@ -5594,6 +5611,12 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_I(vrr.dc_balance.max_increase); PIPE_CONF_CHECK_I(vrr.dc_balance.max_decrease); PIPE_CONF_CHECK_I(vrr.dc_balance.vblank_target); + PIPE_CONF_CHECK_I(dip.emp_as_sdp_tl); + PIPE_CONF_CHECK_I(dip.gmp_sdp_tl); + PIPE_CONF_CHECK_I(dip.pps_sdp_tl); + PIPE_CONF_CHECK_I(dip.vsc_sdp_tl); + PIPE_CONF_CHECK_I(dip.vsc_ext_sdp_tl); + PIPE_CONF_CHECK_I(dip.cmn_sdp_tl); } if (!fastset || intel_vrr_always_use_vrr_tg(display)) { @@ -6911,6 +6934,9 @@ static void intel_pre_update_crtc(struct intel_atomic_state *state, if (vrr_params_changed(old_crtc_state, new_crtc_state) || cmrr_params_changed(old_crtc_state, new_crtc_state)) intel_vrr_set_transcoder_timings(new_crtc_state); + + if (cmn_sdp_changed(old_crtc_state, new_crtc_state)) + intel_dip_cmn_sdp_transmission_line_enable(new_crtc_state); } intel_fbc_update(state, crtc); @@ -6971,6 +6997,16 @@ static void intel_update_crtc(struct intel_atomic_state *state, intel_crtc_update_active_timings(new_crtc_state, new_crtc_state->vrr.enable); + /* + * VRR is being enabled seamlessly (no modeset, Panel Replay stays + * enabled), so re-apply the AS SDP skip-frame programming for the new + * (VRR on) state. Done here, outside the vblank-evasion critical section + * (which runs with interrupts disabled), because it takes alpm.lock. + */ + if (intel_crtc_vrr_enabling(state, crtc) && + !intel_crtc_needs_modeset(new_crtc_state)) + intel_alpm_pr_as_sdp_update(new_crtc_state); + if (new_crtc_state->vrr.dc_balance.enable) intel_vrr_dcb_increment_flip_count(new_crtc_state, crtc); @@ -7271,23 +7307,27 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) drm_WARN_ON(display->drm, update_pipes); } -static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_state) +static void intel_atomic_commit_fence_wait(struct intel_atomic_state *state) { + struct intel_display *display = to_intel_display(state); struct drm_plane *plane; struct drm_plane_state *new_plane_state; long ret; int i; - for_each_new_plane_in_state(&intel_state->base, plane, new_plane_state, i) { - if (new_plane_state->fence) { - ret = dma_fence_wait_timeout(new_plane_state->fence, false, - i915_fence_timeout()); - if (ret <= 0) - break; + for_each_new_plane_in_state(&state->base, plane, new_plane_state, i) { + if (!new_plane_state->fence) + continue; - dma_fence_put(new_plane_state->fence); - new_plane_state->fence = NULL; + ret = dma_fence_wait(new_plane_state->fence, false); + if (ret < 0) { + drm_dbg_kms(display->drm, "[PLANE:%d:%s] fence wait failed (%pe)\n", + plane->base.id, plane->name, ERR_PTR(ret)); + break; } + + dma_fence_put(new_plane_state->fence); + new_plane_state->fence = NULL; } } diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 7e988b7b1fe7..c80b4a2f74f9 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -244,6 +244,13 @@ struct intel_vbt_data { struct list_head display_devices; struct list_head bdb_blocks; + struct { + const u32 *tables; + int num_tables; + int num_columns; + int num_rows; + } vspeo; + struct sdvo_device_mapping { u8 initialized; u8 dvo_port; diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index a59b75830bd1..8ce30112de97 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -2217,8 +2217,10 @@ static void gen11_display_irq_reset(struct intel_display *display) enum pipe pipe; u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C) | BIT(TRANSCODER_D); + bool reset_hpd = !intel_display_rpm_pme_enabled(display); - intel_de_write(display, GEN11_DISPLAY_INT_CTL, 0); + if (reset_hpd) + intel_de_write(display, GEN11_DISPLAY_INT_CTL, 0); if (DISPLAY_VER(display) >= 12) { enum transcoder trans; @@ -2250,13 +2252,15 @@ static void gen11_display_irq_reset(struct intel_display *display) irq_reset(display, GEN8_DE_PORT_IRQ_REGS); irq_reset(display, GEN8_DE_MISC_IRQ_REGS); - if (DISPLAY_VER(display) >= 14) - irq_reset(display, PICAINTERRUPT_IRQ_REGS); - else - irq_reset(display, GEN11_DE_HPD_IRQ_REGS); + if (reset_hpd) { + if (DISPLAY_VER(display) >= 14) + irq_reset(display, PICAINTERRUPT_IRQ_REGS); + else + irq_reset(display, GEN11_DE_HPD_IRQ_REGS); - if (INTEL_PCH_TYPE(display) >= PCH_ICP) - irq_reset(display, SDE_IRQ_REGS); + if (INTEL_PCH_TYPE(display) >= PCH_ICP) + irq_reset(display, SDE_IRQ_REGS); + } } void gen8_irq_power_well_post_enable(struct intel_display *display, diff --git a/drivers/gpu/drm/i915/display/intel_display_limits.h b/drivers/gpu/drm/i915/display/intel_display_limits.h index ea89473c177f..7ba7360c574e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_limits.h +++ b/drivers/gpu/drm/i915/display/intel_display_limits.h @@ -169,6 +169,7 @@ enum aux_ch { enum intel_color_block { INTEL_PLANE_CB_PRE_CSC_LUT, INTEL_PLANE_CB_CSC, + INTEL_PLANE_CB_CSC_FF, INTEL_PLANE_CB_POST_CSC_LUT, INTEL_PLANE_CB_3DLUT, diff --git a/drivers/gpu/drm/i915/display/intel_display_params.h b/drivers/gpu/drm/i915/display/intel_display_params.h index 16759e94c025..5c5a1a1358c3 100644 --- a/drivers/gpu/drm/i915/display/intel_display_params.h +++ b/drivers/gpu/drm/i915/display/intel_display_params.h @@ -51,6 +51,11 @@ struct drm_printer; param(bool, psr_safest_params, false, 0400) \ param(bool, enable_psr2_sel_fetch, true, 0400) \ param(int, enable_dmc_wl, -1, 0400) \ + /* + * Debugfs-only knob (per-device): no matching module_param is registered + * in intel_display_params.c on purpose. Runtime-toggle via debugfs. + */ \ + param(bool, enable_periodic_assdp, false, 0600) \ #define MEMBER(T, member, ...) T member; struct intel_display_params { diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 0ebec6e0c240..1b60ce2dd00c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -10,6 +10,7 @@ #include #include +#include "intel_alpm.h" #include "intel_backlight_regs.h" #include "intel_cdclk.h" #include "intel_clock_gating.h" @@ -488,6 +489,14 @@ void intel_display_power_dc3co_compute(struct intel_atomic_state *state) if (crtc_state->has_sel_update) trigger |= DC3CO_TRIGGER_PSR2; + /* + * Periodic AS SDP (skip frames) needs the AS SDP to keep flowing during + * PR active, which is incompatible with DC3co. Keep DC3co disabled while + * skip frames is enabled. + */ + if (intel_alpm_pr_as_sdp_skip_frames_enabled(intel_dp, crtc_state)) + trigger = DC3CO_TRIGGER_NONE; + done: intel_display_power_dc3co_update(display, trigger); } diff --git a/drivers/gpu/drm/i915/display/intel_display_power_map.c b/drivers/gpu/drm/i915/display/intel_display_power_map.c index 3400080d78d2..e18eb49983fe 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_map.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_map.c @@ -1759,6 +1759,44 @@ static const struct i915_power_well_desc_list wcl_power_wells[] = { I915_PW_DESCRIPTORS(wcl_power_wells_aux), }; +I915_DECL_PW_DOMAINS(xe3plpd_pwdoms_dc_off, + POWER_DOMAIN_DC_OFF, + XE3LPD_PW_2_POWER_DOMAINS, + XE3LPD_PW_C_POWER_DOMAINS, + XE3LPD_PW_D_POWER_DOMAINS, + POWER_DOMAIN_AUDIO_MMIO, + POWER_DOMAIN_AUDIO_PLAYBACK, + POWER_DOMAIN_AUX_A, + POWER_DOMAIN_AUX_B, + 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 xe3plpd_power_wells_dcoff[] = { + { + .instances = &I915_PW_INSTANCES( + I915_PW("DC_off", &xe3plpd_pwdoms_dc_off, + .id = SKL_DISP_DC_OFF), + ), + .ops = &gen9_dc_off_power_well_ops, + }, +}; + +static const struct i915_power_well_desc_list xe3plpd_power_wells[] = { + I915_PW_DESCRIPTORS(i9xx_power_wells_always_on), + I915_PW_DESCRIPTORS(icl_power_wells_pw_1), + I915_PW_DESCRIPTORS(xe3plpd_power_wells_dcoff), + I915_PW_DESCRIPTORS(xe3lpd_power_wells_main), + I915_PW_DESCRIPTORS(xe2lpd_power_wells_pica), + I915_PW_DESCRIPTORS(xelpdp_power_wells_aux), +}; + static void init_power_well_domains(const struct i915_power_well_instance *inst, struct i915_power_well *power_well) { @@ -1865,7 +1903,9 @@ int intel_display_power_map_init(struct i915_power_domains *power_domains) return 0; } - if (DISPLAY_VERx100(display) == 3002) + if (DISPLAY_VER(display) >= 35) + return set_power_wells(power_domains, xe3plpd_power_wells); + else if (DISPLAY_VERx100(display) == 3002) return set_power_wells(power_domains, wcl_power_wells); else if (DISPLAY_VER(display) >= 30) return set_power_wells(power_domains, xe3lpd_power_wells); diff --git a/drivers/gpu/drm/i915/display/intel_display_rpm.c b/drivers/gpu/drm/i915/display/intel_display_rpm.c index 0a331f89b4db..9927119a0fd1 100644 --- a/drivers/gpu/drm/i915/display/intel_display_rpm.c +++ b/drivers/gpu/drm/i915/display/intel_display_rpm.c @@ -46,6 +46,13 @@ bool intel_display_rpm_suspended(struct intel_display *display) return display->parent->rpm->suspended(display->drm); } +bool intel_display_rpm_pme_enabled(struct intel_display *display) +{ + const struct intel_display_rpm_interface *rpm = display->parent->rpm; + + return rpm->pme_enabled && rpm->pme_enabled(display->drm); +} + void assert_display_rpm_held(struct intel_display *display) { display->parent->rpm->assert_held(display->drm); diff --git a/drivers/gpu/drm/i915/display/intel_display_rpm.h b/drivers/gpu/drm/i915/display/intel_display_rpm.h index 6ef48515f84b..5d9a1cdddfa7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_rpm.h +++ b/drivers/gpu/drm/i915/display/intel_display_rpm.h @@ -21,6 +21,7 @@ void intel_display_rpm_put(struct intel_display *display, struct ref_tracker *wa /* Only for special cases. */ bool intel_display_rpm_suspended(struct intel_display *display); +bool intel_display_rpm_pme_enabled(struct intel_display *display); void assert_display_rpm_held(struct intel_display *display); void intel_display_rpm_assert_block(struct intel_display *display); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 5cfc123c86d1..0e3083e852d5 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -41,10 +41,10 @@ #include #include #include +#include #include #include -#include "i915_gtt_view_types.h" #include "intel_bios.h" #include "intel_display.h" #include "intel_display_conversion.h" @@ -111,7 +111,7 @@ struct intel_fb_view { * In the normal view the FB object's backing store sg list is used * directly and hence the remap information here is not used. */ - struct i915_gtt_view gtt; + struct intel_gtt_view gtt; /* * The GTT view (gtt.type) specific information for each FB color @@ -289,6 +289,9 @@ struct intel_encoder { */ enum icl_port_dpll_id (*port_pll_type)(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); + const struct intel_ddi_buf_trans *(*get_buf_trans_override)(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + int *n_entries); const struct intel_ddi_buf_trans *(*get_buf_trans)(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, int *n_entries); @@ -683,6 +686,7 @@ struct intel_plane_state { enum drm_color_range color_range; enum drm_scaling_filter scaling_filter; struct drm_property_blob *ctm, *degamma_lut, *gamma_lut, *lut_3d; + bool csc_ff_enable; } hw; struct i915_vma *ggtt_vma; @@ -1003,6 +1007,20 @@ struct intel_casf { bool enable; }; +struct intel_dip { + /* + * DIP Transmission line, relative to the Vtotal. + * The programmed transmit line is (Vtotal - value) + */ + u16 emp_as_sdp_tl; + u16 gmp_sdp_tl; + u16 pps_sdp_tl; + u16 vsc_sdp_tl; + u16 vsc_ext_sdp_tl; + /* Common SDP Base transmission line (Xe3p_lpd+) */ + u16 cmn_sdp_tl; +}; + struct intel_crtc_state { /* * uapi (drm) state. This is the software state shown to userspace. @@ -1311,6 +1329,8 @@ struct intel_crtc_state { struct drm_dp_as_sdp as_sdp; } infoframes; + struct intel_dip dip; + u8 eld[MAX_ELD_BYTES]; /* HDMI scrambling status */ diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 0cd5e6b5034c..d8c0d9381471 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -61,6 +61,8 @@ #include "intel_cx0_phy.h" #include "intel_ddi.h" #include "intel_de.h" +#include "intel_dip.h" +#include "intel_dip_regs.h" #include "intel_display_driver.h" #include "intel_display_jiffies.h" #include "intel_display_utils.h" @@ -3734,19 +3736,19 @@ static bool downstream_hpd_needs_d0(struct intel_dp *intel_dp) static int write_dsc_decompression_flag(struct drm_dp_aux *aux, u8 flag, bool set) { - int err; + int ret; u8 val; - err = drm_dp_dpcd_readb(aux, DP_DSC_ENABLE, &val); - if (err < 0) - return err; + ret = drm_dp_dpcd_read_byte(aux, DP_DSC_ENABLE, &val); + if (ret < 0) + return ret; if (set) val |= flag; else val &= ~flag; - return drm_dp_dpcd_writeb(aux, DP_DSC_ENABLE, val); + return drm_dp_dpcd_write_byte(aux, DP_DSC_ENABLE, val); } static void @@ -3910,6 +3912,7 @@ intel_dp_init_source_oui(struct intel_dp *intel_dp) struct intel_display *display = to_intel_display(intel_dp); u8 oui[] = { 0x00, 0xaa, 0x01 }; u8 buf[3] = {}; + int ret; if (READ_ONCE(intel_dp->oui_valid)) return; @@ -3920,8 +3923,9 @@ intel_dp_init_source_oui(struct intel_dp *intel_dp) * During driver init, we want to be careful and avoid changing the source OUI if it's * already set to what we want, so as to avoid clearing any state by accident */ - if (drm_dp_dpcd_read(&intel_dp->aux, DP_SOURCE_OUI, buf, sizeof(buf)) < 0) - drm_dbg_kms(display->drm, "Failed to read source OUI\n"); + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_SOURCE_OUI, buf, sizeof(buf)); + if (ret < 0) + drm_dbg_kms(display->drm, "Failed to read source OUI (%pe)\n", ERR_PTR(ret)); if (memcmp(oui, buf, sizeof(oui)) == 0) { /* Assume the OUI was written now. */ @@ -3929,8 +3933,9 @@ intel_dp_init_source_oui(struct intel_dp *intel_dp) return; } - if (drm_dp_dpcd_write(&intel_dp->aux, DP_SOURCE_OUI, oui, sizeof(oui)) < 0) { - drm_dbg_kms(display->drm, "Failed to write source OUI\n"); + ret = drm_dp_dpcd_write_data(&intel_dp->aux, DP_SOURCE_OUI, oui, sizeof(oui)); + if (ret < 0) { + drm_dbg_kms(display->drm, "Failed to write source OUI (%pe)\n", ERR_PTR(ret)); WRITE_ONCE(intel_dp->oui_valid, false); } @@ -3971,7 +3976,7 @@ void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode) if (downstream_hpd_needs_d0(intel_dp)) return; - ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, mode); + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_SET_POWER, mode); } else { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); @@ -3985,21 +3990,21 @@ void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode) * time to wake up. */ for (i = 0; i < 3; i++) { - ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, mode); - if (ret == 1) + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_SET_POWER, mode); + if (!ret) break; msleep(1); } - if (ret == 1 && intel_lspcon_active(dig_port)) + if (!ret && intel_lspcon_active(dig_port)) intel_lspcon_wait_pcon_mode(dig_port); } - if (ret != 1) + if (ret < 0) drm_dbg_kms(display->drm, - "[ENCODER:%d:%s] Set power to %s failed\n", + "[ENCODER:%d:%s] Set power to %s failed (%pe)\n", encoder->base.base.id, encoder->base.name, - mode == DP_SET_POWER_D0 ? "D0" : "D3"); + mode == DP_SET_POWER_D0 ? "D0" : "D3", ERR_PTR(ret)); } static bool @@ -4086,6 +4091,7 @@ bool intel_dp_initial_fastset_check(struct intel_encoder *encoder, static void intel_dp_get_pcon_dsc_cap(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); + int ret; /* Clear the cached register set to avoid using stale values */ @@ -4094,11 +4100,12 @@ static void intel_dp_get_pcon_dsc_cap(struct intel_dp *intel_dp) if (!drm_dp_is_branch(intel_dp->dpcd)) return; - if (drm_dp_dpcd_read(&intel_dp->aux, DP_PCON_DSC_ENCODER, - intel_dp->pcon_dsc_dpcd, - sizeof(intel_dp->pcon_dsc_dpcd)) < 0) - drm_err(display->drm, "Failed to read DPCD register 0x%x\n", - DP_PCON_DSC_ENCODER); + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_PCON_DSC_ENCODER, + intel_dp->pcon_dsc_dpcd, + sizeof(intel_dp->pcon_dsc_dpcd)); + if (ret < 0) + drm_err(display->drm, "Failed to read DPCD register 0x%x (%pe)\n", + DP_PCON_DSC_ENCODER, ERR_PTR(ret)); drm_dbg_kms(display->drm, "PCON ENCODER DSC DPCD: %*ph\n", (int)sizeof(intel_dp->pcon_dsc_dpcd), intel_dp->pcon_dsc_dpcd); @@ -4255,13 +4262,13 @@ int intel_dp_pcon_set_tmds_mode(struct intel_dp *intel_dp) /* Set PCON source control mode */ buf |= DP_PCON_ENABLE_SOURCE_CTL_MODE; - ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_PCON_HDMI_LINK_CONFIG_1, buf); + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_PCON_HDMI_LINK_CONFIG_1, buf); if (ret < 0) return ret; /* Set HDMI LINK ENABLE */ buf |= DP_PCON_ENABLE_HDMI_LINK; - ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_PCON_HDMI_LINK_CONFIG_1, buf); + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_PCON_HDMI_LINK_CONFIG_1, buf); if (ret < 0) return ret; @@ -4407,6 +4414,7 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp, bool ycbcr444_to_420 = false; bool rgb_to_ycbcr = false; u8 tmp; + int ret; if (intel_dp->dpcd[DP_DPCD_REV] < 0x13) return; @@ -4416,11 +4424,13 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp, tmp = intel_dp_has_hdmi_sink(intel_dp) ? DP_HDMI_DVI_OUTPUT_CONFIG : 0; - if (drm_dp_dpcd_writeb(&intel_dp->aux, - DP_PROTOCOL_CONVERTER_CONTROL_0, tmp) != 1) + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, + DP_PROTOCOL_CONVERTER_CONTROL_0, tmp); + if (ret < 0) drm_dbg_kms(display->drm, - "Failed to %s protocol converter HDMI mode\n", - str_enable_disable(intel_dp_has_hdmi_sink(intel_dp))); + "Failed to %s protocol converter HDMI mode (%pe)\n", + str_enable_disable(intel_dp_has_hdmi_sink(intel_dp)), + ERR_PTR(ret)); if (crtc_state->sink_format == INTEL_OUTPUT_FORMAT_YCBCR420) { switch (crtc_state->output_format) { @@ -4452,26 +4462,29 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp, tmp = ycbcr444_to_420 ? DP_CONVERSION_TO_YCBCR420_ENABLE : 0; - if (drm_dp_dpcd_writeb(&intel_dp->aux, - DP_PROTOCOL_CONVERTER_CONTROL_1, tmp) != 1) + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, + DP_PROTOCOL_CONVERTER_CONTROL_1, tmp); + if (ret < 0) drm_dbg_kms(display->drm, - "Failed to %s protocol converter YCbCr 4:2:0 conversion mode\n", - str_enable_disable(intel_dp->dfp.ycbcr_444_to_420)); + "Failed to %s protocol converter YCbCr 4:2:0 conversion mode (%pe)\n", + str_enable_disable(intel_dp->dfp.ycbcr_444_to_420), + ERR_PTR(ret)); tmp = rgb_to_ycbcr ? DP_CONVERSION_BT709_RGB_YCBCR_ENABLE : 0; - if (drm_dp_pcon_convert_rgb_to_ycbcr(&intel_dp->aux, tmp) < 0) + ret = drm_dp_pcon_convert_rgb_to_ycbcr(&intel_dp->aux, tmp); + if (ret < 0) drm_dbg_kms(display->drm, - "Failed to %s protocol converter RGB->YCbCr conversion mode\n", - str_enable_disable(tmp)); + "Failed to %s protocol converter RGB->YCbCr conversion mode (%pe)\n", + str_enable_disable(tmp), ERR_PTR(ret)); } static u8 intel_dp_read_dprx_feature_enum(struct intel_dp *intel_dp) { u8 dprx = 0; - drm_dp_dpcd_read_data(&intel_dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST, - &dprx, sizeof(dprx)); + drm_dp_dpcd_read_byte(&intel_dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST, &dprx); + return dprx; } @@ -4490,9 +4503,8 @@ static int intel_dp_read_dsc_dpcd(struct drm_dp_aux *aux, { int ret; - ret = drm_dp_dpcd_read_data(aux, DP_DSC_SUPPORT, dsc_dpcd, - DP_DSC_RECEIVER_CAP_SIZE); - if (ret) { + ret = drm_dp_dpcd_read_data(aux, DP_DSC_SUPPORT, dsc_dpcd, DP_DSC_RECEIVER_CAP_SIZE); + if (ret < 0) { drm_dbg_kms(aux->drm_dev, "Could not read DSC DPCD register 0x%x Error: %pe\n", DP_DSC_SUPPORT, ERR_PTR(ret)); @@ -4508,7 +4520,7 @@ static int intel_dp_read_dsc_dpcd(struct drm_dp_aux *aux, static void init_dsc_overall_throughput_limits(struct intel_connector *connector, bool is_branch) { u8 branch_caps[DP_DSC_BRANCH_CAP_SIZE]; - int line_width; + int line_width, ret; connector->dp.dsc_branch_caps.overall_throughput.rgb_yuv444 = INT_MAX; connector->dp.dsc_branch_caps.overall_throughput.yuv422_420 = INT_MAX; @@ -4517,9 +4529,10 @@ static void init_dsc_overall_throughput_limits(struct intel_connector *connector if (!is_branch) return; - if (drm_dp_dpcd_read_data(connector->dp.dsc_decompression_aux, - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0, branch_caps, - sizeof(branch_caps)) != 0) + ret = drm_dp_dpcd_read_data(connector->dp.dsc_decompression_aux, + DP_DSC_BRANCH_OVERALL_THROUGHPUT_0, branch_caps, + sizeof(branch_caps)); + if (ret < 0) return; connector->dp.dsc_branch_caps.overall_throughput.rgb_yuv444 = @@ -4537,6 +4550,7 @@ void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_connector *connector) { struct intel_display *display = to_intel_display(connector); + int ret; /* * Clear the cached register set to avoid using stale values @@ -4553,13 +4567,16 @@ void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, if (dpcd_rev < DP_DPCD_REV_14) return; - if (intel_dp_read_dsc_dpcd(connector->dp.dsc_decompression_aux, - connector->dp.dsc_dpcd) < 0) + ret = intel_dp_read_dsc_dpcd(connector->dp.dsc_decompression_aux, + connector->dp.dsc_dpcd); + if (ret < 0) return; - if (drm_dp_dpcd_readb(connector->dp.dsc_decompression_aux, DP_FEC_CAPABILITY, - &connector->dp.fec_capability) < 0) { - drm_dbg_kms(display->drm, "Could not read FEC DPCD register\n"); + ret = drm_dp_dpcd_read_byte(connector->dp.dsc_decompression_aux, DP_FEC_CAPABILITY, + &connector->dp.fec_capability); + if (ret < 0) { + drm_dbg_kms(display->drm, "Could not read FEC DPCD register (%pe)\n", + ERR_PTR(ret)); return; } @@ -4668,13 +4685,15 @@ static void intel_edp_mso_init(struct intel_dp *intel_dp) struct intel_display *display = to_intel_display(intel_dp); struct intel_connector *connector = intel_dp->attached_connector; struct drm_display_info *info = &connector->base.display_info; + int ret; u8 mso; if (intel_dp->edp_dpcd[0] < DP_EDP_14) return; - if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_MSO_LINK_CAPABILITIES, &mso) != 1) { - drm_err(display->drm, "Failed to read MSO cap\n"); + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_EDP_MSO_LINK_CAPABILITIES, &mso); + if (ret < 0) { + drm_err(display->drm, "Failed to read MSO cap (%pe)\n", ERR_PTR(ret)); return; } @@ -4779,6 +4798,38 @@ intel_edp_set_sink_rates(struct intel_dp *intel_dp) intel_edp_set_data_override_rates(intel_dp); } +static void intel_edp_wake_sink(struct intel_dp *intel_dp) +{ + u8 value = 0; + int ret; + + /* + * Read the current sink power state. drm_dp_dpcd_read_byte() already + * retries the AUX transaction internally, so a single read suffices. + * First commercial eDP panels are Ver1.0 or 1.1, on which DPCD + * DP_SET_POWER is supported. + */ + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_SET_POWER, &value); + + /* + * If the AUX read failed the sink may be asleep and not responding, + * or it read back D3; in either case wake it up to D0. + * In case of AUX read failure which is usually a POR case, the + * remaining bits of register 0x600 is set to '0' on POR. So a bare + * write should be fine. + */ + if (ret < 0 || value == DP_SET_POWER_D3) { + value &= ~DP_SET_POWER_MASK; + value |= DP_SET_POWER_D0; + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_SET_POWER, + value); + /* After setting to D0 need a min of 1ms to wake (Spec DP2.1 sec 2.3.1.2) */ + fsleep(1000); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_SET_POWER, + value); + } +} + static bool intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector) { @@ -4789,6 +4840,12 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector /* this function is meant to be called only once */ drm_WARN_ON(display->drm, intel_dp->dpcd[DP_DPCD_REV] != 0); + /* + * Spec DP2.1 Section 3.5.2.16 page 966. + * Also if sink is asleep, this will wake the sink. + */ + intel_edp_wake_sink(intel_dp); + if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd) != 0) return false; @@ -4813,9 +4870,9 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector * method). The display control registers should read zero if they're * not supported anyway. */ - if (drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV, - intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd)) == - sizeof(intel_dp->edp_dpcd)) { + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_EDP_DPCD_REV, + intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd)); + if (!ret) { drm_dbg_kms(display->drm, "eDP DPCD: %*ph\n", (int)sizeof(intel_dp->edp_dpcd), intel_dp->edp_dpcd); @@ -5044,6 +5101,7 @@ static bool intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *esi) { struct intel_display *display = to_intel_display(intel_dp); + int ret; /* * Display WA for HSD #13013007775: mtl/arl/lnl @@ -5052,24 +5110,30 @@ intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *esi) * inadvertently. */ if (IS_DISPLAY_VER(display, 14, 20) && !display->platform.battlemage) { - if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT_ESI, esi, 3) != 3) + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_SINK_COUNT_ESI, esi, 3); + if (ret < 0) return false; /* DP_SINK_COUNT_ESI + 3 == DP_LINK_SERVICE_IRQ_VECTOR_ESI0 */ - return drm_dp_dpcd_readb(&intel_dp->aux, DP_LINK_SERVICE_IRQ_VECTOR_ESI0, - &esi[3]) == 1; + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_LINK_SERVICE_IRQ_VECTOR_ESI0, + &esi[3]); + return ret == 0; } - return drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT_ESI, esi, 4) == 4; + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_SINK_COUNT_ESI, esi, 4); + + return ret == 0; } static bool intel_dp_ack_sink_irq_esi(struct intel_dp *intel_dp, u8 esi[4]) { int retry; + int ret; for (retry = 0; retry < 3; retry++) { - if (drm_dp_dpcd_write(&intel_dp->aux, DP_SINK_COUNT_ESI + 1, - &esi[1], 3) == 3) + ret = drm_dp_dpcd_write_data(&intel_dp->aux, DP_SINK_COUNT_ESI + 1, + &esi[1], 3); + if (!ret) return true; } @@ -5079,20 +5143,24 @@ static bool intel_dp_ack_sink_irq_esi(struct intel_dp *intel_dp, u8 esi[4]) /* Return %true if reading the ESI vector succeeded, %false otherwise. */ static bool intel_dp_get_sink_irq_esi_sst(struct intel_dp *intel_dp, u8 esi[4]) { + int ret; + memset(esi, 0, 4); /* * TODO: For DP_DPCD_REV >= 0x12 read * DP_SINK_COUNT_ESI and DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0. */ - if (drm_dp_dpcd_read_data(&intel_dp->aux, DP_SINK_COUNT, esi, 2) != 0) + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_SINK_COUNT, esi, 2); + if (ret < 0) return false; if (intel_dp->dpcd[DP_DPCD_REV] < DP_DPCD_REV_12) return true; /* TODO: Read DP_DEVICE_SERVICE_IRQ_VECTOR_ESI1 as well */ - if (drm_dp_dpcd_read_byte(&intel_dp->aux, DP_LINK_SERVICE_IRQ_VECTOR_ESI0, &esi[3]) != 0) + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_LINK_SERVICE_IRQ_VECTOR_ESI0, &esi[3]); + if (ret < 0) return false; return true; @@ -5101,18 +5169,22 @@ static bool intel_dp_get_sink_irq_esi_sst(struct intel_dp *intel_dp, u8 esi[4]) /* Return %true if acking the ESI vector IRQ events succeeded, %false otherwise. */ static bool intel_dp_ack_sink_irq_esi_sst(struct intel_dp *intel_dp, u8 esi[4]) { + int ret; + /* * TODO: For DP_DPCD_REV >= 0x12 write * DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0 */ - if (drm_dp_dpcd_write_byte(&intel_dp->aux, DP_DEVICE_SERVICE_IRQ_VECTOR, esi[1]) != 0) + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_DEVICE_SERVICE_IRQ_VECTOR, esi[1]); + if (ret < 0) return false; if (intel_dp->dpcd[DP_DPCD_REV] < DP_DPCD_REV_12) return true; /* TODO: Read DP_DEVICE_SERVICE_IRQ_VECTOR_ESI1 as well */ - if (drm_dp_dpcd_write_byte(&intel_dp->aux, DP_LINK_SERVICE_IRQ_VECTOR_ESI0, esi[3]) != 0) + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_LINK_SERVICE_IRQ_VECTOR_ESI0, esi[3]); + if (ret < 0) return false; return true; @@ -5435,11 +5507,15 @@ static int intel_dp_vsc_sdp_unpack(struct drm_dp_vsc_sdp *vsc, * VSC SDP supporting 3D stereo + Panel Replay. */ return 0; - } else if (sdp->sdp_header.HB2 == 0x5 && sdp->sdp_header.HB3 == 0x13) { + } else if ((sdp->sdp_header.HB2 == 0x5 || sdp->sdp_header.HB2 == 0x7) && + sdp->sdp_header.HB3 == 0x13) { /* * - HB2 = 0x5, HB3 = 0x13 * VSC SDP supporting 3D stereo + PSR2 + Pixel Encoding/Colorimetry * Format. + * - HB2 = 0x7, HB3 = 0x13 + * VSC SDP supporting 3D stereo + Panel Replay + Pixel Encoding/Colorimetry + * Format. */ vsc->pixelformat = (sdp->db[16] >> 4) & 0xf; vsc->colorimetry = sdp->db[16] & 0xf; @@ -5706,14 +5782,17 @@ intel_dp_handle_hdmi_link_status_change(struct intel_dp *intel_dp) { bool is_active; u8 buf = 0; + int ret; is_active = drm_dp_pcon_hdmi_link_active(&intel_dp->aux); if (intel_dp->frl.is_trained && !is_active) { - if (drm_dp_dpcd_readb(&intel_dp->aux, DP_PCON_HDMI_LINK_CONFIG_1, &buf) < 0) + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_PCON_HDMI_LINK_CONFIG_1, &buf); + if (ret < 0) return; buf &= ~DP_PCON_ENABLE_HDMI_LINK; - if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_PCON_HDMI_LINK_CONFIG_1, buf) < 0) + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_PCON_HDMI_LINK_CONFIG_1, buf); + if (ret < 0) return; drm_dp_pcon_hdmi_frl_link_error_count(&intel_dp->aux, &intel_dp->attached_connector->base); @@ -6218,6 +6297,7 @@ static bool intel_dp_sink_supports_as_sdp_v2(struct intel_dp *intel_dp) { u8 rx_features; + int ret; /* * The DP spec does not explicitly provide the AS SDP v2 capability. @@ -6240,9 +6320,10 @@ intel_dp_sink_supports_as_sdp_v2(struct intel_dp *intel_dp) * support from Display ID. */ - if (drm_dp_dpcd_read_byte(&intel_dp->aux, - DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1, - &rx_features) == 1) { + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, + DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1, + &rx_features); + if (!ret) { if (rx_features & DP_AS_SDP_FAVT_PAYLOAD_FIELDS_PARSING_SUPPORTED) return true; } @@ -7324,6 +7405,8 @@ int intel_dp_sdp_compute_config_late(struct intel_crtc_state *crtc_state) return -EINVAL; } + intel_dip_sdp_tl_compute_config_late(crtc_state); + return 0; } @@ -7345,9 +7428,58 @@ int intel_dp_compute_config_late(struct intel_encoder *encoder, return 0; } +static +int intel_dp_get_lines_for_cmn_sdp_tl(u32 type) +{ + u32 stagger_val; + + /* + * Since we are using default stagger values similar to the case + * where CMN SDP TL is not set, the different SDP transmission + * lines are: + * base : 2nd line of delayed vblank: + * GMP : 2 + GMP_STAGGER + * VSC_EXT: 2 + VSC_EXT_STAGGER + * VSC : 2 + * PPS : 2 + PPS_STAGGER + * + * SDP Setup = 1 + MAX(GMP, VSC_EXT, VSC, PPS setup lines) + * + * For EMP_AS_SDP_TL guardband should be more than vrr.vsync_start. + */ + + switch (type) { + case DP_SDP_VSC_EXT_VESA: + case DP_SDP_VSC_EXT_CEA: + stagger_val = VSC_EXT_STAGGER_DEFAULT; + break; + case HDMI_PACKET_TYPE_GAMUT_METADATA: + stagger_val = GMP_STAGGER_DEFAULT; + break; + case DP_SDP_PPS: + stagger_val = PPS_STAGGER_DEFAULT; + break; + case DP_SDP_VSC: + stagger_val = 0; + break; + default: + return 0; + } + + return 1 + 2 + stagger_val; +} + static int intel_dp_get_lines_for_sdp(const struct intel_crtc_state *crtc_state, u32 type) { + struct intel_display *display = to_intel_display(crtc_state); + + if (type == DP_SDP_ADAPTIVE_SYNC) + return crtc_state->vrr.vsync_start + 1; + + if (HAS_COMMON_SDP_TL(display)) + return intel_dp_get_lines_for_cmn_sdp_tl(type); + switch (type) { case DP_SDP_VSC_EXT_VESA: case DP_SDP_VSC_EXT_CEA: @@ -7356,8 +7488,8 @@ int intel_dp_get_lines_for_sdp(const struct intel_crtc_state *crtc_state, u32 ty return 8; case DP_SDP_PPS: return 7; - case DP_SDP_ADAPTIVE_SYNC: - return crtc_state->vrr.vsync_start + 1; + case DP_SDP_VSC: + return 3; default: break; } @@ -7387,6 +7519,11 @@ int intel_dp_sdp_min_guardband(const struct intel_crtc_state *crtc_state, sdp_guardband = max(sdp_guardband, intel_dp_get_lines_for_sdp(crtc_state, DP_SDP_ADAPTIVE_SYNC)); + if (crtc_state->infoframes.enable & + intel_hdmi_infoframe_enable(DP_SDP_VSC)) + sdp_guardband = max(sdp_guardband, + intel_dp_get_lines_for_sdp(crtc_state, DP_SDP_VSC)); + return sdp_guardband; } diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 266e042e0023..36aebc32971b 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -120,8 +120,8 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) intel_dp_wait_source_oui(intel_dp); - ret = drm_dp_dpcd_read(aux, INTEL_EDP_HDR_TCON_CAP0, tcon_cap, sizeof(tcon_cap)); - if (ret != sizeof(tcon_cap)) + ret = drm_dp_dpcd_read_data(aux, INTEL_EDP_HDR_TCON_CAP0, tcon_cap, sizeof(tcon_cap)); + if (ret < 0) return false; drm_dbg_kms(display->drm, @@ -178,11 +178,13 @@ intel_dp_aux_hdr_get_backlight(struct intel_connector *connector, enum pipe pipe struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); u8 tmp; u8 buf[2] = {}; + int ret; - if (drm_dp_dpcd_readb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &tmp) != 1) { + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &tmp); + if (ret < 0) { drm_err(display->drm, - "[CONNECTOR:%d:%s] Failed to read current backlight mode from DPCD\n", - connector->base.base.id, connector->base.name); + "[CONNECTOR:%d:%s] Failed to read current backlight mode from DPCD (%pe)\n", + connector->base.base.id, connector->base.name, ERR_PTR(ret)); return 0; } @@ -197,11 +199,12 @@ intel_dp_aux_hdr_get_backlight(struct intel_connector *connector, enum pipe pipe return panel->backlight.max; } - if (drm_dp_dpcd_read(&intel_dp->aux, INTEL_EDP_BRIGHTNESS_NITS_LSB, buf, - sizeof(buf)) != sizeof(buf)) { + ret = drm_dp_dpcd_read_data(&intel_dp->aux, INTEL_EDP_BRIGHTNESS_NITS_LSB, buf, + sizeof(buf)); + if (ret < 0) { drm_err(display->drm, - "[CONNECTOR:%d:%s] Failed to read brightness from DPCD\n", - connector->base.base.id, connector->base.name); + "[CONNECTOR:%d:%s] Failed to read brightness from DPCD (%pe)\n", + connector->base.base.id, connector->base.name, ERR_PTR(ret)); return 0; } @@ -215,14 +218,16 @@ intel_dp_aux_hdr_set_aux_backlight(const struct drm_connector_state *conn_state, struct drm_device *dev = connector->base.dev; struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); u8 buf[4] = {}; + int ret; buf[0] = level & 0xFF; buf[1] = (level & 0xFF00) >> 8; - if (drm_dp_dpcd_write(&intel_dp->aux, INTEL_EDP_BRIGHTNESS_NITS_LSB, buf, - sizeof(buf)) != sizeof(buf)) - drm_err(dev, "[CONNECTOR:%d:%s] Failed to write brightness level to DPCD\n", - connector->base.base.id, connector->base.name); + ret = drm_dp_dpcd_write_data(&intel_dp->aux, INTEL_EDP_BRIGHTNESS_NITS_LSB, buf, + sizeof(buf)); + if (ret < 0) + drm_err(dev, "[CONNECTOR:%d:%s] Failed to write brightness level to DPCD (%pe)\n", + connector->base.base.id, connector->base.name, ERR_PTR(ret)); } static void @@ -258,13 +263,12 @@ intel_dp_aux_write_content_luminance(struct intel_connector *connector, buf[2] = hdr_metadata->hdmi_metadata_type1.max_fall & 0xFF; buf[3] = (hdr_metadata->hdmi_metadata_type1.max_fall & 0xFF00) >> 8; - ret = drm_dp_dpcd_write(&intel_dp->aux, - INTEL_EDP_HDR_CONTENT_LUMINANCE, - buf, sizeof(buf)); + ret = drm_dp_dpcd_write_data(&intel_dp->aux, + INTEL_EDP_HDR_CONTENT_LUMINANCE, + buf, sizeof(buf)); if (ret < 0) drm_dbg_kms(display->drm, - "Content Luminance DPCD reg write failed, err:-%d\n", - ret); + "Content Luminance DPCD reg write failed (%pe)\n", ERR_PTR(ret)); } static void @@ -313,11 +317,11 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, intel_dp_wait_source_oui(intel_dp); - ret = drm_dp_dpcd_readb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &old_ctrl); - if (ret != 1) { + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &old_ctrl); + if (ret < 0) { drm_err(display->drm, - "[CONNECTOR:%d:%s] Failed to read current backlight control mode: %d\n", - connector->base.base.id, connector->base.name, ret); + "[CONNECTOR:%d:%s] Failed to read current backlight control mode (%pe)\n", + connector->base.base.id, connector->base.name, ERR_PTR(ret)); return; } @@ -337,11 +341,14 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, intel_dp_aux_fill_hdr_tcon_params(conn_state, &ctrl); - if (ctrl != old_ctrl && - drm_dp_dpcd_writeb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, ctrl) != 1) - drm_err(display->drm, - "[CONNECTOR:%d:%s] Failed to configure DPCD brightness controls\n", - connector->base.base.id, connector->base.name); + if (ctrl != old_ctrl) { + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, + INTEL_EDP_HDR_GETSET_CTRL_PARAMS, ctrl); + if (ret < 0) + drm_err(display->drm, + "[CONNECTOR:%d:%s] Failed to configure DPCD brightness controls (%pe)\n", + connector->base.base.id, connector->base.name, ERR_PTR(ret)); + } if (intel_dp_in_hdr_mode(conn_state)) { hdr_metadata = conn_state->hdr_output_metadata->data; @@ -392,13 +399,12 @@ intel_dp_aux_write_panel_luminance_override(struct intel_connector *connector) buf[2] = panel->backlight.max & 0xFF; buf[3] = (panel->backlight.max & 0xFF00) >> 8; - ret = drm_dp_dpcd_write(&intel_dp->aux, - INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE, - buf, sizeof(buf)); + ret = drm_dp_dpcd_write_data(&intel_dp->aux, + INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE, + buf, sizeof(buf)); if (ret < 0) drm_dbg_kms(display->drm, - "Panel Luminance DPCD reg write failed, err:-%d\n", - ret); + "Panel Luminance DPCD reg write failed (%pe)\n", ERR_PTR(ret)); } static int @@ -456,12 +462,12 @@ static u32 intel_dp_aux_vesa_get_backlight(struct intel_connector *connector, en int ret; if (panel->backlight.edp.vesa.luminance_control_support) { - ret = drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_PANEL_TARGET_LUMINANCE_VALUE, buf, - sizeof(buf)); + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_EDP_PANEL_TARGET_LUMINANCE_VALUE, buf, + sizeof(buf)); if (ret < 0) { drm_err(intel_dp->aux.drm_dev, - "[CONNECTOR:%d:%s] Failed to read Luminance from DPCD\n", - connector->base.base.id, connector->base.name); + "[CONNECTOR:%d:%s] Failed to read Luminance from DPCD (%pe)\n", + connector->base.base.id, connector->base.name, ERR_PTR(ret)); return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 14ed0ea22dd3..566a921d18a1 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -60,16 +60,15 @@ int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *dig_port, { struct intel_display *display = to_intel_display(dig_port); u8 aksv[DRM_HDCP_KSV_LEN] = {}; - ssize_t dpcd_ret; + int ret; /* Output An first, that's easy */ - dpcd_ret = drm_dp_dpcd_write(&dig_port->dp.aux, DP_AUX_HDCP_AN, + ret = drm_dp_dpcd_write_data(&dig_port->dp.aux, DP_AUX_HDCP_AN, an, DRM_HDCP_AN_LEN); - if (dpcd_ret != DRM_HDCP_AN_LEN) { + if (ret < 0) { drm_dbg_kms(display->drm, - "Failed to write An over DP/AUX (%zd)\n", - dpcd_ret); - return dpcd_ret >= 0 ? -EIO : dpcd_ret; + "Failed to write An over DP/AUX (%pe)\n", ERR_PTR(ret)); + return ret; } /* @@ -79,14 +78,14 @@ int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *dig_port, * the destination address which will tickle the hardware to output the * Aksv on our behalf after the header is sent. */ - dpcd_ret = drm_dp_dpcd_write(&dig_port->dp.aux, DP_AUX_HDCP_AKSV, + ret = drm_dp_dpcd_write_data(&dig_port->dp.aux, DP_AUX_HDCP_AKSV, aksv, DRM_HDCP_KSV_LEN); - if (dpcd_ret != DRM_HDCP_KSV_LEN) { + if (ret < 0) { drm_dbg_kms(display->drm, - "Failed to write Aksv over DP/AUX (%zd)\n", - dpcd_ret); - return dpcd_ret >= 0 ? -EIO : dpcd_ret; + "Failed to write Aksv over DP/AUX (%pe)\n", ERR_PTR(ret)); + return ret; } + return 0; } @@ -94,15 +93,16 @@ static int intel_dp_hdcp_read_bksv(struct intel_digital_port *dig_port, u8 *bksv) { struct intel_display *display = to_intel_display(dig_port); - ssize_t ret; + int ret; - ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BKSV, bksv, - DRM_HDCP_KSV_LEN); - if (ret != DRM_HDCP_KSV_LEN) { + ret = drm_dp_dpcd_read_data(&dig_port->dp.aux, DP_AUX_HDCP_BKSV, bksv, + DRM_HDCP_KSV_LEN); + if (ret < 0) { drm_dbg_kms(display->drm, - "Read Bksv from DP/AUX failed (%zd)\n", ret); - return ret >= 0 ? -EIO : ret; + "Read Bksv from DP/AUX failed (%pe)\n", ERR_PTR(ret)); + return ret; } + return 0; } @@ -110,20 +110,21 @@ static int intel_dp_hdcp_read_bstatus(struct intel_digital_port *dig_port, u8 *bstatus) { struct intel_display *display = to_intel_display(dig_port); - ssize_t ret; + int ret; /* * For some reason the HDMI and DP HDCP specs call this register * definition by different names. In the HDMI spec, it's called BSTATUS, * but in DP it's called BINFO. */ - ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BINFO, - bstatus, DRM_HDCP_BSTATUS_LEN); - if (ret != DRM_HDCP_BSTATUS_LEN) { + ret = drm_dp_dpcd_read_data(&dig_port->dp.aux, DP_AUX_HDCP_BINFO, + bstatus, DRM_HDCP_BSTATUS_LEN); + if (ret < 0) { drm_dbg_kms(display->drm, - "Read bstatus from DP/AUX failed (%zd)\n", ret); - return ret >= 0 ? -EIO : ret; + "Read bstatus from DP/AUX failed (%pe)\n", ERR_PTR(ret)); + return ret; } + return 0; } @@ -132,14 +133,13 @@ int intel_dp_hdcp_read_bcaps(struct drm_dp_aux *aux, struct intel_display *display, u8 *bcaps) { - ssize_t ret; + int ret; - ret = drm_dp_dpcd_read(aux, DP_AUX_HDCP_BCAPS, - bcaps, 1); - if (ret != 1) { + ret = drm_dp_dpcd_read_byte(aux, DP_AUX_HDCP_BCAPS, bcaps); + if (ret < 0) { drm_dbg_kms(display->drm, - "Read bcaps from DP/AUX failed (%zd)\n", ret); - return ret >= 0 ? -EIO : ret; + "Read bcaps from DP/AUX failed (%pe)\n", ERR_PTR(ret)); + return ret; } return 0; @@ -166,16 +166,16 @@ int intel_dp_hdcp_read_ri_prime(struct intel_digital_port *dig_port, u8 *ri_prime) { struct intel_display *display = to_intel_display(dig_port); - ssize_t ret; + int ret; - ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_RI_PRIME, - ri_prime, DRM_HDCP_RI_LEN); - if (ret != DRM_HDCP_RI_LEN) { + ret = drm_dp_dpcd_read_data(&dig_port->dp.aux, DP_AUX_HDCP_RI_PRIME, + ri_prime, DRM_HDCP_RI_LEN); + if (ret < 0) { drm_dbg_kms(display->drm, - "Read Ri' from DP/AUX failed (%zd)\n", - ret); - return ret >= 0 ? -EIO : ret; + "Read Ri' from DP/AUX failed (%pe)\n", ERR_PTR(ret)); + return ret; } + return 0; } @@ -184,17 +184,18 @@ int intel_dp_hdcp_read_ksv_ready(struct intel_digital_port *dig_port, bool *ksv_ready) { struct intel_display *display = to_intel_display(dig_port); - ssize_t ret; u8 bstatus; + int ret; - ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BSTATUS, - &bstatus, 1); - if (ret != 1) { + ret = drm_dp_dpcd_read_byte(&dig_port->dp.aux, DP_AUX_HDCP_BSTATUS, + &bstatus); + if (ret < 0) { drm_dbg_kms(display->drm, - "Read bstatus from DP/AUX failed (%zd)\n", ret); - return ret >= 0 ? -EIO : ret; + "Read bstatus from DP/AUX failed (%pe)\n", ERR_PTR(ret)); + return ret; } *ksv_ready = bstatus & DP_BSTATUS_READY; + return 0; } @@ -203,23 +204,24 @@ int intel_dp_hdcp_read_ksv_fifo(struct intel_digital_port *dig_port, int num_downstream, u8 *ksv_fifo) { struct intel_display *display = to_intel_display(dig_port); - ssize_t ret; + int ret; int i; /* KSV list is read via 15 byte window (3 entries @ 5 bytes each) */ for (i = 0; i < num_downstream; i += 3) { size_t len = min(num_downstream - i, 3) * DRM_HDCP_KSV_LEN; - ret = drm_dp_dpcd_read(&dig_port->dp.aux, - DP_AUX_HDCP_KSV_FIFO, - ksv_fifo + i * DRM_HDCP_KSV_LEN, - len); - if (ret != len) { + ret = drm_dp_dpcd_read_data(&dig_port->dp.aux, + DP_AUX_HDCP_KSV_FIFO, + ksv_fifo + i * DRM_HDCP_KSV_LEN, + len); + if (ret < 0) { drm_dbg_kms(display->drm, - "Read ksv[%d] from DP/AUX failed (%zd)\n", - i, ret); - return ret >= 0 ? -EIO : ret; + "Read ksv[%d] from DP/AUX failed (%pe)\n", + i, ERR_PTR(ret)); + return ret; } } + return 0; } @@ -228,19 +230,19 @@ int intel_dp_hdcp_read_v_prime_part(struct intel_digital_port *dig_port, int i, u32 *part) { struct intel_display *display = to_intel_display(dig_port); - ssize_t ret; + int ret; if (i >= DRM_HDCP_V_PRIME_NUM_PARTS) return -EINVAL; - ret = drm_dp_dpcd_read(&dig_port->dp.aux, - DP_AUX_HDCP_V_PRIME(i), part, - DRM_HDCP_V_PRIME_PART_LEN); - if (ret != DRM_HDCP_V_PRIME_PART_LEN) { + ret = drm_dp_dpcd_read_data(&dig_port->dp.aux, DP_AUX_HDCP_V_PRIME(i), part, + DRM_HDCP_V_PRIME_PART_LEN); + if (ret < 0) { drm_dbg_kms(display->drm, - "Read v'[%d] from DP/AUX failed (%zd)\n", i, ret); - return ret >= 0 ? -EIO : ret; + "Read v'[%d] from DP/AUX failed (%pe)\n", i, ERR_PTR(ret)); + return ret; } + return 0; } @@ -258,14 +260,13 @@ bool intel_dp_hdcp_check_link(struct intel_digital_port *dig_port, struct intel_connector *connector) { struct intel_display *display = to_intel_display(dig_port); - ssize_t ret; u8 bstatus; + int ret; - ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BSTATUS, - &bstatus, 1); - if (ret != 1) { + ret = drm_dp_dpcd_read_byte(&dig_port->dp.aux, DP_AUX_HDCP_BSTATUS, &bstatus); + if (ret < 0) { drm_dbg_kms(display->drm, - "Read bstatus from DP/AUX failed (%zd)\n", ret); + "Read bstatus from DP/AUX failed (%pe)\n", ERR_PTR(ret)); return false; } @@ -346,15 +347,14 @@ intel_dp_hdcp2_read_rx_status(struct intel_connector *connector, struct intel_display *display = to_intel_display(connector); struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_dp_aux *aux = &dig_port->dp.aux; - ssize_t ret; + int ret; - 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) { + ret = drm_dp_dpcd_read_data(aux, DP_HDCP_2_2_REG_RXSTATUS_OFFSET, rx_status, + HDCP_2_2_DP_RXSTATUS_LEN); + if (ret < 0) { drm_dbg_kms(display->drm, - "Read bstatus from DP/AUX failed (%zd)\n", ret); - return ret >= 0 ? -EIO : ret; + "Read bstatus from DP/AUX failed (%pe)\n", ERR_PTR(ret)); + return ret; } return 0; @@ -474,8 +474,8 @@ int intel_dp_hdcp2_write_msg(struct intel_connector *connector, len = bytes_to_write > DP_AUX_MAX_PAYLOAD_BYTES ? DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_write; - ret = drm_dp_dpcd_write(aux, - offset, (void *)byte, len); + /* Note: This may return < len for partial writes. */ + ret = drm_dp_dpcd_write(aux, offset, byte, len); if (ret < 0) return ret; @@ -487,20 +487,20 @@ int intel_dp_hdcp2_write_msg(struct intel_connector *connector, return size; } +/* return number of bytes read on success */ static ssize_t get_receiver_id_list_rx_info(struct intel_connector *connector, u32 *dev_cnt, u8 *byte) { struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_dp_aux *aux = &dig_port->dp.aux; - ssize_t ret; u8 *rx_info = byte; + int ret; - 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) - return ret >= 0 ? -EIO : ret; + ret = drm_dp_dpcd_read_data(aux, DP_HDCP_2_2_REG_RXINFO_OFFSET, + rx_info, HDCP_2_2_RXINFO_LEN); + if (ret < 0) + return ret; *dev_cnt = (HDCP_2_2_DEV_COUNT_HI(rx_info[0]) << 4 | HDCP_2_2_DEV_COUNT_LO(rx_info[1])); @@ -508,7 +508,7 @@ ssize_t get_receiver_id_list_rx_info(struct intel_connector *connector, if (*dev_cnt > HDCP_2_2_MAX_DEVICE_COUNT) *dev_cnt = HDCP_2_2_MAX_DEVICE_COUNT; - return ret; + return HDCP_2_2_RXINFO_LEN; } static @@ -566,11 +566,11 @@ int intel_dp_hdcp2_read_msg(struct intel_connector *connector, hdcp2_msg_data->msg_read_timeout); } - ret = drm_dp_dpcd_read(aux, offset, - (void *)byte, len); + /* Note: This may return < len for partial reads. */ + ret = drm_dp_dpcd_read(aux, offset, byte, len); if (ret < 0) { - drm_dbg_kms(display->drm, "msg_id %d, ret %zd\n", - msg_id, ret); + drm_dbg_kms(display->drm, "msg_id %d, ret %pe\n", + msg_id, ERR_PTR(ret)); return ret; } @@ -660,11 +660,11 @@ int _intel_dp_hdcp2_get_capability(struct drm_dp_aux *aux, * declare a monitor not capable of HDCP 2.2. */ for (i = 0; i < 3; i++) { - 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) - return ret >= 0 ? -EIO : ret; + ret = drm_dp_dpcd_read_data(aux, + DP_HDCP_2_2_REG_RX_CAPS_OFFSET, + rx_caps, HDCP_2_2_RXCAPS_LEN); + if (ret < 0) + return ret; if (rx_caps[0] == HDCP_2_2_RX_CAPS_VERSION_VAL && HDCP_2_2_DP_HDCP_CAPABLE(rx_caps[2])) { diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index 9a692f4fdfee..ac1aff6edf05 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -929,7 +929,7 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, { int reg = intel_dp_training_pattern_set_reg(intel_dp, dp_phy); u8 buf[sizeof(intel_dp->train_set) + 1]; - int len; + int ret, len; intel_dp_program_link_training_pattern(intel_dp, crtc_state, dp_phy, dp_train_pat); @@ -939,7 +939,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, memcpy(buf + 1, intel_dp->train_set, crtc_state->lane_count); len = crtc_state->lane_count + 1; - return drm_dp_dpcd_write(&intel_dp->aux, reg, buf, len) == len; + ret = drm_dp_dpcd_write_data(&intel_dp->aux, reg, buf, len); + + return !ret; } static char dp_training_pattern_name(u8 train_pat) @@ -1046,10 +1048,10 @@ intel_dp_update_link_train(struct intel_dp *intel_dp, intel_dp_set_signal_levels(intel_dp, crtc_state, dp_phy); - ret = drm_dp_dpcd_write(&intel_dp->aux, reg, - intel_dp->train_set, crtc_state->lane_count); + ret = drm_dp_dpcd_write_data(&intel_dp->aux, reg, + intel_dp->train_set, crtc_state->lane_count); - return ret == crtc_state->lane_count; + return !ret; } /* 128b/132b */ @@ -1115,7 +1117,7 @@ void intel_dp_link_training_set_mode(struct intel_dp *intel_dp, int link_rate, link_config[0] |= pr_with_as_sdp_enable ? DP_FIXED_VTOTAL_AS_SDP_EN_IN_PR_ACTIVE : 0; link_config[1] = drm_dp_is_uhbr_rate(link_rate) ? DP_SET_ANSI_128B132B : DP_SET_ANSI_8B10B; - drm_dp_dpcd_write(&intel_dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2); + drm_dp_dpcd_write_data(&intel_dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2); } static bool @@ -1163,8 +1165,8 @@ void intel_dp_link_training_set_bw(struct intel_dp *intel_dp, /* DP and eDP v1.3 and earlier link bw set method. */ u8 link_config[] = { link_bw, lane_count }; - drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, - ARRAY_SIZE(link_config)); + drm_dp_dpcd_write_data(&intel_dp->aux, DP_LINK_BW_SET, link_config, + sizeof(link_config)); } else { /* * eDP v1.4 and later link rate set method. @@ -1175,8 +1177,8 @@ void intel_dp_link_training_set_bw(struct intel_dp *intel_dp, * eDP v1.5 sinks allow choosing either, and the last choice * shall be active. */ - drm_dp_dpcd_writeb(&intel_dp->aux, DP_LANE_COUNT_SET, lane_count); - drm_dp_dpcd_writeb(&intel_dp->aux, DP_LINK_RATE_SET, rate_select); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_LANE_COUNT_SET, lane_count); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_LINK_RATE_SET, rate_select); } } @@ -1286,8 +1288,8 @@ intel_dp_prepare_link_train(struct intel_dp *intel_dp, lt_dbg(intel_dp, DP_PHY_DPRX, "Reloading eDP link rates\n"); - drm_dp_dpcd_read(&intel_dp->aux, DP_SUPPORTED_LINK_RATES, - sink_rates, sizeof(sink_rates)); + drm_dp_dpcd_read_data(&intel_dp->aux, DP_SUPPORTED_LINK_RATES, + sink_rates, sizeof(sink_rates)); } if (link_bw) @@ -1612,7 +1614,7 @@ static void intel_dp_stop_post_lt_adj_req(struct intel_dp *intel_dp, if (crtc_state->enhanced_framing) lane_count |= DP_LANE_COUNT_ENHANCED_FRAME_EN; - drm_dp_dpcd_writeb(&intel_dp->aux, DP_LANE_COUNT_SET, lane_count); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_LANE_COUNT_SET, lane_count); } static bool intel_dp_disable_dpcd_training_pattern(struct intel_dp *intel_dp, @@ -1621,7 +1623,7 @@ static bool intel_dp_disable_dpcd_training_pattern(struct intel_dp *intel_dp, int reg = intel_dp_training_pattern_set_reg(intel_dp, dp_phy); u8 val = DP_TRAINING_PATTERN_DISABLE; - return drm_dp_dpcd_write(&intel_dp->aux, reg, &val, 1) == 1; + return drm_dp_dpcd_write_byte(&intel_dp->aux, reg, val) == 0; } static int @@ -1631,10 +1633,11 @@ intel_dp_128b132b_intra_hop(struct intel_dp *intel_dp, u8 sink_status; int ret; - ret = drm_dp_dpcd_readb(&intel_dp->aux, DP_SINK_STATUS, &sink_status); - if (ret != 1) { - lt_dbg(intel_dp, DP_PHY_DPRX, "Failed to read sink status\n"); - return ret < 0 ? ret : -EIO; + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_SINK_STATUS, &sink_status); + if (ret < 0) { + lt_dbg(intel_dp, DP_PHY_DPRX, "Failed to read sink status (%pe)\n", + ERR_PTR(ret)); + return ret; } return sink_status & DP_INTRA_HOP_AUX_REPLY_INDICATION ? 1 : 0; @@ -2173,10 +2176,13 @@ intel_dp_128b132b_lane_cds(struct intel_dp *intel_dp, { u8 link_status[DP_LINK_STATUS_SIZE]; unsigned long deadline; + int ret; - if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TRAINING_PATTERN_SET, - DP_TRAINING_PATTERN_2_CDS) != 1) { - lt_err(intel_dp, DP_PHY_DPRX, "Failed to start 128b/132b TPS2 CDS\n"); + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_2_CDS); + if (ret < 0) { + lt_err(intel_dp, DP_PHY_DPRX, "Failed to start 128b/132b TPS2 CDS (%pe)\n", + ERR_PTR(ret)); return false; } @@ -2363,9 +2369,9 @@ void intel_dp_128b132b_sdp_crc16(struct intel_dp *intel_dp, 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); + drm_dp_dpcd_write_byte(&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"); } diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 0c362784afe4..7023619aaaba 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -2252,7 +2252,7 @@ bool intel_dp_mst_verify_dpcd_state(struct intel_dp *intel_dp) if (!intel_dp->is_mst) return true; - ret = drm_dp_dpcd_readb(intel_dp->mst.mgr.aux, DP_MSTM_CTRL, &val); + ret = drm_dp_dpcd_read_byte(intel_dp->mst.mgr.aux, DP_MSTM_CTRL, &val); /* Adjust the expected register value for SST + SideBand. */ if (ret < 0 || val != (DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC)) { diff --git a/drivers/gpu/drm/i915/display/intel_dp_test.c b/drivers/gpu/drm/i915/display/intel_dp_test.c index 0551a1ce60d3..17cf27273124 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_test.c +++ b/drivers/gpu/drm/i915/display/intel_dp_test.c @@ -147,26 +147,25 @@ bool intel_dp_test_compute_config(struct intel_connector *connector, static u8 intel_dp_autotest_link_training(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); - int status = 0; + int ret; int test_link_rate; u8 test_lane_count, test_link_bw; /* (DP CTS 1.2) * 4.3.1.11 */ /* Read the TEST_LANE_COUNT and TEST_LINK_RTAE fields (DP CTS 3.1.4) */ - status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_LANE_COUNT, - &test_lane_count); - - if (status <= 0) { - drm_dbg_kms(display->drm, "Lane count read failed\n"); + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_TEST_LANE_COUNT, + &test_lane_count); + if (ret < 0) { + drm_dbg_kms(display->drm, "Lane count read failed (%pe)\n", ERR_PTR(ret)); return DP_TEST_NAK; } test_lane_count &= DP_MAX_LANE_COUNT_MASK; - status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_LINK_RATE, - &test_link_bw); - if (status <= 0) { - drm_dbg_kms(display->drm, "Link Rate read failed\n"); + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_TEST_LINK_RATE, + &test_link_bw); + if (ret < 0) { + drm_dbg_kms(display->drm, "Link Rate read failed (%pe)\n", ERR_PTR(ret)); return DP_TEST_NAK; } test_link_rate = drm_dp_bw_code_to_link_rate(test_link_bw); @@ -188,36 +187,34 @@ static u8 intel_dp_autotest_video_pattern(struct intel_dp *intel_dp) u8 test_pattern; u8 test_misc; __be16 h_width, v_height; - int status = 0; + int ret; /* Read the TEST_PATTERN (DP CTS 3.1.5) */ - status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_PATTERN, - &test_pattern); - if (status <= 0) { - drm_dbg_kms(display->drm, "Test pattern read failed\n"); + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_TEST_PATTERN, + &test_pattern); + if (ret < 0) { + drm_dbg_kms(display->drm, "Test pattern read failed (%pe)\n", ERR_PTR(ret)); return DP_TEST_NAK; } if (test_pattern != DP_COLOR_RAMP) return DP_TEST_NAK; - status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_H_WIDTH_HI, - &h_width, 2); - if (status <= 0) { - drm_dbg_kms(display->drm, "H Width read failed\n"); + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_TEST_H_WIDTH_HI, &h_width, 2); + if (ret < 0) { + drm_dbg_kms(display->drm, "H Width read failed (%pe)\n", ERR_PTR(ret)); return DP_TEST_NAK; } - status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_V_HEIGHT_HI, - &v_height, 2); - if (status <= 0) { - drm_dbg_kms(display->drm, "V Height read failed\n"); + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_TEST_V_HEIGHT_HI, + &v_height, 2); + if (ret < 0) { + drm_dbg_kms(display->drm, "V Height read failed (%pe)\n", ERR_PTR(ret)); return DP_TEST_NAK; } - status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_MISC0, - &test_misc); - if (status <= 0) { - drm_dbg_kms(display->drm, "TEST MISC read failed\n"); + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_TEST_MISC0, &test_misc); + if (ret < 0) { + drm_dbg_kms(display->drm, "TEST MISC read failed (%pe)\n", ERR_PTR(ret)); return DP_TEST_NAK; } if ((test_misc & DP_TEST_COLOR_FORMAT_MASK) != DP_COLOR_FORMAT_RGB) @@ -250,6 +247,7 @@ static u8 intel_dp_autotest_edid(struct intel_dp *intel_dp) u8 test_result = DP_TEST_ACK; struct intel_connector *intel_connector = intel_dp->attached_connector; struct drm_connector *connector = &intel_connector->base; + int ret; if (!intel_connector->detect_edid || connector->edid_corrupt || intel_dp->aux.i2c_defer_count > 6) { @@ -274,10 +272,11 @@ static u8 intel_dp_autotest_edid(struct intel_dp *intel_dp) /* We have to write the checksum of the last block read */ block += block->extensions; - if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_EDID_CHECKSUM, - block->checksum) <= 0) + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_TEST_EDID_CHECKSUM, + block->checksum); + if (ret < 0) drm_dbg_kms(display->drm, - "Failed to write EDID checksum\n"); + "Failed to write EDID checksum (%pe)\n", ERR_PTR(ret)); test_result = DP_TEST_ACK | DP_TEST_EDID_CHECKSUM_WRITE; intel_dp->compliance.test_data.edid = INTEL_DP_RESOLUTION_PREFERRED; @@ -397,8 +396,8 @@ static void intel_dp_process_phy_request(struct intel_dp *intel_dp, intel_dp_phy_pattern_update(intel_dp, crtc_state); - drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET, - intel_dp->train_set, crtc_state->lane_count); + drm_dp_dpcd_write_data(&intel_dp->aux, DP_TRAINING_LANE0_SET, + intel_dp->train_set, crtc_state->lane_count); drm_dp_set_phy_test_pattern(&intel_dp->aux, data, intel_dp->dpcd[DP_DPCD_REV]); @@ -427,12 +426,12 @@ void intel_dp_test_request(struct intel_dp *intel_dp) struct intel_display *display = to_intel_display(intel_dp); u8 response = DP_TEST_NAK; u8 request = 0; - int status; + int ret; - status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_REQUEST, &request); - if (status <= 0) { + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_TEST_REQUEST, &request); + if (ret < 0) { drm_dbg_kms(display->drm, - "Could not read test request from sink\n"); + "Could not read test request from sink (%pe)\n", ERR_PTR(ret)); goto update_status; } @@ -463,10 +462,10 @@ void intel_dp_test_request(struct intel_dp *intel_dp) intel_dp->compliance.test_type = request; update_status: - status = drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_RESPONSE, response); - if (status <= 0) + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_TEST_RESPONSE, response); + if (ret < 0) drm_dbg_kms(display->drm, - "Could not write test response to sink\n"); + "Could not write test response to sink (%pe)\n", ERR_PTR(ret)); } /* phy test */ diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 1c0859d5f829..9d71f594537f 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -596,7 +596,7 @@ u64 *intel_fb_plane_get_modifiers(struct intel_display *display, count++; } - list = kmalloc_array(count, sizeof(*list), GFP_KERNEL); + list = kmalloc_objs(*list, count); if (drm_WARN_ON(display->drm, !list)) return NULL; @@ -1289,7 +1289,7 @@ bool intel_plane_uses_fence(const struct intel_plane_state *plane_state) return intel_plane_needs_fence(display) || (plane->fbc && !plane_state->no_fbc_reason && - i915_gtt_view_is_normal(&plane_state->view.gtt)); + intel_gtt_view_is_normal(&plane_state->view.gtt)); } static int intel_fb_pitch(const struct intel_framebuffer *fb, int color_plane, unsigned int rotation) @@ -1511,7 +1511,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p plane_view_height_tiles(fb, color_plane, dims, y)); } - if (i915_gtt_view_is_rotated(&view->gtt)) { + if (intel_gtt_view_is_rotated(&view->gtt)) { drm_WARN_ON(display->drm, remap_info->linear); check_array_bounds(display, view->gtt.rotated.plane, color_plane); @@ -1536,7 +1536,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p /* rotate the tile dimensions to match the GTT view */ swap(tile_width, tile_height); } else { - drm_WARN_ON(display->drm, !i915_gtt_view_is_remapped(&view->gtt)); + drm_WARN_ON(display->drm, !intel_gtt_view_is_remapped(&view->gtt)); check_array_bounds(display, view->gtt.remapped.plane, color_plane); @@ -1632,13 +1632,13 @@ calc_plane_normal_size(const struct intel_framebuffer *fb, int color_plane, static void intel_fb_view_init(struct intel_display *display, struct intel_fb_view *view, - enum i915_gtt_view_type view_type, + enum intel_gtt_view_type view_type, const struct intel_framebuffer *fb) { memset(view, 0, sizeof(*view)); view->gtt.type = view_type; - if (i915_gtt_view_is_remapped(&view->gtt) && + if (intel_gtt_view_is_remapped(&view->gtt) && intel_fb_needs_pot_stride_remap(fb)) view->gtt.remapped.plane_alignment = SZ_2M / PAGE_SIZE; } @@ -1706,7 +1706,7 @@ int intel_fill_fb_info(struct intel_display *display, struct intel_framebuffer * unsigned int tile_size = intel_tile_size(display); intel_fb_view_init(display, &fb->normal_view, - I915_GTT_VIEW_NORMAL, fb); + INTEL_GTT_VIEW_NORMAL, fb); drm_WARN_ON(display->drm, intel_fb_supports_90_270_rotation(fb) && @@ -1714,10 +1714,10 @@ int intel_fill_fb_info(struct intel_display *display, struct intel_framebuffer * if (intel_fb_supports_90_270_rotation(fb)) intel_fb_view_init(display, &fb->rotated_view, - I915_GTT_VIEW_ROTATED, fb); + INTEL_GTT_VIEW_ROTATED, fb); if (intel_fb_needs_pot_stride_remap(fb)) intel_fb_view_init(display, &fb->remapped_view, - I915_GTT_VIEW_REMAPPED, fb); + INTEL_GTT_VIEW_REMAPPED, fb); for (i = 0; i < num_planes; i++) { struct fb_plane_view_dims view_dims; @@ -1845,7 +1845,7 @@ static void intel_plane_remap_gtt(struct intel_plane_state *plane_state) intel_fb_view_init(display, &plane_state->view, drm_rotation_90_or_270(rotation) ? - I915_GTT_VIEW_ROTATED : I915_GTT_VIEW_REMAPPED, + INTEL_GTT_VIEW_ROTATED : INTEL_GTT_VIEW_REMAPPED, intel_fb); src_x = plane_state->uapi.src.x1 >> 16; diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index f61b4a218d6e..5694d20773f8 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -1196,23 +1196,13 @@ xe3p_lpd_fbc_fp16_format_is_valid(const struct intel_plane_state *plane_state) static bool xe3p_lpd_fbc_pixel_format_is_valid(const struct intel_plane_state *plane_state) { - const struct drm_framebuffer *fb = plane_state->hw.fb; - if (lnl_fbc_pixel_format_is_valid(plane_state)) return true; if (xe3p_lpd_fbc_fp16_format_is_valid(plane_state)) return true; - switch (fb->format->format) { - case DRM_FORMAT_XRGB16161616: - case DRM_FORMAT_XBGR16161616: - case DRM_FORMAT_ARGB16161616: - case DRM_FORMAT_ABGR16161616: - return true; - default: - return false; - } + return false; } bool intel_fbc_need_pixel_normalizer(const struct intel_plane_state *plane_state) diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c index 970aa95ee344..d095eb13dc06 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c @@ -867,6 +867,11 @@ void intel_hpd_poll_enable(struct intel_display *display) if (!HAS_DISPLAY(display) || !intel_display_device_enabled(display)) return; + if (intel_display_rpm_pme_enabled(display)) { + drm_dbg_kms(display->drm, "PME wake capable device, skipping HPD polling.\n"); + return; + } + WRITE_ONCE(display->hotplug.poll_enabled, true); /* diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index 9ceabbc981a1..a61224523318 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -137,11 +137,10 @@ bool intel_lspcon_detect_hdr_capability(struct intel_digital_port *dig_port) u8 hdr_caps; int ret; - ret = drm_dp_dpcd_read(&intel_dp->aux, get_hdr_status_reg(lspcon), - &hdr_caps, 1); - + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, get_hdr_status_reg(lspcon), &hdr_caps); if (ret < 0) { - drm_dbg_kms(display->drm, "HDR capability detection failed\n"); + drm_dbg_kms(display->drm, "HDR capability detection failed (%pe)\n", + ERR_PTR(ret)); lspcon->hdr_supported = false; } else if (hdr_caps & 0x1) { drm_dbg_kms(display->drm, "LSPCON capable of HDR\n"); @@ -244,11 +243,12 @@ static bool lspcon_wake_native_aux_ch(struct intel_lspcon *lspcon) { struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); struct intel_display *display = to_intel_display(intel_dp); + int ret; u8 rev; - if (drm_dp_dpcd_readb(&lspcon_to_intel_dp(lspcon)->aux, DP_DPCD_REV, - &rev) != 1) { - drm_dbg_kms(display->drm, "Native AUX CH down\n"); + ret = drm_dp_dpcd_read_byte(&lspcon_to_intel_dp(lspcon)->aux, DP_DPCD_REV, &rev); + if (ret < 0) { + drm_dbg_kms(display->drm, "Native AUX CH down (%pe)\n", ERR_PTR(ret)); return false; } @@ -331,17 +331,17 @@ static bool lspcon_parade_fw_ready(struct drm_dp_aux *aux) { u8 avi_if_ctrl; u8 retry; - ssize_t ret; + int ret; /* Check if LSPCON FW is ready for data */ for (retry = 0; retry < 5; retry++) { if (retry) usleep_range(200, 300); - ret = drm_dp_dpcd_read(aux, LSPCON_PARADE_AVI_IF_CTRL, - &avi_if_ctrl, 1); + ret = drm_dp_dpcd_read_byte(aux, LSPCON_PARADE_AVI_IF_CTRL, &avi_if_ctrl); if (ret < 0) { - drm_err(aux->drm_dev, "Failed to read AVI IF control\n"); + drm_err(aux->drm_dev, "Failed to read AVI IF control (%pe)\n", + ERR_PTR(ret)); return false; } @@ -371,10 +371,10 @@ static bool _lspcon_parade_write_infoframe_blocks(struct drm_dp_aux *aux, reg = LSPCON_PARADE_AVI_IF_WRITE_OFFSET; data = avi_buf + block_count * 8; - ret = drm_dp_dpcd_write(aux, reg, data, 8); + ret = drm_dp_dpcd_write_data(aux, reg, data, 8); if (ret < 0) { - drm_err(aux->drm_dev, "Failed to write AVI IF block %d\n", - block_count); + drm_err(aux->drm_dev, "Failed to write AVI IF block %d (%pe)\n", + block_count, ERR_PTR(ret)); return false; } @@ -386,10 +386,10 @@ static bool _lspcon_parade_write_infoframe_blocks(struct drm_dp_aux *aux, */ reg = LSPCON_PARADE_AVI_IF_CTRL; avi_if_ctrl = LSPCON_PARADE_AVI_IF_KICKOFF | block_count; - ret = drm_dp_dpcd_write(aux, reg, &avi_if_ctrl, 1); + ret = drm_dp_dpcd_write_byte(aux, reg, avi_if_ctrl); if (ret < 0) { - drm_err(aux->drm_dev, "Failed to update (0x%x), block %d\n", - reg, block_count); + drm_err(aux->drm_dev, "Failed to update (0x%x), block %d (%pe)\n", + reg, block_count, ERR_PTR(ret)); return false; } @@ -435,35 +435,38 @@ static bool _lspcon_write_avi_infoframe_parade(struct drm_dp_aux *aux, static bool _lspcon_write_avi_infoframe_mca(struct drm_dp_aux *aux, const u8 *buffer, ssize_t len) { - int ret; - u32 val = 0; + int ret, written = 0; u32 retry; u16 reg; const u8 *data = buffer; + u8 val; reg = LSPCON_MCA_AVI_IF_WRITE_OFFSET; - while (val < len) { + while (written < len) { /* DPCD write for AVI IF can fail on a slow FW day, so retry */ for (retry = 0; retry < 5; retry++) { - ret = drm_dp_dpcd_write(aux, reg, (void *)data, 1); - if (ret == 1) { + ret = drm_dp_dpcd_write_byte(aux, reg, *data); + if (!ret) { break; } else if (retry < 4) { mdelay(50); continue; } else { - drm_err(aux->drm_dev, "DPCD write failed at:0x%x\n", reg); + drm_err(aux->drm_dev, "DPCD write failed at:0x%x (%pe)\n", + reg, ERR_PTR(ret)); return false; } } - val++; reg++; data++; + written++; + reg++; + data++; } - val = 0; reg = LSPCON_MCA_AVI_IF_CTRL; - ret = drm_dp_dpcd_read(aux, reg, &val, 1); + ret = drm_dp_dpcd_read_byte(aux, reg, &val); if (ret < 0) { - drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); + drm_err(aux->drm_dev, "DPCD read failed, address 0x%x (%pe)\n", + reg, ERR_PTR(ret)); return false; } @@ -471,16 +474,17 @@ static bool _lspcon_write_avi_infoframe_mca(struct drm_dp_aux *aux, val &= ~LSPCON_MCA_AVI_IF_HANDLED; val |= LSPCON_MCA_AVI_IF_KICKOFF; - ret = drm_dp_dpcd_write(aux, reg, &val, 1); + ret = drm_dp_dpcd_write_byte(aux, reg, val); if (ret < 0) { - drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); + drm_err(aux->drm_dev, "DPCD write failed at:0x%x (%pe)\n", + reg, ERR_PTR(ret)); return false; } - val = 0; - ret = drm_dp_dpcd_read(aux, reg, &val, 1); + ret = drm_dp_dpcd_read_byte(aux, reg, &val); if (ret < 0) { - drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); + drm_err(aux->drm_dev, "DPCD read failed, address 0x%x (%pe)\n", + reg, ERR_PTR(ret)); return false; } @@ -612,12 +616,13 @@ void lspcon_set_infoframes(struct intel_encoder *encoder, static bool _lspcon_read_avi_infoframe_enabled_mca(struct drm_dp_aux *aux) { int ret; - u32 val = 0; u16 reg = LSPCON_MCA_AVI_IF_CTRL; + u8 val; - ret = drm_dp_dpcd_read(aux, reg, &val, 1); + ret = drm_dp_dpcd_read_byte(aux, reg, &val); if (ret < 0) { - drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); + drm_err(aux->drm_dev, "DPCD read failed, address 0x%x (%pe)\n", + reg, ERR_PTR(ret)); return false; } @@ -627,12 +632,13 @@ static bool _lspcon_read_avi_infoframe_enabled_mca(struct drm_dp_aux *aux) static bool _lspcon_read_avi_infoframe_enabled_parade(struct drm_dp_aux *aux) { int ret; - u32 val = 0; u16 reg = LSPCON_PARADE_AVI_IF_CTRL; + u8 val; - ret = drm_dp_dpcd_read(aux, reg, &val, 1); + ret = drm_dp_dpcd_read_byte(aux, reg, &val); if (ret < 0) { - drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); + drm_err(aux->drm_dev, "DPCD read failed, address 0x%x (%pe)\n", + reg, ERR_PTR(ret)); return false; } diff --git a/drivers/gpu/drm/i915/display/intel_parent.c b/drivers/gpu/drm/i915/display/intel_parent.c index 99cebb17763a..ed3e21b0a927 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.c +++ b/drivers/gpu/drm/i915/display/intel_parent.c @@ -94,9 +94,9 @@ void intel_parent_fb_pin_dpt_unpin(struct intel_display *display, struct i915_vma *intel_parent_fb_pin_reuse_vma(struct intel_display *display, struct i915_vma *old_ggtt_vma, struct drm_gem_object *old_obj, - const struct i915_gtt_view *old_view, + const struct intel_gtt_view *old_view, struct drm_gem_object *new_obj, - const struct i915_gtt_view *new_view, + const struct intel_gtt_view *new_view, u32 *out_offset) { if (!display->parent->fb_pin->reuse_vma) diff --git a/drivers/gpu/drm/i915/display/intel_parent.h b/drivers/gpu/drm/i915/display/intel_parent.h index cc4a58f63166..923cb6464a98 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.h +++ b/drivers/gpu/drm/i915/display/intel_parent.h @@ -11,12 +11,12 @@ struct dma_fence; struct drm_file; struct drm_gem_object; struct drm_scanout_buffer; -struct i915_gtt_view; struct i915_vma; struct intel_display; struct intel_dpt; struct intel_fb_pin_params; struct intel_frontbuffer; +struct intel_gtt_view; struct intel_hdcp_gsc_context; struct intel_panic; struct intel_stolen_node; @@ -53,9 +53,9 @@ void intel_parent_fb_pin_dpt_unpin(struct intel_display *display, struct i915_vma *intel_parent_fb_pin_reuse_vma(struct intel_display *display, struct i915_vma *old_ggtt_vma, struct drm_gem_object *old_obj, - const struct i915_gtt_view *old_view, + const struct intel_gtt_view *old_view, struct drm_gem_object *new_obj, - const struct i915_gtt_view *new_view, + const struct intel_gtt_view *new_view, u32 *out_offset); void intel_parent_fb_pin_get_map(struct intel_display *display, struct i915_vma *vma, struct iosys_map *map); diff --git a/drivers/gpu/drm/i915/display/intel_plane.c b/drivers/gpu/drm/i915/display/intel_plane.c index d0f99a87c42e..25ca049009ef 100644 --- a/drivers/gpu/drm/i915/display/intel_plane.c +++ b/drivers/gpu/drm/i915/display/intel_plane.c @@ -462,6 +462,42 @@ intel_plane_colorop_replace_blob(struct intel_plane_state *plane_state, return false; } +static u32 +fixedmatrix_colorop_to_encoding(enum drm_colorop_fixed_matrix_type fm_type) +{ + switch (fm_type) { + case DRM_COLOROP_FM_YCBCR709_FULL_RGB: + case DRM_COLOROP_FM_YCBCR709_LIMITED_RGB: + return DRM_COLOR_YCBCR_BT709; + + case DRM_COLOROP_FM_YCBCR2020_NC_FULL_RGB: + case DRM_COLOROP_FM_YCBCR2020_NC_LIMITED_RGB: + return DRM_COLOR_YCBCR_BT2020; + + case DRM_COLOROP_FM_YCBCR601_FULL_RGB: + case DRM_COLOROP_FM_YCBCR601_LIMITED_RGB: + default: + return DRM_COLOR_YCBCR_BT601; + } +} + +static u32 +fixedmatrix_colorop_to_range(enum drm_colorop_fixed_matrix_type fm_type) +{ + switch (fm_type) { + case DRM_COLOROP_FM_YCBCR601_FULL_RGB: + case DRM_COLOROP_FM_YCBCR709_FULL_RGB: + case DRM_COLOROP_FM_YCBCR2020_NC_FULL_RGB: + return DRM_COLOR_YCBCR_FULL_RANGE; + + case DRM_COLOROP_FM_YCBCR601_LIMITED_RGB: + case DRM_COLOROP_FM_YCBCR709_LIMITED_RGB: + case DRM_COLOROP_FM_YCBCR2020_NC_LIMITED_RGB: + default: + return DRM_COLOR_YCBCR_LIMITED_RANGE; + } +} + static void intel_plane_color_copy_uapi_to_hw_state(struct intel_atomic_state *state, struct intel_plane_state *plane_state, @@ -474,6 +510,7 @@ intel_plane_color_copy_uapi_to_hw_state(struct intel_atomic_state *state, struct drm_property_blob *blob; struct intel_crtc_state *new_crtc_state = state ? intel_atomic_get_new_crtc_state(state, crtc) : NULL; + enum drm_colorop_fixed_matrix_type fm_type; bool changed = false; int i = 0; @@ -485,11 +522,23 @@ intel_plane_color_copy_uapi_to_hw_state(struct intel_atomic_state *state, while (iter_colorop) { for_each_new_colorop_in_state(&state->base, colorop, new_colorop_state, i) { if (new_colorop_state->colorop == iter_colorop) { - blob = new_colorop_state->bypass ? NULL : new_colorop_state->data; intel_colorop = to_intel_colorop(colorop); - changed |= intel_plane_colorop_replace_blob(plane_state, + if (intel_colorop->id == INTEL_PLANE_CB_CSC_FF) { + fm_type = new_colorop_state->fixed_matrix_type; + + plane_state->hw.csc_ff_enable = + !new_colorop_state->bypass; + plane_state->hw.color_encoding = + fixedmatrix_colorop_to_encoding(fm_type); + plane_state->hw.color_range = + fixedmatrix_colorop_to_range(fm_type); + } else { + blob = new_colorop_state->bypass ? + NULL : new_colorop_state->data; + changed |= intel_plane_colorop_replace_blob(plane_state, intel_colorop, blob); + } } } iter_colorop = iter_colorop->next; diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 872e253db178..00d0146b2600 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -471,13 +471,15 @@ static u8 intel_dp_get_sink_sync_latency(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); u8 val = 8; /* assume the worst if we can't read the value */ + int ret; - if (drm_dp_dpcd_readb(&intel_dp->aux, - DP_SYNCHRONIZATION_LATENCY_IN_SINK, &val) == 1) + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_SYNCHRONIZATION_LATENCY_IN_SINK, &val); + if (!ret) val &= DP_MAX_RESYNC_FRAME_COUNT_MASK; else drm_dbg_kms(display->drm, - "Unable to get sink synchronization latency, assuming 8 frames\n"); + "Unable to get sink synchronization latency, assuming 8 frames (%pe)\n", + ERR_PTR(ret)); return val; } @@ -485,7 +487,7 @@ static void _psr_compute_su_granularity(struct intel_dp *intel_dp, struct intel_connector *connector) { struct intel_display *display = to_intel_display(intel_dp); - ssize_t r; + int ret; __le16 w; u8 y; @@ -500,21 +502,23 @@ static void _psr_compute_su_granularity(struct intel_dp *intel_dp, goto exit; } - r = drm_dp_dpcd_read(&intel_dp->aux, DP_PSR2_SU_X_GRANULARITY, &w, sizeof(w)); - if (r != sizeof(w)) + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_PSR2_SU_X_GRANULARITY, &w, sizeof(w)); + if (ret < 0) drm_dbg_kms(display->drm, - "Unable to read selective update x granularity\n"); + "Unable to read selective update x granularity (%pe)\n", + ERR_PTR(ret)); /* * Spec says that if the value read is 0 the default granularity should * be used instead. */ - if (r != sizeof(w) || w == 0) + if (ret < 0 || w == 0) w = cpu_to_le16(4); - r = drm_dp_dpcd_read(&intel_dp->aux, DP_PSR2_SU_Y_GRANULARITY, &y, 1); - if (r != 1) { + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_PSR2_SU_Y_GRANULARITY, &y); + if (ret < 0) { drm_dbg_kms(display->drm, - "Unable to read selective update y granularity\n"); + "Unable to read selective update y granularity (%pe)\n", + ERR_PTR(ret)); y = 4; } if (y == 0) @@ -796,11 +800,11 @@ static void _panel_replay_enable_sink(struct intel_dp *intel_dp, panel_replay_config[1] |= DP_PANEL_REPLAY_SU_REGION_SCANLINE_CAPTURE; - drm_dp_dpcd_write(&intel_dp->aux, PANEL_REPLAY_CONFIG, - panel_replay_config, sizeof(panel_replay_config)); + drm_dp_dpcd_write_data(&intel_dp->aux, PANEL_REPLAY_CONFIG, + panel_replay_config, sizeof(panel_replay_config)); panel_replay_config_3 = intel_dp_as_sdp_transmission_time(); - drm_dp_dpcd_writeb(&intel_dp->aux, PANEL_REPLAY_CONFIG3, panel_replay_config_3); + drm_dp_dpcd_write_byte(&intel_dp->aux, PANEL_REPLAY_CONFIG3, panel_replay_config_3); } static void _psr_enable_sink(struct intel_dp *intel_dp, @@ -827,10 +831,10 @@ static void _psr_enable_sink(struct intel_dp *intel_dp, if (intel_dp->psr.entry_setup_frames > 0) val |= DP_PSR_FRAME_CAPTURE; - drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, val); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_PSR_EN_CFG, val); val |= DP_PSR_ENABLE; - drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, val); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_PSR_EN_CFG, val); } static void intel_psr_enable_sink(struct intel_dp *intel_dp, @@ -843,7 +847,7 @@ static void intel_psr_enable_sink(struct intel_dp *intel_dp, _psr_enable_sink(intel_dp, crtc_state); if (intel_dp_is_edp(intel_dp)) - drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); } void intel_psr_panel_replay_enable_sink(struct intel_dp *intel_dp) @@ -854,8 +858,8 @@ void intel_psr_panel_replay_enable_sink(struct intel_dp *intel_dp) * ensure this bit is cleared/set accordingly. */ if (CAN_PANEL_REPLAY(intel_dp) && panel_replay_global_enabled(intel_dp)) - drm_dp_dpcd_writeb(&intel_dp->aux, PANEL_REPLAY_CONFIG, - DP_PANEL_REPLAY_ENABLE); + drm_dp_dpcd_write_byte(&intel_dp->aux, PANEL_REPLAY_CONFIG, + DP_PANEL_REPLAY_ENABLE); } static u32 intel_psr1_get_tp_time(struct intel_dp *intel_dp) @@ -2373,11 +2377,11 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) /* Disable PSR on Sink */ if (!intel_dp->psr.panel_replay_enabled) { - drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_PSR_EN_CFG, 0); if (intel_dp->psr.sel_update_enabled) - drm_dp_dpcd_writeb(&intel_dp->aux, - DP_RECEIVER_ALPM_CONFIG, 0); + drm_dp_dpcd_write_byte(&intel_dp->aux, + DP_RECEIVER_ALPM_CONFIG, 0); } /* Wa_16025596647 */ @@ -3517,7 +3521,7 @@ static void intel_psr_handle_irq(struct intel_dp *intel_dp) intel_psr_disable_locked(intel_dp); psr->sink_not_reliable = true; /* let's make sure that sink is awaken */ - drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); } static void intel_psr_work(struct work_struct *work) @@ -3796,15 +3800,15 @@ static int psr_get_status_and_error_status(struct intel_dp *intel_dp, offset = intel_dp->psr.panel_replay_enabled ? DP_SINK_DEVICE_PR_AND_FRAME_LOCK_STATUS : DP_PSR_STATUS; - ret = drm_dp_dpcd_readb(aux, offset, status); - if (ret != 1) + ret = drm_dp_dpcd_read_byte(aux, offset, status); + if (ret < 0) return ret; offset = intel_dp->psr.panel_replay_enabled ? DP_PANEL_REPLAY_ERROR_STATUS : DP_PSR_ERROR_STATUS; - ret = drm_dp_dpcd_readb(aux, offset, error_status); - if (ret != 1) + ret = drm_dp_dpcd_read_byte(aux, offset, error_status); + if (ret < 0) return ret; *status = *status & DP_PSR_SINK_STATE_MASK; @@ -3829,12 +3833,12 @@ static void psr_capability_changed_check(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); struct intel_psr *psr = &intel_dp->psr; + int ret; u8 val; - int r; - r = drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_ESI, &val); - if (r != 1) { - drm_err(display->drm, "Error reading DP_PSR_ESI\n"); + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_PSR_ESI, &val); + if (ret < 0) { + drm_err(display->drm, "Error reading DP_PSR_ESI (%pe)\n", ERR_PTR(ret)); return; } @@ -3845,7 +3849,7 @@ static void psr_capability_changed_check(struct intel_dp *intel_dp) "Sink PSR capability changed, disabling PSR\n"); /* Clearing it */ - drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_ESI, val); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_PSR_ESI, val); } } @@ -3913,10 +3917,10 @@ void intel_psr_short_pulse(struct intel_dp *intel_dp) "PSR_ERROR_STATUS unhandled errors %x\n", error_status & ~errors); /* clear status register */ - drm_dp_dpcd_writeb(&intel_dp->aux, - panel_replay_enabled ? - DP_PANEL_REPLAY_ERROR_STATUS : DP_PSR_ERROR_STATUS, - error_status); + drm_dp_dpcd_write_byte(&intel_dp->aux, + panel_replay_enabled ? + DP_PANEL_REPLAY_ERROR_STATUS : DP_PSR_ERROR_STATUS, + error_status); if (!psr->panel_replay_enabled) { psr_alpm_check(intel_dp); diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h b/drivers/gpu/drm/i915/display/intel_psr_regs.h index 16a9e3af198d..bb577e7e3bbd 100644 --- a/drivers/gpu/drm/i915/display/intel_psr_regs.h +++ b/drivers/gpu/drm/i915/display/intel_psr_regs.h @@ -276,6 +276,8 @@ #define PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1_OR_T2 REG_FIELD_PREP(PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_MASK, 0) #define PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1 REG_FIELD_PREP(PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_MASK, 1) #define PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T2 REG_FIELD_PREP(PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_MASK, 2) +#define PR_ALPM_CTL_AS_SDP_SKIP_FRAMES_MASK REG_GENMASK(27, 16) +#define PR_ALPM_CTL_AS_SDP_SKIP_FRAMES(frames) REG_FIELD_PREP(PR_ALPM_CTL_AS_SDP_SKIP_FRAMES_MASK, (frames)) #define _ALPM_CTL_A 0x60950 #define ALPM_CTL(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _ALPM_CTL_A) diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index 1698c54e258b..d43a06907d18 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -17,6 +17,8 @@ #include "intel_cmtg.h" #include "intel_crtc.h" #include "intel_de.h" +#include "intel_dip.h" +#include "intel_dip_regs.h" #include "intel_display_limits.h" #include "intel_display_regs.h" #include "intel_display_types.h" @@ -712,17 +714,7 @@ void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state) VRR_VSYNC_END(crtc_state->vrr.vsync_end) | VRR_VSYNC_START(crtc_state->vrr.vsync_start)); - /* - * For BMG and LNL+ onwards the EMP_AS_SDP_TL is used for programming - * double buffering point and transmission line for VRR packets for - * HDMI2.1/DP/eDP/DP->HDMI2.1 PCON. - * Since currently we support VRR only for DP/eDP, so this is programmed - * to for Adaptive Sync SDP to Vsync start. - */ - if (DISPLAY_VERx100(display) == 1401 || DISPLAY_VER(display) >= 20) - intel_de_write(display, - EMP_AS_SDP_TL(display, cpu_transcoder), - EMP_AS_SDP_DB_TL(crtc_state->vrr.vsync_start)); + intel_dip_write_emp_as_sdp_tl(crtc_state); } void diff --git a/drivers/gpu/drm/i915/display/intel_vrr_regs.h b/drivers/gpu/drm/i915/display/intel_vrr_regs.h index 9d4d6573a149..ba8631cbc672 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr_regs.h +++ b/drivers/gpu/drm/i915/display/intel_vrr_regs.h @@ -174,12 +174,6 @@ #define VRR_VSYNC_START_MASK REG_GENMASK(12, 0) #define VRR_VSYNC_START(vsync_start) REG_FIELD_PREP(VRR_VSYNC_START_MASK, (vsync_start)) -/* Common register for HDMI EMP and DP AS SDP */ -#define _EMP_AS_SDP_TL_A 0x60204 -#define EMP_AS_SDP_TL(display, trans) _MMIO_TRANS2((display), (trans), _EMP_AS_SDP_TL_A) -#define EMP_AS_SDP_DB_TL_MASK REG_GENMASK(12, 0) -#define EMP_AS_SDP_DB_TL(db_transmit_line) REG_FIELD_PREP(EMP_AS_SDP_DB_TL_MASK, (db_transmit_line)) - #define _TRANS_CMRR_M_LO_A 0x604F0 #define TRANS_CMRR_M_LO(display, trans) _MMIO_TRANS2((display), (trans), _TRANS_CMRR_M_LO_A) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 271c0640fd36..8bdf1b8a0229 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1242,36 +1242,46 @@ static u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state) return plane_color_ctl; } -static u32 glk_plane_color_ctl(const struct intel_plane_state *plane_state) +static u32 glk_plane_color_ctl_input_csc(const struct intel_plane_state *plane_state) { struct intel_display *display = to_intel_display(plane_state); const struct drm_framebuffer *fb = plane_state->hw.fb; struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); + bool color_pipeline = !!plane_state->uapi.color_pipeline; + bool needs_csc = color_pipeline ? plane_state->hw.csc_ff_enable : fb->format->is_yuv; + u32 ctl = 0; + + if (!needs_csc) + return 0; + + if (!icl_is_hdr_plane(display, plane->id)) { + switch (plane_state->hw.color_encoding) { + case DRM_COLOR_YCBCR_BT709: + ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709; + break; + case DRM_COLOR_YCBCR_BT2020: + ctl |= PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020; + break; + default: + ctl |= PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601; + } + } else { + ctl |= PLANE_COLOR_INPUT_CSC_ENABLE; + } + + if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) + ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; + + return ctl; +} + +static u32 glk_plane_color_ctl(const struct intel_plane_state *plane_state) +{ u32 plane_color_ctl = 0; plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state); - - if (fb->format->is_yuv && !icl_is_hdr_plane(display, plane->id)) { - switch (plane_state->hw.color_encoding) { - case DRM_COLOR_YCBCR_BT709: - plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709; - break; - case DRM_COLOR_YCBCR_BT2020: - plane_color_ctl |= - PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020; - break; - default: - plane_color_ctl |= - PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601; - } - if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) - plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; - } else if (fb->format->is_yuv) { - plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE; - if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) - plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; - } + plane_color_ctl |= glk_plane_color_ctl_input_csc(plane_state); if (plane_state->force_black) plane_color_ctl |= PLANE_COLOR_PLANE_CSC_ENABLE; @@ -1613,7 +1623,8 @@ icl_plane_update_noarm(struct intel_dsb *dsb, intel_de_write_dsb(display, dsb, PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl); - if (fb->format->is_yuv && icl_is_hdr_plane(display, plane_id)) + if (icl_is_hdr_plane(display, plane_id) && + (fb->format->is_yuv || plane_state->hw.csc_ff_enable)) icl_program_input_csc(dsb, plane, plane_state); skl_write_plane_wm(dsb, plane, crtc_state); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index b7297c0a3a48..9a82ed77ccaf 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -421,7 +421,7 @@ struct i915_vma * i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, struct i915_gem_ww_ctx *ww, u32 alignment, unsigned int guard, - const struct i915_gtt_view *view, + const struct intel_gtt_view *view, unsigned int flags) { struct drm_i915_private *i915 = to_i915(obj->base.dev); @@ -462,7 +462,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, */ vma = ERR_PTR(-ENOSPC); if ((flags & PIN_MAPPABLE) == 0 && - (!view || view->type == I915_GTT_VIEW_NORMAL)) + (!view || intel_gtt_view_is_normal(view))) vma = i915_gem_object_ggtt_pin_ww(obj, ww, view, 0, alignment, flags | PIN_MAPPABLE | PIN_NONBLOCK); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index 9ca90c1bb5b4..6b337684dbfe 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -196,17 +196,17 @@ int i915_gem_mmap_gtt_version(void) return 5; } -static inline struct i915_gtt_view +static inline struct intel_gtt_view compute_partial_view(const struct drm_i915_gem_object *obj, pgoff_t page_offset, unsigned int chunk) { - struct i915_gtt_view view; + struct intel_gtt_view view; if (i915_gem_object_is_tiled(obj)) chunk = roundup(chunk, tile_row_pages(obj) ?: 1); - view.type = I915_GTT_VIEW_PARTIAL; + view.type = INTEL_GTT_VIEW_PARTIAL; view.partial.offset = rounddown(page_offset, chunk); view.partial.size = min_t(unsigned int, chunk, @@ -214,7 +214,7 @@ compute_partial_view(const struct drm_i915_gem_object *obj, /* If the partial covers the entire object, just create a normal VMA. */ if (chunk >= obj->base.size >> PAGE_SHIFT) - view.type = I915_GTT_VIEW_NORMAL; + view.type = INTEL_GTT_VIEW_NORMAL; return view; } @@ -391,12 +391,12 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf) PIN_NOEVICT); if (IS_ERR(vma) && vma != ERR_PTR(-EDEADLK)) { /* Use a partial view if it is bigger than available space */ - struct i915_gtt_view view = + struct intel_gtt_view view = compute_partial_view(obj, page_offset, MIN_CHUNK_PAGES); unsigned int flags; flags = PIN_MAPPABLE | PIN_NOSEARCH; - if (view.type == I915_GTT_VIEW_NORMAL) + if (intel_gtt_view_is_normal(&view)) flags |= PIN_NONBLOCK; /* avoid warnings for pinned */ /* @@ -407,7 +407,7 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf) vma = i915_gem_object_ggtt_pin_ww(obj, &ww, &view, 0, 0, flags); if (IS_ERR(vma) && vma != ERR_PTR(-EDEADLK)) { flags = PIN_MAPPABLE; - view.type = I915_GTT_VIEW_PARTIAL; + view.type = INTEL_GTT_VIEW_PARTIAL; vma = i915_gem_object_ggtt_pin_ww(obj, &ww, &view, 0, 0, flags); } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index 2c5d20e4dbaf..a2f4b6758a65 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -776,7 +776,7 @@ struct i915_vma * __must_check i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, struct i915_gem_ww_ctx *ww, u32 alignment, unsigned int guard, - const struct i915_gtt_view *view, + const struct intel_gtt_view *view, unsigned int flags); void i915_gem_object_make_unshrinkable(struct drm_i915_gem_object *obj); diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index d01acfb7d93d..4d49fd6c15e3 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -97,7 +97,7 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj, { const unsigned long npages = obj->base.size / PAGE_SIZE; struct drm_i915_private *i915 = to_i915(obj->base.dev); - struct i915_gtt_view view; + struct intel_gtt_view view; struct i915_vma *vma; unsigned long offset; unsigned long page; @@ -214,7 +214,7 @@ static int check_partial_mappings(struct drm_i915_gem_object *obj, } for_each_prime_number_from(page, 1, npages) { - struct i915_gtt_view view = + struct intel_gtt_view view = compute_partial_view(obj, page, MIN_CHUNK_PAGES); unsigned long offset; u32 __iomem *io; diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index c0fd349a4600..9dd9665128ca 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -1607,7 +1607,7 @@ u64 intel_engine_get_last_batch_head(const struct intel_engine_cs *engine) static unsigned long stop_timeout(const struct intel_engine_cs *engine) { - if (in_atomic() || irqs_disabled()) /* inside atomic preempt-reset? */ + if (in_atomic() || irqs_disabled() || rcu_preempt_depth()) /* inside atomic preempt-reset? */ return 0; /* diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index e693b0c9d2a3..841f71932675 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -1300,7 +1300,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) * and context switches) submission. */ - spin_lock(&sched_engine->lock); + spin_lock_irq(&sched_engine->lock); /* * If the queue is higher priority than the last @@ -1400,7 +1400,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) * Even if ELSP[1] is occupied and not worthy * of timeslices, our queue might be. */ - spin_unlock(&sched_engine->lock); + spin_unlock_irq(&sched_engine->lock); return; } } @@ -1426,7 +1426,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) if (last && !can_merge_rq(last, rq)) { spin_unlock(&ve->base.sched_engine->lock); - spin_unlock(&engine->sched_engine->lock); + spin_unlock_irq(&engine->sched_engine->lock); return; /* leave this for another sibling */ } @@ -1588,7 +1588,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) */ sched_engine->queue_priority_hint = queue_prio(sched_engine); i915_sched_engine_reset_on_empty(sched_engine); - spin_unlock(&sched_engine->lock); + spin_unlock_irq(&sched_engine->lock); /* * We can skip poking the HW if we ended up with exactly the same set @@ -1614,13 +1614,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine) } } -static void execlists_dequeue_irq(struct intel_engine_cs *engine) -{ - local_irq_disable(); /* Suspend interrupts across request submission */ - execlists_dequeue(engine); - local_irq_enable(); /* flush irq_work (e.g. breadcrumb enabling) */ -} - static void clear_ports(struct i915_request **ports, int count) { memset_p((void **)ports, NULL, count); @@ -2475,7 +2468,7 @@ static void execlists_submission_tasklet(struct tasklet_struct *t) } if (!engine->execlists.pending[0]) { - execlists_dequeue_irq(engine); + execlists_dequeue(engine); start_timeslice(engine); } diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 6053f3e8aa27..bd1f26336ac4 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1433,13 +1433,7 @@ static void intel_gt_reset_global(struct intel_gt *gt, need_display_reset; if (reset_display) { - if (atomic_read(&i915->pending_fb_pin)) { - drm_dbg_kms(&i915->drm, - "Modeset potentially stuck, unbreaking through wedging\n"); - - intel_gt_set_wedged(gt); - } - + intel_gt_set_wedged(gt); intel_display_reset_prepare(display); } diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_pm.c b/drivers/gpu/drm/i915/gt/selftest_engine_pm.c index 10e556a7eac4..c1eff9edd8a5 100644 --- a/drivers/gpu/drm/i915/gt/selftest_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/selftest_engine_pm.c @@ -277,11 +277,11 @@ static int live_engine_busy_stats(void *arg) st_engine_heartbeat_disable(engine); ENGINE_TRACE(engine, "measuring idle time\n"); - preempt_disable(); + migrate_disable(); de = intel_engine_get_busy_time(engine, &t[0]); udelay(100); de = ktime_sub(intel_engine_get_busy_time(engine, &t[1]), de); - preempt_enable(); + migrate_enable(); dt = ktime_sub(t[1], t[0]); if (de < 0 || de > 10) { pr_err("%s: reported %lldns [%d%%] busyness while sleeping [for %lldns]\n", @@ -316,11 +316,11 @@ static int live_engine_busy_stats(void *arg) } ENGINE_TRACE(engine, "measuring busy time\n"); - preempt_disable(); + migrate_disable(); de = intel_engine_get_busy_time(engine, &t[0]); mdelay(100); de = ktime_sub(intel_engine_get_busy_time(engine, &t[1]), de); - preempt_enable(); + migrate_enable(); dt = ktime_sub(t[1], t[0]); if (100 * de < 95 * dt || 95 * de > 100 * dt) { pr_err("%s: reported %lldns [%d%%] busyness while spinning [for %lldns]\n", diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 053780f562c1..b25fa8f4dc4b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -362,7 +362,7 @@ static inline int intel_guc_send_busy_loop(struct intel_guc *guc, { int err; unsigned int sleep_period_ms = 1; - bool not_atomic = !in_atomic() && !irqs_disabled(); + bool not_atomic = !in_atomic() && !irqs_disabled() && !rcu_preempt_depth(); /* * FIXME: Have caller pass in if we are in an atomic context to avoid diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c b/drivers/gpu/drm/i915/gvt/aperture_gm.c index 253b41789be9..794fb50e48dd 100644 --- a/drivers/gpu/drm/i915/gvt/aperture_gm.c +++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c @@ -34,6 +34,8 @@ * */ +#include + #include #include "gt/intel_ggtt_fencing.h" @@ -76,7 +78,7 @@ static int alloc_gm(struct intel_vgpu *vgpu, bool high_gm) mutex_unlock(>->ggtt->vm.mutex); if (ret) gvt_err("fail to alloc %s gm space from host\n", - high_gm ? "high" : "low"); + str_high_low(high_gm)); return ret; } diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index a3e27f9e4f47..04bc3d27b836 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -179,7 +179,7 @@ i915_debugfs_describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) struct i915_vma *vma; int pin_count = 0; - seq_printf(m, "%pK: %c%c%c %8zdKiB %02x %02x %s%s%s", + seq_printf(m, "%p: %c%c%c %8zdKiB %02x %02x %s%s%s", &obj->base, get_tiling_flag(obj), get_global_flag(obj), @@ -209,18 +209,13 @@ i915_debugfs_describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) stringify_page_sizes(vma->resource->page_sizes_gtt, NULL, 0)); if (i915_vma_is_ggtt(vma) || i915_vma_is_dpt(vma)) { - switch (vma->gtt_view.type) { - case I915_GTT_VIEW_NORMAL: + if (intel_gtt_view_is_normal(&vma->gtt_view)) { seq_puts(m, ", normal"); - break; - - case I915_GTT_VIEW_PARTIAL: + } else if (intel_gtt_view_is_partial(&vma->gtt_view)) { seq_printf(m, ", partial [%08llx+%x]", vma->gtt_view.partial.offset << PAGE_SHIFT, vma->gtt_view.partial.size << PAGE_SHIFT); - break; - - case I915_GTT_VIEW_ROTATED: + } else if (intel_gtt_view_is_rotated(&vma->gtt_view)) { seq_printf(m, ", rotated [(%ux%u, src_stride=%u, dst_stride=%u, offset=%u), (%ux%u, src_stride=%u, dst_stride=%u, offset=%u)]", vma->gtt_view.rotated.plane[0].width, vma->gtt_view.rotated.plane[0].height, @@ -232,9 +227,7 @@ i915_debugfs_describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) vma->gtt_view.rotated.plane[1].src_stride, vma->gtt_view.rotated.plane[1].dst_stride, vma->gtt_view.rotated.plane[1].offset); - break; - - case I915_GTT_VIEW_REMAPPED: + } else if (intel_gtt_view_is_remapped(&vma->gtt_view)) { seq_printf(m, ", remapped [(%ux%u, src_stride=%u, dst_stride=%u, offset=%u), (%ux%u, src_stride=%u, dst_stride=%u, offset=%u)]", vma->gtt_view.remapped.plane[0].width, vma->gtt_view.remapped.plane[0].height, @@ -246,11 +239,8 @@ i915_debugfs_describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) vma->gtt_view.remapped.plane[1].src_stride, vma->gtt_view.remapped.plane[1].dst_stride, vma->gtt_view.remapped.plane[1].offset); - break; - - default: + } else { MISSING_CASE(vma->gtt_view.type); - break; } } if (vma->fence) diff --git a/drivers/gpu/drm/i915/i915_dpt.c b/drivers/gpu/drm/i915/i915_dpt.c index e01dc4de1788..85d872c0f387 100644 --- a/drivers/gpu/drm/i915/i915_dpt.c +++ b/drivers/gpu/drm/i915/i915_dpt.c @@ -139,7 +139,6 @@ struct i915_vma *i915_dpt_pin_to_ggtt(struct intel_dpt *dpt, unsigned int alignm pin_flags |= PIN_MAPPABLE; wakeref = intel_runtime_pm_get(&i915->runtime_pm); - atomic_inc(&i915->pending_fb_pin); for_i915_gem_ww(&ww, err, true) { err = i915_gem_object_lock(dpt->obj, &ww); @@ -169,7 +168,6 @@ struct i915_vma *i915_dpt_pin_to_ggtt(struct intel_dpt *dpt, unsigned int alignm dpt->obj->mm.dirty = true; - atomic_dec(&i915->pending_fb_pin); intel_runtime_pm_put(&i915->runtime_pm, wakeref); return err ? ERR_PTR(err) : vma; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 844ed79e7211..dafee3dcd1c5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -315,8 +315,6 @@ struct drm_i915_private { /* The TTM device structure. */ struct ttm_device bdev; - atomic_t pending_fb_pin; - I915_SELFTEST_DECLARE(struct i915_selftest_stash selftest;) /* diff --git a/drivers/gpu/drm/i915/i915_fb_pin.c b/drivers/gpu/drm/i915/i915_fb_pin.c index 1034cb767e9f..63be136f1a05 100644 --- a/drivers/gpu/drm/i915/i915_fb_pin.c +++ b/drivers/gpu/drm/i915/i915_fb_pin.c @@ -35,8 +35,6 @@ intel_fb_pin_to_dpt(struct drm_gem_object *_obj, struct intel_dpt *dpt, if (WARN_ON(!i915_gem_object_is_framebuffer(obj))) return ERR_PTR(-EINVAL); - atomic_inc(&i915->pending_fb_pin); - for_i915_gem_ww(&ww, ret, true) { ret = i915_gem_object_lock(obj, &ww); if (ret) @@ -98,7 +96,6 @@ intel_fb_pin_to_dpt(struct drm_gem_object *_obj, struct intel_dpt *dpt, */ drm_WARN_ON(&i915->drm, i915_dpt_offset(vma)); err: - atomic_dec(&i915->pending_fb_pin); return vma; } @@ -132,8 +129,6 @@ intel_fb_pin_to_ggtt(struct drm_gem_object *_obj, */ wakeref = intel_runtime_pm_get(&i915->runtime_pm); - atomic_inc(&i915->pending_fb_pin); - pinctl = 0; /* PIN_MAPPABLE limits the address to GMADR size */ if (pin_params->needs_low_address) @@ -206,7 +201,6 @@ intel_fb_pin_to_ggtt(struct drm_gem_object *_obj, if (ret) vma = ERR_PTR(ret); - atomic_dec(&i915->pending_fb_pin); intel_runtime_pm_put(&i915->runtime_pm, wakeref); return vma; } diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a432daf8038a..1209d5f1fc8d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -902,7 +902,7 @@ static void discard_ggtt_vma(struct i915_vma *vma) struct i915_vma * i915_gem_object_ggtt_pin_ww(struct drm_i915_gem_object *obj, struct i915_gem_ww_ctx *ww, - const struct i915_gtt_view *view, + const struct intel_gtt_view *view, u64 size, u64 alignment, u64 flags) { struct drm_i915_private *i915 = to_i915(obj->base.dev); @@ -913,7 +913,7 @@ i915_gem_object_ggtt_pin_ww(struct drm_i915_gem_object *obj, GEM_WARN_ON(!ww); if (flags & PIN_MAPPABLE && - (!view || view->type == I915_GTT_VIEW_NORMAL)) { + (!view || intel_gtt_view_is_normal(view))) { /* * If the required space is larger than the available * aperture, we will not able to find a slot for the @@ -1004,7 +1004,7 @@ i915_gem_object_ggtt_pin_ww(struct drm_i915_gem_object *obj, struct i915_vma * __must_check i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, - const struct i915_gtt_view *view, + const struct intel_gtt_view *view, u64 size, u64 alignment, u64 flags) { struct i915_gem_ww_ctx ww; diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h index 20b3cb29cfff..80d9758fe684 100644 --- a/drivers/gpu/drm/i915/i915_gem.h +++ b/drivers/gpu/drm/i915/i915_gem.h @@ -36,8 +36,8 @@ struct drm_file; struct drm_i915_gem_object; struct drm_i915_private; struct i915_gem_ww_ctx; -struct i915_gtt_view; struct i915_vma; +struct intel_gtt_view; #define I915_GEM_GPU_DOMAINS \ (I915_GEM_DOMAIN_RENDER | \ @@ -55,12 +55,12 @@ void i915_gem_drain_workqueue(struct drm_i915_private *i915); struct i915_vma * __must_check i915_gem_object_ggtt_pin_ww(struct drm_i915_gem_object *obj, struct i915_gem_ww_ctx *ww, - const struct i915_gtt_view *view, + const struct intel_gtt_view *view, u64 size, u64 alignment, u64 flags); struct i915_vma * __must_check i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, - const struct i915_gtt_view *view, + const struct intel_gtt_view *view, u64 size, u64 alignment, u64 flags); int i915_gem_object_unbind(struct drm_i915_gem_object *obj, diff --git a/drivers/gpu/drm/i915/i915_gtt_view_types.h b/drivers/gpu/drm/i915/i915_gtt_view_types.h deleted file mode 100644 index 9c4f38db32ff..000000000000 --- a/drivers/gpu/drm/i915/i915_gtt_view_types.h +++ /dev/null @@ -1,74 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* Copyright © 2025 Intel Corporation */ - -#ifndef __I915_GTT_VIEW_TYPES_H__ -#define __I915_GTT_VIEW_TYPES_H__ - -#include - -struct intel_remapped_plane_info { - /* in gtt pages */ - u32 offset:31; - u32 linear:1; - union { - /* in gtt pages for !linear */ - struct { - u16 width; - u16 height; - u16 src_stride; - u16 dst_stride; - }; - - /* in gtt pages for linear */ - u32 size; - }; -} __packed; - -struct intel_rotation_info { - struct intel_remapped_plane_info plane[2]; -} __packed; - -struct intel_partial_info { - u64 offset; - unsigned int size; -} __packed; - -struct intel_remapped_info { - struct intel_remapped_plane_info plane[4]; - /* in gtt pages */ - u32 plane_alignment; -} __packed; - -enum i915_gtt_view_type { - I915_GTT_VIEW_NORMAL = 0, - I915_GTT_VIEW_ROTATED = sizeof(struct intel_rotation_info), - I915_GTT_VIEW_PARTIAL = sizeof(struct intel_partial_info), - I915_GTT_VIEW_REMAPPED = sizeof(struct intel_remapped_info), -}; - -struct i915_gtt_view { - enum i915_gtt_view_type type; - union { - /* Members need to contain no holes/padding */ - struct intel_partial_info partial; - struct intel_rotation_info rotated; - struct intel_remapped_info remapped; - }; -}; - -static inline bool i915_gtt_view_is_normal(const struct i915_gtt_view *view) -{ - return view->type == I915_GTT_VIEW_NORMAL; -} - -static inline bool i915_gtt_view_is_remapped(const struct i915_gtt_view *view) -{ - return view->type == I915_GTT_VIEW_REMAPPED; -} - -static inline bool i915_gtt_view_is_rotated(const struct i915_gtt_view *view) -{ - return view->type == I915_GTT_VIEW_ROTATED; -} - -#endif /* __I915_GTT_VIEW_TYPES_H__ */ diff --git a/drivers/gpu/drm/i915/i915_overlay.c b/drivers/gpu/drm/i915/i915_overlay.c index 6de550a17756..c1a7920c6324 100644 --- a/drivers/gpu/drm/i915/i915_overlay.c +++ b/drivers/gpu/drm/i915/i915_overlay.c @@ -354,14 +354,11 @@ static struct i915_vma *i915_overlay_pin_fb(struct drm_device *drm, struct drm_gem_object *obj, u32 *offset) { - struct drm_i915_private *i915 = to_i915(drm); struct drm_i915_gem_object *new_bo = to_intel_bo(obj); struct i915_gem_ww_ctx ww; struct i915_vma *vma; int ret; - atomic_inc(&i915->pending_fb_pin); - i915_gem_ww_ctx_init(&ww, true); retry: ret = i915_gem_object_lock(new_bo, &ww); @@ -377,8 +374,6 @@ static struct i915_vma *i915_overlay_pin_fb(struct drm_device *drm, } i915_gem_ww_ctx_fini(&ww); - atomic_dec(&i915->pending_fb_pin); - if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index d2c7b1090df0..f66f8efc7062 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -610,7 +610,6 @@ bool __i915_request_submit(struct i915_request *request) RQ_TRACE(request, "\n"); - GEM_BUG_ON(!irqs_disabled()); lockdep_assert_held(&engine->sched_engine->lock); /* @@ -719,7 +718,6 @@ void __i915_request_unsubmit(struct i915_request *request) */ RQ_TRACE(request, "\n"); - GEM_BUG_ON(!irqs_disabled()); lockdep_assert_held(&engine->sched_engine->lock); /* diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index afc192d9931b..16782d8579a8 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -147,7 +147,7 @@ static void __i915_vma_retire(struct i915_active *ref) static struct i915_vma * vma_create(struct drm_i915_gem_object *obj, struct i915_address_space *vm, - const struct i915_gtt_view *view) + const struct intel_gtt_view *view) { struct i915_vma *pos = ERR_PTR(-E2BIG); struct i915_vma *vma; @@ -179,9 +179,9 @@ vma_create(struct drm_i915_gem_object *obj, INIT_LIST_HEAD(&vma->obj_link); RB_CLEAR_NODE(&vma->obj_node); - if (view && view->type != I915_GTT_VIEW_NORMAL) { + if (view && !intel_gtt_view_is_normal(view)) { vma->gtt_view = *view; - if (view->type == I915_GTT_VIEW_PARTIAL) { + if (intel_gtt_view_is_partial(view)) { GEM_BUG_ON(range_overflows_t(u64, view->partial.offset, view->partial.size, @@ -189,10 +189,10 @@ vma_create(struct drm_i915_gem_object *obj, vma->size = view->partial.size; vma->size <<= PAGE_SHIFT; GEM_BUG_ON(vma->size > obj->base.size); - } else if (view->type == I915_GTT_VIEW_ROTATED) { + } else if (intel_gtt_view_is_rotated(view)) { vma->size = intel_rotation_info_size(&view->rotated); vma->size <<= PAGE_SHIFT; - } else if (view->type == I915_GTT_VIEW_REMAPPED) { + } else if (intel_gtt_view_is_remapped(view)) { vma->size = intel_remapped_info_size(&view->remapped); vma->size <<= PAGE_SHIFT; } @@ -286,7 +286,7 @@ vma_create(struct drm_i915_gem_object *obj, static struct i915_vma * i915_vma_lookup(struct drm_i915_gem_object *obj, struct i915_address_space *vm, - const struct i915_gtt_view *view) + const struct intel_gtt_view *view) { struct rb_node *rb; @@ -324,7 +324,7 @@ i915_vma_lookup(struct drm_i915_gem_object *obj, struct i915_vma * i915_vma_instance(struct drm_i915_gem_object *obj, struct i915_address_space *vm, - const struct i915_gtt_view *view) + const struct intel_gtt_view *view) { struct i915_vma *vma; @@ -1267,7 +1267,7 @@ intel_remap_pages(struct intel_remapped_info *rem_info, } static noinline struct sg_table * -intel_partial_pages(const struct i915_gtt_view *view, +intel_partial_pages(const struct intel_gtt_view *view, struct drm_i915_gem_object *obj) { struct sg_table *st; @@ -1311,27 +1311,15 @@ __i915_vma_get_pages(struct i915_vma *vma) */ GEM_BUG_ON(!i915_gem_object_has_pinned_pages(vma->obj)); - switch (vma->gtt_view.type) { - default: - GEM_BUG_ON(vma->gtt_view.type); - fallthrough; - case I915_GTT_VIEW_NORMAL: - pages = vma->obj->mm.pages; - break; - - case I915_GTT_VIEW_ROTATED: - pages = - intel_rotate_pages(&vma->gtt_view.rotated, vma->obj); - break; - - case I915_GTT_VIEW_REMAPPED: - pages = - intel_remap_pages(&vma->gtt_view.remapped, vma->obj); - break; - - case I915_GTT_VIEW_PARTIAL: + if (intel_gtt_view_is_rotated(&vma->gtt_view)) { + pages = intel_rotate_pages(&vma->gtt_view.rotated, vma->obj); + } else if (intel_gtt_view_is_remapped(&vma->gtt_view)) { + pages = intel_remap_pages(&vma->gtt_view.remapped, vma->obj); + } else if (intel_gtt_view_is_partial(&vma->gtt_view)) { pages = intel_partial_pages(&vma->gtt_view, vma->obj); - break; + } else { + GEM_BUG_ON(!intel_gtt_view_is_normal(&vma->gtt_view)); + pages = vma->obj->mm.pages; } if (IS_ERR(pages)) { diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h index 892306ab935d..b0aca10bf8e7 100644 --- a/drivers/gpu/drm/i915/i915_vma.h +++ b/drivers/gpu/drm/i915/i915_vma.h @@ -43,7 +43,7 @@ struct i915_vma * i915_vma_instance(struct drm_i915_gem_object *obj, struct i915_address_space *vm, - const struct i915_gtt_view *view); + const struct intel_gtt_view *view); void i915_vma_unpin_and_release(struct i915_vma **p_vma, unsigned int flags); #define I915_VMA_RELEASE_MAP BIT(0) @@ -207,7 +207,7 @@ static inline void i915_vma_put(struct i915_vma *vma) static inline long i915_vma_compare(struct i915_vma *vma, struct i915_address_space *vm, - const struct i915_gtt_view *view) + const struct intel_gtt_view *view) { ptrdiff_t cmp; @@ -217,7 +217,7 @@ i915_vma_compare(struct i915_vma *vma, if (cmp) return cmp; - BUILD_BUG_ON(I915_GTT_VIEW_NORMAL != 0); + BUILD_BUG_ON(INTEL_GTT_VIEW_NORMAL != 0); cmp = vma->gtt_view.type; if (!view) return cmp; @@ -238,9 +238,9 @@ i915_vma_compare(struct i915_vma *vma, * we assert above that all branches have the same address, and that * each branch has a unique type/size. */ - BUILD_BUG_ON(I915_GTT_VIEW_NORMAL >= I915_GTT_VIEW_PARTIAL); - BUILD_BUG_ON(I915_GTT_VIEW_PARTIAL >= I915_GTT_VIEW_ROTATED); - BUILD_BUG_ON(I915_GTT_VIEW_ROTATED >= I915_GTT_VIEW_REMAPPED); + BUILD_BUG_ON(INTEL_GTT_VIEW_NORMAL >= INTEL_GTT_VIEW_PARTIAL); + BUILD_BUG_ON(INTEL_GTT_VIEW_PARTIAL >= INTEL_GTT_VIEW_ROTATED); + BUILD_BUG_ON(INTEL_GTT_VIEW_ROTATED >= INTEL_GTT_VIEW_REMAPPED); BUILD_BUG_ON(offsetof(typeof(*view), rotated) != offsetof(typeof(*view), partial)); BUILD_BUG_ON(offsetof(typeof(*view), rotated) != diff --git a/drivers/gpu/drm/i915/i915_vma_types.h b/drivers/gpu/drm/i915/i915_vma_types.h index a499a3bea874..95eaf68fdfae 100644 --- a/drivers/gpu/drm/i915/i915_vma_types.h +++ b/drivers/gpu/drm/i915/i915_vma_types.h @@ -29,11 +29,10 @@ #include #include +#include #include "gem/i915_gem_object_types.h" -#include "i915_gtt_view_types.h" - /** * DOC: Global GTT views * @@ -67,22 +66,22 @@ * Implementation and usage * * GGTT views are implemented using VMAs and are distinguished via enum - * i915_gtt_view_type and struct i915_gtt_view. + * intel_gtt_view_type and struct intel_gtt_view. * * A new flavour of core GEM functions which work with GGTT bound objects were * added with the _ggtt_ infix, and sometimes with _view postfix to avoid - * renaming in large amounts of code. They take the struct i915_gtt_view + * renaming in large amounts of code. They take the struct intel_gtt_view * parameter encapsulating all metadata required to implement a view. * * As a helper for callers which are only interested in the normal view, - * globally const i915_gtt_view_normal singleton instance exists. All old core + * globally const intel_gtt_view_normal singleton instance exists. All old core * GEM API functions, the ones not taking the view parameter, are operating on, * or with the normal GGTT view. * * Code wanting to add or use a new GGTT view needs to: * * 1. Add a new enum with a suitable name. - * 2. Extend the metadata in the i915_gtt_view structure if required. + * 2. Extend the metadata in the intel_gtt_view structure if required. * 3. Add support to i915_get_vma_pages(). * * New views are required to build a scatter-gather table from within the @@ -90,7 +89,7 @@ * exists for the lifetime of an VMA. * * Core API is designed to have copy semantics which means that passed in - * struct i915_gtt_view does not need to be persistent (left around after + * struct intel_gtt_view does not need to be persistent (left around after * calling the core API functions). * */ @@ -112,11 +111,11 @@ static inline void assert_i915_gem_gtt_types(void) /* As we encode the size of each branch inside the union into its type, * we have to be careful that each branch has a unique size. */ - switch ((enum i915_gtt_view_type)0) { - case I915_GTT_VIEW_NORMAL: - case I915_GTT_VIEW_PARTIAL: - case I915_GTT_VIEW_ROTATED: - case I915_GTT_VIEW_REMAPPED: + switch ((enum intel_gtt_view_type)0) { + case INTEL_GTT_VIEW_NORMAL: + case INTEL_GTT_VIEW_PARTIAL: + case INTEL_GTT_VIEW_ROTATED: + case INTEL_GTT_VIEW_REMAPPED: /* gcc complains if these are identical cases */ break; } @@ -231,11 +230,11 @@ struct i915_vma { /** * Support different GGTT views into the same object. * This means there can be multiple VMA mappings per object and per VM. - * i915_gtt_view_type is used to distinguish between those entries. - * The default one of zero (I915_GTT_VIEW_NORMAL) is default and also + * intel_gtt_view_type is used to distinguish between those entries. + * The default one of zero (INTEL_GTT_VIEW_NORMAL) is default and also * assumed in GEM functions which take no ggtt view parameter. */ - struct i915_gtt_view gtt_view; + struct intel_gtt_view gtt_view; /** This object's place on the active/inactive lists */ struct list_head vm_link; diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c index 7c4111e60f2e..fc068dab27f4 100644 --- a/drivers/gpu/drm/i915/selftests/i915_vma.c +++ b/drivers/gpu/drm/i915/selftests/i915_vma.c @@ -51,7 +51,7 @@ static bool assert_vma(struct i915_vma *vma, ok = false; } - if (vma->gtt_view.type != I915_GTT_VIEW_NORMAL) { + if (!intel_gtt_view_is_normal(&vma->gtt_view)) { pr_err("VMA created with wrong type [%d]\n", vma->gtt_view.type); ok = false; @@ -63,7 +63,7 @@ static bool assert_vma(struct i915_vma *vma, static struct i915_vma * checked_vma_instance(struct drm_i915_gem_object *obj, struct i915_address_space *vm, - const struct i915_gtt_view *view) + const struct intel_gtt_view *view) { struct i915_vma *vma; bool ok = true; @@ -533,12 +533,12 @@ assert_remapped(struct drm_i915_gem_object *obj, return sg; } -static unsigned int remapped_size(enum i915_gtt_view_type view_type, +static unsigned int remapped_size(const struct intel_gtt_view *view, const struct intel_remapped_plane_info *a, const struct intel_remapped_plane_info *b) { - if (view_type == I915_GTT_VIEW_ROTATED) + if (intel_gtt_view_is_rotated(view)) return a->dst_stride * a->width + b->dst_stride * b->width; else return a->dst_stride * a->height + b->dst_stride * b->height; @@ -572,9 +572,9 @@ static int igt_vma_rotate_remap(void *arg) { } }, *a, *b; - enum i915_gtt_view_type types[] = { - I915_GTT_VIEW_ROTATED, - I915_GTT_VIEW_REMAPPED, + enum intel_gtt_view_type types[] = { + INTEL_GTT_VIEW_ROTATED, + INTEL_GTT_VIEW_REMAPPED, 0, }, *t; const unsigned int max_pages = 64; @@ -592,7 +592,7 @@ static int igt_vma_rotate_remap(void *arg) for (t = types; *t; t++) { for (a = planes; a->width; a++) { for (b = planes + ARRAY_SIZE(planes); b-- != planes; ) { - struct i915_gtt_view view = { + struct intel_gtt_view view = { .type = *t, .remapped.plane[0] = *a, .remapped.plane[1] = *b, @@ -606,11 +606,11 @@ static int igt_vma_rotate_remap(void *arg) max_offset = max_pages - max_offset; if (!plane_info[0].dst_stride) - plane_info[0].dst_stride = view.type == I915_GTT_VIEW_ROTATED ? + plane_info[0].dst_stride = intel_gtt_view_is_rotated(&view) ? plane_info[0].height : plane_info[0].width; if (!plane_info[1].dst_stride) - plane_info[1].dst_stride = view.type == I915_GTT_VIEW_ROTATED ? + plane_info[1].dst_stride = intel_gtt_view_is_rotated(&view) ? plane_info[1].height : plane_info[1].width; @@ -632,9 +632,9 @@ static int igt_vma_rotate_remap(void *arg) goto out_object; } - expected_pages = remapped_size(view.type, &plane_info[0], &plane_info[1]); + expected_pages = remapped_size(&view, &plane_info[0], &plane_info[1]); - if (view.type == I915_GTT_VIEW_ROTATED && + if (intel_gtt_view_is_rotated(&view) && vma->size != expected_pages * PAGE_SIZE) { pr_err("VMA is wrong size, expected %lu, found %llu\n", PAGE_SIZE * expected_pages, vma->size); @@ -642,7 +642,7 @@ static int igt_vma_rotate_remap(void *arg) goto out_object; } - if (view.type == I915_GTT_VIEW_REMAPPED && + if (intel_gtt_view_is_remapped(&view) && vma->size > expected_pages * PAGE_SIZE) { pr_err("VMA is wrong size, expected %lu, found %llu\n", PAGE_SIZE * expected_pages, vma->size); @@ -672,13 +672,13 @@ static int igt_vma_rotate_remap(void *arg) sg = vma->pages->sgl; for (n = 0; n < ARRAY_SIZE(view.rotated.plane); n++) { - if (view.type == I915_GTT_VIEW_ROTATED) + if (intel_gtt_view_is_rotated(&view)) sg = assert_rotated(obj, &view.rotated, n, sg); else sg = assert_remapped(obj, &view.remapped, n, sg); if (IS_ERR(sg)) { pr_err("Inconsistent %s VMA pages for plane %d: [(%d, %d, %d, %d, %d), (%d, %d, %d, %d, %d)]\n", - view.type == I915_GTT_VIEW_ROTATED ? + intel_gtt_view_is_rotated(&view) ? "rotated" : "remapped", n, plane_info[0].width, plane_info[0].height, @@ -745,7 +745,7 @@ static bool assert_partial(struct drm_i915_gem_object *obj, } static bool assert_pin(struct i915_vma *vma, - struct i915_gtt_view *view, + struct intel_gtt_view *view, u64 size, const char *name) { @@ -763,7 +763,7 @@ static bool assert_pin(struct i915_vma *vma, ok = false; } - if (view && view->type != I915_GTT_VIEW_NORMAL) { + if (view && !intel_gtt_view_is_normal(view)) { if (memcmp(&vma->gtt_view, view, sizeof(*view))) { pr_err("(%s) VMA mismatch upon creation!\n", name); @@ -776,7 +776,7 @@ static bool assert_pin(struct i915_vma *vma, ok = false; } } else { - if (vma->gtt_view.type != I915_GTT_VIEW_NORMAL) { + if (!intel_gtt_view_is_normal(&vma->gtt_view)) { pr_err("Not the normal ggtt view! Found %d\n", vma->gtt_view.type); ok = false; @@ -823,14 +823,14 @@ static int igt_vma_partial(void *arg) nvma = 0; for_each_prime_number_from(sz, 1, npages) { for_each_prime_number_from(offset, 0, npages - sz) { - struct i915_gtt_view view; + struct intel_gtt_view view; - view.type = I915_GTT_VIEW_PARTIAL; + view.type = INTEL_GTT_VIEW_PARTIAL; view.partial.offset = offset; view.partial.size = sz; if (sz == npages) - view.type = I915_GTT_VIEW_NORMAL; + view.type = INTEL_GTT_VIEW_NORMAL; vma = checked_vma_instance(obj, vm, &view); if (IS_ERR(vma)) { @@ -981,9 +981,9 @@ static int igt_vma_remapped_gtt(void *arg) { } }, *p; - enum i915_gtt_view_type types[] = { - I915_GTT_VIEW_ROTATED, - I915_GTT_VIEW_REMAPPED, + enum intel_gtt_view_type types[] = { + INTEL_GTT_VIEW_ROTATED, + INTEL_GTT_VIEW_REMAPPED, 0, }, *t; struct drm_i915_gem_object *obj; @@ -1001,7 +1001,7 @@ static int igt_vma_remapped_gtt(void *arg) for (t = types; *t; t++) { for (p = planes; p->width; p++) { - struct i915_gtt_view view = { + struct intel_gtt_view view = { .type = *t, .rotated.plane[0] = *p, }; @@ -1017,7 +1017,7 @@ static int igt_vma_remapped_gtt(void *arg) goto out; if (!plane_info[0].dst_stride) - plane_info[0].dst_stride = *t == I915_GTT_VIEW_ROTATED ? + plane_info[0].dst_stride = intel_gtt_view_is_rotated(&view) ? p->height : p->width; vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, PIN_MAPPABLE); @@ -1040,7 +1040,7 @@ static int igt_vma_remapped_gtt(void *arg) unsigned int offset; u32 val = y << 16 | x; - if (*t == I915_GTT_VIEW_ROTATED) + if (intel_gtt_view_is_rotated(&view)) offset = (x * plane_info[0].dst_stride + y) * PAGE_SIZE; else offset = (y * plane_info[0].dst_stride + x) * PAGE_SIZE; @@ -1057,7 +1057,7 @@ static int igt_vma_remapped_gtt(void *arg) goto out; } - GEM_BUG_ON(vma->gtt_view.type != I915_GTT_VIEW_NORMAL); + GEM_BUG_ON(!intel_gtt_view_is_normal(&vma->gtt_view)); map = i915_vma_pin_iomap(vma); i915_vma_unpin(vma); @@ -1072,7 +1072,7 @@ static int igt_vma_remapped_gtt(void *arg) u32 exp = y << 16 | x; u32 val; - if (*t == I915_GTT_VIEW_ROTATED) + if (intel_gtt_view_is_rotated(&view)) src_idx = rotated_index(&view.rotated, 0, x, y); else src_idx = remapped_index(&view.remapped, 0, x, y); @@ -1081,7 +1081,7 @@ static int igt_vma_remapped_gtt(void *arg) val = ioread32(&map[offset / sizeof(*map)]); if (val != exp) { pr_err("%s VMA write test failed, expected 0x%x, found 0x%x\n", - *t == I915_GTT_VIEW_ROTATED ? "Rotated" : "Remapped", + intel_gtt_view_is_rotated(&view) ? "Rotated" : "Remapped", exp, val); i915_vma_unpin_iomap(vma); err = -EINVAL; diff --git a/drivers/gpu/drm/i915/selftests/igt_atomic.c b/drivers/gpu/drm/i915/selftests/igt_atomic.c index fb506b699095..8ae39cf570b7 100644 --- a/drivers/gpu/drm/i915/selftests/igt_atomic.c +++ b/drivers/gpu/drm/i915/selftests/igt_atomic.c @@ -39,7 +39,14 @@ static void __hardirq_end(void) local_irq_enable(); } +static void __maybe_unused __nop(void) +{} + const struct igt_atomic_section igt_atomic_phases[] = { +#if IS_ENABLED(CONFIG_PREEMPT_RT) + { "sleeping", __nop, __nop }, + { }, +#endif { "preempt", __preempt_begin, __preempt_end }, { "softirq", __softirq_begin, __softirq_end }, { "hardirq", __hardirq_begin, __hardirq_end }, diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.c b/drivers/gpu/drm/i915/vlv_iosf_sb.c index 1f0332b4ad0d..fede1735bc08 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.c +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.c @@ -3,6 +3,8 @@ * Copyright © 2013-2021 Intel Corporation */ +#include + #include #include @@ -101,7 +103,7 @@ static int vlv_sideband_rw(struct drm_i915_private *i915, VLV_IOSF_DOORBELL_REQ, IOSF_SB_BUSY, 0, 5)) { drm_dbg(&i915->drm, "IOSF sideband idle wait (%s) timed out\n", - is_read ? "read" : "write"); + str_read_write(is_read)); return -EAGAIN; } @@ -125,7 +127,7 @@ static int vlv_sideband_rw(struct drm_i915_private *i915, err = 0; } else { drm_dbg(&i915->drm, "IOSF sideband finish wait (%s) timed out\n", - is_read ? "read" : "write"); + str_read_write(is_read)); err = -ETIMEDOUT; } diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 0670a3f08ec8..563c2f859361 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -260,6 +260,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_ddi.o \ i915-display/intel_ddi_buf_trans.o \ i915-display/intel_de.o \ + i915-display/intel_dip.o \ i915-display/intel_display.o \ i915-display/intel_display_conversion.o \ i915-display/intel_display_device.o \ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_config.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_config.h deleted file mode 100644 index d4522203e2dd..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/i915_config.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#ifndef __I915_CONFIG_H__ -#define __I915_CONFIG_H__ - -#include - -static inline unsigned long i915_fence_timeout(void) -{ - return MAX_SCHEDULE_TIMEOUT; -} - -#endif /* __I915_CONFIG_H__ */ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_gtt_view_types.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_gtt_view_types.h deleted file mode 100644 index b261910cd6f9..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/i915_gtt_view_types.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* Copyright © 2025 Intel Corporation */ - -#include "../../i915/i915_gtt_view_types.h" - -/* Partial view not supported in xe, fail build if used. */ -#define I915_GTT_VIEW_PARTIAL diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 7b25c0814674..506f26e9c59a 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -6,31 +6,23 @@ #include "xe_display.h" #include "regs/xe_irq_regs.h" -#include +#include -#include -#include #include #include -#include #include #include -#include -#include "intel_acpi.h" #include "intel_display.h" #include "intel_display_core.h" #include "intel_display_device.h" #include "intel_display_driver.h" #include "intel_display_irq.h" -#include "intel_display_types.h" #include "intel_dmc.h" #include "intel_dmc_wl.h" -#include "intel_dp.h" #include "intel_fbdev.h" #include "intel_hotplug.h" #include "intel_opregion.h" -#include "skl_watermark.h" #include "xe_device.h" #include "xe_display_bo.h" #include "xe_display_pcode.h" diff --git a/drivers/gpu/drm/xe/display/xe_display_rpm.c b/drivers/gpu/drm/xe/display/xe_display_rpm.c index 548b503aa024..57bcfb41bdda 100644 --- a/drivers/gpu/drm/xe/display/xe_display_rpm.c +++ b/drivers/gpu/drm/xe/display/xe_display_rpm.c @@ -45,6 +45,11 @@ static bool xe_display_rpm_suspended(const struct drm_device *drm) return pm_runtime_suspended(xe->drm.dev); } +static bool xe_display_rpm_pme_enabled(const struct drm_device *drm) +{ + return xe_pm_pme_enabled(to_xe_device(drm)); +} + static void xe_display_rpm_assert_held(const struct drm_device *drm) { /* FIXME */ @@ -69,6 +74,7 @@ const struct intel_display_rpm_interface xe_display_rpm_interface = { .put_raw = xe_display_rpm_put, .put_unchecked = xe_display_rpm_put_unchecked, .suspended = xe_display_rpm_suspended, + .pme_enabled = xe_display_rpm_pme_enabled, .assert_held = xe_display_rpm_assert_held, .assert_block = xe_display_rpm_assert_block, .assert_unblock = xe_display_rpm_assert_unblock diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index b46a2c32ac07..15fbd3fe6cbb 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -4,11 +4,9 @@ */ #include +#include #include -/* FIXME move the types to parent interface? */ -#include "i915_gtt_view_types.h" - /* FIXME move intel_remapped_info_size() & co. to parent interface? */ #include "intel_fb.h" @@ -150,13 +148,13 @@ static int __xe_pin_fb_vma_dpt(struct drm_gem_object *obj, struct xe_device *xe = to_xe_device(obj->dev); struct xe_tile *tile0 = xe_device_get_root_tile(xe); struct xe_ggtt *ggtt = tile0->mem.ggtt; - const struct i915_gtt_view *view = pin_params->view; + const struct intel_gtt_view *view = pin_params->view; struct xe_bo *bo = gem_to_xe_bo(obj), *dpt; u32 dpt_size, size = bo->ttm.base.size; - if (view->type == I915_GTT_VIEW_NORMAL) + if (intel_gtt_view_is_normal(view)) dpt_size = ALIGN(size / XE_PAGE_SIZE * 8, XE_PAGE_SIZE); - else if (view->type == I915_GTT_VIEW_REMAPPED) + else if (intel_gtt_view_is_remapped(view)) dpt_size = ALIGN(intel_remapped_info_size(&view->remapped) * 8, XE_PAGE_SIZE); else @@ -175,7 +173,7 @@ static int __xe_pin_fb_vma_dpt(struct drm_gem_object *obj, if (IS_ERR(dpt)) return PTR_ERR(dpt); - if (view->type == I915_GTT_VIEW_NORMAL) { + if (intel_gtt_view_is_normal(view)) { u64 pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe_cache_pat_idx(xe, XE_CACHE_NONE)); u32 x; @@ -184,7 +182,7 @@ static int __xe_pin_fb_vma_dpt(struct drm_gem_object *obj, iosys_map_wr(&dpt->vmap, x * 8, u64, pte | addr); } - } else if (view->type == I915_GTT_VIEW_REMAPPED) { + } else if (intel_gtt_view_is_remapped(view)) { write_dpt_remapped(bo, &view->remapped, &dpt->vmap); } else { const struct intel_rotation_info *rot_info = &view->rotated; @@ -233,7 +231,7 @@ write_ggtt_rotated(struct xe_ggtt *ggtt, u32 *ggtt_ofs, } struct fb_rotate_args { - const struct i915_gtt_view *view; + const struct intel_gtt_view *view; struct xe_bo *bo; }; @@ -258,7 +256,7 @@ static int __xe_pin_fb_vma_ggtt(struct drm_gem_object *obj, const struct intel_fb_pin_params *pin_params, struct i915_vma *vma) { - const struct i915_gtt_view *view = pin_params->view; + const struct intel_gtt_view *view = pin_params->view; struct xe_bo *bo = gem_to_xe_bo(obj); struct xe_device *xe = to_xe_device(obj->dev); struct xe_tile *tile0 = xe_device_get_root_tile(xe); @@ -277,7 +275,7 @@ static int __xe_pin_fb_vma_ggtt(struct drm_gem_object *obj, align = max(align, SZ_64K); /* Fast case, preallocated GGTT view? */ - if (bo->ggtt_node[tile0->id] && view->type == I915_GTT_VIEW_NORMAL) { + if (bo->ggtt_node[tile0->id] && intel_gtt_view_is_normal(view)) { vma->node = bo->ggtt_node[tile0->id]; return 0; } @@ -285,7 +283,7 @@ static int __xe_pin_fb_vma_ggtt(struct drm_gem_object *obj, /* TODO: Consider sharing framebuffer mapping? * embed i915_vma inside intel_framebuffer */ - if (view->type == I915_GTT_VIEW_NORMAL) + if (intel_gtt_view_is_normal(view)) size = xe_bo_size(bo); else /* display uses tiles instead of bytes here, so convert it back.. */ @@ -294,7 +292,7 @@ static int __xe_pin_fb_vma_ggtt(struct drm_gem_object *obj, pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe_cache_pat_idx(xe, XE_CACHE_NONE)); vma->node = xe_ggtt_insert_node_transform(ggtt, bo, pte, ALIGN(size, align), align, - view->type == I915_GTT_VIEW_NORMAL ? + intel_gtt_view_is_normal(view) ? NULL : write_ggtt_rotated_node, &(struct fb_rotate_args){view, bo}); if (IS_ERR(vma->node)) @@ -459,9 +457,9 @@ static void xe_fb_pin_dpt_unpin(struct intel_dpt *dpt, static struct i915_vma * xe_fb_pin_reuse_vma(struct i915_vma *old_ggtt_vma, struct drm_gem_object *old_obj, - const struct i915_gtt_view *old_view, + const struct intel_gtt_view *old_view, struct drm_gem_object *new_obj, - const struct i915_gtt_view *new_view, + const struct intel_gtt_view *new_view, u32 *out_offset) { if (old_ggtt_vma && old_obj == new_obj && diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 4e0e1bc040c1..41f703a87916 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -466,6 +466,19 @@ struct xe_device { struct mutex lock; } d3cold; + /** @pme: Encapsulate pme related stuff */ + struct { + /** @pme.capable: Indicates if device is PME capable */ + bool capable; + + /** @pme.enabled: + * + * Indicates if PME is enabled - depends on user controllable + * sysfs interface as well + */ + bool enabled; + } pme; + /** @pm_notifier: Our PM notifier to perform actions in response to various PM events. */ struct notifier_block pm_notifier; /** @pm_block: Completion to block validating tasks on suspend / hibernate prepare */ diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index e44b74b9aa27..50e4920e8e08 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -1384,6 +1384,8 @@ static int xe_pci_runtime_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct xe_device *xe = pdev_to_xe_device(pdev); + unsigned int flags; + bool pme_enabled; int err, ret; /* @@ -1395,9 +1397,25 @@ static int xe_pci_runtime_suspend(struct device *dev) xe_assert(xe, !IS_SRIOV_VF(xe)); xe_assert(xe, !pci_num_vf(pdev)); + flags = memalloc_noreclaim_save(); + pme_enabled = xe->pme.capable && !xe->d3cold.allowed && + pci_enable_wake(pdev, PCI_D3hot, true) == 0; + memalloc_noreclaim_restore(flags); + + xe_pm_update_pme_enabled(xe, pme_enabled); + err = xe_pm_runtime_suspend(xe); - if (err) + if (err) { + if (pme_enabled) { + flags = memalloc_noreclaim_save(); + pci_enable_wake(pdev, PCI_D3hot, false); + memalloc_noreclaim_restore(flags); + + xe_pm_update_pme_enabled(xe, false); + } + return err; + } err = xe_pm_wait_all_c6(xe); if (err) { @@ -1437,6 +1455,8 @@ static int xe_pci_runtime_resume(struct device *dev) pci_restore_state(pdev); + xe_pm_update_pme_enabled(xe, false); + if (xe->d3cold.allowed) { err = pci_enable_device(pdev); if (err) diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c index 4a745c3a933b..daa7ba2df317 100644 --- a/drivers/gpu/drm/xe/xe_pm.c +++ b/drivers/gpu/drm/xe/xe_pm.c @@ -78,6 +78,8 @@ * management (RPS). */ +#define HAS_PM_PME_SUPPORT(xe) (GRAPHICS_VERx100(xe) >= 3500) + #ifdef CONFIG_LOCKDEP static struct lockdep_map xe_pm_runtime_d3cold_map = { .name = "xe_rpm_d3cold_map" @@ -384,6 +386,14 @@ int xe_pm_init_early(struct xe_device *xe) } ALLOW_ERROR_INJECTION(xe_pm_init_early, ERRNO); /* See xe_pci_probe() */ +static bool xe_pm_pci_pme_capable(struct xe_device *xe) +{ + struct pci_dev *pdev = to_pci_dev(xe->drm.dev); + + return HAS_PM_PME_SUPPORT(xe) ? + pci_pme_capable(pdev, PCI_D3hot) : false; +} + /** * xe_pm_probe() - Initialize Xe Power Management * @xe: the &xe_device instance @@ -397,6 +407,16 @@ int xe_pm_probe(struct xe_device *xe) xe->d3cold.capable = xe_pm_pci_d3cold_capable(xe); xe_dbg(xe, "d3cold: capable=%s\n", str_yes_no(xe->d3cold.capable)); + xe->pme.capable = xe_pm_pci_pme_capable(xe); + xe_dbg(xe, "pme: capable=%s\n", str_yes_no(xe->pme.capable)); + + if (xe->pme.capable) { + int err = devm_device_init_wakeup(xe->drm.dev); + + if (err) + return err; + } + return 0; } @@ -650,6 +670,7 @@ int xe_pm_runtime_suspend(struct xe_device *xe) return 0; out_resume: + xe_pm_update_pme_enabled(xe, false); xe_display_pm_runtime_resume(xe); xe_pxp_pm_resume(xe->pxp); out: @@ -993,6 +1014,30 @@ int xe_pm_set_vram_threshold(struct xe_device *xe, u32 threshold) return 0; } +/** + * xe_pm_pme_enabled - get the current status of PME enabled + * @xe: xe device instance + * + * Returns: True if PME is enabled, false otherwise. + */ +bool xe_pm_pme_enabled(struct xe_device *xe) +{ + return xe->pme.enabled; +} + +/** + * xe_pm_update_pme_enabled - Update the PME enabled state + * @xe: xe device instance + * @status: New PME enabled status + * + * Called during runtime suspend / resume. Status is set to True if PME is + * enabled during runtime_suspend. Cleared on runtime_resume. + */ +void xe_pm_update_pme_enabled(struct xe_device *xe, bool status) +{ + xe->pme.enabled = status; +} + /** * xe_pm_d3cold_allowed_toggle - Check conditions to toggle d3cold.allowed * @xe: xe device instance diff --git a/drivers/gpu/drm/xe/xe_pm.h b/drivers/gpu/drm/xe/xe_pm.h index fd8b2eab5de9..16d4e6c629f1 100644 --- a/drivers/gpu/drm/xe/xe_pm.h +++ b/drivers/gpu/drm/xe/xe_pm.h @@ -33,6 +33,8 @@ bool xe_pm_runtime_resume_and_get(struct xe_device *xe); void xe_pm_assert_unbounded_bridge(struct xe_device *xe); int xe_pm_set_vram_threshold(struct xe_device *xe, u32 threshold); void xe_pm_d3cold_allowed_toggle(struct xe_device *xe); +bool xe_pm_pme_enabled(struct xe_device *xe); +void xe_pm_update_pme_enabled(struct xe_device *xe, bool status); bool xe_rpm_reclaim_safe(const struct xe_device *xe); struct task_struct *xe_pm_read_callback_task(struct xe_device *xe); int xe_pm_block_on_suspend(struct xe_device *xe); diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h index 5e44c022d1ae..464fb588cb60 100644 --- a/include/drm/intel/display_parent_interface.h +++ b/include/drm/intel/display_parent_interface.h @@ -16,11 +16,11 @@ struct drm_mode_fb_cmd2; struct drm_plane_state; struct drm_scanout_buffer; struct fb_info; -struct i915_gtt_view; struct i915_vma; struct intel_dpt; struct intel_dsb_buffer; struct intel_frontbuffer; +struct intel_gtt_view; struct intel_hdcp_gsc_context; struct intel_initial_plane_config; struct intel_panic; @@ -31,7 +31,7 @@ struct seq_file; struct vm_area_struct; struct intel_fb_pin_params { - const struct i915_gtt_view *view; + const struct intel_gtt_view *view; unsigned int alignment; unsigned int phys_alignment; unsigned int vtd_guard; @@ -101,9 +101,9 @@ struct intel_display_fb_pin_interface { struct i915_vma *ggtt_vma); struct i915_vma *(*reuse_vma)(struct i915_vma *old_ggtt_vma, struct drm_gem_object *old_obj, - const struct i915_gtt_view *old_view, + const struct intel_gtt_view *old_view, struct drm_gem_object *new_obj, - const struct i915_gtt_view *new_view, + const struct intel_gtt_view *new_view, u32 *out_offset); void (*get_map)(struct i915_vma *vma, struct iosys_map *map); }; @@ -196,6 +196,7 @@ struct intel_display_rpm_interface { void (*put_unchecked)(const struct drm_device *drm); bool (*suspended)(const struct drm_device *drm); + bool (*pme_enabled)(const struct drm_device *drm); /* Optional */ void (*assert_held)(const struct drm_device *drm); void (*assert_block)(const struct drm_device *drm); void (*assert_unblock)(const struct drm_device *drm); diff --git a/include/drm/intel/gtt_view_types.h b/include/drm/intel/gtt_view_types.h new file mode 100644 index 000000000000..128392d98f3a --- /dev/null +++ b/include/drm/intel/gtt_view_types.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2025 Intel Corporation */ + +#ifndef __DRM_INTEL_GTT_VIEW_TYPES_H__ +#define __DRM_INTEL_GTT_VIEW_TYPES_H__ + +#include + +struct intel_remapped_plane_info { + /* in gtt pages */ + u32 offset:31; + u32 linear:1; + union { + /* in gtt pages for !linear */ + struct { + u16 width; + u16 height; + u16 src_stride; + u16 dst_stride; + }; + + /* in gtt pages for linear */ + u32 size; + }; +} __packed; + +struct intel_rotation_info { + struct intel_remapped_plane_info plane[2]; +} __packed; + +struct intel_partial_info { + u64 offset; + unsigned int size; +} __packed; + +struct intel_remapped_info { + struct intel_remapped_plane_info plane[4]; + /* in gtt pages */ + u32 plane_alignment; +} __packed; + +enum intel_gtt_view_type { + INTEL_GTT_VIEW_NORMAL = 0, + INTEL_GTT_VIEW_ROTATED = sizeof(struct intel_rotation_info), + INTEL_GTT_VIEW_PARTIAL = sizeof(struct intel_partial_info), + INTEL_GTT_VIEW_REMAPPED = sizeof(struct intel_remapped_info), +}; + +struct intel_gtt_view { + enum intel_gtt_view_type type; + union { + /* Members need to contain no holes/padding */ + struct intel_partial_info partial; + struct intel_rotation_info rotated; + struct intel_remapped_info remapped; + }; +}; + +static inline bool intel_gtt_view_is_normal(const struct intel_gtt_view *view) +{ + return view->type == INTEL_GTT_VIEW_NORMAL; +} + +static inline bool intel_gtt_view_is_remapped(const struct intel_gtt_view *view) +{ + return view->type == INTEL_GTT_VIEW_REMAPPED; +} + +static inline bool intel_gtt_view_is_rotated(const struct intel_gtt_view *view) +{ + return view->type == INTEL_GTT_VIEW_ROTATED; +} + +static inline bool intel_gtt_view_is_partial(const struct intel_gtt_view *view) +{ + return view->type == INTEL_GTT_VIEW_PARTIAL; +} + +#endif /* __DRM_INTEL_GTT_VIEW_TYPES_H__ */