1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Freescale i.MX23/i.MX28 LCDIF driver
4  *
5  * Copyright (C) 2011-2013 Marek Vasut <marex@denx.de>
6  */
7 #include <clk.h>
8 #include <dm.h>
9 #include <env.h>
10 #include <log.h>
11 #include <asm/cache.h>
12 #include <dm/device_compat.h>
13 #include <linux/delay.h>
14 #include <linux/errno.h>
15 #include <malloc.h>
16 #include <video.h>
17 
18 #include <asm/arch/clock.h>
19 #include <asm/arch/imx-regs.h>
20 #include <asm/arch/sys_proto.h>
21 #include <asm/global_data.h>
22 #include <asm/mach-imx/dma.h>
23 #include <asm/io.h>
24 
25 #include "videomodes.h"
26 
27 #define	PS2KHZ(ps)	(1000000000UL / (ps))
28 #define HZ2PS(hz)	(1000000000UL / ((hz) / 1000))
29 
30 #define BITS_PP		18
31 #define BYTES_PP	4
32 
33 struct mxs_dma_desc desc;
34 
35 /**
36  * mxsfb_system_setup() - Fine-tune LCDIF configuration
37  *
38  * This function is used to adjust the LCDIF configuration. This is usually
39  * needed when driving the controller in System-Mode to operate an 8080 or
40  * 6800 connected SmartLCD.
41  */
mxsfb_system_setup(void)42 __weak void mxsfb_system_setup(void)
43 {
44 }
45 
46 /*
47  * ARIES M28EVK:
48  * setenv videomode
49  * video=ctfb:x:800,y:480,depth:18,mode:0,pclk:30066,
50  *       le:0,ri:256,up:0,lo:45,hs:1,vs:1,sync:100663296,vmode:0
51  *
52  * Freescale mx23evk/mx28evk with a Seiko 4.3'' WVGA panel:
53  * setenv videomode
54  * video=ctfb:x:800,y:480,depth:24,mode:0,pclk:29851,
55  *	 le:89,ri:164,up:23,lo:10,hs:10,vs:10,sync:0,vmode:0
56  */
57 
mxs_lcd_init(struct udevice * dev,u32 fb_addr,struct display_timing * timings,int bpp)58 static void mxs_lcd_init(struct udevice *dev, u32 fb_addr,
59 			 struct display_timing *timings, int bpp)
60 {
61 	struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
62 	const enum display_flags flags = timings->flags;
63 	uint32_t word_len = 0, bus_width = 0;
64 	uint8_t valid_data = 0;
65 	uint32_t vdctrl0;
66 
67 #if CONFIG_IS_ENABLED(CLK)
68 	struct clk clk;
69 	int ret;
70 
71 	ret = clk_get_by_name(dev, "pix", &clk);
72 	if (ret) {
73 		dev_err(dev, "Failed to get mxs pix clk: %d\n", ret);
74 		return;
75 	}
76 
77 	ret = clk_set_rate(&clk, timings->pixelclock.typ);
78 	if (ret < 0) {
79 		dev_err(dev, "Failed to set mxs pix clk: %d\n", ret);
80 		return;
81 	}
82 
83 	ret = clk_enable(&clk);
84 	if (ret < 0) {
85 		dev_err(dev, "Failed to enable mxs pix clk: %d\n", ret);
86 		return;
87 	}
88 
89 	ret = clk_get_by_name(dev, "axi", &clk);
90 	if (ret < 0) {
91 		debug("%s: Failed to get mxs axi clk: %d\n", __func__, ret);
92 	} else {
93 		ret = clk_enable(&clk);
94 		if (ret < 0) {
95 			dev_err(dev, "Failed to enable mxs axi clk: %d\n", ret);
96 			return;
97 		}
98 	}
99 
100 	ret = clk_get_by_name(dev, "disp_axi", &clk);
101 	if (ret < 0) {
102 		debug("%s: Failed to get mxs disp_axi clk: %d\n", __func__, ret);
103 	} else {
104 		ret = clk_enable(&clk);
105 		if (ret < 0) {
106 			dev_err(dev, "Failed to enable mxs disp_axi clk: %d\n", ret);
107 			return;
108 		}
109 	}
110 #else
111 	/* Kick in the LCDIF clock */
112 	mxs_set_lcdclk(MXS_LCDIF_BASE, timings->pixelclock.typ / 1000);
113 #endif
114 
115 	/* Restart the LCDIF block */
116 	mxs_reset_block(&regs->hw_lcdif_ctrl_reg);
117 
118 	switch (bpp) {
119 	case 24:
120 		word_len = LCDIF_CTRL_WORD_LENGTH_24BIT;
121 		bus_width = LCDIF_CTRL_LCD_DATABUS_WIDTH_24BIT;
122 		valid_data = 0x7;
123 		break;
124 	case 18:
125 		word_len = LCDIF_CTRL_WORD_LENGTH_24BIT;
126 		bus_width = LCDIF_CTRL_LCD_DATABUS_WIDTH_18BIT;
127 		valid_data = 0x7;
128 		break;
129 	case 16:
130 		word_len = LCDIF_CTRL_WORD_LENGTH_16BIT;
131 		bus_width = LCDIF_CTRL_LCD_DATABUS_WIDTH_16BIT;
132 		valid_data = 0xf;
133 		break;
134 	case 8:
135 		word_len = LCDIF_CTRL_WORD_LENGTH_8BIT;
136 		bus_width = LCDIF_CTRL_LCD_DATABUS_WIDTH_8BIT;
137 		valid_data = 0xf;
138 		break;
139 	}
140 
141 	writel(bus_width | word_len | LCDIF_CTRL_DOTCLK_MODE |
142 		LCDIF_CTRL_BYPASS_COUNT | LCDIF_CTRL_LCDIF_MASTER,
143 		&regs->hw_lcdif_ctrl);
144 
145 	writel(valid_data << LCDIF_CTRL1_BYTE_PACKING_FORMAT_OFFSET,
146 		&regs->hw_lcdif_ctrl1);
147 
148 	mxsfb_system_setup();
149 
150 	writel((timings->vactive.typ << LCDIF_TRANSFER_COUNT_V_COUNT_OFFSET) |
151 		timings->hactive.typ, &regs->hw_lcdif_transfer_count);
152 
153 	vdctrl0 = LCDIF_VDCTRL0_ENABLE_PRESENT | LCDIF_VDCTRL0_ENABLE_POL |
154 		  LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT |
155 		  LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
156 		  timings->vsync_len.typ;
157 
158 	if(flags & DISPLAY_FLAGS_HSYNC_HIGH)
159 		vdctrl0 |= LCDIF_VDCTRL0_HSYNC_POL;
160 	if(flags & DISPLAY_FLAGS_VSYNC_HIGH)
161 		vdctrl0 |= LCDIF_VDCTRL0_VSYNC_POL;
162 	if(flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
163 		vdctrl0 |= LCDIF_VDCTRL0_DOTCLK_POL;
164 	if(flags & DISPLAY_FLAGS_DE_HIGH)
165 		vdctrl0 |= LCDIF_VDCTRL0_ENABLE_POL;
166 
167 	writel(vdctrl0, &regs->hw_lcdif_vdctrl0);
168 	writel(timings->vback_porch.typ + timings->vfront_porch.typ +
169 		timings->vsync_len.typ + timings->vactive.typ,
170 		&regs->hw_lcdif_vdctrl1);
171 	writel((timings->hsync_len.typ << LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_OFFSET) |
172 		(timings->hback_porch.typ + timings->hfront_porch.typ +
173 		timings->hsync_len.typ + timings->hactive.typ),
174 		&regs->hw_lcdif_vdctrl2);
175 	writel(((timings->hback_porch.typ + timings->hsync_len.typ) <<
176 		LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_OFFSET) |
177 		(timings->vback_porch.typ + timings->vsync_len.typ),
178 		&regs->hw_lcdif_vdctrl3);
179 	writel((0 << LCDIF_VDCTRL4_DOTCLK_DLY_SEL_OFFSET) | timings->hactive.typ,
180 		&regs->hw_lcdif_vdctrl4);
181 
182 	writel(fb_addr, &regs->hw_lcdif_cur_buf);
183 	writel(fb_addr, &regs->hw_lcdif_next_buf);
184 
185 	/* Flush FIFO first */
186 	writel(LCDIF_CTRL1_FIFO_CLEAR, &regs->hw_lcdif_ctrl1_set);
187 
188 #ifndef CONFIG_VIDEO_MXS_MODE_SYSTEM
189 	/* Sync signals ON */
190 	setbits_le32(&regs->hw_lcdif_vdctrl4, LCDIF_VDCTRL4_SYNC_SIGNALS_ON);
191 #endif
192 
193 	/* FIFO cleared */
194 	writel(LCDIF_CTRL1_FIFO_CLEAR, &regs->hw_lcdif_ctrl1_clr);
195 
196 	/* RUN! */
197 	writel(LCDIF_CTRL_RUN, &regs->hw_lcdif_ctrl_set);
198 }
199 
mxs_probe_common(struct udevice * dev,struct display_timing * timings,int bpp,u32 fb)200 static int mxs_probe_common(struct udevice *dev, struct display_timing *timings,
201 			    int bpp, u32 fb)
202 {
203 	/* Start framebuffer */
204 	mxs_lcd_init(dev, fb, timings, bpp);
205 
206 #ifdef CONFIG_VIDEO_MXS_MODE_SYSTEM
207 	/*
208 	 * If the LCD runs in system mode, the LCD refresh has to be triggered
209 	 * manually by setting the RUN bit in HW_LCDIF_CTRL register. To avoid
210 	 * having to set this bit manually after every single change in the
211 	 * framebuffer memory, we set up specially crafted circular DMA, which
212 	 * sets the RUN bit, then waits until it gets cleared and repeats this
213 	 * infinitelly. This way, we get smooth continuous updates of the LCD.
214 	 */
215 	struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
216 
217 	memset(&desc, 0, sizeof(struct mxs_dma_desc));
218 	desc.address = (dma_addr_t)&desc;
219 	desc.cmd.data = MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
220 			MXS_DMA_DESC_WAIT4END |
221 			(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
222 	desc.cmd.pio_words[0] = readl(&regs->hw_lcdif_ctrl) | LCDIF_CTRL_RUN;
223 	desc.cmd.next = (uint32_t)&desc.cmd;
224 
225 	/* Execute the DMA chain. */
226 	mxs_dma_circ_start(MXS_DMA_CHANNEL_AHB_APBH_LCDIF, &desc);
227 #endif
228 
229 	return 0;
230 }
231 
mxs_remove_common(u32 fb)232 static int mxs_remove_common(u32 fb)
233 {
234 	struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
235 	int timeout = 1000000;
236 
237 	if (!fb)
238 		return -EINVAL;
239 
240 	writel(fb, &regs->hw_lcdif_cur_buf_reg);
241 	writel(fb, &regs->hw_lcdif_next_buf_reg);
242 	writel(LCDIF_CTRL1_VSYNC_EDGE_IRQ, &regs->hw_lcdif_ctrl1_clr);
243 	while (--timeout) {
244 		if (readl(&regs->hw_lcdif_ctrl1_reg) &
245 		    LCDIF_CTRL1_VSYNC_EDGE_IRQ)
246 			break;
247 		udelay(1);
248 	}
249 	mxs_reset_block((struct mxs_register_32 *)&regs->hw_lcdif_ctrl_reg);
250 
251 	return 0;
252 }
253 
mxs_of_get_timings(struct udevice * dev,struct display_timing * timings,u32 * bpp)254 static int mxs_of_get_timings(struct udevice *dev,
255 			      struct display_timing *timings,
256 			      u32 *bpp)
257 {
258 	int ret = 0;
259 	u32 display_phandle;
260 	ofnode display_node;
261 
262 	ret = ofnode_read_u32(dev_ofnode(dev), "display", &display_phandle);
263 	if (ret) {
264 		dev_err(dev, "required display property isn't provided\n");
265 		return -EINVAL;
266 	}
267 
268 	display_node = ofnode_get_by_phandle(display_phandle);
269 	if (!ofnode_valid(display_node)) {
270 		dev_err(dev, "failed to find display subnode\n");
271 		return -EINVAL;
272 	}
273 
274 	ret = ofnode_read_u32(display_node, "bits-per-pixel", bpp);
275 	if (ret) {
276 		dev_err(dev,
277 			"required bits-per-pixel property isn't provided\n");
278 		return -EINVAL;
279 	}
280 
281 	ret = ofnode_decode_display_timing(display_node, 0, timings);
282 	if (ret) {
283 		dev_err(dev, "failed to get any display timings\n");
284 		return -EINVAL;
285 	}
286 
287 	return ret;
288 }
289 
mxs_video_probe(struct udevice * dev)290 static int mxs_video_probe(struct udevice *dev)
291 {
292 	struct video_uc_plat *plat = dev_get_uclass_plat(dev);
293 	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
294 
295 	struct display_timing timings;
296 	u32 bpp = 0;
297 	u32 fb_start, fb_end;
298 	int ret;
299 
300 	debug("%s() plat: base 0x%lx, size 0x%x\n",
301 	       __func__, plat->base, plat->size);
302 
303 	ret = mxs_of_get_timings(dev, &timings, &bpp);
304 	if (ret)
305 		return ret;
306 
307 	ret = mxs_probe_common(dev, &timings, bpp, plat->base);
308 	if (ret)
309 		return ret;
310 
311 	switch (bpp) {
312 	case 32:
313 	case 24:
314 	case 18:
315 		uc_priv->bpix = VIDEO_BPP32;
316 		break;
317 	case 16:
318 		uc_priv->bpix = VIDEO_BPP16;
319 		break;
320 	case 8:
321 		uc_priv->bpix = VIDEO_BPP8;
322 		break;
323 	default:
324 		dev_err(dev, "invalid bpp specified (bpp = %i)\n", bpp);
325 		return -EINVAL;
326 	}
327 
328 	uc_priv->xsize = timings.hactive.typ;
329 	uc_priv->ysize = timings.vactive.typ;
330 
331 	/* Enable dcache for the frame buffer */
332 	fb_start = plat->base & ~(MMU_SECTION_SIZE - 1);
333 	fb_end = plat->base + plat->size;
334 	fb_end = ALIGN(fb_end, 1 << MMU_SECTION_SHIFT);
335 	mmu_set_region_dcache_behaviour(fb_start, fb_end - fb_start,
336 					DCACHE_WRITEBACK);
337 	video_set_flush_dcache(dev, true);
338 
339 	return ret;
340 }
341 
mxs_video_bind(struct udevice * dev)342 static int mxs_video_bind(struct udevice *dev)
343 {
344 	struct video_uc_plat *plat = dev_get_uclass_plat(dev);
345 	struct display_timing timings;
346 	u32 bpp = 0;
347 	u32 bytes_pp = 0;
348 	int ret;
349 
350 	ret = mxs_of_get_timings(dev, &timings, &bpp);
351 	if (ret)
352 		return ret;
353 
354 	switch (bpp) {
355 	case 32:
356 	case 24:
357 	case 18:
358 		bytes_pp = 4;
359 		break;
360 	case 16:
361 		bytes_pp = 2;
362 		break;
363 	case 8:
364 		bytes_pp = 1;
365 		break;
366 	default:
367 		dev_err(dev, "invalid bpp specified (bpp = %i)\n", bpp);
368 		return -EINVAL;
369 	}
370 
371 	plat->size = timings.hactive.typ * timings.vactive.typ * bytes_pp;
372 
373 	return 0;
374 }
375 
mxs_video_remove(struct udevice * dev)376 static int mxs_video_remove(struct udevice *dev)
377 {
378 	struct video_uc_plat *plat = dev_get_uclass_plat(dev);
379 
380 	mxs_remove_common(plat->base);
381 
382 	return 0;
383 }
384 
385 static const struct udevice_id mxs_video_ids[] = {
386 	{ .compatible = "fsl,imx23-lcdif" },
387 	{ .compatible = "fsl,imx28-lcdif" },
388 	{ .compatible = "fsl,imx6sx-lcdif" },
389 	{ .compatible = "fsl,imx7ulp-lcdif" },
390 	{ .compatible = "fsl,imxrt-lcdif" },
391 	{ /* sentinel */ }
392 };
393 
394 U_BOOT_DRIVER(mxs_video) = {
395 	.name	= "mxs_video",
396 	.id	= UCLASS_VIDEO,
397 	.of_match = mxs_video_ids,
398 	.bind	= mxs_video_bind,
399 	.probe	= mxs_video_probe,
400 	.remove = mxs_video_remove,
401 	.flags	= DM_FLAG_PRE_RELOC | DM_FLAG_OS_PREPARE,
402 };
403