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 13993a7515aSWenping Zhang #define PMU_BASE_ADDR 0xfdd90000 14093a7515aSWenping Zhang #define PMU_PWR_GATE_SFTCON 0xA0 14193a7515aSWenping Zhang #define PMU_PWR_DWN_ST 0x98 14293a7515aSWenping Zhang #define RGA_PD_OFF BIT(5) 14393a7515aSWenping Zhang #define RGA_PD_STAT BIT(5) 14493a7515aSWenping Zhang enum ebc_win_data_fmt { 14593a7515aSWenping Zhang Y_DATA_4BPP = 0, 14693a7515aSWenping Zhang Y_DATA_8BPP = 1, 14793a7515aSWenping Zhang RGB888 = 2, 14893a7515aSWenping Zhang RGB565 = 3, 14993a7515aSWenping Zhang }; 15093a7515aSWenping Zhang 15193a7515aSWenping Zhang #ifdef CONFIG_IRQ 15293a7515aSWenping Zhang #define IRQ_EBC 49 15393a7515aSWenping Zhang #endif 15439939100SWenping Zhang static volatile int last_frame_done = -1; 15593a7515aSWenping Zhang static inline void regs_dump(struct ebc_tcon_priv *tcon) 15693a7515aSWenping Zhang { 15793a7515aSWenping Zhang int i; 15893a7515aSWenping Zhang 15993a7515aSWenping Zhang printf("dump registers:\n"); 16093a7515aSWenping Zhang for (i = 0; i <= EBC_WIN_MST2; i = i + 4) { 16193a7515aSWenping Zhang if (!(i % 16)) 16293a7515aSWenping Zhang printf("\n 0x%p:\t", tcon->reg + i); 16393a7515aSWenping Zhang printf("0x%x\t", readl(tcon->reg + i)); 16493a7515aSWenping Zhang } 16593a7515aSWenping Zhang printf("\nlut data:\n"); 16693a7515aSWenping Zhang for (i = 0x1000; i <= 0x1100; i = i + 4) { 16793a7515aSWenping Zhang if (!(i % 16)) 16893a7515aSWenping Zhang printf("\n 0x%p:\t", tcon->reg + i); 16993a7515aSWenping Zhang printf("0x%x\t", readl(tcon->reg + i)); 17093a7515aSWenping Zhang } 17193a7515aSWenping Zhang printf("\n"); 17293a7515aSWenping Zhang } 17393a7515aSWenping Zhang 17493a7515aSWenping Zhang static int ebc_power_domain(int on) 17593a7515aSWenping Zhang { 17693a7515aSWenping Zhang u32 pd_reg; 17793a7515aSWenping Zhang u32 pd_stat; 17893a7515aSWenping Zhang int delay = 0; 17993a7515aSWenping Zhang 18093a7515aSWenping Zhang if (on) { 18193a7515aSWenping Zhang pd_reg = RGA_PD_OFF << 16; 18293a7515aSWenping Zhang pd_stat = RGA_PD_STAT; 18393a7515aSWenping Zhang } else { 18493a7515aSWenping Zhang pd_reg = RGA_PD_OFF | (RGA_PD_OFF << 16); 18593a7515aSWenping Zhang pd_stat = ~((u32)RGA_PD_STAT); 18693a7515aSWenping Zhang } 18793a7515aSWenping Zhang 18893a7515aSWenping Zhang /* enable rga pd for ebc tcon*/ 18993a7515aSWenping Zhang writel(pd_reg, PMU_BASE_ADDR + PMU_PWR_GATE_SFTCON); 19093a7515aSWenping Zhang delay = 1000; 19193a7515aSWenping Zhang do { 19293a7515aSWenping Zhang udelay(1); 19393a7515aSWenping Zhang delay--; 19493a7515aSWenping Zhang if (delay == 0) { 19593a7515aSWenping Zhang printf("Enable rga pd for ebc failed !\n"); 19693a7515aSWenping Zhang return -1; 19793a7515aSWenping Zhang } 19893a7515aSWenping Zhang } while (readl(PMU_BASE_ADDR + PMU_PWR_DWN_ST) & pd_stat); 19993a7515aSWenping Zhang 20093a7515aSWenping Zhang return 0; 20193a7515aSWenping Zhang } 20293a7515aSWenping Zhang 20393a7515aSWenping Zhang static inline void tcon_write(struct ebc_tcon_priv *tcon, unsigned int reg, 20493a7515aSWenping Zhang unsigned int value) 20593a7515aSWenping Zhang { 20693a7515aSWenping Zhang unsigned int *cache = tcon->regcache + (reg >> 2); 20793a7515aSWenping Zhang 20893a7515aSWenping Zhang writel(value, tcon->reg + reg); 20993a7515aSWenping Zhang *cache = value; 21093a7515aSWenping Zhang } 21193a7515aSWenping Zhang 21293a7515aSWenping Zhang static inline unsigned int tcon_read(struct ebc_tcon_priv *tcon, 21393a7515aSWenping Zhang unsigned int reg) 21493a7515aSWenping Zhang { 21593a7515aSWenping Zhang return readl(tcon->reg + reg); 21693a7515aSWenping Zhang } 21793a7515aSWenping Zhang 21893a7515aSWenping Zhang static inline void tcon_update_bits(struct ebc_tcon_priv *tcon, 21993a7515aSWenping Zhang unsigned int reg, unsigned int mask, 22093a7515aSWenping Zhang unsigned int val) 22193a7515aSWenping Zhang { 22293a7515aSWenping Zhang unsigned int tmp; 22393a7515aSWenping Zhang unsigned int *cache = tcon->regcache + (reg >> 2); 22493a7515aSWenping Zhang 22593a7515aSWenping Zhang tmp = *cache & ~mask; 22693a7515aSWenping Zhang tmp |= val & mask; 22793a7515aSWenping Zhang 22893a7515aSWenping Zhang writel(tmp, tcon->reg + reg); 22993a7515aSWenping Zhang *cache = tmp; 23093a7515aSWenping Zhang } 23193a7515aSWenping Zhang 23293a7515aSWenping Zhang #ifdef CONFIG_IRQ 23393a7515aSWenping Zhang static void ebc_irq_handler(int irq, void *data) 23493a7515aSWenping Zhang { 23593a7515aSWenping Zhang u32 intr_status; 23693a7515aSWenping Zhang struct udevice *dev = data; 23793a7515aSWenping Zhang struct ebc_tcon_priv *tcon = dev_get_priv(dev); 23893a7515aSWenping Zhang 23993a7515aSWenping Zhang intr_status = readl(tcon->reg + EBC_INT_STATUS); 24093a7515aSWenping Zhang 24193a7515aSWenping Zhang if (intr_status & DSP_END_INT) { 24293a7515aSWenping Zhang tcon_update_bits(tcon, EBC_INT_STATUS, 24393a7515aSWenping Zhang DSP_END_INT_CLR, DSP_END_INT_CLR); 24439939100SWenping Zhang last_frame_done = 1; 24593a7515aSWenping Zhang } 24693a7515aSWenping Zhang } 24793a7515aSWenping Zhang #endif 24893a7515aSWenping Zhang 24993a7515aSWenping Zhang static inline void tcon_cfg_done(struct ebc_tcon_priv *tcon) 25093a7515aSWenping Zhang { 25193a7515aSWenping Zhang writel(REG_LOAD_GLOBAL_EN, tcon->reg + EBC_CONFIG_DONE); 25293a7515aSWenping Zhang } 25393a7515aSWenping Zhang 25493a7515aSWenping Zhang static int ebc_tcon_enable(struct udevice *dev, struct ebc_panel *panel) 25593a7515aSWenping Zhang { 256f968f3bcSZorro Liu int ret; 25793a7515aSWenping Zhang struct ebc_tcon_priv *tcon = dev_get_priv(dev); 25893a7515aSWenping Zhang 25993a7515aSWenping Zhang /* panel timing and win info config */ 26093a7515aSWenping Zhang tcon_write(tcon, EBC_DSP_HTIMING0, 26193a7515aSWenping Zhang DSP_HTOTAL(panel->lsl + panel->lbl + panel->ldl + 262*514e00a9SZorro Liu panel->lel) | DSP_HS_END(panel->lsl)); 26393a7515aSWenping Zhang tcon_write(tcon, EBC_DSP_HTIMING1, 26493a7515aSWenping Zhang DSP_HACT_END(panel->lsl + panel->lbl + panel->ldl) | 26593a7515aSWenping Zhang DSP_HACT_ST(panel->lsl + panel->lbl - 1)); 26693a7515aSWenping Zhang tcon_write(tcon, EBC_DSP_VTIMING0, 26793a7515aSWenping Zhang DSP_VTOTAL(panel->fsl + panel->fbl + panel->fdl + 26893a7515aSWenping Zhang panel->fel) | DSP_VS_END(panel->fsl)); 26993a7515aSWenping Zhang tcon_write(tcon, EBC_DSP_VTIMING1, 27093a7515aSWenping Zhang DSP_VACT_END(panel->fsl + panel->fbl + panel->fdl) | 27193a7515aSWenping Zhang DSP_VACT_ST(panel->fsl + panel->fbl)); 27293a7515aSWenping Zhang tcon_write(tcon, EBC_DSP_ACT_INFO, 27393a7515aSWenping Zhang DSP_HEIGHT(panel->height) | 27493a7515aSWenping Zhang DSP_WIDTH(panel->width)); 27593a7515aSWenping Zhang tcon_write(tcon, EBC_WIN_VIR, 2769876686dSWenping Zhang WIN_VIR_HEIGHT(panel->vir_height) | 2779876686dSWenping Zhang WIN_VIR_WIDTH(panel->vir_width)); 27893a7515aSWenping Zhang tcon_write(tcon, EBC_WIN_ACT, 27993a7515aSWenping Zhang WIN_ACT_HEIGHT(panel->height) | 28093a7515aSWenping Zhang WIN_ACT_WIDTH(panel->width)); 28193a7515aSWenping Zhang tcon_write(tcon, EBC_WIN_DSP, 28293a7515aSWenping Zhang WIN_DSP_HEIGHT(panel->height) | 28393a7515aSWenping Zhang WIN_DSP_WIDTH(panel->width)); 28493a7515aSWenping Zhang tcon_write(tcon, EBC_WIN_DSP_ST, 28593a7515aSWenping Zhang WIN_DSP_YST(panel->fsl + panel->fbl) | 28693a7515aSWenping Zhang WIN_DSP_XST(panel->lsl + panel->lbl)); 28793a7515aSWenping Zhang 28893a7515aSWenping Zhang /* win2 fifo is 512x128, win fifo is 256x128, 28993a7515aSWenping Zhang * we set fifo almost value (fifo_size - 16) 29093a7515aSWenping Zhang * burst_reg = 7 mean ahb burst is incr16 29193a7515aSWenping Zhang */ 29293a7515aSWenping Zhang tcon_write(tcon, EBC_WIN_CTRL, 29393a7515aSWenping Zhang WIN2_FIFO_ALMOST_FULL_LEVEL(496) | WIN_EN(1) | 29493a7515aSWenping Zhang BURST_REG(7) | WIN_FIFO_ALMOST_FULL_LEVEL(240) | 29593a7515aSWenping Zhang WIN_FMT(Y_DATA_4BPP)); 29693a7515aSWenping Zhang 29793a7515aSWenping Zhang /* 29893a7515aSWenping Zhang * EBC_EPD_CTRL info: 29993a7515aSWenping Zhang * DSP_GD_ST: GCLK rising edge point(SCLK), which count from 30093a7515aSWenping Zhang * the rasing edge of hsync(spec is wrong, count 30193a7515aSWenping Zhang * from rasing edge of hsync, not falling edge of hsync) 30293a7515aSWenping Zhang * DSP_GD_END : GCLK falling edge point(SCLK), which count from 30393a7515aSWenping Zhang * the rasing edge of hsync 30493a7515aSWenping Zhang * DSP_THREE_WIN_MODE: 0: lut mode or direct mode; 1: three win mode 30593a7515aSWenping Zhang * DSP_SDDW_MODE: 0: 8 bit data output; 1: 16 bit data output 30693a7515aSWenping Zhang * EPD_AUO: 0: EINK; 1:AUO 30793a7515aSWenping Zhang * EPD_GDRL: gate scanning direction: 1:button to top 0:top to button 30893a7515aSWenping Zhang * EPD_SDSHR: source scanning direction 1:right to left 0:left to right 30993a7515aSWenping Zhang */ 31093a7515aSWenping Zhang tcon_write(tcon, EBC_EPD_CTRL, 31193a7515aSWenping Zhang EINK_MODE_SWAP(1) | 31293a7515aSWenping Zhang DSP_GD_ST(panel->lsl + panel->gdck_sta) | 31393a7515aSWenping Zhang DSP_GD_END(panel->lsl + panel->gdck_sta + panel->lgonl) | 31493a7515aSWenping Zhang DSP_THREE_WIN_MODE(0) | 31593a7515aSWenping Zhang DSP_SDDW_MODE(!!panel->panel_16bit) | 31693a7515aSWenping Zhang EPD_AUO(0) | 31793a7515aSWenping Zhang EPD_GDRL(1) | 31893a7515aSWenping Zhang EPD_SDSHR(1)); 31993a7515aSWenping Zhang tcon_write(tcon, EBC_DSP_START, 32093a7515aSWenping Zhang DSP_SDCE_WIDTH(panel->ldl) | SW_BURST_CTRL); 32193a7515aSWenping Zhang 32293a7515aSWenping Zhang tcon_write(tcon, EBC_DSP_CTRL, 32393a7515aSWenping Zhang DSP_SWAP_MODE(panel->panel_16bit ? 2 : 3) | 32493a7515aSWenping Zhang DSP_VCOM_MODE(1) | 32593a7515aSWenping Zhang DSP_SDCLK_DIV(panel->panel_16bit ? 7 : 3)); 32693a7515aSWenping Zhang 32793a7515aSWenping Zhang tcon_cfg_done(tcon); 32893a7515aSWenping Zhang 329f968f3bcSZorro Liu ret = clk_set_rate(&tcon->dclk, panel->sdck * ((panel->panel_16bit ? 7 : 3) + 1)); 330f968f3bcSZorro Liu if (ret < 0) { 331f968f3bcSZorro Liu printf("%s: set clock rate failed, %d\n", __func__, ret); 332f968f3bcSZorro Liu return ret; 333f968f3bcSZorro Liu } 334f968f3bcSZorro Liu 33593a7515aSWenping Zhang return 0; 33693a7515aSWenping Zhang } 33793a7515aSWenping Zhang 33893a7515aSWenping Zhang static int ebc_tcon_disable(struct udevice *dev) 33993a7515aSWenping Zhang { 34093a7515aSWenping Zhang return 0; 34193a7515aSWenping Zhang } 34293a7515aSWenping Zhang 34393a7515aSWenping Zhang static int ebc_tcon_dsp_mode_set(struct udevice *dev, int update_mode, 34493a7515aSWenping Zhang int display_mode, int three_win_mode, 34593a7515aSWenping Zhang int eink_mode) 34693a7515aSWenping Zhang { 34793a7515aSWenping Zhang struct ebc_tcon_priv *tcon = dev_get_priv(dev); 34893a7515aSWenping Zhang 34993a7515aSWenping Zhang tcon_update_bits(tcon, EBC_DSP_CTRL, 35093a7515aSWenping Zhang UPDATE_MODE_MASK | DISPLAY_MODE_MASK, 35193a7515aSWenping Zhang DSP_UPDATE_MODE(!!update_mode) | 35293a7515aSWenping Zhang DSP_DISPLAY_MODE(!!display_mode)); 35393a7515aSWenping Zhang 35493a7515aSWenping Zhang tcon_update_bits(tcon, EBC_EPD_CTRL, THREE_WIN_MODE_MASK, 35593a7515aSWenping Zhang DSP_THREE_WIN_MODE(!!three_win_mode)); 35693a7515aSWenping Zhang /* always set frm start bit 0 before real frame start */ 35793a7515aSWenping Zhang tcon_update_bits(tcon, EBC_DSP_START, 35893a7515aSWenping Zhang DSP_EINK_MODE_MASK | DSP_FRM_START_MASK, 35993a7515aSWenping Zhang DSP_EINK_MODE(!!eink_mode)); 36093a7515aSWenping Zhang tcon_cfg_done(tcon); 36193a7515aSWenping Zhang 36293a7515aSWenping Zhang return 0; 36393a7515aSWenping Zhang } 36493a7515aSWenping Zhang 36593a7515aSWenping Zhang static int ebc_tcon_image_addr_set(struct udevice *dev, u32 pre_image_addr, 36693a7515aSWenping Zhang u32 cur_image_addr) 36793a7515aSWenping Zhang { 36893a7515aSWenping Zhang struct ebc_tcon_priv *tcon = dev_get_priv(dev); 36993a7515aSWenping Zhang 37093a7515aSWenping Zhang tcon_write(tcon, EBC_WIN_MST0, pre_image_addr); 37193a7515aSWenping Zhang tcon_write(tcon, EBC_WIN_MST1, cur_image_addr); 37293a7515aSWenping Zhang tcon_cfg_done(tcon); 37393a7515aSWenping Zhang 37493a7515aSWenping Zhang return 0; 37593a7515aSWenping Zhang } 37693a7515aSWenping Zhang 37793a7515aSWenping Zhang static int ebc_tcon_frame_addr_set(struct udevice *dev, u32 frame_addr) 37893a7515aSWenping Zhang { 37993a7515aSWenping Zhang struct ebc_tcon_priv *tcon = dev_get_priv(dev); 38093a7515aSWenping Zhang 38193a7515aSWenping Zhang tcon_write(tcon, EBC_WIN_MST2, frame_addr); 38293a7515aSWenping Zhang tcon_cfg_done(tcon); 38393a7515aSWenping Zhang 38493a7515aSWenping Zhang return 0; 38593a7515aSWenping Zhang } 38693a7515aSWenping Zhang 38793a7515aSWenping Zhang static int ebc_tcon_lut_data_set(struct udevice *dev, unsigned int *lut_data, 38893a7515aSWenping Zhang int frame_count, int lut_32) 38993a7515aSWenping Zhang { 39093a7515aSWenping Zhang int i, lut_size; 39193a7515aSWenping Zhang struct ebc_tcon_priv *tcon = dev_get_priv(dev); 39293a7515aSWenping Zhang 39393a7515aSWenping Zhang if ((!lut_32 && frame_count > 256) || (lut_32 && frame_count > 64)) { 39493a7515aSWenping Zhang dev_err(tcon->dev, "frame count over flow\n"); 39593a7515aSWenping Zhang return -1; 39693a7515aSWenping Zhang } 39793a7515aSWenping Zhang 39893a7515aSWenping Zhang if (lut_32) 39993a7515aSWenping Zhang lut_size = frame_count * 64; 40093a7515aSWenping Zhang else 40193a7515aSWenping Zhang lut_size = frame_count * 16; 40293a7515aSWenping Zhang 40393a7515aSWenping Zhang for (i = 0; i < lut_size; i++) 40493a7515aSWenping Zhang tcon_write(tcon, EBC_LUT_DATA_ADDR + (i * 4), lut_data[i]); 40593a7515aSWenping Zhang 40693a7515aSWenping Zhang tcon_cfg_done(tcon); 40793a7515aSWenping Zhang 40893a7515aSWenping Zhang return 0; 40993a7515aSWenping Zhang } 41093a7515aSWenping Zhang 41193a7515aSWenping Zhang static int wait_for_last_frame_complete(struct udevice *dev) 41293a7515aSWenping Zhang { 41393a7515aSWenping Zhang #ifndef CONFIG_IRQ 41493a7515aSWenping Zhang u32 intr_status; 41593a7515aSWenping Zhang #endif 41693a7515aSWenping Zhang struct ebc_tcon_priv *tcon = dev_get_priv(dev); 41793a7515aSWenping Zhang 41893a7515aSWenping Zhang #ifdef CONFIG_IRQ 41939939100SWenping Zhang while (1) { 42039939100SWenping Zhang if ((last_frame_done == -1) || (last_frame_done == 1)) 42139939100SWenping Zhang break; 42293a7515aSWenping Zhang msleep(1); 42339939100SWenping Zhang } 42493a7515aSWenping Zhang #else 42593a7515aSWenping Zhang /* wait for frame display end*/ 42639939100SWenping Zhang while (1) { 42739939100SWenping Zhang /* first frame don't need to wait*/ 42839939100SWenping Zhang if (last_frame_done == -1) 42939939100SWenping Zhang break; 43093a7515aSWenping Zhang intr_status = readl(tcon->reg + EBC_INT_STATUS); 43139939100SWenping Zhang if (intr_status & DSP_END_INT) 43239939100SWenping Zhang break; 43339939100SWenping Zhang msleep(1); 43439939100SWenping Zhang } 43593a7515aSWenping Zhang #endif 43693a7515aSWenping Zhang tcon_update_bits(tcon, EBC_INT_STATUS, 43793a7515aSWenping Zhang DSP_END_INT_CLR, DSP_END_INT_CLR); 43893a7515aSWenping Zhang 43993a7515aSWenping Zhang return 0; 44093a7515aSWenping Zhang } 44193a7515aSWenping Zhang 44293a7515aSWenping Zhang static int ebc_tcon_frame_start(struct udevice *dev, int frame_total) 44393a7515aSWenping Zhang { 44493a7515aSWenping Zhang struct ebc_tcon_priv *tcon = dev_get_priv(dev); 44593a7515aSWenping Zhang 44693a7515aSWenping Zhang tcon_write(tcon, EBC_INT_STATUS, 44793a7515aSWenping Zhang LINE_FLAG_INT_MASK | DSP_FRM_INT_MASK | FRM_END_INT_MASK); 44893a7515aSWenping Zhang tcon_update_bits(tcon, EBC_DSP_START, 44993a7515aSWenping Zhang DSP_FRM_TOTAL_MASK, DSP_FRM_TOTAL(frame_total - 1)); 45093a7515aSWenping Zhang tcon_cfg_done(tcon); 45193a7515aSWenping Zhang 45293a7515aSWenping Zhang tcon_update_bits(tcon, EBC_DSP_START, 45393a7515aSWenping Zhang DSP_FRM_START_MASK, DSP_FRM_START); 45439939100SWenping Zhang last_frame_done = 0; 45593a7515aSWenping Zhang return 0; 45693a7515aSWenping Zhang } 45793a7515aSWenping Zhang 45893a7515aSWenping Zhang static int rk_ebc_tcon_probe(struct udevice *dev) 45993a7515aSWenping Zhang { 46093a7515aSWenping Zhang int ret; 46193a7515aSWenping Zhang struct ebc_tcon_priv *priv = dev_get_priv(dev); 46293a7515aSWenping Zhang 46393a7515aSWenping Zhang /*Enable PD first*/ 46493a7515aSWenping Zhang ret = ebc_power_domain(1); 46593a7515aSWenping Zhang if (ret) { 46693a7515aSWenping Zhang printf("%s, enable pd failed\n", __func__); 46793a7515aSWenping Zhang return -1; 46893a7515aSWenping Zhang } 46993a7515aSWenping Zhang 47093a7515aSWenping Zhang priv->dev = dev; 471f968f3bcSZorro Liu ret = clk_get_by_index(dev, 1, &priv->dclk); 472f968f3bcSZorro Liu if (ret < 0) { 473f968f3bcSZorro Liu printf("%s get clock fail! %d\n", __func__, ret); 474f968f3bcSZorro Liu return -EINVAL; 475f968f3bcSZorro Liu } 47693a7515aSWenping Zhang 47793a7515aSWenping Zhang #ifdef CONFIG_IRQ 47893a7515aSWenping Zhang irq_install_handler(IRQ_EBC, ebc_irq_handler, dev); 47993a7515aSWenping Zhang irq_handler_enable(IRQ_EBC); 48093a7515aSWenping Zhang #endif 48193a7515aSWenping Zhang return 0; 48293a7515aSWenping Zhang } 48393a7515aSWenping Zhang 48493a7515aSWenping Zhang const struct rk_ebc_tcon_ops ebc_tcon_funcs = { 48593a7515aSWenping Zhang .enable = ebc_tcon_enable, 48693a7515aSWenping Zhang .disable = ebc_tcon_disable, 48793a7515aSWenping Zhang .dsp_mode_set = ebc_tcon_dsp_mode_set, 48893a7515aSWenping Zhang .image_addr_set = ebc_tcon_image_addr_set, 48993a7515aSWenping Zhang .frame_addr_set = ebc_tcon_frame_addr_set, 49093a7515aSWenping Zhang .lut_data_set = ebc_tcon_lut_data_set, 49193a7515aSWenping Zhang .frame_start = ebc_tcon_frame_start, 49293a7515aSWenping Zhang .wait_for_last_frame_complete = wait_for_last_frame_complete, 49393a7515aSWenping Zhang }; 49493a7515aSWenping Zhang 49593a7515aSWenping Zhang static int rk_ebc_tcon_ofdata_to_platdata(struct udevice *dev) 49693a7515aSWenping Zhang { 49793a7515aSWenping Zhang fdt_size_t size; 49893a7515aSWenping Zhang fdt_addr_t addr; 49993a7515aSWenping Zhang struct ebc_tcon_priv *priv = dev_get_priv(dev); 50093a7515aSWenping Zhang 50193a7515aSWenping Zhang priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 50293a7515aSWenping Zhang if (priv->grf <= 0) { 50393a7515aSWenping Zhang debug("%s: Get syscon grf failed (ret=%p)\n", 50493a7515aSWenping Zhang __func__, priv->grf); 50593a7515aSWenping Zhang return -ENXIO; 50693a7515aSWenping Zhang } 50793a7515aSWenping Zhang priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF); 50893a7515aSWenping Zhang if (priv->pmugrf <= 0) { 50993a7515aSWenping Zhang debug("%s: Get syscon pmugrf failed (ret=%p)\n", 51093a7515aSWenping Zhang __func__, priv->grf); 51193a7515aSWenping Zhang return -ENXIO; 51293a7515aSWenping Zhang } 51393a7515aSWenping Zhang addr = dev_read_addr_size(dev, "reg", &size); 51493a7515aSWenping Zhang if (addr == FDT_ADDR_T_NONE) { 51593a7515aSWenping Zhang debug("%s: Get ebc_tcon address failed\n", __func__); 51693a7515aSWenping Zhang return -ENXIO; 51793a7515aSWenping Zhang } 51893a7515aSWenping Zhang 51993a7515aSWenping Zhang priv->reg = ioremap(addr, size); 52093a7515aSWenping Zhang priv->reg_len = size; 52193a7515aSWenping Zhang priv->regcache = malloc(size); 52293a7515aSWenping Zhang memset(priv->regcache, 0, size); 52393a7515aSWenping Zhang return 0; 52493a7515aSWenping Zhang } 52593a7515aSWenping Zhang 52693a7515aSWenping Zhang static const struct udevice_id ebc_tcon_ids[] = { 52793a7515aSWenping Zhang { .compatible = "rockchip,rk3568-ebc-tcon" }, 52893a7515aSWenping Zhang { } 52993a7515aSWenping Zhang }; 53093a7515aSWenping Zhang 53193a7515aSWenping Zhang U_BOOT_DRIVER(rk_ebc_tcon) = { 53293a7515aSWenping Zhang .name = "rk_ebc_tcon", 53393a7515aSWenping Zhang .id = UCLASS_EBC, 53493a7515aSWenping Zhang .of_match = ebc_tcon_ids, 53593a7515aSWenping Zhang .ofdata_to_platdata = rk_ebc_tcon_ofdata_to_platdata, 53693a7515aSWenping Zhang .probe = rk_ebc_tcon_probe, 53793a7515aSWenping Zhang .ops = &ebc_tcon_funcs, 53893a7515aSWenping Zhang .priv_auto_alloc_size = sizeof(struct ebc_tcon_priv), 53993a7515aSWenping Zhang }; 54093a7515aSWenping Zhang 54193a7515aSWenping Zhang UCLASS_DRIVER(ebc_tcon) = { 54293a7515aSWenping Zhang .id = UCLASS_EBC, 54393a7515aSWenping Zhang .name = "ebc_tcon", 54493a7515aSWenping Zhang }; 54593a7515aSWenping Zhang 546