Commit 3170244b authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'drm-fixes-2025-09-26' of https://gitlab.freedesktop.org/drm/kernel

Pull drm fixes from Dave Airlie:
 "Weekly fixes, some fbcon font handling fixes, then amdgpu/xe/i915 with
  a few, and a few misc fixes for other drivers. Seems about right for
  this stage, and I don't know of anything outstanding.

  fbcon:
   - fix OOB access in font allocation
   - fix integer overflow in font handling

  amdgpu:
   - Backlight fix
   - DC preblend fix
   - DCN 3.5 fix
   - Cleanup output_tf_change

  xe:
   - Don't expose sysfs attributes not applicable for VFs
   - Fix build with CONFIG_MODULES=n
   - Don't copy pinned kernel bos twice on suspend

  i915:
   - Set O_LARGEFILE in __create_shmem()
   - Guard reg_val against a INVALID_TRANSCODER [ddi]

  ast:
   - sleeps causing cpu stall fix

  panthor:
   - scheduler race condition fix

  gma500:
   - NULL ptr deref in hdmi teardown fix"

* tag 'drm-fixes-2025-09-26' of https://gitlab.freedesktop.org/drm/kernel:
  drm/panthor: Defer scheduler entitiy destruction to queue release
  drm/amd/display: remove output_tf_change flag
  drm/amd/display: Init DCN35 clocks from pre-os HW values
  drm/amd/display: Use mpc.preblend flag to indicate preblend
  drm/amd/display: Only restore backlight after amdgpu_dm_init or dm_resume
  fbcon: Fix OOB access in font allocation
  drm/i915/ddi: Guard reg_val against a INVALID_TRANSCODER
  drm/i915: set O_LARGEFILE in __create_shmem()
  drm/xe: Don't copy pinned kernel bos twice on suspend
  drm/xe: Fix build with CONFIG_MODULES=n
  drm/xe/vf: Don't expose sysfs attributes not applicable for VFs
  fbcon: fix integer overflow in fbcon_do_set_font
  drm/gma500: Fix null dereference in hdmi teardown
  drm/ast: Use msleep instead of mdelay for edid read
parents 4ff71af0 ec73e598
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -2037,6 +2037,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)

	dc_hardware_init(adev->dm.dc);

	adev->dm.restore_backlight = true;

	adev->dm.hpd_rx_offload_wq = hpd_rx_irq_create_workqueue(adev);
	if (!adev->dm.hpd_rx_offload_wq) {
		drm_err(adev_to_drm(adev), "failed to create hpd rx offload workqueue.\n");
@@ -3399,6 +3401,7 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
		dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0);

		dc_resume(dm->dc);
		adev->dm.restore_backlight = true;

		amdgpu_dm_irq_resume_early(adev);

