Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/drivers/media/platform/mediatek/mdp3/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 59 kB image not shown  

Quelle  mtk-mdp3-comp.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2022 MediaTek Inc.
 * Author: Ping-Hsun Wu <ping-hsun.wu@mediatek.com>
 */


#include <linux/clk.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
#include <linux/pm_runtime.h>
#include "mtk-mdp3-cfg.h"
#include "mtk-mdp3-comp.h"
#include "mtk-mdp3-core.h"
#include "mtk-mdp3-regs.h"

#include "mdp_reg_aal.h"
#include "mdp_reg_ccorr.h"
#include "mdp_reg_color.h"
#include "mdp_reg_fg.h"
#include "mdp_reg_hdr.h"
#include "mdp_reg_merge.h"
#include "mdp_reg_ovl.h"
#include "mdp_reg_pad.h"
#include "mdp_reg_rdma.h"
#include "mdp_reg_rsz.h"
#include "mdp_reg_tdshp.h"
#include "mdp_reg_wdma.h"
#include "mdp_reg_wrot.h"

static u32 mdp_comp_alias_id[MDP_COMP_TYPE_COUNT];
static int p_id;

static inline const struct mdp_platform_config *
__get_plat_cfg(const struct mdp_comp_ctx *ctx)
{
 if (!ctx)
  return NULL;

 return ctx->comp->mdp_dev->mdp_data->mdp_cfg;
}

static s64 get_comp_flag(const struct mdp_comp_ctx *ctx)
{
 const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
 u32 rdma0, rsz1;

 rdma0 = mdp_cfg_get_id_inner(ctx->comp->mdp_dev, MDP_COMP_RDMA0);
 rsz1 = mdp_cfg_get_id_inner(ctx->comp->mdp_dev, MDP_COMP_RSZ1);
 if (!rdma0 || !rsz1)
  return MDP_COMP_NONE;

 if (mdp_cfg && mdp_cfg->rdma_rsz1_sram_sharing)
  if (ctx->comp->inner_id == rdma0)
   return BIT(rdma0) | BIT(rsz1);

 return BIT(ctx->comp->inner_id);
}

static int init_rdma(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
{
 const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
 phys_addr_t base = ctx->comp->reg_base;
 u8 subsys_id = ctx->comp->subsys_id;
 s32 rdma0;

 rdma0 = mdp_cfg_get_id_inner(ctx->comp->mdp_dev, MDP_COMP_RDMA0);
 if (!rdma0)
  return -EINVAL;

 if (mdp_cfg && mdp_cfg->rdma_support_10bit) {
  struct mdp_comp *prz1 = ctx->comp->mdp_dev->comp[MDP_COMP_RSZ1];

  /* Disable RSZ1 */
  if (ctx->comp->inner_id == rdma0 && prz1)
   MM_REG_WRITE_MASK(cmd, subsys_id, prz1->reg_base,
       PRZ_ENABLE, 0x0, BIT(0));
 }

 /* Reset RDMA */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_RESET, BIT(0), BIT(0));
 MM_REG_POLL_MASK(cmd, subsys_id, base, MDP_RDMA_MON_STA_1, BIT(8), BIT(8));
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_RESET, 0x0, BIT(0));
 return 0;
}

static int config_rdma_frame(struct mdp_comp_ctx *ctx,
        struct mdp_cmdq_cmd *cmd,
        const struct v4l2_rect *compose)
{
 const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
 u32 colorformat = ctx->input->buffer.format.colorformat;
 bool block10bit = MDP_COLOR_IS_10BIT_PACKED(colorformat);
 bool en_ufo = MDP_COLOR_IS_UFP(colorformat);
 phys_addr_t base = ctx->comp->reg_base;
 u8 subsys_id = ctx->comp->subsys_id;
 u32 rdma_con_mask = 0;
 u32 reg = 0;

 if (mdp_cfg && mdp_cfg->rdma_support_10bit) {
  if (block10bit)
   MM_REG_WRITE_MASK(cmd, subsys_id, base,
       MDP_RDMA_RESV_DUMMY_0, 0x7, 0x7);
  else
   MM_REG_WRITE_MASK(cmd, subsys_id, base,
       MDP_RDMA_RESV_DUMMY_0, 0x0, 0x7);
 }

 /* Setup smi control */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_GMCIF_CON,
     (7 <<  4) + //burst type to 8
     (1 << 16),  //enable pre-ultra
     0x00030071);

 /* Setup source frame info */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rdma.src_ctrl);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.src_ctrl);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_SRC_CON, reg, 0x03C8FE0F);

 if (mdp_cfg)
  if (mdp_cfg->rdma_support_10bit && en_ufo) {
   /* Setup source buffer base */
   if (CFG_CHECK(MT8183, p_id))
    reg = CFG_COMP(MT8183, ctx->param, rdma.ufo_dec_y);
   else if (CFG_CHECK(MT8195, p_id))
    reg = CFG_COMP(MT8195, ctx->param, rdma.ufo_dec_y);
   MM_REG_WRITE(cmd, subsys_id, base,
         MDP_RDMA_UFO_DEC_LENGTH_BASE_Y, reg);

   if (CFG_CHECK(MT8183, p_id))
    reg = CFG_COMP(MT8183, ctx->param, rdma.ufo_dec_c);
   else if (CFG_CHECK(MT8195, p_id))
    reg = CFG_COMP(MT8195, ctx->param, rdma.ufo_dec_c);
   MM_REG_WRITE(cmd, subsys_id, base,
         MDP_RDMA_UFO_DEC_LENGTH_BASE_C, reg);

   /* Set 10bit source frame pitch */
   if (block10bit) {
    if (CFG_CHECK(MT8183, p_id))
     reg = CFG_COMP(MT8183, ctx->param, rdma.mf_bkgd_in_pxl);
    else if (CFG_CHECK(MT8195, p_id))
     reg = CFG_COMP(MT8195, ctx->param, rdma.mf_bkgd_in_pxl);
    MM_REG_WRITE_MASK(cmd, subsys_id, base,
        MDP_RDMA_MF_BKGD_SIZE_IN_PXL,
        reg, 0x001FFFFF);
   }
  }

 if (CFG_CHECK(MT8183, p_id)) {
  reg = CFG_COMP(MT8183, ctx->param, rdma.control);
  rdma_con_mask = 0x1110;
 } else if (CFG_CHECK(MT8195, p_id)) {
  reg = CFG_COMP(MT8195, ctx->param, rdma.control);
  rdma_con_mask = 0x1130;
 }
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_CON, reg, rdma_con_mask);

 /* Setup source buffer base */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rdma.iova[0]);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.iova[0]);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_0, reg);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rdma.iova[1]);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.iova[1]);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_1, reg);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rdma.iova[2]);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.iova[2]);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_2, reg);

 /* Setup source buffer end */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rdma.iova_end[0]);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.iova_end[0]);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_END_0, reg);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rdma.iova_end[1]);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.iova_end[1]);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_END_1, reg);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rdma.iova_end[2]);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.iova_end[2]);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_END_2, reg);

 /* Setup source frame pitch */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rdma.mf_bkgd);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.mf_bkgd);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_MF_BKGD_SIZE_IN_BYTE,
     reg, 0x001FFFFF);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rdma.sf_bkgd);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.sf_bkgd);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_SF_BKGD_SIZE_IN_BYTE,
     reg, 0x001FFFFF);

 /* Setup color transform */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rdma.transform);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.transform);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_TRANSFORM_0,
     reg, 0x0F110000);

 if (!mdp_cfg || !mdp_cfg->rdma_esl_setting)
  goto rdma_config_done;

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.dmabuf_con0);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_DMABUF_CON_0,
     reg, 0x0FFF00FF);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.ultra_th_high_con0);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_ULTRA_TH_HIGH_CON_0,
     reg, 0x3FFFFFFF);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.ultra_th_low_con0);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_ULTRA_TH_LOW_CON_0,
     reg, 0x3FFFFFFF);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.dmabuf_con1);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_DMABUF_CON_1,
     reg, 0x0F7F007F);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.ultra_th_high_con1);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_ULTRA_TH_HIGH_CON_1,
     reg, 0x3FFFFFFF);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.ultra_th_low_con1);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_ULTRA_TH_LOW_CON_1,
     reg, 0x3FFFFFFF);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.dmabuf_con2);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_DMABUF_CON_2,
     reg, 0x0F3F003F);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.ultra_th_high_con2);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_ULTRA_TH_HIGH_CON_2,
     reg, 0x3FFFFFFF);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.ultra_th_low_con2);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_ULTRA_TH_LOW_CON_2,
     reg, 0x3FFFFFFF);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.dmabuf_con3);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_DMABUF_CON_3,
     reg, 0x0F3F003F);

