Commit 88a29f8c authored by Dave Airlie's avatar Dave Airlie
Browse files

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

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

 into drm-next

Mediatek DRM Next for Linux 6.12

1. Support alpha blending
2. Remove cl in struct cmdq_pkt
3. Fixup for ovl adaptor
4. Declare Z Position for all planes
5. Drop unnecessary check for property presence
6. Add dsi per-frame lp code for mt8188
7. Fix missing configuration flags in mtk_crtc_ddp_config()
8. Use spin_lock_irqsave() for CRTC event lock
9. Add power domain binding to the mediatek DPI controller

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

From: Chun-Kuang Hu <chunkuang.hu@kernel.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20240901131354.2686-1-chunkuang.hu@kernel.org
parents eb7205b7 5474d49b
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -62,6 +62,9 @@ properties:
      - const: default
      - const: sleep

  power-domains:
    maxItems: 1

  port:
    $ref: /schemas/graph.yaml#/properties/port
    description:
@@ -76,6 +79,20 @@ required:
  - clock-names
  - port

allOf:
  - if:
      not:
        properties:
          compatible:
            contains:
              enum:
                - mediatek,mt6795-dpi
                - mediatek,mt8173-dpi
                - mediatek,mt8186-dpi
    then:
      properties:
        power-domains: false

additionalProperties: false

examples:
+36 −46
Original line number Diff line number Diff line
@@ -69,6 +69,8 @@ struct mtk_crtc {
	/* lock for display hardware access */
	struct mutex			hw_lock;
	bool				config_updating;
	/* lock for config_updating to cmd buffer */
	spinlock_t			config_lock;
};

struct mtk_crtc_state {
@@ -106,51 +108,18 @@ static void mtk_crtc_finish_page_flip(struct mtk_crtc *mtk_crtc)

static void mtk_drm_finish_page_flip(struct mtk_crtc *mtk_crtc)
{
	unsigned long flags;

	drm_crtc_handle_vblank(&mtk_crtc->base);

	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);
		mtk_crtc->pending_needs_vblank = false;
	}
	spin_unlock_irqrestore(&mtk_crtc->config_lock, flags);
}

#if IS_REACHABLE(CONFIG_MTK_CMDQ)
static int mtk_drm_cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt *pkt,
				   size_t size)
{
	struct device *dev;
	dma_addr_t dma_addr;

	pkt->va_base = kzalloc(size, GFP_KERNEL);
	if (!pkt->va_base)
		return -ENOMEM;

	pkt->buf_size = size;
	pkt->cl = (void *)client;

	dev = client->chan->mbox->dev;
	dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size,
				  DMA_TO_DEVICE);
	if (dma_mapping_error(dev, dma_addr)) {
		dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size);
		kfree(pkt->va_base);
		return -ENOMEM;
	}

	pkt->pa_base = dma_addr;

	return 0;
}

static void mtk_drm_cmdq_pkt_destroy(struct cmdq_pkt *pkt)
{
	struct cmdq_client *client = (struct cmdq_client *)pkt->cl;

	dma_unmap_single(client->chan->mbox->dev, pkt->pa_base, pkt->buf_size,
			 DMA_TO_DEVICE);
	kfree(pkt->va_base);
}
#endif

static void mtk_crtc_destroy(struct drm_crtc *crtc)
{
	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
@@ -158,7 +127,7 @@ static void mtk_crtc_destroy(struct drm_crtc *crtc)

	mtk_mutex_put(mtk_crtc->mutex);
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
	mtk_drm_cmdq_pkt_destroy(&mtk_crtc->cmdq_handle);
	cmdq_pkt_destroy(&mtk_crtc->cmdq_client, &mtk_crtc->cmdq_handle);

	if (mtk_crtc->cmdq_client.chan) {
		mbox_free_channel(mtk_crtc->cmdq_client.chan);
@@ -308,12 +277,19 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg)
	struct mtk_crtc *mtk_crtc = container_of(cmdq_cl, struct mtk_crtc, cmdq_client);
	struct mtk_crtc_state *state;
	unsigned int i;
	unsigned long flags;

	if (data->sta < 0)
		return;

	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);
		goto ddp_cmdq_cb_out;
	}

	state->pending_config = false;

	if (mtk_crtc->pending_planes) {
@@ -340,6 +316,10 @@ 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:

	mtk_crtc->cmdq_vblank_cnt = 0;
	wake_up(&mtk_crtc->cb_blocking_queue);
}
@@ -449,6 +429,7 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_crtc *mtk_crtc)
{
	struct drm_device *drm = mtk_crtc->base.dev;
	struct drm_crtc *crtc = &mtk_crtc->base;
	unsigned long flags;
	int i;

	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
@@ -480,10 +461,10 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_crtc *mtk_crtc)
	pm_runtime_put(drm->dev);

	if (crtc->state->event && !crtc->state->active) {
		spin_lock_irq(&crtc->dev->event_lock);
		spin_lock_irqsave(&crtc->dev->event_lock, flags);
		drm_crtc_send_vblank_event(crtc, crtc->state->event);
		crtc->state->event = NULL;
		spin_unlock_irq(&crtc->dev->event_lock);
		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
	}
}

