Message ID | 20210707041249.29816-18-jason-jh.lin@mediatek.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add MediaTek SoC DRM (vdosys0) support for mt8195 | expand |
Hi, Jason: On Wed, 2021-07-07 at 12:12 +0800, jason-jh.lin wrote: > 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@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. 2021 > + */ > + > +#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; > +}; Now just support mt8195-dsc, so remove this. > + > +/** > + * 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; Sub driver should get rid of ddp_comp. > + struct cmdq_client_reg cmdq_reg; > + const struct mtk_disp_dsc_data *data; > + int enable; enable is always false, so remove it. > +}; > + > +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; > +} Useless, so remove. > + > +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; > + } Keep only bypass mode. > +} > + > +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); All mtk_panel_ext is useless, so remove. > + > +#endif > diff --git a/drivers/soc/mediatek/mt8195-mmsys.h b/drivers/soc/mediatek/mt8195-mmsys.h Move mmsys part to another patch. Regards, CK > 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, > }; >
HiCK, On Wed, 2021-07-07 at 15:35 +0800, CK Hu wrote: > Hi, Jason: > > On Wed, 2021-07-07 at 12:12 +0800, jason-jh.lin wrote: > > 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@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. > > 2021 > OK, I'll fix it. > > + */ > > + > > +#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; > > +}; > > Now just support mt8195-dsc, so remove this. > OK, I'll remove it. > > + > > +/** > > + * 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; > > Sub driver should get rid of ddp_comp. > OK, I'll remove it. > > + struct cmdq_client_reg cmdq_reg; > > + const struct mtk_disp_dsc_data *data; > > + int enable; > > enable is always false, so remove it. > OK, I'll remove it. > > +}; > > + > > +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; > > +} > > Useless, so remove. > OK, I'll remove it. > > + > > +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; > > + } > > Keep only bypass mode. > OK, I'll fix it. > > +} > > + > > +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 0x0 > > 6 > > + > > + * 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); > > All mtk_panel_ext is useless, so remove. > OK, I'll remove it. > > + > > +#endif > > diff --git a/drivers/soc/mediatek/mt8195-mmsys.h > > b/drivers/soc/mediatek/mt8195-mmsys.h > > Move mmsys part to another patch. > > Regards, > CK > OK, I'll move it. Regards, Jason-JH.Lin > > 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, > > }; > > > >
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, };
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@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