rdma_config_done:
 return 0;
}

static int config_rdma_subfrm(struct mdp_comp_ctx *ctx,
         struct mdp_cmdq_cmd *cmd, u32 index)
{
 const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
 u32 colorformat = ctx->input->buffer.format.colorformat;
 bool block10bit = MDP_COLOR_IS_10BIT_PACKED(colorformat);
 bool en_ufo = MDP_COLOR_IS_UFP(colorformat);
 phys_addr_t base = ctx->comp->reg_base;
 u8 subsys_id = ctx->comp->subsys_id;
 u32 csf_l = 0, csf_r = 0;
 u32 reg = 0;

 /* Enable RDMA */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_EN, BIT(0), BIT(0));

 /* Set Y pixel offset */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].offset[0]);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.subfrms[index].offset[0]);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_0, reg);

 /* Set 10bit UFO mode */
 if (mdp_cfg) {
  if (mdp_cfg->rdma_support_10bit && block10bit && en_ufo) {
   if (CFG_CHECK(MT8183, p_id))
    reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].offset_0_p);
   else if (CFG_CHECK(MT8195, p_id))
    reg = CFG_COMP(MT8195, ctx->param, rdma.subfrms[index].offset_0_p);
   MM_REG_WRITE(cmd, subsys_id, base,
         MDP_RDMA_SRC_OFFSET_0_P, reg);
  }
 }

 /* Set U pixel offset */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].offset[1]);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.subfrms[index].offset[1]);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_1, reg);

 /* Set V pixel offset */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].offset[2]);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.subfrms[index].offset[2]);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_2, reg);

 /* Set source size */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].src);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.subfrms[index].src);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_MF_SRC_SIZE, reg,
     0x1FFF1FFF);

 /* Set target size */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].clip);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.subfrms[index].clip);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_MF_CLIP_SIZE,
     reg, 0x1FFF1FFF);

 /* Set crop offset */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].clip_ofst);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rdma.subfrms[index].clip_ofst);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_MF_OFFSET_1,
     reg, 0x003F001F);

 if (CFG_CHECK(MT8183, p_id)) {
  csf_l = CFG_COMP(MT8183, ctx->param, subfrms[index].in.left);
  csf_r = CFG_COMP(MT8183, ctx->param, subfrms[index].in.right);
 } else if (CFG_CHECK(MT8195, p_id)) {
  csf_l = CFG_COMP(MT8195, ctx->param, subfrms[index].in.left);
  csf_r = CFG_COMP(MT8195, ctx->param, subfrms[index].in.right);
 }
 if (mdp_cfg && mdp_cfg->rdma_upsample_repeat_only)
  if ((csf_r - csf_l + 1) > 320)
   MM_REG_WRITE_MASK(cmd, subsys_id, base,
       MDP_RDMA_RESV_DUMMY_0, BIT(2), BIT(2));

 return 0;
}

static int wait_rdma_event(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
{
 const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
 struct device *dev = &ctx->comp->mdp_dev->pdev->dev;
 phys_addr_t base = ctx->comp->reg_base;
 u8 subsys_id = ctx->comp->subsys_id;

 if (!mdp_cfg)
  return -EINVAL;

 if (ctx->comp->alias_id >= mdp_cfg->rdma_event_num) {
  dev_err(dev, "Invalid RDMA event %d\n", ctx->comp->alias_id);
  return -EINVAL;
 }

 MM_REG_WAIT(cmd, ctx->comp->gce_event[MDP_GCE_EVENT_EOF]);

 /* Disable RDMA */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_RDMA_EN, 0x0, BIT(0));
 return 0;
}

static const struct mdp_comp_ops rdma_ops = {
 .get_comp_flag = get_comp_flag,
 .init_comp = init_rdma,
 .config_frame = config_rdma_frame,
 .config_subfrm = config_rdma_subfrm,
 .wait_comp_event = wait_rdma_event,
};

static int init_rsz(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
{
 phys_addr_t base = ctx->comp->reg_base;
 u8 subsys_id = ctx->comp->subsys_id;

 /* Reset RSZ */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, PRZ_ENABLE, 0x10000, BIT(16));
 MM_REG_WRITE_MASK(cmd, subsys_id, base, PRZ_ENABLE, 0x0, BIT(16));
 /* Enable RSZ */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, PRZ_ENABLE, BIT(0), BIT(0));

 if (CFG_CHECK(MT8195, p_id)) {
  struct device *dev;

  dev = ctx->comp->mdp_dev->mm_subsys[MDP_MM_SUBSYS_1].mmsys;
  mtk_mmsys_vpp_rsz_dcm_config(dev, true, NULL);
 }

 return 0;
}

static int config_rsz_frame(struct mdp_comp_ctx *ctx,
       struct mdp_cmdq_cmd *cmd,
       const struct v4l2_rect *compose)
{
 const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
 phys_addr_t base = ctx->comp->reg_base;
 u8 subsys_id = ctx->comp->subsys_id;
 bool bypass = FALSE;
 u32 reg = 0;

 if (mdp_cfg && mdp_cfg->rsz_etc_control)
  MM_REG_WRITE(cmd, subsys_id, base, RSZ_ETC_CONTROL, 0x0);

 if (CFG_CHECK(MT8183, p_id))
  bypass = CFG_COMP(MT8183, ctx->param, frame.bypass);
 else if (CFG_CHECK(MT8195, p_id))
  bypass = CFG_COMP(MT8195, ctx->param, frame.bypass);

 if (bypass) {
  /* Disable RSZ */
  MM_REG_WRITE_MASK(cmd, subsys_id, base, PRZ_ENABLE, 0x0, BIT(0));
  return 0;
 }

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rsz.control1);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rsz.control1);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, PRZ_CONTROL_1, reg, 0x03FFFDF3);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rsz.control2);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rsz.control2);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, PRZ_CONTROL_2, reg, 0x0FFFC290);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rsz.coeff_step_x);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rsz.coeff_step_x);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, PRZ_HORIZONTAL_COEFF_STEP, reg,
     0x007FFFFF);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rsz.coeff_step_y);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rsz.coeff_step_y);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, PRZ_VERTICAL_COEFF_STEP, reg,
     0x007FFFFF);

 return 0;
}

