1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2020 Rockchip Electronics Co. Ltd.
4 *
5 * Author: Zorro Liu <zorro.liu@rock-chips.com>
6 */
7
8 #include <linux/module.h>
9 #include <linux/kernel.h>
10 #include <linux/errno.h>
11 #include <linux/err.h>
12 #include <linux/io.h>
13 #include <linux/of.h>
14 #include <linux/slab.h>
15 #include <linux/device.h>
16 #include <linux/delay.h>
17 #include <linux/init.h>
18 #include <linux/interrupt.h>
19 #include <linux/platform_device.h>
20 #include <linux/clk.h>
21 #include <linux/irq.h>
22 #include <linux/pm_runtime.h>
23 #include <linux/mfd/syscon.h>
24 #include <linux/regmap.h>
25
26 #include "ebc_tcon.h"
27
28 #define HIWORD_UPDATE(x, l, h) (((x) << (l)) | (GENMASK(h, l) << 16))
29 #define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l)))
30
31 #define REG_LOAD_GLOBAL_EN 0x1
32
33 /* ebc register define */
34 #define EBC_DSP_START 0x0000 //Frame statrt register
35 #define EBC_EPD_CTRL 0x0004 //EPD control register
36 #define EBC_DSP_CTRL 0x0008 //Display control register
37 #define EBC_DSP_HTIMING0 0x000c //H-Timing setting register0
38 #define EBC_DSP_HTIMING1 0x0010 //H-Timing setting register1
39 #define EBC_DSP_VTIMING0 0x0014 //V-Timing setting register0
40 #define EBC_DSP_VTIMING1 0x0018 //V-Timing setting register1
41 #define EBC_DSP_ACT_INFO 0x001c //ACTIVE width/height
42 #define EBC_WIN_CTRL 0x0020 //Window ctrl
43 #define EBC_WIN_MST0 0x0024 //Current win memory start
44 #define EBC_WIN_MST1 0x0028 //Next win memory start
45 #define EBC_WIN_VIR 0x002c //Window vir width/height
46 #define EBC_WIN_ACT 0x0030 //Window act width/height
47 #define EBC_WIN_DSP 0x0034 //Window dsp width/height
48 #define EBC_WIN_DSP_ST 0x0038 //Window display start piont
49 #define EBC_INT_STATUS 0x003c //Interrupt register
50 #define EBC_VCOM0 0x0040 //VCOM setting register0
51 #define EBC_VCOM1 0x0044 //VCOM setting register1
52 #define EBC_VCOM2 0x0048 //VCOM setting register2
53 #define EBC_VCOM3 0x004c //VCOM setting register3
54 #define EBC_CONFIG_DONE 0x0050 //Config done register
55 #define EBC_VNUM 0x0054 //Line flag num
56 #define EBC_WIN_MST2 0x0058 //Framecount memory start
57 #define EBC_LUT_DATA_ADDR 0x1000 //lut data address
58
59 #define DSP_HTOTAL(x) UPDATE(x, 27, 16)
60 #define DSP_HS_END(x) UPDATE(x, 7, 0)
61 #define DSP_HACT_END(x) UPDATE(x, 26, 16)
62 #define DSP_HACT_ST(x) UPDATE(x, 7, 0)
63 #define DSP_VTOTAL(x) UPDATE(x, 26, 16)
64 #define DSP_VS_END(x) UPDATE(x, 7, 0)
65 #define DSP_VACT_END(x) UPDATE(x, 26, 16)
66 #define DSP_VACT_ST(x) UPDATE(x, 7, 0)
67 #define DSP_HEIGHT(x) UPDATE(x, 26, 16)
68 #define DSP_WIDTH(x) UPDATE(x, 11, 0)
69
70 #define WIN2_FIFO_ALMOST_FULL_LEVEL(x) UPDATE(x, 27, 19)
71 #define WIN_EN(x) UPDATE(x, 18, 18)
72 #define BURST_REG(x) UPDATE(x, 12, 10)
73 #define WIN_FIFO_ALMOST_FULL_LEVEL(x) UPDATE(x, 9, 2)
74 #define WIN_FMT(x) UPDATE(x, 1, 0)
75
76 #define WIN_VIR_HEIGHT(x) UPDATE(x, 31, 16)
77 #define WIN_VIR_WIDTH(x) UPDATE(x, 15, 0)
78 #define WIN_ACT_HEIGHT(x) UPDATE(x, 26, 16)
79 #define WIN_ACT_WIDTH(x) UPDATE(x, 11, 0)
80 #define WIN_DSP_HEIGHT(x) UPDATE(x, 26, 16)
81 #define WIN_DSP_WIDTH(x) UPDATE(x, 11, 0)
82 #define WIN_DSP_YST(x) UPDATE(x, 26, 16)
83 #define WIN_DSP_XST(x) UPDATE(x, 11, 0)
84
85 #define DSP_OUT_LOW BIT(31)
86 #define DSP_EINK_MODE(x) UPDATE(x, 13, 13)
87 #define DSP_EINK_MODE_MASK BIT(13)
88 #define DSP_SDCE_WIDTH(x) UPDATE(x, 25, 16)
89 #define DSP_FRM_TOTAL(x) UPDATE(x, 9, 2)
90 #define DSP_FRM_TOTAL_MASK GENMASK(9, 2)
91 #define DSP_FRM_START BIT(0)
92 #define DSP_FRM_START_MASK BIT(0)
93 #define SW_BURST_CTRL BIT(12)
94
95 #define EINK_MODE_SWAP(x) UPDATE(x, 31, 31)
96 #define EINK_MODE_FRM_SEL(x) UPDATE(x, 30, 30)
97 #define DSP_GD_END(x) UPDATE(x, 26, 16)
98 #define DSP_GD_ST(x) UPDATE(x, 15, 8)
99 #define DSP_THREE_WIN_MODE(x) UPDATE(x, 7, 7)
100 #define THREE_WIN_MODE_MASK BIT(7)
101 #define DSP_SDDW_MODE(x) UPDATE(x, 6, 6)
102 #define EPD_AUO(x) UPDATE(x, 5, 5)
103 #define EPD_PWR(x) UPDATE(x, 4, 2)
104 #define EPD_GDRL(x) UPDATE(x, 1, 1)
105 #define EPD_SDSHR(x) UPDATE(x, 0, 0)
106
107 #define DSP_SWAP_MODE(x) UPDATE(x, 31, 30)
108 #define DSP_SDCLK_DIV(x) UPDATE(x, 19, 16)
109 #define DSP_SDCLK_DIV_MASK GENMASK(19, 16)
110 #define DSP_VCOM_MODE(x) UPDATE(x, 27, 27)
111
112 #define DSP_UPDATE_MODE(x) UPDATE(x, 29, 29)
113 #define DSP_DISPLAY_MODE(x) UPDATE(x, 28, 28)
114 #define UPDATE_MODE_MASK BIT(29)
115 #define DISPLAY_MODE_MASK BIT(28)
116
117 #define DSP_FRM_INT_NUM(x) UPDATE(x, 19, 12)
118 #define FRM_END_INT BIT(0)
119 #define DSP_END_INT BIT(1)
120 #define DSP_FRM_INT BIT(2)
121 #define LINE_FLAG_INT BIT(3)
122 #define FRM_END_INT_MASK BIT(4)
123 #define DSP_END_INT_MASK BIT(5)
124 #define DSP_FRM_INT_MASK BIT(6)
125 #define LINE_FLAG_INT_MASK BIT(7)
126 #define FRM_END_INT_CLR BIT(8)
127 #define DSP_END_INT_CLR BIT(9)
128 #define DSP_FRM_INT_CLR BIT(10)
129 #define LINE_FLAG_INT_CLR BIT(11)
130
131 enum ebc_win_data_fmt {
132 Y_DATA_4BPP = 0,
133 Y_DATA_8BPP = 1,
134 RGB888 = 2,
135 RGB565 = 3,
136 };
137
tcon_write(struct ebc_tcon * tcon,unsigned int reg,unsigned int value)138 static inline void tcon_write(struct ebc_tcon *tcon, unsigned int reg,
139 unsigned int value)
140 {
141 regmap_write(tcon->regmap_base, reg, value);
142 }
143
tcon_read(struct ebc_tcon * tcon,unsigned int reg)144 static inline unsigned int tcon_read(struct ebc_tcon *tcon, unsigned int reg)
145 {
146 unsigned int value;
147
148 regmap_read(tcon->regmap_base, reg, &value);
149
150 return value;
151 }
152
tcon_update_bits(struct ebc_tcon * tcon,unsigned int reg,unsigned int mask,unsigned int val)153 static inline void tcon_update_bits(struct ebc_tcon *tcon, unsigned int reg,
154 unsigned int mask, unsigned int val)
155 {
156 regmap_update_bits(tcon->regmap_base, reg, mask, val);
157 }
158
tcon_cfg_done(struct ebc_tcon * tcon)159 static inline void tcon_cfg_done(struct ebc_tcon *tcon)
160 {
161 regmap_write(tcon->regmap_base, EBC_CONFIG_DONE, REG_LOAD_GLOBAL_EN);
162 }
163
tcon_enable(struct ebc_tcon * tcon,struct ebc_panel * panel)164 static int tcon_enable(struct ebc_tcon *tcon, struct ebc_panel *panel)
165 {
166 clk_prepare_enable(tcon->hclk);
167 clk_prepare_enable(tcon->dclk);
168 pm_runtime_get_sync(tcon->dev);
169
170 /* panel timing and win info config */
171 tcon_write(tcon, EBC_DSP_HTIMING0,
172 DSP_HTOTAL(panel->lsl + panel->lbl + panel->ldl + panel->lel) | DSP_HS_END(panel->lsl + 2));
173 tcon_write(tcon, EBC_DSP_HTIMING1,
174 DSP_HACT_END(panel->lsl + panel->lbl + panel->ldl) | DSP_HACT_ST(panel->lsl + panel->lbl - 1));
175 tcon_write(tcon, EBC_DSP_VTIMING0,
176 DSP_VTOTAL(panel->fsl + panel->fbl + panel->fdl + panel->fel) | DSP_VS_END(panel->fsl));
177 tcon_write(tcon, EBC_DSP_VTIMING1,
178 DSP_VACT_END(panel->fsl + panel->fbl + panel->fdl) | DSP_VACT_ST(panel->fsl + panel->fbl));
179 tcon_write(tcon, EBC_DSP_ACT_INFO, DSP_HEIGHT(panel->height) | DSP_WIDTH(panel->width));
180 tcon_write(tcon, EBC_WIN_VIR, WIN_VIR_HEIGHT(panel->vir_height) | WIN_VIR_WIDTH(panel->vir_width));
181 tcon_write(tcon, EBC_WIN_ACT, WIN_ACT_HEIGHT(panel->height) | WIN_ACT_WIDTH(panel->width));
182 tcon_write(tcon, EBC_WIN_DSP, WIN_DSP_HEIGHT(panel->height) | WIN_DSP_WIDTH(panel->width));
183 tcon_write(tcon, EBC_WIN_DSP_ST, WIN_DSP_YST(panel->fsl + panel->fbl) | WIN_DSP_XST(panel->lsl + panel->lbl));
184
185 /* win2 fifo is 512x128, win fifo is 256x128, we set fifo almost value (fifo_size - 16)
186 * burst_reg = 7 mean ahb burst is incr16
187 */
188 tcon_write(tcon, EBC_WIN_CTRL, WIN2_FIFO_ALMOST_FULL_LEVEL(496) | WIN_EN(1)
189 | BURST_REG(7) | WIN_FIFO_ALMOST_FULL_LEVEL(240) | WIN_FMT(Y_DATA_4BPP));
190
191 /*
192 * EBC_EPD_CTRL info:
193 * DSP_GD_ST: GCLK rising edge point(SCLK), which count from the rasing edge of hsync(spec is wrong, count
194 * from rasing edge of hsync, not falling edge of hsync)
195 * DSP_GD_END : GCLK falling edge point(SCLK), which count from the rasing edge of hsync
196 * DSP_THREE_WIN_MODE: 0: lut mode or direct mode; 1: three win mode
197 * DSP_SDDW_MODE: 0: 8 bit data output; 1: 16 bit data output
198 * EPD_AUO: 0: EINK; 1:AUO
199 * EPD_GDRL: gate scanning direction: 1: button to top 0: top to button
200 * EPD_SDSHR: source scanning direction 1: right to left 0: left to right
201 */
202 tcon_write(tcon, EBC_EPD_CTRL, EINK_MODE_SWAP(1)
203 | DSP_GD_ST(panel->lsl + panel->gdck_sta)
204 | DSP_GD_END(panel->lsl + panel->gdck_sta + panel->lgonl)
205 | DSP_THREE_WIN_MODE(0)
206 | DSP_SDDW_MODE(!!panel->panel_16bit)
207 | EPD_AUO(0)
208 | EPD_GDRL(1)
209 | EPD_SDSHR(1));
210 tcon_write(tcon, EBC_DSP_START, DSP_SDCE_WIDTH(panel->ldl) | SW_BURST_CTRL);
211 tcon_write(tcon, EBC_DSP_CTRL,
212 DSP_SWAP_MODE(panel->panel_16bit ? 2 : 3) | DSP_VCOM_MODE(1) | DSP_SDCLK_DIV(panel->panel_16bit ? 7 : 3));
213 tcon_cfg_done(tcon);
214
215 enable_irq(tcon->irq);
216
217 return 0;
218 }
219
tcon_disable(struct ebc_tcon * tcon)220 static void tcon_disable(struct ebc_tcon *tcon)
221 {
222 disable_irq(tcon->irq);
223 /* output low */
224 tcon_update_bits(tcon, EBC_DSP_START, DSP_OUT_LOW | DSP_FRM_START_MASK, DSP_OUT_LOW);
225
226 pm_runtime_put_sync(tcon->dev);
227 clk_disable_unprepare(tcon->dclk);
228 clk_disable_unprepare(tcon->hclk);
229 }
230
tcon_dsp_mode_set(struct ebc_tcon * tcon,int update_mode,int display_mode,int three_win_mode,int eink_mode)231 static void tcon_dsp_mode_set(struct ebc_tcon *tcon, int update_mode, int display_mode, int three_win_mode, int eink_mode)
232 {
233 tcon_update_bits(tcon, EBC_DSP_CTRL, UPDATE_MODE_MASK | DISPLAY_MODE_MASK,
234 DSP_UPDATE_MODE(!!update_mode) | DSP_DISPLAY_MODE(!!display_mode));
235 tcon_update_bits(tcon, EBC_EPD_CTRL, THREE_WIN_MODE_MASK,
236 DSP_THREE_WIN_MODE(!!three_win_mode));
237 /* always set frm start bit 0 before real frame start */
238 tcon_update_bits(tcon, EBC_DSP_START, DSP_EINK_MODE_MASK | DSP_FRM_START_MASK, DSP_EINK_MODE(!!eink_mode));
239 tcon_cfg_done(tcon);
240 }
241
tcon_image_addr_set(struct ebc_tcon * tcon,u32 pre_image_addr,u32 cur_image_addr)242 static void tcon_image_addr_set(struct ebc_tcon *tcon, u32 pre_image_addr, u32 cur_image_addr)
243 {
244 tcon_write(tcon, EBC_WIN_MST0, pre_image_addr);
245 tcon_write(tcon, EBC_WIN_MST1, cur_image_addr);
246 tcon_cfg_done(tcon);
247 }
248
tcon_frame_addr_set(struct ebc_tcon * tcon,u32 frame_addr)249 static void tcon_frame_addr_set(struct ebc_tcon *tcon, u32 frame_addr)
250 {
251 tcon_write(tcon, EBC_WIN_MST2, frame_addr);
252 tcon_cfg_done(tcon);
253 }
254
tcon_lut_data_set(struct ebc_tcon * tcon,unsigned int * lut_data,int frame_count,int lut_32)255 static int tcon_lut_data_set(struct ebc_tcon *tcon, unsigned int *lut_data, int frame_count, int lut_32)
256 {
257 int i;
258 int lut_size;
259
260 if ((!lut_32 && frame_count > 256) || (lut_32 && frame_count > 64)) {
261 dev_err(tcon->dev, "frame count over flow\n");
262 return -1;
263 }
264
265 if (lut_32)
266 lut_size = frame_count * 64;
267 else
268 lut_size = frame_count * 16;
269
270 for (i = 0; i < lut_size; i++) {
271 tcon_write(tcon, EBC_LUT_DATA_ADDR + (i * 4), lut_data[i]);
272 }
273 tcon_cfg_done(tcon);
274
275 return 0;
276 }
277
tcon_frame_start(struct ebc_tcon * tcon,int frame_total)278 static void tcon_frame_start(struct ebc_tcon *tcon, int frame_total)
279 {
280 tcon_write(tcon, EBC_INT_STATUS, LINE_FLAG_INT_MASK | DSP_FRM_INT_MASK | FRM_END_INT_MASK);
281 /* always set frm start bit 0 before real frame start */
282 tcon_update_bits(tcon, EBC_DSP_START, DSP_FRM_TOTAL_MASK | DSP_FRM_START_MASK, DSP_FRM_TOTAL(frame_total - 1));
283 tcon_cfg_done(tcon);
284
285 tcon_update_bits(tcon, EBC_DSP_START, DSP_FRM_START_MASK, DSP_FRM_START);
286 }
287
tcon_irq_hanlder(int irq,void * dev_id)288 static irqreturn_t tcon_irq_hanlder(int irq, void *dev_id)
289 {
290 struct ebc_tcon *tcon = (struct ebc_tcon *)dev_id;
291 u32 intr_status;
292
293 intr_status = tcon_read(tcon, EBC_INT_STATUS);
294
295 if (intr_status & DSP_END_INT) {
296 tcon_update_bits(tcon, EBC_INT_STATUS, DSP_END_INT_CLR, DSP_END_INT_CLR);
297
298 if (tcon->dsp_end_callback)
299 tcon->dsp_end_callback();
300 }
301
302 return IRQ_HANDLED;
303 }
304
tcon_is_volatile_reg(struct device * dev,unsigned int reg)305 static bool tcon_is_volatile_reg(struct device *dev, unsigned int reg)
306 {
307 switch (reg) {
308 case EBC_DSP_START:
309 case EBC_EPD_CTRL:
310 case EBC_DSP_CTRL:
311 return false;
312 }
313
314 return true;
315 }
316
317 static struct regmap_config ebc_regmap_config = {
318 .reg_bits = 32,
319 .val_bits = 32,
320 .reg_stride = 4,
321 .cache_type = REGCACHE_RBTREE,
322 .volatile_reg = tcon_is_volatile_reg,
323 };
324
ebc_tcon_probe(struct platform_device * pdev)325 static int ebc_tcon_probe(struct platform_device *pdev)
326 {
327 struct device *dev = &pdev->dev;
328 struct ebc_tcon *tcon;
329 struct resource *res;
330 int ret;
331
332 tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL);
333 if (!tcon)
334 return -ENOMEM;
335
336 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
337 tcon->regs = devm_ioremap_resource(dev, res);
338 if (IS_ERR(tcon->regs))
339 return PTR_ERR(tcon->regs);
340
341 tcon->len = resource_size(res);
342 ebc_regmap_config.max_register = resource_size(res) - 4;
343 ebc_regmap_config.name = "rockchip,ebc_tcon";
344 tcon->regmap_base = devm_regmap_init_mmio(dev, tcon->regs, &ebc_regmap_config);
345 if (IS_ERR(tcon->regmap_base))
346 return PTR_ERR(tcon->regmap_base);
347
348 tcon->hclk = devm_clk_get(dev, "hclk");
349 if (IS_ERR(tcon->hclk)) {
350 ret = PTR_ERR(tcon->hclk);
351 dev_err(dev, "failed to get hclk clock: %d\n", ret);
352 return ret;
353 }
354
355 tcon->dclk = devm_clk_get(dev, "dclk");
356 if (IS_ERR(tcon->dclk)) {
357 ret = PTR_ERR(tcon->dclk);
358 dev_err(dev, "failed to get dclk clock: %d\n", ret);
359 return ret;
360 }
361
362 tcon->irq = platform_get_irq(pdev, 0);
363 if (tcon->irq < 0) {
364 dev_err(dev, "No IRQ resource!\n");
365 return tcon->irq;
366 }
367
368 irq_set_status_flags(tcon->irq, IRQ_NOAUTOEN);
369 ret = devm_request_irq(dev, tcon->irq, tcon_irq_hanlder,
370 0, dev_name(dev), tcon);
371 if (ret < 0) {
372 dev_err(dev, "failed to requeset irq: %d\n", ret);
373 return ret;
374 }
375
376 tcon->dev = dev;
377 tcon->enable = tcon_enable;
378 tcon->disable = tcon_disable;
379 tcon->dsp_mode_set = tcon_dsp_mode_set;
380 tcon->image_addr_set = tcon_image_addr_set;
381 tcon->frame_addr_set = tcon_frame_addr_set;
382 tcon->lut_data_set = tcon_lut_data_set;
383 tcon->frame_start = tcon_frame_start;
384 platform_set_drvdata(pdev, tcon);
385
386 pm_runtime_enable(dev);
387
388 return 0;
389 }
390
ebc_tcon_remove(struct platform_device * pdev)391 static int ebc_tcon_remove(struct platform_device *pdev)
392 {
393 pm_runtime_disable(&pdev->dev);
394
395 return 0;
396 }
397
398 static const struct of_device_id ebc_tcon_of_match[] = {
399 { .compatible = "rockchip,rk3568-ebc-tcon" },
400 {}
401 };
402 MODULE_DEVICE_TABLE(of, ebc_tcon_of_match);
403
404 static struct platform_driver ebc_tcon_driver = {
405 .driver = {
406 .name = "rk-ebc-tcon",
407 .of_match_table = ebc_tcon_of_match,
408 },
409 .probe = ebc_tcon_probe,
410 .remove = ebc_tcon_remove,
411 };
412 module_platform_driver(ebc_tcon_driver);
413
414 MODULE_AUTHOR("Zorro Liu <zorro.liu@rock-chips.com>");
415 MODULE_DESCRIPTION("ROCKCHIP EBC tcon driver");
416 MODULE_LICENSE("GPL v2");
417