blob: ab6fde9403363cdd9055f242b26f593bfb542b4f [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018 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-comp.h"
#include "mtk-mdp3-core.h"
#include "mtk-mdp3-regs.h"
#include "mdp-platform.h"
#include "mmsys_config.h"
#include "mdp_reg_rdma.h"
#include "mdp_reg_rsz.h"
#include "mdp_reg_wrot.h"
#include "mdp_reg_aal.h"
#include "mdp_reg_tdshp.h"
#include "mdp_reg_color.h"
#include "mdp_reg_hdr.h"
#include "isp_reg.h"
static s64 get_comp_flag(const struct mdp_comp_ctx *ctx)
{
#if RDMA0_RSZ1_SRAM_SHARING
if (ctx->comp->id == MDP_RDMA0)
return (1 << MDP_RDMA0) | (1 << MDP_SCL1);
#endif
return 1 << ctx->comp->id;
}
static int init_rdma(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd)
{
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
#if RDMA0_RSZ1_SRAM_SHARING
struct mdp_comp *prz1 = ctx->comp->mdp_dev->comp[MDP_SCL1];
/* Disable RSZ1 */
if (ctx->comp->id == MDP_RDMA0 && prz1)
MM_REG_WRITE_S(cmd, subsys_id, prz1->reg_base, PRZ_ENABLE,
0x00000000, 0x00000001);
#endif
/* Reset RDMA */
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_RESET, 0x00000001,
0x00000001);
MM_REG_POLL_S(cmd, subsys_id, base, MDP_RDMA_MON_STA_1, 0x00600100,
0x00600100);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_RESET, 0x00000000,
0x00000001);
return 0;
}
static int config_rdma_frame(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd,
const struct v4l2_rect *compose)
{
const struct mdp_rdma_data *rdma = &ctx->param->rdma;
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;
u16 subsys_id = ctx->comp->subsys_id;
#if RDMA_SUPPORT_10BIT
if (block10bit)
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_RESV_DUMMY_0,
0x00000007, 0x00000007);
else
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_RESV_DUMMY_0,
0x00000000, 0x00000007);
#endif
/* Setup smi control */
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_GMCIF_CON,
(1 << 0) +
(7 << 4) + //burst type to 8
(1 << 16), //enable pre-ultra
0x00030071);
/* Setup source frame info */
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_SRC_CON, rdma->src_ctrl,
0x03C8FE0F);
#if RDMA_SUPPORT_10BIT
if (en_ufo) {
/* Setup source buffer base */
MM_REG_WRITE_S(cmd, subsys_id,
base, MDP_RDMA_UFO_DEC_LENGTH_BASE_Y,
rdma->ufo_dec_y, 0xFFFFFFFF);
MM_REG_WRITE_S(cmd, subsys_id,
base, MDP_RDMA_UFO_DEC_LENGTH_BASE_C,
rdma->ufo_dec_c, 0xFFFFFFFF);
/* Set 10bit source frame pitch */
if (block10bit)
MM_REG_WRITE_S(cmd, subsys_id,
base, MDP_RDMA_MF_BKGD_SIZE_IN_PXL,
rdma->mf_bkgd_in_pxl, 0x001FFFFF);
}
#endif
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_CON, rdma->control,
0x00001110);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_COMP_CON, rdma->comp_ctrl,
rdma->comp_ctrl);
/* Setup source buffer base */
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_0, rdma->iova[0],
0xFFFFFFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_1, rdma->iova[1],
0xFFFFFFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_2, rdma->iova[2],
0xFFFFFFFF);
/* Setup source buffer end */
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_SRC_END_0,
rdma->iova_end[0], 0xFFFFFFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_SRC_END_1,
rdma->iova_end[1], 0xFFFFFFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_SRC_END_2,
rdma->iova_end[2], 0xFFFFFFFF);
/* Setup source frame pitch */
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_MF_BKGD_SIZE_IN_BYTE,
rdma->mf_bkgd, 0x001FFFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_SF_BKGD_SIZE_IN_BYTE,
rdma->sf_bkgd, 0x001FFFFF);
/* Setup color transform */
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_TRANSFORM_0,
rdma->transform, 0x0F110000);
return 0;
}
static int config_rdma_subfrm(struct mdp_comp_ctx *ctx,
struct mdp_cmd *cmd, u32 index)
{
const struct mdp_rdma_subfrm *subfrm = &ctx->param->rdma.subfrms[index];
const struct img_comp_subfrm *csf = &ctx->param->subfrms[index];
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;
u16 subsys_id = ctx->comp->subsys_id;
/* Enable RDMA */
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_EN, 0x00000001,
0x00000001);
/* Set Y pixel offset */
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_0,
subfrm->offset[0], 0xFFFFFFFF);
#if RDMA_SUPPORT_10BIT
/* Set 10bit UFO mode */
if (block10bit && en_ufo)
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_0_P,
subfrm->offset_0_p, 0xFFFFFFFF);
#endif
/* Set U pixel offset */
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_1,
subfrm->offset[1], 0xFFFFFFFF);
/* Set V pixel offset */
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_2,
subfrm->offset[2], 0xFFFFFFFF);
/* Set source size */
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_MF_SRC_SIZE, subfrm->src,
0x1FFF1FFF);
/* Set target size */
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_MF_CLIP_SIZE,
subfrm->clip, 0x1FFF1FFF);
/* Set crop offset */
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_MF_OFFSET_1,
subfrm->clip_ofst, 0x003F001F);
#if RDMA_UPSAMPLE_REPEAT_ONLY
if ((csf->in.right - csf->in.left + 1) > 320)
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_RESV_DUMMY_0,
0x00000004, 0x00000004);
#endif
return 0;
}
static int wait_rdma_event(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd)
{
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
if (ctx->comp->alias_id == 0)
MM_REG_WAIT(cmd, RDMA0_FRAME_DONE);
else if (ctx->comp->alias_id == 1)
MM_REG_WAIT(cmd, RDMA1_FRAME_DONE);
else
pr_err("Do not support RDMA%d_DONE event\n", ctx->comp->alias_id);
/* Disable RDMA */
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_RDMA_EN, 0x00000000,
0x00000001);
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,
/* .reconfig_frame = reconfig_rdma_frame, */
/* .reconfig_subfrms = reconfig_rdma_subfrms, */
.wait_comp_event = wait_rdma_event,
.advance_subfrm = NULL,
.post_process = NULL,
};
static int init_rsz(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd)
{
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
/* Reset RSZ */
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_ENABLE, 0x00010000,
0x00010000);
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_ENABLE, 0x00000000,
0x00010000);
/* Enable RSZ */
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_ENABLE, 0x00000001,
0x00000001);
return 0;
}
static int config_rsz_frame(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd,
const struct v4l2_rect *compose)
{
const struct mdp_rsz_data *rsz = &ctx->param->rsz;
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
#ifdef RSZ_ETC_CONTROL
MM_REG_WRITE_S(cmd, subsys_id, base, RSZ_ETC_CONTROL, 0,
0xFFFFFFFF);
#endif
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_CONTROL_1, rsz->control1,
0x03FFFDF3);
if (ctx->param->frame.bypass) {
/* Disable RSZ */
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_ENABLE, 0x00000000,
0x00000001);
return 0;
}
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_CONTROL_1, rsz->control1,
0x07FF01F3);
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_CONTROL_2, rsz->control2,
0x0FFFC290);
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_HORIZONTAL_COEFF_STEP,
rsz->coeff_step_x, 0x007FFFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_VERTICAL_COEFF_STEP,
rsz->coeff_step_y, 0x007FFFFF);
return 0;
}
static int config_rsz_subfrm(struct mdp_comp_ctx *ctx,
struct mdp_cmd *cmd, u32 index)
{
const struct mdp_rsz_subfrm *subfrm = &ctx->param->rsz.subfrms[index];
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_CONTROL_2, subfrm->control2,
0x00003800);
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_INPUT_IMAGE, subfrm->src,
0xFFFFFFFF);
#if RSZ_DISABLE_DCM_SMALL_TILE
if ((csf->in.right - csf->in.left + 1) <= 16)
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_CONTROL_1, 1 << 27,
1 << 27);
#endif
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_LUMA_HORIZONTAL_INTEGER_OFFSET,
subfrm->luma_h_int_ofst, 0x0000FFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_LUMA_HORIZONTAL_SUBPIXEL_OFFSET,
subfrm->luma_h_sub_ofst, 0x001FFFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_LUMA_VERTICAL_INTEGER_OFFSET,
subfrm->luma_v_int_ofst, 0x0000FFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_LUMA_VERTICAL_SUBPIXEL_OFFSET,
subfrm->luma_v_int_ofst, 0x001FFFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_CHROMA_HORIZONTAL_INTEGER_OFFSET,
subfrm->chroma_h_int_ofst, 0x001FFFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_CHROMA_HORIZONTAL_SUBPIXEL_OFFSET,
subfrm->chroma_h_sub_ofst, 0x001FFFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_OUTPUT_IMAGE, subfrm->clip,
0xFFFFFFFF);
return 0;
}
static int advance_rsz_subfrm(struct mdp_comp_ctx *ctx,
struct mdp_cmd *cmd, u32 index)
{
#if RSZ_DISABLE_DCM_SMALL_TILE
const struct img_comp_subfrm *csf = &ctx->param->subfrms[index];
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
if ((csf->in.right - csf->in.left + 1) <= 16)
MM_REG_WRITE_S(cmd, subsys_id, base, PRZ_CONTROL_1, 0, 1 << 27);
#endif
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,
/* .reconfig_frame = NULL, */
/* .reconfig_subfrms = NULL, */
.wait_comp_event = NULL,
.advance_subfrm = advance_rsz_subfrm,
.post_process = NULL,
};
static int init_aal(struct mdp_comp_ctx *ctx, struct mdp_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_S(cmd, subsys_id, base, MDP_AAL_EN, 0x1, 0x1);
return 0;
}
static int config_aal_frame(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd,
const struct v4l2_rect *compose)
{
const struct mdp_aal_data *aal = &ctx->param->aal;
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_AAL_CFG, 0x1, 0x1);
/* 10 bit format */
if (aal->format10bits)
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_AAL_CFG_MAIN, 0 << 7, 0x80);
else
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_AAL_CFG_MAIN, 1 << 7, 0x80);
return 0;
}
static int config_aal_subfrm(struct mdp_comp_ctx *ctx,
struct mdp_cmd *cmd, u32 index)
{
const struct mdp_aal_subfrm *subfrm = &ctx->param->aal.subfrms[index];
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_AAL_SIZE,
subfrm->src, 0xFFFFFFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_AAL_OUTPUT_OFFSET,
subfrm->clip_ofst, 0x00FF00FF);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_AAL_OUTPUT_SIZE,
subfrm->clip, 0xFFFFFFFF);
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,
/* .reconfig_frame = NULL, */
/* .reconfig_subfrms = NULL, */
.wait_comp_event = NULL,
.advance_subfrm = NULL,
.post_process = NULL,
};
static int init_hdr(struct mdp_comp_ctx *ctx, struct mdp_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_S(cmd, subsys_id, base, MDP_HDR_TOP, 1, 0x1);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_HDR_RELAY, 1, 0x1);
return 0;
}
static int config_hdr_subfrm(struct mdp_comp_ctx *ctx,
struct mdp_cmd *cmd, u32 index)
{
const struct mdp_hdr_subfrm *subfrm = &ctx->param->hdr.subfrms[index];
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_HDR_TILE_POS,
subfrm->win_size, MDP_HDR_TILE_POS_MASK);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_HDR_SIZE_0,
subfrm->src, 0x1FFF1FFF);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_HDR_SIZE_1,
subfrm->clip_ofst0, 0x1FFF1FFF);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_HDR_SIZE_2,
subfrm->clip_ofst1, 0x1FFF1FFF);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_HDR_HIST_CTRL_0,
subfrm->hist_ctrl_0, 0x00001FFF);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_HDR_HIST_CTRL_1,
subfrm->hist_ctrl_1, 0x00001FFF);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_HDR_TOP,
subfrm->hdr_top, 0x00000060);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_HDR_HIST_ADDR,
subfrm->hist_addr, 0x00000200);
return 0;
}
static const struct mdp_comp_ops hdr_ops = {
.get_comp_flag = get_comp_flag,
.init_comp = init_hdr,
.config_frame = NULL,
.config_subfrm = config_hdr_subfrm,
/* .reconfig_frame = NULL, */
/* .reconfig_subfrms = NULL, */
.wait_comp_event = NULL,
.advance_subfrm = NULL,
.post_process = NULL,
};
static int init_tdshp(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd)
{
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_TDSHP_CTRL, 0x00000001,
0x00000001);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_HFG_CTRL, 0x00000000,
0x00000303);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_TDSHP_CFG, 0x00000001,
0x00000001);
return 0;
}
static int config_tdshp_subfrm(struct mdp_comp_ctx *ctx,
struct mdp_cmd *cmd, u32 index)
{
const struct mdp_tdshp_subfrm *subfrm = &ctx->param->tdshp.subfrms[index];
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_TDSHP_INPUT_SIZE,
subfrm->src, 0xFFFFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_TDSHP_OUTPUT_OFFSET,
subfrm->clip_ofst, 0xFFFFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_TDSHP_OUTPUT_SIZE,
subfrm->clip, 0xFFFFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_HIST_CFG_00,
subfrm->hist_cfg_0, 0xFFFFFFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_HIST_CFG_00,
subfrm->hist_cfg_1, 0xFFFFFFFF);
return 0;
}
static const struct mdp_comp_ops tdshp_ops = {
.get_comp_flag = get_comp_flag,
.init_comp = init_tdshp,
.config_frame = NULL,
.config_subfrm = config_tdshp_subfrm,
/* .reconfig_frame = NULL, */
/* .reconfig_subfrms = NULL, */
.wait_comp_event = NULL,
.advance_subfrm = NULL,
.post_process = NULL,
};
static int init_color(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd)
{
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
MM_REG_WRITE_S(cmd, subsys_id, base, DISP_COLOR_START, 0x3, 0x3);
MM_REG_WRITE_S(cmd, subsys_id, base, DISP_COLOR_CFG_MAIN, 0x7, 0x7);
MM_REG_WRITE_S(cmd, subsys_id, base, DISP_COLOR_CM1_EN, 0x0, 0x1);
MM_REG_WRITE_S(cmd, subsys_id, base, DISP_COLOR_CM2_EN, 0x0, 0x1);
return 0;
}
static int config_color_subfrm(struct mdp_comp_ctx *ctx,
struct mdp_cmd *cmd, u32 index)
{
const struct mdp_color_subfrm *subfrm = &ctx->param->color.subfrms[index];
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
MM_REG_WRITE_S(cmd, subsys_id, base, DISP_COLOR_INTERNAL_IP_WIDTH,
subfrm->src>>16, 0x3FFF);
MM_REG_WRITE_S(cmd, subsys_id, base, DISP_COLOR_INTERNAL_IP_HEIGHT,
subfrm->src&0xFFFF, 0x3FFF);
return 0;
}
static const struct mdp_comp_ops color_ops = {
.get_comp_flag = get_comp_flag,
.init_comp = init_color,
.config_frame = NULL,
.config_subfrm = config_color_subfrm,
/* .reconfig_frame = NULL, */
/* .reconfig_subfrms = NULL, */
.wait_comp_event = NULL,
.advance_subfrm = NULL,
.post_process = NULL,
};
static int init_wrot(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd)
{
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
#if WROT_FILTER_CONSTRAINT
/* Wait WROT SRAM shared to DISP RDMA */
if (ctx->comp->alias_id == 0)
pr_err("Do not support WROT0_SRAM_READY event\n");
else
pr_err("Do not support WROT1_SRAM_READY event\n");
#endif
/* Reset WROT */
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_SOFT_RST, 0x01, 0x00000001);
MM_REG_POLL_S(cmd, subsys_id, base, VIDO_SOFT_RST_STAT, 0x01,
0x00000001);
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_SOFT_RST, 0x00, 0x00000001);
MM_REG_POLL_S(cmd, subsys_id, base, VIDO_SOFT_RST_STAT, 0x00,
0x00000001);
return 0;
}
static int config_wrot_frame(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd,
const struct v4l2_rect *compose)
{
const struct mdp_wrot_data *wrot = &ctx->param->wrot;
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
/* Write frame base address */
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_BASE_ADDR, wrot->iova[0],
0xFFFFFFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_BASE_ADDR_C, wrot->iova[1],
0xFFFFFFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_BASE_ADDR_V, wrot->iova[2],
0xFFFFFFFF);
/* Write frame related registers */
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_CTRL, wrot->control,
0xF131510F);
/* Write frame Y pitch */
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_STRIDE, wrot->stride[0],
0x0000FFFF);
/* Write frame UV pitch */
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_STRIDE_C, wrot->stride[1],
0x0000FFFF);
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_STRIDE_V, wrot->stride[2],
0x0000FFFF);
/* Write matrix control */
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_MAT_CTRL, wrot->mat_ctrl,
0x000000F3);
/* Set the fixed ALPHA as 0xFF */
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_DITHER, 0xFF000000,
0xFF000000);
/* Set VIDO_EOL_SEL */
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_RSV_1, 0x80000000,
0x80000000);
/* Set VIDO_FIFO_TEST */
if (wrot->fifo_test != 0)
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_FIFO_TEST,
wrot->fifo_test, 0x00000FFF);
#if WROT_FILTER_CONSTRAINT
/* Filter enable */
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_MAIN_BUF_SIZE, wrot->filter,
0x00000077);
#endif
return 0;
}
static int config_wrot_subfrm(struct mdp_comp_ctx *ctx,
struct mdp_cmd *cmd, u32 index)
{
const struct mdp_wrot_subfrm *subfrm = &ctx->param->wrot.subfrms[index];
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
/* Write Y pixel offset */
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_OFST_ADDR,
subfrm->offset[0], 0x0FFFFFFF);
/* Write U pixel offset */
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_OFST_ADDR_C,
subfrm->offset[1], 0x0FFFFFFF);
/* Write V pixel offset */
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_OFST_ADDR_V,
subfrm->offset[2], 0x0FFFFFFF);
/* Write source size */
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_IN_SIZE, subfrm->src,
0x1FFF1FFF);
/* Write target size */
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_TAR_SIZE, subfrm->clip,
0x1FFF1FFF);
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_CROP_OFST, subfrm->clip_ofst,
0x1FFF1FFF);
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_MAIN_BUF_SIZE,
subfrm->main_buf, 0x1FFF7F00);
/* Enable WROT */
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_ROT_EN, 0x01, 0x00000001);
return 0;
}
static int wait_wrot_event(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd)
{
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
if (ctx->comp->alias_id == 0)
MM_REG_WAIT(cmd, WROT0_FRAME_DONE);
else if (ctx->comp->alias_id == 1)
MM_REG_WAIT(cmd, WROT1_FRAME_DONE);
else
pr_err("Do not support WROT%d_DONE event\n", ctx->comp->alias_id);
#if WROT_FILTER_CONSTRAINT
/* Filter disable */
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_MAIN_BUF_SIZE,
(0 << 4) +
(0 << 0),
0x00000077);
#endif
/* Disable WROT */
MM_REG_WRITE_S(cmd, subsys_id, base, VIDO_ROT_EN, 0x00, 0x00000001);
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,
/* .reconfig_frame = reconfig_wrot_frame, */
/* .reconfig_subfrms = reconfig_wrot_subfrms, */
.wait_comp_event = wait_wrot_event,
.advance_subfrm = NULL,
.post_process = NULL,
};
static int init_isp(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd)
{
const struct isp_data *isp = &ctx->param->isp;
phys_addr_t mmsys = ctx->comp->mdp_dev->mmsys.reg_base;
u16 subsys_id = ctx->comp->mdp_dev->mmsys.subsys_id;
/* Direct link */
if (isp->dl_flags & (1 << MDP_CAMIN)) {
mdp_dbg(2, "SW_RST ASYNC");
/* Reset MDP_DL_ASYNC_TX */
/* Bit 3: MDP_DL_ASYNC_TX / MDP_RELAY */
MM_REG_WRITE_S(cmd, subsys_id, mmsys, MMSYS_SW0_RST_B, 0x0,
0x00000008);
MM_REG_WRITE_S(cmd, subsys_id, mmsys, MMSYS_SW0_RST_B, 1 << 3,
0x00000008);
/* Reset MDP_DL_ASYNC_RX */
/* Bit 10: MDP_DL_ASYNC_RX */
MM_REG_WRITE_S(cmd, subsys_id, mmsys, MMSYS_SW1_RST_B, 0x0,
0x00000400);
MM_REG_WRITE_S(cmd, subsys_id, mmsys, MMSYS_SW1_RST_B, 1 << 10,
0x00000400);
/* Enable sof mode */
//MM_REG_WRITE_S(cmd, subsys_id, mmsys, ISP_RELAY_CFG_WD, 0 << 31,
// 0x80000000);
}
if (isp->dl_flags & (1 << MDP_CAMIN2)) {
mdp_dbg(2, "SW_RST ASYNC2");
/* Reset MDP_DL_ASYNC2_TX */
/* Bit 4: MDP_DL_ASYNC2_TX / MDP_RELAY2 */
MM_REG_WRITE_S(cmd, subsys_id, mmsys, MMSYS_SW0_RST_B, 0x0,
0x00000010);
MM_REG_WRITE_S(cmd, subsys_id, mmsys, MMSYS_SW0_RST_B, 1 << 4,
0x00000010);
/* Reset MDP_DL_ASYNC2_RX */
/* Bit 11: MDP_DL_ASYNC2_RX */
MM_REG_WRITE_S(cmd, subsys_id, mmsys, MMSYS_SW1_RST_B, 0x0,
0x00000800);
MM_REG_WRITE_S(cmd, subsys_id, mmsys, MMSYS_SW1_RST_B, 1 << 11,
0x00000800);
/* Enable sof mode */
//MM_REG_WRITE_S(cmd, subsys_id, mmsys, IPU_RELAY_CFG_WD, 0 << 31,
// 0x80000000);
}
return 0;
}
static int config_isp_frame(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd,
const struct v4l2_rect *compose)
{
const struct isp_data *isp = &ctx->param->isp;
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
/* DIP_X_SMX1I_BASE_ADDR, DIP_X_SMX1O_BASE_ADDR */
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2890, isp->smxi_iova[0],
0xFFFFFFFF);
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x27D0, isp->smxi_iova[0],
0xFFFFFFFF);
/* DIP_X_SMX2I_BASE_ADDR, DIP_X_SMX2O_BASE_ADDR */
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x28C0, isp->smxi_iova[1],
0xFFFFFFFF);
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2800, isp->smxi_iova[1],
0xFFFFFFFF);
/* DIP_X_SMX3I_BASE_ADDR, DIP_X_SMX3O_BASE_ADDR */
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x28F0, isp->smxi_iova[2],
0xFFFFFFFF);
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2830, isp->smxi_iova[2],
0xFFFFFFFF);
/* DIP_X_SMX4I_BASE_ADDR, DIP_X_SMX4O_BASE_ADDR */
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2920, isp->smxi_iova[3],
0xFFFFFFFF);
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2860, isp->smxi_iova[3],
0xFFFFFFFF);
switch (isp->cq_idx) {
case ISP_DRV_DIP_CQ_THRE0:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2208,
isp->cq_iova, 0xFFFFFFFF);
break;
case ISP_DRV_DIP_CQ_THRE1:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2214,
isp->cq_iova, 0xFFFFFFFF);
break;
case ISP_DRV_DIP_CQ_THRE2:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2220,
isp->cq_iova, 0xFFFFFFFF);
break;
case ISP_DRV_DIP_CQ_THRE3:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x222C,
isp->cq_iova, 0xFFFFFFFF);
break;
case ISP_DRV_DIP_CQ_THRE4:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2238,
isp->cq_iova, 0xFFFFFFFF);
break;
case ISP_DRV_DIP_CQ_THRE5:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2244,
isp->cq_iova, 0xFFFFFFFF);
break;
case ISP_DRV_DIP_CQ_THRE6:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2250,
isp->cq_iova, 0xFFFFFFFF);
break;
case ISP_DRV_DIP_CQ_THRE7:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x225C,
isp->cq_iova, 0xFFFFFFFF);
break;
case ISP_DRV_DIP_CQ_THRE8:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2268,
isp->cq_iova, 0xFFFFFFFF);
break;
case ISP_DRV_DIP_CQ_THRE9:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2274,
isp->cq_iova, 0xFFFFFFFF);
break;
case ISP_DRV_DIP_CQ_THRE10:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2280,
isp->cq_iova, 0xFFFFFFFF);
break;
case ISP_DRV_DIP_CQ_THRE11:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x228C,
isp->cq_iova, 0xFFFFFFFF);
break;
case ISP_DRV_DIP_CQ_THRE12:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2298,
isp->cq_iova, 0xFFFFFFFF);
break;
case ISP_DRV_DIP_CQ_THRE13:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x22A4,
isp->cq_iova, 0xFFFFFFFF);
break;
case ISP_DRV_DIP_CQ_THRE14:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x22B0,
isp->cq_iova, 0xFFFFFFFF);
break;
/* From CQ15 to CQ18, these do not connect to GCE */
default:
mdp_err("Do not support this cq (%d)", isp->cq_idx);
return -EINVAL;
}
return 0;
}
static int config_isp_subfrm(struct mdp_comp_ctx *ctx,
struct mdp_cmd *cmd, u32 index)
{
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2304,
ctx->param->isp.tpipe_iova[index], 0xFFFFFFFF);
return 0;
}
static int wait_isp_event(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd)
{
const struct isp_data *isp = &ctx->param->isp;
phys_addr_t base = ctx->comp->reg_base;
u16 subsys_id = ctx->comp->subsys_id;
/* MDP_DL_SEL: select MDP_CROP */
if (isp->dl_flags & (1 << MDP_CAMIN))
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x0030, 0x00000000,
0x00000200);
/* MDP2_DL_SEL: select MDP_CROP2 */
if (isp->dl_flags & (1 << MDP_CAMIN2))
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x0030, 0x00000000,
0x00000C00);
switch (isp->cq_idx) {
case ISP_DRV_DIP_CQ_THRE0:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0001,
0x00000001);
//MM_REG_WAIT(cmd, ISP_P2_0_DONE);
break;
case ISP_DRV_DIP_CQ_THRE1:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0002,
0x00000002);
//MM_REG_WAIT(cmd, ISP_P2_1_DONE);
break;
case ISP_DRV_DIP_CQ_THRE2:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0004,
0x00000004);
//MM_REG_WAIT(cmd, ISP_P2_2_DONE);
break;
case ISP_DRV_DIP_CQ_THRE3:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0008,
0x00000008);
//MM_REG_WAIT(cmd, ISP_P2_3_DONE);
break;
case ISP_DRV_DIP_CQ_THRE4:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0010,
0x00000010);
//MM_REG_WAIT(cmd, ISP_P2_4_DONE);
break;
case ISP_DRV_DIP_CQ_THRE5:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0020,
0x00000020);
//MM_REG_WAIT(cmd, ISP_P2_5_DONE);
break;
case ISP_DRV_DIP_CQ_THRE6:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0040,
0x00000040);
///MM_REG_WAIT(cmd, ISP_P2_6_DONE);
break;
case ISP_DRV_DIP_CQ_THRE7:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0080,
0x00000080);
//MM_REG_WAIT(cmd, ISP_P2_7_DONE);
break;
case ISP_DRV_DIP_CQ_THRE8:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0100,
0x00000100);
//MM_REG_WAIT(cmd, ISP_P2_8_DONE);
break;
case ISP_DRV_DIP_CQ_THRE9:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0200,
0x00000200);
//MM_REG_WAIT(cmd, ISP_P2_9_DONE);
break;
case ISP_DRV_DIP_CQ_THRE10:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0400,
0x00000400);
//MM_REG_WAIT(cmd, ISP_P2_10_DONE);
break;
case ISP_DRV_DIP_CQ_THRE11:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0800,
0x00000800);
//MM_REG_WAIT(cmd, ISP_P2_11_DONE);
break;
case ISP_DRV_DIP_CQ_THRE12:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x1000,
0x00001000);
//MM_REG_WAIT(cmd, ISP_P2_12_DONE);
break;
case ISP_DRV_DIP_CQ_THRE13:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x2000,
0x00002000);
//MM_REG_WAIT(cmd, ISP_P2_13_DONE);
break;
case ISP_DRV_DIP_CQ_THRE14:
MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x4000,
0x00004000);
//MM_REG_WAIT(cmd, ISP_P2_14_DONE);
break;
/* From CQ15 to CQ18, these do not connect to GCE */
default:
mdp_err("Do not support this cq (%d)", isp->cq_idx);
return -EINVAL;
}
return 0;
}
static const struct mdp_comp_ops imgi_ops = {
.get_comp_flag = get_comp_flag,
.init_comp = init_isp,
.config_frame = config_isp_frame,
.config_subfrm = config_isp_subfrm,
/* .reconfig_frame = reconfig_isp_frame, */
/* .reconfig_subfrms = reconfig_isp_subfrms, */
.wait_comp_event = wait_isp_event,
.advance_subfrm = NULL,
.post_process = NULL,
};
static int config_camin_subfrm(struct mdp_comp_ctx *ctx,
struct mdp_cmd *cmd, u32 index)
{
const struct img_comp_subfrm *csf = &ctx->param->subfrms[index];
//phys_addr_t base = ctx->comp->reg_base;
//u8 subsys_id = ctx->comp->subsys_id;
u32 isp_dl_w, isp_dl_h;
isp_dl_w = csf->in.right - csf->in.left + 1;
isp_dl_h = csf->in.bottom - csf->in.top + 1;
/* Config for direct link */
if (ctx->comp->alias_id == 0) {
/*#ifdef MDP_ASYNC_CFG_WD
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_ASYNC_CFG_WD,
(isp_dl_h << 16) + isp_dl_w, 0x3FFF3FFF);
#endif
#ifdef ISP_RELAY_CFG_WD
MM_REG_WRITE_S(cmd, subsys_id, base, ISP_RELAY_CFG_WD,
(isp_dl_h << 16) + isp_dl_w, 0x3FFF3FFF);
#endif
} else {
#ifdef MDP_ASYNC_IPU_CFG_WD
MM_REG_WRITE_S(cmd, subsys_id, base, MDP_ASYNC_IPU_CFG_WD,
(isp_dl_h << 16) + isp_dl_w, 0x3FFF3FFF);
#endif
#ifdef IPU_RELAY_CFG_WD
MM_REG_WRITE_S(cmd, subsys_id, base, IPU_RELAY_CFG_WD,
(isp_dl_h << 16) + isp_dl_w, 0x3FFF3FFF);
#endif*/
}
return 0;
}
static const struct mdp_comp_ops camin_ops = {
.get_comp_flag = get_comp_flag,
.init_comp = NULL,
.config_frame = NULL,
.config_subfrm = config_camin_subfrm,
/* .reconfig_frame = NULL, */
/* .reconfig_subfrms = NULL, */
.wait_comp_event = NULL,
.advance_subfrm = NULL,
.post_process = NULL,
};
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_AAL] = &aal_ops,
[MDP_COMP_TYPE_HDR] = &hdr_ops,
[MDP_COMP_TYPE_TDSHP] = &tdshp_ops,
[MDP_COMP_TYPE_COLOR] = &color_ops,
[MDP_COMP_TYPE_WROT] = &wrot_ops,
[MDP_COMP_TYPE_WDMA] = NULL,
[MDP_COMP_TYPE_PATH] = NULL,
[MDP_COMP_TYPE_CCORR] = NULL,
[MDP_COMP_TYPE_IMGI] = &imgi_ops,
[MDP_COMP_TYPE_EXTO] = NULL,
[MDP_COMP_TYPE_DL_PATH] = &camin_ops,
};
struct mdp_comp_match {
enum mdp_comp_type type;
u32 alias_id;
};
static const struct mdp_comp_match mdp_comp_matches[MDP_MAX_COMP_COUNT] = {
[MDP_COMP_WPEI] = { MDP_COMP_TYPE_WPEI, 0 },
[MDP_COMP_WPEO] = { MDP_COMP_TYPE_EXTO, 2 },
[MDP_COMP_WPEI2] = { MDP_COMP_TYPE_WPEI, 1 },
[MDP_COMP_WPEO2] = { MDP_COMP_TYPE_EXTO, 3 },
[MDP_COMP_ISP_IMGI] = { MDP_COMP_TYPE_IMGI, 0 },
[MDP_COMP_ISP_IMG2O] = { MDP_COMP_TYPE_EXTO, 1 },
[MDP_COMP_CAMIN] = { MDP_COMP_TYPE_DL_PATH, 0 },
[MDP_COMP_CAMIN2] = { MDP_COMP_TYPE_DL_PATH, 1 },
[MDP_COMP_RDMA0] = { MDP_COMP_TYPE_RDMA, 0 },
[MDP_COMP_RDMA1] = { MDP_COMP_TYPE_RDMA, 1 },
[MDP_COMP_HDR0] = { MDP_COMP_TYPE_HDR, 0 },
[MDP_COMP_HDR1] = { MDP_COMP_TYPE_HDR, 1 },
[MDP_COMP_COLOR0] = { MDP_COMP_TYPE_COLOR, 0 },
[MDP_COMP_COLOR1] = { MDP_COMP_TYPE_COLOR, 1 },
[MDP_COMP_AAL0] = { MDP_COMP_TYPE_AAL, 0 },
[MDP_COMP_AAL1] = { MDP_COMP_TYPE_AAL, 1 },
[MDP_COMP_RSZ0] = { MDP_COMP_TYPE_RSZ, 0 },
[MDP_COMP_RSZ1] = { MDP_COMP_TYPE_RSZ, 1 },
[MDP_COMP_TDSHP0] = { MDP_COMP_TYPE_TDSHP, 0 },
[MDP_COMP_TDSHP1] = { MDP_COMP_TYPE_TDSHP, 1 },
[MDP_COMP_WROT0] = { MDP_COMP_TYPE_WROT, 0 },
[MDP_COMP_WROT1] = { MDP_COMP_TYPE_WROT, 1 },
};
static const char * const gce_event_names[MDP_MAX_EVENT_COUNT] = {
[RDMA0_SOF] = "RDMA0_SOF",
[RDMA1_SOF] = "RDMA1_SOF",
[AAL0_SOF] = "AAL0_SOF",
[AAL1_SOF] = "AAL1_SOF",
[HDR0_SOF] = "HDR0_SOF",
[HDR1_SOF] = "HDR1_SOF",
[RSZ0_SOF] = "RSZ0_SOF",
[RSZ1_SOF] = "RSZ1_SOF",
[WROT0_SOF] = "WROT0_SOF",
[WROT1_SOF] = "WROT1_SOF",
[TDSHP0_SOF] = "TDSHP0_SOF",
[TDSHP1_SOF] = "TDSHP1_SOF",
[DL_RELAY0_SOF] = "DL_RELAY0_SOF",
[DL_RELAY1_SOF] = "DL_RELAY1_SOF",
[COLOR0_SOF] = "COLOR0_SOF",
[COLOR1_SOF] = "COLOR1_SOF",
[WROT1_FRAME_DONE] = "WROT1_FRAME_DONE",
[WROT0_FRAME_DONE] = "WROT0_FRAME_DONE",
[TDSHP1_FRAME_DONE] = "TDSHP1_FRAME_DONE",
[TDSHP0_FRAME_DONE] = "TDSHP0_FRAME_DONE",
[RSZ1_FRAME_DONE] = "RSZ1_FRAME_DONE",
[RSZ0_FRAME_DONE] = "RSZ0_FRAME_DONE",
[RDMA1_FRAME_DONE] = "RDMA1_FRAME_DONE",
[RDMA0_FRAME_DONE] = "RDMA0_FRAME_DONE",
[HDR1_FRAME_DONE] = "HDR1_FRAME_DONE",
[HDR0_FRAME_DONE] = "HDR0_FRAME_DONE",
[COLOR1_FRAME_DONE] = "COLOR1_FRAME_DONE",
[COLOR0_FRAME_DONE] = "COLOR0_FRAME_DONE",
[AAL1_FRAME_DONE] = "AAL1_FRAME_DONE",
[AAL0_FRAME_DONE] = "AAL0_FRAME_DONE",
[STREAM_DONE_0] = "STREAM_DONE_0",
[STREAM_DONE_1] = "STREAM_DONE_1",
[STREAM_DONE_2] = "STREAM_DONE_2",
[STREAM_DONE_3] = "STREAM_DONE_3",
[STREAM_DONE_4] = "STREAM_DONE_4",
[STREAM_DONE_5] = "STREAM_DONE_5",
[STREAM_DONE_6] = "STREAM_DONE_6",
[STREAM_DONE_7] = "STREAM_DONE_7",
[STREAM_DONE_8] = "STREAM_DONE_8",
[STREAM_DONE_9] = "STREAM_DONE_9",
[STREAM_DONE_10] = "STREAM_DONE_10",
[STREAM_DONE_11] = "STREAM_DONE_11",
[STREAM_DONE_12] = "STREAM_DONE_12",
[STREAM_DONE_13] = "STREAM_DONE_13",
[STREAM_DONE_14] = "STREAM_DONE_14",
[STREAM_DONE_15] = "STREAM_DONE_15",
[WROT1_SW_RST_DONE] = "WROT1_SW_RST_DONE",
[WROT0_SW_RST_DONE] = "WROT0_SW_RST_DONE",
[RDMA1_SW_RST_DONE] = "RDMA1_SW_RST_DONE",
[RDMA0_SW_RST_DONE] = "RDMA0_SW_RST_DONE",
};
static const struct of_device_id mdp_comp_dt_ids[] = {
{
.compatible = "mediatek,mt8192-mdp-rdma",
.data = (void *)MDP_COMP_TYPE_RDMA,
}, {
.compatible = "mediatek,mt8192-mdp-color",
.data = (void *)MDP_COMP_TYPE_COLOR,
}, {
.compatible = "mediatek,mt8192-mdp-aal",
.data = (void *)MDP_COMP_TYPE_AAL,
}, {
.compatible = "mediatek,mt8192-mdp-hdr",
.data = (void *)MDP_COMP_TYPE_HDR,
}, {
.compatible = "mediatek,mt8192-mdp-rsz",
.data = (void *)MDP_COMP_TYPE_RSZ,
}, {
.compatible = "mediatek,mt8192-mdp-wrot",
.data = (void *)MDP_COMP_TYPE_WROT,
}, {
.compatible = "mediatek,mt8192-mdp-tdshp",
.data = (void *)MDP_COMP_TYPE_TDSHP,
}, {
.compatible = "mediatek,mt8192-mdp-dl",
.data = (void *)MDP_COMP_TYPE_DL_PATH,
},
{}
};
static int mdp_comp_get_id(struct device *dev, struct device_node *node,
enum mdp_comp_type type)
{
u32 alias_id;
int i, ret;
ret = of_property_read_u32(node, "mediatek,mdp-id", &alias_id);
if (ret)
return ret;
for (i = 0; i < ARRAY_SIZE(mdp_comp_matches); i++)
if (mdp_comp_matches[i].type == type &&
mdp_comp_matches[i].alias_id == alias_id)
return i;
dev_err(dev, "Failed to get id. type: %d, alias: %d\n", type, alias_id);
return -EINVAL;
}
void mdp_comp_clock_on(struct device *dev, struct mdp_comp *comp)
{
int i, err;
if (comp->larb_dev) {
err = pm_runtime_get_sync(comp->larb_dev);
if (err < 0)
dev_err(dev,
"Failed to try get larb once, err %d. type:%d id:%d\n",
err, comp->type, comp->id);
err = pm_runtime_get_sync(comp->larb_dev);
if (err < 0)
dev_err(dev,
"Failed to get larb, err %d. type:%d id:%d\n",
err, comp->type, comp->id);
}
for (i = 0; i < ARRAY_SIZE(comp->clks); i++) {
if (IS_ERR(comp->clks[i]))
break;
err = clk_prepare_enable(comp->clks[i]);
if (err)
dev_err(dev,
"Failed to enable clock %d, err %d. type:%d id:%d\n",
i, err, comp->type, comp->id);
}
}
void mdp_comp_clock_off(struct device *dev, struct mdp_comp *comp)
{
int i;
for (i = 0; i < ARRAY_SIZE(comp->clks); i++) {
if (IS_ERR(comp->clks[i]))
break;
clk_disable_unprepare(comp->clks[i]);
}
if (comp->larb_dev)
pm_runtime_put(comp->larb_dev);
}
void mdp_comp_clocks_on(struct device *dev, struct mdp_comp *comps, int num)
{
int i;
for (i = 0; i < num; i++)
mdp_comp_clock_on(dev, &comps[i]);
}
void mdp_comp_clocks_off(struct device *dev, struct mdp_comp *comps, int num)
{
int i;
for (i = 0; i < num; i++)
mdp_comp_clock_off(dev, &comps[i]);
}
static int mdp_get_subsys_id(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;
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 id=%d type=%d\n",
comp->id, comp->type);
return -ENODEV;
}
cmdq_reg = kzalloc(sizeof(*cmdq_reg), GFP_KERNEL);
if (!cmdq_reg)
return -ENOMEM;
ret = cmdq_dev_get_client_reg(&comp_pdev->dev, cmdq_reg, 0);
if (ret != 0) {
dev_err(&comp_pdev->dev,
"cmdq_dev_get_subsys fail!\n");
kfree(cmdq_reg);
return -EINVAL;
}
comp->subsys_id = cmdq_reg->subsys;
dev_err(&comp_pdev->dev, "subsys id=%d\n", cmdq_reg->subsys);
kfree(cmdq_reg);
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 i;
if (of_address_to_resource(node, 0, &res) < 0)
base = 0L;
else
base = 0L | res.start;
comp->mdp_dev = mdp;
/* comp->dev_node = of_node_get(node); */
comp->regs = of_iomap(node, 0);
comp->reg_base = base;
for (i = 0; i < ARRAY_SIZE(comp->clks); i++) {
comp->clks[i] = of_clk_get(node, i);
if (IS_ERR(comp->clks[i]))
break;
}
}
static int mdp_mm_init(struct mdp_dev *mdp,
struct mdp_comp *comp, const char *ref_name)
{
struct device_node *node;
struct device *dev = &mdp->pdev->dev;
node = of_parse_phandle(dev->of_node, ref_name, 0);
if (!node) {
dev_err(dev, "Failed to parse dt %s\n", ref_name);
return -EINVAL;
}
__mdp_comp_init(mdp, node, comp);
mdp_get_subsys_id(dev, node, comp);
of_node_put(node);
if (!comp->reg_base) {
dev_err(dev, "Failed to init %s base\n", ref_name);
return -EINVAL;
}
return 0;
}
static int mdp_comp_init(struct device *dev, struct mdp_dev *mdp,
struct device_node *node, struct mdp_comp *comp,
enum mdp_comp_id id)
{
struct device_node *larb_node;
struct platform_device *larb_pdev;
int i;
if (id < 0 || id >= MDP_MAX_COMP_COUNT) {
dev_err(dev, "Invalid component id %d\n", id);
return -EINVAL;
}
__mdp_comp_init(mdp, node, comp);
comp->type = mdp_comp_matches[id].type;
comp->id = id;
comp->alias_id = mdp_comp_matches[id].alias_id;
comp->ops = mdp_comp_ops[comp->type];
for (i = 0; i < ARRAY_SIZE(comp->clks); i++) {
comp->clks[i] = of_clk_get(node, i);
if (IS_ERR(comp->clks[i]))
break;
}
mdp_get_subsys_id(dev, node, comp);
/* Only DMA capable components need the LARB property */
comp->larb_dev = NULL;
if (comp->type != MDP_COMP_TYPE_RDMA &&
comp->type != MDP_COMP_TYPE_WROT &&
comp->type != MDP_COMP_TYPE_WDMA)
return 0;
larb_node = of_parse_phandle(node, "mediatek,larb", 0);
if (!larb_node) {
dev_err(dev, "Missing mediatek,larb phandle in %pOF node\n",
node);
return -EINVAL;
}
larb_pdev = of_find_device_by_node(larb_node);
if (!larb_pdev) {
dev_warn(dev, "Waiting for larb device %pOF\n", larb_node);
of_node_put(larb_node);
return -EPROBE_DEFER;
}
of_node_put(larb_node);
comp->larb_dev = &larb_pdev->dev;
return 0;
}
static void mdp_comp_deinit(struct mdp_comp *comp)
{
iounmap(comp->regs);
/* of_node_put(comp->dev_node); */
}
void mdp_component_deinit(struct mdp_dev *mdp)
{
int i;
mdp_comp_deinit(&mdp->mmsys);
mdp_comp_deinit(&mdp->mm_mutex);
for (i = 0; i < ARRAY_SIZE(mdp->comp); i++) {
if (mdp->comp[i]) {
mdp_comp_deinit(mdp->comp[i]);
kfree(mdp->comp[i]);
}
}
}
int mdp_component_init(struct mdp_dev *mdp)
{
struct device *dev = &mdp->pdev->dev;
struct device_node *node, *parent;
int i, ret;
for (i = RDMA0_SOF; i < MDP_MAX_EVENT_COUNT; i++) {
s32 event_id;
if (!dev)
return -EINVAL;
if (of_property_read_u32_index(dev->of_node,
"mediatek,gce-events",
i, &event_id)) {
dev_err(dev, "can't parse gce-events property");
return -ENODEV;
}
mdp->event[i] = (event_id < 0) ? -i : event_id;
dev_info(dev, "Get event %s id:%d\n",
gce_event_names[i], mdp->event[i]);
}
ret = mdp_mm_init(mdp, &mdp->mmsys, "mediatek,mmsys");
if (ret)
goto err_init_mm;
ret = mdp_mm_init(mdp, &mdp->mm_mutex, "mediatek,mm-mutex");
if (ret)
goto err_init_mm;
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;
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_info(dev, "Skipping disabled component %pOF\n",
node);
continue;
}
type = (enum mdp_comp_type)of_id->data;
id = mdp_comp_get_id(dev, node, type);
if (id < 0) {
dev_warn(dev, "Skipping unknown component %pOF\n",
node);
continue;
}
comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL);
if (!comp) {
ret = -ENOMEM;
goto err_init_comps;
}
mdp->comp[id] = comp;
ret = mdp_comp_init(dev, mdp, node, comp, id);
if (ret)
goto err_init_comps;
dev_info(dev, "%s type:%d alias:%d id:%d base:%#x regs:%p\n",
of_id->compatible, type, comp->alias_id, id,
(u32)comp->reg_base, comp->regs);
}
return 0;
err_init_comps:
mdp_component_deinit(mdp);
err_init_mm:
return ret;
}
int mdp_comp_ctx_init(struct mdp_dev *mdp, struct mdp_comp_ctx *ctx,
const struct img_compparam *param,
const struct img_ipi_frameparam *frame)
{
int i;
if (param->type < 0 || param->type >= MDP_MAX_COMP_COUNT) {
mdp_err("Invalid component id %d", param->type);
return -EINVAL;
}
ctx->comp = mdp->comp[param->type];
if (!ctx->comp) {
mdp_err("Uninit component id %d", param->type);
return -EINVAL;
}
ctx->param = param;
ctx->input = &frame->inputs[param->input];
for (i = 0; i < param->num_outputs; i++)
ctx->outputs[i] = &frame->outputs[param->outputs[i]];
return 0;
}