@@ -569,9 +550,14 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank)
	struct mtk_drm_private *priv = crtc->dev->dev_private;
	unsigned int pending_planes = 0, pending_async_planes = 0;
	int i;
	unsigned long flags;

	mutex_lock(&mtk_crtc->hw_lock);

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

	if (needs_vblank)
		mtk_crtc->pending_needs_vblank = true;

@@ -607,7 +593,7 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank)
		cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event);
		cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, false);
		mtk_crtc_ddp_config(crtc, cmdq_handle);
		cmdq_pkt_finalize(cmdq_handle);
		cmdq_pkt_eoc(cmdq_handle);
		dma_sync_single_for_device(mtk_crtc->cmdq_client.chan->mbox->dev,
					   cmdq_handle->pa_base,
					   cmdq_handle->cmd_buf_size,
@@ -625,7 +611,10 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank)
		mbox_client_txdone(mtk_crtc->cmdq_client.chan, 0);
	}
#endif
	spin_lock_irqsave(&mtk_crtc->config_lock, flags);
	mtk_crtc->config_updating = false;
	spin_unlock_irqrestore(&mtk_crtc->config_lock, flags);

	mutex_unlock(&mtk_crtc->hw_lock);
}

@@ -925,7 +914,7 @@ static int mtk_crtc_init_comp_planes(struct drm_device *drm_dev,
				mtk_crtc_plane_type(mtk_crtc->layer_nr, num_planes),
				mtk_ddp_comp_supported_rotations(comp),
				mtk_ddp_comp_get_formats(comp),
				mtk_ddp_comp_get_num_formats(comp));
				mtk_ddp_comp_get_num_formats(comp), i);
		if (ret)
			return ret;

@@ -1068,6 +1057,7 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
		drm_mode_crtc_set_gamma_size(&mtk_crtc->base, gamma_lut_size);
	drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, has_ctm, gamma_lut_size);
	mutex_init(&mtk_crtc->hw_lock);
	spin_lock_init(&mtk_crtc->config_lock);

#if IS_REACHABLE(CONFIG_MTK_CMDQ)
	i = priv->mbox_index++;
@@ -1094,7 +1084,7 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
			mbox_free_channel(mtk_crtc->cmdq_client.chan);
			mtk_crtc->cmdq_client.chan = NULL;
		} else {
			ret = mtk_drm_cmdq_pkt_create(&mtk_crtc->cmdq_client,
			ret = cmdq_pkt_create(&mtk_crtc->cmdq_client,
					      &mtk_crtc->cmdq_handle,
					      PAGE_SIZE);
			if (ret) {
+28 −8
Original line number Diff line number Diff line
@@ -56,8 +56,12 @@
#define GMC_THRESHOLD_HIGH	((1 << GMC_THRESHOLD_BITS) / 4)
#define GMC_THRESHOLD_LOW	((1 << GMC_THRESHOLD_BITS) / 8)

#define OVL_CON_CLRFMT_MAN	BIT(23)
#define OVL_CON_BYTE_SWAP	BIT(24)
#define OVL_CON_MTX_YUV_TO_RGB	(6 << 16)

/* OVL_CON_RGB_SWAP works only if OVL_CON_CLRFMT_MAN is enabled */
#define OVL_CON_RGB_SWAP	BIT(25)

#define OVL_CON_CLRFMT_RGB	(1 << 12)
#define OVL_CON_CLRFMT_ARGB8888	(2 << 12)
#define OVL_CON_CLRFMT_RGBA8888	(3 << 12)
@@ -65,6 +69,11 @@
#define OVL_CON_CLRFMT_BGRA8888	(OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP)
#define OVL_CON_CLRFMT_UYVY	(4 << 12)
#define OVL_CON_CLRFMT_YUYV	(5 << 12)
#define OVL_CON_MTX_YUV_TO_RGB	(6 << 16)
#define OVL_CON_CLRFMT_PARGB8888 ((3 << 12) | OVL_CON_CLRFMT_MAN)
#define OVL_CON_CLRFMT_PABGR8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_RGB_SWAP)
#define OVL_CON_CLRFMT_PBGRA8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_BYTE_SWAP)
#define OVL_CON_CLRFMT_PRGBA8888 (OVL_CON_CLRFMT_PABGR8888 | OVL_CON_BYTE_SWAP)
#define OVL_CON_CLRFMT_RGB565(ovl)	((ovl)->data->fmt_rgb565_is_0 ? \
					0 : OVL_CON_CLRFMT_RGB)
#define OVL_CON_CLRFMT_RGB888(ovl)	((ovl)->data->fmt_rgb565_is_0 ? \
@@ -377,7 +386,8 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx,
		      DISP_REG_OVL_RDMA_CTRL(idx));
}

