Commit 017da39e authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'mediatek-drm-next-6.9' of...

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

 into drm-next

Mediatek DRM Next for Linux 6.9

1. Add display driver for MT8188 VDOSYS1
2. DSI driver cleanups
3. Filter modes according to hardware capability
4. Fix a null pointer crash in mtk_drm_crtc_finish_page_flip

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

From: Chun-Kuang Hu <chunkuang.hu@kernel.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20240229162143.28957-1-chunkuang.hu@kernel.org
parents 1752f138 c958e86e
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -73,6 +73,8 @@ void mtk_merge_advance_config(struct device *dev, unsigned int l_w, unsigned int
			      struct cmdq_pkt *cmdq_pkt);
void mtk_merge_start_cmdq(struct device *dev, struct cmdq_pkt *cmdq_pkt);
void mtk_merge_stop_cmdq(struct device *dev, struct cmdq_pkt *cmdq_pkt);
enum drm_mode_status mtk_merge_mode_valid(struct device *dev,
					  const struct drm_display_mode *mode);

void mtk_ovl_bgclr_in_on(struct device *dev);
void mtk_ovl_bgclr_in_off(struct device *dev);
@@ -131,6 +133,8 @@ unsigned int mtk_ovl_adaptor_layer_nr(struct device *dev);
struct device *mtk_ovl_adaptor_dma_dev_get(struct device *dev);
const u32 *mtk_ovl_adaptor_get_formats(struct device *dev);
size_t mtk_ovl_adaptor_get_num_formats(struct device *dev);
enum drm_mode_status mtk_ovl_adaptor_mode_valid(struct device *dev,
						const struct drm_display_mode *mode);

void mtk_rdma_bypass_shadow(struct device *dev);
int mtk_rdma_clk_enable(struct device *dev);
+65 −0
Original line number Diff line number Diff line
@@ -222,6 +222,71 @@ void mtk_merge_clk_disable(struct device *dev)
	clk_disable_unprepare(priv->clk);
}

enum drm_mode_status mtk_merge_mode_valid(struct device *dev,
					  const struct drm_display_mode *mode)
{
	struct mtk_disp_merge *priv = dev_get_drvdata(dev);
	unsigned long rate;

	rate = clk_get_rate(priv->clk);

	/* Convert to KHz and round the number */
	rate = (rate + 500) / 1000;

	if (rate && mode->clock > rate) {
		dev_dbg(dev, "invalid clock: %d (>%lu)\n", mode->clock, rate);
		return MODE_CLOCK_HIGH;
	}

	/*
	 * Measure the bandwidth requirement of hardware prefetch (per frame)
	 *
	 * let N = prefetch buffer size in lines
	 *         (ex. N=3, then prefetch buffer size = 3 lines)
	 *
	 * prefetch size = htotal * N (pixels)
	 * time per line = 1 / fps / vtotal (seconds)
	 * duration      = vbp * time per line
	 *               = vbp / fps / vtotal
	 *
	 * data rate = prefetch size / duration
	 *           = htotal * N / (vbp / fps / vtotal)
	 *           = htotal * vtotal * fps * N / vbp
	 *           = clk * N / vbp (pixels per second)
	 *
	 * Say 4K60 (CEA-861) is the maximum mode supported by the SoC
	 * data rate = 594000K * N / 72 = 8250 (standard)
	 * (remove K * N due to the same unit)
	 *
	 * For 2560x1440@144 (clk=583600K, vbp=17):
	 * data rate = 583600 / 17 ~= 34329 > 8250 (NG)
	 *
	 * For 2560x1440@120 (clk=497760K, vbp=77):
	 * data rate = 497760 / 77 ~= 6464 < 8250 (OK)
	 *
	 * A non-standard 4K60 timing (clk=521280K, vbp=54)
	 * data rate = 521280 / 54 ~= 9653 > 8250 (NG)
	 *
	 * Bandwidth requirement of hardware prefetch increases significantly
	 * when the VBP decreases (more than 4x in this example).
	 *
	 * The proposed formula is only one way to estimate whether our SoC
	 * supports the mode setting. The basic idea behind it is just to check
	 * if the data rate requirement is too high (directly proportional to
	 * pixel clock, inversely proportional to vbp). Please adjust the
	 * function if it doesn't fit your situation in the future.
	 */
	rate = mode->clock / (mode->vtotal - mode->vsync_end);

	if (rate > 8250) {
		dev_dbg(dev, "invalid rate: %lu (>8250): " DRM_MODE_FMT "\n",
			rate, DRM_MODE_ARG(mode));
		return MODE_BAD;
	}

	return MODE_OK;
}

