162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2022 MediaTek Inc. 462306a36Sopenharmony_ci * Author: Ping-Hsun Wu <ping-hsun.wu@mediatek.com> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/clk.h> 862306a36Sopenharmony_ci#include <linux/of_platform.h> 962306a36Sopenharmony_ci#include <linux/of_address.h> 1062306a36Sopenharmony_ci#include <linux/pm_runtime.h> 1162306a36Sopenharmony_ci#include "mtk-mdp3-cfg.h" 1262306a36Sopenharmony_ci#include "mtk-mdp3-comp.h" 1362306a36Sopenharmony_ci#include "mtk-mdp3-core.h" 1462306a36Sopenharmony_ci#include "mtk-mdp3-regs.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "mdp_reg_rdma.h" 1762306a36Sopenharmony_ci#include "mdp_reg_ccorr.h" 1862306a36Sopenharmony_ci#include "mdp_reg_rsz.h" 1962306a36Sopenharmony_ci#include "mdp_reg_wrot.h" 2062306a36Sopenharmony_ci#include "mdp_reg_wdma.h" 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistatic u32 mdp_comp_alias_id[MDP_COMP_TYPE_COUNT]; 2362306a36Sopenharmony_cistatic int p_id; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic inline const struct mdp_platform_config * 2662306a36Sopenharmony_ci__get_plat_cfg(const struct mdp_comp_ctx *ctx) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci if (!ctx) 2962306a36Sopenharmony_ci return NULL; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci return ctx->comp->mdp_dev->mdp_data->mdp_cfg; 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic s64 get_comp_flag(const struct mdp_comp_ctx *ctx) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx); 3762306a36Sopenharmony_ci u32 rdma0, rsz1; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci rdma0 = mdp_cfg_get_id_inner(ctx->comp->mdp_dev, MDP_COMP_RDMA0); 4062306a36Sopenharmony_ci rsz1 = mdp_cfg_get_id_inner(ctx->comp->mdp_dev, MDP_COMP_RSZ1); 4162306a36Sopenharmony_ci if (!rdma0 || !rsz1) 4262306a36Sopenharmony_ci return MDP_COMP_NONE; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci if (mdp_cfg && mdp_cfg->rdma_rsz1_sram_sharing) 4562306a36Sopenharmony_ci if (ctx->comp->inner_id == rdma0) 4662306a36Sopenharmony_ci return BIT(rdma0) | BIT(rsz1); 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci return BIT(ctx->comp->inner_id); 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic int init_rdma(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx); 5462306a36Sopenharmony_ci phys_addr_t base = ctx->comp->reg_base; 5562306a36Sopenharmony_ci u8 subsys_id = ctx->comp->subsys_id; 5662306a36Sopenharmony_ci s32 rdma0; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci rdma0 = mdp_cfg_get_id_inner(ctx->comp->mdp_dev, MDP_COMP_RDMA0); 5962306a36Sopenharmony_ci if (!rdma0) 6062306a36Sopenharmony_ci return -EINVAL; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci if (mdp_cfg && mdp_cfg->rdma_support_10bit) { 6362306a36Sopenharmony_ci struct mdp_comp *prz1 = ctx->comp->mdp_dev->comp[MDP_COMP_RSZ1]; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci /* Disable RSZ1 */ 6662306a36Sopenharmony_ci if (ctx->comp->inner_id == rdma0 && prz1) 6762306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, prz1->reg_base, PRZ_ENABLE, 6862306a36Sopenharmony_ci 0x0, BIT(0)); 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci /* Reset RDMA */ 7262306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_RESET, BIT(0), BIT(0)); 7362306a36Sopenharmony_ci MM_REG_POLL(cmd, subsys_id, base, MDP_RDMA_MON_STA_1, BIT(8), BIT(8)); 7462306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_RESET, 0x0, BIT(0)); 7562306a36Sopenharmony_ci return 0; 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistatic int config_rdma_frame(struct mdp_comp_ctx *ctx, 7962306a36Sopenharmony_ci struct mdp_cmdq_cmd *cmd, 8062306a36Sopenharmony_ci const struct v4l2_rect *compose) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx); 8362306a36Sopenharmony_ci u32 colorformat = ctx->input->buffer.format.colorformat; 8462306a36Sopenharmony_ci bool block10bit = MDP_COLOR_IS_10BIT_PACKED(colorformat); 8562306a36Sopenharmony_ci bool en_ufo = MDP_COLOR_IS_UFP(colorformat); 8662306a36Sopenharmony_ci phys_addr_t base = ctx->comp->reg_base; 8762306a36Sopenharmony_ci u8 subsys_id = ctx->comp->subsys_id; 8862306a36Sopenharmony_ci u32 reg = 0; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci if (mdp_cfg && mdp_cfg->rdma_support_10bit) { 9162306a36Sopenharmony_ci if (block10bit) 9262306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, 9362306a36Sopenharmony_ci MDP_RDMA_RESV_DUMMY_0, 0x7, 0x7); 9462306a36Sopenharmony_ci else 9562306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, 9662306a36Sopenharmony_ci MDP_RDMA_RESV_DUMMY_0, 0x0, 0x7); 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci /* Setup smi control */ 10062306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_GMCIF_CON, 10162306a36Sopenharmony_ci (7 << 4) + //burst type to 8 10262306a36Sopenharmony_ci (1 << 16), //enable pre-ultra 10362306a36Sopenharmony_ci 0x00030071); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci /* Setup source frame info */ 10662306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 10762306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.src_ctrl); 10862306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_CON, reg, 10962306a36Sopenharmony_ci 0x03C8FE0F); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci if (mdp_cfg) 11262306a36Sopenharmony_ci if (mdp_cfg->rdma_support_10bit && en_ufo) { 11362306a36Sopenharmony_ci /* Setup source buffer base */ 11462306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 11562306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.ufo_dec_y); 11662306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, 11762306a36Sopenharmony_ci base, MDP_RDMA_UFO_DEC_LENGTH_BASE_Y, 11862306a36Sopenharmony_ci reg, 0xFFFFFFFF); 11962306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 12062306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.ufo_dec_c); 12162306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, 12262306a36Sopenharmony_ci base, MDP_RDMA_UFO_DEC_LENGTH_BASE_C, 12362306a36Sopenharmony_ci reg, 0xFFFFFFFF); 12462306a36Sopenharmony_ci /* Set 10bit source frame pitch */ 12562306a36Sopenharmony_ci if (block10bit) { 12662306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 12762306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.mf_bkgd_in_pxl); 12862306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, 12962306a36Sopenharmony_ci base, MDP_RDMA_MF_BKGD_SIZE_IN_PXL, 13062306a36Sopenharmony_ci reg, 0x001FFFFF); 13162306a36Sopenharmony_ci } 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 13562306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.control); 13662306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_CON, reg, 13762306a36Sopenharmony_ci 0x1110); 13862306a36Sopenharmony_ci /* Setup source buffer base */ 13962306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 14062306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.iova[0]); 14162306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_0, reg, 14262306a36Sopenharmony_ci 0xFFFFFFFF); 14362306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 14462306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.iova[1]); 14562306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_1, reg, 14662306a36Sopenharmony_ci 0xFFFFFFFF); 14762306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 14862306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.iova[2]); 14962306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_2, reg, 15062306a36Sopenharmony_ci 0xFFFFFFFF); 15162306a36Sopenharmony_ci /* Setup source buffer end */ 15262306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 15362306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.iova_end[0]); 15462306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_END_0, 15562306a36Sopenharmony_ci reg, 0xFFFFFFFF); 15662306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 15762306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.iova_end[1]); 15862306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_END_1, 15962306a36Sopenharmony_ci reg, 0xFFFFFFFF); 16062306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 16162306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.iova_end[2]); 16262306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_END_2, 16362306a36Sopenharmony_ci reg, 0xFFFFFFFF); 16462306a36Sopenharmony_ci /* Setup source frame pitch */ 16562306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 16662306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.mf_bkgd); 16762306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_MF_BKGD_SIZE_IN_BYTE, 16862306a36Sopenharmony_ci reg, 0x001FFFFF); 16962306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 17062306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.sf_bkgd); 17162306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SF_BKGD_SIZE_IN_BYTE, 17262306a36Sopenharmony_ci reg, 0x001FFFFF); 17362306a36Sopenharmony_ci /* Setup color transform */ 17462306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 17562306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.transform); 17662306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_TRANSFORM_0, 17762306a36Sopenharmony_ci reg, 0x0F110000); 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci return 0; 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic int config_rdma_subfrm(struct mdp_comp_ctx *ctx, 18362306a36Sopenharmony_ci struct mdp_cmdq_cmd *cmd, u32 index) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx); 18662306a36Sopenharmony_ci u32 colorformat = ctx->input->buffer.format.colorformat; 18762306a36Sopenharmony_ci bool block10bit = MDP_COLOR_IS_10BIT_PACKED(colorformat); 18862306a36Sopenharmony_ci bool en_ufo = MDP_COLOR_IS_UFP(colorformat); 18962306a36Sopenharmony_ci phys_addr_t base = ctx->comp->reg_base; 19062306a36Sopenharmony_ci u8 subsys_id = ctx->comp->subsys_id; 19162306a36Sopenharmony_ci u32 csf_l = 0, csf_r = 0; 19262306a36Sopenharmony_ci u32 reg = 0; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci /* Enable RDMA */ 19562306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_EN, BIT(0), BIT(0)); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci /* Set Y pixel offset */ 19862306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 19962306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].offset[0]); 20062306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_0, 20162306a36Sopenharmony_ci reg, 0xFFFFFFFF); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci /* Set 10bit UFO mode */ 20462306a36Sopenharmony_ci if (mdp_cfg) { 20562306a36Sopenharmony_ci if (mdp_cfg->rdma_support_10bit && block10bit && en_ufo) { 20662306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 20762306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].offset_0_p); 20862306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, 20962306a36Sopenharmony_ci MDP_RDMA_SRC_OFFSET_0_P, 21062306a36Sopenharmony_ci reg, 0xFFFFFFFF); 21162306a36Sopenharmony_ci } 21262306a36Sopenharmony_ci } 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci /* Set U pixel offset */ 21562306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 21662306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].offset[1]); 21762306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_1, 21862306a36Sopenharmony_ci reg, 0xFFFFFFFF); 21962306a36Sopenharmony_ci /* Set V pixel offset */ 22062306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 22162306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].offset[2]); 22262306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_2, 22362306a36Sopenharmony_ci reg, 0xFFFFFFFF); 22462306a36Sopenharmony_ci /* Set source size */ 22562306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 22662306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].src); 22762306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_MF_SRC_SIZE, reg, 22862306a36Sopenharmony_ci 0x1FFF1FFF); 22962306a36Sopenharmony_ci /* Set target size */ 23062306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 23162306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].clip); 23262306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_MF_CLIP_SIZE, 23362306a36Sopenharmony_ci reg, 0x1FFF1FFF); 23462306a36Sopenharmony_ci /* Set crop offset */ 23562306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 23662306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].clip_ofst); 23762306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_MF_OFFSET_1, 23862306a36Sopenharmony_ci reg, 0x003F001F); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) { 24162306a36Sopenharmony_ci csf_l = CFG_COMP(MT8183, ctx->param, subfrms[index].in.left); 24262306a36Sopenharmony_ci csf_r = CFG_COMP(MT8183, ctx->param, subfrms[index].in.right); 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci if (mdp_cfg && mdp_cfg->rdma_upsample_repeat_only) 24562306a36Sopenharmony_ci if ((csf_r - csf_l + 1) > 320) 24662306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, 24762306a36Sopenharmony_ci MDP_RDMA_RESV_DUMMY_0, BIT(2), BIT(2)); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci return 0; 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_cistatic int wait_rdma_event(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd) 25362306a36Sopenharmony_ci{ 25462306a36Sopenharmony_ci struct device *dev = &ctx->comp->mdp_dev->pdev->dev; 25562306a36Sopenharmony_ci phys_addr_t base = ctx->comp->reg_base; 25662306a36Sopenharmony_ci u8 subsys_id = ctx->comp->subsys_id; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci if (ctx->comp->alias_id == 0) 25962306a36Sopenharmony_ci MM_REG_WAIT(cmd, ctx->comp->gce_event[MDP_GCE_EVENT_EOF]); 26062306a36Sopenharmony_ci else 26162306a36Sopenharmony_ci dev_err(dev, "Do not support RDMA1_DONE event\n"); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci /* Disable RDMA */ 26462306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_EN, 0x0, BIT(0)); 26562306a36Sopenharmony_ci return 0; 26662306a36Sopenharmony_ci} 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_cistatic const struct mdp_comp_ops rdma_ops = { 26962306a36Sopenharmony_ci .get_comp_flag = get_comp_flag, 27062306a36Sopenharmony_ci .init_comp = init_rdma, 27162306a36Sopenharmony_ci .config_frame = config_rdma_frame, 27262306a36Sopenharmony_ci .config_subfrm = config_rdma_subfrm, 27362306a36Sopenharmony_ci .wait_comp_event = wait_rdma_event, 27462306a36Sopenharmony_ci}; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_cistatic int init_rsz(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci phys_addr_t base = ctx->comp->reg_base; 27962306a36Sopenharmony_ci u8 subsys_id = ctx->comp->subsys_id; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci /* Reset RSZ */ 28262306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, PRZ_ENABLE, 0x10000, BIT(16)); 28362306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, PRZ_ENABLE, 0x0, BIT(16)); 28462306a36Sopenharmony_ci /* Enable RSZ */ 28562306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, PRZ_ENABLE, BIT(0), BIT(0)); 28662306a36Sopenharmony_ci return 0; 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cistatic int config_rsz_frame(struct mdp_comp_ctx *ctx, 29062306a36Sopenharmony_ci struct mdp_cmdq_cmd *cmd, 29162306a36Sopenharmony_ci const struct v4l2_rect *compose) 29262306a36Sopenharmony_ci{ 29362306a36Sopenharmony_ci phys_addr_t base = ctx->comp->reg_base; 29462306a36Sopenharmony_ci u8 subsys_id = ctx->comp->subsys_id; 29562306a36Sopenharmony_ci bool bypass = FALSE; 29662306a36Sopenharmony_ci u32 reg = 0; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 29962306a36Sopenharmony_ci bypass = CFG_COMP(MT8183, ctx->param, frame.bypass); 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci if (bypass) { 30262306a36Sopenharmony_ci /* Disable RSZ */ 30362306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, PRZ_ENABLE, 0x0, BIT(0)); 30462306a36Sopenharmony_ci return 0; 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 30862306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rsz.control1); 30962306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_1, reg, 31062306a36Sopenharmony_ci 0x03FFFDF3); 31162306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 31262306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rsz.control2); 31362306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_2, reg, 31462306a36Sopenharmony_ci 0x0FFFC290); 31562306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 31662306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rsz.coeff_step_x); 31762306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, PRZ_HORIZONTAL_COEFF_STEP, 31862306a36Sopenharmony_ci reg, 0x007FFFFF); 31962306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 32062306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rsz.coeff_step_y); 32162306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, PRZ_VERTICAL_COEFF_STEP, 32262306a36Sopenharmony_ci reg, 0x007FFFFF); 32362306a36Sopenharmony_ci return 0; 32462306a36Sopenharmony_ci} 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_cistatic int config_rsz_subfrm(struct mdp_comp_ctx *ctx, 32762306a36Sopenharmony_ci struct mdp_cmdq_cmd *cmd, u32 index) 32862306a36Sopenharmony_ci{ 32962306a36Sopenharmony_ci const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx); 33062306a36Sopenharmony_ci phys_addr_t base = ctx->comp->reg_base; 33162306a36Sopenharmony_ci u8 subsys_id = ctx->comp->subsys_id; 33262306a36Sopenharmony_ci u32 csf_l = 0, csf_r = 0; 33362306a36Sopenharmony_ci u32 reg = 0; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 33662306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rsz.subfrms[index].control2); 33762306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_2, reg, 33862306a36Sopenharmony_ci 0x00003800); 33962306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 34062306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rsz.subfrms[index].src); 34162306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, PRZ_INPUT_IMAGE, reg, 34262306a36Sopenharmony_ci 0xFFFFFFFF); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) { 34562306a36Sopenharmony_ci csf_l = CFG_COMP(MT8183, ctx->param, subfrms[index].in.left); 34662306a36Sopenharmony_ci csf_r = CFG_COMP(MT8183, ctx->param, subfrms[index].in.right); 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci if (mdp_cfg && mdp_cfg->rsz_disable_dcm_small_sample) 34962306a36Sopenharmony_ci if ((csf_r - csf_l + 1) <= 16) 35062306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_1, 35162306a36Sopenharmony_ci BIT(27), BIT(27)); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 35462306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, subfrms[index].luma.left); 35562306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, PRZ_LUMA_HORIZONTAL_INTEGER_OFFSET, 35662306a36Sopenharmony_ci reg, 0xFFFF); 35762306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 35862306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, subfrms[index].luma.left_subpix); 35962306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, 36062306a36Sopenharmony_ci base, PRZ_LUMA_HORIZONTAL_SUBPIXEL_OFFSET, 36162306a36Sopenharmony_ci reg, 0x1FFFFF); 36262306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 36362306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, subfrms[index].luma.top); 36462306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, PRZ_LUMA_VERTICAL_INTEGER_OFFSET, 36562306a36Sopenharmony_ci reg, 0xFFFF); 36662306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 36762306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, subfrms[index].luma.top_subpix); 36862306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, PRZ_LUMA_VERTICAL_SUBPIXEL_OFFSET, 36962306a36Sopenharmony_ci reg, 0x1FFFFF); 37062306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 37162306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, subfrms[index].chroma.left); 37262306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, 37362306a36Sopenharmony_ci base, PRZ_CHROMA_HORIZONTAL_INTEGER_OFFSET, 37462306a36Sopenharmony_ci reg, 0xFFFF); 37562306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 37662306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, subfrms[index].chroma.left_subpix); 37762306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, 37862306a36Sopenharmony_ci base, PRZ_CHROMA_HORIZONTAL_SUBPIXEL_OFFSET, 37962306a36Sopenharmony_ci reg, 0x1FFFFF); 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 38262306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, rsz.subfrms[index].clip); 38362306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, PRZ_OUTPUT_IMAGE, reg, 38462306a36Sopenharmony_ci 0xFFFFFFFF); 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci return 0; 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_cistatic int advance_rsz_subfrm(struct mdp_comp_ctx *ctx, 39062306a36Sopenharmony_ci struct mdp_cmdq_cmd *cmd, u32 index) 39162306a36Sopenharmony_ci{ 39262306a36Sopenharmony_ci const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci if (mdp_cfg && mdp_cfg->rsz_disable_dcm_small_sample) { 39562306a36Sopenharmony_ci phys_addr_t base = ctx->comp->reg_base; 39662306a36Sopenharmony_ci u8 subsys_id = ctx->comp->subsys_id; 39762306a36Sopenharmony_ci u32 csf_l = 0, csf_r = 0; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) { 40062306a36Sopenharmony_ci csf_l = CFG_COMP(MT8183, ctx->param, subfrms[index].in.left); 40162306a36Sopenharmony_ci csf_r = CFG_COMP(MT8183, ctx->param, subfrms[index].in.right); 40262306a36Sopenharmony_ci } 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci if ((csf_r - csf_l + 1) <= 16) 40562306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_1, 0x0, 40662306a36Sopenharmony_ci BIT(27)); 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci return 0; 41062306a36Sopenharmony_ci} 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_cistatic const struct mdp_comp_ops rsz_ops = { 41362306a36Sopenharmony_ci .get_comp_flag = get_comp_flag, 41462306a36Sopenharmony_ci .init_comp = init_rsz, 41562306a36Sopenharmony_ci .config_frame = config_rsz_frame, 41662306a36Sopenharmony_ci .config_subfrm = config_rsz_subfrm, 41762306a36Sopenharmony_ci .advance_subfrm = advance_rsz_subfrm, 41862306a36Sopenharmony_ci}; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_cistatic int init_wrot(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd) 42162306a36Sopenharmony_ci{ 42262306a36Sopenharmony_ci phys_addr_t base = ctx->comp->reg_base; 42362306a36Sopenharmony_ci u8 subsys_id = ctx->comp->subsys_id; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci /* Reset WROT */ 42662306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_SOFT_RST, BIT(0), BIT(0)); 42762306a36Sopenharmony_ci MM_REG_POLL(cmd, subsys_id, base, VIDO_SOFT_RST_STAT, BIT(0), BIT(0)); 42862306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_SOFT_RST, 0x0, BIT(0)); 42962306a36Sopenharmony_ci MM_REG_POLL(cmd, subsys_id, base, VIDO_SOFT_RST_STAT, 0x0, BIT(0)); 43062306a36Sopenharmony_ci return 0; 43162306a36Sopenharmony_ci} 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_cistatic int config_wrot_frame(struct mdp_comp_ctx *ctx, 43462306a36Sopenharmony_ci struct mdp_cmdq_cmd *cmd, 43562306a36Sopenharmony_ci const struct v4l2_rect *compose) 43662306a36Sopenharmony_ci{ 43762306a36Sopenharmony_ci const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx); 43862306a36Sopenharmony_ci phys_addr_t base = ctx->comp->reg_base; 43962306a36Sopenharmony_ci u8 subsys_id = ctx->comp->subsys_id; 44062306a36Sopenharmony_ci u32 reg = 0; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci /* Write frame base address */ 44362306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 44462306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wrot.iova[0]); 44562306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_BASE_ADDR, reg, 44662306a36Sopenharmony_ci 0xFFFFFFFF); 44762306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 44862306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wrot.iova[1]); 44962306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_BASE_ADDR_C, reg, 45062306a36Sopenharmony_ci 0xFFFFFFFF); 45162306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 45262306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wrot.iova[2]); 45362306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_BASE_ADDR_V, reg, 45462306a36Sopenharmony_ci 0xFFFFFFFF); 45562306a36Sopenharmony_ci /* Write frame related registers */ 45662306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 45762306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wrot.control); 45862306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_CTRL, reg, 45962306a36Sopenharmony_ci 0xF131510F); 46062306a36Sopenharmony_ci /* Write frame Y pitch */ 46162306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 46262306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wrot.stride[0]); 46362306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_STRIDE, reg, 46462306a36Sopenharmony_ci 0x0000FFFF); 46562306a36Sopenharmony_ci /* Write frame UV pitch */ 46662306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 46762306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wrot.stride[1]); 46862306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_STRIDE_C, reg, 46962306a36Sopenharmony_ci 0xFFFF); 47062306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 47162306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wrot.stride[2]); 47262306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_STRIDE_V, reg, 47362306a36Sopenharmony_ci 0xFFFF); 47462306a36Sopenharmony_ci /* Write matrix control */ 47562306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 47662306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wrot.mat_ctrl); 47762306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_MAT_CTRL, reg, 0xF3); 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci /* Set the fixed ALPHA as 0xFF */ 48062306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_DITHER, 0xFF000000, 48162306a36Sopenharmony_ci 0xFF000000); 48262306a36Sopenharmony_ci /* Set VIDO_EOL_SEL */ 48362306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_RSV_1, BIT(31), BIT(31)); 48462306a36Sopenharmony_ci /* Set VIDO_FIFO_TEST */ 48562306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 48662306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wrot.fifo_test); 48762306a36Sopenharmony_ci if (reg != 0) 48862306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_FIFO_TEST, 48962306a36Sopenharmony_ci reg, 0xFFF); 49062306a36Sopenharmony_ci /* Filter enable */ 49162306a36Sopenharmony_ci if (mdp_cfg && mdp_cfg->wrot_filter_constraint) { 49262306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 49362306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wrot.filter); 49462306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_MAIN_BUF_SIZE, 49562306a36Sopenharmony_ci reg, 0x77); 49662306a36Sopenharmony_ci } 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci return 0; 49962306a36Sopenharmony_ci} 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_cistatic int config_wrot_subfrm(struct mdp_comp_ctx *ctx, 50262306a36Sopenharmony_ci struct mdp_cmdq_cmd *cmd, u32 index) 50362306a36Sopenharmony_ci{ 50462306a36Sopenharmony_ci phys_addr_t base = ctx->comp->reg_base; 50562306a36Sopenharmony_ci u8 subsys_id = ctx->comp->subsys_id; 50662306a36Sopenharmony_ci u32 reg = 0; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci /* Write Y pixel offset */ 50962306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 51062306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].offset[0]); 51162306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_OFST_ADDR, 51262306a36Sopenharmony_ci reg, 0x0FFFFFFF); 51362306a36Sopenharmony_ci /* Write U pixel offset */ 51462306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 51562306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].offset[1]); 51662306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_OFST_ADDR_C, 51762306a36Sopenharmony_ci reg, 0x0FFFFFFF); 51862306a36Sopenharmony_ci /* Write V pixel offset */ 51962306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 52062306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].offset[2]); 52162306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_OFST_ADDR_V, 52262306a36Sopenharmony_ci reg, 0x0FFFFFFF); 52362306a36Sopenharmony_ci /* Write source size */ 52462306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 52562306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].src); 52662306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_IN_SIZE, reg, 52762306a36Sopenharmony_ci 0x1FFF1FFF); 52862306a36Sopenharmony_ci /* Write target size */ 52962306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 53062306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].clip); 53162306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_TAR_SIZE, reg, 53262306a36Sopenharmony_ci 0x1FFF1FFF); 53362306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 53462306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].clip_ofst); 53562306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_CROP_OFST, reg, 53662306a36Sopenharmony_ci 0x1FFF1FFF); 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 53962306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].main_buf); 54062306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_MAIN_BUF_SIZE, 54162306a36Sopenharmony_ci reg, 0x1FFF7F00); 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci /* Enable WROT */ 54462306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_ROT_EN, BIT(0), BIT(0)); 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci return 0; 54762306a36Sopenharmony_ci} 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_cistatic int wait_wrot_event(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd) 55062306a36Sopenharmony_ci{ 55162306a36Sopenharmony_ci const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx); 55262306a36Sopenharmony_ci struct device *dev = &ctx->comp->mdp_dev->pdev->dev; 55362306a36Sopenharmony_ci phys_addr_t base = ctx->comp->reg_base; 55462306a36Sopenharmony_ci u8 subsys_id = ctx->comp->subsys_id; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci if (ctx->comp->alias_id == 0) 55762306a36Sopenharmony_ci MM_REG_WAIT(cmd, ctx->comp->gce_event[MDP_GCE_EVENT_EOF]); 55862306a36Sopenharmony_ci else 55962306a36Sopenharmony_ci dev_err(dev, "Do not support WROT1_DONE event\n"); 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci if (mdp_cfg && mdp_cfg->wrot_filter_constraint) 56262306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_MAIN_BUF_SIZE, 0x0, 56362306a36Sopenharmony_ci 0x77); 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci /* Disable WROT */ 56662306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, VIDO_ROT_EN, 0x0, BIT(0)); 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci return 0; 56962306a36Sopenharmony_ci} 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_cistatic const struct mdp_comp_ops wrot_ops = { 57262306a36Sopenharmony_ci .get_comp_flag = get_comp_flag, 57362306a36Sopenharmony_ci .init_comp = init_wrot, 57462306a36Sopenharmony_ci .config_frame = config_wrot_frame, 57562306a36Sopenharmony_ci .config_subfrm = config_wrot_subfrm, 57662306a36Sopenharmony_ci .wait_comp_event = wait_wrot_event, 57762306a36Sopenharmony_ci}; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_cistatic int init_wdma(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd) 58062306a36Sopenharmony_ci{ 58162306a36Sopenharmony_ci phys_addr_t base = ctx->comp->reg_base; 58262306a36Sopenharmony_ci u8 subsys_id = ctx->comp->subsys_id; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci /* Reset WDMA */ 58562306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, WDMA_RST, BIT(0), BIT(0)); 58662306a36Sopenharmony_ci MM_REG_POLL(cmd, subsys_id, base, WDMA_FLOW_CTRL_DBG, BIT(0), BIT(0)); 58762306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, WDMA_RST, 0x0, BIT(0)); 58862306a36Sopenharmony_ci return 0; 58962306a36Sopenharmony_ci} 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_cistatic int config_wdma_frame(struct mdp_comp_ctx *ctx, 59262306a36Sopenharmony_ci struct mdp_cmdq_cmd *cmd, 59362306a36Sopenharmony_ci const struct v4l2_rect *compose) 59462306a36Sopenharmony_ci{ 59562306a36Sopenharmony_ci phys_addr_t base = ctx->comp->reg_base; 59662306a36Sopenharmony_ci u8 subsys_id = ctx->comp->subsys_id; 59762306a36Sopenharmony_ci u32 reg = 0; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, WDMA_BUF_CON2, 0x10101050, 60062306a36Sopenharmony_ci 0xFFFFFFFF); 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci /* Setup frame information */ 60362306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 60462306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wdma.wdma_cfg); 60562306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, WDMA_CFG, reg, 60662306a36Sopenharmony_ci 0x0F01B8F0); 60762306a36Sopenharmony_ci /* Setup frame base address */ 60862306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 60962306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wdma.iova[0]); 61062306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_ADDR, reg, 61162306a36Sopenharmony_ci 0xFFFFFFFF); 61262306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 61362306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wdma.iova[1]); 61462306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_U_ADDR, reg, 61562306a36Sopenharmony_ci 0xFFFFFFFF); 61662306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 61762306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wdma.iova[2]); 61862306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_V_ADDR, reg, 61962306a36Sopenharmony_ci 0xFFFFFFFF); 62062306a36Sopenharmony_ci /* Setup Y pitch */ 62162306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 62262306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wdma.w_in_byte); 62362306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_W_IN_BYTE, 62462306a36Sopenharmony_ci reg, 0x0000FFFF); 62562306a36Sopenharmony_ci /* Setup UV pitch */ 62662306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 62762306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wdma.uv_stride); 62862306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_UV_PITCH, 62962306a36Sopenharmony_ci reg, 0x0000FFFF); 63062306a36Sopenharmony_ci /* Set the fixed ALPHA as 0xFF */ 63162306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, WDMA_ALPHA, 0x800000FF, 63262306a36Sopenharmony_ci 0x800000FF); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci return 0; 63562306a36Sopenharmony_ci} 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_cistatic int config_wdma_subfrm(struct mdp_comp_ctx *ctx, 63862306a36Sopenharmony_ci struct mdp_cmdq_cmd *cmd, u32 index) 63962306a36Sopenharmony_ci{ 64062306a36Sopenharmony_ci phys_addr_t base = ctx->comp->reg_base; 64162306a36Sopenharmony_ci u8 subsys_id = ctx->comp->subsys_id; 64262306a36Sopenharmony_ci u32 reg = 0; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci /* Write Y pixel offset */ 64562306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 64662306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].offset[0]); 64762306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_ADDR_OFFSET, 64862306a36Sopenharmony_ci reg, 0x0FFFFFFF); 64962306a36Sopenharmony_ci /* Write U pixel offset */ 65062306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 65162306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].offset[1]); 65262306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_U_ADDR_OFFSET, 65362306a36Sopenharmony_ci reg, 0x0FFFFFFF); 65462306a36Sopenharmony_ci /* Write V pixel offset */ 65562306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 65662306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].offset[2]); 65762306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_V_ADDR_OFFSET, 65862306a36Sopenharmony_ci reg, 0x0FFFFFFF); 65962306a36Sopenharmony_ci /* Write source size */ 66062306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 66162306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].src); 66262306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, WDMA_SRC_SIZE, reg, 66362306a36Sopenharmony_ci 0x3FFF3FFF); 66462306a36Sopenharmony_ci /* Write target size */ 66562306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 66662306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].clip); 66762306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, WDMA_CLIP_SIZE, reg, 66862306a36Sopenharmony_ci 0x3FFF3FFF); 66962306a36Sopenharmony_ci /* Write clip offset */ 67062306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 67162306a36Sopenharmony_ci reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].clip_ofst); 67262306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, WDMA_CLIP_COORD, reg, 67362306a36Sopenharmony_ci 0x3FFF3FFF); 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci /* Enable WDMA */ 67662306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, WDMA_EN, BIT(0), BIT(0)); 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci return 0; 67962306a36Sopenharmony_ci} 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_cistatic int wait_wdma_event(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd) 68262306a36Sopenharmony_ci{ 68362306a36Sopenharmony_ci phys_addr_t base = ctx->comp->reg_base; 68462306a36Sopenharmony_ci u8 subsys_id = ctx->comp->subsys_id; 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci MM_REG_WAIT(cmd, ctx->comp->gce_event[MDP_GCE_EVENT_EOF]); 68762306a36Sopenharmony_ci /* Disable WDMA */ 68862306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, WDMA_EN, 0x0, BIT(0)); 68962306a36Sopenharmony_ci return 0; 69062306a36Sopenharmony_ci} 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_cistatic const struct mdp_comp_ops wdma_ops = { 69362306a36Sopenharmony_ci .get_comp_flag = get_comp_flag, 69462306a36Sopenharmony_ci .init_comp = init_wdma, 69562306a36Sopenharmony_ci .config_frame = config_wdma_frame, 69662306a36Sopenharmony_ci .config_subfrm = config_wdma_subfrm, 69762306a36Sopenharmony_ci .wait_comp_event = wait_wdma_event, 69862306a36Sopenharmony_ci}; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_cistatic int init_ccorr(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd) 70162306a36Sopenharmony_ci{ 70262306a36Sopenharmony_ci phys_addr_t base = ctx->comp->reg_base; 70362306a36Sopenharmony_ci u8 subsys_id = ctx->comp->subsys_id; 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci /* CCORR enable */ 70662306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_CCORR_EN, BIT(0), BIT(0)); 70762306a36Sopenharmony_ci /* Relay mode */ 70862306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_CCORR_CFG, BIT(0), BIT(0)); 70962306a36Sopenharmony_ci return 0; 71062306a36Sopenharmony_ci} 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_cistatic int config_ccorr_subfrm(struct mdp_comp_ctx *ctx, 71362306a36Sopenharmony_ci struct mdp_cmdq_cmd *cmd, u32 index) 71462306a36Sopenharmony_ci{ 71562306a36Sopenharmony_ci phys_addr_t base = ctx->comp->reg_base; 71662306a36Sopenharmony_ci u8 subsys_id = ctx->comp->subsys_id; 71762306a36Sopenharmony_ci u32 csf_l = 0, csf_r = 0; 71862306a36Sopenharmony_ci u32 csf_t = 0, csf_b = 0; 71962306a36Sopenharmony_ci u32 hsize, vsize; 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) { 72262306a36Sopenharmony_ci csf_l = CFG_COMP(MT8183, ctx->param, subfrms[index].in.left); 72362306a36Sopenharmony_ci csf_r = CFG_COMP(MT8183, ctx->param, subfrms[index].in.right); 72462306a36Sopenharmony_ci csf_t = CFG_COMP(MT8183, ctx->param, subfrms[index].in.top); 72562306a36Sopenharmony_ci csf_b = CFG_COMP(MT8183, ctx->param, subfrms[index].in.bottom); 72662306a36Sopenharmony_ci } 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci hsize = csf_r - csf_l + 1; 72962306a36Sopenharmony_ci vsize = csf_b - csf_t + 1; 73062306a36Sopenharmony_ci MM_REG_WRITE(cmd, subsys_id, base, MDP_CCORR_SIZE, 73162306a36Sopenharmony_ci (hsize << 16) + (vsize << 0), 0x1FFF1FFF); 73262306a36Sopenharmony_ci return 0; 73362306a36Sopenharmony_ci} 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_cistatic const struct mdp_comp_ops ccorr_ops = { 73662306a36Sopenharmony_ci .get_comp_flag = get_comp_flag, 73762306a36Sopenharmony_ci .init_comp = init_ccorr, 73862306a36Sopenharmony_ci .config_subfrm = config_ccorr_subfrm, 73962306a36Sopenharmony_ci}; 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_cistatic const struct mdp_comp_ops *mdp_comp_ops[MDP_COMP_TYPE_COUNT] = { 74262306a36Sopenharmony_ci [MDP_COMP_TYPE_RDMA] = &rdma_ops, 74362306a36Sopenharmony_ci [MDP_COMP_TYPE_RSZ] = &rsz_ops, 74462306a36Sopenharmony_ci [MDP_COMP_TYPE_WROT] = &wrot_ops, 74562306a36Sopenharmony_ci [MDP_COMP_TYPE_WDMA] = &wdma_ops, 74662306a36Sopenharmony_ci [MDP_COMP_TYPE_CCORR] = &ccorr_ops, 74762306a36Sopenharmony_ci}; 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_cistatic const struct of_device_id mdp_comp_dt_ids[] __maybe_unused = { 75062306a36Sopenharmony_ci { 75162306a36Sopenharmony_ci .compatible = "mediatek,mt8183-mdp3-rdma", 75262306a36Sopenharmony_ci .data = (void *)MDP_COMP_TYPE_RDMA, 75362306a36Sopenharmony_ci }, { 75462306a36Sopenharmony_ci .compatible = "mediatek,mt8183-mdp3-ccorr", 75562306a36Sopenharmony_ci .data = (void *)MDP_COMP_TYPE_CCORR, 75662306a36Sopenharmony_ci }, { 75762306a36Sopenharmony_ci .compatible = "mediatek,mt8183-mdp3-rsz", 75862306a36Sopenharmony_ci .data = (void *)MDP_COMP_TYPE_RSZ, 75962306a36Sopenharmony_ci }, { 76062306a36Sopenharmony_ci .compatible = "mediatek,mt8183-mdp3-wrot", 76162306a36Sopenharmony_ci .data = (void *)MDP_COMP_TYPE_WROT, 76262306a36Sopenharmony_ci }, { 76362306a36Sopenharmony_ci .compatible = "mediatek,mt8183-mdp3-wdma", 76462306a36Sopenharmony_ci .data = (void *)MDP_COMP_TYPE_WDMA, 76562306a36Sopenharmony_ci }, 76662306a36Sopenharmony_ci {} 76762306a36Sopenharmony_ci}; 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_cistatic inline bool is_dma_capable(const enum mdp_comp_type type) 77062306a36Sopenharmony_ci{ 77162306a36Sopenharmony_ci return (type == MDP_COMP_TYPE_RDMA || 77262306a36Sopenharmony_ci type == MDP_COMP_TYPE_WROT || 77362306a36Sopenharmony_ci type == MDP_COMP_TYPE_WDMA); 77462306a36Sopenharmony_ci} 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_cistatic inline bool is_bypass_gce_event(const enum mdp_comp_type type) 77762306a36Sopenharmony_ci{ 77862306a36Sopenharmony_ci /* 77962306a36Sopenharmony_ci * Subcomponent PATH is only used for the direction of data flow and 78062306a36Sopenharmony_ci * dose not need to wait for GCE event. 78162306a36Sopenharmony_ci */ 78262306a36Sopenharmony_ci return (type == MDP_COMP_TYPE_PATH); 78362306a36Sopenharmony_ci} 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_cistatic int mdp_comp_get_id(struct mdp_dev *mdp, enum mdp_comp_type type, u32 alias_id) 78662306a36Sopenharmony_ci{ 78762306a36Sopenharmony_ci int i; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci for (i = 0; i < mdp->mdp_data->comp_data_len; i++) 79062306a36Sopenharmony_ci if (mdp->mdp_data->comp_data[i].match.type == type && 79162306a36Sopenharmony_ci mdp->mdp_data->comp_data[i].match.alias_id == alias_id) 79262306a36Sopenharmony_ci return i; 79362306a36Sopenharmony_ci return -ENODEV; 79462306a36Sopenharmony_ci} 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ciint mdp_comp_clock_on(struct device *dev, struct mdp_comp *comp) 79762306a36Sopenharmony_ci{ 79862306a36Sopenharmony_ci int i, ret; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci /* Only DMA capable components need the pm control */ 80162306a36Sopenharmony_ci if (comp->comp_dev && is_dma_capable(comp->type)) { 80262306a36Sopenharmony_ci ret = pm_runtime_resume_and_get(comp->comp_dev); 80362306a36Sopenharmony_ci if (ret < 0) { 80462306a36Sopenharmony_ci dev_err(dev, 80562306a36Sopenharmony_ci "Failed to get power, err %d. type:%d id:%d\n", 80662306a36Sopenharmony_ci ret, comp->type, comp->inner_id); 80762306a36Sopenharmony_ci return ret; 80862306a36Sopenharmony_ci } 80962306a36Sopenharmony_ci } 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci for (i = 0; i < comp->clk_num; i++) { 81262306a36Sopenharmony_ci if (IS_ERR_OR_NULL(comp->clks[i])) 81362306a36Sopenharmony_ci continue; 81462306a36Sopenharmony_ci ret = clk_prepare_enable(comp->clks[i]); 81562306a36Sopenharmony_ci if (ret) { 81662306a36Sopenharmony_ci dev_err(dev, 81762306a36Sopenharmony_ci "Failed to enable clk %d. type:%d id:%d\n", 81862306a36Sopenharmony_ci i, comp->type, comp->inner_id); 81962306a36Sopenharmony_ci goto err_revert; 82062306a36Sopenharmony_ci } 82162306a36Sopenharmony_ci } 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci return 0; 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_cierr_revert: 82662306a36Sopenharmony_ci while (--i >= 0) { 82762306a36Sopenharmony_ci if (IS_ERR_OR_NULL(comp->clks[i])) 82862306a36Sopenharmony_ci continue; 82962306a36Sopenharmony_ci clk_disable_unprepare(comp->clks[i]); 83062306a36Sopenharmony_ci } 83162306a36Sopenharmony_ci if (comp->comp_dev && is_dma_capable(comp->type)) 83262306a36Sopenharmony_ci pm_runtime_put_sync(comp->comp_dev); 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci return ret; 83562306a36Sopenharmony_ci} 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_civoid mdp_comp_clock_off(struct device *dev, struct mdp_comp *comp) 83862306a36Sopenharmony_ci{ 83962306a36Sopenharmony_ci int i; 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci for (i = 0; i < comp->clk_num; i++) { 84262306a36Sopenharmony_ci if (IS_ERR_OR_NULL(comp->clks[i])) 84362306a36Sopenharmony_ci continue; 84462306a36Sopenharmony_ci clk_disable_unprepare(comp->clks[i]); 84562306a36Sopenharmony_ci } 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci if (comp->comp_dev && is_dma_capable(comp->type)) 84862306a36Sopenharmony_ci pm_runtime_put(comp->comp_dev); 84962306a36Sopenharmony_ci} 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ciint mdp_comp_clocks_on(struct device *dev, struct mdp_comp *comps, int num) 85262306a36Sopenharmony_ci{ 85362306a36Sopenharmony_ci int i, ret; 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci for (i = 0; i < num; i++) { 85662306a36Sopenharmony_ci ret = mdp_comp_clock_on(dev, &comps[i]); 85762306a36Sopenharmony_ci if (ret) 85862306a36Sopenharmony_ci return ret; 85962306a36Sopenharmony_ci } 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci return 0; 86262306a36Sopenharmony_ci} 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_civoid mdp_comp_clocks_off(struct device *dev, struct mdp_comp *comps, int num) 86562306a36Sopenharmony_ci{ 86662306a36Sopenharmony_ci int i; 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci for (i = 0; i < num; i++) 86962306a36Sopenharmony_ci mdp_comp_clock_off(dev, &comps[i]); 87062306a36Sopenharmony_ci} 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_cistatic int mdp_get_subsys_id(struct mdp_dev *mdp, struct device *dev, 87362306a36Sopenharmony_ci struct device_node *node, struct mdp_comp *comp) 87462306a36Sopenharmony_ci{ 87562306a36Sopenharmony_ci struct platform_device *comp_pdev; 87662306a36Sopenharmony_ci struct cmdq_client_reg cmdq_reg; 87762306a36Sopenharmony_ci int ret = 0; 87862306a36Sopenharmony_ci int index = 0; 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci if (!dev || !node || !comp) 88162306a36Sopenharmony_ci return -EINVAL; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci comp_pdev = of_find_device_by_node(node); 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci if (!comp_pdev) { 88662306a36Sopenharmony_ci dev_err(dev, "get comp_pdev fail! comp public id=%d, inner id=%d, type=%d\n", 88762306a36Sopenharmony_ci comp->public_id, comp->inner_id, comp->type); 88862306a36Sopenharmony_ci return -ENODEV; 88962306a36Sopenharmony_ci } 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci index = mdp->mdp_data->comp_data[comp->public_id].info.dts_reg_ofst; 89262306a36Sopenharmony_ci ret = cmdq_dev_get_client_reg(&comp_pdev->dev, &cmdq_reg, index); 89362306a36Sopenharmony_ci if (ret != 0) { 89462306a36Sopenharmony_ci dev_err(&comp_pdev->dev, "cmdq_dev_get_subsys fail!\n"); 89562306a36Sopenharmony_ci put_device(&comp_pdev->dev); 89662306a36Sopenharmony_ci return -EINVAL; 89762306a36Sopenharmony_ci } 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci comp->subsys_id = cmdq_reg.subsys; 90062306a36Sopenharmony_ci dev_dbg(&comp_pdev->dev, "subsys id=%d\n", cmdq_reg.subsys); 90162306a36Sopenharmony_ci put_device(&comp_pdev->dev); 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci return 0; 90462306a36Sopenharmony_ci} 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_cistatic void __mdp_comp_init(struct mdp_dev *mdp, struct device_node *node, 90762306a36Sopenharmony_ci struct mdp_comp *comp) 90862306a36Sopenharmony_ci{ 90962306a36Sopenharmony_ci struct resource res; 91062306a36Sopenharmony_ci phys_addr_t base; 91162306a36Sopenharmony_ci int index; 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci index = mdp->mdp_data->comp_data[comp->public_id].info.dts_reg_ofst; 91462306a36Sopenharmony_ci if (of_address_to_resource(node, index, &res) < 0) 91562306a36Sopenharmony_ci base = 0L; 91662306a36Sopenharmony_ci else 91762306a36Sopenharmony_ci base = res.start; 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci comp->mdp_dev = mdp; 92062306a36Sopenharmony_ci comp->regs = of_iomap(node, 0); 92162306a36Sopenharmony_ci comp->reg_base = base; 92262306a36Sopenharmony_ci} 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_cistatic int mdp_comp_init(struct mdp_dev *mdp, struct device_node *node, 92562306a36Sopenharmony_ci struct mdp_comp *comp, enum mtk_mdp_comp_id id) 92662306a36Sopenharmony_ci{ 92762306a36Sopenharmony_ci struct device *dev = &mdp->pdev->dev; 92862306a36Sopenharmony_ci struct platform_device *pdev_c; 92962306a36Sopenharmony_ci int clk_ofst; 93062306a36Sopenharmony_ci int i; 93162306a36Sopenharmony_ci s32 event; 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci if (id < 0 || id >= MDP_MAX_COMP_COUNT) { 93462306a36Sopenharmony_ci dev_err(dev, "Invalid component id %d\n", id); 93562306a36Sopenharmony_ci return -EINVAL; 93662306a36Sopenharmony_ci } 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_ci pdev_c = of_find_device_by_node(node); 93962306a36Sopenharmony_ci if (!pdev_c) { 94062306a36Sopenharmony_ci dev_warn(dev, "can't find platform device of node:%s\n", 94162306a36Sopenharmony_ci node->name); 94262306a36Sopenharmony_ci return -ENODEV; 94362306a36Sopenharmony_ci } 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci comp->comp_dev = &pdev_c->dev; 94662306a36Sopenharmony_ci comp->public_id = id; 94762306a36Sopenharmony_ci comp->type = mdp->mdp_data->comp_data[id].match.type; 94862306a36Sopenharmony_ci comp->inner_id = mdp->mdp_data->comp_data[id].match.inner_id; 94962306a36Sopenharmony_ci comp->alias_id = mdp->mdp_data->comp_data[id].match.alias_id; 95062306a36Sopenharmony_ci comp->ops = mdp_comp_ops[comp->type]; 95162306a36Sopenharmony_ci __mdp_comp_init(mdp, node, comp); 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_ci comp->clk_num = mdp->mdp_data->comp_data[id].info.clk_num; 95462306a36Sopenharmony_ci comp->clks = devm_kzalloc(dev, sizeof(struct clk *) * comp->clk_num, 95562306a36Sopenharmony_ci GFP_KERNEL); 95662306a36Sopenharmony_ci if (!comp->clks) 95762306a36Sopenharmony_ci return -ENOMEM; 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci clk_ofst = mdp->mdp_data->comp_data[id].info.clk_ofst; 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci for (i = 0; i < comp->clk_num; i++) { 96262306a36Sopenharmony_ci comp->clks[i] = of_clk_get(node, i + clk_ofst); 96362306a36Sopenharmony_ci if (IS_ERR(comp->clks[i])) 96462306a36Sopenharmony_ci break; 96562306a36Sopenharmony_ci } 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci mdp_get_subsys_id(mdp, dev, node, comp); 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci /* Set GCE SOF event */ 97062306a36Sopenharmony_ci if (is_bypass_gce_event(comp->type) || 97162306a36Sopenharmony_ci of_property_read_u32_index(node, "mediatek,gce-events", 97262306a36Sopenharmony_ci MDP_GCE_EVENT_SOF, &event)) 97362306a36Sopenharmony_ci event = MDP_GCE_NO_EVENT; 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci comp->gce_event[MDP_GCE_EVENT_SOF] = event; 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci /* Set GCE EOF event */ 97862306a36Sopenharmony_ci if (is_dma_capable(comp->type)) { 97962306a36Sopenharmony_ci if (of_property_read_u32_index(node, "mediatek,gce-events", 98062306a36Sopenharmony_ci MDP_GCE_EVENT_EOF, &event)) { 98162306a36Sopenharmony_ci dev_err(dev, "Component id %d has no EOF\n", id); 98262306a36Sopenharmony_ci return -EINVAL; 98362306a36Sopenharmony_ci } 98462306a36Sopenharmony_ci } else { 98562306a36Sopenharmony_ci event = MDP_GCE_NO_EVENT; 98662306a36Sopenharmony_ci } 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci comp->gce_event[MDP_GCE_EVENT_EOF] = event; 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci return 0; 99162306a36Sopenharmony_ci} 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_cistatic void mdp_comp_deinit(struct mdp_comp *comp) 99462306a36Sopenharmony_ci{ 99562306a36Sopenharmony_ci if (!comp) 99662306a36Sopenharmony_ci return; 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci if (comp->comp_dev && comp->clks) { 99962306a36Sopenharmony_ci devm_kfree(&comp->mdp_dev->pdev->dev, comp->clks); 100062306a36Sopenharmony_ci comp->clks = NULL; 100162306a36Sopenharmony_ci } 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_ci if (comp->regs) 100462306a36Sopenharmony_ci iounmap(comp->regs); 100562306a36Sopenharmony_ci} 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_cistatic struct mdp_comp *mdp_comp_create(struct mdp_dev *mdp, 100862306a36Sopenharmony_ci struct device_node *node, 100962306a36Sopenharmony_ci enum mtk_mdp_comp_id id) 101062306a36Sopenharmony_ci{ 101162306a36Sopenharmony_ci struct device *dev = &mdp->pdev->dev; 101262306a36Sopenharmony_ci struct mdp_comp *comp; 101362306a36Sopenharmony_ci int ret; 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci if (mdp->comp[id]) 101662306a36Sopenharmony_ci return ERR_PTR(-EEXIST); 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL); 101962306a36Sopenharmony_ci if (!comp) 102062306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci ret = mdp_comp_init(mdp, node, comp, id); 102362306a36Sopenharmony_ci if (ret) { 102462306a36Sopenharmony_ci devm_kfree(dev, comp); 102562306a36Sopenharmony_ci return ERR_PTR(ret); 102662306a36Sopenharmony_ci } 102762306a36Sopenharmony_ci mdp->comp[id] = comp; 102862306a36Sopenharmony_ci mdp->comp[id]->mdp_dev = mdp; 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci dev_dbg(dev, "%s type:%d alias:%d public id:%d inner id:%d base:%#x regs:%p\n", 103162306a36Sopenharmony_ci dev->of_node->name, comp->type, comp->alias_id, id, comp->inner_id, 103262306a36Sopenharmony_ci (u32)comp->reg_base, comp->regs); 103362306a36Sopenharmony_ci return comp; 103462306a36Sopenharmony_ci} 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_cistatic int mdp_comp_sub_create(struct mdp_dev *mdp) 103762306a36Sopenharmony_ci{ 103862306a36Sopenharmony_ci struct device *dev = &mdp->pdev->dev; 103962306a36Sopenharmony_ci struct device_node *node, *parent; 104062306a36Sopenharmony_ci int ret = 0; 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci parent = dev->of_node->parent; 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci for_each_child_of_node(parent, node) { 104562306a36Sopenharmony_ci const struct of_device_id *of_id; 104662306a36Sopenharmony_ci enum mdp_comp_type type; 104762306a36Sopenharmony_ci int id, alias_id; 104862306a36Sopenharmony_ci struct mdp_comp *comp; 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci of_id = of_match_node(mdp->mdp_data->mdp_sub_comp_dt_ids, node); 105162306a36Sopenharmony_ci if (!of_id) 105262306a36Sopenharmony_ci continue; 105362306a36Sopenharmony_ci if (!of_device_is_available(node)) { 105462306a36Sopenharmony_ci dev_dbg(dev, "Skipping disabled sub comp. %pOF\n", 105562306a36Sopenharmony_ci node); 105662306a36Sopenharmony_ci continue; 105762306a36Sopenharmony_ci } 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci type = (enum mdp_comp_type)(uintptr_t)of_id->data; 106062306a36Sopenharmony_ci alias_id = mdp_comp_alias_id[type]; 106162306a36Sopenharmony_ci id = mdp_comp_get_id(mdp, type, alias_id); 106262306a36Sopenharmony_ci if (id < 0) { 106362306a36Sopenharmony_ci dev_err(dev, 106462306a36Sopenharmony_ci "Fail to get sub comp. id: type %d alias %d\n", 106562306a36Sopenharmony_ci type, alias_id); 106662306a36Sopenharmony_ci ret = -EINVAL; 106762306a36Sopenharmony_ci goto err_free_node; 106862306a36Sopenharmony_ci } 106962306a36Sopenharmony_ci mdp_comp_alias_id[type]++; 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci comp = mdp_comp_create(mdp, node, id); 107262306a36Sopenharmony_ci if (IS_ERR(comp)) { 107362306a36Sopenharmony_ci ret = PTR_ERR(comp); 107462306a36Sopenharmony_ci goto err_free_node; 107562306a36Sopenharmony_ci } 107662306a36Sopenharmony_ci } 107762306a36Sopenharmony_ci return ret; 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_cierr_free_node: 108062306a36Sopenharmony_ci of_node_put(node); 108162306a36Sopenharmony_ci return ret; 108262306a36Sopenharmony_ci} 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_civoid mdp_comp_destroy(struct mdp_dev *mdp) 108562306a36Sopenharmony_ci{ 108662306a36Sopenharmony_ci int i; 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mdp->comp); i++) { 108962306a36Sopenharmony_ci if (mdp->comp[i]) { 109062306a36Sopenharmony_ci if (is_dma_capable(mdp->comp[i]->type)) 109162306a36Sopenharmony_ci pm_runtime_disable(mdp->comp[i]->comp_dev); 109262306a36Sopenharmony_ci mdp_comp_deinit(mdp->comp[i]); 109362306a36Sopenharmony_ci devm_kfree(mdp->comp[i]->comp_dev, mdp->comp[i]); 109462306a36Sopenharmony_ci mdp->comp[i] = NULL; 109562306a36Sopenharmony_ci } 109662306a36Sopenharmony_ci } 109762306a36Sopenharmony_ci} 109862306a36Sopenharmony_ci 109962306a36Sopenharmony_ciint mdp_comp_config(struct mdp_dev *mdp) 110062306a36Sopenharmony_ci{ 110162306a36Sopenharmony_ci struct device *dev = &mdp->pdev->dev; 110262306a36Sopenharmony_ci struct device_node *node, *parent; 110362306a36Sopenharmony_ci int ret; 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci memset(mdp_comp_alias_id, 0, sizeof(mdp_comp_alias_id)); 110662306a36Sopenharmony_ci p_id = mdp->mdp_data->mdp_plat_id; 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci parent = dev->of_node->parent; 110962306a36Sopenharmony_ci /* Iterate over sibling MDP function blocks */ 111062306a36Sopenharmony_ci for_each_child_of_node(parent, node) { 111162306a36Sopenharmony_ci const struct of_device_id *of_id; 111262306a36Sopenharmony_ci enum mdp_comp_type type; 111362306a36Sopenharmony_ci int id, alias_id; 111462306a36Sopenharmony_ci struct mdp_comp *comp; 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci of_id = of_match_node(mdp_comp_dt_ids, node); 111762306a36Sopenharmony_ci if (!of_id) 111862306a36Sopenharmony_ci continue; 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci if (!of_device_is_available(node)) { 112162306a36Sopenharmony_ci dev_dbg(dev, "Skipping disabled component %pOF\n", 112262306a36Sopenharmony_ci node); 112362306a36Sopenharmony_ci continue; 112462306a36Sopenharmony_ci } 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci type = (enum mdp_comp_type)(uintptr_t)of_id->data; 112762306a36Sopenharmony_ci alias_id = mdp_comp_alias_id[type]; 112862306a36Sopenharmony_ci id = mdp_comp_get_id(mdp, type, alias_id); 112962306a36Sopenharmony_ci if (id < 0) { 113062306a36Sopenharmony_ci dev_err(dev, 113162306a36Sopenharmony_ci "Fail to get component id: type %d alias %d\n", 113262306a36Sopenharmony_ci type, alias_id); 113362306a36Sopenharmony_ci continue; 113462306a36Sopenharmony_ci } 113562306a36Sopenharmony_ci mdp_comp_alias_id[type]++; 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci comp = mdp_comp_create(mdp, node, id); 113862306a36Sopenharmony_ci if (IS_ERR(comp)) { 113962306a36Sopenharmony_ci ret = PTR_ERR(comp); 114062306a36Sopenharmony_ci goto err_init_comps; 114162306a36Sopenharmony_ci } 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_ci /* Only DMA capable components need the pm control */ 114462306a36Sopenharmony_ci if (!is_dma_capable(comp->type)) 114562306a36Sopenharmony_ci continue; 114662306a36Sopenharmony_ci pm_runtime_enable(comp->comp_dev); 114762306a36Sopenharmony_ci } 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ci ret = mdp_comp_sub_create(mdp); 115062306a36Sopenharmony_ci if (ret) 115162306a36Sopenharmony_ci goto err_init_comps; 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_ci return 0; 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_cierr_init_comps: 115662306a36Sopenharmony_ci mdp_comp_destroy(mdp); 115762306a36Sopenharmony_ci return ret; 115862306a36Sopenharmony_ci} 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_ciint mdp_comp_ctx_config(struct mdp_dev *mdp, struct mdp_comp_ctx *ctx, 116162306a36Sopenharmony_ci const struct img_compparam *param, 116262306a36Sopenharmony_ci const struct img_ipi_frameparam *frame) 116362306a36Sopenharmony_ci{ 116462306a36Sopenharmony_ci struct device *dev = &mdp->pdev->dev; 116562306a36Sopenharmony_ci enum mtk_mdp_comp_id public_id = MDP_COMP_NONE; 116662306a36Sopenharmony_ci u32 arg; 116762306a36Sopenharmony_ci int i, idx; 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci if (!param) { 117062306a36Sopenharmony_ci dev_err(dev, "Invalid component param"); 117162306a36Sopenharmony_ci return -EINVAL; 117262306a36Sopenharmony_ci } 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 117562306a36Sopenharmony_ci arg = CFG_COMP(MT8183, param, type); 117662306a36Sopenharmony_ci else 117762306a36Sopenharmony_ci return -EINVAL; 117862306a36Sopenharmony_ci public_id = mdp_cfg_get_id_public(mdp, arg); 117962306a36Sopenharmony_ci if (public_id < 0) { 118062306a36Sopenharmony_ci dev_err(dev, "Invalid component id %d", public_id); 118162306a36Sopenharmony_ci return -EINVAL; 118262306a36Sopenharmony_ci } 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_ci ctx->comp = mdp->comp[public_id]; 118562306a36Sopenharmony_ci if (!ctx->comp) { 118662306a36Sopenharmony_ci dev_err(dev, "Uninit component inner id %d", arg); 118762306a36Sopenharmony_ci return -EINVAL; 118862306a36Sopenharmony_ci } 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_ci ctx->param = param; 119162306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 119262306a36Sopenharmony_ci arg = CFG_COMP(MT8183, param, input); 119362306a36Sopenharmony_ci else 119462306a36Sopenharmony_ci return -EINVAL; 119562306a36Sopenharmony_ci ctx->input = &frame->inputs[arg]; 119662306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 119762306a36Sopenharmony_ci idx = CFG_COMP(MT8183, param, num_outputs); 119862306a36Sopenharmony_ci else 119962306a36Sopenharmony_ci return -EINVAL; 120062306a36Sopenharmony_ci for (i = 0; i < idx; i++) { 120162306a36Sopenharmony_ci if (CFG_CHECK(MT8183, p_id)) 120262306a36Sopenharmony_ci arg = CFG_COMP(MT8183, param, outputs[i]); 120362306a36Sopenharmony_ci else 120462306a36Sopenharmony_ci return -EINVAL; 120562306a36Sopenharmony_ci ctx->outputs[i] = &frame->outputs[arg]; 120662306a36Sopenharmony_ci } 120762306a36Sopenharmony_ci return 0; 120862306a36Sopenharmony_ci} 1209