Commit fddb4fd9 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'mediatek-drm-fixes-20250104' of...

Merge tag 'mediatek-drm-fixes-20250104' of https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux

 into drm-fixes

Mediatek DRM Fixes - 20250104

1. Revert "drm/mediatek: dsi: Correct calculation formula of PHY Timing"
2. Set private->all_drm_private[i]->drm to NULL if mtk_drm_bind returns err
3. Move mtk_crtc_finish_page_flip() to ddp_cmdq_cb()
4. Only touch DISP_REG_OVL_PITCH_MSB if AFBC is supported
5. Add support for 180-degree rotation in the display driver
6. Stop selecting foreign drivers
7. Revert "drm/mediatek: Switch to for_each_child_of_node_scoped()"
8. Fix YCbCr422 color format issue for DP
9. Fix mode valid issue for dp
10. dp: Reference common DAI properties
11. dsi: Add registers to pdata to fix MT8186/MT8188
12. Remove unneeded semicolon
13. Add return value check when reading DPCD
14. Initialize pointer in mtk_drm_of_ddp_path_build_one()

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Chun-Kuang Hu <chunkuang.hu@kernel.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20250104124227.45505-1-chunkuang.hu@kernel.org
parents 85bf89f2 f563dd9c
Loading
Loading
Loading
Loading
+18 −1
Original line number Diff line number Diff line
@@ -42,6 +42,9 @@ properties:
  interrupts:
    maxItems: 1

  '#sound-dai-cells':
    const: 0

  ports:
    $ref: /schemas/graph.yaml#/properties/ports
    properties:
@@ -85,7 +88,21 @@ required:
  - ports
  - max-linkrate-mhz

additionalProperties: false
allOf:
  - $ref: /schemas/sound/dai-common.yaml#
  - if:
      not:
        properties:
          compatible:
            contains:
              enum:
                - mediatek,mt8188-dp-tx
                - mediatek,mt8195-dp-tx
    then:
      properties:
        '#sound-dai-cells': false

unevaluatedProperties: false

examples:
  - |
+0 −5
Original line number Diff line number Diff line
@@ -14,9 +14,6 @@ config DRM_MEDIATEK
	select DRM_BRIDGE_CONNECTOR
	select DRM_MIPI_DSI
	select DRM_PANEL
	select MEMORY
	select MTK_SMI
	select PHY_MTK_MIPI_DSI
	select VIDEOMODE_HELPERS
	help
	  Choose this option if you have a Mediatek SoCs.
@@ -27,7 +24,6 @@ config DRM_MEDIATEK
config DRM_MEDIATEK_DP
	tristate "DRM DPTX Support for MediaTek SoCs"
	depends on DRM_MEDIATEK
	select PHY_MTK_DP
	select DRM_DISPLAY_HELPER
	select DRM_DISPLAY_DP_HELPER
	select DRM_DISPLAY_DP_AUX_BUS
@@ -38,6 +34,5 @@ config DRM_MEDIATEK_HDMI
	tristate "DRM HDMI Support for Mediatek SoCs"
	depends on DRM_MEDIATEK
	select SND_SOC_HDMI_CODEC if SND_SOC
	select PHY_MTK_HDMI
	help
	  DRM/KMS HDMI driver for Mediatek SoCs
+19 −6
Original line number Diff line number Diff line
@@ -112,6 +112,11 @@ static void mtk_drm_finish_page_flip(struct mtk_crtc *mtk_crtc)

	drm_crtc_handle_vblank(&mtk_crtc->base);

#if IS_REACHABLE(CONFIG_MTK_CMDQ)
	if (mtk_crtc->cmdq_client.chan)
		return;
#endif

	spin_lock_irqsave(&mtk_crtc->config_lock, flags);
	if (!mtk_crtc->config_updating && mtk_crtc->pending_needs_vblank) {
		mtk_crtc_finish_page_flip(mtk_crtc);
@@ -284,10 +289,8 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg)
	state = to_mtk_crtc_state(mtk_crtc->base.state);

	spin_lock_irqsave(&mtk_crtc->config_lock, flags);
	if (mtk_crtc->config_updating) {
		spin_unlock_irqrestore(&mtk_crtc->config_lock, flags);
	if (mtk_crtc->config_updating)
		goto ddp_cmdq_cb_out;
	}

	state->pending_config = false;

