[PATCH v1 17/17] drm/mediatek: add DSC support for MT8195
jason-jh.lin
jason-jh.lin at mediatek.com
Tue Jul 6 21:12:49 PDT 2021
1. Add DSC module file.
2. Add mtk_panel_ext source file to get the mtk_panel_dsc_params
from panel.
3. Add DSC related path to mtk-mmsys routing table.
Signed-off-by: jason-jh.lin <jason-jh.lin at mediatek.com>
---
drivers/gpu/drm/mediatek/Makefile | 4 +-
drivers/gpu/drm/mediatek/mtk_disp_drv.h | 8 +
drivers/gpu/drm/mediatek/mtk_disp_dsc.c | 286 ++++++++++++++++
drivers/gpu/drm/mediatek/mtk_drm_crtc.h | 1 +
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 13 +
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 1 +
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 4 +
drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 +
drivers/gpu/drm/mediatek/mtk_panel_ext.c | 136 ++++++++
drivers/gpu/drm/mediatek/mtk_panel_ext.h | 344 ++++++++++++++++++++
drivers/soc/mediatek/mt8195-mmsys.h | 18 +
drivers/soc/mediatek/mtk-mutex.c | 1 +
include/linux/soc/mediatek/mtk-mmsys.h | 3 +
13 files changed, 819 insertions(+), 1 deletion(-)
create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_dsc.c
create mode 100644 drivers/gpu/drm/mediatek/mtk_panel_ext.c
create mode 100644 drivers/gpu/drm/mediatek/mtk_panel_ext.h
diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index 5fd95b9d5aae..4dc0b2901a22 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -6,13 +6,15 @@ mediatek-drm-y := mtk_disp_ccorr.o \
mtk_disp_ovl.o \
mtk_disp_rdma.o \
mtk_disp_merge.o \
+ mtk_disp_dsc.o \
mtk_drm_crtc.o \
mtk_drm_ddp_comp.o \
mtk_drm_drv.o \
mtk_drm_gem.o \
mtk_drm_plane.o \
mtk_dsi.o \
- mtk_dpi.o
+ mtk_dpi.o \
+ mtk_panel_ext.o
obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index 7fd5260e2a72..11a6c9d6cff3 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -100,4 +100,12 @@ void mtk_merge_config(struct device *dev, unsigned int width,
void mtk_merge_start(struct device *dev);
void mtk_merge_stop(struct device *dev);
+int mtk_dsc_clk_enable(struct device *dev);
+void mtk_dsc_clk_disable(struct device *dev);
+void mtk_dsc_config(struct device *dev, unsigned int width,
+ unsigned int height, unsigned int vrefresh,
+ unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
+void mtk_dsc_start(struct device *dev);
+void mtk_dsc_stop(struct device *dev);
+
#endif
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_dsc.c b/drivers/gpu/drm/mediatek/mtk_disp_dsc.c
new file mode 100644
index 000000000000..5da820feead5
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_dsc.c
@@ -0,0 +1,286 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/soc/mediatek/mtk-cmdq.h>
+
+#include "mtk_drm_crtc.h"
+#include "mtk_drm_ddp_comp.h"
+#include "mtk_drm_gem.h"
+#include "mtk_disp_drv.h"
+#ifdef CONFIG_MTK_DPTX_SUPPORT
+#include "mtk_dp_api.h"
+#endif
+
+#define DISP_REG_DSC_CON 0x0000
+#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_EMPTY_FLAG_SEL 0xc000
+#define DSC_UFOE_SEL BIT(16)
+#define DISP_REG_DSC_OBUF 0x0070
+
+struct mtk_disp_dsc_data {
+ bool support_shadow;
+};
+
+/**
+ * struct mtk_disp_dsc - DISP_DSC driver structure
+ * @clk - clk of dsc hardware
+ * @regs - hardware register address of dsc
+ * @ddp_comp - structure containing type enum and hardware resources
+ * @cmdq_reg - structure containing cmdq hardware resource
+ * @data - dsc driver data
+ * @enable - enable dsc hardward
+ */
+struct mtk_disp_dsc {
+ struct clk *clk;
+ void __iomem *regs;
+ struct mtk_ddp_comp ddp_comp;
+ struct cmdq_client_reg cmdq_reg;
+ const struct mtk_disp_dsc_data *data;
+ int enable;
+};
+
+void mtk_dsc_start(struct device *dev)
+{
+ struct mtk_disp_dsc *dsc = dev_get_drvdata(dev);
+ void __iomem *baddr = dsc->regs;
+ int ret = 0;
+
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0)
+ DRM_ERROR("Failed to enable power domain: %d\n", ret);
+
+ if (dsc->enable) {
+ int high = BIT(14);
+ int obud_sw = BIT(31);
+ int obud_size = 706; /* unit is 6 byte */
+
+ /* DSC Empty flag always high */
+ mtk_ddp_write_mask(NULL, high,
+ &dsc->cmdq_reg, baddr,
+ DISP_REG_DSC_CON, DSC_EMPTY_FLAG_SEL);
+
+ /* DSC output buffer as FHD(plus) */
+ mtk_ddp_write_mask(NULL, (obud_sw | obud_size),
+ &dsc->cmdq_reg, baddr,
+ DISP_REG_DSC_OBUF, ~0);
+ }
+
+ mtk_ddp_write_mask(NULL, DSC_EN,
+ &dsc->cmdq_reg, baddr,
+ DISP_REG_DSC_CON, DSC_EN);
+
+ pr_debug("dsc_start:0x%x\n", readl(baddr + DISP_REG_DSC_CON));
+}
+
+void mtk_dsc_stop(struct device *dev)
+{
+ struct mtk_disp_dsc *dsc = dev_get_drvdata(dev);
+ void __iomem *baddr = dsc->regs;
+ int ret = 0;
+
+ mtk_ddp_write_mask(NULL, 0x0, &dsc->cmdq_reg, baddr,
+ DISP_REG_DSC_CON, DSC_EN);
+
+ pr_debug("dsc_stop:0x%x\n", readl(baddr + DISP_REG_DSC_CON));
+
+ ret = pm_runtime_put(dev);
+ if (ret < 0)
+ DRM_ERROR("Failed to disable power domain: %d\n", ret);
+}
+
+int mtk_dsc_clk_enable(struct device *dev)
+{
+ struct mtk_disp_dsc *dsc = dev_get_drvdata(dev);
+
+ return clk_prepare_enable(dsc->clk);
+}
+
+void mtk_dsc_clk_disable(struct device *dev)
+{
+ struct mtk_disp_dsc *dsc = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(dsc->clk);
+}
+
+static struct mtk_panel_dsc_params *mtk_dsc_default_setting(void)
+{
+ static struct mtk_panel_dsc_params dsc_params = {
+ .enable = 0, /* 0: bypass mode */
+ .ver = 2,
+ .slice_mode = 1,
+ .rgb_swap = 0,
+ .dsc_cfg = 0x12, /* flatness_det_thr, 8bit */
+ .rct_on = 1, // default
+ .bit_per_channel = 8,
+ .dsc_line_buf_depth = 13, /* 9, 11: for 10bit */
+ .bp_enable = 1, /* align vend */
+ .bit_per_pixel = 128, /* 16 x bpp */
+ .pic_height = 2160,
+ .pic_width = 3840, /* for dp port 4k scenario */
+ .slice_height = 8,
+ .slice_width = 1920, /* frame_width/slice mode */
+ .chunk_size = 1920,
+ .xmit_delay = 512,
+ .dec_delay = 1216,
+ .scale_value = 32,
+ .increment_interval = 286,
+ .decrement_interval = 26,
+ .line_bpg_offset = 12,
+ .nfl_bpg_offset = 3511,
+ .slice_bpg_offset = 916,
+ .initial_offset = 6144,
+ .final_offset = 4336,
+ .flatness_minqp = 3,
+ .flatness_maxqp = 12,
+ .rc_model_size = 8192,
+ .rc_edge_factor = 6,
+ .rc_quant_incr_limit0 = 11,
+ .rc_quant_incr_limit1 = 11,
+ .rc_tgt_offset_hi = 3,
+ .rc_tgt_offset_lo = 3,
+ };
+
+ return &dsc_params;
+}
+
+void mtk_dsc_config(struct device *dev, unsigned int w,
+ unsigned int h, unsigned int vrefresh,
+ unsigned int bpc, struct cmdq_pkt *handle)
+{
+ struct mtk_disp_dsc *dsc = dev_get_drvdata(dev);
+ struct mtk_ddp_comp *comp = &dsc->ddp_comp;
+ struct mtk_panel_dsc_params *dsc_params;
+
+ dsc_params = mtk_dsc_default_setting();
+
+ if (dsc_params->enable == 1) {
+ /* dsc enable mode not support yet */
+ pr_debug("comp_id:%d, w:%d, h:%d\n",
+ comp->id, w, h);
+ pr_debug("slice_mode:%d, slice(%d,%d), bpp:%d\n",
+ dsc_params->slice_mode, dsc_params->slice_width,
+ dsc_params->slice_height, dsc_params->bit_per_pixel);
+ } else {
+ /* dsc bypass mode */
+ mtk_ddp_write_mask(handle, DSC_BYPASS,
+ &dsc->cmdq_reg, dsc->regs,
+ DISP_REG_DSC_CON, DSC_BYPASS);
+ mtk_ddp_write_mask(handle, DSC_UFOE_SEL,
+ &dsc->cmdq_reg, dsc->regs,
+ DISP_REG_DSC_CON, DSC_UFOE_SEL);
+ mtk_ddp_write_mask(handle, DSC_DUAL_INOUT,
+ &dsc->cmdq_reg, dsc->regs,
+ DISP_REG_DSC_CON, DSC_DUAL_INOUT);
+ dsc->enable = false;
+ }
+}
+
+static int mtk_disp_dsc_bind(struct device *dev, struct device *master,
+ void *data)
+{
+ return 0;
+}
+
+static void mtk_disp_dsc_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+}
+
+static const struct component_ops mtk_disp_dsc_component_ops = {
+ .bind = mtk_disp_dsc_bind,
+ .unbind = mtk_disp_dsc_unbind,
+};
+
+static int mtk_disp_dsc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct mtk_disp_dsc *priv;
+ int irq;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ priv->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(priv->clk)) {
+ dev_err(dev, "failed to get dsc clk\n");
+ return PTR_ERR(priv->clk);
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->regs)) {
+ dev_err(dev, "failed to ioremap dsc\n");
+ return PTR_ERR(priv->regs);
+ }
+
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+ ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
+ if (ret)
+ dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
+#endif
+
+ priv->data = of_device_get_match_data(dev);
+ platform_set_drvdata(pdev, priv);
+
+ pm_runtime_enable(dev);
+
+ ret = component_add(dev, &mtk_disp_dsc_component_ops);
+ if (ret != 0) {
+ dev_err(dev, "Failed to add component: %d\n", ret);
+ pm_runtime_disable(dev);
+ }
+
+ return ret;
+}
+
+static int mtk_disp_dsc_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &mtk_disp_dsc_component_ops);
+
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+}
+
+static const struct mtk_disp_dsc_data mt8195_dsc_driver_data = {
+ .support_shadow = false,
+};
+
+static const struct of_device_id mtk_disp_dsc_driver_dt_match[] = {
+ {
+ .compatible = "mediatek,mt8195-disp-dsc",
+ .data = &mt8195_dsc_driver_data
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, mtk_disp_dsc_driver_dt_match);
+
+struct platform_driver mtk_disp_dsc_driver = {
+ .probe = mtk_disp_dsc_probe,
+ .remove = mtk_disp_dsc_remove,
+ .driver = {
+ .name = "mediatek-disp-dsc",
+ .owner = THIS_MODULE,
+ .of_match_table = mtk_disp_dsc_driver_dt_match,
+ },
+};
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.h b/drivers/gpu/drm/mediatek/mtk_drm_crtc.h
index 7419cd0fb424..7b8f9cb96d44 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.h
@@ -9,6 +9,7 @@
#include <drm/drm_crtc.h>
#include "mtk_drm_ddp_comp.h"
#include "mtk_drm_plane.h"
+#include "mtk_panel_ext.h"
#define MTK_LUT_SIZE 512
#define MTK_MAX_BPC 10
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
index 2ccf3db1950d..b68bde6eb6ed 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
@@ -347,6 +347,14 @@ static const struct mtk_ddp_comp_funcs ddp_merge = {
.config = mtk_merge_config,
};
+static const struct mtk_ddp_comp_funcs ddp_dsc = {
+ .config = mtk_dsc_config,
+ .start = mtk_dsc_start,
+ .stop = mtk_dsc_stop,
+ .clk_enable = mtk_dsc_clk_enable,
+ .clk_disable = mtk_dsc_clk_disable,
+};
+
static const struct mtk_ddp_comp_funcs ddp_ufoe = {
.clk_enable = mtk_ddp_clk_enable,
.clk_disable = mtk_ddp_clk_disable,
@@ -371,6 +379,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
[MTK_DISP_OD] = "od",
[MTK_DISP_BLS] = "bls",
[MTK_DISP_MERGE] = "merge",
+ [MTK_DISP_DSC] = "dsc",
};
struct mtk_ddp_comp_match {
@@ -412,6 +421,9 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_MERGE3] = { MTK_DISP_MERGE, 3, &ddp_merge },
[DDP_COMPONENT_MERGE4] = { MTK_DISP_MERGE, 4, &ddp_merge },
[DDP_COMPONENT_MERGE5] = { MTK_DISP_MERGE, 5, &ddp_merge },
+ [DDP_COMPONENT_DSC0] = { MTK_DISP_DSC, 0, &ddp_dsc },
+ [DDP_COMPONENT_DSC1] = { MTK_DISP_DSC, 1, &ddp_dsc },
+ [DDP_COMPONENT_DSC1_VIRTUAL0] = { MTK_DISP_DSC, -1, &ddp_dsc },
[DDP_COMPONENT_UFOE] = { MTK_DISP_UFOE, 0, &ddp_ufoe },
[DDP_COMPONENT_WDMA0] = { MTK_DISP_WDMA, 0, NULL },
[DDP_COMPONENT_WDMA1] = { MTK_DISP_WDMA, 1, NULL },
@@ -531,6 +543,7 @@ int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp,
type == MTK_DISP_COLOR ||
type == MTK_DISP_GAMMA ||
type == MTK_DISP_MERGE ||
+ type == MTK_DISP_DSC ||
type == MTK_DPI ||
type == MTK_DSI ||
type == MTK_DISP_OVL ||
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
index 038775b4531b..b4f6b52dac69 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
@@ -35,6 +35,7 @@ enum mtk_ddp_comp_type {
MTK_DISP_OD,
MTK_DISP_BLS,
MTK_DISP_MERGE,
+ MTK_DISP_DSC,
MTK_DDP_COMP_TYPE_MAX,
};
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index f891316008aa..af3e69e0edbe 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -464,6 +464,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
.data = (void *)MTK_DISP_DITHER },
{ .compatible = "mediatek,mt8195-disp-merge",
.data = (void *)MTK_DISP_MERGE },
+ { .compatible = "mediatek,mt8195-disp-dsc",
+ .data = (void *)MTK_DISP_DSC },
{ .compatible = "mediatek,mt8173-disp-ufoe",
.data = (void *)MTK_DISP_UFOE },
{ .compatible = "mediatek,mt2701-dsi",
@@ -582,6 +584,7 @@ static int mtk_drm_probe(struct platform_device *pdev)
comp_type == MTK_DISP_COLOR ||
comp_type == MTK_DISP_GAMMA ||
comp_type == MTK_DISP_MERGE ||
+ comp_type == MTK_DISP_DSC ||
comp_type == MTK_DISP_OVL ||
comp_type == MTK_DISP_OVL_2L ||
comp_type == MTK_DISP_RDMA ||
@@ -687,6 +690,7 @@ static struct platform_driver * const mtk_drm_drivers[] = {
&mtk_dpi_driver,
&mtk_drm_platform_driver,
&mtk_disp_merge_driver,
+ &mtk_disp_dsc_driver,
&mtk_dsi_driver,
};
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index 18548a373626..7f821b96aac3 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -52,6 +52,7 @@ extern struct platform_driver mtk_disp_gamma_driver;
extern struct platform_driver mtk_disp_ovl_driver;
extern struct platform_driver mtk_disp_rdma_driver;
extern struct platform_driver mtk_disp_merge_driver;
+extern struct platform_driver mtk_disp_dsc_driver;
extern struct platform_driver mtk_dpi_driver;
extern struct platform_driver mtk_dsi_driver;
diff --git a/drivers/gpu/drm/mediatek/mtk_panel_ext.c b/drivers/gpu/drm/mediatek/mtk_panel_ext.c
new file mode 100644
index 000000000000..5887a1cd08bc
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_panel_ext.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_mipi_dsi.h>
+
+#include <drm/drm_panel.h>
+
+#include "mtk_panel_ext.h"
+
+struct _panel_rst_ctx {
+ struct drm_panel *panel;
+ panel_tch_rst rst_cb;
+};
+
+static DEFINE_MUTEX(panel_ext_lock);
+static LIST_HEAD(panel_ext_list);
+static struct _panel_rst_ctx panel_rst_ctx;
+
+void mtk_panel_init(struct mtk_panel_ctx *ctx)
+{
+ INIT_LIST_HEAD(&ctx->list);
+}
+
+void mtk_panel_add(struct mtk_panel_ctx *ctx)
+{
+ mutex_lock(&panel_ext_lock);
+ list_add_tail(&ctx->list, &panel_ext_list);
+ mutex_unlock(&panel_ext_lock);
+}
+
+void mtk_panel_remove(struct mtk_panel_ctx *ctx)
+{
+ mutex_lock(&panel_ext_lock);
+ list_del_init(&ctx->list);
+ mutex_unlock(&panel_ext_lock);
+}
+
+int mtk_panel_attach(struct mtk_panel_ctx *ctx, struct drm_panel *panel)
+{
+ if (ctx->panel)
+ return -EBUSY;
+
+ ctx->panel = panel;
+
+ return 0;
+}
+
+int mtk_panel_tch_handle_reg(struct drm_panel *panel)
+{
+ mutex_lock(&panel_ext_lock);
+ if (panel_rst_ctx.panel) {
+ mutex_unlock(&panel_ext_lock);
+ return -EEXIST;
+ }
+ panel_rst_ctx.panel = panel;
+ mutex_unlock(&panel_ext_lock);
+
+ return 0;
+}
+
+void **mtk_panel_tch_handle_init(void)
+{
+ return (void **)&panel_rst_ctx.rst_cb;
+}
+
+int mtk_panel_tch_rst(struct drm_panel *panel)
+{
+ int ret = 0;
+
+ mutex_lock(&panel_ext_lock);
+ if (panel_rst_ctx.rst_cb && panel_rst_ctx.panel == panel)
+ panel_rst_ctx.rst_cb();
+ else
+ ret = -EEXIST;
+ mutex_unlock(&panel_ext_lock);
+
+ return ret;
+}
+
+int mtk_panel_detach(struct mtk_panel_ctx *ctx)
+{
+ ctx->panel = NULL;
+
+ return 0;
+}
+
+int mtk_panel_ext_create(struct device *dev,
+ struct mtk_panel_params *ext_params,
+ struct mtk_panel_funcs *ext_funcs,
+ struct drm_panel *panel)
+{
+ struct mtk_panel_ctx *ext_ctx;
+ struct mtk_panel_ext *ext;
+
+ ext_ctx = devm_kzalloc(dev, sizeof(struct mtk_panel_ctx), GFP_KERNEL);
+ if (!ext_ctx)
+ return -ENOMEM;
+
+ ext = devm_kzalloc(dev, sizeof(struct mtk_panel_ext), GFP_KERNEL);
+ if (!ext)
+ return -ENOMEM;
+
+ mtk_panel_init(ext_ctx);
+ ext->params = ext_params;
+ ext->funcs = ext_funcs;
+ ext_ctx->ext = ext;
+
+ mtk_panel_add(ext_ctx);
+ mtk_panel_attach(ext_ctx, panel);
+
+ return 0;
+}
+
+struct mtk_panel_ext *find_panel_ext(struct drm_panel *panel)
+{
+ struct mtk_panel_ctx *ctx;
+
+ mutex_lock(&panel_ext_lock);
+
+ list_for_each_entry(ctx, &panel_ext_list, list) {
+ if (ctx->panel == panel) {
+ mutex_unlock(&panel_ext_lock);
+ return ctx->ext;
+ }
+ }
+
+ mutex_unlock(&panel_ext_lock);
+ return NULL;
+}
diff --git a/drivers/gpu/drm/mediatek/mtk_panel_ext.h b/drivers/gpu/drm/mediatek/mtk_panel_ext.h
new file mode 100644
index 000000000000..f828d468817d
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_panel_ext.h
@@ -0,0 +1,344 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __MTK_PANEL_EXT_H__
+#define __MTK_PANEL_EXT_H__
+
+#include <drm/drm_panel.h>
+
+#define RT_MAX_NUM 10
+#define ESD_CHECK_NUM 3
+#define MAX_TX_CMD_NUM 20
+#define MAX_RX_CMD_NUM 20
+#define READ_DDIC_SLOT_NUM 4
+#define MAX_DYN_CMD_NUM 20
+
+struct mtk_dsi;
+struct cmdq_pkt;
+struct mtk_panel_para_table {
+ u8 count;
+ u8 para_list[64];
+};
+
+/*
+ * DSI data type:
+ * DSI_DCS_WRITE_SHORT_PACKET_NO_PARAM 0x05
+ * DSI_DCS_WRITE_SHORT_PACKET_1_PARAM 0x15
+ * DSI_DCS_WRITE_LONG_PACKET 0x39
+ * DSI_DCS_READ_NO_PARAM 0x06
+
+ * DSI_GERNERIC_WRITE_SHORT_NO_PARAM 0x03
+ * DSI_GERNERIC_WRITE_SHORT_1_PARAM 0x13
+ * DSI_GERNERIC_WRITE_SHORT_1_PARAM 0x23
+ * DSI_GERNERIC_WRITE_LONG_PACKET 0x29
+ * DSI_GERNERIC_READ_NO_PARAM 0x04
+ * DSI_GERNERIC_READ_1_PARAM 0x14
+ * DSI_GERNERIC_READ_2_PARAM 0x24
+ */
+
+/**
+ * struct mtk_ddic_dsi_msg - MTK write/read DDIC RG cmd buffer
+ * @channel: virtual channel id
+ * @flags: flags controlling this message transmission
+ * @type: payload data type array
+ * @tx_len: length of @tx_buf
+ * @tx_buf: data array to be written
+ * @tx_cmd_num: tx cmd number
+ * @rx_len: length of @rx_buf
+ * @rx_buf: data array to be read, or NULL
+ * @rx_cmd_num: rx cmd number
+ */
+struct mtk_ddic_dsi_msg {
+ u8 channel;
+ u16 flags;
+
+ u8 type[MAX_TX_CMD_NUM];
+ size_t tx_len[MAX_TX_CMD_NUM];
+ const void *tx_buf[MAX_TX_CMD_NUM];
+ size_t tx_cmd_num;
+
+ size_t rx_len[MAX_RX_CMD_NUM];
+ void *rx_buf[MAX_RX_CMD_NUM];
+ size_t rx_cmd_num;
+};
+
+struct DSI_RX_DATA_REG {
+ unsigned char byte0;
+ unsigned char byte1;
+ unsigned char byte2;
+ unsigned char byte3;
+};
+
+typedef void (*dcs_write_gce) (struct mtk_dsi *dsi, struct cmdq_pkt *handle,
+ const void *data, size_t len);
+typedef void (*dcs_grp_write_gce) (struct mtk_dsi *dsi, struct cmdq_pkt *handle,
+ struct mtk_panel_para_table *para_table,
+ unsigned int para_size);
+typedef int (*panel_tch_rst) (void);
+
+enum MTK_PANEL_OUTPUT_MODE {
+ MTK_PANEL_SINGLE_PORT = 0x0,
+ MTK_PANEL_DSC_SINGLE_PORT,
+ MTK_PANEL_DUAL_PORT,
+};
+
+struct esd_check_item {
+ unsigned char cmd;
+ unsigned char count;
+ unsigned char para_list[RT_MAX_NUM];
+ unsigned char mask_list[RT_MAX_NUM];
+};
+
+enum MTK_PANEL_MODE_SWITCH_STAGE {
+ BEFORE_DSI_POWERDOWN,
+ AFTER_DSI_POWERON,
+};
+
+enum MIPITX_PHY_PORT {
+ MIPITX_PHY_PORT_0 = 0,
+ MIPITX_PHY_PORT_1,
+ MIPITX_PHY_PORT_NUM
+};
+
+enum MIPITX_PHY_LANE_SWAP {
+ MIPITX_PHY_LANE_0 = 0,
+ MIPITX_PHY_LANE_1,
+ MIPITX_PHY_LANE_2,
+ MIPITX_PHY_LANE_3,
+ MIPITX_PHY_LANE_CK,
+ MIPITX_PHY_LANE_RX,
+ MIPITX_PHY_LANE_NUM
+};
+
+enum FPS_CHANGE_INDEX {
+ DYNFPS_NOT_DEFINED = 0,
+ DYNFPS_DSI_VFP = 1,
+ DYNFPS_DSI_HFP = 2,
+ DYNFPS_DSI_MIPI_CLK = 4,
+};
+
+struct mtk_panel_dsc_params {
+ unsigned int enable;
+ unsigned int ver; /* [7:4] major [3:0] minor */
+ unsigned int slice_mode;
+ unsigned int rgb_swap;
+ unsigned int dsc_cfg;
+ unsigned int rct_on;
+ unsigned int bit_per_channel;
+ unsigned int dsc_line_buf_depth;
+ unsigned int bp_enable;
+ unsigned int bit_per_pixel;
+ unsigned int pic_height; /* need to check */
+ unsigned int pic_width; /* need to check */
+ unsigned int slice_height;
+ unsigned int slice_width;
+ unsigned int chunk_size;
+ unsigned int xmit_delay;
+ unsigned int dec_delay;
+ unsigned int scale_value;
+ unsigned int increment_interval;
+ unsigned int decrement_interval;
+ unsigned int line_bpg_offset;
+ unsigned int nfl_bpg_offset;
+ unsigned int slice_bpg_offset;
+ unsigned int initial_offset;
+ unsigned int final_offset;
+ unsigned int flatness_minqp;
+ unsigned int flatness_maxqp;
+ unsigned int rc_model_size;
+ unsigned int rc_edge_factor;
+ unsigned int rc_quant_incr_limit0;
+ unsigned int rc_quant_incr_limit1;
+ unsigned int rc_tgt_offset_hi;
+ unsigned int rc_tgt_offset_lo;
+};
+
+struct mtk_dsi_phy_timcon {
+ unsigned int hs_trail;
+ unsigned int hs_prpr;
+ unsigned int hs_zero;
+ unsigned int lpx;
+ unsigned int ta_get;
+ unsigned int ta_sure;
+ unsigned int ta_go;
+ unsigned int da_hs_exit;
+ unsigned int clk_trail;
+ unsigned int cont_det;
+ unsigned int da_hs_sync;
+ unsigned int clk_zero;
+ unsigned int clk_hs_prpr;
+ unsigned int clk_hs_exit;
+ unsigned int clk_hs_post;
+};
+
+struct dynamic_mipi_params {
+ unsigned int switch_en;
+ unsigned int pll_clk;
+ unsigned int data_rate;
+
+ unsigned int vsa;
+ unsigned int vbp;
+ unsigned int vfp;
+ unsigned int vfp_lp_dyn;
+
+ unsigned int hsa;
+ unsigned int hbp;
+ unsigned int hfp;
+};
+
+struct dfps_switch_cmd {
+ unsigned int src_fps;
+ unsigned int cmd_num;
+ unsigned char para_list[64];
+};
+
+struct dynamic_fps_params {
+ unsigned int switch_en;
+ unsigned int vact_timing_fps;
+ struct dfps_switch_cmd dfps_cmd_table[MAX_DYN_CMD_NUM];
+
+ unsigned int lfr_enable;
+ unsigned int lfr_minimum_fps;
+};
+
+struct mtk_panel_params {
+ unsigned int pll_clk;
+ unsigned int data_rate;
+ struct mtk_dsi_phy_timcon phy_timcon;
+ unsigned int vfp_low_power;
+ struct dynamic_mipi_params dyn;
+ struct dynamic_fps_params dyn_fps;
+ unsigned int cust_esd_check;
+ unsigned int esd_check_enable;
+ struct esd_check_item lcm_esd_check_table[ESD_CHECK_NUM];
+ unsigned int ssc_disable;
+ unsigned int ssc_range;
+ int lcm_color_mode;
+ unsigned int min_luminance;
+ unsigned int average_luminance;
+ unsigned int max_luminance;
+ unsigned int round_corner_en;
+ unsigned int corner_pattern_height;
+ unsigned int corner_pattern_height_bot;
+ unsigned int corner_pattern_tp_size;
+ void *corner_pattern_lt_addr;
+ unsigned int physical_width_um;
+ unsigned int physical_height_um;
+ unsigned int lane_swap_en;
+ unsigned int is_cphy;
+ enum MIPITX_PHY_LANE_SWAP
+ lane_swap[MIPITX_PHY_PORT_NUM][MIPITX_PHY_LANE_NUM];
+ struct mtk_panel_dsc_params dsc_params;
+ unsigned int output_mode;
+ unsigned int hbm_en_time;
+ unsigned int hbm_dis_time;
+ unsigned int lcm_index;
+ unsigned int wait_sof_before_dec_vfp;
+ unsigned int doze_delay;
+};
+
+struct mtk_panel_ext {
+ struct mtk_panel_funcs *funcs;
+ struct mtk_panel_params *params;
+};
+
+struct mtk_panel_ctx {
+ struct drm_panel *panel;
+ struct mtk_panel_ext *ext;
+
+ struct list_head list;
+};
+
+struct mtk_panel_funcs {
+ int (*set_backlight_cmdq)(void *dsi_drv, dcs_write_gce cb,
+ void *handle, unsigned int level);
+ int (*set_aod_light_mode)(void *dsi_drv, dcs_write_gce cb,
+ void *handle, unsigned int mode);
+ int (*set_backlight_grp_cmdq)(void *dsi_drv, dcs_grp_write_gce cb,
+ void *handle, unsigned int level);
+ int (*reset)(struct drm_panel *panel, int on);
+ int (*ata_check)(struct drm_panel *panel);
+ int (*ext_param_set)(struct drm_panel *panel, unsigned int mode);
+ int (*ext_param_get)(struct mtk_panel_params *ext_para,
+ unsigned int mode);
+ int (*mode_switch)(struct drm_panel *panel, unsigned int cur_mode,
+ unsigned int dst_mode, enum MTK_PANEL_MODE_SWITCH_STAGE stage);
+ int (*get_virtual_heigh)(void);
+ int (*get_virtual_width)(void);
+ /**
+ * @doze_enable_start:
+ *
+ * Call the @doze_enable_start before starting AOD mode.
+ * The LCM off may add here to avoid panel show unexpected
+ * content when switching to specific panel low power mode.
+ */
+ int (*doze_enable_start)(struct drm_panel *panel,
+ void *dsi_drv, dcs_write_gce cb, void *handle);
+
+ /**
+ * @doze_enable:
+ *
+ * Call the @doze_enable starts AOD mode.
+ */
+ int (*doze_enable)(struct drm_panel *panel,
+ void *dsi_drv, dcs_write_gce cb, void *handle);
+
+ /**
+ * @doze_disable:
+ *
+ * Call the @doze_disable before ending AOD mode.
+ */
+ int (*doze_disable)(struct drm_panel *panel,
+ void *dsi_drv, dcs_write_gce cb, void *handle);
+
+ /**
+ * @doze_post_disp_on:
+ *
+ * In some situation, the LCM off may set in @doze_enable & @disable.
+ * After LCM switch to the new mode stable, system call
+ * @doze_post_disp_on to turn on panel.
+ */
+ int (*doze_post_disp_on)(struct drm_panel *panel,
+ void *dsi_drv, dcs_write_gce cb, void *handle);
+
+ /**
+ * @doze_area:
+ *
+ * Send the panel area in command here.
+ */
+ int (*doze_area)(struct drm_panel *panel,
+ void *dsi_drv, dcs_write_gce cb, void *handle);
+
+ /**
+ * @doze_get_mode_flags:
+ *
+ * If CV switch is needed for doze mode, fill the mode_flags in this
+ * function for both CMD and VDO mode.
+ */
+ unsigned long (*doze_get_mode_flags)(struct drm_panel *panel,
+ int aod_en);
+
+ int (*hbm_set_cmdq)(struct drm_panel *panel, void *dsi_drv,
+ dcs_write_gce cb, void *handle, bool en);
+ void (*hbm_get_state)(struct drm_panel *panel, bool *state);
+ void (*hbm_get_wait_state)(struct drm_panel *panel, bool *wait);
+ bool (*hbm_set_wait_state)(struct drm_panel *panel, bool wait);
+};
+
+void mtk_panel_init(struct mtk_panel_ctx *ctx);
+void mtk_panel_add(struct mtk_panel_ctx *ctx);
+void mtk_panel_remove(struct mtk_panel_ctx *ctx);
+int mtk_panel_attach(struct mtk_panel_ctx *ctx, struct drm_panel *panel);
+int mtk_panel_detach(struct mtk_panel_ctx *ctx);
+struct mtk_panel_ext *find_panel_ext(struct drm_panel *panel);
+int mtk_panel_ext_create(struct device *dev,
+ struct mtk_panel_params *ext_params,
+ struct mtk_panel_funcs *ext_funcs,
+ struct drm_panel *panel);
+int mtk_panel_tch_handle_reg(struct drm_panel *panel);
+void **mtk_panel_tch_handle_init(void);
+int mtk_panel_tch_rst(struct drm_panel *panel);
+
+#endif
diff --git a/drivers/soc/mediatek/mt8195-mmsys.h b/drivers/soc/mediatek/mt8195-mmsys.h
index 47f3d0ea3c6c..73e9e8286d50 100644
--- a/drivers/soc/mediatek/mt8195-mmsys.h
+++ b/drivers/soc/mediatek/mt8195-mmsys.h
@@ -161,12 +161,30 @@ static const struct mtk_mmsys_routes mmsys_mt8195_routing_table[] = {
}, {
DDP_COMPONENT_OVL1, DDP_COMPONENT_RDMA1,
MT8195_VDO0_OVL_MOUT_EN, MOUT_DISP_OVL1_TO_DISP_RDMA1
+ }, {
+ DDP_COMPONENT_DSC0, DDP_COMPONENT_MERGE0,
+ MT8195_VDO0_SEL_IN, SEL_IN_VPP_MERGE_FROM_DSC_WRAP0_OUT
+ }, {
+ DDP_COMPONENT_DITHER, DDP_COMPONENT_DSC0,
+ MT8195_VDO0_SEL_IN, SEL_IN_DSC_WRAP0_IN_FROM_DISP_DITHER0
+ }, {
+ DDP_COMPONENT_DSC0, DDP_COMPONENT_DSI0,
+ MT8195_VDO0_SEL_IN, SEL_IN_DSI0_FROM_DSC_WRAP0_OUT
}, {
DDP_COMPONENT_DITHER, DDP_COMPONENT_DSI0,
MT8195_VDO0_SEL_IN, SEL_IN_DSI0_FROM_DISP_DITHER0
+ }, {
+ DDP_COMPONENT_DITHER, DDP_COMPONENT_DSC0,
+ MT8195_VDO0_SEL_OUT, SOUT_DISP_DITHER0_TO_DSC_WRAP0_IN
}, {
DDP_COMPONENT_DITHER, DDP_COMPONENT_DSI0,
MT8195_VDO0_SEL_OUT, DDP_COMPONENT_DSI0
+ }, {
+ DDP_COMPONENT_DSC0, DDP_COMPONENT_DSI0,
+ MT8195_VDO0_SEL_OUT, SOUT_DSC_WRAP0_OUT_TO_DSI0
+ }, {
+ DDP_COMPONENT_DSC0, DDP_COMPONENT_MERGE0,
+ MT8195_VDO0_SEL_OUT, SOUT_DSC_WRAP0_OUT_TO_VPP_MERGE
}
};
diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
index 84ece5486902..d74eb3f97f1d 100644
--- a/drivers/soc/mediatek/mtk-mutex.c
+++ b/drivers/soc/mediatek/mtk-mutex.c
@@ -285,6 +285,7 @@ static const unsigned int mt8195_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_GAMMA] = MT8195_MUTEX_MOD_DISP_GAMMA0,
[DDP_COMPONENT_DITHER] = MT8195_MUTEX_MOD_DISP_DITHER0,
[DDP_COMPONENT_MERGE0] = MT8195_MUTEX_MOD_DISP_VPP_MERGE,
+ [DDP_COMPONENT_DSC0] = MT8195_MUTEX_MOD_DISP_DSC_WRAP0_CORE0,
[DDP_COMPONENT_DSI0] = MT8195_MUTEX_MOD_DISP_DSI0,
[DDP_COMPONENT_PWM0] = MT8195_MUTEX_MOD_DISP_PWM0,
};
diff --git a/include/linux/soc/mediatek/mtk-mmsys.h b/include/linux/soc/mediatek/mtk-mmsys.h
index 3135ce82a7f7..89a625743737 100644
--- a/include/linux/soc/mediatek/mtk-mmsys.h
+++ b/include/linux/soc/mediatek/mtk-mmsys.h
@@ -45,6 +45,9 @@ enum mtk_ddp_comp_id {
DDP_COMPONENT_MERGE3,
DDP_COMPONENT_MERGE4,
DDP_COMPONENT_MERGE5,
+ DDP_COMPONENT_DSC0,
+ DDP_COMPONENT_DSC1,
+ DDP_COMPONENT_DSC1_VIRTUAL0,
DDP_COMPONENT_ID_MAX,
};
--
2.18.0
More information about the Linux-mediatek
mailing list