static int config_rsz_subfrm(struct mdp_comp_ctx *ctx,
        struct mdp_cmdq_cmd *cmd, u32 index)
{
 const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
 phys_addr_t base = ctx->comp->reg_base;
 u8 subsys_id = ctx->comp->subsys_id;
 u32 csf_l = 0, csf_r = 0;
 u32 reg = 0;
 u32 id;

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rsz.subfrms[index].control2);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rsz.subfrms[index].control2);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, PRZ_CONTROL_2, reg, 0x00003800);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rsz.subfrms[index].src);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rsz.subfrms[index].src);
 MM_REG_WRITE(cmd, subsys_id, base, PRZ_INPUT_IMAGE, reg);

 if (CFG_CHECK(MT8183, p_id)) {
  csf_l = CFG_COMP(MT8183, ctx->param, subfrms[index].in.left);
  csf_r = CFG_COMP(MT8183, ctx->param, subfrms[index].in.right);
 } else if (CFG_CHECK(MT8195, p_id)) {
  csf_l = CFG_COMP(MT8195, ctx->param, subfrms[index].in.left);
  csf_r = CFG_COMP(MT8195, ctx->param, subfrms[index].in.right);
 }
 if (mdp_cfg && mdp_cfg->rsz_disable_dcm_small_sample)
  if ((csf_r - csf_l + 1) <= 16)
   MM_REG_WRITE_MASK(cmd, subsys_id, base, PRZ_CONTROL_1,
       BIT(27), BIT(27));

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, subfrms[index].luma.left);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, subfrms[index].luma.left);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, PRZ_LUMA_HORIZONTAL_INTEGER_OFFSET,
     reg, 0xFFFF);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, subfrms[index].luma.left_subpix);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, subfrms[index].luma.left_subpix);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, PRZ_LUMA_HORIZONTAL_SUBPIXEL_OFFSET,
     reg, 0x1FFFFF);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, subfrms[index].luma.top);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, subfrms[index].luma.top);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, PRZ_LUMA_VERTICAL_INTEGER_OFFSET,
     reg, 0xFFFF);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, subfrms[index].luma.top_subpix);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, subfrms[index].luma.top_subpix);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, PRZ_LUMA_VERTICAL_SUBPIXEL_OFFSET,
     reg, 0x1FFFFF);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, subfrms[index].chroma.left);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, subfrms[index].chroma.left);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, PRZ_CHROMA_HORIZONTAL_INTEGER_OFFSET,
     reg, 0xFFFF);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, subfrms[index].chroma.left_subpix);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, subfrms[index].chroma.left_subpix);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, PRZ_CHROMA_HORIZONTAL_SUBPIXEL_OFFSET,
     reg, 0x1FFFFF);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, rsz.subfrms[index].clip);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, rsz.subfrms[index].clip);
 MM_REG_WRITE(cmd, subsys_id, base, PRZ_OUTPUT_IMAGE, reg);

 if (CFG_CHECK(MT8195, p_id)) {
  struct device *dev;
  struct mdp_comp *merge;
  const struct mtk_mdp_driver_data *data = ctx->comp->mdp_dev->mdp_data;
  enum mtk_mdp_comp_id public_id = ctx->comp->public_id;

  switch (public_id) {
  case MDP_COMP_RSZ2:
   merge = ctx->comp->mdp_dev->comp[MDP_COMP_MERGE2];
   break;
  case MDP_COMP_RSZ3:
   merge = ctx->comp->mdp_dev->comp[MDP_COMP_MERGE3];
   break;
  default:
   goto rsz_subfrm_done;
  }

  if (CFG_CHECK(MT8195, p_id))
   reg = CFG_COMP(MT8195, ctx->param, rsz.subfrms[index].rsz_switch);

  id = data->comp_data[public_id].match.alias_id;
  dev = ctx->comp->mdp_dev->mm_subsys[MDP_MM_SUBSYS_1].mmsys;
  mtk_mmsys_vpp_rsz_merge_config(dev, id, reg, NULL);

  if (CFG_CHECK(MT8195, p_id))
   reg = CFG_COMP(MT8195, ctx->param, rsz.subfrms[index].merge_cfg);
  MM_REG_WRITE(cmd, merge->subsys_id, merge->reg_base,
        MDP_MERGE_CFG_0, reg);
  MM_REG_WRITE(cmd, merge->subsys_id, merge->reg_base,
        MDP_MERGE_CFG_4, reg);
  MM_REG_WRITE(cmd, merge->subsys_id, merge->reg_base,
        MDP_MERGE_CFG_24, reg);
  MM_REG_WRITE(cmd, merge->subsys_id, merge->reg_base,
        MDP_MERGE_CFG_25, reg);

  /* Bypass mode */
  MM_REG_WRITE(cmd, merge->subsys_id, merge->reg_base,
        MDP_MERGE_CFG_12, BIT(0));
  MM_REG_WRITE(cmd, merge->subsys_id, merge->reg_base,
        MDP_MERGE_ENABLE, BIT(0));
 }

rsz_subfrm_done:
 return 0;
}

static int advance_rsz_subfrm(struct mdp_comp_ctx *ctx,
         struct mdp_cmdq_cmd *cmd, u32 index)
{
 const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);

 if (mdp_cfg && mdp_cfg->rsz_disable_dcm_small_sample) {
  phys_addr_t base = ctx->comp->reg_base;
  u8 subsys_id = ctx->comp->subsys_id;
  u32 csf_l = 0, csf_r = 0;

  if (CFG_CHECK(MT8183, p_id)) {
   csf_l = CFG_COMP(MT8183, ctx->param, subfrms[index].in.left);
   csf_r = CFG_COMP(MT8183, ctx->param, subfrms[index].in.right);
  } else if (CFG_CHECK(MT8195, p_id)) {
   csf_l = CFG_COMP(MT8195, ctx->param, subfrms[index].in.left);
   csf_r = CFG_COMP(MT8195, ctx->param, subfrms[index].in.right);
  }

  if ((csf_r - csf_l + 1) <= 16)
   MM_REG_WRITE_MASK(cmd, subsys_id, base, PRZ_CONTROL_1, 0x0,
       BIT(27));
 }

 return 0;
}

static const struct mdp_comp_ops rsz_ops = {
 .get_comp_flag = get_comp_flag,
 .init_comp = init_rsz,
 .config_frame = config_rsz_frame,
 .config_subfrm = config_rsz_subfrm,
 .advance_subfrm = advance_rsz_subfrm,
};

static int init_wrot(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
{
 phys_addr_t base = ctx->comp->reg_base;
 u8 subsys_id = ctx->comp->subsys_id;

 /* Reset WROT */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_SOFT_RST, BIT(0), BIT(0));
 MM_REG_POLL_MASK(cmd, subsys_id, base, VIDO_SOFT_RST_STAT, BIT(0), BIT(0));

 /* Reset setting */
 if (CFG_CHECK(MT8195, p_id))
  MM_REG_WRITE(cmd, subsys_id, base, VIDO_CTRL, 0x0);

 MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_SOFT_RST, 0x0, BIT(0));
 MM_REG_POLL_MASK(cmd, subsys_id, base, VIDO_SOFT_RST_STAT, 0x0, BIT(0));
 return 0;
}