static int mtk_disp_merge_bind(struct device *dev, struct device *master,
			       void *data)
{
+43 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ enum mtk_ovl_adaptor_comp_type {
	OVL_ADAPTOR_TYPE_ETHDR,
	OVL_ADAPTOR_TYPE_MDP_RDMA,
	OVL_ADAPTOR_TYPE_MERGE,
	OVL_ADAPTOR_TYPE_PADDING,
	OVL_ADAPTOR_TYPE_NUM,
};

@@ -47,6 +48,14 @@ enum mtk_ovl_adaptor_comp_id {
	OVL_ADAPTOR_MERGE1,
	OVL_ADAPTOR_MERGE2,
	OVL_ADAPTOR_MERGE3,
	OVL_ADAPTOR_PADDING0,
	OVL_ADAPTOR_PADDING1,
	OVL_ADAPTOR_PADDING2,
	OVL_ADAPTOR_PADDING3,
	OVL_ADAPTOR_PADDING4,
	OVL_ADAPTOR_PADDING5,
	OVL_ADAPTOR_PADDING6,
	OVL_ADAPTOR_PADDING7,
	OVL_ADAPTOR_ID_MAX
};

@@ -67,6 +76,7 @@ static const char * const private_comp_stem[OVL_ADAPTOR_TYPE_NUM] = {
	[OVL_ADAPTOR_TYPE_ETHDR]	= "ethdr",
	[OVL_ADAPTOR_TYPE_MDP_RDMA]	= "vdo1-rdma",
	[OVL_ADAPTOR_TYPE_MERGE]	= "merge",
	[OVL_ADAPTOR_TYPE_PADDING]	= "padding",
};

static const struct mtk_ddp_comp_funcs ethdr = {
@@ -79,6 +89,14 @@ static const struct mtk_ddp_comp_funcs ethdr = {
static const struct mtk_ddp_comp_funcs merge = {
	.clk_enable = mtk_merge_clk_enable,
	.clk_disable = mtk_merge_clk_disable,
	.mode_valid = mtk_merge_mode_valid,
};

static const struct mtk_ddp_comp_funcs padding = {
	.clk_enable = mtk_padding_clk_enable,
	.clk_disable = mtk_padding_clk_disable,
	.start = mtk_padding_start,
	.stop = mtk_padding_stop,
};

static const struct mtk_ddp_comp_funcs rdma = {
@@ -102,6 +120,14 @@ static const struct ovl_adaptor_comp_match comp_matches[OVL_ADAPTOR_ID_MAX] = {
	[OVL_ADAPTOR_MERGE1] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE2, 2, &merge },
	[OVL_ADAPTOR_MERGE2] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE3, 3, &merge },
	[OVL_ADAPTOR_MERGE3] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE4, 4, &merge },
	[OVL_ADAPTOR_PADDING0] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING0, 0, &padding },
	[OVL_ADAPTOR_PADDING1] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING1, 1, &padding },
	[OVL_ADAPTOR_PADDING2] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING2, 2, &padding },
	[OVL_ADAPTOR_PADDING3] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING3, 3, &padding },
	[OVL_ADAPTOR_PADDING4] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING4, 4, &padding },
	[OVL_ADAPTOR_PADDING5] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING5, 5, &padding },
	[OVL_ADAPTOR_PADDING6] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING6, 6, &padding },
	[OVL_ADAPTOR_PADDING7] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING7, 7, &padding },
};