@@ -315,10 +318,15 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg)
		mtk_crtc->pending_async_planes = false;
	}

	spin_unlock_irqrestore(&mtk_crtc->config_lock, flags);

ddp_cmdq_cb_out:

	if (mtk_crtc->pending_needs_vblank) {
		mtk_crtc_finish_page_flip(mtk_crtc);
		mtk_crtc->pending_needs_vblank = false;
	}

	spin_unlock_irqrestore(&mtk_crtc->config_lock, flags);

	mtk_crtc->cmdq_vblank_cnt = 0;
	wake_up(&mtk_crtc->cb_blocking_queue);
}
@@ -606,13 +614,18 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank)
		 */
		mtk_crtc->cmdq_vblank_cnt = 3;

		spin_lock_irqsave(&mtk_crtc->config_lock, flags);
		mtk_crtc->config_updating = false;
		spin_unlock_irqrestore(&mtk_crtc->config_lock, flags);

		mbox_send_message(mtk_crtc->cmdq_client.chan, cmdq_handle);
		mbox_client_txdone(mtk_crtc->cmdq_client.chan, 0);
	}
#endif
#else
	spin_lock_irqsave(&mtk_crtc->config_lock, flags);
	mtk_crtc->config_updating = false;
	spin_unlock_irqrestore(&mtk_crtc->config_lock, flags);
#endif

	mutex_unlock(&mtk_crtc->hw_lock);
}
+39 −30
Original line number Diff line number Diff line
@@ -460,6 +460,29 @@ static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl,
	}
}

static void mtk_ovl_afbc_layer_config(struct mtk_disp_ovl *ovl,
				      unsigned int idx,
				      struct mtk_plane_pending_state *pending,
				      struct cmdq_pkt *cmdq_pkt)
{
	unsigned int pitch_msb = pending->pitch >> 16;
	unsigned int hdr_pitch = pending->hdr_pitch;
	unsigned int hdr_addr = pending->hdr_addr;

	if (pending->modifier != DRM_FORMAT_MOD_LINEAR) {
		mtk_ddp_write_relaxed(cmdq_pkt, hdr_addr, &ovl->cmdq_reg, ovl->regs,
				      DISP_REG_OVL_HDR_ADDR(ovl, idx));
		mtk_ddp_write_relaxed(cmdq_pkt,
				      OVL_PITCH_MSB_2ND_SUBBUF | pitch_msb,
				      &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH_MSB(idx));
		mtk_ddp_write_relaxed(cmdq_pkt, hdr_pitch, &ovl->cmdq_reg, ovl->regs,
				      DISP_REG_OVL_HDR_PITCH(ovl, idx));
	} else {
		mtk_ddp_write_relaxed(cmdq_pkt, pitch_msb,
				      &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH_MSB(idx));
	}
}

void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
			  struct mtk_plane_state *state,
			  struct cmdq_pkt *cmdq_pkt)