static int config_wrot_frame(struct mdp_comp_ctx *ctx,
        struct mdp_cmdq_cmd *cmd,
        const struct v4l2_rect *compose)
{
 const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
 phys_addr_t base = ctx->comp->reg_base;
 u8 subsys_id = ctx->comp->subsys_id;
 u32 reg = 0;

 /* Write frame base address */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wrot.iova[0]);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, wrot.iova[0]);
 MM_REG_WRITE(cmd, subsys_id, base, VIDO_BASE_ADDR, reg);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wrot.iova[1]);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, wrot.iova[1]);
 MM_REG_WRITE(cmd, subsys_id, base, VIDO_BASE_ADDR_C, reg);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wrot.iova[2]);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, wrot.iova[2]);
 MM_REG_WRITE(cmd, subsys_id, base, VIDO_BASE_ADDR_V, reg);

 if (mdp_cfg && mdp_cfg->wrot_support_10bit) {
  if (CFG_CHECK(MT8195, p_id))
   reg = CFG_COMP(MT8195, ctx->param, wrot.scan_10bit);
  MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_SCAN_10BIT,
      reg, 0x0000000F);

  if (CFG_CHECK(MT8195, p_id))
   reg = CFG_COMP(MT8195, ctx->param, wrot.pending_zero);
  MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_PENDING_ZERO,
      reg, 0x04000000);
 }

 if (CFG_CHECK(MT8195, p_id)) {
  reg = CFG_COMP(MT8195, ctx->param, wrot.bit_number);
  MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_CTRL_2,
      reg, 0x00000007);
 }

 /* Write frame related registers */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wrot.control);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, wrot.control);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_CTRL, reg, 0xF131510F);

 /* Write pre-ultra threshold */
 if (CFG_CHECK(MT8195, p_id)) {
  reg = CFG_COMP(MT8195, ctx->param, wrot.pre_ultra);
  MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_DMA_PREULTRA, reg,
      0x00FFFFFF);
 }

 /* Write frame Y pitch */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wrot.stride[0]);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, wrot.stride[0]);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_STRIDE, reg, 0x0000FFFF);

 /* Write frame UV pitch */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wrot.stride[1]);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, wrot.stride[1]);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_STRIDE_C, reg, 0xFFFF);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wrot.stride[2]);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, wrot.stride[2]);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_STRIDE_V, reg, 0xFFFF);

 /* Write matrix control */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wrot.mat_ctrl);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, wrot.mat_ctrl);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_MAT_CTRL, reg, 0xF3);

 /* Set the fixed ALPHA as 0xFF */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_DITHER, 0xFF000000,
     0xFF000000);

 /* Set VIDO_EOL_SEL */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_RSV_1, BIT(31), BIT(31));

 /* Set VIDO_FIFO_TEST */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wrot.fifo_test);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, wrot.fifo_test);

 if (reg != 0)
  MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_FIFO_TEST, reg,
      0xFFF);

 /* Filter enable */
 if (mdp_cfg && mdp_cfg->wrot_filter_constraint) {
  if (CFG_CHECK(MT8183, p_id))
   reg = CFG_COMP(MT8183, ctx->param, wrot.filter);
  else if (CFG_CHECK(MT8195, p_id))
   reg = CFG_COMP(MT8195, ctx->param, wrot.filter);
  MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_MAIN_BUF_SIZE, reg,
      0x77);

  /* Turn off WROT DMA DCM */
  if (CFG_CHECK(MT8195, p_id))
   MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_ROT_EN,
       (0x1 << 23) + (0x1 << 20), 0x900000);
 }

 return 0;
}

static int config_wrot_subfrm(struct mdp_comp_ctx *ctx,
         struct mdp_cmdq_cmd *cmd, u32 index)
{
 phys_addr_t base = ctx->comp->reg_base;
 u8 subsys_id = ctx->comp->subsys_id;
 u32 reg = 0;

 /* Write Y pixel offset */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].offset[0]);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, wrot.subfrms[index].offset[0]);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_OFST_ADDR, reg, 0x0FFFFFFF);

 /* Write U pixel offset */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].offset[1]);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, wrot.subfrms[index].offset[1]);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_OFST_ADDR_C, reg, 0x0FFFFFFF);

 /* Write V pixel offset */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].offset[2]);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, wrot.subfrms[index].offset[2]);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_OFST_ADDR_V, reg,
     0x0FFFFFFF);

 /* Write source size */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].src);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, wrot.subfrms[index].src);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_IN_SIZE, reg, 0x1FFF1FFF);

 /* Write target size */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].clip);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, wrot.subfrms[index].clip);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_TAR_SIZE, reg, 0x1FFF1FFF);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].clip_ofst);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, wrot.subfrms[index].clip_ofst);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_CROP_OFST, reg, 0x1FFF1FFF);

 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].main_buf);
 else if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, wrot.subfrms[index].main_buf);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_MAIN_BUF_SIZE, reg,
     0x1FFF7F00);

 /* Enable WROT */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_ROT_EN, BIT(0), BIT(0));

 return 0;
}

static int wait_wrot_event(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
{
 const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
 struct device *dev = &ctx->comp->mdp_dev->pdev->dev;
 phys_addr_t base = ctx->comp->reg_base;
 u8 subsys_id = ctx->comp->subsys_id;

 if (!mdp_cfg)
  return -EINVAL;

 if (ctx->comp->alias_id >= mdp_cfg->wrot_event_num) {
  dev_err(dev, "Invalid WROT event %d!\n", ctx->comp->alias_id);
  return -EINVAL;
 }

 MM_REG_WAIT(cmd, ctx->comp->gce_event[MDP_GCE_EVENT_EOF]);

 if (mdp_cfg && mdp_cfg->wrot_filter_constraint)
  MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_MAIN_BUF_SIZE, 0x0,
      0x77);

 /* Disable WROT */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, VIDO_ROT_EN, 0x0, BIT(0));

 return 0;
}

static const struct mdp_comp_ops wrot_ops = {
 .get_comp_flag = get_comp_flag,
 .init_comp = init_wrot,
 .config_frame = config_wrot_frame,
 .config_subfrm = config_wrot_subfrm,
 .wait_comp_event = wait_wrot_event,
};

static int init_wdma(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
{
 phys_addr_t base = ctx->comp->reg_base;
 u8 subsys_id = ctx->comp->subsys_id;

 /* Reset WDMA */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, WDMA_RST, BIT(0), BIT(0));
 MM_REG_POLL_MASK(cmd, subsys_id, base, WDMA_FLOW_CTRL_DBG, BIT(0), BIT(0));
 MM_REG_WRITE_MASK(cmd, subsys_id, base, WDMA_RST, 0x0, BIT(0));
 return 0;
}

static int config_wdma_frame(struct mdp_comp_ctx *ctx,
        struct mdp_cmdq_cmd *cmd,
        const struct v4l2_rect *compose)
{
 phys_addr_t base = ctx->comp->reg_base;
 u8 subsys_id = ctx->comp->subsys_id;
 u32 reg = 0;

 MM_REG_WRITE(cmd, subsys_id, base, WDMA_BUF_CON2, 0x10101050);

 /* Setup frame information */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wdma.wdma_cfg);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, WDMA_CFG, reg, 0x0F01B8F0);
 /* Setup frame base address */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wdma.iova[0]);
 MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_ADDR, reg);
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wdma.iova[1]);
 MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_U_ADDR, reg);
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wdma.iova[2]);
 MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_V_ADDR, reg);
 /* Setup Y pitch */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wdma.w_in_byte);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, WDMA_DST_W_IN_BYTE, reg,
     0x0000FFFF);
 /* Setup UV pitch */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wdma.uv_stride);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, WDMA_DST_UV_PITCH, reg,
     0x0000FFFF);
 /* Set the fixed ALPHA as 0xFF */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, WDMA_ALPHA, 0x800000FF,
     0x800000FF);

 return 0;
}

static int config_wdma_subfrm(struct mdp_comp_ctx *ctx,
         struct mdp_cmdq_cmd *cmd, u32 index)
{
 phys_addr_t base = ctx->comp->reg_base;
 u8 subsys_id = ctx->comp->subsys_id;
 u32 reg = 0;

 /* Write Y pixel offset */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].offset[0]);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, WDMA_DST_ADDR_OFFSET, reg,
     0x0FFFFFFF);
 /* Write U pixel offset */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].offset[1]);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, WDMA_DST_U_ADDR_OFFSET, reg,
     0x0FFFFFFF);
 /* Write V pixel offset */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].offset[2]);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, WDMA_DST_V_ADDR_OFFSET, reg,
     0x0FFFFFFF);
 /* Write source size */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].src);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, WDMA_SRC_SIZE, reg, 0x3FFF3FFF);
 /* Write target size */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].clip);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, WDMA_CLIP_SIZE, reg, 0x3FFF3FFF);
 /* Write clip offset */
 if (CFG_CHECK(MT8183, p_id))
  reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].clip_ofst);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, WDMA_CLIP_COORD, reg, 0x3FFF3FFF);

 /* Enable WDMA */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, WDMA_EN, BIT(0), BIT(0));

 return 0;
}

static int wait_wdma_event(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
{
 phys_addr_t base = ctx->comp->reg_base;
 u8 subsys_id = ctx->comp->subsys_id;

 MM_REG_WAIT(cmd, ctx->comp->gce_event[MDP_GCE_EVENT_EOF]);
 /* Disable WDMA */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, WDMA_EN, 0x0, BIT(0));
 return 0;
}

