Message ID | 20210906071539.12953-14-nancy.lin@mediatek.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add MediaTek SoC DRM (vdosys1) support for mt8195 | expand |
Hi, Nancy: Nancy.Lin <nancy.lin@mediatek.com> 於 2021年9月6日 週一 下午3:15寫道: > > ETHDR is a part of ovl_adaptor. > ETHDR is designed for HDR video and graphics conversion in the external > display path. It handles multiple HDR input types and performs tone > mapping, color space/color format conversion, and then combine > different layers, output the required HDR or SDR signal to the > subsequent display path. > > Signed-off-by: Nancy.Lin <nancy.lin@mediatek.com> > --- > drivers/gpu/drm/mediatek/Makefile | 1 + > drivers/gpu/drm/mediatek/mtk_ethdr.c | 424 +++++++++++++++++++++++++++ > drivers/gpu/drm/mediatek/mtk_ethdr.h | 25 ++ > 3 files changed, 450 insertions(+) > create mode 100644 drivers/gpu/drm/mediatek/mtk_ethdr.c > create mode 100644 drivers/gpu/drm/mediatek/mtk_ethdr.h [snip] > + > +void mtk_ethdr_disable_vblank(struct device *dev) > +{ > + struct mtk_ethdr *priv = dev_get_drvdata(dev); > + unsigned long flags; > + > + spin_lock_irqsave(&priv->lock, flags); > + priv->vblank_cb = NULL; > + priv->vblank_cb_data = NULL; > + spin_unlock_irqrestore(&priv->lock, flags); > + > + writel(0x0, priv->ethdr_comp[ETHDR_MIXER].regs + MIX_INTEN); > +} > + > +static irqreturn_t mtk_ethdr_irq_handler(int irq, void *dev_id) > +{ > + struct mtk_ethdr *priv = dev_id; > + unsigned long flags; > + > + writel(0x0, priv->ethdr_comp[ETHDR_MIXER].regs + MIX_INTSTA); > + > + spin_lock_irqsave(&priv->lock, flags); > + if (!priv->vblank_cb) { > + spin_unlock_irqrestore(&priv->lock, flags); > + return IRQ_NONE; > + } > + > + priv->vblank_cb(priv->vblank_cb_data); > + spin_unlock_irqrestore(&priv->lock, flags); > + > + return IRQ_HANDLED; > +} > + > +void mtk_ethdr_layer_config(struct device *dev, unsigned int idx, > + struct mtk_plane_state *state, > + struct cmdq_pkt *cmdq_pkt) > +{ > + struct mtk_ethdr *priv = dev_get_drvdata(dev); > + struct mtk_ethdr_comp *mixer = &priv->ethdr_comp[ETHDR_MIXER]; > + struct mtk_plane_pending_state *pending = &state->pending; > + unsigned int offset = (pending->y << 16) | pending->x; unsigned int offset = (pending->x & 1) << 31 | pending->y << 16 | pending->x; So you don't need x_offset_odd. > + unsigned int mixer_pad_mode = MIXER_INx_MODE_BYPASS; > + unsigned int alpha_con = 0; > + unsigned int fmt = 0; > + bool x_offset_odd = false; > + > + dev_dbg(dev, "%s+ idx:%d", __func__, idx); > + > + if (idx >= 4) > + return; > + > + if (!pending->enable) { > + mtk_ddp_write(cmdq_pkt, 0, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_SIZE(idx)); > + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_MIXER_IN_MODE, > + idx + 1, MIXER_INx_MODE_BYPASS, cmdq_pkt); > + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_MIXER_IN_BIWIDTH, > + idx + 1, 0, cmdq_pkt); > + return; > + } > + > + if (pending->x % 2) { > + x_offset_odd = true; > + mixer_pad_mode = MIXER_INx_MODE_EVEN_EXTEND; > + } > + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_MIXER_IN_MODE, > + idx + 1, mixer_pad_mode, cmdq_pkt); > + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_MIXER_IN_BIWIDTH, > + idx + 1, pending->width / 2 - 1, cmdq_pkt); > + > + if (state->base.fb && state->base.fb->format->has_alpha) { > + alpha_con = MIXER_ALPHA_AEN | MIXER_ALPHA; > + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_HDR_ALPHA_SEL, > + idx + 1, 0, cmdq_pkt); > + } else { > + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_HDR_ALPHA_SEL, > + idx + 1, 1, cmdq_pkt); > + } > + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_MIXER_IN_ALPHA_ODD, idx + 1, > + DEFAULT_9BIT_ALPHA, cmdq_pkt); > + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_MIXER_IN_ALPHA_EVEN, idx + 1, > + DEFAULT_9BIT_ALPHA, cmdq_pkt); > + > + mtk_ddp_write(cmdq_pkt, (pending->height << 16) | pending->width, &mixer->cmdq_base, mtk_ddp_write(cmdq_pkt, pending->height << 16 | pending->width, &mixer->cmdq_base, > + mixer->regs, MIX_L_SRC_SIZE(idx)); > + mtk_ddp_write(cmdq_pkt, (x_offset_odd << 31) | offset, &mixer->cmdq_base, > + mixer->regs, MIX_L_SRC_OFFSET(idx)); > + mtk_ddp_write_mask(cmdq_pkt, alpha_con, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_CON(idx), > + 0x1ff); > + mtk_ddp_write_mask(cmdq_pkt, BIT(idx), &mixer->cmdq_base, mixer->regs, MIX_SRC_CON, > + BIT(idx)); > +} > + > +void mtk_ethdr_config(struct device *dev, unsigned int w, > + unsigned int h, unsigned int vrefresh, > + unsigned int bpc, struct cmdq_pkt *cmdq_pkt) > +{ > + struct mtk_ethdr *priv = dev_get_drvdata(dev); > + struct mtk_ethdr_comp *vdo_fe0 = &priv->ethdr_comp[ETHDR_VDO_FE0]; > + struct mtk_ethdr_comp *vdo_fe1 = &priv->ethdr_comp[ETHDR_VDO_FE1]; > + struct mtk_ethdr_comp *gfx_fe0 = &priv->ethdr_comp[ETHDR_GFX_FE0]; > + struct mtk_ethdr_comp *gfx_fe1 = &priv->ethdr_comp[ETHDR_GFX_FE1]; > + struct mtk_ethdr_comp *vdo_be = &priv->ethdr_comp[ETHDR_VDO_BE]; > + struct mtk_ethdr_comp *mixer = &priv->ethdr_comp[ETHDR_MIXER]; > + > + dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h); > + > + mtk_ddp_write(cmdq_pkt, HDR_VDO_FE_0804_BYPASS_ALL, &vdo_fe0->cmdq_base, > + vdo_fe0->regs, HDR_VDO_FE_0804_HDR_DM_FE); > + > + mtk_ddp_write(cmdq_pkt, HDR_VDO_FE_0804_BYPASS_ALL, &vdo_fe1->cmdq_base, > + vdo_fe1->regs, HDR_VDO_FE_0804_HDR_DM_FE); > + > + mtk_ddp_write(cmdq_pkt, HDR_GFX_FE_0204_BYPASS_ALL, &gfx_fe0->cmdq_base, > + gfx_fe0->regs, HDR_GFX_FE_0204_GFX_HDR_FE); > + > + mtk_ddp_write(cmdq_pkt, HDR_GFX_FE_0204_BYPASS_ALL, &gfx_fe1->cmdq_base, > + gfx_fe1->regs, HDR_GFX_FE_0204_GFX_HDR_FE); > + > + mtk_ddp_write(cmdq_pkt, HDR_VDO_BE_0204_BYPASS_ALL, &vdo_be->cmdq_base, > + vdo_be->regs, HDR_VDO_BE_0204_VDO_DM_BE); > + > + mtk_ddp_write(cmdq_pkt, MIX_FUNC_DCM_ENABLE, &mixer->cmdq_base, mixer->regs, MIX_FUNC_DCM0); > + mtk_ddp_write(cmdq_pkt, MIX_FUNC_DCM_ENABLE, &mixer->cmdq_base, mixer->regs, MIX_FUNC_DCM1); > + mtk_ddp_write(cmdq_pkt, (h << 16 | w), &mixer->cmdq_base, mixer->regs, MIX_ROI_SIZE); mtk_ddp_write(cmdq_pkt, h << 16 | w, &mixer->cmdq_base, mixer->regs, MIX_ROI_SIZE); > + mtk_ddp_write(cmdq_pkt, BGCLR_BLACK, &mixer->cmdq_base, mixer->regs, MIX_ROI_BGCLR); > + mtk_ddp_write(cmdq_pkt, NON_PREMULTI_SOURCE, &mixer->cmdq_base, mixer->regs, > + MIX_L_SRC_CON(0)); > + mtk_ddp_write(cmdq_pkt, NON_PREMULTI_SOURCE, &mixer->cmdq_base, mixer->regs, > + MIX_L_SRC_CON(1)); > + mtk_ddp_write(cmdq_pkt, NON_PREMULTI_SOURCE, &mixer->cmdq_base, mixer->regs, > + MIX_L_SRC_CON(2)); > + mtk_ddp_write(cmdq_pkt, NON_PREMULTI_SOURCE, &mixer->cmdq_base, mixer->regs, > + MIX_L_SRC_CON(3)); > + mtk_ddp_write(cmdq_pkt, 0x0, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_SIZE(0)); > + mtk_ddp_write(cmdq_pkt, OUTPUT_NO_RND | SOURCE_RGB_SEL | BACKGROUND_RELAY, > + &mixer->cmdq_base, mixer->regs, MIX_DATAPATH_CON); > + mtk_ddp_write_mask(cmdq_pkt, MIX_SRC_L0_EN, &mixer->cmdq_base, mixer->regs, > + MIX_SRC_CON, MIX_SRC_L0_EN); mtk_ddp_write_mask(cmdq_pkt, BIT(0), &mixer->cmdq_base, mixer->regs, MIX_SRC_CON, BIT(0)); Why do you enable layer 0? > + > + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_HDR_BE_ASYNC_WIDTH, 0, > + w / 2, cmdq_pkt); > + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_HDR_BE_ASYNC_HEIGHT, 0, > + h, cmdq_pkt); > + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_MIXER_IN_CH_SWAP, 4, 0, cmdq_pkt); > +} > + > +void mtk_ethdr_start(struct device *dev) > +{ > + struct mtk_ethdr *priv = dev_get_drvdata(dev); > + struct mtk_ethdr_comp *mixer = &priv->ethdr_comp[ETHDR_MIXER]; > + > + writel(1, mixer->regs + MIX_EN); > +} > + > +void mtk_ethdr_stop(struct device *dev) > +{ > + struct mtk_ethdr *priv = dev_get_drvdata(dev); > + struct mtk_ethdr_comp *mixer = &priv->ethdr_comp[ETHDR_MIXER]; > + > + writel(0, mixer->regs + MIX_EN); > + writel(1, mixer->regs + MIX_RST); > + reset_control_reset(devm_reset_control_array_get(dev, true, true)); > + writel(0, mixer->regs + MIX_RST); > +} > + > +int mtk_ethdr_clk_enable(struct device *dev) > +{ > + int ret; > + struct mtk_ethdr *priv = dev_get_drvdata(dev); > + > + ret = clk_bulk_prepare_enable(ETHDR_CLK_NUM, priv->ethdr_clk); > + if (ret) > + dev_err(dev, > + "ethdr_clk prepare enable failed\n"); > + return ret; > +} > + > +void mtk_ethdr_clk_disable(struct device *dev) > +{ > + struct mtk_ethdr *priv = dev_get_drvdata(dev); > + > + clk_bulk_disable_unprepare(ETHDR_CLK_NUM, priv->ethdr_clk); > +} > + > +static int mtk_ethdr_bind(struct device *dev, struct device *master, > + void *data) > +{ > + struct mtk_ethdr *priv = dev_get_drvdata(dev); > + struct platform_device *ovl_adaptor; > + struct drm_device *drm_dev = data; > + struct mtk_drm_private *drm_private = drm_dev->dev_private; > + > + priv->mmsys_dev = drm_private->mmsys_dev; > + > + /* Bring up ovl adaptor rdma and merge */ > + ovl_adaptor = platform_device_register_data(dev, "mediatek-disp-ovl-adaptor", > + PLATFORM_DEVID_NONE, (void *)priv->mmsys_dev, > + sizeof(*priv->mmsys_dev)); I would like that mtk drm driver bring up ovl adaptor and ovl adaptor bring up ethdr, rdma and merge. In another SoC, edhdr may be not related to ovl. Regards, Chun-Kuang. > + if (IS_ERR(ovl_adaptor)) > + return PTR_ERR(ovl_adaptor); > + > + priv->ovl_adaptor_dev = &ovl_adaptor->dev; > + > + return 0; > +} > + > +static void mtk_ethdr_unbind(struct device *dev, struct device *master, void *data) > +{ > +} > + > +static const struct component_ops mtk_ethdr_component_ops = { > + .bind = mtk_ethdr_bind, > + .unbind = mtk_ethdr_unbind, > +}; > +
Hi Chun-Kuang, Thanks for the review. On Wed, 2021-09-22 at 08:09 +0800, Chun-Kuang Hu wrote: > Hi, Nancy: > > Nancy.Lin <nancy.lin@mediatek.com> 於 2021年9月6日 週一 下午3:15寫道: > > > > ETHDR is a part of ovl_adaptor. > > ETHDR is designed for HDR video and graphics conversion in the > > external > > display path. It handles multiple HDR input types and performs tone > > mapping, color space/color format conversion, and then combine > > different layers, output the required HDR or SDR signal to the > > subsequent display path. > > > > Signed-off-by: Nancy.Lin <nancy.lin@mediatek.com> > > --- > > drivers/gpu/drm/mediatek/Makefile | 1 + > > drivers/gpu/drm/mediatek/mtk_ethdr.c | 424 > > +++++++++++++++++++++++++++ > > drivers/gpu/drm/mediatek/mtk_ethdr.h | 25 ++ > > 3 files changed, 450 insertions(+) > > create mode 100644 drivers/gpu/drm/mediatek/mtk_ethdr.c > > create mode 100644 drivers/gpu/drm/mediatek/mtk_ethdr.h > > [snip] > > > + > > +void mtk_ethdr_disable_vblank(struct device *dev) > > +{ > > + struct mtk_ethdr *priv = dev_get_drvdata(dev); > > + unsigned long flags; > > + > > + spin_lock_irqsave(&priv->lock, flags); > > + priv->vblank_cb = NULL; > > + priv->vblank_cb_data = NULL; > > + spin_unlock_irqrestore(&priv->lock, flags); > > + > > + writel(0x0, priv->ethdr_comp[ETHDR_MIXER].regs + > > MIX_INTEN); > > +} > > + > > +static irqreturn_t mtk_ethdr_irq_handler(int irq, void *dev_id) > > +{ > > + struct mtk_ethdr *priv = dev_id; > > + unsigned long flags; > > + > > + writel(0x0, priv->ethdr_comp[ETHDR_MIXER].regs + > > MIX_INTSTA); > > + > > + spin_lock_irqsave(&priv->lock, flags); > > + if (!priv->vblank_cb) { > > + spin_unlock_irqrestore(&priv->lock, flags); > > + return IRQ_NONE; > > + } > > + > > + priv->vblank_cb(priv->vblank_cb_data); > > + spin_unlock_irqrestore(&priv->lock, flags); > > + > > + return IRQ_HANDLED; > > +} > > + > > +void mtk_ethdr_layer_config(struct device *dev, unsigned int idx, > > + struct mtk_plane_state *state, > > + struct cmdq_pkt *cmdq_pkt) > > +{ > > + struct mtk_ethdr *priv = dev_get_drvdata(dev); > > + struct mtk_ethdr_comp *mixer = &priv- > > >ethdr_comp[ETHDR_MIXER]; > > + struct mtk_plane_pending_state *pending = &state->pending; > > + unsigned int offset = (pending->y << 16) | pending->x; > > unsigned int offset = (pending->x & 1) << 31 | pending->y << 16 | > pending->x; > > So you don't need x_offset_odd. > OK, I will modify it. > > + > > unsigned int mixer_pad_mode = MIXER_INx_MODE_BYPASS; > > + unsigned int alpha_con = 0; > > + unsigned int fmt = 0; > > + bool x_offset_odd = false; > > + > > + dev_dbg(dev, "%s+ idx:%d", __func__, idx); > > + > > + if (idx >= 4) > > + return; > > + > > + if (!pending->enable) { > > + mtk_ddp_write(cmdq_pkt, 0, &mixer->cmdq_base, > > mixer->regs, MIX_L_SRC_SIZE(idx)); > > + mtk_mmsys_ddp_config(priv->mmsys_dev, > > MMSYS_CONFIG_MIXER_IN_MODE, > > + idx + 1, > > MIXER_INx_MODE_BYPASS, cmdq_pkt); > > + mtk_mmsys_ddp_config(priv->mmsys_dev, > > MMSYS_CONFIG_MIXER_IN_BIWIDTH, > > + idx + 1, 0, cmdq_pkt); > > + return; > > + } > > + > > + if (pending->x % 2) { > > + x_offset_odd = true; > > + mixer_pad_mode = MIXER_INx_MODE_EVEN_EXTEND; > > + } > > + mtk_mmsys_ddp_config(priv->mmsys_dev, > > MMSYS_CONFIG_MIXER_IN_MODE, > > + idx + 1, mixer_pad_mode, cmdq_pkt); > > + mtk_mmsys_ddp_config(priv->mmsys_dev, > > MMSYS_CONFIG_MIXER_IN_BIWIDTH, > > + idx + 1, pending->width / 2 - 1, > > cmdq_pkt); > > + > > + if (state->base.fb && state->base.fb->format->has_alpha) { > > + alpha_con = MIXER_ALPHA_AEN | MIXER_ALPHA; > > + mtk_mmsys_ddp_config(priv->mmsys_dev, > > MMSYS_CONFIG_HDR_ALPHA_SEL, > > + idx + 1, 0, cmdq_pkt); > > + } else { > > + mtk_mmsys_ddp_config(priv->mmsys_dev, > > MMSYS_CONFIG_HDR_ALPHA_SEL, > > + idx + 1, 1, cmdq_pkt); > > + } > > + mtk_mmsys_ddp_config(priv->mmsys_dev, > > MMSYS_CONFIG_MIXER_IN_ALPHA_ODD, idx + 1, > > + DEFAULT_9BIT_ALPHA, cmdq_pkt); > > + mtk_mmsys_ddp_config(priv->mmsys_dev, > > MMSYS_CONFIG_MIXER_IN_ALPHA_EVEN, idx + 1, > > + DEFAULT_9BIT_ALPHA, cmdq_pkt); > > + > > + mtk_ddp_write(cmdq_pkt, (pending->height << 16) | pending- > > >width, &mixer->cmdq_base, > > mtk_ddp_write(cmdq_pkt, pending->height << 16 | pending->width, > &mixer->cmdq_base, > OK. > > + mixer->regs, MIX_L_SRC_SIZE(idx)); > > + mtk_ddp_write(cmdq_pkt, (x_offset_odd << 31) | offset, > > &mixer->cmdq_base, > > + mixer->regs, MIX_L_SRC_OFFSET(idx)); > > + mtk_ddp_write_mask(cmdq_pkt, alpha_con, &mixer->cmdq_base, > > mixer->regs, MIX_L_SRC_CON(idx), > > + 0x1ff); > > + mtk_ddp_write_mask(cmdq_pkt, BIT(idx), &mixer->cmdq_base, > > mixer->regs, MIX_SRC_CON, > > + BIT(idx)); > > +} > > + > > +void mtk_ethdr_config(struct device *dev, unsigned int w, > > + unsigned int h, unsigned int vrefresh, > > + unsigned int bpc, struct cmdq_pkt *cmdq_pkt) > > +{ > > + struct mtk_ethdr *priv = dev_get_drvdata(dev); > > + struct mtk_ethdr_comp *vdo_fe0 = &priv- > > >ethdr_comp[ETHDR_VDO_FE0]; > > + struct mtk_ethdr_comp *vdo_fe1 = &priv- > > >ethdr_comp[ETHDR_VDO_FE1]; > > + struct mtk_ethdr_comp *gfx_fe0 = &priv- > > >ethdr_comp[ETHDR_GFX_FE0]; > > + struct mtk_ethdr_comp *gfx_fe1 = &priv- > > >ethdr_comp[ETHDR_GFX_FE1]; > > + struct mtk_ethdr_comp *vdo_be = &priv- > > >ethdr_comp[ETHDR_VDO_BE]; > > + struct mtk_ethdr_comp *mixer = &priv- > > >ethdr_comp[ETHDR_MIXER]; > > + > > + dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h); > > + > > + mtk_ddp_write(cmdq_pkt, HDR_VDO_FE_0804_BYPASS_ALL, > > &vdo_fe0->cmdq_base, > > + vdo_fe0->regs, HDR_VDO_FE_0804_HDR_DM_FE); > > + > > + mtk_ddp_write(cmdq_pkt, HDR_VDO_FE_0804_BYPASS_ALL, > > &vdo_fe1->cmdq_base, > > + vdo_fe1->regs, HDR_VDO_FE_0804_HDR_DM_FE); > > + > > + mtk_ddp_write(cmdq_pkt, HDR_GFX_FE_0204_BYPASS_ALL, > > &gfx_fe0->cmdq_base, > > + gfx_fe0->regs, HDR_GFX_FE_0204_GFX_HDR_FE); > > + > > + mtk_ddp_write(cmdq_pkt, HDR_GFX_FE_0204_BYPASS_ALL, > > &gfx_fe1->cmdq_base, > > + gfx_fe1->regs, HDR_GFX_FE_0204_GFX_HDR_FE); > > + > > + mtk_ddp_write(cmdq_pkt, HDR_VDO_BE_0204_BYPASS_ALL, > > &vdo_be->cmdq_base, > > + vdo_be->regs, HDR_VDO_BE_0204_VDO_DM_BE); > > + > > + mtk_ddp_write(cmdq_pkt, MIX_FUNC_DCM_ENABLE, &mixer- > > >cmdq_base, mixer->regs, MIX_FUNC_DCM0); > > + mtk_ddp_write(cmdq_pkt, MIX_FUNC_DCM_ENABLE, &mixer- > > >cmdq_base, mixer->regs, MIX_FUNC_DCM1); > > + mtk_ddp_write(cmdq_pkt, (h << 16 | w), &mixer->cmdq_base, > > mixer->regs, MIX_ROI_SIZE); > > mtk_ddp_write(cmdq_pkt, h << 16 | w, &mixer->cmdq_base, mixer->regs, > MIX_ROI_SIZE); > OK. > > + mtk_ddp_write(cmdq_pkt, BGCLR_BLACK, &mixer->cmdq_base, > > mixer->regs, MIX_ROI_BGCLR); > > + mtk_ddp_write(cmdq_pkt, NON_PREMULTI_SOURCE, &mixer- > > >cmdq_base, mixer->regs, > > + MIX_L_SRC_CON(0)); > > + mtk_ddp_write(cmdq_pkt, NON_PREMULTI_SOURCE, &mixer- > > >cmdq_base, mixer->regs, > > + MIX_L_SRC_CON(1)); > > + mtk_ddp_write(cmdq_pkt, NON_PREMULTI_SOURCE, &mixer- > > >cmdq_base, mixer->regs, > > + MIX_L_SRC_CON(2)); > > + mtk_ddp_write(cmdq_pkt, NON_PREMULTI_SOURCE, &mixer- > > >cmdq_base, mixer->regs, > > + MIX_L_SRC_CON(3)); > > + mtk_ddp_write(cmdq_pkt, 0x0, &mixer->cmdq_base, mixer- > > >regs, MIX_L_SRC_SIZE(0)); > > + mtk_ddp_write(cmdq_pkt, OUTPUT_NO_RND | SOURCE_RGB_SEL | > > BACKGROUND_RELAY, > > + &mixer->cmdq_base, mixer->regs, > > MIX_DATAPATH_CON); > > + mtk_ddp_write_mask(cmdq_pkt, MIX_SRC_L0_EN, &mixer- > > >cmdq_base, mixer->regs, > > + MIX_SRC_CON, MIX_SRC_L0_EN); > > mtk_ddp_write_mask(cmdq_pkt, BIT(0), &mixer->cmdq_base, > mixer->regs, MIX_SRC_CON, > BIT(0)); > > Why do you enable layer 0? > There are two modes in Mixer. 1. Background relay mode: all layers off 2. Normal mix mode: at least one layer on The two modes of mixer have different timings for the back-end engine, so switching between these two modes will cause the screen to jitter. Default enable layer 0 and set it's region to zero, keep mixer in normal mix mode. > > + > > + mtk_mmsys_ddp_config(priv->mmsys_dev, > > MMSYS_CONFIG_HDR_BE_ASYNC_WIDTH, 0, > > + w / 2, cmdq_pkt); > > + mtk_mmsys_ddp_config(priv->mmsys_dev, > > MMSYS_CONFIG_HDR_BE_ASYNC_HEIGHT, 0, > > + h, cmdq_pkt); > > + mtk_mmsys_ddp_config(priv->mmsys_dev, > > MMSYS_CONFIG_MIXER_IN_CH_SWAP, 4, 0, cmdq_pkt); > > +} > > + > > +void mtk_ethdr_start(struct device *dev) > > +{ > > + struct mtk_ethdr *priv = dev_get_drvdata(dev); > > + struct mtk_ethdr_comp *mixer = &priv- > > >ethdr_comp[ETHDR_MIXER]; > > + > > + writel(1, mixer->regs + MIX_EN); > > +} > > + > > +void mtk_ethdr_stop(struct device *dev) > > +{ > > + struct mtk_ethdr *priv = dev_get_drvdata(dev); > > + struct mtk_ethdr_comp *mixer = &priv- > > >ethdr_comp[ETHDR_MIXER]; > > + > > + writel(0, mixer->regs + MIX_EN); > > + writel(1, mixer->regs + MIX_RST); > > + reset_control_reset(devm_reset_control_array_get(dev, true, > > true)); > > + writel(0, mixer->regs + MIX_RST); > > +} > > + > > +int mtk_ethdr_clk_enable(struct device *dev) > > +{ > > + int ret; > > + struct mtk_ethdr *priv = dev_get_drvdata(dev); > > + > > + ret = clk_bulk_prepare_enable(ETHDR_CLK_NUM, priv- > > >ethdr_clk); > > + if (ret) > > + dev_err(dev, > > + "ethdr_clk prepare enable failed\n"); > > + return ret; > > +} > > + > > +void mtk_ethdr_clk_disable(struct device *dev) > > +{ > > + struct mtk_ethdr *priv = dev_get_drvdata(dev); > > + > > + clk_bulk_disable_unprepare(ETHDR_CLK_NUM, priv->ethdr_clk); > > +} > > + > > +static int mtk_ethdr_bind(struct device *dev, struct device > > *master, > > + void *data) > > +{ > > + struct mtk_ethdr *priv = dev_get_drvdata(dev); > > + struct platform_device *ovl_adaptor; > > + struct drm_device *drm_dev = data; > > + struct mtk_drm_private *drm_private = drm_dev->dev_private; > > + > > + priv->mmsys_dev = drm_private->mmsys_dev; > > + > > + /* Bring up ovl adaptor rdma and merge */ > > + ovl_adaptor = platform_device_register_data(dev, "mediatek- > > disp-ovl-adaptor", > > + PLATFORM_DEVID_ > > NONE, (void *)priv->mmsys_dev, > > + sizeof(*priv- > > >mmsys_dev)); > > I would like that mtk drm driver bring up ovl adaptor and ovl adaptor > bring up ethdr, rdma and merge. In another SoC, edhdr may be not > related to ovl. > > Regards, > Chun-Kuang. > OK. I will change to use drm driver to bring up ovl_adaptor. Regards, Nancy Lin > > + if (IS_ERR(ovl_adaptor)) > > + return PTR_ERR(ovl_adaptor); > > + > > + priv->ovl_adaptor_dev = &ovl_adaptor->dev; > > + > > + return 0; > > +} > > + > > +static void mtk_ethdr_unbind(struct device *dev, struct device > > *master, void *data) > > +{ > > +} > > + > > +static const struct component_ops mtk_ethdr_component_ops = { > > + .bind = mtk_ethdr_bind, > > + .unbind = mtk_ethdr_unbind, > > +}; > > +
diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile index 6e604a933ed0..fb158a1e7f06 100644 --- a/drivers/gpu/drm/mediatek/Makefile +++ b/drivers/gpu/drm/mediatek/Makefile @@ -14,6 +14,7 @@ mediatek-drm-y := mtk_disp_aal.o \ mtk_drm_plane.o \ mtk_dsi.o \ mtk_dpi.o \ + mtk_ethdr.o \ mtk_mdp_rdma.o obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o diff --git a/drivers/gpu/drm/mediatek/mtk_ethdr.c b/drivers/gpu/drm/mediatek/mtk_ethdr.c new file mode 100644 index 000000000000..c93c881c5a36 --- /dev/null +++ b/drivers/gpu/drm/mediatek/mtk_ethdr.c @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021 MediaTek Inc. + */ + +#include <drm/drm_fourcc.h> +#include <linux/clk.h> +#include <linux/reset.h> +#include <linux/component.h> +#include <linux/of_device.h> +#include <linux/of_address.h> +#include <linux/pm_runtime.h> +#include <linux/platform_device.h> +#include <linux/soc/mediatek/mtk-cmdq.h> +#include <linux/soc/mediatek/mtk-mmsys.h> + +#include "mtk_drm_crtc.h" +#include "mtk_drm_ddp_comp.h" +#include "mtk_drm_drv.h" +#include "mtk_ethdr.h" + +#define MIX_INTEN 0x4 + #define MIX_FME_CPL_INTEN BIT(1) +#define MIX_INTSTA 0x8 +#define MIX_EN 0xc +#define MIX_RST 0x14 +#define MIX_ROI_SIZE 0x18 +#define MIX_DATAPATH_CON 0x1c + #define OUTPUT_NO_RND BIT(3) + #define SOURCE_RGB_SEL BIT(7) + #define BACKGROUND_RELAY (4 << 9) +#define MIX_ROI_BGCLR 0x20 + #define BGCLR_BLACK 0xff000000 +#define MIX_SRC_CON 0x24 + #define MIX_SRC_L0_EN BIT(0) +#define MIX_L_SRC_CON(n) (0x28 + 0x18 * (n)) + #define NON_PREMULTI_SOURCE (2 << 12) +#define MIX_L_SRC_SIZE(n) (0x30 + 0x18 * (n)) +#define MIX_L_SRC_OFFSET(n) (0x34 + 0x18 * (n)) +#define MIX_FUNC_DCM0 0x120 +#define MIX_FUNC_DCM1 0x124 + #define MIX_FUNC_DCM_ENABLE 0xffffffff + +#define HDR_VDO_FE_0804_HDR_DM_FE 0x804 + #define HDR_VDO_FE_0804_BYPASS_ALL 0xfd +#define HDR_GFX_FE_0204_GFX_HDR_FE 0x204 + #define HDR_GFX_FE_0204_BYPASS_ALL 0xfd +#define HDR_VDO_BE_0204_VDO_DM_BE 0x204 + #define HDR_VDO_BE_0204_BYPASS_ALL 0x7e + +#define MIXER_INx_MODE_BYPASS 0 +#define MIXER_INx_MODE_EVEN_EXTEND 1 +#define MIXER_INx_MODE_ODD_EXTEND 2 +#define DEFAULT_9BIT_ALPHA 0x100 +#define MIXER_ALPHA_AEN BIT(8) +#define MIXER_ALPHA 0xff +#define ETHDR_CLK_NUM 13 + +enum mtk_ethdr_comp_id { + ETHDR_MIXER, + ETHDR_VDO_FE0, + ETHDR_VDO_FE1, + ETHDR_GFX_FE0, + ETHDR_GFX_FE1, + ETHDR_VDO_BE, + ETHDR_ADL_DS, + ETHDR_ID_MAX +}; + +struct mtk_ethdr_comp { + struct device *dev; + void __iomem *regs; + struct cmdq_client_reg cmdq_base; +}; + +struct mtk_ethdr { + struct mtk_ethdr_comp ethdr_comp[ETHDR_ID_MAX]; + struct clk_bulk_data ethdr_clk[ETHDR_CLK_NUM]; + struct device *ovl_adaptor_dev; + struct device *mmsys_dev; + spinlock_t lock; /* protects vblank_cb and vblank_cb_data */ + void (*vblank_cb)(void *data); + void *vblank_cb_data; + int irq; +}; + +static const char * const ethdr_comp_str[] = { + "ETHDR_MIXER", + "ETHDR_VDO_FE0", + "ETHDR_VDO_FE1", + "ETHDR_GFX_FE0", + "ETHDR_GFX_FE1", + "ETHDR_VDO_BE", + "ETHDR_ADL_DS", + "ETHDR_ID_MAX" +}; + +static const char * const ethdr_clk_str[] = { + "ethdr_top", + "mixer", + "vdo_fe0", + "vdo_fe1", + "gfx_fe0", + "gfx_fe1", + "vdo_be", + "adl_ds", + "vdo_fe0_async", + "vdo_fe1_async", + "gfx_fe0_async", + "gfx_fe1_async", + "vdo_be_async", +}; + +void mtk_ethdr_enable_vblank(struct device *dev, + void (*vblank_cb)(void *), + void *vblank_cb_data) +{ + struct mtk_ethdr *priv = dev_get_drvdata(dev); + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + priv->vblank_cb = vblank_cb; + priv->vblank_cb_data = vblank_cb_data; + spin_unlock_irqrestore(&priv->lock, flags); + + writel(MIX_FME_CPL_INTEN, priv->ethdr_comp[ETHDR_MIXER].regs + MIX_INTEN); +} + +void mtk_ethdr_disable_vblank(struct device *dev) +{ + struct mtk_ethdr *priv = dev_get_drvdata(dev); + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + priv->vblank_cb = NULL; + priv->vblank_cb_data = NULL; + spin_unlock_irqrestore(&priv->lock, flags); + + writel(0x0, priv->ethdr_comp[ETHDR_MIXER].regs + MIX_INTEN); +} + +static irqreturn_t mtk_ethdr_irq_handler(int irq, void *dev_id) +{ + struct mtk_ethdr *priv = dev_id; + unsigned long flags; + + writel(0x0, priv->ethdr_comp[ETHDR_MIXER].regs + MIX_INTSTA); + + spin_lock_irqsave(&priv->lock, flags); + if (!priv->vblank_cb) { + spin_unlock_irqrestore(&priv->lock, flags); + return IRQ_NONE; + } + + priv->vblank_cb(priv->vblank_cb_data); + spin_unlock_irqrestore(&priv->lock, flags); + + return IRQ_HANDLED; +} + +void mtk_ethdr_layer_config(struct device *dev, unsigned int idx, + struct mtk_plane_state *state, + struct cmdq_pkt *cmdq_pkt) +{ + struct mtk_ethdr *priv = dev_get_drvdata(dev); + struct mtk_ethdr_comp *mixer = &priv->ethdr_comp[ETHDR_MIXER]; + struct mtk_plane_pending_state *pending = &state->pending; + unsigned int offset = (pending->y << 16) | pending->x; + unsigned int mixer_pad_mode = MIXER_INx_MODE_BYPASS; + unsigned int alpha_con = 0; + unsigned int fmt = 0; + bool x_offset_odd = false; + + dev_dbg(dev, "%s+ idx:%d", __func__, idx); + + if (idx >= 4) + return; + + if (!pending->enable) { + mtk_ddp_write(cmdq_pkt, 0, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_SIZE(idx)); + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_MIXER_IN_MODE, + idx + 1, MIXER_INx_MODE_BYPASS, cmdq_pkt); + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_MIXER_IN_BIWIDTH, + idx + 1, 0, cmdq_pkt); + return; + } + + if (pending->x % 2) { + x_offset_odd = true; + mixer_pad_mode = MIXER_INx_MODE_EVEN_EXTEND; + } + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_MIXER_IN_MODE, + idx + 1, mixer_pad_mode, cmdq_pkt); + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_MIXER_IN_BIWIDTH, + idx + 1, pending->width / 2 - 1, cmdq_pkt); + + if (state->base.fb && state->base.fb->format->has_alpha) { + alpha_con = MIXER_ALPHA_AEN | MIXER_ALPHA; + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_HDR_ALPHA_SEL, + idx + 1, 0, cmdq_pkt); + } else { + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_HDR_ALPHA_SEL, + idx + 1, 1, cmdq_pkt); + } + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_MIXER_IN_ALPHA_ODD, idx + 1, + DEFAULT_9BIT_ALPHA, cmdq_pkt); + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_MIXER_IN_ALPHA_EVEN, idx + 1, + DEFAULT_9BIT_ALPHA, cmdq_pkt); + + mtk_ddp_write(cmdq_pkt, (pending->height << 16) | pending->width, &mixer->cmdq_base, + mixer->regs, MIX_L_SRC_SIZE(idx)); + mtk_ddp_write(cmdq_pkt, (x_offset_odd << 31) | offset, &mixer->cmdq_base, + mixer->regs, MIX_L_SRC_OFFSET(idx)); + mtk_ddp_write_mask(cmdq_pkt, alpha_con, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_CON(idx), + 0x1ff); + mtk_ddp_write_mask(cmdq_pkt, BIT(idx), &mixer->cmdq_base, mixer->regs, MIX_SRC_CON, + BIT(idx)); +} + +void mtk_ethdr_config(struct device *dev, unsigned int w, + unsigned int h, unsigned int vrefresh, + unsigned int bpc, struct cmdq_pkt *cmdq_pkt) +{ + struct mtk_ethdr *priv = dev_get_drvdata(dev); + struct mtk_ethdr_comp *vdo_fe0 = &priv->ethdr_comp[ETHDR_VDO_FE0]; + struct mtk_ethdr_comp *vdo_fe1 = &priv->ethdr_comp[ETHDR_VDO_FE1]; + struct mtk_ethdr_comp *gfx_fe0 = &priv->ethdr_comp[ETHDR_GFX_FE0]; + struct mtk_ethdr_comp *gfx_fe1 = &priv->ethdr_comp[ETHDR_GFX_FE1]; + struct mtk_ethdr_comp *vdo_be = &priv->ethdr_comp[ETHDR_VDO_BE]; + struct mtk_ethdr_comp *mixer = &priv->ethdr_comp[ETHDR_MIXER]; + + dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h); + + mtk_ddp_write(cmdq_pkt, HDR_VDO_FE_0804_BYPASS_ALL, &vdo_fe0->cmdq_base, + vdo_fe0->regs, HDR_VDO_FE_0804_HDR_DM_FE); + + mtk_ddp_write(cmdq_pkt, HDR_VDO_FE_0804_BYPASS_ALL, &vdo_fe1->cmdq_base, + vdo_fe1->regs, HDR_VDO_FE_0804_HDR_DM_FE); + + mtk_ddp_write(cmdq_pkt, HDR_GFX_FE_0204_BYPASS_ALL, &gfx_fe0->cmdq_base, + gfx_fe0->regs, HDR_GFX_FE_0204_GFX_HDR_FE); + + mtk_ddp_write(cmdq_pkt, HDR_GFX_FE_0204_BYPASS_ALL, &gfx_fe1->cmdq_base, + gfx_fe1->regs, HDR_GFX_FE_0204_GFX_HDR_FE); + + mtk_ddp_write(cmdq_pkt, HDR_VDO_BE_0204_BYPASS_ALL, &vdo_be->cmdq_base, + vdo_be->regs, HDR_VDO_BE_0204_VDO_DM_BE); + + mtk_ddp_write(cmdq_pkt, MIX_FUNC_DCM_ENABLE, &mixer->cmdq_base, mixer->regs, MIX_FUNC_DCM0); + mtk_ddp_write(cmdq_pkt, MIX_FUNC_DCM_ENABLE, &mixer->cmdq_base, mixer->regs, MIX_FUNC_DCM1); + mtk_ddp_write(cmdq_pkt, (h << 16 | w), &mixer->cmdq_base, mixer->regs, MIX_ROI_SIZE); + mtk_ddp_write(cmdq_pkt, BGCLR_BLACK, &mixer->cmdq_base, mixer->regs, MIX_ROI_BGCLR); + mtk_ddp_write(cmdq_pkt, NON_PREMULTI_SOURCE, &mixer->cmdq_base, mixer->regs, + MIX_L_SRC_CON(0)); + mtk_ddp_write(cmdq_pkt, NON_PREMULTI_SOURCE, &mixer->cmdq_base, mixer->regs, + MIX_L_SRC_CON(1)); + mtk_ddp_write(cmdq_pkt, NON_PREMULTI_SOURCE, &mixer->cmdq_base, mixer->regs, + MIX_L_SRC_CON(2)); + mtk_ddp_write(cmdq_pkt, NON_PREMULTI_SOURCE, &mixer->cmdq_base, mixer->regs, + MIX_L_SRC_CON(3)); + mtk_ddp_write(cmdq_pkt, 0x0, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_SIZE(0)); + mtk_ddp_write(cmdq_pkt, OUTPUT_NO_RND | SOURCE_RGB_SEL | BACKGROUND_RELAY, + &mixer->cmdq_base, mixer->regs, MIX_DATAPATH_CON); + mtk_ddp_write_mask(cmdq_pkt, MIX_SRC_L0_EN, &mixer->cmdq_base, mixer->regs, + MIX_SRC_CON, MIX_SRC_L0_EN); + + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_HDR_BE_ASYNC_WIDTH, 0, + w / 2, cmdq_pkt); + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_HDR_BE_ASYNC_HEIGHT, 0, + h, cmdq_pkt); + mtk_mmsys_ddp_config(priv->mmsys_dev, MMSYS_CONFIG_MIXER_IN_CH_SWAP, 4, 0, cmdq_pkt); +} + +void mtk_ethdr_start(struct device *dev) +{ + struct mtk_ethdr *priv = dev_get_drvdata(dev); + struct mtk_ethdr_comp *mixer = &priv->ethdr_comp[ETHDR_MIXER]; + + writel(1, mixer->regs + MIX_EN); +} + +void mtk_ethdr_stop(struct device *dev) +{ + struct mtk_ethdr *priv = dev_get_drvdata(dev); + struct mtk_ethdr_comp *mixer = &priv->ethdr_comp[ETHDR_MIXER]; + + writel(0, mixer->regs + MIX_EN); + writel(1, mixer->regs + MIX_RST); + reset_control_reset(devm_reset_control_array_get(dev, true, true)); + writel(0, mixer->regs + MIX_RST); +} + +int mtk_ethdr_clk_enable(struct device *dev) +{ + int ret; + struct mtk_ethdr *priv = dev_get_drvdata(dev); + + ret = clk_bulk_prepare_enable(ETHDR_CLK_NUM, priv->ethdr_clk); + if (ret) + dev_err(dev, + "ethdr_clk prepare enable failed\n"); + return ret; +} + +void mtk_ethdr_clk_disable(struct device *dev) +{ + struct mtk_ethdr *priv = dev_get_drvdata(dev); + + clk_bulk_disable_unprepare(ETHDR_CLK_NUM, priv->ethdr_clk); +} + +static int mtk_ethdr_bind(struct device *dev, struct device *master, + void *data) +{ + struct mtk_ethdr *priv = dev_get_drvdata(dev); + struct platform_device *ovl_adaptor; + struct drm_device *drm_dev = data; + struct mtk_drm_private *drm_private = drm_dev->dev_private; + + priv->mmsys_dev = drm_private->mmsys_dev; + + /* Bring up ovl adaptor rdma and merge */ + ovl_adaptor = platform_device_register_data(dev, "mediatek-disp-ovl-adaptor", + PLATFORM_DEVID_NONE, (void *)priv->mmsys_dev, + sizeof(*priv->mmsys_dev)); + if (IS_ERR(ovl_adaptor)) + return PTR_ERR(ovl_adaptor); + + priv->ovl_adaptor_dev = &ovl_adaptor->dev; + + return 0; +} + +static void mtk_ethdr_unbind(struct device *dev, struct device *master, void *data) +{ +} + +static const struct component_ops mtk_ethdr_component_ops = { + .bind = mtk_ethdr_bind, + .unbind = mtk_ethdr_unbind, +}; + +static int mtk_ethdr_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mtk_ethdr *priv; + int ret; + int i; + + dev_info(dev, "%s+\n", __func__); + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + for (i = 0; i < ETHDR_ID_MAX; i++) { + priv->ethdr_comp[i].dev = dev; + priv->ethdr_comp[i].regs = of_iomap(dev->of_node, i); +#if IS_REACHABLE(CONFIG_MTK_CMDQ) + ret = cmdq_dev_get_client_reg(dev, + &priv->ethdr_comp[i].cmdq_base, i); + if (ret) + dev_dbg(dev, "get mediatek,gce-client-reg fail!\n"); +#endif + dev_info(dev, "[DRM]regs:0x%x, node:%s\n", + priv->ethdr_comp[i].regs, ethdr_comp_str[i]); + } + + for (i = 0; i < ETHDR_CLK_NUM; i++) + priv->ethdr_clk[i].id = ethdr_clk_str[i]; + ret = devm_clk_bulk_get_optional(dev, ETHDR_CLK_NUM, priv->ethdr_clk); + if (ret) + return ret; + + priv->irq = platform_get_irq(pdev, 0); + if (priv->irq < 0) + priv->irq = 0; + + if (priv->irq) { + ret = devm_request_irq(dev, priv->irq, mtk_ethdr_irq_handler, + IRQF_TRIGGER_NONE, dev_name(dev), priv); + if (ret < 0) { + dev_err(dev, "Failed to request irq %d: %d\n", priv->irq, ret); + return ret; + } + } + + spin_lock_init(&priv->lock); + platform_set_drvdata(pdev, priv); + + ret = component_add(dev, &mtk_ethdr_component_ops); + if (ret) + dev_notice(dev, "Failed to add component: %d\n", ret); + + dev_info(dev, "%s-\n", __func__); + pm_runtime_enable(dev); + + return ret; +} + +static int mtk_ethdr_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &mtk_ethdr_component_ops); + pm_runtime_disable(&pdev->dev); + return 0; +} + +static const struct of_device_id mtk_ethdr_driver_dt_match[] = { + { .compatible = "mediatek,mt8195-disp-ethdr"}, + {}, +}; + +MODULE_DEVICE_TABLE(of, mtk_ethdr_driver_dt_match); + +struct platform_driver mtk_ethdr_driver = { + .probe = mtk_ethdr_probe, + .remove = mtk_ethdr_remove, + .driver = { + .name = "mediatek-disp-ethdr", + .owner = THIS_MODULE, + .of_match_table = mtk_ethdr_driver_dt_match, + }, +}; +module_platform_driver(mtk_ethdr_driver); diff --git a/drivers/gpu/drm/mediatek/mtk_ethdr.h b/drivers/gpu/drm/mediatek/mtk_ethdr.h new file mode 100644 index 000000000000..84eb9bf2ede0 --- /dev/null +++ b/drivers/gpu/drm/mediatek/mtk_ethdr.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021 MediaTek Inc. + */ + +#ifndef __MTK_ETHDR_H__ +#define __MTK_ETHDR_H__ + +#include <drm/mediatek_drm.h> + +void mtk_ethdr_start(struct device *dev); +void mtk_ethdr_stop(struct device *dev); +int mtk_ethdr_clk_enable(struct device *dev); +void mtk_ethdr_clk_disable(struct device *dev); +void mtk_ethdr_config(struct device *dev, unsigned int w, + unsigned int h, unsigned int vrefresh, + unsigned int bpc, struct cmdq_pkt *cmdq_pkt); +void mtk_ethdr_layer_config(struct device *dev, unsigned int idx, + struct mtk_plane_state *state, + struct cmdq_pkt *cmdq_pkt); +void mtk_ethdr_enable_vblank(struct device *dev, void (*vblank_cb)(void *), + void *vblank_cb_data); +void mtk_ethdr_disable_vblank(struct device *dev); +#endif +
ETHDR is a part of ovl_adaptor. ETHDR is designed for HDR video and graphics conversion in the external display path. It handles multiple HDR input types and performs tone mapping, color space/color format conversion, and then combine different layers, output the required HDR or SDR signal to the subsequent display path. Signed-off-by: Nancy.Lin <nancy.lin@mediatek.com> --- drivers/gpu/drm/mediatek/Makefile | 1 + drivers/gpu/drm/mediatek/mtk_ethdr.c | 424 +++++++++++++++++++++++++++ drivers/gpu/drm/mediatek/mtk_ethdr.h | 25 ++ 3 files changed, 450 insertions(+) create mode 100644 drivers/gpu/drm/mediatek/mtk_ethdr.c create mode 100644 drivers/gpu/drm/mediatek/mtk_ethdr.h