static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt)
static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt,
				    unsigned int blend_mode)
{
	/* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX"
	 * is defined in mediatek HW data sheet.
@@ -398,22 +408,30 @@ static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt)
	case DRM_FORMAT_RGBA8888:
	case DRM_FORMAT_RGBX1010102:
	case DRM_FORMAT_RGBA1010102:
		return OVL_CON_CLRFMT_RGBA8888;
		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
		       OVL_CON_CLRFMT_RGBA8888 :
		       OVL_CON_CLRFMT_PRGBA8888;
	case DRM_FORMAT_BGRX8888:
	case DRM_FORMAT_BGRA8888:
	case DRM_FORMAT_BGRX1010102:
	case DRM_FORMAT_BGRA1010102:
		return OVL_CON_CLRFMT_BGRA8888;
		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
		       OVL_CON_CLRFMT_BGRA8888 :
		       OVL_CON_CLRFMT_PBGRA8888;
	case DRM_FORMAT_XRGB8888:
	case DRM_FORMAT_ARGB8888:
	case DRM_FORMAT_XRGB2101010:
	case DRM_FORMAT_ARGB2101010:
		return OVL_CON_CLRFMT_ARGB8888;
		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
		       OVL_CON_CLRFMT_ARGB8888 :
		       OVL_CON_CLRFMT_PARGB8888;
	case DRM_FORMAT_XBGR8888:
	case DRM_FORMAT_ABGR8888:
	case DRM_FORMAT_XBGR2101010:
	case DRM_FORMAT_ABGR2101010:
		return OVL_CON_CLRFMT_ABGR8888;
		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
		       OVL_CON_CLRFMT_ABGR8888 :
		       OVL_CON_CLRFMT_PABGR8888;
	case DRM_FORMAT_UYVY:
		return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB;
	case DRM_FORMAT_YUYV:
@@ -434,6 +452,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
	unsigned int fmt = pending->format;
	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;
@@ -452,7 +471,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
		return;
	}

	con = ovl_fmt_convert(ovl, fmt);
	con = ovl_fmt_convert(ovl, fmt, blend_mode);
	if (state->base.fb) {
		con |= OVL_CON_AEN;
		con |= state->base.alpha & OVL_CON_ALPHA;
@@ -463,7 +482,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
	 * For RGB888 related formats, whether CONST_BLD is enabled or not won't
	 * affect the result. Therefore we use !has_alpha as the condition.
	 */
	if (state->base.fb && !state->base.fb->format->has_alpha)
	if ((state->base.fb && !state->base.fb->format->has_alpha) ||
	    blend_mode == DRM_MODE_BLEND_PIXEL_NONE)
		ignore_pixel_alpha = OVL_CONST_BLEND;

	if (pending->rotation & DRM_MODE_REFLECT_Y) {
+2 −3
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
#include <linux/soc/mediatek/mtk-mmsys.h>
#include <linux/soc/mediatek/mtk-mutex.h>

#include "mtk_crtc.h"
#include "mtk_ddp_comp.h"
#include "mtk_disp_drv.h"
#include "mtk_drm_drv.h"
@@ -494,12 +493,12 @@ static int compare_of(struct device *dev, void *data)
static int ovl_adaptor_comp_init(struct device *dev, struct component_match **match)
{
	struct mtk_disp_ovl_adaptor *priv = dev_get_drvdata(dev);
	struct device_node *node, *parent;
	struct device_node *parent;
	struct platform_device *comp_pdev;

	parent = dev->parent->parent->of_node->parent;

	for_each_child_of_node(parent, node) {
	for_each_child_of_node_scoped(parent, node) {
		const struct of_device_id *of_id;
		enum mtk_ovl_adaptor_comp_type type;
		int id;
+5 −8
Original line number Diff line number Diff line
@@ -341,14 +341,11 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
		dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
#endif

	if (of_find_property(dev->of_node, "mediatek,rdma-fifo-size", &ret)) {
	ret = of_property_read_u32(dev->of_node,
				   "mediatek,rdma-fifo-size",
				   &priv->fifo_size);
		if (ret)
			return dev_err_probe(dev, ret,
					     "Failed to get rdma fifo size\n");
	}
	if (ret && (ret != -EINVAL))
		return dev_err_probe(dev, ret, "Failed to get rdma fifo size\n");

	/* Disable and clear pending interrupts */
	writel(0x0, priv->regs + DISP_REG_RDMA_INT_ENABLE);
Loading