static const struct mdp_comp_ops wdma_ops = {
 .get_comp_flag = get_comp_flag,
 .init_comp = init_wdma,
 .config_frame = config_wdma_frame,
 .config_subfrm = config_wdma_subfrm,
 .wait_comp_event = wait_wdma_event,
};

static int reset_luma_hist(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
{
 const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;
 u32 hist_num, i;

 if (!mdp_cfg)
  return -EINVAL;

 hist_num = mdp_cfg->tdshp_hist_num;

 /* Reset histogram */
 for (i = 0; i <= hist_num; i++)
  MM_REG_WRITE(cmd, subsys_id, base,
        (MDP_LUMA_HIST_INIT + (i << 2)), 0);

 if (mdp_cfg->tdshp_constrain)
  MM_REG_WRITE(cmd, subsys_id, base,
        MDP_DC_TWO_D_W1_RESULT_INIT, 0);

 if (mdp_cfg->tdshp_contour)
  for (i = 0; i < hist_num; i++)
   MM_REG_WRITE(cmd, subsys_id, base,
         (MDP_CONTOUR_HIST_INIT + (i << 2)), 0);

 return 0;
}

static int init_tdshp(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;

 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_TDSHP_CTRL, BIT(0), BIT(0));
 /* Enable FIFO */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_TDSHP_CFG, BIT(1), BIT(1));

 return reset_luma_hist(ctx, cmd);
}

static int config_tdshp_frame(struct mdp_comp_ctx *ctx,
         struct mdp_cmdq_cmd *cmd,
         const struct v4l2_rect *compose)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;
 u32 reg = 0;

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, tdshp.cfg);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_TDSHP_CFG, reg, BIT(0));

 return 0;
}

static int config_tdshp_subfrm(struct mdp_comp_ctx *ctx,
          struct mdp_cmdq_cmd *cmd, u32 index)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;
 u32 reg = 0;

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, tdshp.subfrms[index].src);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_TDSHP_INPUT_SIZE, reg);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, tdshp.subfrms[index].clip_ofst);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_TDSHP_OUTPUT_OFFSET, reg,
     0x00FF00FF);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, tdshp.subfrms[index].clip);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_TDSHP_OUTPUT_SIZE, reg);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, tdshp.subfrms[index].hist_cfg_0);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_HIST_CFG_00, reg);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, tdshp.subfrms[index].hist_cfg_1);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_HIST_CFG_01, reg);

 return 0;
}

static const struct mdp_comp_ops tdshp_ops = {
 .get_comp_flag = get_comp_flag,
 .init_comp = init_tdshp,
 .config_frame = config_tdshp_frame,
 .config_subfrm = config_tdshp_subfrm,
};

static int init_color(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;

 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_COLOR_START, 0x1,
     BIT(1) | BIT(0));
 MM_REG_WRITE(cmd, subsys_id, base, MDP_COLOR_WIN_X_MAIN, 0xFFFF0000);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_COLOR_WIN_Y_MAIN, 0xFFFF0000);

 /* Reset color matrix */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_COLOR_CM1_EN, 0x0, BIT(0));
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_COLOR_CM2_EN, 0x0, BIT(0));

 /* Enable interrupt */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_COLOR_INTEN, 0x7, 0x7);

 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_COLOR_OUT_SEL, 0x333, 0x333);

 return 0;
}

static int config_color_frame(struct mdp_comp_ctx *ctx,
         struct mdp_cmdq_cmd *cmd,
         const struct v4l2_rect *compose)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;
 u32 reg = 0;

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, color.start);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_COLOR_START, reg);

 return 0;
}

static int config_color_subfrm(struct mdp_comp_ctx *ctx,
          struct mdp_cmdq_cmd *cmd, u32 index)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;
 u32 reg = 0;

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, color.subfrms[index].in_hsize);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_COLOR_INTERNAL_IP_WIDTH,
     reg, 0x00003FFF);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, color.subfrms[index].in_vsize);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_COLOR_INTERNAL_IP_HEIGHT,
     reg, 0x00003FFF);

 return 0;
}

static const struct mdp_comp_ops color_ops = {
 .get_comp_flag = get_comp_flag,
 .init_comp = init_color,
 .config_frame = config_color_frame,
 .config_subfrm = config_color_subfrm,
};

static int init_ccorr(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
{
 phys_addr_t base = ctx->comp->reg_base;
 u8 subsys_id = ctx->comp->subsys_id;

 /* CCORR enable */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_CCORR_EN, BIT(0), BIT(0));
 /* Relay mode */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_CCORR_CFG, BIT(0), BIT(0));
 return 0;
}

static int config_ccorr_subfrm(struct mdp_comp_ctx *ctx,
          struct mdp_cmdq_cmd *cmd, u32 index)
{
 phys_addr_t base = ctx->comp->reg_base;
 u8 subsys_id = ctx->comp->subsys_id;
 u32 csf_l = 0, csf_r = 0;
 u32 csf_t = 0, csf_b = 0;
 u32 hsize, vsize;

 if (CFG_CHECK(MT8183, p_id)) {
  csf_l = CFG_COMP(MT8183, ctx->param, subfrms[index].in.left);
  csf_r = CFG_COMP(MT8183, ctx->param, subfrms[index].in.right);
  csf_t = CFG_COMP(MT8183, ctx->param, subfrms[index].in.top);
  csf_b = CFG_COMP(MT8183, ctx->param, subfrms[index].in.bottom);
 }

 hsize = csf_r - csf_l + 1;
 vsize = csf_b - csf_t + 1;
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_CCORR_SIZE,
     (hsize << 16) + (vsize <<  0), 0x1FFF1FFF);
 return 0;
}

static const struct mdp_comp_ops ccorr_ops = {
 .get_comp_flag = get_comp_flag,
 .init_comp = init_ccorr,
 .config_subfrm = config_ccorr_subfrm,
};

static int init_aal(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;

 /* Always set MDP_AAL enable to 1 */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_AAL_EN, BIT(0), BIT(0));

 return 0;
}

static int config_aal_frame(struct mdp_comp_ctx *ctx,
       struct mdp_cmdq_cmd *cmd,
       const struct v4l2_rect *compose)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;
 u32 reg = 0;

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, aal.cfg_main);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_AAL_CFG_MAIN, reg, BIT(7));

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, aal.cfg);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_AAL_CFG, reg, BIT(0));

 return 0;
}

static int config_aal_subfrm(struct mdp_comp_ctx *ctx,
        struct mdp_cmdq_cmd *cmd, u32 index)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;
 u32 reg = 0;

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, aal.subfrms[index].src);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_AAL_SIZE, reg);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, aal.subfrms[index].clip_ofst);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_AAL_OUTPUT_OFFSET, reg,
     0x00FF00FF);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, aal.subfrms[index].clip);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_AAL_OUTPUT_SIZE, reg);

 return 0;
}

static const struct mdp_comp_ops aal_ops = {
 .get_comp_flag = get_comp_flag,
 .init_comp = init_aal,
 .config_frame = config_aal_frame,
 .config_subfrm = config_aal_subfrm,
};

static int init_hdr(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;

 /* Always set MDP_HDR enable to 1 */
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_HDR_TOP, BIT(0), BIT(0));

 return 0;
}

static int config_hdr_frame(struct mdp_comp_ctx *ctx,
       struct mdp_cmdq_cmd *cmd,
       const struct v4l2_rect *compose)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;
 u32 reg = 0;

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, hdr.top);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_HDR_TOP, reg, BIT(29) | BIT(28));

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, hdr.relay);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_HDR_RELAY, reg, BIT(0));

 return 0;
}

