unplugged-kernel/drivers/misc/mediatek/video/mt6779/dispsys/ddp_misc.c

453 lines
11 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#include <linux/of_address.h>
#include <linux/of.h>
#include <linux/delay.h>
#include <linux/types.h>
#include "ddp_misc.h"
#include "ddp_reg.h"
#include "ddp_log.h"
#include "ddp_rdma_ex.h"
#include "ddp_wdma_ex.h"
#include "ddp_ovl.h"
#if defined(CONFIG_MTK_M4U)
#include "m4u.h"
#endif
#include "ddp_info.h"
#include "mtk_disp_mgr.h"
#include "disp_helper.h"
#include "mmpath.h"
unsigned long get_smi_larb_va(unsigned int larb)
{
struct device_node *node = NULL;
char smi_larb_dt_name[25];
unsigned long va = 0;
unsigned int id;
int i, ret;
scnprintf(smi_larb_dt_name, sizeof(smi_larb_dt_name),
"mediatek,mt6779-smi-larb");
for (i = 0; i < DISP_LARB_NUM; i++) {
node = of_find_compatible_node(node,
NULL, smi_larb_dt_name);
if (node) {
ret = of_property_read_u32(node,
"mediatek,larb-id", &id);
if ((!ret) && (id == larb))
break;
}
}
if (i == DISP_LARB_NUM) {
DDP_PR_ERR("Cannot find smi-larb%d\n",
larb);
return 0;
}
if (node != NULL)
va = (unsigned long)of_iomap(node, 0);
if (va == 0)
DDP_PR_ERR("Cannot get smi larb va, smi DT name: %s\n",
smi_larb_dt_name);
return va;
}
void enable_smi_ultra(unsigned int larb, unsigned int value)
{
unsigned long va = get_smi_larb_va(larb);
unsigned long offset = SMI_LARB_FORCE_ULTRA;
unsigned int prev_value, cur_value;
if (va == 0)
return;
prev_value = DISP_REG_GET(va + offset);
DISP_REG_SET(NULL, va + offset, value);
cur_value = DISP_REG_GET(va + offset);
DDPMSG("enable smi ultra, larb:%u, prev:0x%x, cur:0x%x\n",
larb, prev_value, cur_value);
}
void enable_smi_preultra(unsigned int larb, unsigned int value)
{
unsigned long va = get_smi_larb_va(larb);
unsigned long offset = SMI_LARB_FORCE_PREULTRA;
unsigned int prev_value, cur_value;
if (va == 0)
return;
prev_value = DISP_REG_GET(va + offset);
DISP_REG_SET(NULL, va + offset, value);
cur_value = DISP_REG_GET(va + offset);
DDPMSG("enable smi pre-ultra, larb:%u, prev:0x%x, cur:0x%x\n",
larb, prev_value, cur_value);
}
void disable_smi_ultra(unsigned int larb, unsigned int value)
{
unsigned long va = get_smi_larb_va(larb);
unsigned long offset = SMI_LARB_ULTRA_DIS;
unsigned int prev_value, cur_value;
if (va == 0)
return;
prev_value = DISP_REG_GET(va + offset);
DISP_REG_SET(NULL, va + offset, value);
cur_value = DISP_REG_GET(va + offset);
DDPMSG("disable smi ultra, larb:%u, prev:0x%x, cur:0x%x\n",
larb, prev_value, cur_value);
}
void disable_smi_preultra(unsigned int larb, unsigned int value)
{
unsigned long va = get_smi_larb_va(larb);
unsigned long offset = SMI_LARB_PREULTRA_DIS;
unsigned int prev_value, cur_value;
if (va == 0)
return;
prev_value = DISP_REG_GET(va + offset);
DISP_REG_SET(NULL, va + offset, value);
cur_value = DISP_REG_GET(va + offset);
DDPMSG("disable smi pre-ultra, larb:%u, prev:0x%x, cur:0x%x\n",
larb, prev_value, cur_value);
}
void rdma_golden_setting_test(unsigned int idx, unsigned int bpp,
unsigned int w, unsigned int h, unsigned int is_wrot_sram,
bool is_dc, unsigned int is_vdo)
{
struct golden_setting_context gsc;
unsigned int gs[GS_RDMA_FLD_NUM] = {-1};
unsigned int i;
gsc.dst_width = w;
gsc.dst_height = h;
gsc.is_dc = is_dc;
gsc.is_wrot_sram = is_wrot_sram;
rdma_cal_golden_setting(idx, bpp, &gsc, gs, is_vdo);
DDPMSG("== RDMA_GOLDEN_SETTING_TEST ==\n");
DDPMSG("Input: idx:%u, bpp:%u, w:%u, h:%u, is_dc:%d, is_vdo:%d\n",
idx, bpp, w, h, is_dc, is_vdo);
DDPMSG("Result:\n");
for (i = 0; i < GS_RDMA_FLD_NUM; i++)
DDPMSG("%u\n", gs[i]);
}
void ovl_golden_setting_test(enum dst_module_type dst_mode_type)
{
unsigned int gs[GS_OVL_FLD_NUM] = {-1};
unsigned int i;
ovl_cal_golden_setting(dst_mode_type, gs);
DDPMSG("== OVL_GOLDEN_SETTING_TEST ==\n");
DDPMSG("dst_module_type%u\n", dst_mode_type);
DDPMSG("Result:\n");
for (i = 0; i < GS_OVL_FLD_NUM; i++)
DDPMSG("%u\n", gs[i]);
}
void wdma_golden_setting_test(unsigned int w, unsigned int h,
unsigned int is_dc, enum UNIFIED_COLOR_FMT format)
{
struct golden_setting_context gsc;
unsigned int i;
unsigned int gs[GS_WDMA_FLD_NUM] = {-1};
gsc.dst_width = w;
gsc.dst_height = h;
gsc.is_dc = is_dc;
gsc.ext_dst_width = w;
gsc.ext_dst_height = h;
wdma_calc_golden_setting(&gsc, 1, gs, format);
DDPMSG("== WDMA_GOLDEN_SETTING_TEST ==\n");
DDPMSG("width%u, height:%u, is_dc:%u\n", w, h, is_dc);
DDPMSG("Result:\n");
for (i = 0; i < GS_WDMA_FLD_NUM; i++)
DDPMSG("%u\n", gs[i]);
}
void golden_setting_test(void)
{
/* RDMA golden setting */
rdma_golden_setting_test(0, 24, 1080, 1920, 0, 0, 0);
rdma_golden_setting_test(0, 24, 1080, 1920, 0, 1, 0);
rdma_golden_setting_test(0, 24, 1080, 1920, 0, 0, 1);
rdma_golden_setting_test(0, 24, 1080, 1920, 0, 1, 1);
rdma_golden_setting_test(0, 24, 1080, 2520, 0, 0, 0);
rdma_golden_setting_test(0, 24, 1080, 2520, 0, 1, 0);
rdma_golden_setting_test(0, 24, 1080, 2520, 0, 0, 1);
rdma_golden_setting_test(0, 24, 1080, 2520, 0, 1, 1);
/* OVL golden setting */
ovl_golden_setting_test(DST_MOD_REAL_TIME);
ovl_golden_setting_test(DST_MOD_WDMA);
/* WDMA golden setting */
wdma_golden_setting_test(1080, 1920, 0, UFMT_RGBA8888);
wdma_golden_setting_test(1080, 1920, 1, UFMT_I420);
wdma_golden_setting_test(1080, 2520, 0, UFMT_NV12);
wdma_golden_setting_test(1080, 2520, 1, UFMT_YV12);
}
void fake_engine(unsigned int idx, unsigned int en,
unsigned int wr_en, unsigned int rd_en,
unsigned int latency, unsigned int preultra_cnt,
unsigned int ultra_cnt)
{
#if defined(CONFIG_MTK_M4U)
int offset = idx * 0x20;
struct M4U_PORT_STRUCT port;
static void *va[2];
static phys_addr_t pa[2];
int wr_pat = 4;
int burst = 7;
int test_len = 255;
int loop = 1;
int preultra_en = 0;
int ultra_en = 0;
int dis_wr = !wr_en;
int dis_rd = !rd_en;
int delay_cnt = 0;
if (idx > 1) {
DDP_PR_ERR("%s idx only 0 and 1\n", __func__);
return;
}
if (preultra_cnt > 0) {
preultra_en = 1;
preultra_cnt--;
}
if (ultra_cnt > 0) {
ultra_en = 1;
ultra_cnt--;
}
if (!va[idx]) {
va[idx] = kzalloc(1024*1024, GFP_KERNEL | GFP_DMA);
pa[idx] = virt_to_phys(va[idx]);
DDPMSG("%s fake_engine_%d va=%p, pa=0x%pa\n",
__func__, idx, va[idx], &pa[idx]);
}
if (en) {
memset(&port, 0, sizeof(port));
if (idx)
port.ePortID = M4U_PORT_DISP_FAKE1;
else
port.ePortID = M4U_PORT_DISP_FAKE0;
port.Security = 0;
port.Virtuality = 0;
m4u_config_port(&port);
if (idx)
DISP_REG_SET(NULL,
DISP_REG_CONFIG_MMSYS_CG_CLR1, BIT(4));
else
DISP_REG_SET(NULL,
DISP_REG_CONFIG_MMSYS_CG_CLR0, BIT(19));
DISP_REG_SET(NULL,
DISP_REG_CONFIG_DISP_FAKE_ENG_RD_ADDR + offset,
(unsigned int)pa[idx]);
DISP_REG_SET(NULL,
DISP_REG_CONFIG_DISP_FAKE_ENG_WR_ADDR + offset,
(unsigned int)pa[idx] + 4096);
DISP_REG_SET(NULL,
DISP_REG_CONFIG_DISP_FAKE_ENG_CON0 + offset,
(wr_pat << 24) | (loop << 22) | test_len);
DISP_REG_SET(NULL,
DISP_REG_CONFIG_DISP_FAKE_ENG_CON1 + offset,
(ultra_en << 23) | (ultra_cnt << 20) |
(preultra_en << 19) | (preultra_cnt << 16) |
(burst << 12) | (dis_wr << 11) | (dis_rd << 10) |
latency);
DISP_REG_SET(NULL,
DISP_REG_CONFIG_DISP_FAKE_ENG_RST + offset, 1);
DISP_REG_SET(NULL,
DISP_REG_CONFIG_DISP_FAKE_ENG_RST + offset, 0);
DISP_REG_SET(NULL,
DISP_REG_CONFIG_DISP_FAKE_ENG_EN + offset, 0x3);
DDPMSG("fake_engine_%d enable\n", idx);
} else {
DISP_REG_SET(NULL,
DISP_REG_CONFIG_DISP_FAKE_ENG_EN + offset, 0x1);
while ((DISP_REG_GET(DISP_REG_CONFIG_DISP_FAKE_ENG_STATE
+ offset) & 0x1) == 0x1) {
delay_cnt++;
udelay(1);
if (delay_cnt > 1000) {
DDP_PR_ERR("Wait fake_engine_%d idle timeout\n",
idx);
break;
}
}
DISP_REG_SET(NULL,
DISP_REG_CONFIG_DISP_FAKE_ENG_EN + offset, 0x0);
if (idx)
DISP_REG_SET(NULL,
DISP_REG_CONFIG_MMSYS_CG_SET1, BIT(4));
else
DISP_REG_SET(NULL,
DISP_REG_CONFIG_MMSYS_CG_SET0, BIT(19));
DDPMSG("fake_engine_%d disable\n", idx);
}
#endif
}
void dump_fake_engine(void)
{
DDPMSG("=================Dump Fake_engine================\n");
DDPMSG("CG_CON0 = 0x%x\n",
DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON0));
DDPMSG("CG_CON1 = 0x%x\n",
DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON1));
DDPMSG("FAKE_ENG_RD_ADDR = 0x%x\n",
DISP_REG_GET(DISP_REG_CONFIG_DISP_FAKE_ENG_RD_ADDR));
DDPMSG("FAKE_ENG_WR_ADDR = 0x%x\n",
DISP_REG_GET(DISP_REG_CONFIG_DISP_FAKE_ENG_WR_ADDR));
DDPMSG("FAKE_ENG_CON0 = 0x%x\n",
DISP_REG_GET(DISP_REG_CONFIG_DISP_FAKE_ENG_CON0));
DDPMSG("FAKE_ENG_CON1 = 0x%x\n",
DISP_REG_GET(DISP_REG_CONFIG_DISP_FAKE_ENG_CON1));
DDPMSG("FAKE_ENG_EN = 0x%x\n",
DISP_REG_GET(DISP_REG_CONFIG_DISP_FAKE_ENG_EN));
DDPMSG("FAKE_ENG_STATE = 0x%x\n",
DISP_REG_GET(DISP_REG_CONFIG_DISP_FAKE_ENG_STATE));
DDPMSG("FAKE2_ENG_RD_ADDR = 0x%x\n",
DISP_REG_GET(DISP_REG_CONFIG_DISP_FAKE2_ENG_RD_ADDR));
DDPMSG("FAKE2_ENG_WR_ADDR = 0x%x\n",
DISP_REG_GET(DISP_REG_CONFIG_DISP_FAKE2_ENG_WR_ADDR));
DDPMSG("FAKE2_ENG_CON0 = 0x%x\n",
DISP_REG_GET(DISP_REG_CONFIG_DISP_FAKE2_ENG_CON0));
DDPMSG("FAKE2_ENG_CON1 = 0x%x\n",
DISP_REG_GET(DISP_REG_CONFIG_DISP_FAKE2_ENG_CON1));
DDPMSG("FAKE2_ENG_EN = 0x%x\n",
DISP_REG_GET(DISP_REG_CONFIG_DISP_FAKE2_ENG_EN));
DDPMSG("FAKE2_ENG_STATE = 0x%x\n",
DISP_REG_GET(DISP_REG_CONFIG_DISP_FAKE2_ENG_STATE));
DDPMSG("====================================================\n");
}
void MMPathTracePrimaryOvl2Dsi(void)
{
char str[1300] = "";
int strlen = sizeof(str), n = 0;
int HWC_gpid = get_HWC_gpid();
if (disp_helper_get_option(DISP_OPT_MMPATH) == 0)
return;
if (MMPathIsPrimaryDL()) {
n += scnprintf(str + n, strlen - n, "hw=DISP_OVL0, pid=%d, ",
HWC_gpid);
n = MMPathTracePrimaryOVL(str, strlen, n);
} else {
n += scnprintf(str + n, strlen - n, "hw=DISP_RDMA0, pid=%d, ",
HWC_gpid);
n = MMPathTracePrimaryRDMA(str, strlen, n);
}
n += scnprintf(str + n, strlen - n, "OUT=DSI");
trace_MMPath(str);
}
void MMPathTracePrimaryOvl2Mem(void)
{
char str[1300] = "";
int strlen = sizeof(str), n = 0;
int HWC_gpid = get_HWC_gpid();
unsigned int wdma_sel_in = 0;
if (disp_helper_get_option(DISP_OPT_MMPATH) == 0)
return;
/* do not print if path is 1-to-2 */
if (MMPathIsPrimaryDL())
return;
wdma_sel_in = DISP_REG_GET(DISP_REG_CONFIG_OVL_TO_WDMA_SEL_IN);
/* check if ovl0 to wdma */
if (wdma_sel_in != 0)
return;
n += scnprintf(str + n, strlen - n, "hw=DISP_OVL0, pid=%d, ",
HWC_gpid);
n = MMPathTracePrimaryOVL(str, strlen, n);
n = MMPathTracePrimaryWDMA(str, strlen, n);
trace_MMPath(str);
}
void MMPathTraceSecondOvl2Mem(void)
{
char str[1300] = "";
int strlen = sizeof(str), n = 0;
int HWC_gpid = get_HWC_gpid();
unsigned int wdma_sel_in = 0;
if (disp_helper_get_option(DISP_OPT_MMPATH) == 0)
return;
wdma_sel_in = DISP_REG_GET(DISP_REG_CONFIG_OVL_TO_WDMA_SEL_IN);
/* check if ovl1_2l to wdma */
if (wdma_sel_in != 2)
return;
n += scnprintf(str + n, strlen - n, "hw=DISP_OVL1, pid=%d, ",
HWC_gpid);
n = MMPathTraceSecondOVL(str, strlen, n);
n = MMPathTracePrimaryWDMA(str, strlen, n);
trace_MMPath(str);
}