193a7515aSWenping Zhang // SPDX-License-Identifier: GPL-2.0
293a7515aSWenping Zhang /*
393a7515aSWenping Zhang * Copyright (c) 2020 Rockchip Electronics Co. Ltd.
493a7515aSWenping Zhang *
593a7515aSWenping Zhang * Author: Wenping Zhang <wenping.zhang@rock-chips.com>
693a7515aSWenping Zhang */
793a7515aSWenping Zhang #include <common.h>
893a7515aSWenping Zhang #include <clk.h>
993a7515aSWenping Zhang #include <dm.h>
1093a7515aSWenping Zhang #include <dm/pinctrl.h>
1193a7515aSWenping Zhang #include <pwm.h>
1293a7515aSWenping Zhang #include <regmap.h>
1393a7515aSWenping Zhang #include <syscon.h>
1493a7515aSWenping Zhang #include <asm/arch/clock.h>
1593a7515aSWenping Zhang #include <asm/io.h>
1693a7515aSWenping Zhang #include <syscon.h>
1793a7515aSWenping Zhang #include <linux/io.h>
1893a7515aSWenping Zhang #include "rk_ebc.h"
1993a7515aSWenping Zhang #ifdef CONFIG_IRQ
2093a7515aSWenping Zhang #include <irq-generic.h>
2193a7515aSWenping Zhang #endif
2293a7515aSWenping Zhang
2393a7515aSWenping Zhang struct ebc_tcon_priv {
2493a7515aSWenping Zhang struct udevice *dev;
2593a7515aSWenping Zhang void __iomem *reg;
2693a7515aSWenping Zhang u32 *regcache;
2793a7515aSWenping Zhang u32 reg_len;
2893a7515aSWenping Zhang void *grf;
2993a7515aSWenping Zhang void *pmugrf;
30f968f3bcSZorro Liu struct clk dclk;
3193a7515aSWenping Zhang };
3293a7515aSWenping Zhang
3393a7515aSWenping Zhang #define msleep(a) udelay((a) * 1000)
3493a7515aSWenping Zhang #define HIWORD_UPDATE(x, l, h) (((x) << (l)) | (GENMASK(h, l) << 16))
3593a7515aSWenping Zhang #define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l)))
3693a7515aSWenping Zhang
3793a7515aSWenping Zhang #define REG_LOAD_GLOBAL_EN 0x1
3893a7515aSWenping Zhang
3993a7515aSWenping Zhang /* ebc register define */
4093a7515aSWenping Zhang #define EBC_DSP_START 0x0000 //Frame statrt register
4193a7515aSWenping Zhang #define EBC_EPD_CTRL 0x0004 //EPD control register
4293a7515aSWenping Zhang #define EBC_DSP_CTRL 0x0008 //Display control register
4393a7515aSWenping Zhang #define EBC_DSP_HTIMING0 0x000c //H-Timing setting register0
4493a7515aSWenping Zhang #define EBC_DSP_HTIMING1 0x0010 //H-Timing setting register1
4593a7515aSWenping Zhang #define EBC_DSP_VTIMING0 0x0014 //V-Timing setting register0
4693a7515aSWenping Zhang #define EBC_DSP_VTIMING1 0x0018 //V-Timing setting register1
4793a7515aSWenping Zhang #define EBC_DSP_ACT_INFO 0x001c //ACTIVE width/height
4893a7515aSWenping Zhang #define EBC_WIN_CTRL 0x0020 //Window ctrl
4993a7515aSWenping Zhang #define EBC_WIN_MST0 0x0024 //Current win memory start
5093a7515aSWenping Zhang #define EBC_WIN_MST1 0x0028 //Next win memory start
5193a7515aSWenping Zhang #define EBC_WIN_VIR 0x002c //Window vir width/height
5293a7515aSWenping Zhang #define EBC_WIN_ACT 0x0030 //Window act width/height
5393a7515aSWenping Zhang #define EBC_WIN_DSP 0x0034 //Window dsp width/height
5493a7515aSWenping Zhang #define EBC_WIN_DSP_ST 0x0038 //Window display start point
5593a7515aSWenping Zhang #define EBC_INT_STATUS 0x003c //Interrupt register
5693a7515aSWenping Zhang #define EBC_VCOM0 0x0040 //VCOM setting register0
5793a7515aSWenping Zhang #define EBC_VCOM1 0x0044 //VCOM setting register1
5893a7515aSWenping Zhang #define EBC_VCOM2 0x0048 //VCOM setting register2
5993a7515aSWenping Zhang #define EBC_VCOM3 0x004c //VCOM setting register3
6093a7515aSWenping Zhang #define EBC_CONFIG_DONE 0x0050 //Config done register
6193a7515aSWenping Zhang #define EBC_VNUM 0x0054 //Line flag num
6293a7515aSWenping Zhang #define EBC_WIN_MST2 0x0058 //Framecount memory start
6393a7515aSWenping Zhang #define EBC_LUT_DATA_ADDR 0x1000 //lut data address
6493a7515aSWenping Zhang
6593a7515aSWenping Zhang #define DSP_HTOTAL(x) UPDATE(x, 27, 16)
6693a7515aSWenping Zhang #define DSP_HS_END(x) UPDATE(x, 7, 0)
6793a7515aSWenping Zhang #define DSP_HACT_END(x) UPDATE(x, 26, 16)
6893a7515aSWenping Zhang #define DSP_HACT_ST(x) UPDATE(x, 7, 0)
6993a7515aSWenping Zhang #define DSP_VTOTAL(x) UPDATE(x, 26, 16)
7093a7515aSWenping Zhang #define DSP_VS_END(x) UPDATE(x, 7, 0)
7193a7515aSWenping Zhang #define DSP_VACT_END(x) UPDATE(x, 26, 16)
7293a7515aSWenping Zhang #define DSP_VACT_ST(x) UPDATE(x, 7, 0)
7393a7515aSWenping Zhang #define DSP_HEIGHT(x) UPDATE(x, 26, 16)
7493a7515aSWenping Zhang #define DSP_WIDTH(x) UPDATE(x, 11, 0)
7593a7515aSWenping Zhang
7693a7515aSWenping Zhang #define WIN2_FIFO_ALMOST_FULL_LEVEL(x) UPDATE(x, 27, 19)
7793a7515aSWenping Zhang #define WIN_EN(x) UPDATE(x, 18, 18)
7893a7515aSWenping Zhang #define BURST_REG(x) UPDATE(x, 12, 10)
7993a7515aSWenping Zhang #define WIN_FIFO_ALMOST_FULL_LEVEL(x) UPDATE(x, 9, 2)
8093a7515aSWenping Zhang #define WIN_FMT(x) UPDATE(x, 1, 0)
8193a7515aSWenping Zhang
8293a7515aSWenping Zhang #define WIN_VIR_HEIGHT(x) UPDATE(x, 31, 16)
8393a7515aSWenping Zhang #define WIN_VIR_WIDTH(x) UPDATE(x, 15, 0)
8493a7515aSWenping Zhang #define WIN_ACT_HEIGHT(x) UPDATE(x, 26, 16)
8593a7515aSWenping Zhang #define WIN_ACT_WIDTH(x) UPDATE(x, 11, 0)
8693a7515aSWenping Zhang #define WIN_DSP_HEIGHT(x) UPDATE(x, 26, 16)
8793a7515aSWenping Zhang #define WIN_DSP_WIDTH(x) UPDATE(x, 11, 0)
8893a7515aSWenping Zhang #define WIN_DSP_YST(x) UPDATE(x, 26, 16)
8993a7515aSWenping Zhang #define WIN_DSP_XST(x) UPDATE(x, 11, 0)
9093a7515aSWenping Zhang
9193a7515aSWenping Zhang #define DSP_OUT_LOW BIT(31)
9293a7515aSWenping Zhang #define DSP_EINK_MODE(x) UPDATE(x, 13, 13)
9393a7515aSWenping Zhang #define DSP_EINK_MODE_MASK BIT(13)
9493a7515aSWenping Zhang #define DSP_SDCE_WIDTH(x) UPDATE(x, 25, 16)
9593a7515aSWenping Zhang #define DSP_FRM_TOTAL(x) UPDATE(x, 9, 2)
9693a7515aSWenping Zhang #define DSP_FRM_TOTAL_MASK GENMASK(9, 2)
9793a7515aSWenping Zhang #define DSP_FRM_START BIT(0)
9893a7515aSWenping Zhang #define DSP_FRM_START_MASK BIT(0)
9993a7515aSWenping Zhang #define SW_BURST_CTRL BIT(12)
10093a7515aSWenping Zhang
10193a7515aSWenping Zhang #define EINK_MODE_SWAP(x) UPDATE(x, 31, 31)
10293a7515aSWenping Zhang #define EINK_MODE_FRM_SEL(x) UPDATE(x, 30, 30)
10393a7515aSWenping Zhang #define DSP_GD_END(x) UPDATE(x, 26, 16)
10493a7515aSWenping Zhang #define DSP_GD_ST(x) UPDATE(x, 15, 8)
10593a7515aSWenping Zhang #define DSP_THREE_WIN_MODE(x) UPDATE(x, 7, 7)
10693a7515aSWenping Zhang #define THREE_WIN_MODE_MASK BIT(7)
10793a7515aSWenping Zhang #define DSP_SDDW_MODE(x) UPDATE(x, 6, 6)
10893a7515aSWenping Zhang #define EPD_AUO(x) UPDATE(x, 5, 5)
10993a7515aSWenping Zhang #define EPD_PWR(x) UPDATE(x, 4, 2)
11093a7515aSWenping Zhang #define EPD_GDRL(x) UPDATE(x, 1, 1)
11193a7515aSWenping Zhang #define EPD_SDSHR(x) UPDATE(x, 0, 0)
11293a7515aSWenping Zhang
11393a7515aSWenping Zhang #define DSP_SWAP_MODE(x) UPDATE(x, 31, 30)
11493a7515aSWenping Zhang #define DSP_SWAP_MODE_MASK GENMASK(31, 30)
11593a7515aSWenping Zhang #define DSP_SDCLK_DIV(x) UPDATE(x, 19, 16)
11693a7515aSWenping Zhang #define DSP_SDCLK_DIV_MASK GENMASK(19, 16)
11793a7515aSWenping Zhang #define DSP_VCOM_MODE(x) UPDATE(x, 27, 27)
11893a7515aSWenping Zhang #define DSP_VCOM_MODE_MASK BIT(27)
11993a7515aSWenping Zhang
12093a7515aSWenping Zhang #define DSP_UPDATE_MODE(x) UPDATE(x, 29, 29)
12193a7515aSWenping Zhang #define DSP_DISPLAY_MODE(x) UPDATE(x, 28, 28)
12293a7515aSWenping Zhang #define UPDATE_MODE_MASK BIT(29)
12393a7515aSWenping Zhang #define DISPLAY_MODE_MASK BIT(28)
12493a7515aSWenping Zhang
12593a7515aSWenping Zhang #define DSP_FRM_INT_NUM(x) UPDATE(x, 19, 12)
12693a7515aSWenping Zhang #define FRM_END_INT BIT(0)
12793a7515aSWenping Zhang #define DSP_END_INT BIT(1)
12893a7515aSWenping Zhang #define DSP_FRM_INT BIT(2)
12993a7515aSWenping Zhang #define LINE_FLAG_INT BIT(3)
13093a7515aSWenping Zhang #define FRM_END_INT_MASK BIT(4)
13193a7515aSWenping Zhang #define DSP_END_INT_MASK BIT(5)
13293a7515aSWenping Zhang #define DSP_FRM_INT_MASK BIT(6)
13393a7515aSWenping Zhang #define LINE_FLAG_INT_MASK BIT(7)
13493a7515aSWenping Zhang #define FRM_END_INT_CLR BIT(8)
13593a7515aSWenping Zhang #define DSP_END_INT_CLR BIT(9)
13693a7515aSWenping Zhang #define DSP_FRM_INT_CLR BIT(10)
13793a7515aSWenping Zhang #define LINE_FLAG_INT_CLR BIT(11)
13893a7515aSWenping Zhang
1398766792cSChaoyi Chen #define RK3576_EBC_DSP_START 0x0000
1408766792cSChaoyi Chen #define RK3576_EBC_EPD_CTRL 0x0004
1418766792cSChaoyi Chen #define RK3576_EBC_DSP_CTRL 0x0008
1428766792cSChaoyi Chen #define RK3576_EBC_DSP_HTIMING0 0x000C
1438766792cSChaoyi Chen #define RK3576_EBC_DSP_HTIMING1 0x0010
1448766792cSChaoyi Chen #define RK3576_EBC_DSP_VTIMING0 0x0014
1458766792cSChaoyi Chen #define RK3576_EBC_DSP_VTIMING1 0x0018
1468766792cSChaoyi Chen #define RK3576_EBC_DSP_ACT_INFO 0x001C
1478766792cSChaoyi Chen #define RK3576_EBC_WIN_CTRL 0x0020
1488766792cSChaoyi Chen #define RK3576_EBC_WIN_MST0 0x0024
1498766792cSChaoyi Chen #define RK3576_EBC_WIN_MST1 0x0028
1508766792cSChaoyi Chen #define RK3576_EBC_WIN_VIR 0x002C
1518766792cSChaoyi Chen #define RK3576_EBC_WIN_ACT 0x0030
1528766792cSChaoyi Chen #define RK3576_EBC_WIN_DSP 0x0034
1538766792cSChaoyi Chen #define RK3576_EBC_WIN_DSP_ST 0x0038
1548766792cSChaoyi Chen #define RK3576_EBC_INT_STATUS 0x003C
1558766792cSChaoyi Chen #define RK3576_EBC_VCOM0 0x0040
1568766792cSChaoyi Chen #define RK3576_EBC_VCOM1 0x0044
1578766792cSChaoyi Chen #define RK3576_EBC_VCOM2 0x0048
1588766792cSChaoyi Chen #define RK3576_EBC_VCOM3 0x004C
1598766792cSChaoyi Chen #define RK3576_EBC_CONFIG_DONE 0x0050
1608766792cSChaoyi Chen #define RK3576_EBC_VNUM 0x0054
1618766792cSChaoyi Chen #define RK3576_EBC_WIN_MST2 0x0058
1628766792cSChaoyi Chen #define RK3576_EBC_DSP_CTRL2 0x005C
1638766792cSChaoyi Chen #define RK3576_EBC_DSP_CTRL3 0x0060
1648766792cSChaoyi Chen #define RK3576_EBC_WIN0_CTRL 0x0064
1658766792cSChaoyi Chen #define RK3576_EBC_WIN1_CTRL 0x0068
1668766792cSChaoyi Chen #define RK3576_EBC_WIN2_CTRL 0x006C
1678766792cSChaoyi Chen #define RK3576_EBC_SYS_CTRL 0x0070
1688766792cSChaoyi Chen #define RK3576_EBC_LUT_ADDRESS_MAP_0 0x1000
1698766792cSChaoyi Chen
1708766792cSChaoyi Chen #define RK3576_DSP_FRM_START BIT(0)
1718766792cSChaoyi Chen #define RK3576_DSP_FRM_START_MASK BIT(0)
1728766792cSChaoyi Chen
1738766792cSChaoyi Chen #define RK3576_EINK_MODE_SWAP(x) UPDATE(x, 31, 31)
1748766792cSChaoyi Chen #define RK3576_EINK_MODE_FRM_SEL(x) UPDATE(x, 30, 30)
1758766792cSChaoyi Chen #define RK3576_DSP_THREE_WIN_MODE(x) UPDATE(x, 29, 29)
1768766792cSChaoyi Chen #define RK3576_THREE_WIN_MODE_MASK BIT(29)
1778766792cSChaoyi Chen #define RK3576_DSP_GD_END(x) UPDATE(x, 26, 16)
1788766792cSChaoyi Chen #define RK3576_DSP_GD_ST(x) UPDATE(x, 15, 8)
1798766792cSChaoyi Chen #define RK3576_DSP_SDDW_MODE(x) UPDATE(x, 7, 6)
1808766792cSChaoyi Chen #define RK3576_EPD_AUO(x) UPDATE(x, 5, 5)
1818766792cSChaoyi Chen #define RK3576_EPD_PWR(x) UPDATE(x, 4, 2)
1828766792cSChaoyi Chen #define RK3576_EPD_GDRL(x) UPDATE(x, 1, 1)
1838766792cSChaoyi Chen #define RK3576_EPD_SDSHR(x) UPDATE(x, 0, 0)
1848766792cSChaoyi Chen
1858766792cSChaoyi Chen #define RK3576_DSP_SWAP_MODE(x) UPDATE(x, 31, 30)
1868766792cSChaoyi Chen #define RK3576_DSP_UPDATE_MODE(x) UPDATE(x, 29, 29)
1878766792cSChaoyi Chen #define RK3576_DSP_DISPLAY_MODE(x) UPDATE(x, 28, 28)
1888766792cSChaoyi Chen #define RK3576_UPDATE_MODE_MASK BIT(29)
1898766792cSChaoyi Chen #define RK3576_DISPLAY_MODE_MASK BIT(28)
1908766792cSChaoyi Chen #define RK3576_DSP_VCOM_MODE(x) UPDATE(x, 27, 27)
1918766792cSChaoyi Chen #define RK3576_DSP_SDCLK_DIV(x) UPDATE(x, 19, 16)
1928766792cSChaoyi Chen #define RK3576_DSP_SDCLK_DIV_MASK GENMASK(19, 16)
1931020d760SChaoyi Chen #define RK3576_DSP_SDOE_MODE(x) UPDATE(x, 0, 0)
1948766792cSChaoyi Chen
1958766792cSChaoyi Chen #define RK3576_DSP_HTOTAL(x) UPDATE(x, 31, 16)
1968766792cSChaoyi Chen #define RK3576_DSP_HS_END(x) UPDATE(x, 15, 0)
1978766792cSChaoyi Chen #define RK3576_DSP_HACT_END(x) UPDATE(x, 31, 16)
1988766792cSChaoyi Chen #define RK3576_DSP_HACT_ST(x) UPDATE(x, 15, 0)
1998766792cSChaoyi Chen #define RK3576_DSP_VTOTAL(x) UPDATE(x, 31, 16)
2008766792cSChaoyi Chen #define RK3576_DSP_VS_END(x) UPDATE(x, 15, 0)
2018766792cSChaoyi Chen #define RK3576_DSP_VACT_END(x) UPDATE(x, 31, 16)
2028766792cSChaoyi Chen #define RK3576_DSP_VACT_ST(x) UPDATE(x, 15, 0)
2038766792cSChaoyi Chen #define RK3576_DSP_HEIGHT(x) UPDATE(x, 31, 16)
2048766792cSChaoyi Chen #define RK3576_DSP_WIDTH(x) UPDATE(x, 15, 0)
2058766792cSChaoyi Chen
2068766792cSChaoyi Chen #define RK3576_WIN_VIR_HEIGHT(x) UPDATE(x, 31, 16)
2078766792cSChaoyi Chen #define RK3576_WIN_VIR_WIDTH(x) UPDATE(x, 15, 0)
2088766792cSChaoyi Chen #define RK3576_WIN_ACT_HEIGHT(x) UPDATE(x, 31, 16)
2098766792cSChaoyi Chen #define RK3576_WIN_ACT_WIDTH(x) UPDATE(x, 15, 0)
2108766792cSChaoyi Chen #define RK3576_WIN_DSP_HEIGHT(x) UPDATE(x, 31, 16)
2118766792cSChaoyi Chen #define RK3576_WIN_DSP_WIDTH(x) UPDATE(x, 15, 0)
2128766792cSChaoyi Chen #define RK3576_WIN_DSP_YST(x) UPDATE(x, 31, 16)
2138766792cSChaoyi Chen #define RK3576_WIN_DSP_XST(x) UPDATE(x, 15, 0)
2148766792cSChaoyi Chen
2158766792cSChaoyi Chen #define RK3576_DMA_BURST_LENGTH(x) UPDATE(x, 25, 24)
2168766792cSChaoyi Chen #define RK3576_WIN2_FIFO_ALMOST_FULL_LEVEL(x) UPDATE(x, 20, 12)
2178766792cSChaoyi Chen #define RK3576_WIN_FIFO_ALMOST_FULL_LEVEL(x) UPDATE(x, 11, 4)
2188766792cSChaoyi Chen #define RK3576_WIN_FMT(x) UPDATE(x, 2, 0)
2198766792cSChaoyi Chen #define RK3576_WIN_FMT_MASK GENMASK(2, 0)
2208766792cSChaoyi Chen
2218766792cSChaoyi Chen #define RK3576_WIN_RID(x) UPDATE(x, 7, 4)
2228766792cSChaoyi Chen #define RK3576_WIN_AXI_GATHER_NUM(x) UPDATE(x, 11, 8)
2238766792cSChaoyi Chen #define RK3576_WIN_AXI_GATHER_EN BIT(1)
2248766792cSChaoyi Chen #define RK3576_WIN_EN BIT(0)
2258766792cSChaoyi Chen
2268766792cSChaoyi Chen #define RK3576_WIN2_EMPTY_INT_MASK BIT(26)
2278766792cSChaoyi Chen #define RK3576_WIN1_EMPTY_INT_MASK BIT(25)
2288766792cSChaoyi Chen #define RK3576_WIN0_EMPTY_INT_MASK BIT(24)
2298766792cSChaoyi Chen #define RK3576_FRM_END_INT_MASK BIT(4)
2308766792cSChaoyi Chen #define RK3576_DSP_FRM_INT_MASK BIT(6)
2318766792cSChaoyi Chen #define RK3576_LINE_FLAG_INT_MASK BIT(7)
2328766792cSChaoyi Chen
2338766792cSChaoyi Chen #define RK3576_DSP_SDCE_WIDTH(x) UPDATE(x, 23, 12)
2348766792cSChaoyi Chen #define RK3576_DSP_SDCE_WIDTH_MASK(x) GENMASK(x, 23, 12)
2358766792cSChaoyi Chen #define RK3576_DSP_FRM_TOTAL(x) UPDATE(x, 11, 4)
2368766792cSChaoyi Chen #define RK3576_DSP_FRM_TOTAL_MASK GENMASK(11, 4)
2378766792cSChaoyi Chen #define RK3576_DSP_EINK_MODE(x) UPDATE(x, 2, 2)
2388766792cSChaoyi Chen #define RK3576_DSP_EINK_MODE_MASK BIT(2)
2398766792cSChaoyi Chen #define RK3576_SW_BURST_CTRL BIT(1)
2408766792cSChaoyi Chen #define RK3576_DSP_OUT_LOW BIT(0)
2418766792cSChaoyi Chen
2428766792cSChaoyi Chen #define RK3576_SW_AXI_RD_URGENCY_EN BIT(24)
2438766792cSChaoyi Chen #define RK3576_SW_AXI_MAX_OUTSTAND_NUM(x) UPDATE(x, 20, 16)
2448766792cSChaoyi Chen #define RK3576_SW_AXI_MAX_OUTSTAND_EN BIT(12)
2458766792cSChaoyi Chen #define RK3576_SW_NOC_HURRY_THRESHOLD(x) UPDATE(x, 11, 8)
2468766792cSChaoyi Chen #define RK3576_SW_NOC_HURRY_VALUE(x) UPDATE(x, 6, 5)
2478766792cSChaoyi Chen #define RK3576_SW_NOC_HURRY_EN BIT(4)
2488766792cSChaoyi Chen #define RK3576_SW_NOC_QOS_VALUE(x) UPDATE(x, 2, 1)
2498766792cSChaoyi Chen #define RK3576_SW_NOC_QOS_EN BIT(0)
2508766792cSChaoyi Chen
25193a7515aSWenping Zhang #define PMU_BASE_ADDR 0xfdd90000
25293a7515aSWenping Zhang #define PMU_PWR_GATE_SFTCON 0xA0
25393a7515aSWenping Zhang #define PMU_PWR_DWN_ST 0x98
25493a7515aSWenping Zhang #define RGA_PD_OFF BIT(5)
25593a7515aSWenping Zhang #define RGA_PD_STAT BIT(5)
25693a7515aSWenping Zhang enum ebc_win_data_fmt {
25793a7515aSWenping Zhang Y_DATA_4BPP = 0,
25893a7515aSWenping Zhang Y_DATA_8BPP = 1,
25993a7515aSWenping Zhang RGB888 = 2,
26093a7515aSWenping Zhang RGB565 = 3,
26193a7515aSWenping Zhang };
26293a7515aSWenping Zhang
26339939100SWenping Zhang static volatile int last_frame_done = -1;
regs_dump(struct ebc_tcon_priv * tcon)26493a7515aSWenping Zhang static inline void regs_dump(struct ebc_tcon_priv *tcon)
26593a7515aSWenping Zhang {
26693a7515aSWenping Zhang int i;
26793a7515aSWenping Zhang
26893a7515aSWenping Zhang printf("dump registers:\n");
26993a7515aSWenping Zhang for (i = 0; i <= EBC_WIN_MST2; i = i + 4) {
27093a7515aSWenping Zhang if (!(i % 16))
27193a7515aSWenping Zhang printf("\n 0x%p:\t", tcon->reg + i);
27293a7515aSWenping Zhang printf("0x%x\t", readl(tcon->reg + i));
27393a7515aSWenping Zhang }
27493a7515aSWenping Zhang printf("\nlut data:\n");
27593a7515aSWenping Zhang for (i = 0x1000; i <= 0x1100; i = i + 4) {
27693a7515aSWenping Zhang if (!(i % 16))
27793a7515aSWenping Zhang printf("\n 0x%p:\t", tcon->reg + i);
27893a7515aSWenping Zhang printf("0x%x\t", readl(tcon->reg + i));
27993a7515aSWenping Zhang }
28093a7515aSWenping Zhang printf("\n");
28193a7515aSWenping Zhang }
28293a7515aSWenping Zhang
2831a77b5f7SChaoyi Chen /* RK356X ebc power domain is enabled by default when power up */
ebc_power_domain(int on)2841a77b5f7SChaoyi Chen static int __maybe_unused ebc_power_domain(int on)
28593a7515aSWenping Zhang {
28693a7515aSWenping Zhang u32 pd_reg;
28793a7515aSWenping Zhang u32 pd_stat;
28893a7515aSWenping Zhang int delay = 0;
28993a7515aSWenping Zhang
29093a7515aSWenping Zhang if (on) {
29193a7515aSWenping Zhang pd_reg = RGA_PD_OFF << 16;
29293a7515aSWenping Zhang pd_stat = RGA_PD_STAT;
29393a7515aSWenping Zhang } else {
29493a7515aSWenping Zhang pd_reg = RGA_PD_OFF | (RGA_PD_OFF << 16);
29593a7515aSWenping Zhang pd_stat = ~((u32)RGA_PD_STAT);
29693a7515aSWenping Zhang }
29793a7515aSWenping Zhang
29893a7515aSWenping Zhang /* enable rga pd for ebc tcon*/
29993a7515aSWenping Zhang writel(pd_reg, PMU_BASE_ADDR + PMU_PWR_GATE_SFTCON);
30093a7515aSWenping Zhang delay = 1000;
30193a7515aSWenping Zhang do {
30293a7515aSWenping Zhang udelay(1);
30393a7515aSWenping Zhang delay--;
30493a7515aSWenping Zhang if (delay == 0) {
30593a7515aSWenping Zhang printf("Enable rga pd for ebc failed !\n");
30693a7515aSWenping Zhang return -1;
30793a7515aSWenping Zhang }
30893a7515aSWenping Zhang } while (readl(PMU_BASE_ADDR + PMU_PWR_DWN_ST) & pd_stat);
30993a7515aSWenping Zhang
31093a7515aSWenping Zhang return 0;
31193a7515aSWenping Zhang }
31293a7515aSWenping Zhang
tcon_write(struct ebc_tcon_priv * tcon,unsigned int reg,unsigned int value)31393a7515aSWenping Zhang static inline void tcon_write(struct ebc_tcon_priv *tcon, unsigned int reg,
31493a7515aSWenping Zhang unsigned int value)
31593a7515aSWenping Zhang {
31693a7515aSWenping Zhang unsigned int *cache = tcon->regcache + (reg >> 2);
31793a7515aSWenping Zhang
31893a7515aSWenping Zhang writel(value, tcon->reg + reg);
31993a7515aSWenping Zhang *cache = value;
32093a7515aSWenping Zhang }
32193a7515aSWenping Zhang
tcon_read(struct ebc_tcon_priv * tcon,unsigned int reg)32293a7515aSWenping Zhang static inline unsigned int tcon_read(struct ebc_tcon_priv *tcon,
32393a7515aSWenping Zhang unsigned int reg)
32493a7515aSWenping Zhang {
32593a7515aSWenping Zhang return readl(tcon->reg + reg);
32693a7515aSWenping Zhang }
32793a7515aSWenping Zhang
tcon_update_bits(struct ebc_tcon_priv * tcon,unsigned int reg,unsigned int mask,unsigned int val)32893a7515aSWenping Zhang static inline void tcon_update_bits(struct ebc_tcon_priv *tcon,
32993a7515aSWenping Zhang unsigned int reg, unsigned int mask,
33093a7515aSWenping Zhang unsigned int val)
33193a7515aSWenping Zhang {
33293a7515aSWenping Zhang unsigned int tmp;
33393a7515aSWenping Zhang unsigned int *cache = tcon->regcache + (reg >> 2);
33493a7515aSWenping Zhang
33593a7515aSWenping Zhang tmp = *cache & ~mask;
33693a7515aSWenping Zhang tmp |= val & mask;
33793a7515aSWenping Zhang
33893a7515aSWenping Zhang writel(tmp, tcon->reg + reg);
33993a7515aSWenping Zhang *cache = tmp;
34093a7515aSWenping Zhang }
34193a7515aSWenping Zhang
34293a7515aSWenping Zhang #ifdef CONFIG_IRQ
ebc_irq_handler(int irq,void * data)34393a7515aSWenping Zhang static void ebc_irq_handler(int irq, void *data)
34493a7515aSWenping Zhang {
34593a7515aSWenping Zhang u32 intr_status;
34693a7515aSWenping Zhang struct udevice *dev = data;
34793a7515aSWenping Zhang struct ebc_tcon_priv *tcon = dev_get_priv(dev);
34893a7515aSWenping Zhang
34993a7515aSWenping Zhang intr_status = readl(tcon->reg + EBC_INT_STATUS);
35093a7515aSWenping Zhang
35193a7515aSWenping Zhang if (intr_status & DSP_END_INT) {
35293a7515aSWenping Zhang tcon_update_bits(tcon, EBC_INT_STATUS,
35393a7515aSWenping Zhang DSP_END_INT_CLR, DSP_END_INT_CLR);
35439939100SWenping Zhang last_frame_done = 1;
35593a7515aSWenping Zhang }
35693a7515aSWenping Zhang }
35793a7515aSWenping Zhang #endif
35893a7515aSWenping Zhang
tcon_cfg_done(struct ebc_tcon_priv * tcon)35993a7515aSWenping Zhang static inline void tcon_cfg_done(struct ebc_tcon_priv *tcon)
36093a7515aSWenping Zhang {
36193a7515aSWenping Zhang writel(REG_LOAD_GLOBAL_EN, tcon->reg + EBC_CONFIG_DONE);
36293a7515aSWenping Zhang }
36393a7515aSWenping Zhang
3648766792cSChaoyi Chen #ifdef CONFIG_ROCKCHIP_RK3568
ebc_tcon_enable(struct udevice * dev,struct ebc_panel * panel)36593a7515aSWenping Zhang static int ebc_tcon_enable(struct udevice *dev, struct ebc_panel *panel)
36693a7515aSWenping Zhang {
367f968f3bcSZorro Liu int ret;
36893a7515aSWenping Zhang struct ebc_tcon_priv *tcon = dev_get_priv(dev);
369dfc47936SZorro Liu u32 width, height, vir_width, vir_height;
370dfc47936SZorro Liu
371dfc47936SZorro Liu if (panel->rearrange) {
372dfc47936SZorro Liu width = panel->width * 2;
373dfc47936SZorro Liu height = panel->height / 2;
374dfc47936SZorro Liu vir_width = panel->vir_width * 2;
375dfc47936SZorro Liu vir_height = panel->vir_height / 2;
376dfc47936SZorro Liu } else {
377dfc47936SZorro Liu width = panel->width;
378dfc47936SZorro Liu height = panel->height;
379dfc47936SZorro Liu vir_width = panel->vir_width;
380dfc47936SZorro Liu vir_height = panel->vir_height;
381dfc47936SZorro Liu }
38293a7515aSWenping Zhang
38393a7515aSWenping Zhang /* panel timing and win info config */
38493a7515aSWenping Zhang tcon_write(tcon, EBC_DSP_HTIMING0,
38593a7515aSWenping Zhang DSP_HTOTAL(panel->lsl + panel->lbl + panel->ldl +
386514e00a9SZorro Liu panel->lel) | DSP_HS_END(panel->lsl));
38793a7515aSWenping Zhang tcon_write(tcon, EBC_DSP_HTIMING1,
38893a7515aSWenping Zhang DSP_HACT_END(panel->lsl + panel->lbl + panel->ldl) |
38993a7515aSWenping Zhang DSP_HACT_ST(panel->lsl + panel->lbl - 1));
39093a7515aSWenping Zhang tcon_write(tcon, EBC_DSP_VTIMING0,
39193a7515aSWenping Zhang DSP_VTOTAL(panel->fsl + panel->fbl + panel->fdl +
39293a7515aSWenping Zhang panel->fel) | DSP_VS_END(panel->fsl));
39393a7515aSWenping Zhang tcon_write(tcon, EBC_DSP_VTIMING1,
39493a7515aSWenping Zhang DSP_VACT_END(panel->fsl + panel->fbl + panel->fdl) |
39593a7515aSWenping Zhang DSP_VACT_ST(panel->fsl + panel->fbl));
39693a7515aSWenping Zhang tcon_write(tcon, EBC_DSP_ACT_INFO,
397db4dd7a8SChaoyi Chen DSP_HEIGHT(vir_height) |
398db4dd7a8SChaoyi Chen DSP_WIDTH(vir_width));
39993a7515aSWenping Zhang tcon_write(tcon, EBC_WIN_VIR,
400db4dd7a8SChaoyi Chen WIN_VIR_HEIGHT(height) |
401db4dd7a8SChaoyi Chen WIN_VIR_WIDTH(width));
40293a7515aSWenping Zhang tcon_write(tcon, EBC_WIN_ACT,
403dfc47936SZorro Liu WIN_ACT_HEIGHT(height) |
404dfc47936SZorro Liu WIN_ACT_WIDTH(width));
40593a7515aSWenping Zhang tcon_write(tcon, EBC_WIN_DSP,
406dfc47936SZorro Liu WIN_DSP_HEIGHT(height) |
407dfc47936SZorro Liu WIN_DSP_WIDTH(width));
40893a7515aSWenping Zhang tcon_write(tcon, EBC_WIN_DSP_ST,
40993a7515aSWenping Zhang WIN_DSP_YST(panel->fsl + panel->fbl) |
41093a7515aSWenping Zhang WIN_DSP_XST(panel->lsl + panel->lbl));
41193a7515aSWenping Zhang
41293a7515aSWenping Zhang /* win2 fifo is 512x128, win fifo is 256x128,
41393a7515aSWenping Zhang * we set fifo almost value (fifo_size - 16)
41493a7515aSWenping Zhang * burst_reg = 7 mean ahb burst is incr16
41593a7515aSWenping Zhang */
41693a7515aSWenping Zhang tcon_write(tcon, EBC_WIN_CTRL,
41793a7515aSWenping Zhang WIN2_FIFO_ALMOST_FULL_LEVEL(496) | WIN_EN(1) |
41893a7515aSWenping Zhang BURST_REG(7) | WIN_FIFO_ALMOST_FULL_LEVEL(240) |
41993a7515aSWenping Zhang WIN_FMT(Y_DATA_4BPP));
42093a7515aSWenping Zhang
42193a7515aSWenping Zhang /*
42293a7515aSWenping Zhang * EBC_EPD_CTRL info:
42393a7515aSWenping Zhang * DSP_GD_ST: GCLK rising edge point(SCLK), which count from
42493a7515aSWenping Zhang * the rasing edge of hsync(spec is wrong, count
42593a7515aSWenping Zhang * from rasing edge of hsync, not falling edge of hsync)
42693a7515aSWenping Zhang * DSP_GD_END : GCLK falling edge point(SCLK), which count from
42793a7515aSWenping Zhang * the rasing edge of hsync
42893a7515aSWenping Zhang * DSP_THREE_WIN_MODE: 0: lut mode or direct mode; 1: three win mode
42993a7515aSWenping Zhang * DSP_SDDW_MODE: 0: 8 bit data output; 1: 16 bit data output
43093a7515aSWenping Zhang * EPD_AUO: 0: EINK; 1:AUO
43193a7515aSWenping Zhang * EPD_GDRL: gate scanning direction: 1:button to top 0:top to button
43293a7515aSWenping Zhang * EPD_SDSHR: source scanning direction 1:right to left 0:left to right
43393a7515aSWenping Zhang */
43493a7515aSWenping Zhang tcon_write(tcon, EBC_EPD_CTRL,
43593a7515aSWenping Zhang EINK_MODE_SWAP(1) |
43693a7515aSWenping Zhang DSP_GD_ST(panel->lsl + panel->gdck_sta) |
43793a7515aSWenping Zhang DSP_GD_END(panel->lsl + panel->gdck_sta + panel->lgonl) |
43893a7515aSWenping Zhang DSP_THREE_WIN_MODE(0) |
43993a7515aSWenping Zhang DSP_SDDW_MODE(!!panel->panel_16bit) |
44093a7515aSWenping Zhang EPD_AUO(0) |
44193a7515aSWenping Zhang EPD_GDRL(1) |
44293a7515aSWenping Zhang EPD_SDSHR(1));
44393a7515aSWenping Zhang tcon_write(tcon, EBC_DSP_START,
44493a7515aSWenping Zhang DSP_SDCE_WIDTH(panel->ldl) | SW_BURST_CTRL);
44593a7515aSWenping Zhang
44693a7515aSWenping Zhang tcon_write(tcon, EBC_DSP_CTRL,
44793a7515aSWenping Zhang DSP_SWAP_MODE(panel->panel_16bit ? 2 : 3) |
44893a7515aSWenping Zhang DSP_VCOM_MODE(1) |
44993a7515aSWenping Zhang DSP_SDCLK_DIV(panel->panel_16bit ? 7 : 3));
45093a7515aSWenping Zhang
45193a7515aSWenping Zhang tcon_cfg_done(tcon);
45293a7515aSWenping Zhang
453f968f3bcSZorro Liu ret = clk_set_rate(&tcon->dclk, panel->sdck * ((panel->panel_16bit ? 7 : 3) + 1));
454f968f3bcSZorro Liu if (ret < 0) {
455f968f3bcSZorro Liu printf("%s: set clock rate failed, %d\n", __func__, ret);
456f968f3bcSZorro Liu return ret;
457f968f3bcSZorro Liu }
458f968f3bcSZorro Liu
45993a7515aSWenping Zhang return 0;
46093a7515aSWenping Zhang }
4618766792cSChaoyi Chen #endif
46293a7515aSWenping Zhang
ebc_tcon_disable(struct udevice * dev)46393a7515aSWenping Zhang static int ebc_tcon_disable(struct udevice *dev)
46493a7515aSWenping Zhang {
46593a7515aSWenping Zhang return 0;
46693a7515aSWenping Zhang }
46793a7515aSWenping Zhang
4688766792cSChaoyi Chen #ifdef CONFIG_ROCKCHIP_RK3568
ebc_tcon_dsp_mode_set(struct udevice * dev,int update_mode,int display_mode,int three_win_mode,int eink_mode)46993a7515aSWenping Zhang static int ebc_tcon_dsp_mode_set(struct udevice *dev, int update_mode,
47093a7515aSWenping Zhang int display_mode, int three_win_mode,
47193a7515aSWenping Zhang int eink_mode)
47293a7515aSWenping Zhang {
47393a7515aSWenping Zhang struct ebc_tcon_priv *tcon = dev_get_priv(dev);
47493a7515aSWenping Zhang
47593a7515aSWenping Zhang tcon_update_bits(tcon, EBC_DSP_CTRL,
47693a7515aSWenping Zhang UPDATE_MODE_MASK | DISPLAY_MODE_MASK,
47793a7515aSWenping Zhang DSP_UPDATE_MODE(!!update_mode) |
47893a7515aSWenping Zhang DSP_DISPLAY_MODE(!!display_mode));
47993a7515aSWenping Zhang
48093a7515aSWenping Zhang tcon_update_bits(tcon, EBC_EPD_CTRL, THREE_WIN_MODE_MASK,
48193a7515aSWenping Zhang DSP_THREE_WIN_MODE(!!three_win_mode));
48293a7515aSWenping Zhang /* always set frm start bit 0 before real frame start */
48393a7515aSWenping Zhang tcon_update_bits(tcon, EBC_DSP_START,
48493a7515aSWenping Zhang DSP_EINK_MODE_MASK | DSP_FRM_START_MASK,
48593a7515aSWenping Zhang DSP_EINK_MODE(!!eink_mode));
48693a7515aSWenping Zhang tcon_cfg_done(tcon);
48793a7515aSWenping Zhang
48893a7515aSWenping Zhang return 0;
48993a7515aSWenping Zhang }
4908766792cSChaoyi Chen #endif
49193a7515aSWenping Zhang
ebc_tcon_image_addr_set(struct udevice * dev,u32 pre_image_addr,u32 cur_image_addr)49293a7515aSWenping Zhang static int ebc_tcon_image_addr_set(struct udevice *dev, u32 pre_image_addr,
49393a7515aSWenping Zhang u32 cur_image_addr)
49493a7515aSWenping Zhang {
49593a7515aSWenping Zhang struct ebc_tcon_priv *tcon = dev_get_priv(dev);
49693a7515aSWenping Zhang
49793a7515aSWenping Zhang tcon_write(tcon, EBC_WIN_MST0, pre_image_addr);
49893a7515aSWenping Zhang tcon_write(tcon, EBC_WIN_MST1, cur_image_addr);
49993a7515aSWenping Zhang tcon_cfg_done(tcon);
50093a7515aSWenping Zhang
50193a7515aSWenping Zhang return 0;
50293a7515aSWenping Zhang }
50393a7515aSWenping Zhang
ebc_tcon_frame_addr_set(struct udevice * dev,u32 frame_addr)50493a7515aSWenping Zhang static int ebc_tcon_frame_addr_set(struct udevice *dev, u32 frame_addr)
50593a7515aSWenping Zhang {
50693a7515aSWenping Zhang struct ebc_tcon_priv *tcon = dev_get_priv(dev);
50793a7515aSWenping Zhang
50893a7515aSWenping Zhang tcon_write(tcon, EBC_WIN_MST2, frame_addr);
50993a7515aSWenping Zhang tcon_cfg_done(tcon);
51093a7515aSWenping Zhang
51193a7515aSWenping Zhang return 0;
51293a7515aSWenping Zhang }
51393a7515aSWenping Zhang
ebc_tcon_lut_data_set(struct udevice * dev,unsigned int * lut_data,int frame_count,int lut_32)51493a7515aSWenping Zhang static int ebc_tcon_lut_data_set(struct udevice *dev, unsigned int *lut_data,
51593a7515aSWenping Zhang int frame_count, int lut_32)
51693a7515aSWenping Zhang {
51793a7515aSWenping Zhang int i, lut_size;
51893a7515aSWenping Zhang struct ebc_tcon_priv *tcon = dev_get_priv(dev);
51993a7515aSWenping Zhang
52093a7515aSWenping Zhang if ((!lut_32 && frame_count > 256) || (lut_32 && frame_count > 64)) {
52193a7515aSWenping Zhang dev_err(tcon->dev, "frame count over flow\n");
52293a7515aSWenping Zhang return -1;
52393a7515aSWenping Zhang }
52493a7515aSWenping Zhang
52593a7515aSWenping Zhang if (lut_32)
52693a7515aSWenping Zhang lut_size = frame_count * 64;
52793a7515aSWenping Zhang else
52893a7515aSWenping Zhang lut_size = frame_count * 16;
52993a7515aSWenping Zhang
53093a7515aSWenping Zhang for (i = 0; i < lut_size; i++)
53193a7515aSWenping Zhang tcon_write(tcon, EBC_LUT_DATA_ADDR + (i * 4), lut_data[i]);
53293a7515aSWenping Zhang
53393a7515aSWenping Zhang tcon_cfg_done(tcon);
53493a7515aSWenping Zhang
53593a7515aSWenping Zhang return 0;
53693a7515aSWenping Zhang }
53793a7515aSWenping Zhang
wait_for_last_frame_complete(struct udevice * dev)53893a7515aSWenping Zhang static int wait_for_last_frame_complete(struct udevice *dev)
53993a7515aSWenping Zhang {
54093a7515aSWenping Zhang #ifndef CONFIG_IRQ
54193a7515aSWenping Zhang u32 intr_status;
54293a7515aSWenping Zhang #endif
54393a7515aSWenping Zhang struct ebc_tcon_priv *tcon = dev_get_priv(dev);
54493a7515aSWenping Zhang
54593a7515aSWenping Zhang #ifdef CONFIG_IRQ
54639939100SWenping Zhang while (1) {
54739939100SWenping Zhang if ((last_frame_done == -1) || (last_frame_done == 1))
54839939100SWenping Zhang break;
54993a7515aSWenping Zhang msleep(1);
55039939100SWenping Zhang }
55193a7515aSWenping Zhang #else
55293a7515aSWenping Zhang /* wait for frame display end*/
55339939100SWenping Zhang while (1) {
55439939100SWenping Zhang /* first frame don't need to wait*/
55539939100SWenping Zhang if (last_frame_done == -1)
55639939100SWenping Zhang break;
55793a7515aSWenping Zhang intr_status = readl(tcon->reg + EBC_INT_STATUS);
55839939100SWenping Zhang if (intr_status & DSP_END_INT)
55939939100SWenping Zhang break;
56039939100SWenping Zhang msleep(1);
56139939100SWenping Zhang }
56293a7515aSWenping Zhang #endif
56393a7515aSWenping Zhang tcon_update_bits(tcon, EBC_INT_STATUS,
56493a7515aSWenping Zhang DSP_END_INT_CLR, DSP_END_INT_CLR);
56593a7515aSWenping Zhang
56693a7515aSWenping Zhang return 0;
56793a7515aSWenping Zhang }
56893a7515aSWenping Zhang
5698766792cSChaoyi Chen #ifdef CONFIG_ROCKCHIP_RK3568
ebc_tcon_frame_start(struct udevice * dev,int frame_total)57093a7515aSWenping Zhang static int ebc_tcon_frame_start(struct udevice *dev, int frame_total)
57193a7515aSWenping Zhang {
57293a7515aSWenping Zhang struct ebc_tcon_priv *tcon = dev_get_priv(dev);
57393a7515aSWenping Zhang
57493a7515aSWenping Zhang tcon_write(tcon, EBC_INT_STATUS,
57593a7515aSWenping Zhang LINE_FLAG_INT_MASK | DSP_FRM_INT_MASK | FRM_END_INT_MASK);
57693a7515aSWenping Zhang tcon_update_bits(tcon, EBC_DSP_START,
57793a7515aSWenping Zhang DSP_FRM_TOTAL_MASK, DSP_FRM_TOTAL(frame_total - 1));
57893a7515aSWenping Zhang tcon_cfg_done(tcon);
57993a7515aSWenping Zhang
58093a7515aSWenping Zhang tcon_update_bits(tcon, EBC_DSP_START,
58193a7515aSWenping Zhang DSP_FRM_START_MASK, DSP_FRM_START);
58239939100SWenping Zhang last_frame_done = 0;
58393a7515aSWenping Zhang return 0;
58493a7515aSWenping Zhang }
5858766792cSChaoyi Chen #endif
5868766792cSChaoyi Chen
5878766792cSChaoyi Chen #ifdef CONFIG_ROCKCHIP_RK3576
rk3576_ebc_tcon_enable(struct udevice * dev,struct ebc_panel * panel)5888766792cSChaoyi Chen static int rk3576_ebc_tcon_enable(struct udevice *dev, struct ebc_panel *panel)
5898766792cSChaoyi Chen {
5908766792cSChaoyi Chen struct ebc_tcon_priv *tcon = dev_get_priv(dev);
5918766792cSChaoyi Chen u32 width, height, vir_width, vir_height;
5920b3fbe3bSChaoyi Chen u32 val;
5930b3fbe3bSChaoyi Chen int ret;
5948766792cSChaoyi Chen
5958766792cSChaoyi Chen if (panel->rearrange) {
5968766792cSChaoyi Chen width = panel->width * 2;
5978766792cSChaoyi Chen height = panel->height / 2;
5988766792cSChaoyi Chen vir_width = panel->vir_width * 2;
5998766792cSChaoyi Chen vir_height = panel->vir_height / 2;
6008766792cSChaoyi Chen } else {
6018766792cSChaoyi Chen width = panel->width;
6028766792cSChaoyi Chen height = panel->height;
6038766792cSChaoyi Chen vir_width = panel->vir_width;
6048766792cSChaoyi Chen vir_height = panel->vir_height;
6058766792cSChaoyi Chen }
6068766792cSChaoyi Chen
6078766792cSChaoyi Chen /* panel timing and win info config */
6088766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_DSP_HTIMING0,
6098766792cSChaoyi Chen RK3576_DSP_HTOTAL(panel->lsl + panel->lbl + panel->ldl + panel->lel) |
6108766792cSChaoyi Chen RK3576_DSP_HS_END(panel->lsl));
6118766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_DSP_HTIMING1,
6128766792cSChaoyi Chen RK3576_DSP_HACT_END(panel->lsl + panel->lbl + panel->ldl) |
6138766792cSChaoyi Chen RK3576_DSP_HACT_ST(panel->lsl + panel->lbl - 1));
6148766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_DSP_VTIMING0,
6158766792cSChaoyi Chen RK3576_DSP_VTOTAL(panel->fsl + panel->fbl + panel->fdl + panel->fel) |
6168766792cSChaoyi Chen RK3576_DSP_VS_END(panel->fsl));
6178766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_DSP_VTIMING1,
6188766792cSChaoyi Chen RK3576_DSP_VACT_END(panel->fsl + panel->fbl + panel->fdl) |
6198766792cSChaoyi Chen RK3576_DSP_VACT_ST(panel->fsl + panel->fbl));
6208766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_DSP_ACT_INFO,
621db4dd7a8SChaoyi Chen RK3576_DSP_HEIGHT(vir_height) |
622db4dd7a8SChaoyi Chen RK3576_DSP_WIDTH(vir_width));
6238766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_WIN_VIR,
624db4dd7a8SChaoyi Chen RK3576_WIN_VIR_HEIGHT(height) |
625db4dd7a8SChaoyi Chen RK3576_WIN_VIR_WIDTH(width));
6268766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_WIN_ACT,
6278766792cSChaoyi Chen RK3576_WIN_ACT_HEIGHT(height) |
6288766792cSChaoyi Chen RK3576_WIN_ACT_WIDTH(width));
6298766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_WIN_DSP,
6308766792cSChaoyi Chen RK3576_WIN_DSP_HEIGHT(height) |
6318766792cSChaoyi Chen RK3576_WIN_DSP_WIDTH(width));
6320b3fbe3bSChaoyi Chen if (width != vir_width || height != vir_height) {
6330b3fbe3bSChaoyi Chen if (((vir_width - width) / 2) % 2)
6340b3fbe3bSChaoyi Chen dev_warn(dev,
6350b3fbe3bSChaoyi Chen "Margin left/right between width/vir_width must be same\n");
6360b3fbe3bSChaoyi Chen if (((vir_height - height) / 2) % 2)
6370b3fbe3bSChaoyi Chen dev_warn(tcon->dev,
6380b3fbe3bSChaoyi Chen "Margin top/bottom between height/vir_height must be same\n");
6390b3fbe3bSChaoyi Chen
6400b3fbe3bSChaoyi Chen val = panel->panel_16bit ? 8 : 4;
6410b3fbe3bSChaoyi Chen if (((vir_width - width) / 2) % val)
6420b3fbe3bSChaoyi Chen dev_warn(dev,
6430b3fbe3bSChaoyi Chen "Margin left/right between width/vir_width must align with %d\n",
6440b3fbe3bSChaoyi Chen val);
6450b3fbe3bSChaoyi Chen
6460b3fbe3bSChaoyi Chen val = RK3576_WIN_DSP_YST(panel->fsl + panel->fbl + (vir_height - height) / 2);
6470b3fbe3bSChaoyi Chen if (panel->panel_16bit)
6480b3fbe3bSChaoyi Chen val |= RK3576_WIN_DSP_XST(panel->lsl + panel->lbl +
6490b3fbe3bSChaoyi Chen (vir_width - width) / 2 / 8);
6500b3fbe3bSChaoyi Chen else
6510b3fbe3bSChaoyi Chen val |= RK3576_WIN_DSP_XST(panel->lsl + panel->lbl +
6520b3fbe3bSChaoyi Chen (vir_width - width) / 2 / 4);
6530b3fbe3bSChaoyi Chen tcon_write(tcon, RK3576_EBC_WIN_DSP_ST, val);
6540b3fbe3bSChaoyi Chen } else {
6558766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_WIN_DSP_ST,
6568766792cSChaoyi Chen RK3576_WIN_DSP_YST(panel->fsl + panel->fbl) |
6578766792cSChaoyi Chen RK3576_WIN_DSP_XST(panel->lsl + panel->lbl));
6580b3fbe3bSChaoyi Chen }
6598766792cSChaoyi Chen
6608766792cSChaoyi Chen /*
6618766792cSChaoyi Chen * win2 fifo is 512x64, win fifo is 256x64,
6628766792cSChaoyi Chen * we set fifo almost value (fifo_size - 16(brust_length))
6638766792cSChaoyi Chen *
6648766792cSChaoyi Chen * dma_burst_length mean axi burst length = 16
6658766792cSChaoyi Chen */
6668766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_WIN_CTRL,
6678766792cSChaoyi Chen RK3576_WIN2_FIFO_ALMOST_FULL_LEVEL(496) |
6688766792cSChaoyi Chen RK3576_DMA_BURST_LENGTH(0) |
6698766792cSChaoyi Chen RK3576_WIN_FIFO_ALMOST_FULL_LEVEL(240) |
6708766792cSChaoyi Chen RK3576_WIN_FMT(Y_DATA_4BPP));
6718766792cSChaoyi Chen
6728766792cSChaoyi Chen /* win0 always enable */
6738766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_WIN0_CTRL, RK3576_WIN_AXI_GATHER_NUM(8) |
6748766792cSChaoyi Chen RK3576_WIN_AXI_GATHER_EN | RK3576_WIN_RID(1) |
6758766792cSChaoyi Chen RK3576_WIN_EN);
6768766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_WIN1_CTRL, RK3576_WIN_RID(2));
6778766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_WIN2_CTRL, RK3576_WIN_RID(3));
6788766792cSChaoyi Chen
6798766792cSChaoyi Chen /*
6808766792cSChaoyi Chen * RK3576_EBC_EPD_CTRL info:
6818766792cSChaoyi Chen * DSP_GD_END : GCLK falling edge point(SCLK), which count from the rising edge of hsync
6828766792cSChaoyi Chen * DSP_GD_ST: GCLK rising edge point(SCLK), which count from the rising edge of hsync
6838766792cSChaoyi Chen * DSP_THREE_WIN_MODE: 0: lut mode or direct mode; 1: three win mode
6848766792cSChaoyi Chen * DSP_SDDW_MODE: 0: 8 bit data output; 1: 16 bit data output
6858766792cSChaoyi Chen * EPD_AUO: 0: EINK; 1:AUO
6868766792cSChaoyi Chen * EPD_GDRL: gate scanning direction: 1: button to top 0: top to button
6878766792cSChaoyi Chen * EPD_SDSHR: source scanning direction 1: right to left 0: left to right
6888766792cSChaoyi Chen */
6898766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_EPD_CTRL, RK3576_EINK_MODE_SWAP(1) |
6908766792cSChaoyi Chen RK3576_DSP_GD_ST(panel->lsl + panel->gdck_sta) |
6918766792cSChaoyi Chen RK3576_DSP_GD_END(panel->lsl + panel->gdck_sta + panel->lgonl) |
6928766792cSChaoyi Chen RK3576_DSP_THREE_WIN_MODE(0) |
6938766792cSChaoyi Chen RK3576_DSP_SDDW_MODE(!!panel->panel_16bit) |
6948766792cSChaoyi Chen RK3576_EPD_AUO(0) |
6958766792cSChaoyi Chen RK3576_EPD_GDRL(1) |
6968766792cSChaoyi Chen RK3576_EPD_SDSHR(1));
6978766792cSChaoyi Chen
6988766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_DSP_START, 0);
6991020d760SChaoyi Chen
7001020d760SChaoyi Chen if (panel->sdce_width == 0)
7011020d760SChaoyi Chen val = RK3576_DSP_SDCE_WIDTH(panel->ldl);
7021020d760SChaoyi Chen else
7031020d760SChaoyi Chen val = RK3576_DSP_SDCE_WIDTH(panel->sdce_width);
7041020d760SChaoyi Chen tcon_write(tcon, RK3576_EBC_DSP_CTRL2, RK3576_SW_BURST_CTRL | val);
7051020d760SChaoyi Chen
7061020d760SChaoyi Chen /**
7071020d760SChaoyi Chen * SDOE_MODE 1 : sdce signal act as vden
7081020d760SChaoyi Chen * SDOE_MODE 0 : sdce signal act as hden
7091020d760SChaoyi Chen */
7101020d760SChaoyi Chen if (panel->sdoe_mode == 1)
7111020d760SChaoyi Chen val = RK3576_DSP_SDOE_MODE(1);
7121020d760SChaoyi Chen else
7131020d760SChaoyi Chen val = RK3576_DSP_SDOE_MODE(0);
7148766792cSChaoyi Chen
7158766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_DSP_CTRL,
7161020d760SChaoyi Chen RK3576_DSP_SWAP_MODE(panel->panel_16bit ? 2 : 3) | RK3576_DSP_VCOM_MODE(1) |
7171020d760SChaoyi Chen RK3576_DSP_SDCLK_DIV(panel->panel_16bit ? 7 : 3) | val);
7188766792cSChaoyi Chen
7198766792cSChaoyi Chen tcon_cfg_done(tcon);
7208766792cSChaoyi Chen
7218766792cSChaoyi Chen ret = clk_set_rate(&tcon->dclk,
7228766792cSChaoyi Chen panel->sdck * ((panel->panel_16bit ? 7 : 3) + 1));
7238766792cSChaoyi Chen if (ret < 0) {
7248766792cSChaoyi Chen printf("%s: set clock rate failed, %d\n", __func__, ret);
7258766792cSChaoyi Chen return ret;
7268766792cSChaoyi Chen }
7278766792cSChaoyi Chen
7288766792cSChaoyi Chen return 0;
7298766792cSChaoyi Chen }
7308766792cSChaoyi Chen
rk3576_ebc_tcon_dsp_mode_set(struct udevice * dev,int update_mode,int display_mode,int three_win_mode,int eink_mode)7318766792cSChaoyi Chen static int rk3576_ebc_tcon_dsp_mode_set(struct udevice *dev, int update_mode,
7328766792cSChaoyi Chen int display_mode, int three_win_mode,
7338766792cSChaoyi Chen int eink_mode)
7348766792cSChaoyi Chen {
7358766792cSChaoyi Chen struct ebc_tcon_priv *tcon = dev_get_priv(dev);
7368766792cSChaoyi Chen
7378766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_WIN1_CTRL, RK3576_WIN_AXI_GATHER_NUM(8) |
7388766792cSChaoyi Chen RK3576_WIN_AXI_GATHER_EN |
7398766792cSChaoyi Chen RK3576_WIN_RID(2) |
7408766792cSChaoyi Chen ((!!display_mode) | (!!three_win_mode)));
7418766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_WIN2_CTRL, RK3576_WIN_AXI_GATHER_NUM(8) |
7428766792cSChaoyi Chen RK3576_WIN_AXI_GATHER_EN |
7438766792cSChaoyi Chen RK3576_WIN_RID(3) |
7448766792cSChaoyi Chen (!!three_win_mode));
7458766792cSChaoyi Chen
7468766792cSChaoyi Chen tcon_update_bits(tcon, RK3576_EBC_DSP_CTRL,
7478766792cSChaoyi Chen RK3576_UPDATE_MODE_MASK | RK3576_DISPLAY_MODE_MASK,
7488766792cSChaoyi Chen RK3576_DSP_UPDATE_MODE(!!update_mode) |
7498766792cSChaoyi Chen RK3576_DSP_DISPLAY_MODE(!!display_mode));
7508766792cSChaoyi Chen tcon_update_bits(tcon, RK3576_EBC_EPD_CTRL, RK3576_THREE_WIN_MODE_MASK,
7518766792cSChaoyi Chen RK3576_DSP_THREE_WIN_MODE(!!three_win_mode));
7528766792cSChaoyi Chen /* always set frm start bit 0 before real frame start */
7538766792cSChaoyi Chen tcon_update_bits(tcon, RK3576_EBC_DSP_CTRL2, RK3576_DSP_EINK_MODE_MASK,
7548766792cSChaoyi Chen RK3576_DSP_EINK_MODE(!!eink_mode));
7558766792cSChaoyi Chen tcon_cfg_done(tcon);
7568766792cSChaoyi Chen
7578766792cSChaoyi Chen return 0;
7588766792cSChaoyi Chen }
7598766792cSChaoyi Chen
rk3576_ebc_tcon_frame_start(struct udevice * dev,int frame_total)7608766792cSChaoyi Chen static int rk3576_ebc_tcon_frame_start(struct udevice *dev, int frame_total)
7618766792cSChaoyi Chen {
7628766792cSChaoyi Chen struct ebc_tcon_priv *tcon = dev_get_priv(dev);
7638766792cSChaoyi Chen
7648766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_INT_STATUS, RK3576_LINE_FLAG_INT_MASK |
7658766792cSChaoyi Chen RK3576_DSP_FRM_INT_MASK | RK3576_FRM_END_INT_MASK |
7668766792cSChaoyi Chen RK3576_WIN2_EMPTY_INT_MASK | RK3576_WIN1_EMPTY_INT_MASK |
7678766792cSChaoyi Chen RK3576_WIN0_EMPTY_INT_MASK);
7688766792cSChaoyi Chen /* always set frm start bit 0 before real frame start */
7698766792cSChaoyi Chen tcon_update_bits(tcon, RK3576_EBC_DSP_CTRL2, RK3576_DSP_FRM_TOTAL_MASK,
7708766792cSChaoyi Chen RK3576_DSP_FRM_TOTAL(frame_total - 1));
7718766792cSChaoyi Chen tcon_cfg_done(tcon);
7728766792cSChaoyi Chen
7738766792cSChaoyi Chen last_frame_done = 0;
7748766792cSChaoyi Chen tcon_write(tcon, RK3576_EBC_DSP_START, 1);
7758766792cSChaoyi Chen
7768766792cSChaoyi Chen return 0;
7778766792cSChaoyi Chen }
7788766792cSChaoyi Chen #endif
77993a7515aSWenping Zhang
rk_ebc_tcon_probe(struct udevice * dev)78093a7515aSWenping Zhang static int rk_ebc_tcon_probe(struct udevice *dev)
78193a7515aSWenping Zhang {
78293a7515aSWenping Zhang int ret;
78393a7515aSWenping Zhang struct ebc_tcon_priv *priv = dev_get_priv(dev);
7841a77b5f7SChaoyi Chen struct driver *driver = (struct driver *)dev->driver;
7851a77b5f7SChaoyi Chen const struct rk_ebc_tcon_ops *tcon_ops;
7861a77b5f7SChaoyi Chen #ifdef CONFIG_IRQ
7871a77b5f7SChaoyi Chen u32 interrupt[2];
7881a77b5f7SChaoyi Chen int irq;
7891a77b5f7SChaoyi Chen #endif
79093a7515aSWenping Zhang
7911a77b5f7SChaoyi Chen tcon_ops = (const struct rk_ebc_tcon_ops *)dev_get_driver_data(dev);
7921a77b5f7SChaoyi Chen driver->ops = tcon_ops;
79393a7515aSWenping Zhang
79493a7515aSWenping Zhang priv->dev = dev;
795*be899ebcSChaoyi Chen
796*be899ebcSChaoyi Chen /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
797*be899ebcSChaoyi Chen ret = clk_set_defaults(dev);
798*be899ebcSChaoyi Chen if (ret)
799*be899ebcSChaoyi Chen dev_warn(dev, "clk_set_defaults failed %d\n", ret);
800*be899ebcSChaoyi Chen
8011a77b5f7SChaoyi Chen ret = clk_get_by_name(dev, "dclk", &priv->dclk);
802f968f3bcSZorro Liu if (ret < 0) {
803f968f3bcSZorro Liu printf("%s get clock fail! %d\n", __func__, ret);
804f968f3bcSZorro Liu return -EINVAL;
805f968f3bcSZorro Liu }
80693a7515aSWenping Zhang
80793a7515aSWenping Zhang #ifdef CONFIG_IRQ
8081a77b5f7SChaoyi Chen ret = dev_read_u32_array(dev, "interrupts", interrupt, 2);
8091a77b5f7SChaoyi Chen if (ret) {
8101a77b5f7SChaoyi Chen printf("read ebc irq failed:%d\n", ret);
8111a77b5f7SChaoyi Chen return ret;
8121a77b5f7SChaoyi Chen }
8131a77b5f7SChaoyi Chen
8141a77b5f7SChaoyi Chen /* convert to Shared Peripheral Interrupt */
8151a77b5f7SChaoyi Chen irq = interrupt[1] + 32;
8161a77b5f7SChaoyi Chen irq_install_handler(irq, ebc_irq_handler, dev);
8171a77b5f7SChaoyi Chen irq_handler_enable(irq);
81893a7515aSWenping Zhang #endif
81993a7515aSWenping Zhang return 0;
82093a7515aSWenping Zhang }
82193a7515aSWenping Zhang
8228766792cSChaoyi Chen #ifdef CONFIG_ROCKCHIP_RK3568
8238766792cSChaoyi Chen const struct rk_ebc_tcon_ops rk3568_ebc_tcon_funcs = {
82493a7515aSWenping Zhang .enable = ebc_tcon_enable,
82593a7515aSWenping Zhang .disable = ebc_tcon_disable,
82693a7515aSWenping Zhang .dsp_mode_set = ebc_tcon_dsp_mode_set,
82793a7515aSWenping Zhang .image_addr_set = ebc_tcon_image_addr_set,
82893a7515aSWenping Zhang .frame_addr_set = ebc_tcon_frame_addr_set,
82993a7515aSWenping Zhang .lut_data_set = ebc_tcon_lut_data_set,
83093a7515aSWenping Zhang .frame_start = ebc_tcon_frame_start,
83193a7515aSWenping Zhang .wait_for_last_frame_complete = wait_for_last_frame_complete,
83293a7515aSWenping Zhang };
8338766792cSChaoyi Chen #endif
8348766792cSChaoyi Chen
8358766792cSChaoyi Chen #ifdef CONFIG_ROCKCHIP_RK3576
8368766792cSChaoyi Chen const struct rk_ebc_tcon_ops rk3576_ebc_tcon_funcs = {
8378766792cSChaoyi Chen .enable = rk3576_ebc_tcon_enable,
8388766792cSChaoyi Chen .disable = ebc_tcon_disable,
8398766792cSChaoyi Chen .dsp_mode_set = rk3576_ebc_tcon_dsp_mode_set,
8408766792cSChaoyi Chen .image_addr_set = ebc_tcon_image_addr_set,
8418766792cSChaoyi Chen .frame_addr_set = ebc_tcon_frame_addr_set,
8428766792cSChaoyi Chen .lut_data_set = ebc_tcon_lut_data_set,
8438766792cSChaoyi Chen .frame_start = rk3576_ebc_tcon_frame_start,
8448766792cSChaoyi Chen .wait_for_last_frame_complete = wait_for_last_frame_complete,
8458766792cSChaoyi Chen };
8468766792cSChaoyi Chen #endif
84793a7515aSWenping Zhang
rk_ebc_tcon_ofdata_to_platdata(struct udevice * dev)84893a7515aSWenping Zhang static int rk_ebc_tcon_ofdata_to_platdata(struct udevice *dev)
84993a7515aSWenping Zhang {
85093a7515aSWenping Zhang fdt_size_t size;
85193a7515aSWenping Zhang fdt_addr_t addr;
85293a7515aSWenping Zhang struct ebc_tcon_priv *priv = dev_get_priv(dev);
85393a7515aSWenping Zhang
85493a7515aSWenping Zhang priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
85593a7515aSWenping Zhang if (priv->grf <= 0) {
85693a7515aSWenping Zhang debug("%s: Get syscon grf failed (ret=%p)\n",
85793a7515aSWenping Zhang __func__, priv->grf);
85893a7515aSWenping Zhang return -ENXIO;
85993a7515aSWenping Zhang }
86093a7515aSWenping Zhang priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
86193a7515aSWenping Zhang if (priv->pmugrf <= 0) {
86293a7515aSWenping Zhang debug("%s: Get syscon pmugrf failed (ret=%p)\n",
86393a7515aSWenping Zhang __func__, priv->grf);
86493a7515aSWenping Zhang return -ENXIO;
86593a7515aSWenping Zhang }
86693a7515aSWenping Zhang addr = dev_read_addr_size(dev, "reg", &size);
86793a7515aSWenping Zhang if (addr == FDT_ADDR_T_NONE) {
86893a7515aSWenping Zhang debug("%s: Get ebc_tcon address failed\n", __func__);
86993a7515aSWenping Zhang return -ENXIO;
87093a7515aSWenping Zhang }
87193a7515aSWenping Zhang
87293a7515aSWenping Zhang priv->reg = ioremap(addr, size);
87393a7515aSWenping Zhang priv->reg_len = size;
87493a7515aSWenping Zhang priv->regcache = malloc(size);
87593a7515aSWenping Zhang memset(priv->regcache, 0, size);
87693a7515aSWenping Zhang return 0;
87793a7515aSWenping Zhang }
87893a7515aSWenping Zhang
87993a7515aSWenping Zhang static const struct udevice_id ebc_tcon_ids[] = {
8808766792cSChaoyi Chen #ifdef CONFIG_ROCKCHIP_RK3568
8811a77b5f7SChaoyi Chen {
8821a77b5f7SChaoyi Chen .compatible = "rockchip,rk3568-ebc-tcon",
8838766792cSChaoyi Chen .data = (ulong)&rk3568_ebc_tcon_funcs,
8841a77b5f7SChaoyi Chen },
8858766792cSChaoyi Chen #endif
8868766792cSChaoyi Chen #ifdef CONFIG_ROCKCHIP_RK3576
8878766792cSChaoyi Chen {
8888766792cSChaoyi Chen .compatible = "rockchip,rk3576-ebc-tcon",
8898766792cSChaoyi Chen .data = (ulong)&rk3576_ebc_tcon_funcs,
8908766792cSChaoyi Chen },
8918766792cSChaoyi Chen #endif
89293a7515aSWenping Zhang {}
89393a7515aSWenping Zhang };
89493a7515aSWenping Zhang
89593a7515aSWenping Zhang U_BOOT_DRIVER(rk_ebc_tcon) = {
89693a7515aSWenping Zhang .name = "rk_ebc_tcon",
89793a7515aSWenping Zhang .id = UCLASS_EBC,
89893a7515aSWenping Zhang .of_match = ebc_tcon_ids,
89993a7515aSWenping Zhang .ofdata_to_platdata = rk_ebc_tcon_ofdata_to_platdata,
90093a7515aSWenping Zhang .probe = rk_ebc_tcon_probe,
90193a7515aSWenping Zhang .priv_auto_alloc_size = sizeof(struct ebc_tcon_priv),
90293a7515aSWenping Zhang };
90393a7515aSWenping Zhang
90493a7515aSWenping Zhang UCLASS_DRIVER(ebc_tcon) = {
90593a7515aSWenping Zhang .id = UCLASS_EBC,
90693a7515aSWenping Zhang .name = "ebc_tcon",
90793a7515aSWenping Zhang };
90893a7515aSWenping Zhang
909