static int config_hdr_subfrm(struct mdp_comp_ctx *ctx,
        struct mdp_cmdq_cmd *cmd, u32 index)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;
 u32 reg = 0;

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, hdr.subfrms[index].win_size);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_HDR_TILE_POS, reg);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, hdr.subfrms[index].src);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_HDR_SIZE_0, reg, 0x1FFF1FFF);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, hdr.subfrms[index].clip_ofst0);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_HDR_SIZE_1, reg, 0x1FFF1FFF);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, hdr.subfrms[index].clip_ofst1);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_HDR_SIZE_2, reg, 0x1FFF1FFF);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, hdr.subfrms[index].hist_ctrl_0);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_HDR_HIST_CTRL_0, reg, 0x00003FFF);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, hdr.subfrms[index].hist_ctrl_1);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_HDR_HIST_CTRL_1, reg, 0x00003FFF);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, hdr.subfrms[index].hdr_top);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_HDR_TOP, reg, BIT(6) | BIT(5));

 /* Enable histogram */
 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, hdr.subfrms[index].hist_addr);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_HDR_HIST_ADDR, reg, BIT(9));

 return 0;
}

static const struct mdp_comp_ops hdr_ops = {
 .get_comp_flag = get_comp_flag,
 .init_comp = init_hdr,
 .config_frame = config_hdr_frame,
 .config_subfrm = config_hdr_subfrm,
};

static int init_fg(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;

 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_FG_TRIGGER, BIT(2), BIT(2));
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_FG_TRIGGER, 0x0, BIT(2));

 return 0;
}

static int config_fg_frame(struct mdp_comp_ctx *ctx,
      struct mdp_cmdq_cmd *cmd,
      const struct v4l2_rect *compose)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;
 u32 reg = 0;

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, fg.ctrl_0);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_FG_FG_CTRL_0, reg, BIT(0));

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, fg.ck_en);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_FG_FG_CK_EN, reg, 0x7);

 return 0;
}

static int config_fg_subfrm(struct mdp_comp_ctx *ctx,
       struct mdp_cmdq_cmd *cmd, u32 index)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;
 u32 reg = 0;

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, fg.subfrms[index].info_0);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_FG_TILE_INFO_0, reg);

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, fg.subfrms[index].info_1);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_FG_TILE_INFO_1, reg);

 return 0;
}

static const struct mdp_comp_ops fg_ops = {
 .get_comp_flag = get_comp_flag,
 .init_comp = init_fg,
 .config_frame = config_fg_frame,
 .config_subfrm = config_fg_subfrm,
};

static int init_ovl(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;

 MM_REG_WRITE(cmd, subsys_id, base, MDP_OVL_EN, BIT(0));

 /* Set to relay mode */
 MM_REG_WRITE(cmd, subsys_id, base, MDP_OVL_SRC_CON, BIT(9));
 MM_REG_WRITE(cmd, subsys_id, base, MDP_OVL_DP_CON, BIT(0));

 return 0;
}

static int config_ovl_frame(struct mdp_comp_ctx *ctx,
       struct mdp_cmdq_cmd *cmd,
       const struct v4l2_rect *compose)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;
 u32 reg = 0;

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, ovl.L0_con);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_OVL_L0_CON, reg, BIT(29) | BIT(28));

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, ovl.src_con);
 MM_REG_WRITE_MASK(cmd, subsys_id, base, MDP_OVL_SRC_CON, reg, BIT(0));

 return 0;
}

static int config_ovl_subfrm(struct mdp_comp_ctx *ctx,
        struct mdp_cmdq_cmd *cmd, u32 index)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;
 u32 reg = 0;

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, ovl.subfrms[index].L0_src_size);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_OVL_L0_SRC_SIZE, reg);

 /* Setup output size */
 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, ovl.subfrms[index].roi_size);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_OVL_ROI_SIZE, reg);

 return 0;
}

static const struct mdp_comp_ops ovl_ops = {
 .get_comp_flag = get_comp_flag,
 .init_comp = init_ovl,
 .config_frame = config_ovl_frame,
 .config_subfrm = config_ovl_subfrm,
};

static int init_pad(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;

 MM_REG_WRITE(cmd, subsys_id, base, MDP_PAD_CON, BIT(1));
 /* Reset */
 MM_REG_WRITE(cmd, subsys_id, base, MDP_PAD_W_SIZE, 0);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_PAD_H_SIZE, 0);

 return 0;
}

static int config_pad_subfrm(struct mdp_comp_ctx *ctx,
        struct mdp_cmdq_cmd *cmd, u32 index)
{
 phys_addr_t base = ctx->comp->reg_base;
 u16 subsys_id = ctx->comp->subsys_id;
 u32 reg = 0;

 if (CFG_CHECK(MT8195, p_id))
  reg = CFG_COMP(MT8195, ctx->param, pad.subfrms[index].pic_size);
 MM_REG_WRITE(cmd, subsys_id, base, MDP_PAD_PIC_SIZE, reg);

 return 0;
}

static const struct mdp_comp_ops pad_ops = {
 .get_comp_flag = get_comp_flag,
 .init_comp = init_pad,
 .config_subfrm = config_pad_subfrm,
};

static const struct mdp_comp_ops *mdp_comp_ops[MDP_COMP_TYPE_COUNT] = {
 [MDP_COMP_TYPE_RDMA] =  &rdma_ops,
 [MDP_COMP_TYPE_RSZ] =  &rsz_ops,
 [MDP_COMP_TYPE_WROT] =  &wrot_ops,
 [MDP_COMP_TYPE_WDMA] =  &wdma_ops,
 [MDP_COMP_TYPE_TDSHP] =  &tdshp_ops,
 [MDP_COMP_TYPE_COLOR] =  &color_ops,
 [MDP_COMP_TYPE_CCORR] =  &ccorr_ops,
 [MDP_COMP_TYPE_AAL] =  &aal_ops,
 [MDP_COMP_TYPE_HDR] =  &hdr_ops,
 [MDP_COMP_TYPE_FG] =  &fg_ops,
 [MDP_COMP_TYPE_OVL] =  &ovl_ops,
 [MDP_COMP_TYPE_PAD] =  &pad_ops,
};

static const struct of_device_id mdp_comp_dt_ids[] __maybe_unused = {
 {
  .compatible = "mediatek,mt8183-mdp3-rdma",
  .data = (void *)MDP_COMP_TYPE_RDMA,
 }, {
  .compatible = "mediatek,mt8183-mdp3-ccorr",
  .data = (void *)MDP_COMP_TYPE_CCORR,
 }, {
  .compatible = "mediatek,mt8183-mdp3-rsz",
  .data = (void *)MDP_COMP_TYPE_RSZ,
 }, {
  .compatible = "mediatek,mt8183-mdp3-wrot",
  .data = (void *)MDP_COMP_TYPE_WROT,
 }, {
  .compatible = "mediatek,mt8183-mdp3-wdma",
  .data = (void *)MDP_COMP_TYPE_WDMA,
 }, {
  .compatible = "mediatek,mt8195-mdp3-rdma",
  .data = (void *)MDP_COMP_TYPE_RDMA,
 }, {
  .compatible = "mediatek,mt8195-mdp3-split",
  .data = (void *)MDP_COMP_TYPE_SPLIT,
 }, {
  .compatible = "mediatek,mt8195-mdp3-stitch",
  .data = (void *)MDP_COMP_TYPE_STITCH,
 }, {
  .compatible = "mediatek,mt8195-mdp3-fg",
  .data = (void *)MDP_COMP_TYPE_FG,
 }, {
  .compatible = "mediatek,mt8195-mdp3-hdr",
  .data = (void *)MDP_COMP_TYPE_HDR,
 }, {
  .compatible = "mediatek,mt8195-mdp3-aal",
  .data = (void *)MDP_COMP_TYPE_AAL,
 }, {
  .compatible = "mediatek,mt8195-mdp3-merge",
  .data = (void *)MDP_COMP_TYPE_MERGE,
 }, {
  .compatible = "mediatek,mt8195-mdp3-tdshp",
  .data = (void *)MDP_COMP_TYPE_TDSHP,
 }, {
  .compatible = "mediatek,mt8195-mdp3-color",
  .data = (void *)MDP_COMP_TYPE_COLOR,
 }, {
  .compatible = "mediatek,mt8195-mdp3-ovl",
  .data = (void *)MDP_COMP_TYPE_OVL,
 }, {
  .compatible = "mediatek,mt8195-mdp3-padding",
  .data = (void *)MDP_COMP_TYPE_PAD,
 }, {
  .compatible = "mediatek,mt8195-mdp3-tcc",
  .data = (void *)MDP_COMP_TYPE_TCC,
 }, {
  .compatible = "mediatek,mt8188-mdp3-rdma",
  .data = (void *)MDP_COMP_TYPE_RDMA,
 },
 {}
};

