1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2013-2018 Hannes Schmelzer <oe5hpm@oevsv.at>
4 * B&R Industrial Automation GmbH - http://www.br-automation.com
5 * Copyright (C) 2020 Dario Binacchi <dariobin@libero.it>
6 *
7 * minimal framebuffer driver for TI's AM335x SoC to be compatible with
8 * Wolfgang Denk's LCD-Framework (CONFIG_LCD, common/lcd.c)
9 *
10 * - supporting 16/24/32bit RGB/TFT raster Mode (not using palette)
11 * - sets up LCD controller as in 'am335x_lcdpanel' struct given
12 * - starts output DMA from gd->fb_base buffer
13 */
14 #include <common.h>
15 #include <lcd.h>
16 #include <log.h>
17 #include <asm/arch/clock.h>
18 #include <asm/arch/hardware.h>
19 #include <asm/arch/omap.h>
20 #include <asm/arch/sys_proto.h>
21 #include <asm/global_data.h>
22 #include <asm/io.h>
23 #include <linux/delay.h>
24 #include <linux/err.h>
25 #include "am335x-fb.h"
26
27 #define LCDC_FMAX 200000000
28
29 /* LCD Control Register */
30 #define LCDC_CTRL_CLK_DIVISOR_MASK GENMASK(15, 8)
31 #define LCDC_CTRL_RASTER_MODE BIT(0)
32 #define LCDC_CTRL_CLK_DIVISOR(x) (((x) & GENMASK(7, 0)) << 8)
33 /* LCD Clock Enable Register */
34 #define LCDC_CLKC_ENABLE_CORECLKEN BIT(0)
35 #define LCDC_CLKC_ENABLE_LIDDCLKEN BIT(1)
36 #define LCDC_CLKC_ENABLE_DMACLKEN BIT(2)
37 /* LCD DMA Control Register */
38 #define LCDC_DMA_CTRL_BURST_SIZE(x) (((x) & GENMASK(2, 0)) << 4)
39 #define LCDC_DMA_CTRL_BURST_1 0x0
40 #define LCDC_DMA_CTRL_BURST_2 0x1
41 #define LCDC_DMA_CTRL_BURST_4 0x2
42 #define LCDC_DMA_CTRL_BURST_8 0x3
43 #define LCDC_DMA_CTRL_BURST_16 0x4
44 #define LCDC_DMA_CTRL_FIFO_TH(x) (((x) & GENMASK(2, 0)) << 8)
45 /* LCD Timing_0 Register */
46 #define LCDC_RASTER_TIMING_0_HORMSB(x) ((((x) - 1) & BIT(10)) >> 7)
47 #define LCDC_RASTER_TIMING_0_HORLSB(x) (((((x) >> 4) - 1) & GENMASK(5, 0)) << 4)
48 #define LCDC_RASTER_TIMING_0_HSWLSB(x) ((((x) - 1) & GENMASK(5, 0)) << 10)
49 #define LCDC_RASTER_TIMING_0_HFPLSB(x) ((((x) - 1) & GENMASK(7, 0)) << 16)
50 #define LCDC_RASTER_TIMING_0_HBPLSB(x) ((((x) - 1) & GENMASK(7, 0)) << 24)
51 /* LCD Timing_1 Register */
52 #define LCDC_RASTER_TIMING_1_VERLSB(x) (((x) - 1) & GENMASK(9, 0))
53 #define LCDC_RASTER_TIMING_1_VSW(x) ((((x) - 1) & GENMASK(5, 0)) << 10)
54 #define LCDC_RASTER_TIMING_1_VFP(x) (((x) & GENMASK(7, 0)) << 16)
55 #define LCDC_RASTER_TIMING_1_VBP(x) (((x) & GENMASK(7, 0)) << 24)
56 /* LCD Timing_2 Register */
57 #define LCDC_RASTER_TIMING_2_HFPMSB(x) ((((x) - 1) & GENMASK(9, 8)) >> 8)
58 #define LCDC_RASTER_TIMING_2_HBPMSB(x) ((((x) - 1) & GENMASK(9, 8)) >> 4)
59 #define LCDC_RASTER_TIMING_2_ACB(x) (((x) & GENMASK(7, 0)) << 8)
60 #define LCDC_RASTER_TIMING_2_ACBI(x) (((x) & GENMASK(3, 0)) << 16)
61 #define LCDC_RASTER_TIMING_2_VSYNC_INVERT BIT(20)
62 #define LCDC_RASTER_TIMING_2_HSYNC_INVERT BIT(21)
63 #define LCDC_RASTER_TIMING_2_PXCLK_INVERT BIT(22)
64 #define LCDC_RASTER_TIMING_2_DE_INVERT BIT(23)
65 #define LCDC_RASTER_TIMING_2_HSVS_RISEFALL BIT(24)
66 #define LCDC_RASTER_TIMING_2_HSVS_CONTROL BIT(25)
67 #define LCDC_RASTER_TIMING_2_VERMSB(x) ((((x) - 1) & BIT(10)) << 16)
68 #define LCDC_RASTER_TIMING_2_HSWMSB(x) ((((x) - 1) & GENMASK(9, 6)) << 21)
69 /* LCD Raster Ctrl Register */
70 #define LCDC_RASTER_CTRL_ENABLE BIT(0)
71 #define LCDC_RASTER_CTRL_TFT_MODE BIT(7)
72 #define LCDC_RASTER_CTRL_DATA_ORDER BIT(8)
73 #define LCDC_RASTER_CTRL_REQDLY(x) (((x) & GENMASK(7, 0)) << 12)
74 #define LCDC_RASTER_CTRL_PALMODE_RAWDATA (0x02 << 20)
75 #define LCDC_RASTER_CTRL_TFT_ALT_ENABLE BIT(23)
76 #define LCDC_RASTER_CTRL_TFT_24BPP_MODE BIT(25)
77 #define LCDC_RASTER_CTRL_TFT_24BPP_UNPACK BIT(26)
78
79 struct am335x_lcdhw {
80 unsigned int pid; /* 0x00 */
81 unsigned int ctrl; /* 0x04 */
82 unsigned int gap0; /* 0x08 */
83 unsigned int lidd_ctrl; /* 0x0C */
84 unsigned int lidd_cs0_conf; /* 0x10 */
85 unsigned int lidd_cs0_addr; /* 0x14 */
86 unsigned int lidd_cs0_data; /* 0x18 */
87 unsigned int lidd_cs1_conf; /* 0x1C */
88 unsigned int lidd_cs1_addr; /* 0x20 */
89 unsigned int lidd_cs1_data; /* 0x24 */
90 unsigned int raster_ctrl; /* 0x28 */
91 unsigned int raster_timing0; /* 0x2C */
92 unsigned int raster_timing1; /* 0x30 */
93 unsigned int raster_timing2; /* 0x34 */
94 unsigned int raster_subpanel; /* 0x38 */
95 unsigned int raster_subpanel2; /* 0x3C */
96 unsigned int lcddma_ctrl; /* 0x40 */
97 unsigned int lcddma_fb0_base; /* 0x44 */
98 unsigned int lcddma_fb0_ceiling; /* 0x48 */
99 unsigned int lcddma_fb1_base; /* 0x4C */
100 unsigned int lcddma_fb1_ceiling; /* 0x50 */
101 unsigned int sysconfig; /* 0x54 */
102 unsigned int irqstatus_raw; /* 0x58 */
103 unsigned int irqstatus; /* 0x5C */
104 unsigned int irqenable_set; /* 0x60 */
105 unsigned int irqenable_clear; /* 0x64 */
106 unsigned int gap1; /* 0x68 */
107 unsigned int clkc_enable; /* 0x6C */
108 unsigned int clkc_reset; /* 0x70 */
109 };
110
111 DECLARE_GLOBAL_DATA_PTR;
112
113 #if !defined(LCD_CNTL_BASE)
114 #error "hw-base address of LCD-Controller (LCD_CNTL_BASE) not defined!"
115 #endif
116
117 /* Macro definitions */
118 #define FBSIZE(x) (((x)->hactive * (x)->vactive * (x)->bpp) >> 3)
119
120 #define LCDC_RASTER_TIMING_2_INVMASK(x) ((x) & GENMASK(25, 20))
121
122 static struct am335x_lcdhw *lcdhw = (void *)LCD_CNTL_BASE;
123
lcd_get_size(int * line_length)124 int lcd_get_size(int *line_length)
125 {
126 *line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;
127 return *line_length * panel_info.vl_row + 0x20;
128 }
129
130 struct dpll_data {
131 unsigned long rounded_rate;
132 u16 rounded_m;
133 u8 rounded_n;
134 u8 rounded_div;
135 };
136
137 /**
138 * am335x_dpll_round_rate() - Round a target rate for an OMAP DPLL
139 *
140 * @dpll_data: struct dpll_data pointer for the DPLL
141 * @rate: New DPLL clock rate
142 * @return rounded rate and the computed m, n and div values in the dpll_data
143 * structure, or -ve error code.
144 */
am335x_dpll_round_rate(struct dpll_data * dd,ulong rate)145 static ulong am335x_dpll_round_rate(struct dpll_data *dd, ulong rate)
146 {
147 unsigned int m, n, d;
148 unsigned long rounded_rate;
149 int err, err_r;
150
151 dd->rounded_rate = -EFAULT;
152 err = rate;
153 err_r = err;
154
155 for (d = 2; err && d < 255; d++) {
156 for (m = 2; m < 2047; m++) {
157 if ((V_OSCK * m) < (rate * d))
158 continue;
159
160 n = (V_OSCK * m) / (rate * d);
161 if (n > 127)
162 break;
163
164 if (((V_OSCK * m) / n) > LCDC_FMAX)
165 break;
166
167 rounded_rate = (V_OSCK * m) / n / d;
168 err = abs(rounded_rate - rate);
169 if (err < err_r) {
170 err_r = err;
171 dd->rounded_rate = rounded_rate;
172 dd->rounded_m = m;
173 dd->rounded_n = n;
174 dd->rounded_div = d;
175 if (err == 0)
176 break;
177 }
178 }
179 }
180
181 debug("DPLL display: best error %d Hz (M %d, N %d, DIV %d)\n",
182 err_r, dd->rounded_m, dd->rounded_n, dd->rounded_div);
183
184 return dd->rounded_rate;
185 }
186
187 /**
188 * am335x_fb_set_pixel_clk_rate() - Set pixel clock rate.
189 *
190 * @am335x_lcdhw: Base address of the LCD controller registers.
191 * @rate: New clock rate in Hz.
192 * @return new rate, or -ve error code.
193 */
am335x_fb_set_pixel_clk_rate(struct am335x_lcdhw * regs,ulong rate)194 static ulong am335x_fb_set_pixel_clk_rate(struct am335x_lcdhw *regs, ulong rate)
195 {
196 struct dpll_params dpll_disp = { 1, 0, 1, -1, -1, -1, -1 };
197 struct dpll_data dd;
198 ulong round_rate;
199 u32 reg;
200
201 round_rate = am335x_dpll_round_rate(&dd, rate);
202 if (IS_ERR_VALUE(round_rate))
203 return round_rate;
204
205 dpll_disp.m = dd.rounded_m;
206 dpll_disp.n = dd.rounded_n;
207 do_setup_dpll(&dpll_disp_regs, &dpll_disp);
208
209 reg = readl(®s->ctrl) & ~LCDC_CTRL_CLK_DIVISOR_MASK;
210 reg |= LCDC_CTRL_CLK_DIVISOR(dd.rounded_div);
211 writel(reg, ®s->ctrl);
212 return round_rate;
213 }
214
am335xfb_init(struct am335x_lcdpanel * panel)215 int am335xfb_init(struct am335x_lcdpanel *panel)
216 {
217 u32 raster_ctrl = 0;
218 struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL;
219 ulong rate;
220 u32 reg;
221
222 if (gd->fb_base == 0) {
223 printf("ERROR: no valid fb_base stored in GLOBAL_DATA_PTR!\n");
224 return -1;
225 }
226 if (panel == NULL) {
227 printf("ERROR: missing ptr to am335x_lcdpanel!\n");
228 return -1;
229 }
230
231 /* We can already set the bits for the raster_ctrl in this check */
232 switch (panel->bpp) {
233 case 16:
234 break;
235 case 32:
236 raster_ctrl |= LCDC_RASTER_CTRL_TFT_24BPP_UNPACK;
237 /* fallthrough */
238 case 24:
239 raster_ctrl |= LCDC_RASTER_CTRL_TFT_24BPP_MODE;
240 break;
241 default:
242 pr_err("am335x-fb: invalid bpp value: %d\n", panel->bpp);
243 return -1;
244 }
245
246 /* check given clock-frequency */
247 if (panel->pxl_clk > (LCDC_FMAX / 2)) {
248 pr_err("am335x-fb: requested pxl-clk: %d not supported!\n",
249 panel->pxl_clk);
250 return -1;
251 }
252
253 debug("setting up LCD-Controller for %dx%dx%d (hfp=%d,hbp=%d,hsw=%d / ",
254 panel->hactive, panel->vactive, panel->bpp,
255 panel->hfp, panel->hbp, panel->hsw);
256 debug("vfp=%d,vbp=%d,vsw=%d / clk=%d)\n",
257 panel->vfp, panel->vfp, panel->vsw, panel->pxl_clk);
258 debug("using frambuffer at 0x%08x with size %d.\n",
259 (unsigned int)gd->fb_base, FBSIZE(panel));
260
261 rate = am335x_fb_set_pixel_clk_rate(lcdhw, panel->pxl_clk);
262 if (IS_ERR_VALUE(rate))
263 return rate;
264
265 /* clock source for LCDC from dispPLL M2 */
266 writel(0x0, &cmdpll->clklcdcpixelclk);
267
268 /* palette default entry */
269 memset((void *)gd->fb_base, 0, 0x20);
270 *(unsigned int *)gd->fb_base = 0x4000;
271 /* point fb behind palette */
272 gd->fb_base += 0x20;
273
274 /* turn ON display through powercontrol function if accessible */
275 if (panel->panel_power_ctrl != NULL)
276 panel->panel_power_ctrl(1);
277
278 debug("am335x-fb: wait for stable power ...\n");
279 mdelay(panel->pup_delay);
280 lcdhw->clkc_enable = LCDC_CLKC_ENABLE_CORECLKEN |
281 LCDC_CLKC_ENABLE_LIDDCLKEN | LCDC_CLKC_ENABLE_DMACLKEN;
282 lcdhw->raster_ctrl = 0;
283
284 reg = lcdhw->ctrl & LCDC_CTRL_CLK_DIVISOR_MASK;
285 reg |= LCDC_CTRL_RASTER_MODE;
286 lcdhw->ctrl = reg;
287
288 lcdhw->lcddma_fb0_base = gd->fb_base;
289 lcdhw->lcddma_fb0_ceiling = gd->fb_base + FBSIZE(panel);
290 lcdhw->lcddma_fb1_base = gd->fb_base;
291 lcdhw->lcddma_fb1_ceiling = gd->fb_base + FBSIZE(panel);
292 lcdhw->lcddma_ctrl = LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_16);
293
294 lcdhw->raster_timing0 = LCDC_RASTER_TIMING_0_HORLSB(panel->hactive) |
295 LCDC_RASTER_TIMING_0_HORMSB(panel->hactive) |
296 LCDC_RASTER_TIMING_0_HFPLSB(panel->hfp) |
297 LCDC_RASTER_TIMING_0_HBPLSB(panel->hbp) |
298 LCDC_RASTER_TIMING_0_HSWLSB(panel->hsw);
299 lcdhw->raster_timing1 = LCDC_RASTER_TIMING_1_VBP(panel->vbp) |
300 LCDC_RASTER_TIMING_1_VFP(panel->vfp) |
301 LCDC_RASTER_TIMING_1_VSW(panel->vsw) |
302 LCDC_RASTER_TIMING_1_VERLSB(panel->vactive);
303 lcdhw->raster_timing2 = LCDC_RASTER_TIMING_2_HSWMSB(panel->hsw) |
304 LCDC_RASTER_TIMING_2_VERMSB(panel->vactive) |
305 LCDC_RASTER_TIMING_2_INVMASK(panel->pol) |
306 LCDC_RASTER_TIMING_2_HBPMSB(panel->hbp) |
307 LCDC_RASTER_TIMING_2_HFPMSB(panel->hfp) |
308 0x0000FF00; /* clk cycles for ac-bias */
309 lcdhw->raster_ctrl = raster_ctrl |
310 LCDC_RASTER_CTRL_PALMODE_RAWDATA |
311 LCDC_RASTER_CTRL_TFT_MODE |
312 LCDC_RASTER_CTRL_ENABLE;
313
314 debug("am335x-fb: waiting picture to be stable.\n.");
315 mdelay(panel->pon_delay);
316
317 return 0;
318 }
319