1348 lines
42 KiB
C
1348 lines
42 KiB
C
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||
|
|
/*
|
||
|
|
* Copyright (c) 2019 MediaTek Inc.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include <linux/clk.h>
|
||
|
|
#include <linux/iopoll.h>
|
||
|
|
#include <linux/of.h>
|
||
|
|
#include <linux/of_address.h>
|
||
|
|
#include <linux/of_irq.h>
|
||
|
|
#include <linux/of_platform.h>
|
||
|
|
#include <linux/platform_device.h>
|
||
|
|
#include <drm/drmP.h>
|
||
|
|
#include <linux/soc/mediatek/mtk-cmdq.h>
|
||
|
|
#include <soc/mediatek/smi.h>
|
||
|
|
#ifdef CONFIG_MTK_IOMMU_V2
|
||
|
|
#include "mt_iommu.h"
|
||
|
|
#include "mtk_iommu_ext.h"
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#include "mtk_drm_drv.h"
|
||
|
|
#include "mtk_drm_plane.h"
|
||
|
|
#include "mtk_drm_ddp_comp.h"
|
||
|
|
#include "mtk_drm_crtc.h"
|
||
|
|
#include "mtk_drm_gem.h"
|
||
|
|
#include "mtk_dump.h"
|
||
|
|
|
||
|
|
#ifdef CONFIG_MTK_SMI_EXT
|
||
|
|
#include "smi_public.h"
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#define DISP_OD_EN 0x0000
|
||
|
|
#define DISP_OD_INTEN 0x0008
|
||
|
|
#define DISP_OD_INTSTA 0x000c
|
||
|
|
#define DISP_OD_CFG 0x0020
|
||
|
|
#define DISP_OD_SIZE 0x0030
|
||
|
|
#define DISP_DITHER_5 0x0114
|
||
|
|
#define DISP_DITHER_7 0x011c
|
||
|
|
#define DISP_DITHER_15 0x013c
|
||
|
|
#define DISP_DITHER_16 0x0140
|
||
|
|
|
||
|
|
#define DISP_REG_SPLIT_START 0x0000
|
||
|
|
|
||
|
|
#define DISP_REG_UFO_START 0x0000
|
||
|
|
#define DISP_REG_UFO_WIDTH 0x0050
|
||
|
|
#define DISP_REG_UFO_HEIGHT 0x0054
|
||
|
|
|
||
|
|
#define OD_RELAYMODE BIT(0)
|
||
|
|
|
||
|
|
#define UFO_BYPASS BIT(2)
|
||
|
|
#define UFO_LR (BIT(3) | BIT(0))
|
||
|
|
|
||
|
|
#define DISP_DITHERING BIT(2)
|
||
|
|
#define DITHER_LSB_ERR_SHIFT_R(x) (((x)&0x7) << 28)
|
||
|
|
#define DITHER_OVFLW_BIT_R(x) (((x)&0x7) << 24)
|
||
|
|
#define DITHER_ADD_LSHIFT_R(x) (((x)&0x7) << 20)
|
||
|
|
#define DITHER_ADD_RSHIFT_R(x) (((x)&0x7) << 16)
|
||
|
|
#define DITHER_NEW_BIT_MODE BIT(0)
|
||
|
|
#define DITHER_LSB_ERR_SHIFT_B(x) (((x)&0x7) << 28)
|
||
|
|
#define DITHER_OVFLW_BIT_B(x) (((x)&0x7) << 24)
|
||
|
|
#define DITHER_ADD_LSHIFT_B(x) (((x)&0x7) << 20)
|
||
|
|
#define DITHER_ADD_RSHIFT_B(x) (((x)&0x7) << 16)
|
||
|
|
#define DITHER_LSB_ERR_SHIFT_G(x) (((x)&0x7) << 12)
|
||
|
|
#define DITHER_OVFLW_BIT_G(x) (((x)&0x7) << 8)
|
||
|
|
#define DITHER_ADD_LSHIFT_G(x) (((x)&0x7) << 4)
|
||
|
|
#define DITHER_ADD_RSHIFT_G(x) (((x)&0x7) << 0)
|
||
|
|
|
||
|
|
#define MMSYS_SODI_REQ_MASK 0xF4
|
||
|
|
#define SODI_REQ_SEL_ALL REG_FLD_MSB_LSB(11, 8)
|
||
|
|
#define MT6873_SODI_REQ_SEL_ALL REG_FLD_MSB_LSB(9, 8)
|
||
|
|
#define SODI_REQ_SEL_RDMA0_PD_MODE REG_FLD_MSB_LSB(8, 8)
|
||
|
|
#define SODI_REQ_SEL_RDMA0_CG_MODE REG_FLD_MSB_LSB(9, 9)
|
||
|
|
#define SODI_REQ_SEL_RDMA1_PD_MODE REG_FLD_MSB_LSB(10, 10)
|
||
|
|
#define SODI_REQ_SEL_RDMA1_CG_MODE REG_FLD_MSB_LSB(11, 11)
|
||
|
|
|
||
|
|
#define SODI_REQ_VAL_ALL REG_FLD_MSB_LSB(15, 12)
|
||
|
|
#define MT6873_SODI_REQ_VAL_ALL REG_FLD_MSB_LSB(13, 12)
|
||
|
|
#define SODI_REQ_VAL_RDMA0_PD_MODE REG_FLD_MSB_LSB(12, 12)
|
||
|
|
#define SODI_REQ_VAL_RDMA0_CG_MODE REG_FLD_MSB_LSB(13, 13)
|
||
|
|
#define SODI_REQ_VAL_RDMA1_PD_MODE REG_FLD_MSB_LSB(14, 14)
|
||
|
|
#define SODI_REQ_VAL_RDMA1_CG_MODE REG_FLD_MSB_LSB(15, 15)
|
||
|
|
|
||
|
|
#define MMSYS_EMI_REQ_CTL 0xF8
|
||
|
|
#define HRT_URGENT_CTL_SEL_ALL REG_FLD_MSB_LSB(7, 0)
|
||
|
|
#define HRT_URGENT_CTL_SEL_RDMA0 REG_FLD_MSB_LSB(0, 0)
|
||
|
|
#define HRT_URGENT_CTL_SEL_WDMA0 REG_FLD_MSB_LSB(1, 1)
|
||
|
|
#define HRT_URGENT_CTL_SEL_RDMA1 REG_FLD_MSB_LSB(2, 2)
|
||
|
|
#define HRT_URGENT_CTL_SEL_WDMA1 REG_FLD_MSB_LSB(3, 3)
|
||
|
|
#define HRT_URGENT_CTL_SEL_RDMA4 REG_FLD_MSB_LSB(4, 4)
|
||
|
|
#define HRT_URGENT_CTL_SEL_RDMA5 REG_FLD_MSB_LSB(5, 5)
|
||
|
|
#define HRT_URGENT_CTL_SEL_MDP_RDMA4 REG_FLD_MSB_LSB(6, 6)
|
||
|
|
|
||
|
|
#define HRT_URGENT_CTL_VAL_ALL REG_FLD_MSB_LSB(16, 9)
|
||
|
|
#define HRT_URGENT_CTL_VAL_RDMA0 REG_FLD_MSB_LSB(9, 9)
|
||
|
|
#define HRT_URGENT_CTL_VAL_WDMA0 REG_FLD_MSB_LSB(10, 10)
|
||
|
|
#define HRT_URGENT_CTL_VAL_RDMA4 REG_FLD_MSB_LSB(13, 13)
|
||
|
|
#define HRT_URGENT_CTL_VAL_MDP_RDMA4 REG_FLD_MSB_LSB(15, 15)
|
||
|
|
|
||
|
|
#define DVFS_HALT_MASK_SEL_ALL REG_FLD_MSB_LSB(23, 18)
|
||
|
|
#define DVFS_HALT_MASK_SEL_RDMA0 REG_FLD_MSB_LSB(18, 18)
|
||
|
|
#define DVFS_HALT_MASK_SEL_RDMA1 REG_FLD_MSB_LSB(19, 19)
|
||
|
|
#define DVFS_HALT_MASK_SEL_RDMA4 REG_FLD_MSB_LSB(20, 20)
|
||
|
|
#define DVFS_HALT_MASK_SEL_RDMA5 REG_FLD_MSB_LSB(21, 21)
|
||
|
|
#define DVFS_HALT_MASK_SEL_WDMA0 REG_FLD_MSB_LSB(22, 22)
|
||
|
|
#define DVFS_HALT_MASK_SEL_WDMA1 REG_FLD_MSB_LSB(23, 23)
|
||
|
|
|
||
|
|
#define MT6877_INFRA_MEM_IDLE_ASYNC_2 0x178
|
||
|
|
#define MT6877_MM_PORT0_AXI_IDLE_ASYNC REG_FLD_MSB_LSB(2, 2)
|
||
|
|
#define MT6877_MM_PORT1_AXI_IDLE_ASYNC REG_FLD_MSB_LSB(3, 3)
|
||
|
|
#define MT6877_INFRA_MEM_IDLE_ASYNC_3 0x17c
|
||
|
|
#define MT6877_MDP2INFRA0_GALS_TX_AXI_IDLE REG_FLD_MSB_LSB(12, 12)
|
||
|
|
#define MT6877_COMM0_GALS_TX_AXI_IDLE REG_FLD_MSB_LSB(13, 13)
|
||
|
|
|
||
|
|
#define MT6833_INFRA_DISP_DDR_CTL 0x2C
|
||
|
|
#define MT6833_INFRA_FLD_DDR_MASK REG_FLD_MSB_LSB(7, 4)
|
||
|
|
|
||
|
|
#define MT6781_INFRA_DISP_DDR_CTL 0xB8
|
||
|
|
#define MT6781_INFRA_DISP_DDR_MASK 0xC02
|
||
|
|
#define SMI_LARB_NON_SEC_CON 0x0380
|
||
|
|
|
||
|
|
#define MTK_DDP_COMP_USER "DISP"
|
||
|
|
|
||
|
|
|
||
|
|
void mtk_ddp_write(struct mtk_ddp_comp *comp, unsigned int value,
|
||
|
|
unsigned int offset, void *handle)
|
||
|
|
{
|
||
|
|
#ifdef CONFIG_MTK_DISPLAY_CMDQ
|
||
|
|
cmdq_pkt_write((struct cmdq_pkt *)handle, comp->cmdq_base,
|
||
|
|
comp->regs_pa + offset, value, ~0);
|
||
|
|
#else
|
||
|
|
writel(value, comp->regs + offset);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
void mtk_ddp_write_relaxed(struct mtk_ddp_comp *comp, unsigned int value,
|
||
|
|
unsigned int offset, void *handle)
|
||
|
|
{
|
||
|
|
#ifdef CONFIG_MTK_DISPLAY_CMDQ
|
||
|
|
cmdq_pkt_write((struct cmdq_pkt *)handle, comp->cmdq_base,
|
||
|
|
comp->regs_pa + offset, value, ~0);
|
||
|
|
#else
|
||
|
|
writel_relaxed(value, comp->regs + offset);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
void mtk_ddp_write_mask(struct mtk_ddp_comp *comp, unsigned int value,
|
||
|
|
unsigned int offset, unsigned int mask, void *handle)
|
||
|
|
{
|
||
|
|
#ifdef CONFIG_MTK_DISPLAY_CMDQ
|
||
|
|
cmdq_pkt_write((struct cmdq_pkt *)handle, comp->cmdq_base,
|
||
|
|
comp->regs_pa + offset, value, mask);
|
||
|
|
#else
|
||
|
|
unsigned int tmp = readl(comp->regs + offset);
|
||
|
|
|
||
|
|
tmp = (tmp & ~mask) | (value & mask);
|
||
|
|
writel(tmp, comp->regs + offset);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
void mtk_ddp_write_mask_cpu(struct mtk_ddp_comp *comp,
|
||
|
|
unsigned int value, unsigned int offset, unsigned int mask)
|
||
|
|
{
|
||
|
|
unsigned int tmp = readl(comp->regs + offset);
|
||
|
|
|
||
|
|
tmp = (tmp & ~mask) | (value & mask);
|
||
|
|
writel(tmp, comp->regs + offset);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void mtk_write_cpu_relaxed(void __iomem *addr,
|
||
|
|
unsigned int value, unsigned int mask)
|
||
|
|
{
|
||
|
|
unsigned int tmp = readl(addr);
|
||
|
|
|
||
|
|
tmp = (tmp & ~mask) | (value & mask);
|
||
|
|
writel_relaxed(tmp, addr);
|
||
|
|
}
|
||
|
|
|
||
|
|
void mtk_dither_set(struct mtk_ddp_comp *comp, unsigned int bpc,
|
||
|
|
unsigned int CFG, struct cmdq_pkt *handle)
|
||
|
|
{
|
||
|
|
/* If bpc equal to 0, the dithering function didn't be enabled */
|
||
|
|
if (bpc == 0)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (bpc >= MTK_MIN_BPC) {
|
||
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
||
|
|
comp->regs_pa + DISP_DITHER_5, 0, ~0);
|
||
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
||
|
|
comp->regs_pa + DISP_DITHER_7, 0, ~0);
|
||
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
||
|
|
comp->regs_pa + DISP_DITHER_15,
|
||
|
|
DITHER_LSB_ERR_SHIFT_R(MTK_MAX_BPC - bpc) |
|
||
|
|
DITHER_ADD_LSHIFT_R(MTK_MAX_BPC - bpc) |
|
||
|
|
DITHER_NEW_BIT_MODE,
|
||
|
|
~0);
|
||
|
|
cmdq_pkt_write(
|
||
|
|
handle, comp->cmdq_base, comp->regs_pa + DISP_DITHER_16,
|
||
|
|
DITHER_LSB_ERR_SHIFT_B(MTK_MAX_BPC - bpc) |
|
||
|
|
DITHER_ADD_LSHIFT_B(MTK_MAX_BPC - bpc) |
|
||
|
|
DITHER_LSB_ERR_SHIFT_G(MTK_MAX_BPC - bpc) |
|
||
|
|
DITHER_ADD_LSHIFT_G(MTK_MAX_BPC - bpc),
|
||
|
|
~0);
|
||
|
|
cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + CFG,
|
||
|
|
DISP_DITHERING, ~0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
static void mtk_od_config(struct mtk_ddp_comp *comp, struct mtk_ddp_config *cfg,
|
||
|
|
struct cmdq_pkt *handle)
|
||
|
|
{
|
||
|
|
cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_OD_SIZE,
|
||
|
|
cfg->w << 16 | cfg->h, ~0);
|
||
|
|
cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_OD_CFG,
|
||
|
|
OD_RELAYMODE, ~0);
|
||
|
|
mtk_dither_set(comp, cfg->bpc, DISP_OD_CFG, handle);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void mtk_od_start(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle)
|
||
|
|
{
|
||
|
|
cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_OD_EN, 1,
|
||
|
|
~0);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void mtk_ufoe_config(struct mtk_ddp_comp *comp,
|
||
|
|
struct mtk_ddp_config *cfg, struct cmdq_pkt *handle)
|
||
|
|
{
|
||
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
||
|
|
comp->regs_pa + DISP_REG_UFO_WIDTH, cfg->w, ~0);
|
||
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
||
|
|
comp->regs_pa + DISP_REG_UFO_HEIGHT, cfg->h, ~0);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void mtk_ufoe_start(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle)
|
||
|
|
{
|
||
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
||
|
|
comp->regs_pa + DISP_REG_UFO_START, UFO_BYPASS, ~0);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void mtk_split_start(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle)
|
||
|
|
{
|
||
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
||
|
|
comp->regs_pa + DISP_REG_SPLIT_START, 1, ~0);
|
||
|
|
}
|
||
|
|
|
||
|
|
static const struct mtk_ddp_comp_funcs ddp_od = {
|
||
|
|
.config = mtk_od_config, .start = mtk_od_start,
|
||
|
|
};
|
||
|
|
|
||
|
|
static const struct mtk_ddp_comp_funcs ddp_ufoe = {
|
||
|
|
.start = mtk_ufoe_start, .config = mtk_ufoe_config,
|
||
|
|
};
|
||
|
|
|
||
|
|
static const struct mtk_ddp_comp_funcs ddp_split = {
|
||
|
|
.start = mtk_split_start,
|
||
|
|
};
|
||
|
|
|
||
|
|
static const char *const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
|
||
|
|
[MTK_DISP_OVL] = "ovl",
|
||
|
|
[MTK_DISP_RDMA] = "rdma",
|
||
|
|
[MTK_DISP_WDMA] = "wdma",
|
||
|
|
[MTK_DISP_COLOR] = "color",
|
||
|
|
[MTK_DISP_CCORR] = "ccorr",
|
||
|
|
[MTK_DISP_AAL] = "aal",
|
||
|
|
[MTK_DISP_GAMMA] = "gamma",
|
||
|
|
[MTK_DISP_DITHER] = "dither",
|
||
|
|
[MTK_DISP_UFOE] = "ufoe",
|
||
|
|
[MTK_DSI] = "dsi",
|
||
|
|
[MTK_DP_INTF] = "dp_intf",
|
||
|
|
[MTK_DPI] = "dpi",
|
||
|
|
[MTK_DISP_PWM] = "pwm",
|
||
|
|
[MTK_DISP_MUTEX] = "mutex",
|
||
|
|
[MTK_DISP_OD] = "od",
|
||
|
|
[MTK_DISP_BLS] = "bls",
|
||
|
|
[MTK_DISP_RSZ] = "rsz",
|
||
|
|
[MTK_DISP_POSTMASK] = "postmask",
|
||
|
|
[MTK_DMDP_RDMA] = "mrdma",
|
||
|
|
[MTK_DMDP_HDR] = "mhdr",
|
||
|
|
[MTK_DMDP_AAL] = "maal",
|
||
|
|
[MTK_DMDP_RSZ] = "mrsz",
|
||
|
|
[MTK_DMDP_TDSHP] = "mtdshp",
|
||
|
|
[MTK_DISP_DSC] = "dsc",
|
||
|
|
[MTK_DISP_MERGE] = "merge",
|
||
|
|
[MTK_DISP_DPTX] = "dptx",
|
||
|
|
[MTK_DISP_VIRTUAL] = "virtual",
|
||
|
|
};
|
||
|
|
|
||
|
|
struct mtk_ddp_comp_match {
|
||
|
|
enum mtk_ddp_comp_id index;
|
||
|
|
enum mtk_ddp_comp_type type;
|
||
|
|
int alias_id;
|
||
|
|
const struct mtk_ddp_comp_funcs *funcs;
|
||
|
|
bool is_output;
|
||
|
|
};
|
||
|
|
|
||
|
|
static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
|
||
|
|
{DDP_COMPONENT_AAL0, MTK_DISP_AAL, 0, NULL, 0},
|
||
|
|
{DDP_COMPONENT_AAL1, MTK_DISP_AAL, 1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_BLS, MTK_DISP_BLS, 0, NULL, 0},
|
||
|
|
{DDP_COMPONENT_CCORR0, MTK_DISP_CCORR, 0, NULL, 0},
|
||
|
|
{DDP_COMPONENT_CCORR1, MTK_DISP_CCORR, 1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_COLOR0, MTK_DISP_COLOR, 0, NULL, 0},
|
||
|
|
{DDP_COMPONENT_COLOR1, MTK_DISP_COLOR, 1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_COLOR2, MTK_DISP_COLOR, 2, NULL, 0},
|
||
|
|
{DDP_COMPONENT_DITHER0, MTK_DISP_DITHER, 0, NULL, 0},
|
||
|
|
{DDP_COMPONENT_DITHER1, MTK_DISP_DITHER, 1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_DPI0, MTK_DPI, 0, NULL, 1},
|
||
|
|
{DDP_COMPONENT_DPI1, MTK_DPI, 1, NULL, 1},
|
||
|
|
{DDP_COMPONENT_DSI0, MTK_DSI, 0, NULL, 1},
|
||
|
|
{DDP_COMPONENT_DSI1, MTK_DSI, 1, NULL, 1},
|
||
|
|
{DDP_COMPONENT_GAMMA0, MTK_DISP_GAMMA, 0, NULL, 0},
|
||
|
|
{DDP_COMPONENT_GAMMA1, MTK_DISP_GAMMA, 1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_OD, MTK_DISP_OD, 0, &ddp_od, 0},
|
||
|
|
{DDP_COMPONENT_OD1, MTK_DISP_OD, 1, &ddp_od, 0},
|
||
|
|
{DDP_COMPONENT_OVL0, MTK_DISP_OVL, 0, NULL, 0},
|
||
|
|
{DDP_COMPONENT_OVL1, MTK_DISP_OVL, 1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_OVL2, MTK_DISP_OVL, 2, NULL, 0},
|
||
|
|
{DDP_COMPONENT_OVL0_2L, MTK_DISP_OVL, 3, NULL, 0},
|
||
|
|
{DDP_COMPONENT_OVL1_2L, MTK_DISP_OVL, 4, NULL, 0},
|
||
|
|
{DDP_COMPONENT_OVL2_2L, MTK_DISP_OVL, 5, NULL, 0},
|
||
|
|
{DDP_COMPONENT_OVL3_2L, MTK_DISP_OVL, 6, NULL, 0},
|
||
|
|
{DDP_COMPONENT_OVL0_2L_VIRTUAL0, MTK_DISP_VIRTUAL, -1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_OVL1_2L_VIRTUAL0, MTK_DISP_VIRTUAL, -1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_OVL0_VIRTUAL0, MTK_DISP_VIRTUAL, -1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_OVL1_VIRTUAL0, MTK_DISP_VIRTUAL, -1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_OVL0_OVL0_2L_VIRTUAL0, MTK_DISP_VIRTUAL, -1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_PWM0, MTK_DISP_PWM, 0, NULL, 0},
|
||
|
|
{DDP_COMPONENT_PWM1, MTK_DISP_PWM, 1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_PWM2, MTK_DISP_PWM, 2, NULL, 0},
|
||
|
|
{DDP_COMPONENT_RDMA0, MTK_DISP_RDMA, 0, NULL, 0},
|
||
|
|
{DDP_COMPONENT_RDMA1, MTK_DISP_RDMA, 1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_RDMA2, MTK_DISP_RDMA, 2, NULL, 0},
|
||
|
|
{DDP_COMPONENT_RDMA3, MTK_DISP_RDMA, 3, NULL, 0},
|
||
|
|
{DDP_COMPONENT_RDMA4, MTK_DISP_RDMA, 4, NULL, 0},
|
||
|
|
{DDP_COMPONENT_RDMA5, MTK_DISP_RDMA, 5, NULL, 0},
|
||
|
|
{DDP_COMPONENT_RDMA0_VIRTUAL0, MTK_DISP_VIRTUAL, -1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_RDMA1_VIRTUAL0, MTK_DISP_VIRTUAL, -1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_RDMA2_VIRTUAL0, MTK_DISP_VIRTUAL, -1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_RSZ0, MTK_DISP_RSZ, 0, NULL, 0},
|
||
|
|
{DDP_COMPONENT_RSZ1, MTK_DISP_RSZ, 1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_UFOE, MTK_DISP_UFOE, 0, &ddp_ufoe, 0},
|
||
|
|
{DDP_COMPONENT_WDMA0, MTK_DISP_WDMA, 0, NULL, 1},
|
||
|
|
{DDP_COMPONENT_WDMA1, MTK_DISP_WDMA, 1, NULL, 1},
|
||
|
|
{DDP_COMPONENT_UFBC_WDMA0, MTK_DISP_WDMA, 2, NULL, 1},
|
||
|
|
{DDP_COMPONENT_WDMA_VIRTUAL0, MTK_DISP_VIRTUAL, -1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_WDMA_VIRTUAL1, MTK_DISP_VIRTUAL, -1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_POSTMASK0, MTK_DISP_POSTMASK, 0, NULL, 0},
|
||
|
|
{DDP_COMPONENT_POSTMASK1, MTK_DISP_POSTMASK, 1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_DMDP_RDMA0, MTK_DMDP_RDMA, 0, NULL, 0},
|
||
|
|
{DDP_COMPONENT_DMDP_HDR0, MTK_DMDP_HDR, 0, NULL, 0},
|
||
|
|
{DDP_COMPONENT_DMDP_AAL0, MTK_DMDP_AAL, 0, NULL, 0},
|
||
|
|
{DDP_COMPONENT_DMDP_RSZ0, MTK_DMDP_RSZ, 0, NULL, 0},
|
||
|
|
{DDP_COMPONENT_DMDP_TDSHP0, MTK_DMDP_TDSHP, 0, NULL, 0},
|
||
|
|
{DDP_COMPONENT_DMDP_RDMA1, MTK_DMDP_RDMA, 1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_DMDP_HDR1, MTK_DMDP_HDR, 1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_DMDP_AAL1, MTK_DMDP_AAL, 1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_DMDP_RSZ1, MTK_DMDP_RSZ, 1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_DMDP_TDSHP1, MTK_DMDP_TDSHP, 1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_DSC0, MTK_DISP_DSC, 0, NULL, 0},
|
||
|
|
{DDP_COMPONENT_MERGE0, MTK_DISP_MERGE, 0, NULL, 0},
|
||
|
|
{DDP_COMPONENT_DPTX, MTK_DISP_DPTX, 0, NULL, 1},
|
||
|
|
{DDP_COMPONENT_DP_INTF0, MTK_DP_INTF, 0, NULL, 1},
|
||
|
|
{DDP_COMPONENT_RDMA4_VIRTUAL0, MTK_DISP_VIRTUAL, -1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_RDMA5_VIRTUAL0, MTK_DISP_VIRTUAL, -1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_MERGE1, MTK_DISP_MERGE, 1, NULL, 0},
|
||
|
|
{DDP_COMPONENT_SPR0_VIRTUAL, MTK_DISP_VIRTUAL, -1, NULL, 0},
|
||
|
|
};
|
||
|
|
|
||
|
|
bool mtk_ddp_comp_is_output(struct mtk_ddp_comp *comp)
|
||
|
|
{
|
||
|
|
if (comp->id < 0 || comp->id >= DDP_COMPONENT_ID_MAX)
|
||
|
|
return false;
|
||
|
|
|
||
|
|
return mtk_ddp_matches[comp->id].is_output;
|
||
|
|
}
|
||
|
|
|
||
|
|
void mtk_ddp_comp_get_name(struct mtk_ddp_comp *comp, char *buf, int buf_len)
|
||
|
|
{
|
||
|
|
int r;
|
||
|
|
|
||
|
|
if (comp->id < 0 || comp->id >= DDP_COMPONENT_ID_MAX) {
|
||
|
|
DDPPR_ERR("%s(), invalid id %d, set buf to 0\n",
|
||
|
|
__func__, comp->id);
|
||
|
|
memset(buf, 0, buf_len);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (buf_len > sizeof(buf))
|
||
|
|
buf_len = sizeof(buf);
|
||
|
|
if (mtk_ddp_matches[comp->id].type < 0) {
|
||
|
|
DDPPR_ERR("%s invalid type\n", __func__);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
r = snprintf(buf, buf_len, "%s%d",
|
||
|
|
mtk_ddp_comp_stem[mtk_ddp_matches[comp->id].type],
|
||
|
|
mtk_ddp_matches[comp->id].alias_id);
|
||
|
|
if (r < 0) {
|
||
|
|
/* Handle snprintf() error */
|
||
|
|
DDPPR_ERR("snprintf error\n");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
int mtk_ddp_comp_get_type(enum mtk_ddp_comp_id comp_id)
|
||
|
|
{
|
||
|
|
if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX)
|
||
|
|
return -EINVAL;
|
||
|
|
|
||
|
|
return mtk_ddp_matches[comp_id].type;
|
||
|
|
}
|
||
|
|
|
||
|
|
static bool mtk_drm_find_comp_in_ddp(struct mtk_ddp_comp ddp_comp,
|
||
|
|
const struct mtk_crtc_path_data *path_data)
|
||
|
|
{
|
||
|
|
unsigned int i, j, ddp_mode;
|
||
|
|
const enum mtk_ddp_comp_id *path = NULL;
|
||
|
|
|
||
|
|
if (path_data == NULL)
|
||
|
|
return false;
|
||
|
|
|
||
|
|
for (ddp_mode = 0U; ddp_mode < DDP_MODE_NR; ddp_mode++)
|
||
|
|
for (i = 0U; i < DDP_PATH_NR; i++) {
|
||
|
|
path = path_data->path[ddp_mode][i];
|
||
|
|
for (j = 0U; j < path_data->path_len[ddp_mode][i]; j++)
|
||
|
|
if (ddp_comp.id == path[j])
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
enum mtk_ddp_comp_id mtk_ddp_comp_get_id(struct device_node *node,
|
||
|
|
enum mtk_ddp_comp_type comp_type)
|
||
|
|
{
|
||
|
|
int id;
|
||
|
|
int i;
|
||
|
|
|
||
|
|
if (comp_type < 0)
|
||
|
|
return -EINVAL;
|
||
|
|
|
||
|
|
id = of_alias_get_id(node, mtk_ddp_comp_stem[comp_type]);
|
||
|
|
|
||
|
|
DDPINFO("id:%d, comp_type:%d\n", id, comp_type);
|
||
|
|
for (i = 0; i < ARRAY_SIZE(mtk_ddp_matches); i++) {
|
||
|
|
if (comp_type == mtk_ddp_matches[i].type &&
|
||
|
|
(id < 0 || id == mtk_ddp_matches[i].alias_id))
|
||
|
|
return mtk_ddp_matches[i].index;
|
||
|
|
}
|
||
|
|
|
||
|
|
return -EINVAL;
|
||
|
|
}
|
||
|
|
|
||
|
|
struct mtk_ddp_comp *mtk_ddp_comp_find_by_id(struct drm_crtc *crtc,
|
||
|
|
enum mtk_ddp_comp_id comp_id)
|
||
|
|
{
|
||
|
|
unsigned int i = 0, j = 0, ddp_mode = 0;
|
||
|
|
struct mtk_drm_crtc *mtk_crtc =
|
||
|
|
container_of(crtc, struct mtk_drm_crtc, base);
|
||
|
|
struct mtk_ddp_comp *comp;
|
||
|
|
|
||
|
|
for_each_comp_in_all_crtc_mode(comp, mtk_crtc, i, j,
|
||
|
|
ddp_mode)
|
||
|
|
if (comp_id == comp->id)
|
||
|
|
return comp;
|
||
|
|
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void mtk_ddp_comp_set_larb(struct device *dev, struct device_node *node,
|
||
|
|
struct mtk_ddp_comp *comp)
|
||
|
|
{
|
||
|
|
int ret;
|
||
|
|
struct device_node *larb_node = NULL;
|
||
|
|
struct platform_device *larb_pdev = NULL;
|
||
|
|
enum mtk_ddp_comp_type type = mtk_ddp_comp_get_type(comp->id);
|
||
|
|
unsigned int larb_id;
|
||
|
|
|
||
|
|
comp->larb_dev = NULL;
|
||
|
|
|
||
|
|
larb_node = of_parse_phandle(node, "mediatek,larb", 0);
|
||
|
|
|
||
|
|
if (larb_node) {
|
||
|
|
larb_pdev = of_find_device_by_node(larb_node);
|
||
|
|
if (larb_pdev)
|
||
|
|
comp->larb_dev = &larb_pdev->dev;
|
||
|
|
of_node_put(larb_node);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!comp->larb_dev)
|
||
|
|
return;
|
||
|
|
|
||
|
|
ret = of_property_read_u32(node,
|
||
|
|
"mediatek,smi-id", &larb_id);
|
||
|
|
if (ret) {
|
||
|
|
dev_err(comp->larb_dev,
|
||
|
|
"read smi-id failed:%d\n", ret);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
comp->larb_id = larb_id;
|
||
|
|
|
||
|
|
/* check if this module need larb_dev */
|
||
|
|
if (type == MTK_DISP_OVL || type == MTK_DISP_RDMA ||
|
||
|
|
type == MTK_DISP_WDMA || type == MTK_DISP_POSTMASK) {
|
||
|
|
dev_warn(dev, "%s: %s need larb device\n", __func__,
|
||
|
|
mtk_dump_comp_str(comp));
|
||
|
|
DDPPR_ERR("%s: smi-id:%d\n", mtk_dump_comp_str(comp),
|
||
|
|
comp->larb_id);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm,
|
||
|
|
struct mtk_ddp_comp ddp_comp)
|
||
|
|
{
|
||
|
|
struct mtk_drm_private *private = drm->dev_private;
|
||
|
|
unsigned int ret;
|
||
|
|
|
||
|
|
if (mtk_drm_find_comp_in_ddp(ddp_comp, private->data->main_path_data) ==
|
||
|
|
true) {
|
||
|
|
ret = BIT(0);
|
||
|
|
} else if (mtk_drm_find_comp_in_ddp(
|
||
|
|
ddp_comp, private->data->ext_path_data) == true) {
|
||
|
|
ret = BIT(1);
|
||
|
|
} else if (mtk_drm_find_comp_in_ddp(
|
||
|
|
ddp_comp, private->data->third_path_data) == true) {
|
||
|
|
ret = BIT(2);
|
||
|
|
} else {
|
||
|
|
DRM_INFO("Failed to find comp in ddp table\n");
|
||
|
|
ret = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
int mtk_ddp_comp_init(struct device *dev, struct device_node *node,
|
||
|
|
struct mtk_ddp_comp *comp, enum mtk_ddp_comp_id comp_id,
|
||
|
|
const struct mtk_ddp_comp_funcs *funcs)
|
||
|
|
{
|
||
|
|
enum mtk_ddp_comp_type type;
|
||
|
|
struct platform_device *comp_pdev = NULL;
|
||
|
|
struct resource res;
|
||
|
|
|
||
|
|
DDPINFO("%s+\n", __func__);
|
||
|
|
|
||
|
|
if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX)
|
||
|
|
return -EINVAL;
|
||
|
|
|
||
|
|
type = mtk_ddp_matches[comp_id].type;
|
||
|
|
|
||
|
|
comp->id = comp_id;
|
||
|
|
comp->funcs = funcs ?: mtk_ddp_matches[comp_id].funcs;
|
||
|
|
comp->dev = dev;
|
||
|
|
|
||
|
|
/* get the first clk in the device node */
|
||
|
|
comp->clk = of_clk_get(node, 0);
|
||
|
|
if (IS_ERR(comp->clk)) {
|
||
|
|
comp->clk = NULL;
|
||
|
|
DDPPR_ERR("comp:%d get clock fail!\n", comp_id);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (comp_id == DDP_COMPONENT_BLS || comp_id == DDP_COMPONENT_PWM0) {
|
||
|
|
comp->regs_pa = 0;
|
||
|
|
comp->regs = NULL;
|
||
|
|
comp->irq = 0;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (of_address_to_resource(node, 0, &res) != 0) {
|
||
|
|
dev_err(dev, "Missing reg in %s node\n", node->full_name);
|
||
|
|
return -EINVAL;
|
||
|
|
}
|
||
|
|
|
||
|
|
comp->regs_pa = res.start;
|
||
|
|
|
||
|
|
if (comp_id == DDP_COMPONENT_DPI0 || comp_id == DDP_COMPONENT_DPI1 ||
|
||
|
|
comp_id == DDP_COMPONENT_DSI0 || comp_id == DDP_COMPONENT_DSI1)
|
||
|
|
comp->irq = 0;
|
||
|
|
else
|
||
|
|
comp->irq = of_irq_get(node, 0);
|
||
|
|
|
||
|
|
comp->regs = of_iomap(node, 0);
|
||
|
|
DDPINFO("[DRM]regs_pa:0x%lx, regs:0x%p, node:%s\n",
|
||
|
|
(unsigned long)comp->regs_pa, comp->regs, node->full_name);
|
||
|
|
|
||
|
|
/* handle cmdq related resources */
|
||
|
|
comp_pdev = of_find_device_by_node(node);
|
||
|
|
if (!comp_pdev) {
|
||
|
|
dev_warn(dev, "Waiting for comp device %s\n", node->full_name);
|
||
|
|
return -EPROBE_DEFER;
|
||
|
|
}
|
||
|
|
|
||
|
|
comp->cmdq_base = cmdq_register_device(&comp_pdev->dev);
|
||
|
|
|
||
|
|
#if 0
|
||
|
|
/* TODO: if no subsys id, use 99 instead. CMDQ owner would define 99 in
|
||
|
|
* DTS afterward.
|
||
|
|
*/
|
||
|
|
if (of_property_read_u8(node, "my_subsys_id", &comp->cmdq_subsys))
|
||
|
|
comp->cmdq_subsys = 99;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
/* handle larb resources */
|
||
|
|
mtk_ddp_comp_set_larb(dev, node, comp);
|
||
|
|
|
||
|
|
DDPINFO("%s-\n", __func__);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int mtk_ddp_comp_register(struct drm_device *drm, struct mtk_ddp_comp *comp)
|
||
|
|
{
|
||
|
|
struct mtk_drm_private *private = drm->dev_private;
|
||
|
|
|
||
|
|
if (private->ddp_comp[comp->id])
|
||
|
|
return -EBUSY;
|
||
|
|
|
||
|
|
if (comp->id < 0)
|
||
|
|
return -EINVAL;
|
||
|
|
|
||
|
|
private->ddp_comp[comp->id] = comp;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
void mtk_ddp_comp_unregister(struct drm_device *drm, struct mtk_ddp_comp *comp)
|
||
|
|
{
|
||
|
|
struct mtk_drm_private *private = drm->dev_private;
|
||
|
|
|
||
|
|
if (comp && comp->id >= 0 && comp->id < DDP_COMPONENT_ID_MAX)
|
||
|
|
private->ddp_comp[comp->id] = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
void mtk_ddp_comp_clk_prepare(struct mtk_ddp_comp *comp)
|
||
|
|
{
|
||
|
|
int ret;
|
||
|
|
|
||
|
|
if (comp == NULL)
|
||
|
|
return;
|
||
|
|
|
||
|
|
#ifdef CONFIG_MTK_SMI_EXT
|
||
|
|
if (comp->larb_dev)
|
||
|
|
smi_bus_prepare_enable(comp->larb_id, MTK_DDP_COMP_USER);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if (comp->clk) {
|
||
|
|
ret = clk_prepare_enable(comp->clk);
|
||
|
|
if (ret)
|
||
|
|
DDPPR_ERR("clk prepare enable failed:%s\n",
|
||
|
|
mtk_dump_comp_str(comp));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void mtk_ddp_comp_clk_unprepare(struct mtk_ddp_comp *comp)
|
||
|
|
{
|
||
|
|
if (comp == NULL)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (comp->clk)
|
||
|
|
clk_disable_unprepare(comp->clk);
|
||
|
|
|
||
|
|
#ifdef CONFIG_MTK_SMI_EXT
|
||
|
|
if (comp->larb_dev)
|
||
|
|
smi_bus_disable_unprepare(comp->larb_id, MTK_DDP_COMP_USER);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef CONFIG_MTK_IOMMU_V2
|
||
|
|
static enum mtk_iommu_callback_ret_t
|
||
|
|
mtk_ddp_m4u_callback(int port, unsigned long mva,
|
||
|
|
void *data)
|
||
|
|
{
|
||
|
|
struct mtk_ddp_comp *comp = (struct mtk_ddp_comp *)data;
|
||
|
|
|
||
|
|
DDPPR_ERR("fault call port=%d, mva=0x%lx, data=0x%p\n", port, mva,
|
||
|
|
data);
|
||
|
|
|
||
|
|
if (comp && comp->mtk_crtc) {
|
||
|
|
mtk_drm_crtc_analysis(&(comp->mtk_crtc->base));
|
||
|
|
mtk_drm_crtc_dump(&(comp->mtk_crtc->base));
|
||
|
|
}
|
||
|
|
|
||
|
|
return MTK_IOMMU_CALLBACK_HANDLED;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#define GET_M4U_PORT 0x1F
|
||
|
|
void mtk_ddp_comp_iommu_enable(struct mtk_ddp_comp *comp,
|
||
|
|
struct cmdq_pkt *handle)
|
||
|
|
{
|
||
|
|
int port, index, ret;
|
||
|
|
struct resource res;
|
||
|
|
|
||
|
|
if (!comp->dev || !comp->larb_dev)
|
||
|
|
return;
|
||
|
|
|
||
|
|
index = 0;
|
||
|
|
while (1) {
|
||
|
|
ret = of_property_read_u32_index(comp->dev->of_node,
|
||
|
|
"iommus", index * 2 + 1, &port);
|
||
|
|
if (ret < 0)
|
||
|
|
break;
|
||
|
|
|
||
|
|
#ifdef CONFIG_MTK_IOMMU_V2
|
||
|
|
mtk_iommu_register_fault_callback(
|
||
|
|
port, (mtk_iommu_fault_callback_t)mtk_ddp_m4u_callback,
|
||
|
|
(void *)comp);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
port &= (unsigned int)GET_M4U_PORT;
|
||
|
|
if (of_address_to_resource(comp->larb_dev->of_node, 0, &res) !=
|
||
|
|
0) {
|
||
|
|
dev_err(comp->dev, "Missing reg in %s node\n",
|
||
|
|
comp->larb_dev->of_node->full_name);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
#ifndef CONFIG_MTK_DISPLAY_M4U
|
||
|
|
//bypass m4u
|
||
|
|
cmdq_pkt_write(handle, NULL,
|
||
|
|
res.start + SMI_LARB_NON_SEC_CON + port * 4, 0,
|
||
|
|
0x1);
|
||
|
|
#else
|
||
|
|
cmdq_pkt_write(handle, NULL,
|
||
|
|
res.start + SMI_LARB_NON_SEC_CON + port * 4, 0x1,
|
||
|
|
0x1);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
index++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void mt6779_mtk_sodi_config(struct drm_device *drm, enum mtk_ddp_comp_id id,
|
||
|
|
struct cmdq_pkt *handle, void *data)
|
||
|
|
{
|
||
|
|
struct mtk_drm_private *priv = drm->dev_private;
|
||
|
|
unsigned int val = 0, mask = 0;
|
||
|
|
bool en = *((bool *)data);
|
||
|
|
|
||
|
|
if (id == DDP_COMPONENT_ID_MAX) { /* config when top clk on */
|
||
|
|
if (!en)
|
||
|
|
return;
|
||
|
|
val = 0x0F005506;
|
||
|
|
mask = 0xFFFFFFFF;
|
||
|
|
} else if (id == DDP_COMPONENT_RDMA0) {
|
||
|
|
mask |= (BIT(9) + BIT(16));
|
||
|
|
val |= (((!(unsigned int)en) << 9) + ((en) << 16));
|
||
|
|
} else if (id == DDP_COMPONENT_RDMA1) {
|
||
|
|
mask |= (BIT(11) + BIT(17));
|
||
|
|
val |= (((!(unsigned int)en) << 11) + ((en) << 17));
|
||
|
|
} else if (id == DDP_COMPONENT_WDMA0) {
|
||
|
|
mask |= BIT(18);
|
||
|
|
val |= ((en) << 18);
|
||
|
|
} else
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (handle == NULL) {
|
||
|
|
unsigned int v = (readl(priv->config_regs + 0xF8) & (~mask));
|
||
|
|
|
||
|
|
v += (val & mask);
|
||
|
|
writel_relaxed(v, priv->config_regs + 0xF8);
|
||
|
|
} else
|
||
|
|
cmdq_pkt_write(handle, NULL, priv->config_regs_pa + 0xF8, val,
|
||
|
|
mask);
|
||
|
|
}
|
||
|
|
|
||
|
|
void mt6853_mtk_sodi_config(struct drm_device *drm, enum mtk_ddp_comp_id id,
|
||
|
|
struct cmdq_pkt *handle, void *data)
|
||
|
|
{
|
||
|
|
struct mtk_drm_private *priv = drm->dev_private;
|
||
|
|
unsigned int sodi_req_val = 0, sodi_req_mask = 0;
|
||
|
|
unsigned int emi_req_val = 0, emi_req_mask = 0;
|
||
|
|
bool en = *((bool *)data);
|
||
|
|
|
||
|
|
if (id == DDP_COMPONENT_ID_MAX) { /* config when top clk on */
|
||
|
|
if (!en)
|
||
|
|
return;
|
||
|
|
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
0, MT6873_SODI_REQ_SEL_ALL);
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
0, MT6873_SODI_REQ_VAL_ALL);
|
||
|
|
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
1, SODI_REQ_SEL_RDMA0_PD_MODE);
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
1, SODI_REQ_VAL_RDMA0_PD_MODE);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0x1, HRT_URGENT_CTL_SEL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0x1, HRT_URGENT_CTL_SEL_WDMA0);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, HRT_URGENT_CTL_VAL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, HRT_URGENT_CTL_VAL_WDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, HRT_URGENT_CTL_VAL_RDMA4);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, HRT_URGENT_CTL_VAL_MDP_RDMA4);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, DVFS_HALT_MASK_SEL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, DVFS_HALT_MASK_SEL_RDMA4);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, DVFS_HALT_MASK_SEL_WDMA0);
|
||
|
|
} else if (id == DDP_COMPONENT_RDMA0) {
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask, (!en),
|
||
|
|
SODI_REQ_SEL_RDMA0_CG_MODE);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, (!en),
|
||
|
|
HRT_URGENT_CTL_SEL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, en,
|
||
|
|
DVFS_HALT_MASK_SEL_RDMA0);
|
||
|
|
} else if (id == DDP_COMPONENT_WDMA0) {
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, (!en),
|
||
|
|
HRT_URGENT_CTL_SEL_WDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, en,
|
||
|
|
DVFS_HALT_MASK_SEL_WDMA0);
|
||
|
|
} else
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (handle == NULL) {
|
||
|
|
unsigned int v;
|
||
|
|
|
||
|
|
v = (readl(priv->config_regs + MMSYS_SODI_REQ_MASK)
|
||
|
|
& (~sodi_req_mask));
|
||
|
|
v += (sodi_req_val & sodi_req_mask);
|
||
|
|
writel_relaxed(v, priv->config_regs + MMSYS_SODI_REQ_MASK);
|
||
|
|
|
||
|
|
v = (readl(priv->config_regs + MMSYS_EMI_REQ_CTL)
|
||
|
|
& (~emi_req_mask));
|
||
|
|
v += (emi_req_val & emi_req_mask);
|
||
|
|
writel_relaxed(v, priv->config_regs + MMSYS_EMI_REQ_CTL);
|
||
|
|
} else {
|
||
|
|
cmdq_pkt_write(handle, NULL, priv->config_regs_pa +
|
||
|
|
MMSYS_SODI_REQ_MASK, sodi_req_val, sodi_req_mask);
|
||
|
|
cmdq_pkt_write(handle, NULL, priv->config_regs_pa +
|
||
|
|
MMSYS_EMI_REQ_CTL, emi_req_val, emi_req_mask);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void mt6781_mtk_sodi_config(struct drm_device *drm, enum mtk_ddp_comp_id id,
|
||
|
|
struct cmdq_pkt *handle, void *data)
|
||
|
|
{
|
||
|
|
struct mtk_drm_private *priv = drm->dev_private;
|
||
|
|
unsigned int sodi_req_val = 0, sodi_req_mask = 0;
|
||
|
|
unsigned int emi_req_val = 0, emi_req_mask = 0;
|
||
|
|
bool en = *((bool *)data);
|
||
|
|
|
||
|
|
if (id == DDP_COMPONENT_ID_MAX) { /* config when top clk on */
|
||
|
|
if (!en)
|
||
|
|
return;
|
||
|
|
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
0, MT6873_SODI_REQ_SEL_ALL);
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
0, MT6873_SODI_REQ_VAL_ALL);
|
||
|
|
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
1, SODI_REQ_SEL_RDMA0_PD_MODE);
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
1, SODI_REQ_VAL_RDMA0_PD_MODE);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0x1, HRT_URGENT_CTL_SEL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0x1, HRT_URGENT_CTL_SEL_WDMA0);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, HRT_URGENT_CTL_VAL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, HRT_URGENT_CTL_VAL_WDMA0);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, DVFS_HALT_MASK_SEL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, DVFS_HALT_MASK_SEL_WDMA0);
|
||
|
|
} else if (id == DDP_COMPONENT_RDMA0) {
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask, (!en),
|
||
|
|
SODI_REQ_SEL_RDMA0_CG_MODE);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, (!en),
|
||
|
|
HRT_URGENT_CTL_SEL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, en,
|
||
|
|
DVFS_HALT_MASK_SEL_RDMA0);
|
||
|
|
} else if (id == DDP_COMPONENT_WDMA0) {
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, (!en),
|
||
|
|
HRT_URGENT_CTL_SEL_WDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, en,
|
||
|
|
DVFS_HALT_MASK_SEL_WDMA0);
|
||
|
|
} else
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (handle == NULL) {
|
||
|
|
unsigned int v;
|
||
|
|
|
||
|
|
v = (readl(priv->config_regs + MMSYS_SODI_REQ_MASK)
|
||
|
|
& (~sodi_req_mask));
|
||
|
|
v += (sodi_req_val & sodi_req_mask);
|
||
|
|
writel_relaxed(v, priv->config_regs + MMSYS_SODI_REQ_MASK);
|
||
|
|
|
||
|
|
v = (readl(priv->config_regs + MMSYS_EMI_REQ_CTL)
|
||
|
|
& (~emi_req_mask));
|
||
|
|
v += (emi_req_val & emi_req_mask);
|
||
|
|
writel_relaxed(v, priv->config_regs + MMSYS_EMI_REQ_CTL);
|
||
|
|
if (priv->data->bypass_infra_ddr_control) {
|
||
|
|
if (!IS_ERR(priv->infra_regs)) {
|
||
|
|
v = (readl(priv->infra_regs + MT6781_INFRA_DISP_DDR_CTL)
|
||
|
|
| MT6781_INFRA_DISP_DDR_MASK);
|
||
|
|
writel_relaxed(v, priv->infra_regs + MT6781_INFRA_DISP_DDR_CTL);
|
||
|
|
} else
|
||
|
|
DDPINFO("%s: failed to disable infra ddr control\n", __func__);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
cmdq_pkt_write(handle, NULL, priv->config_regs_pa +
|
||
|
|
MMSYS_SODI_REQ_MASK, sodi_req_val, sodi_req_mask);
|
||
|
|
cmdq_pkt_write(handle, NULL, priv->config_regs_pa +
|
||
|
|
MMSYS_EMI_REQ_CTL, emi_req_val, emi_req_mask);
|
||
|
|
if (priv->data->bypass_infra_ddr_control) {
|
||
|
|
if (priv->infra_regs_pa) {
|
||
|
|
cmdq_pkt_write(handle, NULL, priv->infra_regs_pa +
|
||
|
|
MT6781_INFRA_DISP_DDR_CTL,
|
||
|
|
MT6781_INFRA_DISP_DDR_MASK,
|
||
|
|
MT6781_INFRA_DISP_DDR_MASK);
|
||
|
|
} else
|
||
|
|
DDPINFO("%s: failed to disable infra ddr control\n", __func__);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void mt6877_mtk_sodi_config(struct drm_device *drm, enum mtk_ddp_comp_id id,
|
||
|
|
struct cmdq_pkt *handle, void *data)
|
||
|
|
{
|
||
|
|
struct mtk_drm_private *priv = drm->dev_private;
|
||
|
|
unsigned int sodi_req_val = 0, sodi_req_mask = 0;
|
||
|
|
unsigned int emi_req_val = 0, emi_req_mask = 0;
|
||
|
|
unsigned int infra_req_val1 = 0, infra_req_mask1 = 0;
|
||
|
|
unsigned int infra_req_val2 = 0, infra_req_mask2 = 0;
|
||
|
|
unsigned int infra_req_val3 = 0, infra_req_mask3 = 0;
|
||
|
|
unsigned int infra_req_val4 = 0, infra_req_mask4 = 0;
|
||
|
|
bool en = *((bool *)data);
|
||
|
|
|
||
|
|
if (id == DDP_COMPONENT_ID_MAX) { /* config when top clk on */
|
||
|
|
if (!en)
|
||
|
|
return;
|
||
|
|
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
0, MT6873_SODI_REQ_SEL_ALL);
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
0, MT6873_SODI_REQ_VAL_ALL);
|
||
|
|
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
1, SODI_REQ_SEL_RDMA0_PD_MODE);
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
1, SODI_REQ_VAL_RDMA0_PD_MODE);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0x1, HRT_URGENT_CTL_SEL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0x1, HRT_URGENT_CTL_SEL_WDMA0);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, HRT_URGENT_CTL_VAL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, HRT_URGENT_CTL_VAL_WDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, HRT_URGENT_CTL_VAL_RDMA4);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, HRT_URGENT_CTL_VAL_MDP_RDMA4);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, DVFS_HALT_MASK_SEL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, DVFS_HALT_MASK_SEL_RDMA4);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, DVFS_HALT_MASK_SEL_WDMA0);
|
||
|
|
} else if (id == DDP_COMPONENT_RDMA0) {
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask, (!en),
|
||
|
|
SODI_REQ_SEL_RDMA0_CG_MODE);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, (!en),
|
||
|
|
HRT_URGENT_CTL_SEL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, en,
|
||
|
|
DVFS_HALT_MASK_SEL_RDMA0);
|
||
|
|
} else if (id == DDP_COMPONENT_WDMA0) {
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, (!en),
|
||
|
|
HRT_URGENT_CTL_SEL_WDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, en,
|
||
|
|
DVFS_HALT_MASK_SEL_WDMA0);
|
||
|
|
} else
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (priv->data->bypass_infra_ddr_control) {
|
||
|
|
SET_VAL_MASK(infra_req_val1, infra_req_mask1,
|
||
|
|
0x0, MT6877_MM_PORT0_AXI_IDLE_ASYNC);
|
||
|
|
SET_VAL_MASK(infra_req_val2, infra_req_mask2,
|
||
|
|
0x0, MT6877_MM_PORT1_AXI_IDLE_ASYNC);
|
||
|
|
SET_VAL_MASK(infra_req_val3, infra_req_mask3,
|
||
|
|
0x0, MT6877_MDP2INFRA0_GALS_TX_AXI_IDLE);
|
||
|
|
SET_VAL_MASK(infra_req_val4, infra_req_mask4,
|
||
|
|
0x0, MT6877_COMM0_GALS_TX_AXI_IDLE);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (handle == NULL) {
|
||
|
|
unsigned int v;
|
||
|
|
|
||
|
|
v = (readl(priv->config_regs + MMSYS_SODI_REQ_MASK)
|
||
|
|
& (~sodi_req_mask));
|
||
|
|
v += (sodi_req_val & sodi_req_mask);
|
||
|
|
writel_relaxed(v, priv->config_regs + MMSYS_SODI_REQ_MASK);
|
||
|
|
|
||
|
|
v = (readl(priv->config_regs + MMSYS_EMI_REQ_CTL)
|
||
|
|
& (~emi_req_mask));
|
||
|
|
v += (emi_req_val & emi_req_mask);
|
||
|
|
writel_relaxed(v, priv->config_regs + MMSYS_EMI_REQ_CTL);
|
||
|
|
if (priv->data->bypass_infra_ddr_control) {
|
||
|
|
if (!IS_ERR(priv->infra_regs)) {
|
||
|
|
mtk_write_cpu_relaxed(
|
||
|
|
priv->infra_regs + MT6877_INFRA_MEM_IDLE_ASYNC_2,
|
||
|
|
infra_req_val1, infra_req_mask1);
|
||
|
|
mtk_write_cpu_relaxed(
|
||
|
|
priv->infra_regs + MT6877_INFRA_MEM_IDLE_ASYNC_2,
|
||
|
|
infra_req_val2, infra_req_mask2);
|
||
|
|
mtk_write_cpu_relaxed(
|
||
|
|
priv->infra_regs + MT6877_INFRA_MEM_IDLE_ASYNC_3,
|
||
|
|
infra_req_val3, infra_req_mask3);
|
||
|
|
mtk_write_cpu_relaxed(
|
||
|
|
priv->infra_regs + MT6877_INFRA_MEM_IDLE_ASYNC_3,
|
||
|
|
infra_req_val4, infra_req_mask4);
|
||
|
|
} else
|
||
|
|
DDPINFO("%s: failed to disable infra ddr control\n", __func__);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
cmdq_pkt_write(handle, NULL, priv->config_regs_pa +
|
||
|
|
MMSYS_SODI_REQ_MASK, sodi_req_val, sodi_req_mask);
|
||
|
|
cmdq_pkt_write(handle, NULL, priv->config_regs_pa +
|
||
|
|
MMSYS_EMI_REQ_CTL, emi_req_val, emi_req_mask);
|
||
|
|
if (priv->data->bypass_infra_ddr_control) {
|
||
|
|
if (priv->infra_regs_pa) {
|
||
|
|
cmdq_pkt_write(handle, NULL, priv->infra_regs_pa +
|
||
|
|
MT6877_INFRA_MEM_IDLE_ASYNC_2,
|
||
|
|
infra_req_val1, infra_req_mask1);
|
||
|
|
cmdq_pkt_write(handle, NULL, priv->infra_regs_pa +
|
||
|
|
MT6877_INFRA_MEM_IDLE_ASYNC_2,
|
||
|
|
infra_req_val2, infra_req_mask2);
|
||
|
|
cmdq_pkt_write(handle, NULL, priv->infra_regs_pa +
|
||
|
|
MT6877_INFRA_MEM_IDLE_ASYNC_3,
|
||
|
|
infra_req_val3, infra_req_mask3);
|
||
|
|
cmdq_pkt_write(handle, NULL, priv->infra_regs_pa +
|
||
|
|
MT6877_INFRA_MEM_IDLE_ASYNC_3,
|
||
|
|
infra_req_val4, infra_req_mask4);
|
||
|
|
} else
|
||
|
|
DDPINFO("%s: failed to disable infra ddr control\n", __func__);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void mt6833_mtk_sodi_config(struct drm_device *drm, enum mtk_ddp_comp_id id,
|
||
|
|
struct cmdq_pkt *handle, void *data)
|
||
|
|
{
|
||
|
|
struct mtk_drm_private *priv = drm->dev_private;
|
||
|
|
unsigned int sodi_req_val = 0, sodi_req_mask = 0;
|
||
|
|
unsigned int emi_req_val = 0, emi_req_mask = 0;
|
||
|
|
unsigned int infra_req_val = 0, infra_req_mask = 0;
|
||
|
|
bool en = *((bool *)data);
|
||
|
|
|
||
|
|
if (id == DDP_COMPONENT_ID_MAX) { /* config when top clk on */
|
||
|
|
if (!en)
|
||
|
|
return;
|
||
|
|
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
0, MT6873_SODI_REQ_SEL_ALL);
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
0, MT6873_SODI_REQ_VAL_ALL);
|
||
|
|
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
1, SODI_REQ_SEL_RDMA0_PD_MODE);
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
1, SODI_REQ_VAL_RDMA0_PD_MODE);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0x1, HRT_URGENT_CTL_SEL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0x1, HRT_URGENT_CTL_SEL_WDMA0);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, HRT_URGENT_CTL_VAL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, HRT_URGENT_CTL_VAL_WDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, HRT_URGENT_CTL_VAL_RDMA4);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, HRT_URGENT_CTL_VAL_MDP_RDMA4);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, DVFS_HALT_MASK_SEL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, DVFS_HALT_MASK_SEL_RDMA4);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, DVFS_HALT_MASK_SEL_WDMA0);
|
||
|
|
} else if (id == DDP_COMPONENT_RDMA0) {
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask, (!en),
|
||
|
|
SODI_REQ_SEL_RDMA0_CG_MODE);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, (!en),
|
||
|
|
HRT_URGENT_CTL_SEL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, en,
|
||
|
|
DVFS_HALT_MASK_SEL_RDMA0);
|
||
|
|
} else if (id == DDP_COMPONENT_WDMA0) {
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, (!en),
|
||
|
|
HRT_URGENT_CTL_SEL_WDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, en,
|
||
|
|
DVFS_HALT_MASK_SEL_WDMA0);
|
||
|
|
} else
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (priv->data->bypass_infra_ddr_control)
|
||
|
|
SET_VAL_MASK(infra_req_val, infra_req_mask,
|
||
|
|
0x0, MT6833_INFRA_FLD_DDR_MASK);
|
||
|
|
|
||
|
|
if (handle == NULL) {
|
||
|
|
unsigned int v;
|
||
|
|
|
||
|
|
v = (readl(priv->config_regs + MMSYS_SODI_REQ_MASK)
|
||
|
|
& (~sodi_req_mask));
|
||
|
|
v += (sodi_req_val & sodi_req_mask);
|
||
|
|
writel_relaxed(v, priv->config_regs + MMSYS_SODI_REQ_MASK);
|
||
|
|
|
||
|
|
v = (readl(priv->config_regs + MMSYS_EMI_REQ_CTL)
|
||
|
|
& (~emi_req_mask));
|
||
|
|
v += (emi_req_val & emi_req_mask);
|
||
|
|
writel_relaxed(v, priv->config_regs + MMSYS_EMI_REQ_CTL);
|
||
|
|
if (priv->data->bypass_infra_ddr_control) {
|
||
|
|
if (!IS_ERR(priv->infra_regs))
|
||
|
|
mtk_write_cpu_relaxed(
|
||
|
|
priv->infra_regs + MT6833_INFRA_DISP_DDR_CTL,
|
||
|
|
infra_req_val, infra_req_mask);
|
||
|
|
else
|
||
|
|
DDPINFO("%s: failed to disable infra ddr control\n", __func__);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
cmdq_pkt_write(handle, NULL, priv->config_regs_pa +
|
||
|
|
MMSYS_SODI_REQ_MASK, sodi_req_val, sodi_req_mask);
|
||
|
|
cmdq_pkt_write(handle, NULL, priv->config_regs_pa +
|
||
|
|
MMSYS_EMI_REQ_CTL, emi_req_val, emi_req_mask);
|
||
|
|
if (priv->data->bypass_infra_ddr_control) {
|
||
|
|
if (priv->infra_regs_pa) {
|
||
|
|
cmdq_pkt_write(handle, NULL, priv->infra_regs_pa +
|
||
|
|
MT6833_INFRA_DISP_DDR_CTL,
|
||
|
|
infra_req_val, infra_req_mask);
|
||
|
|
} else
|
||
|
|
DDPINFO("%s: failed to disable infra ddr control\n", __func__);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void mt6873_mtk_sodi_config(struct drm_device *drm, enum mtk_ddp_comp_id id,
|
||
|
|
struct cmdq_pkt *handle, void *data)
|
||
|
|
{
|
||
|
|
struct mtk_drm_private *priv = drm->dev_private;
|
||
|
|
unsigned int sodi_req_val = 0, sodi_req_mask = 0;
|
||
|
|
unsigned int emi_req_val = 0, emi_req_mask = 0;
|
||
|
|
bool en = *((bool *)data);
|
||
|
|
|
||
|
|
if (id == DDP_COMPONENT_ID_MAX) { /* config when top clk on */
|
||
|
|
if (!en)
|
||
|
|
return;
|
||
|
|
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
0, MT6873_SODI_REQ_SEL_ALL);
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
0, MT6873_SODI_REQ_VAL_ALL);
|
||
|
|
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
1, SODI_REQ_SEL_RDMA0_PD_MODE);
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
1, SODI_REQ_VAL_RDMA0_PD_MODE);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0x1, HRT_URGENT_CTL_SEL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0x1, HRT_URGENT_CTL_SEL_WDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0x1, HRT_URGENT_CTL_SEL_RDMA4);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0x1, HRT_URGENT_CTL_SEL_MDP_RDMA4);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, HRT_URGENT_CTL_VAL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, HRT_URGENT_CTL_VAL_WDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, HRT_URGENT_CTL_VAL_RDMA4);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, HRT_URGENT_CTL_VAL_MDP_RDMA4);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, DVFS_HALT_MASK_SEL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, DVFS_HALT_MASK_SEL_RDMA4);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, DVFS_HALT_MASK_SEL_WDMA0);
|
||
|
|
} else if (id == DDP_COMPONENT_RDMA0) {
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask, (!(unsigned int)en),
|
||
|
|
SODI_REQ_SEL_RDMA0_CG_MODE);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, (!(unsigned int)en),
|
||
|
|
HRT_URGENT_CTL_SEL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, en,
|
||
|
|
DVFS_HALT_MASK_SEL_RDMA0);
|
||
|
|
} else if (id == DDP_COMPONENT_RDMA4) {
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, (!(unsigned int)en),
|
||
|
|
HRT_URGENT_CTL_SEL_RDMA4);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, (unsigned int)en,
|
||
|
|
DVFS_HALT_MASK_SEL_RDMA4);
|
||
|
|
} else if (id == DDP_COMPONENT_WDMA0) {
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, (!(unsigned int)en),
|
||
|
|
HRT_URGENT_CTL_SEL_WDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, en,
|
||
|
|
DVFS_HALT_MASK_SEL_WDMA0);
|
||
|
|
} else
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (handle == NULL) {
|
||
|
|
unsigned int v;
|
||
|
|
|
||
|
|
v = (readl(priv->config_regs + MMSYS_SODI_REQ_MASK)
|
||
|
|
& (~sodi_req_mask));
|
||
|
|
v += (sodi_req_val & sodi_req_mask);
|
||
|
|
writel_relaxed(v, priv->config_regs + MMSYS_SODI_REQ_MASK);
|
||
|
|
|
||
|
|
v = (readl(priv->config_regs + MMSYS_EMI_REQ_CTL)
|
||
|
|
& (~emi_req_mask));
|
||
|
|
v += (emi_req_val & emi_req_mask);
|
||
|
|
writel_relaxed(v, priv->config_regs + MMSYS_EMI_REQ_CTL);
|
||
|
|
} else {
|
||
|
|
cmdq_pkt_write(handle, NULL, priv->config_regs_pa +
|
||
|
|
MMSYS_SODI_REQ_MASK, sodi_req_val, sodi_req_mask);
|
||
|
|
cmdq_pkt_write(handle, NULL, priv->config_regs_pa +
|
||
|
|
MMSYS_EMI_REQ_CTL, emi_req_val, emi_req_mask);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void mt6885_mtk_sodi_config(struct drm_device *drm, enum mtk_ddp_comp_id id,
|
||
|
|
struct cmdq_pkt *handle, void *data)
|
||
|
|
{
|
||
|
|
struct mtk_drm_private *priv = drm->dev_private;
|
||
|
|
unsigned int sodi_req_val = 0, sodi_req_mask = 0;
|
||
|
|
unsigned int emi_req_val = 0, emi_req_mask = 0;
|
||
|
|
bool en = *((bool *)data);
|
||
|
|
|
||
|
|
if (id == DDP_COMPONENT_ID_MAX) { /* config when top clk on */
|
||
|
|
if (!en)
|
||
|
|
return;
|
||
|
|
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
0, SODI_REQ_SEL_ALL);
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
0, SODI_REQ_VAL_ALL);
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
1, SODI_REQ_SEL_RDMA0_PD_MODE);
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
1, SODI_REQ_VAL_RDMA0_PD_MODE);
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
1, SODI_REQ_SEL_RDMA1_PD_MODE);
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask,
|
||
|
|
1, SODI_REQ_VAL_RDMA1_PD_MODE);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0xFF, HRT_URGENT_CTL_SEL_ALL);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, HRT_URGENT_CTL_VAL_ALL);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask,
|
||
|
|
0, DVFS_HALT_MASK_SEL_ALL);
|
||
|
|
} else if (id == DDP_COMPONENT_RDMA0) {
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask, (!(unsigned int)en),
|
||
|
|
SODI_REQ_SEL_RDMA0_CG_MODE);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, (!(unsigned int)en),
|
||
|
|
HRT_URGENT_CTL_SEL_RDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, en,
|
||
|
|
DVFS_HALT_MASK_SEL_RDMA0);
|
||
|
|
} else if (id == DDP_COMPONENT_RDMA1) {
|
||
|
|
SET_VAL_MASK(sodi_req_val, sodi_req_mask, (!(unsigned int)en),
|
||
|
|
SODI_REQ_SEL_RDMA1_CG_MODE);
|
||
|
|
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, (!(unsigned int)en),
|
||
|
|
HRT_URGENT_CTL_SEL_RDMA1);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, en,
|
||
|
|
DVFS_HALT_MASK_SEL_RDMA1);
|
||
|
|
} else if (id == DDP_COMPONENT_RDMA4) {
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, (!(unsigned int)en),
|
||
|
|
HRT_URGENT_CTL_SEL_RDMA4);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, en,
|
||
|
|
DVFS_HALT_MASK_SEL_RDMA4);
|
||
|
|
} else if (id == DDP_COMPONENT_RDMA5) {
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, (!(unsigned int)en),
|
||
|
|
HRT_URGENT_CTL_SEL_RDMA5);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, en,
|
||
|
|
DVFS_HALT_MASK_SEL_RDMA5);
|
||
|
|
} else if (id == DDP_COMPONENT_WDMA0) {
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, (!(unsigned int)en),
|
||
|
|
HRT_URGENT_CTL_SEL_WDMA0);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, en,
|
||
|
|
DVFS_HALT_MASK_SEL_WDMA0);
|
||
|
|
} else if (id == DDP_COMPONENT_WDMA1) {
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, (!(unsigned int)en),
|
||
|
|
HRT_URGENT_CTL_SEL_WDMA1);
|
||
|
|
SET_VAL_MASK(emi_req_val, emi_req_mask, en,
|
||
|
|
DVFS_HALT_MASK_SEL_WDMA1);
|
||
|
|
} else
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (handle == NULL) {
|
||
|
|
unsigned int v;
|
||
|
|
|
||
|
|
v = (readl(priv->config_regs + MMSYS_SODI_REQ_MASK)
|
||
|
|
& (~sodi_req_mask));
|
||
|
|
v += (sodi_req_val & sodi_req_mask);
|
||
|
|
writel_relaxed(v, priv->config_regs + MMSYS_SODI_REQ_MASK);
|
||
|
|
|
||
|
|
v = (readl(priv->config_regs + MMSYS_EMI_REQ_CTL)
|
||
|
|
& (~emi_req_mask));
|
||
|
|
v += (emi_req_val & emi_req_mask);
|
||
|
|
writel_relaxed(v, priv->config_regs + MMSYS_EMI_REQ_CTL);
|
||
|
|
} else {
|
||
|
|
cmdq_pkt_write(handle, NULL, priv->config_regs_pa +
|
||
|
|
MMSYS_SODI_REQ_MASK, sodi_req_val, sodi_req_mask);
|
||
|
|
cmdq_pkt_write(handle, NULL, priv->config_regs_pa +
|
||
|
|
MMSYS_EMI_REQ_CTL, emi_req_val, emi_req_mask);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
int mtk_ddp_comp_helper_get_opt(struct mtk_ddp_comp *comp,
|
||
|
|
enum MTK_DRM_HELPER_OPT option)
|
||
|
|
{
|
||
|
|
struct mtk_drm_crtc *mtk_crtc = comp->mtk_crtc;
|
||
|
|
struct mtk_drm_private *priv = NULL;
|
||
|
|
struct mtk_drm_helper *helper_opt = NULL;
|
||
|
|
|
||
|
|
if (!mtk_crtc) {
|
||
|
|
DDPINFO("%s: crtc is empty\n", __func__);
|
||
|
|
return -EINVAL;
|
||
|
|
}
|
||
|
|
|
||
|
|
priv = mtk_crtc->base.dev->dev_private;
|
||
|
|
helper_opt = priv->helper_opt;
|
||
|
|
|
||
|
|
return mtk_drm_helper_get_opt(helper_opt, option);
|
||
|
|
}
|