static inline bool is_dma_capable(const enum mdp_comp_type type)
{
 return (type == MDP_COMP_TYPE_RDMA ||
  type == MDP_COMP_TYPE_WROT ||
  type == MDP_COMP_TYPE_WDMA);
}

static inline bool is_bypass_gce_event(const enum mdp_comp_type type)
{
 /*
 * Subcomponent PATH is only used for the direction of data flow and
 * dose not need to wait for GCE event.
 */

 return (type == MDP_COMP_TYPE_PATH);
}

static int mdp_comp_get_id(struct mdp_dev *mdp, enum mdp_comp_type type, u32 alias_id)
{
 int i;

 for (i = 0; i < mdp->mdp_data->comp_data_len; i++)
  if (mdp->mdp_data->comp_data[i].match.type == type &&
      mdp->mdp_data->comp_data[i].match.alias_id == alias_id)
   return i;
 return -ENODEV;
}

int mdp_comp_clock_on(struct device *dev, struct mdp_comp *comp)
{
 int i, ret;

 /* Only DMA capable components need the pm control */
 if (comp->comp_dev && is_dma_capable(comp->type)) {
  ret = pm_runtime_resume_and_get(comp->comp_dev);
  if (ret < 0) {
   dev_err(dev,
    "Failed to get power, err %d. type:%d id:%d\n",
    ret, comp->type, comp->inner_id);
   return ret;
  }
 }

 for (i = 0; i < comp->clk_num; i++) {
  if (IS_ERR_OR_NULL(comp->clks[i]))
   continue;
  ret = clk_prepare_enable(comp->clks[i]);
  if (ret) {
   dev_err(dev,
    "Failed to enable clk %d. type:%d id:%d\n",
    i, comp->type, comp->inner_id);
   goto err_revert;
  }
 }

 return 0;

err_revert:
 while (--i >= 0) {
  if (IS_ERR_OR_NULL(comp->clks[i]))
   continue;
  clk_disable_unprepare(comp->clks[i]);
 }
 if (comp->comp_dev && is_dma_capable(comp->type))
  pm_runtime_put_sync(comp->comp_dev);

 return ret;
}

void mdp_comp_clock_off(struct device *dev, struct mdp_comp *comp)
{
 int i;

 for (i = 0; i < comp->clk_num; i++) {
  if (IS_ERR_OR_NULL(comp->clks[i]))
   continue;
  clk_disable_unprepare(comp->clks[i]);
 }

 if (comp->comp_dev && is_dma_capable(comp->type))
  pm_runtime_put(comp->comp_dev);
}

int mdp_comp_clocks_on(struct device *dev, struct mdp_comp *comps, int num)
{
 int i, ret;

 for (i = 0; i < num; i++) {
  struct mdp_dev *m = comps[i].mdp_dev;
  enum mtk_mdp_comp_id id;
  const struct mdp_comp_blend *b;

  /* Bypass the dummy component*/
  if (!m)
   continue;

  ret = mdp_comp_clock_on(dev, &comps[i]);
  if (ret)
   return ret;

  id = comps[i].public_id;
  b = &m->mdp_data->comp_data[id].blend;

  if (b && b->aid_clk) {
   ret = mdp_comp_clock_on(dev, m->comp[b->b_id]);
   if (ret)
    return ret;
  }
 }

 return 0;
}

void mdp_comp_clocks_off(struct device *dev, struct mdp_comp *comps, int num)
{
 int i;

 for (i = 0; i < num; i++) {
  struct mdp_dev *m = comps[i].mdp_dev;
  enum mtk_mdp_comp_id id;
  const struct mdp_comp_blend *b;

  /* Bypass the dummy component*/
  if (!m)
   continue;

  mdp_comp_clock_off(dev, &comps[i]);

  id = comps[i].public_id;
  b = &m->mdp_data->comp_data[id].blend;

  if (b && b->aid_clk)
   mdp_comp_clock_off(dev, m->comp[b->b_id]);
 }
}

static int mdp_get_subsys_id(struct mdp_dev *mdp, struct device *dev,
        struct device_node *node, struct mdp_comp *comp)
{
 struct platform_device *comp_pdev;
 struct cmdq_client_reg  cmdq_reg;
 int ret = 0;
 int index = 0;

 if (!dev || !node || !comp)
  return -EINVAL;

 comp_pdev = of_find_device_by_node(node);

 if (!comp_pdev) {
  dev_err(dev, "get comp_pdev fail! comp public id=%d, inner id=%d, type=%d\n",
   comp->public_id, comp->inner_id, comp->type);
  return -ENODEV;
 }

 index = mdp->mdp_data->comp_data[comp->public_id].info.dts_reg_ofst;
 ret = cmdq_dev_get_client_reg(&comp_pdev->dev, &cmdq_reg, index);
 if (ret != 0) {
  dev_err(&comp_pdev->dev, "cmdq_dev_get_subsys fail!\n");
  put_device(&comp_pdev->dev);
  return -EINVAL;
 }

 comp->subsys_id = cmdq_reg.subsys;
 dev_dbg(&comp_pdev->dev, "subsys id=%d\n", cmdq_reg.subsys);
 put_device(&comp_pdev->dev);

 return 0;
}

static void __mdp_comp_init(struct mdp_dev *mdp, struct device_node *node,
       struct mdp_comp *comp)
{
 struct resource res;
 phys_addr_t base;
 int index;

 index = mdp->mdp_data->comp_data[comp->public_id].info.dts_reg_ofst;
 if (of_address_to_resource(node, index, &res) < 0)
  base = 0L;
 else
  base = res.start;

 comp->mdp_dev = mdp;
 comp->regs = of_iomap(node, 0);
 comp->reg_base = base;
}

static int mdp_comp_init(struct mdp_dev *mdp, struct device_node *node,
    struct mdp_comp *comp, enum mtk_mdp_comp_id id)
{
 struct device *dev = &mdp->pdev->dev;
 struct platform_device *pdev_c;
 int clk_ofst;
 int i;
 s32 event;

 if (id < 0 || id >= MDP_MAX_COMP_COUNT) {
  dev_err(dev, "Invalid component id %d\n", id);
  return -EINVAL;
 }

 pdev_c = of_find_device_by_node(node);
 if (!pdev_c) {
  dev_warn(dev, "can't find platform device of node:%s\n",
    node->name);
  return -ENODEV;
 }

 comp->comp_dev = &pdev_c->dev;
 comp->public_id = id;
 comp->type = mdp->mdp_data->comp_data[id].match.type;
 comp->inner_id = mdp->mdp_data->comp_data[id].match.inner_id;
 comp->alias_id = mdp->mdp_data->comp_data[id].match.alias_id;
 comp->ops = mdp_comp_ops[comp->type];
 __mdp_comp_init(mdp, node, comp);

 comp->clk_num = mdp->mdp_data->comp_data[id].info.clk_num;
 comp->clks = devm_kzalloc(dev, sizeof(struct clk *) * comp->clk_num,
      GFP_KERNEL);
 if (!comp->clks)
  return -ENOMEM;

 clk_ofst = mdp->mdp_data->comp_data[id].info.clk_ofst;

 for (i = 0; i < comp->clk_num; i++) {
  comp->clks[i] = of_clk_get(node, i + clk_ofst);
  if (IS_ERR(comp->clks[i]))
   break;
 }

 mdp_get_subsys_id(mdp, dev, node, comp);