void mtk_ovl_adaptor_layer_config(struct device *dev, unsigned int idx,
@@ -317,6 +343,22 @@ void mtk_ovl_adaptor_clk_disable(struct device *dev)
	}
}

enum drm_mode_status mtk_ovl_adaptor_mode_valid(struct device *dev,
						const struct drm_display_mode *mode)

{
	int i;
	struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);

	for (i = 0; i < OVL_ADAPTOR_ID_MAX; i++) {
		dev = ovl_adaptor->ovl_adaptor_comp[i];
		if (!dev || !comp_matches[i].funcs->mode_valid)
			continue;
		return comp_matches[i].funcs->mode_valid(dev, mode);
	}
	return MODE_OK;
}

unsigned int mtk_ovl_adaptor_layer_nr(struct device *dev)
{
	return MTK_OVL_ADAPTOR_LAYER_NUM;
@@ -437,6 +479,7 @@ static int ovl_adaptor_comp_get_id(struct device *dev, struct device_node *node,
}

static const struct of_device_id mtk_ovl_adaptor_comp_dt_ids[] = {
	{ .compatible = "mediatek,mt8188-disp-padding", .data = (void *)OVL_ADAPTOR_TYPE_PADDING },
	{ .compatible = "mediatek,mt8195-disp-ethdr", .data = (void *)OVL_ADAPTOR_TYPE_ETHDR },
	{ .compatible = "mediatek,mt8195-disp-merge", .data = (void *)OVL_ADAPTOR_TYPE_MERGE },
	{ .compatible = "mediatek,mt8195-vdo1-rdma", .data = (void *)OVL_ADAPTOR_TYPE_MDP_RDMA },
+24 −5
Original line number Diff line number Diff line
@@ -95,12 +95,14 @@ static void mtk_drm_crtc_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)
	struct drm_crtc *crtc = &mtk_crtc->base;
	unsigned long flags;

	if (mtk_crtc->event) {
		spin_lock_irqsave(&crtc->dev->event_lock, flags);
		drm_crtc_send_vblank_event(crtc, mtk_crtc->event);
		drm_crtc_vblank_put(crtc);
		mtk_crtc->event = NULL;
		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
	}
}

static void mtk_drm_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)
{
@@ -213,6 +215,22 @@ static void mtk_drm_crtc_destroy_state(struct drm_crtc *crtc,
	kfree(to_mtk_crtc_state(state));
}

static enum drm_mode_status
mtk_drm_crtc_mode_valid(struct drm_crtc *crtc,
			const struct drm_display_mode *mode)
{
	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
	enum drm_mode_status status = MODE_OK;
	int i;

	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
		status = mtk_ddp_comp_mode_valid(mtk_crtc->ddp_comp[i], mode);
		if (status != MODE_OK)
			break;
	}
	return status;
}

static bool mtk_drm_crtc_mode_fixup(struct drm_crtc *crtc,
				    const struct drm_display_mode *mode,
				    struct drm_display_mode *adjusted_mode)
@@ -831,6 +849,7 @@ static const struct drm_crtc_funcs mtk_crtc_funcs = {
static const struct drm_crtc_helper_funcs mtk_crtc_helper_funcs = {
	.mode_fixup	= mtk_drm_crtc_mode_fixup,
	.mode_set_nofb	= mtk_drm_crtc_mode_set_nofb,
	.mode_valid	= mtk_drm_crtc_mode_valid,
	.atomic_begin	= mtk_drm_crtc_atomic_begin,
	.atomic_flush	= mtk_drm_crtc_atomic_flush,
	.atomic_enable	= mtk_drm_crtc_atomic_enable,
+1 −0
Original line number Diff line number Diff line
@@ -418,6 +418,7 @@ static const struct mtk_ddp_comp_funcs ddp_ovl_adaptor = {
	.remove = mtk_ovl_adaptor_remove_comp,
	.get_formats = mtk_ovl_adaptor_get_formats,
	.get_num_formats = mtk_ovl_adaptor_get_num_formats,
	.mode_valid = mtk_ovl_adaptor_mode_valid,
};

static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
Loading