blob: 814126af666445501085ed1cfb333a646d0eacbb [file] [log] [blame]
Dario Binacchi35ab1b62020-12-30 00:16:30 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2020 Dario Binacchi <dariobin@libero.it>
4 */
5
6#include <common.h>
7#include <clk.h>
8#include <dm.h>
9#include <dm/device_compat.h>
10#include <lcd.h>
11#include <log.h>
12#include <panel.h>
13#include <video.h>
14#include <asm/io.h>
15#include <asm/utils.h>
16#include "tilcdc.h"
17#include "tilcdc-panel.h"
18
19#define LCDC_FMAX 200000000
20
21/* LCD Control Register */
22#define LCDC_CTRL_CLK_DIVISOR_MASK GENMASK(15, 8)
23#define LCDC_CTRL_RASTER_MODE BIT(0)
24#define LCDC_CTRL_CLK_DIVISOR(x) (((x) & GENMASK(7, 0)) << 8)
25/* LCD Clock Enable Register */
26#define LCDC_CLKC_ENABLE_CORECLKEN BIT(0)
27#define LCDC_CLKC_ENABLE_LIDDCLKEN BIT(1)
28#define LCDC_CLKC_ENABLE_DMACLKEN BIT(2)
29/* LCD DMA Control Register */
30#define LCDC_DMA_CTRL_BURST_SIZE(x) (((x) & GENMASK(2, 0)) << 4)
31#define LCDC_DMA_CTRL_BURST_1 0x0
32#define LCDC_DMA_CTRL_BURST_2 0x1
33#define LCDC_DMA_CTRL_BURST_4 0x2
34#define LCDC_DMA_CTRL_BURST_8 0x3
35#define LCDC_DMA_CTRL_BURST_16 0x4
36#define LCDC_DMA_CTRL_FIFO_TH(x) (((x) & GENMASK(2, 0)) << 8)
37/* LCD Timing_0 Register */
38#define LCDC_RASTER_TIMING_0_HORMSB(x) ((((x) - 1) & BIT(10)) >> 7)
39#define LCDC_RASTER_TIMING_0_HORLSB(x) (((((x) >> 4) - 1) & GENMASK(5, 0)) << 4)
40#define LCDC_RASTER_TIMING_0_HSWLSB(x) ((((x) - 1) & GENMASK(5, 0)) << 10)
41#define LCDC_RASTER_TIMING_0_HFPLSB(x) ((((x) - 1) & GENMASK(7, 0)) << 16)
42#define LCDC_RASTER_TIMING_0_HBPLSB(x) ((((x) - 1) & GENMASK(7, 0)) << 24)
43/* LCD Timing_1 Register */
44#define LCDC_RASTER_TIMING_1_VERLSB(x) (((x) - 1) & GENMASK(9, 0))
45#define LCDC_RASTER_TIMING_1_VSW(x) ((((x) - 1) & GENMASK(5, 0)) << 10)
46#define LCDC_RASTER_TIMING_1_VFP(x) (((x) & GENMASK(7, 0)) << 16)
47#define LCDC_RASTER_TIMING_1_VBP(x) (((x) & GENMASK(7, 0)) << 24)
48/* LCD Timing_2 Register */
49#define LCDC_RASTER_TIMING_2_HFPMSB(x) ((((x) - 1) & GENMASK(9, 8)) >> 8)
50#define LCDC_RASTER_TIMING_2_HBPMSB(x) ((((x) - 1) & GENMASK(9, 8)) >> 4)
51#define LCDC_RASTER_TIMING_2_ACB(x) (((x) & GENMASK(7, 0)) << 8)
52#define LCDC_RASTER_TIMING_2_ACBI(x) (((x) & GENMASK(3, 0)) << 16)
53#define LCDC_RASTER_TIMING_2_VSYNC_INVERT BIT(20)
54#define LCDC_RASTER_TIMING_2_HSYNC_INVERT BIT(21)
55#define LCDC_RASTER_TIMING_2_PXCLK_INVERT BIT(22)
56#define LCDC_RASTER_TIMING_2_DE_INVERT BIT(23)
57#define LCDC_RASTER_TIMING_2_HSVS_RISEFALL BIT(24)
58#define LCDC_RASTER_TIMING_2_HSVS_CONTROL BIT(25)
59#define LCDC_RASTER_TIMING_2_VERMSB(x) ((((x) - 1) & BIT(10)) << 16)
60#define LCDC_RASTER_TIMING_2_HSWMSB(x) ((((x) - 1) & GENMASK(9, 6)) << 21)
61/* LCD Raster Ctrl Register */
62#define LCDC_RASTER_CTRL_ENABLE BIT(0)
63#define LCDC_RASTER_CTRL_TFT_MODE BIT(7)
64#define LCDC_RASTER_CTRL_DATA_ORDER BIT(8)
65#define LCDC_RASTER_CTRL_REQDLY(x) (((x) & GENMASK(7, 0)) << 12)
66#define LCDC_RASTER_CTRL_PALMODE_RAWDATA (0x02 << 20)
67#define LCDC_RASTER_CTRL_TFT_ALT_ENABLE BIT(23)
68#define LCDC_RASTER_CTRL_TFT_24BPP_MODE BIT(25)
69#define LCDC_RASTER_CTRL_TFT_24BPP_UNPACK BIT(26)
70
71enum {
72 LCDC_MAX_WIDTH = 2048,
73 LCDC_MAX_HEIGHT = 2048,
74 LCDC_MAX_LOG2_BPP = VIDEO_BPP32,
75};
76
77struct tilcdc_regs {
78 u32 pid;
79 u32 ctrl;
80 u32 gap0;
81 u32 lidd_ctrl;
82 u32 lidd_cs0_conf;
83 u32 lidd_cs0_addr;
84 u32 lidd_cs0_data;
85 u32 lidd_cs1_conf;
86 u32 lidd_cs1_addr;
87 u32 lidd_cs1_data;
88 u32 raster_ctrl;
89 u32 raster_timing0;
90 u32 raster_timing1;
91 u32 raster_timing2;
92 u32 raster_subpanel;
93 u32 raster_subpanel2;
94 u32 lcddma_ctrl;
95 u32 lcddma_fb0_base;
96 u32 lcddma_fb0_ceiling;
97 u32 lcddma_fb1_base;
98 u32 lcddma_fb1_ceiling;
99 u32 sysconfig;
100 u32 irqstatus_raw;
101 u32 irqstatus;
102 u32 irqenable_set;
103 u32 irqenable_clear;
104 u32 gap1;
105 u32 clkc_enable;
106 u32 clkc_reset;
107};
108
109struct tilcdc_priv {
110 struct tilcdc_regs *regs;
111 struct clk gclk;
112 struct clk dpll_m2_clk;
113};
114
115DECLARE_GLOBAL_DATA_PTR;
116
117static ulong tilcdc_set_pixel_clk_rate(struct udevice *dev, ulong rate)
118{
119 struct tilcdc_priv *priv = dev_get_priv(dev);
120 struct tilcdc_regs *regs = priv->regs;
121 ulong mult_rate, mult_round_rate, best_err, err;
122 u32 v;
123 int div, i;
124
125 best_err = rate;
126 div = 0;
127 for (i = 2; i <= 255; i++) {
128 mult_rate = rate * i;
129 mult_round_rate = clk_round_rate(&priv->gclk, mult_rate);
130 if (IS_ERR_VALUE(mult_round_rate))
131 return mult_round_rate;
132
133 err = mult_rate - mult_round_rate;
134 if (err < best_err) {
135 best_err = err;
136 div = i;
137 if (err == 0)
138 break;
139 }
140 }
141
142 if (div == 0) {
143 dev_err(dev, "failed to find a divisor\n");
144 return -EFAULT;
145 }
146
147 mult_rate = clk_set_rate(&priv->gclk, rate * div);
148 v = readl(&regs->ctrl) & ~LCDC_CTRL_CLK_DIVISOR_MASK;
149 v |= LCDC_CTRL_CLK_DIVISOR(div);
150 writel(v, &regs->ctrl);
151 rate = mult_rate / div;
152 dev_dbg(dev, "rate=%ld, div=%d, err=%ld\n", rate, div, err);
153 return rate;
154}
155
156static int tilcdc_remove(struct udevice *dev)
157{
Dario Binacchib0db69b2021-01-15 09:10:26 +0100158 struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev);
Dario Binacchi35ab1b62020-12-30 00:16:30 +0100159 struct tilcdc_priv *priv = dev_get_priv(dev);
160
161 uc_plat->base -= 0x20;
162 uc_plat->size += 0x20;
163 clk_release_all(&priv->gclk, 1);
164 clk_release_all(&priv->dpll_m2_clk, 1);
165 return 0;
166}
167
168static int tilcdc_probe(struct udevice *dev)
169{
Dario Binacchib0db69b2021-01-15 09:10:26 +0100170 struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev);
Dario Binacchi35ab1b62020-12-30 00:16:30 +0100171 struct video_priv *uc_priv = dev_get_uclass_priv(dev);
172 struct tilcdc_priv *priv = dev_get_priv(dev);
173 struct tilcdc_regs *regs = priv->regs;
174 struct udevice *panel, *clk_dev;
175 struct tilcdc_panel_info info;
176 struct display_timing timing;
177 ulong rate;
178 u32 reg;
179 int err;
180
181 /* Before relocation we don't need to do anything */
182 if (!(gd->flags & GD_FLG_RELOC))
183 return 0;
184
185 err = uclass_get_device(UCLASS_PANEL, 0, &panel);
186 if (err) {
187 dev_err(dev, "failed to get panel\n");
188 return err;
189 }
190
191 err = panel_get_display_timing(panel, &timing);
192 if (err) {
193 dev_err(dev, "failed to get display timing\n");
194 return err;
195 }
196
197 if (timing.pixelclock.typ > (LCDC_FMAX / 2)) {
198 dev_err(dev, "invalid display clock-frequency: %d Hz\n",
199 timing.pixelclock.typ);
200 return -EINVAL;
201 }
202
203 if (timing.hactive.typ > LCDC_MAX_WIDTH)
204 timing.hactive.typ = LCDC_MAX_WIDTH;
205
206 if (timing.vactive.typ > LCDC_MAX_HEIGHT)
207 timing.vactive.typ = LCDC_MAX_HEIGHT;
208
209 err = tilcdc_panel_get_display_info(panel, &info);
210 if (err) {
211 dev_err(dev, "failed to get panel info\n");
212 return err;
213 }
214
215 switch (info.bpp) {
216 case 16:
217 case 24:
218 case 32:
219 break;
220 default:
221 dev_err(dev, "invalid seting, bpp: %d\n", info.bpp);
222 return -EINVAL;
223 }
224
225 switch (info.dma_burst_sz) {
226 case 1:
227 case 2:
228 case 4:
229 case 8:
230 case 16:
231 break;
232 default:
233 dev_err(dev, "invalid setting, dma-burst-sz: %d\n",
234 info.dma_burst_sz);
235 return -EINVAL;
236 }
237
238 err = uclass_get_device_by_name(UCLASS_CLK, "lcd_gclk@534", &clk_dev);
239 if (err) {
240 dev_err(dev, "failed to get lcd_gclk device\n");
241 return err;
242 }
243
244 err = clk_request(clk_dev, &priv->gclk);
245 if (err) {
246 dev_err(dev, "failed to get %s clock\n", clk_dev->name);
247 return err;
248 }
249
250 rate = tilcdc_set_pixel_clk_rate(dev, timing.pixelclock.typ);
251 if (IS_ERR_VALUE(rate)) {
252 dev_err(dev, "failed to set pixel clock rate\n");
253 return rate;
254 }
255
256 err = uclass_get_device_by_name(UCLASS_CLK, "dpll_disp_m2_ck@4a4",
257 &clk_dev);
258 if (err) {
259 dev_err(dev, "failed to get dpll_disp_m2 clock device\n");
260 return err;
261 }
262
263 err = clk_request(clk_dev, &priv->dpll_m2_clk);
264 if (err) {
265 dev_err(dev, "failed to get %s clock\n", clk_dev->name);
266 return err;
267 }
268
269 err = clk_set_parent(&priv->gclk, &priv->dpll_m2_clk);
270 if (err) {
271 dev_err(dev, "failed to set %s clock as %s's parent\n",
272 priv->dpll_m2_clk.dev->name, priv->gclk.dev->name);
273 return err;
274 }
275
276 /* palette default entry */
277 memset((void *)uc_plat->base, 0, 0x20);
278 *(unsigned int *)uc_plat->base = 0x4000;
279 /* point fb behind palette */
280 uc_plat->base += 0x20;
281 uc_plat->size -= 0x20;
282
283 writel(LCDC_CLKC_ENABLE_CORECLKEN | LCDC_CLKC_ENABLE_LIDDCLKEN |
284 LCDC_CLKC_ENABLE_DMACLKEN, &regs->clkc_enable);
285 writel(0, &regs->raster_ctrl);
286
287 reg = readl(&regs->ctrl) & LCDC_CTRL_CLK_DIVISOR_MASK;
288 reg |= LCDC_CTRL_RASTER_MODE;
289 writel(reg, &regs->ctrl);
290
291 reg = (timing.hactive.typ * timing.vactive.typ * info.bpp) >> 3;
292 reg += uc_plat->base;
293 writel(uc_plat->base, &regs->lcddma_fb0_base);
294 writel(reg, &regs->lcddma_fb0_ceiling);
295 writel(uc_plat->base, &regs->lcddma_fb1_base);
296 writel(reg, &regs->lcddma_fb1_ceiling);
297
298 reg = LCDC_DMA_CTRL_FIFO_TH(info.fifo_th);
299 switch (info.dma_burst_sz) {
300 case 1:
301 reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_1);
302 break;
303 case 2:
304 reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_2);
305 break;
306 case 4:
307 reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_4);
308 break;
309 case 8:
310 reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_8);
311 break;
312 case 16:
313 reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_16);
314 break;
315 }
316
317 writel(reg, &regs->lcddma_ctrl);
318
319 writel(LCDC_RASTER_TIMING_0_HORLSB(timing.hactive.typ) |
320 LCDC_RASTER_TIMING_0_HORMSB(timing.hactive.typ) |
321 LCDC_RASTER_TIMING_0_HFPLSB(timing.hfront_porch.typ) |
322 LCDC_RASTER_TIMING_0_HBPLSB(timing.hback_porch.typ) |
323 LCDC_RASTER_TIMING_0_HSWLSB(timing.hsync_len.typ),
324 &regs->raster_timing0);
325
326 writel(LCDC_RASTER_TIMING_1_VBP(timing.vback_porch.typ) |
327 LCDC_RASTER_TIMING_1_VFP(timing.vfront_porch.typ) |
328 LCDC_RASTER_TIMING_1_VSW(timing.vsync_len.typ) |
329 LCDC_RASTER_TIMING_1_VERLSB(timing.vactive.typ),
330 &regs->raster_timing1);
331
332 reg = LCDC_RASTER_TIMING_2_ACB(info.ac_bias) |
333 LCDC_RASTER_TIMING_2_ACBI(info.ac_bias_intrpt) |
334 LCDC_RASTER_TIMING_2_HSWMSB(timing.hsync_len.typ) |
335 LCDC_RASTER_TIMING_2_VERMSB(timing.vactive.typ) |
336 LCDC_RASTER_TIMING_2_HBPMSB(timing.hback_porch.typ) |
337 LCDC_RASTER_TIMING_2_HFPMSB(timing.hfront_porch.typ);
338
339 if (timing.flags & DISPLAY_FLAGS_VSYNC_LOW)
340 reg |= LCDC_RASTER_TIMING_2_VSYNC_INVERT;
341
342 if (timing.flags & DISPLAY_FLAGS_HSYNC_LOW)
343 reg |= LCDC_RASTER_TIMING_2_HSYNC_INVERT;
344
345 if (info.invert_pxl_clk)
346 reg |= LCDC_RASTER_TIMING_2_PXCLK_INVERT;
347
348 if (info.sync_edge)
349 reg |= LCDC_RASTER_TIMING_2_HSVS_RISEFALL;
350
351 if (info.sync_ctrl)
352 reg |= LCDC_RASTER_TIMING_2_HSVS_CONTROL;
353
354 writel(reg, &regs->raster_timing2);
355
356 reg = LCDC_RASTER_CTRL_PALMODE_RAWDATA | LCDC_RASTER_CTRL_TFT_MODE |
357 LCDC_RASTER_CTRL_ENABLE | LCDC_RASTER_CTRL_REQDLY(info.fdd);
358
359 if (info.tft_alt_mode)
360 reg |= LCDC_RASTER_CTRL_TFT_ALT_ENABLE;
361
362 if (info.bpp == 24)
363 reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE;
364 else if (info.bpp == 32)
365 reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE |
366 LCDC_RASTER_CTRL_TFT_24BPP_UNPACK;
367
368 if (info.raster_order)
369 reg |= LCDC_RASTER_CTRL_DATA_ORDER;
370
371 writel(reg, &regs->raster_ctrl);
372
373 uc_priv->xsize = timing.hactive.typ;
374 uc_priv->ysize = timing.vactive.typ;
375 uc_priv->bpix = log_2_n_round_up(info.bpp);
376
377 err = panel_enable_backlight(panel);
378 if (err) {
379 dev_err(dev, "failed to enable panel backlight\n");
380 return err;
381 }
382
383 return 0;
384}
385
386static int tilcdc_of_to_plat(struct udevice *dev)
387{
388 struct tilcdc_priv *priv = dev_get_priv(dev);
389
390 priv->regs = (struct tilcdc_regs *)dev_read_addr(dev);
391 if ((fdt_addr_t)priv->regs == FDT_ADDR_T_NONE) {
392 dev_err(dev, "failed to get base address\n");
393 return -EINVAL;
394 }
395
396 dev_dbg(dev, "LCD: base address=0x%x\n", (unsigned int)priv->regs);
397 return 0;
398}
399
400static int tilcdc_bind(struct udevice *dev)
401{
Dario Binacchib0db69b2021-01-15 09:10:26 +0100402 struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev);
Dario Binacchi35ab1b62020-12-30 00:16:30 +0100403
404 uc_plat->size = ((LCDC_MAX_WIDTH * LCDC_MAX_HEIGHT *
405 (1 << LCDC_MAX_LOG2_BPP)) >> 3) + 0x20;
406
407 dev_dbg(dev, "frame buffer size 0x%x\n", uc_plat->size);
408 return 0;
409}
410
411static const struct udevice_id tilcdc_ids[] = {
412 {.compatible = "ti,am33xx-tilcdc"},
413 {}
414};
415
416U_BOOT_DRIVER(tilcdc) = {
417 .name = "tilcdc",
418 .id = UCLASS_VIDEO,
419 .of_match = tilcdc_ids,
420 .bind = tilcdc_bind,
Dario Binacchib0db69b2021-01-15 09:10:26 +0100421 .of_to_plat = tilcdc_of_to_plat,
Dario Binacchi35ab1b62020-12-30 00:16:30 +0100422 .probe = tilcdc_probe,
423 .remove = tilcdc_remove,
424 .priv_auto = sizeof(struct tilcdc_priv)
425};