 /* Set GCE SOF event */
 if (is_bypass_gce_event(comp->type) ||
     of_property_read_u32_index(node, "mediatek,gce-events",
           MDP_GCE_EVENT_SOF, &event))
  event = MDP_GCE_NO_EVENT;

 comp->gce_event[MDP_GCE_EVENT_SOF] = event;

 /* Set GCE EOF event */
 if (is_dma_capable(comp->type)) {
  if (of_property_read_u32_index(node, "mediatek,gce-events",
            MDP_GCE_EVENT_EOF, &event)) {
   dev_err(dev, "Component id %d has no EOF\n", id);
   return -EINVAL;
  }
 } else {
  event = MDP_GCE_NO_EVENT;
 }

 comp->gce_event[MDP_GCE_EVENT_EOF] = event;

 return 0;
}

static void mdp_comp_deinit(struct mdp_comp *comp)
{
 if (!comp)
  return;

 if (comp->comp_dev && comp->clks) {
  devm_kfree(&comp->mdp_dev->pdev->dev, comp->clks);
  comp->clks = NULL;
 }

 if (comp->regs)
  iounmap(comp->regs);
}

static struct mdp_comp *mdp_comp_create(struct mdp_dev *mdp,
     struct device_node *node,
     enum mtk_mdp_comp_id id)
{
 struct device *dev = &mdp->pdev->dev;
 struct mdp_comp *comp;
 int ret;

 if (mdp->comp[id])
  return ERR_PTR(-EEXIST);

 comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL);
 if (!comp)
  return ERR_PTR(-ENOMEM);

 ret = mdp_comp_init(mdp, node, comp, id);
 if (ret) {
  devm_kfree(dev, comp);
  return ERR_PTR(ret);
 }
 mdp->comp[id] = comp;
 mdp->comp[id]->mdp_dev = mdp;

 dev_dbg(dev, "%s type:%d alias:%d public id:%d inner id:%d base:%#x regs:%p\n",
  dev->of_node->name, comp->type, comp->alias_id, id, comp->inner_id,
  (u32)comp->reg_base, comp->regs);
 return comp;
}

static int mdp_comp_sub_create(struct mdp_dev *mdp)
{
 struct device *dev = &mdp->pdev->dev;
 struct device_node *node, *parent;
 int ret = 0;

 parent = dev->of_node->parent;

 for_each_child_of_node(parent, node) {
  const struct of_device_id *of_id;
  enum mdp_comp_type type;
  int id, alias_id;
  struct mdp_comp *comp;

  of_id = of_match_node(mdp->mdp_data->mdp_sub_comp_dt_ids, node);
  if (!of_id)
   continue;
  if (!of_device_is_available(node)) {
   dev_dbg(dev, "Skipping disabled sub comp. %pOF\n",
    node);
   continue;
  }

  type = (enum mdp_comp_type)(uintptr_t)of_id->data;
  alias_id = mdp_comp_alias_id[type];
  id = mdp_comp_get_id(mdp, type, alias_id);
  if (id < 0) {
   dev_err(dev,
    "Fail to get sub comp. id: type %d alias %d\n",
    type, alias_id);
   ret = -EINVAL;
   goto err_free_node;
  }
  mdp_comp_alias_id[type]++;

  comp = mdp_comp_create(mdp, node, id);
  if (IS_ERR(comp)) {
   ret = PTR_ERR(comp);
   goto err_free_node;
  }
 }
 return ret;

err_free_node:
 of_node_put(node);
 return ret;
}

void mdp_comp_destroy(struct mdp_dev *mdp)
{
 int i;

 for (i = 0; i < ARRAY_SIZE(mdp->comp); i++) {
  if (mdp->comp[i]) {
   if (is_dma_capable(mdp->comp[i]->type))
    pm_runtime_disable(mdp->comp[i]->comp_dev);
   mdp_comp_deinit(mdp->comp[i]);
   devm_kfree(mdp->comp[i]->comp_dev, mdp->comp[i]);
   mdp->comp[i] = NULL;
  }
 }
}

int mdp_comp_config(struct mdp_dev *mdp)
{
 struct device *dev = &mdp->pdev->dev;
 struct device_node *node, *parent;
 int ret;

 memset(mdp_comp_alias_id, 0, sizeof(mdp_comp_alias_id));
 p_id = mdp->mdp_data->mdp_plat_id;

 parent = dev->of_node->parent;
 /* Iterate over sibling MDP function blocks */
 for_each_child_of_node(parent, node) {
  const struct of_device_id *of_id;
  enum mdp_comp_type type;
  int id, alias_id;
  struct mdp_comp *comp;

  of_id = of_match_node(mdp_comp_dt_ids, node);
  if (!of_id)
   continue;

  if (!of_device_is_available(node)) {
   dev_dbg(dev, "Skipping disabled component %pOF\n",
    node);
   continue;
  }

  type = (enum mdp_comp_type)(uintptr_t)of_id->data;
  alias_id = mdp_comp_alias_id[type];
  id = mdp_comp_get_id(mdp, type, alias_id);
  if (id < 0) {
   dev_err(dev,
    "Fail to get component id: type %d alias %d\n",
    type, alias_id);
   continue;
  }
  mdp_comp_alias_id[type]++;

  comp = mdp_comp_create(mdp, node, id);
  if (IS_ERR(comp)) {
   ret = PTR_ERR(comp);
   of_node_put(node);
   goto err_init_comps;
  }

  /* Only DMA capable components need the pm control */
  if (!is_dma_capable(comp->type))
   continue;
  pm_runtime_enable(comp->comp_dev);
 }

 ret = mdp_comp_sub_create(mdp);
 if (ret)
  goto err_init_comps;

 return 0;

err_init_comps:
 mdp_comp_destroy(mdp);
 return ret;
}

int mdp_comp_ctx_config(struct mdp_dev *mdp, struct mdp_comp_ctx *ctx,
   const struct img_compparam *param,
   const struct img_ipi_frameparam *frame)
{
 struct device *dev = &mdp->pdev->dev;
 enum mtk_mdp_comp_id public_id = MDP_COMP_NONE;
 u32 arg;
 int i, idx;

 if (!param) {
  dev_err(dev, "Invalid component param");
  return -EINVAL;
 }

 if (CFG_CHECK(MT8183, p_id))
  arg = CFG_COMP(MT8183, param, type);
 else if (CFG_CHECK(MT8195, p_id))
  arg = CFG_COMP(MT8195, param, type);
 else
  return -EINVAL;
 public_id = mdp_cfg_get_id_public(mdp, arg);
 if (public_id < 0) {
  dev_err(dev, "Invalid component id %d", public_id);
  return -EINVAL;
 }

 ctx->comp = mdp->comp[public_id];
 if (!ctx->comp) {
  dev_err(dev, "Uninit component inner id %d", arg);
  return -EINVAL;
 }

 ctx->param = param;
 if (CFG_CHECK(MT8183, p_id))
  arg = CFG_COMP(MT8183, param, input);
 else if (CFG_CHECK(MT8195, p_id))
  arg = CFG_COMP(MT8195, param, input);
 else
  return -EINVAL;
 ctx->input = &frame->inputs[arg];
 if (CFG_CHECK(MT8183, p_id))
  idx = CFG_COMP(MT8183, param, num_outputs);
 else if (CFG_CHECK(MT8195, p_id))
  idx = CFG_COMP(MT8195, param, num_outputs);
 else
  return -EINVAL;
 for (i = 0; i < idx; i++) {
  if (CFG_CHECK(MT8183, p_id))
   arg = CFG_COMP(MT8183, param, outputs[i]);
  else if (CFG_CHECK(MT8195, p_id))
   arg = CFG_COMP(MT8195, param, outputs[i]);
  else
   return -EINVAL;
  ctx->outputs[i] = &frame->outputs[arg];
 }
 return 0;
}

Messung V0.5
C=97 H=97 G=96

¤ Dauer der Verarbeitung: 0.29 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.