@@ -467,25 +490,14 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
	struct mtk_plane_pending_state *pending = &state->pending;
	unsigned int addr = pending->addr;
	unsigned int hdr_addr = pending->hdr_addr;
	unsigned int pitch = pending->pitch;
	unsigned int hdr_pitch = pending->hdr_pitch;
	unsigned int pitch_lsb = pending->pitch & GENMASK(15, 0);
	unsigned int fmt = pending->format;
	unsigned int rotation = pending->rotation;
	unsigned int offset = (pending->y << 16) | pending->x;
	unsigned int src_size = (pending->height << 16) | pending->width;
	unsigned int blend_mode = state->base.pixel_blend_mode;
	unsigned int ignore_pixel_alpha = 0;
	unsigned int con;
	bool is_afbc = pending->modifier != DRM_FORMAT_MOD_LINEAR;
	union overlay_pitch {
		struct split_pitch {
			u16 lsb;
			u16 msb;
		} split_pitch;
		u32 pitch;
	} overlay_pitch;

	overlay_pitch.pitch = pitch;

	if (!pending->enable) {
		mtk_ovl_layer_off(dev, idx, cmdq_pkt);
@@ -513,22 +525,30 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
			ignore_pixel_alpha = OVL_CONST_BLEND;
	}

	if (pending->rotation & DRM_MODE_REFLECT_Y) {
	/*
	 * Treat rotate 180 as flip x + flip y, and XOR the original rotation value
	 * to flip x + flip y to support both in the same time.
	 */
	if (rotation & DRM_MODE_ROTATE_180)
		rotation ^= DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y;

	if (rotation & DRM_MODE_REFLECT_Y) {
		con |= OVL_CON_VIRT_FLIP;
		addr += (pending->height - 1) * pending->pitch;
	}

	if (pending->rotation & DRM_MODE_REFLECT_X) {
	if (rotation & DRM_MODE_REFLECT_X) {
		con |= OVL_CON_HORZ_FLIP;
		addr += pending->pitch - 1;
	}

	if (ovl->data->supports_afbc)
		mtk_ovl_set_afbc(ovl, cmdq_pkt, idx, is_afbc);
		mtk_ovl_set_afbc(ovl, cmdq_pkt, idx,
				 pending->modifier != DRM_FORMAT_MOD_LINEAR);

	mtk_ddp_write_relaxed(cmdq_pkt, con, &ovl->cmdq_reg, ovl->regs,
			      DISP_REG_OVL_CON(idx));
	mtk_ddp_write_relaxed(cmdq_pkt, overlay_pitch.split_pitch.lsb | ignore_pixel_alpha,
	mtk_ddp_write_relaxed(cmdq_pkt, pitch_lsb | ignore_pixel_alpha,
			      &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH(idx));
	mtk_ddp_write_relaxed(cmdq_pkt, src_size, &ovl->cmdq_reg, ovl->regs,
			      DISP_REG_OVL_SRC_SIZE(idx));
@@ -537,19 +557,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
	mtk_ddp_write_relaxed(cmdq_pkt, addr, &ovl->cmdq_reg, ovl->regs,
			      DISP_REG_OVL_ADDR(ovl, idx));

	if (is_afbc) {
		mtk_ddp_write_relaxed(cmdq_pkt, hdr_addr, &ovl->cmdq_reg, ovl->regs,
				      DISP_REG_OVL_HDR_ADDR(ovl, idx));
		mtk_ddp_write_relaxed(cmdq_pkt,
				      OVL_PITCH_MSB_2ND_SUBBUF | overlay_pitch.split_pitch.msb,
				      &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH_MSB(idx));
		mtk_ddp_write_relaxed(cmdq_pkt, hdr_pitch, &ovl->cmdq_reg, ovl->regs,
				      DISP_REG_OVL_HDR_PITCH(ovl, idx));
	} else {
		mtk_ddp_write_relaxed(cmdq_pkt,
				      overlay_pitch.split_pitch.msb,
				      &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH_MSB(idx));
	}
	if (ovl->data->supports_afbc)
		mtk_ovl_afbc_layer_config(ovl, idx, pending, cmdq_pkt);

	mtk_ovl_set_bit_depth(dev, idx, fmt, cmdq_pkt);
	mtk_ovl_layer_on(dev, idx, cmdq_pkt);
+27 −19
Original line number Diff line number Diff line
@@ -543,18 +543,16 @@ static int mtk_dp_set_color_format(struct mtk_dp *mtk_dp,
				   enum dp_pixelformat color_format)
{
	u32 val;

	/* update MISC0 */
	mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3034,
			   color_format << DP_TEST_COLOR_FORMAT_SHIFT,
			   DP_TEST_COLOR_FORMAT_MASK);
	u32 misc0_color;

	switch (color_format) {
	case DP_PIXELFORMAT_YUV422:
		val = PIXEL_ENCODE_FORMAT_DP_ENC0_P0_YCBCR422;
		misc0_color = DP_COLOR_FORMAT_YCbCr422;
		break;
	case DP_PIXELFORMAT_RGB:
		val = PIXEL_ENCODE_FORMAT_DP_ENC0_P0_RGB;
		misc0_color = DP_COLOR_FORMAT_RGB;
		break;
	default:
		drm_warn(mtk_dp->drm_dev, "Unsupported color format: %d\n",
@@ -562,6 +560,11 @@ static int mtk_dp_set_color_format(struct mtk_dp *mtk_dp,
		return -EINVAL;
	}

	/* update MISC0 */
	mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3034,
			   misc0_color,
			   DP_TEST_COLOR_FORMAT_MASK);

	mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_303C,
			   val, PIXEL_ENCODE_FORMAT_DP_ENC0_P0_MASK);
	return 0;
@@ -2100,7 +2103,6 @@ static enum drm_connector_status mtk_dp_bdg_detect(struct drm_bridge *bridge)
	struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge);
	enum drm_connector_status ret = connector_status_disconnected;
	bool enabled = mtk_dp->enabled;
	u8 sink_count = 0;

	if (!mtk_dp->train_info.cable_plugged_in)
		return ret;
@@ -2115,8 +2117,8 @@ static enum drm_connector_status mtk_dp_bdg_detect(struct drm_bridge *bridge)
	 * function, we just need to check the HPD connection to check
	 * whether we connect to a sink device.
	 */
	drm_dp_dpcd_readb(&mtk_dp->aux, DP_SINK_COUNT, &sink_count);
	if (DP_GET_SINK_COUNT(sink_count))

	if (drm_dp_read_sink_count(&mtk_dp->aux) > 0)
		ret = connector_status_connected;

	if (!enabled)
@@ -2408,12 +2410,19 @@ mtk_dp_bridge_mode_valid(struct drm_bridge *bridge,
{
	struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge);
	u32 bpp = info->color_formats & DRM_COLOR_FORMAT_YCBCR422 ? 16 : 24;
	u32 rate = min_t(u32, drm_dp_max_link_rate(mtk_dp->rx_cap) *
			      drm_dp_max_lane_count(mtk_dp->rx_cap),
			 drm_dp_bw_code_to_link_rate(mtk_dp->max_linkrate) *
			 mtk_dp->max_lanes);
	u32 lane_count_min = mtk_dp->train_info.lane_count;
	u32 rate = drm_dp_bw_code_to_link_rate(mtk_dp->train_info.link_rate) *
		   lane_count_min;

	if (rate < mode->clock * bpp / 8)
	/*
	 *FEC overhead is approximately 2.4% from DP 1.4a spec 2.2.1.4.2.
	 *The down-spread amplitude shall either be disabled (0.0%) or up
	 *to 0.5% from 1.4a 3.5.2.6. Add up to approximately 3% total overhead.
	 *
	 *Because rate is already divided by 10,
	 *mode->clock does not need to be multiplied by 10
	 */
	if ((rate * 97 / 100) < (mode->clock * bpp / 8))
		return MODE_CLOCK_HIGH;

	return MODE_OK;
@@ -2454,10 +2463,9 @@ static u32 *mtk_dp_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
	struct drm_display_mode *mode = &crtc_state->adjusted_mode;
	struct drm_display_info *display_info =
		&conn_state->connector->display_info;
	u32 rate = min_t(u32, drm_dp_max_link_rate(mtk_dp->rx_cap) *
			      drm_dp_max_lane_count(mtk_dp->rx_cap),
			 drm_dp_bw_code_to_link_rate(mtk_dp->max_linkrate) *
			 mtk_dp->max_lanes);
	u32 lane_count_min = mtk_dp->train_info.lane_count;
	u32 rate = drm_dp_bw_code_to_link_rate(mtk_dp->train_info.link_rate) *
		   lane_count_min;

	*num_input_fmts = 0;

@@ -2466,8 +2474,8 @@ static u32 *mtk_dp_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
	 * datarate of YUV422 and sink device supports YUV422, we output YUV422
	 * format. Use this condition, we can support more resolution.
	 */
	if ((rate < (mode->clock * 24 / 8)) &&
	    (rate > (mode->clock * 16 / 8)) &&
	if (((rate * 97 / 100) < (mode->clock * 24 / 8)) &&
	    ((rate * 97 / 100) > (mode->clock * 16 / 8)) &&
	    (display_info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) {
		input_fmts = kcalloc(1, sizeof(*input_fmts), GFP_KERNEL);
		if (!input_fmts)
Loading