@@ -9829,7 +9832,6 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_state *state,
	bool mode_set_reset_required = false;
	u32 i;
	struct dc_commit_streams_params params = {dc_state->streams, dc_state->stream_count};
	bool set_backlight_level = false;

	/* Disable writeback */
	for_each_old_connector_in_state(state, connector, old_con_state, i) {
@@ -9949,7 +9951,6 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_state *state,
			acrtc->hw_mode = new_crtc_state->mode;
			crtc->hwmode = new_crtc_state->mode;
			mode_set_reset_required = true;
			set_backlight_level = true;
		} else if (modereset_required(new_crtc_state)) {
			drm_dbg_atomic(dev,
				       "Atomic commit: RESET. crtc id %d:[%p]\n",
@@ -10006,13 +10007,16 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_state *state,
	 * to fix a flicker issue.
	 * It will cause the dm->actual_brightness is not the current panel brightness
	 * level. (the dm->brightness is the correct panel level)
	 * So we set the backlight level with dm->brightness value after set mode
	 * So we set the backlight level with dm->brightness value after initial
	 * set mode. Use restore_backlight flag to avoid setting backlight level
	 * for every subsequent mode set.
	 */
	if (set_backlight_level) {
	if (dm->restore_backlight) {
		for (i = 0; i < dm->num_of_edps; i++) {
			if (dm->backlight_dev[i])
				amdgpu_dm_backlight_set_level(dm, i, dm->brightness[i]);
		}
		dm->restore_backlight = false;
	}
}

+7 −0
Original line number Diff line number Diff line
@@ -610,6 +610,13 @@ struct amdgpu_display_manager {
	 */
	u32 actual_brightness[AMDGPU_DM_MAX_NUM_EDP];

	/**
	 * @restore_backlight:
	 *
	 * Flag to indicate whether to restore backlight after modeset.
	 */
	bool restore_backlight;

	/**
	 * @aux_hpd_discon_quirk:
	 *
+1 −1
Original line number Diff line number Diff line
@@ -821,7 +821,7 @@ int amdgpu_dm_verify_lut3d_size(struct amdgpu_device *adev,
	struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
	const struct drm_color_lut *shaper = NULL, *lut3d = NULL;
	uint32_t exp_size, size, dim_size = MAX_COLOR_3DLUT_SIZE;
	bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut;
	bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut || adev->dm.dc->caps.color.mpc.preblend;

	/* shaper LUT is only available if 3D LUT color caps */
	exp_size = has_3dlut ? MAX_COLOR_LUT_ENTRIES : 0;
+1 −1
Original line number Diff line number Diff line
@@ -1633,7 +1633,7 @@ dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
		drm_object_attach_property(&plane->base,
					   dm->adev->mode_info.plane_ctm_property, 0);

	if (dpp_color_caps.hw_3d_lut) {
	if (dpp_color_caps.hw_3d_lut || dm->dc->caps.color.mpc.preblend) {
		drm_object_attach_property(&plane->base,
					   mode_info.plane_shaper_lut_property, 0);
		drm_object_attach_property(&plane->base,
+119 −2
Original line number Diff line number Diff line
@@ -587,9 +587,118 @@ bool dcn35_are_clock_states_equal(struct dc_clocks *a,
	return true;
}

static void dcn35_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
static void dcn35_save_clk_registers_internal(struct dcn35_clk_internal *internal, struct clk_mgr *clk_mgr_base)
{
	struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);

	// read dtbclk
	internal->CLK1_CLK4_CURRENT_CNT = REG_READ(CLK1_CLK4_CURRENT_CNT);
	internal->CLK1_CLK4_BYPASS_CNTL = REG_READ(CLK1_CLK4_BYPASS_CNTL);

	// read dcfclk
	internal->CLK1_CLK3_CURRENT_CNT = REG_READ(CLK1_CLK3_CURRENT_CNT);
	internal->CLK1_CLK3_BYPASS_CNTL = REG_READ(CLK1_CLK3_BYPASS_CNTL);

	// read dcf deep sleep divider
	internal->CLK1_CLK3_DS_CNTL = REG_READ(CLK1_CLK3_DS_CNTL);
	internal->CLK1_CLK3_ALLOW_DS = REG_READ(CLK1_CLK3_ALLOW_DS);

	// read dppclk
	internal->CLK1_CLK1_CURRENT_CNT = REG_READ(CLK1_CLK1_CURRENT_CNT);
	internal->CLK1_CLK1_BYPASS_CNTL = REG_READ(CLK1_CLK1_BYPASS_CNTL);

	// read dprefclk
	internal->CLK1_CLK2_CURRENT_CNT = REG_READ(CLK1_CLK2_CURRENT_CNT);
	internal->CLK1_CLK2_BYPASS_CNTL = REG_READ(CLK1_CLK2_BYPASS_CNTL);

	// read dispclk
	internal->CLK1_CLK0_CURRENT_CNT = REG_READ(CLK1_CLK0_CURRENT_CNT);
	internal->CLK1_CLK0_BYPASS_CNTL = REG_READ(CLK1_CLK0_BYPASS_CNTL);
}

static void dcn35_save_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
		struct clk_mgr_dcn35 *clk_mgr)
{
	struct dcn35_clk_internal internal = {0};
	char *bypass_clks[5] = {"0x0 DFS", "0x1 REFCLK", "0x2 ERROR", "0x3 400 FCH", "0x4 600 FCH"};

	dcn35_save_clk_registers_internal(&internal, &clk_mgr->base.base);

	regs_and_bypass->dcfclk = internal.CLK1_CLK3_CURRENT_CNT / 10;
	regs_and_bypass->dcf_deep_sleep_divider = internal.CLK1_CLK3_DS_CNTL / 10;
	regs_and_bypass->dcf_deep_sleep_allow = internal.CLK1_CLK3_ALLOW_DS;
	regs_and_bypass->dprefclk = internal.CLK1_CLK2_CURRENT_CNT / 10;
	regs_and_bypass->dispclk = internal.CLK1_CLK0_CURRENT_CNT / 10;
	regs_and_bypass->dppclk = internal.CLK1_CLK1_CURRENT_CNT / 10;
	regs_and_bypass->dtbclk = internal.CLK1_CLK4_CURRENT_CNT / 10;

	regs_and_bypass->dppclk_bypass = internal.CLK1_CLK1_BYPASS_CNTL & 0x0007;
	if (regs_and_bypass->dppclk_bypass < 0 || regs_and_bypass->dppclk_bypass > 4)
		regs_and_bypass->dppclk_bypass = 0;
	regs_and_bypass->dcfclk_bypass = internal.CLK1_CLK3_BYPASS_CNTL & 0x0007;
	if (regs_and_bypass->dcfclk_bypass < 0 || regs_and_bypass->dcfclk_bypass > 4)
		regs_and_bypass->dcfclk_bypass = 0;
	regs_and_bypass->dispclk_bypass = internal.CLK1_CLK0_BYPASS_CNTL & 0x0007;
	if (regs_and_bypass->dispclk_bypass < 0 || regs_and_bypass->dispclk_bypass > 4)
		regs_and_bypass->dispclk_bypass = 0;
	regs_and_bypass->dprefclk_bypass = internal.CLK1_CLK2_BYPASS_CNTL & 0x0007;
	if (regs_and_bypass->dprefclk_bypass < 0 || regs_and_bypass->dprefclk_bypass > 4)
		regs_and_bypass->dprefclk_bypass = 0;

	if (clk_mgr->base.base.ctx->dc->debug.pstate_enabled) {
		DC_LOG_SMU("clk_type,clk_value,deepsleep_cntl,deepsleep_allow,bypass\n");

		DC_LOG_SMU("dcfclk,%d,%d,%d,%s\n",
				   regs_and_bypass->dcfclk,
				   regs_and_bypass->dcf_deep_sleep_divider,
				   regs_and_bypass->dcf_deep_sleep_allow,
				   bypass_clks[(int) regs_and_bypass->dcfclk_bypass]);

		DC_LOG_SMU("dprefclk,%d,N/A,N/A,%s\n",
			regs_and_bypass->dprefclk,
			bypass_clks[(int) regs_and_bypass->dprefclk_bypass]);

		DC_LOG_SMU("dispclk,%d,N/A,N/A,%s\n",
			regs_and_bypass->dispclk,
			bypass_clks[(int) regs_and_bypass->dispclk_bypass]);

		// REGISTER VALUES
		DC_LOG_SMU("reg_name,value,clk_type");

		DC_LOG_SMU("CLK1_CLK3_CURRENT_CNT,%d,dcfclk",
				internal.CLK1_CLK3_CURRENT_CNT);

		DC_LOG_SMU("CLK1_CLK4_CURRENT_CNT,%d,dtbclk",
					internal.CLK1_CLK4_CURRENT_CNT);

		DC_LOG_SMU("CLK1_CLK3_DS_CNTL,%d,dcf_deep_sleep_divider",
					internal.CLK1_CLK3_DS_CNTL);

		DC_LOG_SMU("CLK1_CLK3_ALLOW_DS,%d,dcf_deep_sleep_allow",
					internal.CLK1_CLK3_ALLOW_DS);

		DC_LOG_SMU("CLK1_CLK2_CURRENT_CNT,%d,dprefclk",
					internal.CLK1_CLK2_CURRENT_CNT);

		DC_LOG_SMU("CLK1_CLK0_CURRENT_CNT,%d,dispclk",
					internal.CLK1_CLK0_CURRENT_CNT);

		DC_LOG_SMU("CLK1_CLK1_CURRENT_CNT,%d,dppclk",
					internal.CLK1_CLK1_CURRENT_CNT);

		DC_LOG_SMU("CLK1_CLK3_BYPASS_CNTL,%d,dcfclk_bypass",
					internal.CLK1_CLK3_BYPASS_CNTL);

		DC_LOG_SMU("CLK1_CLK2_BYPASS_CNTL,%d,dprefclk_bypass",
					internal.CLK1_CLK2_BYPASS_CNTL);

		DC_LOG_SMU("CLK1_CLK0_BYPASS_CNTL,%d,dispclk_bypass",
					internal.CLK1_CLK0_BYPASS_CNTL);

		DC_LOG_SMU("CLK1_CLK1_BYPASS_CNTL,%d,dppclk_bypass",
					internal.CLK1_CLK1_BYPASS_CNTL);

	}
}

static bool dcn35_is_spll_ssc_enabled(struct clk_mgr *clk_mgr_base)
@@ -623,6 +732,7 @@ static void init_clk_states(struct clk_mgr *clk_mgr)
void dcn35_init_clocks(struct clk_mgr *clk_mgr)
{
	struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr);
	struct clk_mgr_dcn35 *clk_mgr_dcn35 = TO_CLK_MGR_DCN35(clk_mgr_int);

	init_clk_states(clk_mgr);

@@ -633,6 +743,13 @@ void dcn35_init_clocks(struct clk_mgr *clk_mgr)
	else
		clk_mgr->dp_dto_source_clock_in_khz = clk_mgr->dprefclk_khz;

	dcn35_save_clk_registers(&clk_mgr->boot_snapshot, clk_mgr_dcn35);

	clk_mgr->clks.ref_dtbclk_khz =  clk_mgr->boot_snapshot.dtbclk * 10;
	if (clk_mgr->boot_snapshot.dtbclk > 59000) {
		/*dtbclk enabled based on */
		clk_mgr->clks.dtbclk_en = true;
	}
}
static struct clk_bw_params dcn35_bw_params = {
	.vram_type = Ddr4MemType,
@@ -1323,7 +1440,7 @@ void dcn35_clk_mgr_construct(
		dcn35_bw_params.wm_table = ddr5_wm_table;
	}
	/* Saved clocks configured at boot for debug purposes */
	dcn35_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, clk_mgr);
	dcn35_save_clk_registers(&clk_mgr->base.base.boot_snapshot, clk_mgr);

	clk_mgr->base.base.dprefclk_khz = dcn35_smu_get_dprefclk(&clk_mgr->base);
	clk_mgr->base.base.clks.ref_dtbclk_khz = 600000;
Loading