From nobody Sat Jul 25 21:23:12 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 40C6E42EED6; Mon, 13 Jul 2026 14:27:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783952876; cv=none; b=js0/tO392OKnBXQkhyI7k1QOEqDvxJ5dZ07v4+DVF+bCVH6C9/El2kd8MfF9P1HAtXV/nNtgcY0SDmm+xXKZjVU4MDmaHXrt2yW9P2/mEFpsR8nE9WCu9pFa1PnkmsAklzYw1ZZ46RWYmwJsEXJLJ/R7jyXbH7wbAWQZimcU2Yo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783952876; c=relaxed/simple; bh=CRTgzEIiCGF3Q0P2KDt3LTOIuTWsDk2Q75L0QVm3KT8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FYHOvBmMP8gZMc6qMxU9jpHZgr1ghYqZg45GvTG/jMEdHzKabMJq/CWyo8E+EgKx6FWDVCAksBwHG9Ir2YP1vjq9Hz4YzdW8LYpzRK4WYVX2Sl7rt8XId3S1GE9dUreVizzqFMKNTNVExD4IM4RPFM+rMg2gVcbr+LNCrZG333c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=hW69CgJ0; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="hW69CgJ0" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1783952873; bh=CRTgzEIiCGF3Q0P2KDt3LTOIuTWsDk2Q75L0QVm3KT8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hW69CgJ0E2xqiwgTM0Mz+jn5CE9OICeKQEJopihKmeGK7OZQhFavADhQT6EidGfkB YHVMehqU6qPu0cY8VQupg7NsOeBYQvM2NfZNjflb6ozc65JPgJodlITbIjRynJxGZM 8KJVfoHD+ZBjnTmSeIU6nY0hacfMpXXK09wv2Il7o3OlqW+gYuv5pVkrF9/mwoVwg4 YcCGaxh3ASiOw24holHD6cJR0j3TZ2E+o9wTcmKv2OChzfz7YmPxDSZ5+igi4r1EPA 6Fu+k3SqW0WLAYF+dCCl1hOOaVxHysrLT15Z4Vu+7s5Rtolaqut7LZEbvv48abWCa5 ZuNQ+vedBF7pg== Received: from IcarusMOD.eternityproject.eu (unknown [100.64.1.21]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: kholk11) by bali.collaboradmins.com (Postfix) with ESMTPSA id D024117E07A2; Mon, 13 Jul 2026 16:27:52 +0200 (CEST) From: AngeloGioacchino Del Regno To: chunkuang.hu@kernel.org Cc: p.zabel@pengutronix.de, maarten.lankhorst@linux.intel.com, mripard@kernel.org, tzimmermann@suse.de, airlied@gmail.com, simona@ffwll.ch, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, jitao.shi@mediatek.com, dri-devel@lists.freedesktop.org, linux-mediatek@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, justin.yeh@mediatek.com, jason-jh.lin@mediatek.com Subject: [PATCH v4 01/10] dt-bindings: display: mediatek: dsc: Add MT8196 compatible Date: Mon, 13 Jul 2026 16:27:37 +0200 Message-ID: <20260713142746.40259-2-angelogioacchino.delregno@collabora.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260713142746.40259-1-angelogioacchino.delregno@collabora.com> References: <20260713142746.40259-1-angelogioacchino.delregno@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add compatible for the Display Stream Compression (DSC) IP found in the display controller of the MT8196 SoC. This IP is compatible with the one found in MT8195. Acked-by: Rob Herring (Arm) Signed-off-by: AngeloGioacchino Del Regno --- .../devicetree/bindings/display/mediatek/mediatek,dsc.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,ds= c.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsc.ya= ml index a5b88eb97e3b..c8b3e86943e4 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsc.yaml +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsc.yaml @@ -23,7 +23,9 @@ properties: - enum: - mediatek,mt8195-disp-dsc - items: - - const: mediatek,mt8188-disp-dsc + - enum: + - mediatek,mt8188-disp-dsc + - mediatek,mt8196-disp-dsc - const: mediatek,mt8195-disp-dsc =20 reg: --=20 2.54.0 From nobody Sat Jul 25 21:23:12 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4B03943800F; Mon, 13 Jul 2026 14:27:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783952880; cv=none; b=GGljIAI6qd4sV04DQBFtCDesad6N0tvsL1JGdIgFbTv0X6niknUGiEK/WW2sRYVnJ9fDutRvzztBU7Go54fjW2NIcB5S0F3Gjvo11ndJoIYvk2AxrbRViovi8711drQcgboSa/ALtG7cHCiRzm4JpQv41MmkD8Y1RJH0bys4vG8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783952880; c=relaxed/simple; bh=jVvxY/dayIuxqXjQkzU3DAubmMnZqUuinWaaEmpOnPA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=G70zFyRr8tK6bufKoQPrpEeFhajCRJWvQKqps/hIFhcmVwWnwXdZ4bw1AsX2ITk0WsAmq15jVHkTTutgOvw6il6fph0dufqaEZGjgWZ3qDW3kRDtOI05JwY8fBfbnNs80CoGmCVMq+f+/Ulwv3bkyqCl4wgnB1sC2N9CgRHj8Gg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=FCrQNAj7; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="FCrQNAj7" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1783952875; bh=jVvxY/dayIuxqXjQkzU3DAubmMnZqUuinWaaEmpOnPA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FCrQNAj7I2x1t/Ezj4qmXup1a43W8rEiUnx11VvkZcmfzFlClthalI9Cswa76hltM nf1hlp2cEcjuJoT7ThbQBOKP7vMEK49tVGtH/Fjcc4rps8M58BrpvsJDswWN6mjXIm l1oK0BY9Qu9AGnWjQFMMyie9mJdGMJDYkuAsMjBzIQs8EpiSpHDeGgyirv89UOHarK xG9Nfy5xHKhPsRbQsHnTF4v4co2Clv416Jo65g0wgTcCihBKAoMYrFDxdHXIBXnyPz xxdPj4JoGH0FCB22QEY003nAUHb6M1wnRG2534qpdW8EAckWVdgLKKjRzD5USJsrVd a/z0ufJC7tOqg== Received: from IcarusMOD.eternityproject.eu (unknown [100.64.1.21]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: kholk11) by bali.collaboradmins.com (Postfix) with ESMTPSA id BF0C917E0A4E; Mon, 13 Jul 2026 16:27:53 +0200 (CEST) From: AngeloGioacchino Del Regno To: chunkuang.hu@kernel.org Cc: p.zabel@pengutronix.de, maarten.lankhorst@linux.intel.com, mripard@kernel.org, tzimmermann@suse.de, airlied@gmail.com, simona@ffwll.ch, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, jitao.shi@mediatek.com, dri-devel@lists.freedesktop.org, linux-mediatek@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, justin.yeh@mediatek.com, jason-jh.lin@mediatek.com Subject: [PATCH v4 02/10] drm/mediatek: Implement Display Stream Compression support Date: Mon, 13 Jul 2026 16:27:38 +0200 Message-ID: <20260713142746.40259-3-angelogioacchino.delregno@collabora.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260713142746.40259-1-angelogioacchino.delregno@collabora.com> References: <20260713142746.40259-1-angelogioacchino.delregno@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a real driver for the Display Stream Compression (DSC) Display Controller IP, implementing support for DSC v1.1 to v1.2. In order to do this, it was necessary to remove the basic DSC IP bypass setup from mtk_ddp_comp: this functionality is retained in the new mtk_disp_dsc driver, which checks if DSC was actually requested by other components (with the only one that currently supports this being DSI) and, if not, it will set BYPASS mode in the DSC IP. Like before, the BYPASS mode is set before starting the DSC IP, but unlike before, this is being done in the component start callback instead of the config one. Notably, the config callback is called by mtk_crtc always immediately before the calling start callback, so the order of register writes is retained. The only real difference is that now this is being done through CPU writes instead of CMDQ, but since that's called only once and since it's just three registers, the performance impact will not be minimal and not even measurable. As anticipated, DSC handling was also introduced in the mtk_dsi driver: when performing dsi_host_attach, the driver now checks if the DSI panel adds the DSC configuration structure to the mipi_dsi_device structure and, if it does, it will store a pointer in the driver-local mtk_dsi structure's `dsc` member. The DSI driver will then check whether the DSC configuration that comes from the panel is valid (in regard to MediaTek DSI) and will call the DRM API's DSC helpers to calculate and set all of the const and RC parameters for the actual DSC setup. For the time being, even though the latest MediaTek SoCs do support DSC v1.2, only DSC v1.1 pre-scr support is implemented as an initial contribution (which is rather big, and 1.2 would make it even bigger - but that can anyway be implemented later). As a last step for validation of DSC parameters in DSI, a check for the hdisplay against DSC slice sidth and one for vdisplay against DSC slice height was added to the mode_valid callback, making sure that H/V are, as expected, multiples of slice W/H. Signed-off-by: AngeloGioacchino Del Regno --- drivers/gpu/drm/mediatek/Makefile | 1 + drivers/gpu/drm/mediatek/mtk_crtc.c | 21 ++ drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 43 +-- drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 9 + drivers/gpu/drm/mediatek/mtk_disp_drv.h | 9 + drivers/gpu/drm/mediatek/mtk_disp_dsc.c | 455 ++++++++++++++++++++++++ drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 + drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 + drivers/gpu/drm/mediatek/mtk_dsi.c | 151 +++++++- 9 files changed, 642 insertions(+), 50 deletions(-) create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_dsc.c diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/M= akefile index 952d294642fb..03b3470ea5b5 100644 --- a/drivers/gpu/drm/mediatek/Makefile +++ b/drivers/gpu/drm/mediatek/Makefile @@ -5,6 +5,7 @@ mediatek-drm-y :=3D mtk_crtc.o \ mtk_disp_aal.o \ mtk_disp_ccorr.o \ mtk_disp_color.o \ + mtk_disp_dsc.o \ mtk_disp_gamma.o \ mtk_disp_merge.o \ mtk_disp_ovl.o \ diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek= /mtk_crtc.c index 8e552cdc3b53..d4be40b2574a 100644 --- a/drivers/gpu/drm/mediatek/mtk_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_crtc.c @@ -22,6 +22,7 @@ =20 #include "mtk_crtc.h" #include "mtk_ddp_comp.h" +#include "mtk_disp_drv.h" #include "mtk_drm_drv.h" #include "mtk_plane.h" =20 @@ -344,6 +345,8 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_cr= tc) struct drm_connector *connector; struct drm_encoder *encoder; struct drm_connector_list_iter conn_iter; + struct mtk_ddp_comp *comp_dsi =3D NULL, *comp_dsc =3D NULL; + struct drm_dsc_config *dsc_cfg; struct drm_device *dev =3D mtk_crtc->base.dev; unsigned int width, height, vrefresh, bpc =3D MTK_MAX_BPC; int ret; @@ -398,6 +401,17 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_c= rtc) if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex)) mtk_mutex_add_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id); + + /* For now, only single DSI is supported */ + if (mtk_crtc->ddp_comp[i]->id >=3D DDP_COMPONENT_DSI0 && + mtk_crtc->ddp_comp[i]->id <=3D DDP_COMPONENT_DSI3) + if (!comp_dsi) + comp_dsi =3D mtk_crtc->ddp_comp[i]; + + if (mtk_crtc->ddp_comp[i]->id =3D=3D DDP_COMPONENT_DSC0 || + mtk_crtc->ddp_comp[i]->id =3D=3D DDP_COMPONENT_DSC1) + if (!comp_dsc) + comp_dsc =3D mtk_crtc->ddp_comp[i]; } if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex)) mtk_mutex_add_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id); @@ -413,6 +427,13 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_c= rtc) mtk_ddp_comp_start(comp); } =20 + /* Setup the DSC if present, with the config coming from DSI */ + if (comp_dsc && comp_dsi) { + dsc_cfg =3D mtk_dsi_get_dsc_config(comp_dsi->dev); + if (dsc_cfg) + mtk_ddp_comp_dsc_setup(comp_dsc, dsc_cfg); + } + /* Initially configure all planes */ for (i =3D 0; i < mtk_crtc->layer_nr; i++) { struct drm_plane *plane =3D &mtk_crtc->planes[i]; diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/medi= atek/mtk_ddp_comp.c index 9672ea1f91a2..13aaf12ecbe5 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c @@ -40,12 +40,6 @@ #define DITHER_LSB_ERR_SHIFT_G(x) (((x) & 0x7) << 12) #define DITHER_ADD_LSHIFT_G(x) (((x) & 0x7) << 4) =20 -#define DISP_REG_DSC_CON 0x0000 -#define DSC_EN BIT(0) -#define DSC_DUAL_INOUT BIT(2) -#define DSC_BYPASS BIT(4) -#define DSC_UFOE_SEL BIT(16) - #define DISP_REG_OD_EN 0x0000 #define DISP_REG_OD_CFG 0x0020 #define OD_RELAYMODE BIT(0) @@ -187,36 +181,6 @@ static void mtk_dither_set(struct device *dev, unsigne= d int bpc, DISP_DITHERING, cmdq_pkt); } =20 -static void mtk_dsc_config(struct device *dev, unsigned int w, - unsigned int h, unsigned int vrefresh, - unsigned int bpc, struct cmdq_pkt *cmdq_pkt) -{ - struct mtk_ddp_comp_dev *priv =3D dev_get_drvdata(dev); - - /* dsc bypass mode */ - mtk_ddp_write_mask(cmdq_pkt, DSC_BYPASS, &priv->cmdq_reg, priv->regs, - DISP_REG_DSC_CON, DSC_BYPASS); - mtk_ddp_write_mask(cmdq_pkt, DSC_UFOE_SEL, &priv->cmdq_reg, priv->regs, - DISP_REG_DSC_CON, DSC_UFOE_SEL); - mtk_ddp_write_mask(cmdq_pkt, DSC_DUAL_INOUT, &priv->cmdq_reg, priv->regs, - DISP_REG_DSC_CON, DSC_DUAL_INOUT); -} - -static void mtk_dsc_start(struct device *dev) -{ - struct mtk_ddp_comp_dev *priv =3D dev_get_drvdata(dev); - - /* write with mask to reserve the value set in mtk_dsc_config */ - mtk_ddp_write_mask(NULL, DSC_EN, &priv->cmdq_reg, priv->regs, DISP_REG_DS= C_CON, DSC_EN); -} - -static void mtk_dsc_stop(struct device *dev) -{ - struct mtk_ddp_comp_dev *priv =3D dev_get_drvdata(dev); - - writel_relaxed(0x0, priv->regs + DISP_REG_DSC_CON); -} - static void mtk_od_config(struct device *dev, unsigned int w, unsigned int h, unsigned int vrefresh, unsigned int bpc, struct cmdq_pkt *cmdq_pkt) @@ -309,9 +273,9 @@ static const struct mtk_ddp_comp_funcs ddp_dpi =3D { }; =20 static const struct mtk_ddp_comp_funcs ddp_dsc =3D { - .clk_enable =3D mtk_ddp_clk_enable, - .clk_disable =3D mtk_ddp_clk_disable, - .config =3D mtk_dsc_config, + .clk_enable =3D mtk_dsc_clk_enable, + .clk_disable =3D mtk_dsc_clk_disable, + .dsc_setup =3D mtk_dsc_setup, .start =3D mtk_dsc_start, .stop =3D mtk_dsc_stop, }; @@ -671,6 +635,7 @@ int mtk_ddp_comp_init(struct device *dev, struct device= _node *node, struct mtk_d type =3D=3D MTK_DISP_BLS || type =3D=3D MTK_DISP_CCORR || type =3D=3D MTK_DISP_COLOR || + type =3D=3D MTK_DISP_DSC || type =3D=3D MTK_DISP_GAMMA || type =3D=3D MTK_DISP_MERGE || type =3D=3D MTK_DISP_OVL || diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/medi= atek/mtk_ddp_comp.h index 3f3d43f4330d..99bf1e1015da 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h @@ -20,6 +20,7 @@ struct drm_crtc; struct drm_device; struct mtk_plane_state; struct drm_crtc_state; +struct drm_dsc_config; =20 enum mtk_ddp_comp_type { MTK_DISP_AAL, @@ -56,6 +57,7 @@ struct mtk_ddp_comp_funcs { void (*config)(struct device *dev, unsigned int w, unsigned int h, unsigned int vrefresh, unsigned int bpc, struct cmdq_pkt *cmdq_pkt); + void (*dsc_setup)(struct device *dev, struct drm_dsc_config *dsc); void (*start)(struct device *dev); void (*stop)(struct device *dev); void (*register_vblank_cb)(struct device *dev, @@ -149,6 +151,13 @@ static inline void mtk_ddp_comp_config(struct mtk_ddp_= comp *comp, comp->funcs->config(comp->dev, w, h, vrefresh, bpc, cmdq_pkt); } =20 +static inline void mtk_ddp_comp_dsc_setup(struct mtk_ddp_comp *comp, + struct drm_dsc_config *dsc) +{ + if (comp->funcs && comp->funcs->dsc_setup) + comp->funcs->dsc_setup(comp->dev, dsc); +} + static inline void mtk_ddp_comp_start(struct mtk_ddp_comp *comp) { if (comp->funcs && comp->funcs->start) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/medi= atek/mtk_disp_drv.h index 679d413bf10b..5e2d8748120a 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h @@ -12,6 +12,8 @@ #include "mtk_mdp_rdma.h" #include "mtk_plane.h" =20 +struct drm_dsc_config; + int mtk_aal_clk_enable(struct device *dev); void mtk_aal_clk_disable(struct device *dev); void mtk_aal_config(struct device *dev, unsigned int w, @@ -47,9 +49,16 @@ void mtk_dpi_start(struct device *dev); void mtk_dpi_stop(struct device *dev); unsigned int mtk_dpi_encoder_index(struct device *dev); =20 +int mtk_dsc_clk_enable(struct device *dev); +void mtk_dsc_clk_disable(struct device *dev); +void mtk_dsc_setup(struct device *dev, struct drm_dsc_config *dsc_cfg); +void mtk_dsc_start(struct device *dev); +void mtk_dsc_stop(struct device *dev); + void mtk_dsi_ddp_start(struct device *dev); void mtk_dsi_ddp_stop(struct device *dev); unsigned int mtk_dsi_encoder_index(struct device *dev); +struct drm_dsc_config *mtk_dsi_get_dsc_config(struct device *dev); =20 int mtk_gamma_clk_enable(struct device *dev); void mtk_gamma_clk_disable(struct device *dev); diff --git a/drivers/gpu/drm/mediatek/mtk_disp_dsc.c b/drivers/gpu/drm/medi= atek/mtk_disp_dsc.c new file mode 100644 index 000000000000..bed6b77bf9a9 --- /dev/null +++ b/drivers/gpu/drm/mediatek/mtk_disp_dsc.c @@ -0,0 +1,455 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021 MediaTek Inc. + * Copyright (c) 2025 Collabora Ltd + * AngeloGioacchino Del Regno + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "mtk_crtc.h" +#include "mtk_ddp_comp.h" +#include "mtk_disp_drv.h" + +#define DISP_REG_DSC_CON 0x0 +# define DSC_EN BIT(0) +# define DSC_DUAL_INOUT BIT(2) +# define DSC_IN_SRC_SEL BIT(3) +# define DSC_BYPASS BIT(4) +# define DSC_RELAY BIT(5) +# define DSC_V1_1_EXT BIT(6) +# define DSC_PT_MEM_EN BIT(7) +# define DSC_SW_RESET BIT(8) +# define DSC_EMPTY_FLAG_SEL GENMASK(15, 14) + # define DSC_EMPTY_FLAG_NORMAL_DET 0 + # define DSC_EMPTY_FLAG_ALWAYS_HIGH 1 + # define DSC_EMPTY_FLAG_ALWAYS_LOW 2 + # define DSC_EMPTY_FLAG_DO_NOT_SEND 3 +# define DSC_UFOE_SEL BIT(16) +# define DSC_OUTPUT_SWAP BIT(18) +# define DSC_ZERO_FIFO_STALL_DISABLE BIT(20) + +#define DISP_REG_DSC_SPR 0x14 +#define DISP_REG_DSC_PIC_W 0x18 +# define DSC_PIC_WIDTH GENMASK(15, 0) +# define DSC_PIC_GROUP_WIDTH_M1 GENMASK(31, 16) + +#define DISP_REG_DSC_PIC_H 0x1c +# define DSC_PIC_HEIGHT GENMASK(15, 0) +# define DSC_PIC_HEIGHT_EXT_M1 GENMASK(31, 16) + +#define DISP_REG_DSC_SLICE_W 0x20 +# define DSC_SLICE_WIDTH GENMASK(15, 0) +# define DSC_SLICE_GROUP_WIDTH_M1 GENMASK(31, 16) + +#define DISP_REG_DSC_SLICE_H 0x24 +# define DSC_SLICE_HEIGHT_M1 GENMASK(15, 0) +# define DSC_SLICE_NUM_M1 GENMASK(29, 16) +# define DSC_SLICE_WIDTH_MOD3 GENMASK(31, 30) + +#define DISP_REG_DSC_CHUNK_SIZE 0x28 + +#define DISP_REG_DSC_BUF_SIZE 0x2c +# define DISP_DSC_BUF_SIZE_MASK GENMASK(23, 0) + +#define DISP_REG_DSC_MODE 0x30 +# define DSC_RGB_SWAP BIT(2) +# define DSC_INIT_DELAY_HEIGHT GENMASK(11, 8) + +#define DISP_REG_DSC_CFG 0x34 +# define DSC_CFG_FLATNESS_DET_THRES GENMASK(4, 0) +# define DSC_CFG_FLATNESS_8BITS 2 +# define DSC_CFG_FLATNESS_10BITS 8 +# define DSC_CFG_ICH_EN BIT(5) +# define DSC_CFG_ICH_LINE_CLEAR GENMASK(7, 6) +# define DSC_CFG_V1P1 BIT(8) +# define DSC_CFG_IDLE_MODE BIT(9) +# define DSC_CFG_CRC_EN BIT(12) +# define DSC_CFG_DSC12_BUGFIX BIT(14) +# define DSC_CFG_CORE_CHECKSUM BIT(15) + +#define DISP_REG_DSC_PAD 0x38 +# define DSC_PAD_NUMBER GENMASK(2, 0) + +#define DISP_REG_DSC_ENC_WIDTH 0x3c +# define DSC_ENC_WIDTH_SLICE GENMASK(15, 0) +# define DSC_ENC_WIDTH_PIC GENMASK(31, 16) + +#define DISP_REG_DSC_PIC_PRE_PAD_SIZE 0x40 +# define DSC_PIC_PREPAD_HEIGHT GENMASK(15, 0) +# define DSC_PIC_PREPAD_WIDTH GENMASK(31, 16) + +#define DISP_REG_DSC_DBG_CON 0x60 +# define DSC_CKSM_CAL_EN BIT(9) + +#define DISP_REG_DSC_OUTBUF 0x70 +# define DSC_OBUF_SIZE GENMASK(11, 0) + +#define DISP_REG_DSC_PPS(x) (0x80 + (x * 4)) /* 0..19 */ +# define DSC_P0_UP_LINE_BUF_DEPTH GENMASK(3, 0) +# define DSC_P0_BPC GENMASK(7, 4) +# define DSC_P0_BPP GENMASK(17, 8) +# define DSC_P0_RCT_ON BIT(18) +# define DSC_P0_BLOCK_PRED_EN BIT(19) +# define DSC_P1_INITIAL_XMIT_DELAY GENMASK(15, 0) +# define DSC_P1_INITIAL_DEC_DELAY GENMASK(31, 16) +# define DSC_P2_INITIAL_SCALE_VALUE GENMASK(15, 0) +# define DSC_P2_SCALE_INCR_INTERVAL GENMASK(31, 16) +# define DSC_P3_SCALE_DECR_INTERVAL GENMASK(15, 0) +# define DSC_P3_FIRST_LINE_BPG_OFFSET GENMASK(31, 16) +# define DSC_P4_NFL_BPG_OFFSET GENMASK(15, 0) +# define DSC_P4_SLICE_BPG_OFFSET GENMASK(31, 16) +# define DSC_P5_INITIAL_OFFSET GENMASK(15, 0) +# define DSC_P5_FINAL_OFFSET GENMASK(31, 16) +# define DSC_P6_FLATNESS_MIN_QP GENMASK(4, 0) +# define DSC_P6_FLATNESS_MAX_QP GENMASK(12, 8) +# define DSC_P6_RC_MODEL_SIZE GENMASK(31, 16) +# define DSC_P7_RC_EDGE_FACTOR GENMASK(7, 0) +# define DSC_P7_RC_QUANT_INCR_LIMIT0 GENMASK(12, 8) +# define DSC_P7_RC_QUANT_INCR_LIMIT1 GENMASK(20, 16) +# define DSC_P7_RC_TGT_OFFSET_HI GENMASK(27, 24) +# define DSC_P7_RC_TGT_OFFSET_LO GENMASK(31, 28) +# define DSC_P8_RC_BUF_THR_X GENMASK(7, 0) +# define DSC_P12_RC_RANGE_MIN_QP GENMASK(4, 0) +# define DSC_P12_RC_RANGE_MAX_QP GENMASK(9, 5) +# define DSC_P12_RC_RANGE_BPG_OFFSET GENMASK(15, 10) + +#define DISP_REG_DSC_SHADOW 0x200 +# define DSC_FORCE_COMMIT BIT(0) +# define DSC_BYPASS_SHADOW BIT(1) +# define DSC_READ_WORKING BIT(2) +# define DSC_SHADOW_DSC_VERSION_MINOR GENMASK(8, 5) + +struct mtk_dsc { + struct clk *clk; + void __iomem *reg; + struct cmdq_client_reg cmdq_reg; + bool dsc_config_done; +}; + +int mtk_dsc_clk_enable(struct device *dev) +{ + struct mtk_dsc *disp_dsc =3D dev_get_drvdata(dev); + + return clk_prepare_enable(disp_dsc->clk); +} + +void mtk_dsc_clk_disable(struct device *dev) +{ + struct mtk_dsc *disp_dsc =3D dev_get_drvdata(dev); + + clk_disable_unprepare(disp_dsc->clk); +} + +static void mtk_dsc_pps_setup(struct mtk_dsc *disp_dsc, struct drm_dsc_con= fig *dsc_cfg) +{ + struct drm_dsc_rc_range_parameters *rcrp =3D dsc_cfg->rc_range_params; + u16 *rbt =3D dsc_cfg->rc_buf_thresh; + u32 data; + int i, j; + + /* PPS 0 - Note: Fractional BPP is not supported! */ + data =3D FIELD_PREP(DSC_P0_UP_LINE_BUF_DEPTH, dsc_cfg->line_buf_depth); + data |=3D FIELD_PREP(DSC_P0_BPC, dsc_cfg->bits_per_component); + data |=3D FIELD_PREP(DSC_P0_BPP, dsc_cfg->bits_per_pixel); + data |=3D DSC_P0_RCT_ON | DSC_P0_BLOCK_PRED_EN; + writel(data, disp_dsc->reg + DISP_REG_DSC_PPS(0)); + + /* PPS 1 */ + data =3D FIELD_PREP(DSC_P1_INITIAL_XMIT_DELAY, dsc_cfg->initial_xmit_dela= y); + data |=3D FIELD_PREP(DSC_P1_INITIAL_DEC_DELAY, dsc_cfg->initial_dec_delay= ); + writel(data, disp_dsc->reg + DISP_REG_DSC_PPS(1)); + + /* PPS 2 */ + data =3D FIELD_PREP(DSC_P2_INITIAL_SCALE_VALUE, dsc_cfg->initial_scale_va= lue); + data |=3D FIELD_PREP(DSC_P2_SCALE_INCR_INTERVAL, dsc_cfg->scale_increment= _interval); + writel(data, disp_dsc->reg + DISP_REG_DSC_PPS(2)); + + /* PPS 3 */ + data =3D FIELD_PREP(DSC_P3_SCALE_DECR_INTERVAL, dsc_cfg->scale_decrement_= interval); + data |=3D FIELD_PREP(DSC_P3_FIRST_LINE_BPG_OFFSET, dsc_cfg->first_line_bp= g_offset); + writel(data, disp_dsc->reg + DISP_REG_DSC_PPS(3)); + + /* PPS 4 */ + data =3D FIELD_PREP(DSC_P4_NFL_BPG_OFFSET, dsc_cfg->nfl_bpg_offset); + data |=3D FIELD_PREP(DSC_P4_SLICE_BPG_OFFSET, dsc_cfg->slice_bpg_offset); + writel(data, disp_dsc->reg + DISP_REG_DSC_PPS(4)); + + /* PPS 5 */ + data =3D FIELD_PREP(DSC_P5_INITIAL_OFFSET, dsc_cfg->initial_offset); + data |=3D FIELD_PREP(DSC_P5_FINAL_OFFSET, dsc_cfg->final_offset); + writel(data, disp_dsc->reg + DISP_REG_DSC_PPS(5)); + + /* PPS 6 */ + data =3D FIELD_PREP(DSC_P6_FLATNESS_MIN_QP, dsc_cfg->flatness_min_qp); + data |=3D FIELD_PREP(DSC_P6_FLATNESS_MAX_QP, dsc_cfg->flatness_max_qp); + writel(data, disp_dsc->reg + DISP_REG_DSC_PPS(6)); + + /* PPS 7 */ + data =3D FIELD_PREP(DSC_P7_RC_EDGE_FACTOR, dsc_cfg->rc_edge_factor); + data |=3D FIELD_PREP(DSC_P7_RC_QUANT_INCR_LIMIT0, dsc_cfg->rc_quant_incr_= limit0); + data |=3D FIELD_PREP(DSC_P7_RC_QUANT_INCR_LIMIT1, dsc_cfg->rc_quant_incr_= limit1); + data |=3D FIELD_PREP(DSC_P7_RC_TGT_OFFSET_HI, dsc_cfg->rc_tgt_offset_high= ); + data |=3D FIELD_PREP(DSC_P7_RC_TGT_OFFSET_LO, dsc_cfg->rc_tgt_offset_low); + writel(data, disp_dsc->reg + DISP_REG_DSC_PPS(7)); + + /* PPS 8..11 - Each register holds 4 RC buffer thresholds (PPS 11 has two= ) */ + for (i =3D 0; i < 4; i++) { + u8 block_num =3D i * 4; + data =3D 0; + + for (j =3D 0; j < 4; j++) { + u8 buf_index =3D block_num + j; + u8 data_shift =3D j * 8; + + /* rc_buf_thresh holds 14 elements in total */ + if (buf_index > 13) + break; + + data |=3D (rbt[buf_index] & DSC_P8_RC_BUF_THR_X) << data_shift; + } + writel(data, disp_dsc->reg + DISP_REG_DSC_PPS(8 + i)); + } + + /* PPS 12..18 - Each register holds two sets of RC range parameters */ + for (i =3D 0; i < 7; i++) { + u8 block_num =3D i * 2; + data =3D 0; + + for (j =3D 0; j < 2; j++) { + u8 buf_index =3D block_num + j; + u8 data_shift =3D j * 16; + u32 range_data; + + range_data =3D FIELD_PREP(DSC_P12_RC_RANGE_MIN_QP, + rcrp[buf_index].range_min_qp); + range_data |=3D FIELD_PREP(DSC_P12_RC_RANGE_MAX_QP, + rcrp[buf_index].range_max_qp); + range_data |=3D FIELD_PREP(DSC_P12_RC_RANGE_BPG_OFFSET, + rcrp[buf_index].range_bpg_offset); + data |=3D range_data << data_shift; + + /* rc_range_params holds 15 elements in total */ + if (buf_index =3D=3D 13) + break; + } + writel(data, disp_dsc->reg + DISP_REG_DSC_PPS(12 + i)); + } + + /* PPS 19 - Last RC range register, holds only one set of parameters */ + writel(FIELD_PREP(DSC_P12_RC_RANGE_MIN_QP, rcrp[14].range_min_qp) | + FIELD_PREP(DSC_P12_RC_RANGE_MAX_QP, rcrp[14].range_max_qp) | + FIELD_PREP(DSC_P12_RC_RANGE_BPG_OFFSET, rcrp[14].range_bpg_offset), + disp_dsc->reg + DISP_REG_DSC_PPS(19)); +} + +void mtk_dsc_setup(struct device *dev, struct drm_dsc_config *dsc_cfg) +{ + struct mtk_dsc *disp_dsc =3D dev_get_drvdata(dev); + u32 dsc_slice_w, dsc_slice_h, dsc_mode, dsc_cfg_rval, dsc_shadow; + u32 dsc_dbg_con, dsc_con, dsc_enc_width, dsc_pic_w, dsc_pic_h; + u32 pic_group_width, pic_height_ext_num, slice_group_width; + u32 chunk_size, dsc_pad_num, dsc_pre_pad_sz; + bool dsc_en_bit; + + pic_height_ext_num =3D dsc_cfg->pic_height + dsc_cfg->slice_height - 1; + pic_group_width =3D dsc_cfg->slice_width * 4; + pic_group_width /=3D 3; + + slice_group_width =3D dsc_cfg->slice_width + 2; + slice_group_width /=3D 3; + + if (dsc_cfg->slice_chunk_size) + chunk_size =3D dsc_cfg->slice_chunk_size; + else + chunk_size =3D dsc_cfg->slice_width * dsc_cfg->bits_per_pixel / 8 / 16; + + dsc_enc_width =3D FIELD_PREP(DSC_ENC_WIDTH_PIC, dsc_cfg->pic_width) | + FIELD_PREP(DSC_ENC_WIDTH_SLICE, dsc_cfg->slice_width); + + dsc_pic_w =3D FIELD_PREP(DSC_PIC_GROUP_WIDTH_M1, pic_group_width - 1); + dsc_pic_w |=3D FIELD_PREP(DSC_PIC_WIDTH, dsc_cfg->pic_width); + dsc_pic_h =3D FIELD_PREP(DSC_PIC_HEIGHT_EXT_M1, pic_height_ext_num - 1); + dsc_pic_h |=3D FIELD_PREP(DSC_PIC_HEIGHT, dsc_cfg->pic_height - 1); + + dsc_slice_w =3D FIELD_PREP(DSC_SLICE_GROUP_WIDTH_M1, slice_group_width - = 1); + dsc_slice_w |=3D FIELD_PREP(DSC_SLICE_WIDTH, dsc_cfg->slice_width); + dsc_slice_h =3D FIELD_PREP(DSC_SLICE_WIDTH_MOD3, dsc_cfg->slice_width % 3= ); + dsc_slice_h |=3D FIELD_PREP(DSC_SLICE_NUM_M1, + (pic_height_ext_num / dsc_cfg->slice_height) - 1); + dsc_slice_h |=3D FIELD_PREP(DSC_SLICE_HEIGHT_M1, dsc_cfg->slice_height - = 1); + + dsc_pad_num =3D (3 - ((chunk_size * 2) % 3)) % 3; + dsc_pad_num =3D FIELD_PREP(DSC_PAD_NUMBER, dsc_pad_num); + + dsc_pre_pad_sz =3D FIELD_PREP(DSC_PIC_PREPAD_HEIGHT, dsc_cfg->pic_height); + dsc_pre_pad_sz |=3D FIELD_PREP(DSC_PIC_PREPAD_WIDTH, dsc_cfg->pic_width); + + dsc_mode =3D FIELD_PREP(DSC_INIT_DELAY_HEIGHT, 4); + dsc_mode |=3D FIELD_PREP(DSC_RGB_SWAP, 0); + + /* Must enable checksum calc in DBG if enabling core checksum in CFG */ + dsc_cfg_rval =3D DSC_CFG_ICH_EN | DSC_CFG_CRC_EN | DSC_CFG_DSC12_BUGFIX | + DSC_CFG_CORE_CHECKSUM; + dsc_dbg_con =3D DSC_CKSM_CAL_EN; + + if (dsc_cfg->bits_per_component =3D=3D 8) + dsc_cfg_rval |=3D FIELD_PREP_CONST(DSC_CFG_FLATNESS_DET_THRES, + DSC_CFG_FLATNESS_8BITS); + else + dsc_cfg_rval |=3D FIELD_PREP_CONST(DSC_CFG_FLATNESS_DET_THRES, + DSC_CFG_FLATNESS_10BITS); + + dsc_shadow =3D FIELD_PREP(DSC_SHADOW_DSC_VERSION_MINOR, + dsc_cfg->dsc_version_minor); + dsc_shadow |=3D DSC_FORCE_COMMIT | DSC_BYPASS_SHADOW; + + /* If DSC is currently enabled, disable it before setup and re-enable aft= er */ + dsc_con =3D readl(disp_dsc->reg + DISP_REG_DSC_CON); + if (dsc_con & DSC_EN) { + dsc_en_bit =3D true; + writel(dsc_con & ~DSC_EN, disp_dsc->reg + DISP_REG_DSC_CON); + } else { + dsc_en_bit =3D false; + } + + writel(0, disp_dsc->reg + DISP_REG_DSC_SPR); + writel(dsc_enc_width, disp_dsc->reg + DISP_REG_DSC_ENC_WIDTH); + writel(dsc_pic_w, disp_dsc->reg + DISP_REG_DSC_PIC_W); + writel(dsc_pic_h, disp_dsc->reg + DISP_REG_DSC_PIC_H); + writel(dsc_slice_w, disp_dsc->reg + DISP_REG_DSC_SLICE_W); + writel(dsc_slice_h, disp_dsc->reg + DISP_REG_DSC_SLICE_H); + writel(((chunk_size * 4) / 3) << 16 | chunk_size, + disp_dsc->reg + DISP_REG_DSC_CHUNK_SIZE); + writel(dsc_pre_pad_sz, disp_dsc->reg + DISP_REG_DSC_PIC_PRE_PAD_SIZE); + writel(dsc_pad_num, disp_dsc->reg + DISP_REG_DSC_PAD); + writel(FIELD_PREP(DISP_DSC_BUF_SIZE_MASK, chunk_size * dsc_cfg->slice_hei= ght), + disp_dsc->reg + DISP_REG_DSC_BUF_SIZE); + writel(dsc_mode, disp_dsc->reg + DISP_REG_DSC_MODE); + writel(dsc_cfg_rval, disp_dsc->reg + DISP_REG_DSC_CFG); + writel(dsc_dbg_con, disp_dsc->reg + DISP_REG_DSC_DBG_CON); + writel(FIELD_PREP_CONST(DSC_OBUF_SIZE, 1040), disp_dsc->reg + DISP_REG_DS= C_OUTBUF); + writel(dsc_shadow, disp_dsc->reg + DISP_REG_DSC_SHADOW); + + /* Set PPS registers configuration */ + mtk_dsc_pps_setup(disp_dsc, dsc_cfg); + + dsc_con =3D FIELD_PREP_CONST(DSC_EMPTY_FLAG_SEL, DSC_EMPTY_FLAG_ALWAYS_LO= W); + dsc_con |=3D DSC_V1_1_EXT | DSC_UFOE_SEL | DSC_PT_MEM_EN; + dsc_con |=3D DSC_ZERO_FIFO_STALL_DISABLE; + + if (dsc_en_bit) + dsc_con |=3D DSC_EN; + + writel(dsc_con, disp_dsc->reg + DISP_REG_DSC_CON); + + disp_dsc->dsc_config_done =3D true; +} + +void mtk_dsc_start(struct device *dev) +{ + struct mtk_dsc *disp_dsc =3D dev_get_drvdata(dev); + + /* If no DSC or config not done, set bypass mode */ + if (!disp_dsc->dsc_config_done) { + mtk_ddp_write_mask(NULL, DSC_BYPASS, &disp_dsc->cmdq_reg, + disp_dsc->reg, DISP_REG_DSC_CON, DSC_BYPASS); + mtk_ddp_write_mask(NULL, DSC_UFOE_SEL, &disp_dsc->cmdq_reg, + disp_dsc->reg, DISP_REG_DSC_CON, DSC_UFOE_SEL); + mtk_ddp_write_mask(NULL, DSC_DUAL_INOUT, &disp_dsc->cmdq_reg, + disp_dsc->reg, DISP_REG_DSC_CON, DSC_DUAL_INOUT); + } + + mtk_ddp_write_mask(NULL, DSC_EN, &disp_dsc->cmdq_reg, + disp_dsc->reg, DISP_REG_DSC_CON, DSC_EN); +} + +void mtk_dsc_stop(struct device *dev) +{ + struct mtk_dsc *disp_dsc =3D dev_get_drvdata(dev); + + writel(0, disp_dsc->reg + DISP_REG_DSC_CON); +} + +static int mtk_dsc_bind(struct device *dev, struct device *master, void *d= ata) +{ + return 0; +} + +static void mtk_dsc_unbind(struct device *dev, struct device *master, void= *data) +{ +} + +static const struct component_ops mtk_dsc_component_ops =3D { + .bind =3D mtk_dsc_bind, + .unbind =3D mtk_dsc_unbind, +}; + +static int mtk_dsc_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct mtk_dsc *priv; + struct resource *res; + int ret; + + priv =3D devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->clk =3D devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) + return dev_err_probe(dev, PTR_ERR(priv->clk), + "failed to get clk\n"); + + priv->reg =3D devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(priv->reg)) + return dev_err_probe(dev, PTR_ERR(priv->reg), + "failed to do ioremap\n"); + +#if IS_REACHABLE(CONFIG_MTK_CMDQ) + ret =3D cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0); + if (ret) + return dev_err_probe(dev, ret, "failed to get gce client reg\n"); +#endif + + platform_set_drvdata(pdev, priv); + + ret =3D devm_pm_runtime_enable(dev); + if (ret) + return ret; + + ret =3D component_add(dev, &mtk_dsc_component_ops); + if (ret) + return dev_err_probe(dev, ret, "failed to add component\n"); + + return 0; +} + +static void mtk_dsc_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &mtk_dsc_component_ops); +} + +static const struct of_device_id mtk_dsc_driver_dt_match[] =3D { + { .compatible =3D "mediatek,mt8195-disp-dsc" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mtk_dsc_driver_dt_match); + +struct platform_driver mtk_disp_dsc_driver =3D { + .probe =3D mtk_dsc_probe, + .remove =3D mtk_dsc_remove, + .driver =3D { + .name =3D "mediatek-disp-dsc", + .of_match_table =3D mtk_dsc_driver_dt_match, + }, +}; diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/media= tek/mtk_drm_drv.c index c86a3f54f35b..bd2d17017bd2 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -1164,6 +1164,7 @@ static int mtk_drm_probe(struct platform_device *pdev) if (comp_type =3D=3D MTK_DISP_AAL || comp_type =3D=3D MTK_DISP_CCORR || comp_type =3D=3D MTK_DISP_COLOR || + comp_type =3D=3D MTK_DISP_DSC || comp_type =3D=3D MTK_DISP_GAMMA || comp_type =3D=3D MTK_DISP_MERGE || comp_type =3D=3D MTK_DISP_OVL || @@ -1272,6 +1273,7 @@ static struct platform_driver * const mtk_drm_drivers= [] =3D { &mtk_disp_aal_driver, &mtk_disp_ccorr_driver, &mtk_disp_color_driver, + &mtk_disp_dsc_driver, &mtk_disp_gamma_driver, &mtk_disp_merge_driver, &mtk_disp_ovl_adaptor_driver, diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/media= tek/mtk_drm_drv.h index d48da019a4a3..43aac2d956e7 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h @@ -71,6 +71,7 @@ struct mtk_drm_private { extern struct platform_driver mtk_disp_aal_driver; extern struct platform_driver mtk_disp_ccorr_driver; extern struct platform_driver mtk_disp_color_driver; +extern struct platform_driver mtk_disp_dsc_driver; extern struct platform_driver mtk_disp_gamma_driver; extern struct platform_driver mtk_disp_merge_driver; extern struct platform_driver mtk_disp_ovl_adaptor_driver; diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/= mtk_dsi.c index 3f3f56eed3f9..8ab5c3431dbb 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -18,6 +18,8 @@ #include