Commit 613092e2fd58ac50f4416f73a37ed47de6275a51

Authored by Ye Li
1 parent c48c0a4d72

MLK-25320 video: imx_lcdifv3: Add memory priority threshold setting

Add the panic control from kernel for lcdifv3 to increase the memory
request priority to resolve QoS issue.
User can adjust the thresholds by using 'thres-low' and 'thres-high'
properties in DTS.

Signed-off-by: Ye Li <ye.li@nxp.com>
Reviewed-by: Jian Li <jian.li@nxp.com>
(cherry picked from commit f81e7caa100940206550ee4e2f64b5b799a5d92e)

Showing 1 changed file with 90 additions and 0 deletions Inline Diff

drivers/video/nxp/imx/imx_lcdifv3.c
1 // SPDX-License-Identifier: GPL-2.0+ 1 // SPDX-License-Identifier: GPL-2.0+
2 /* 2 /*
3 * Copyright 2019 NXP 3 * Copyright 2019 NXP
4 */ 4 */
5 5
6 #include <common.h> 6 #include <common.h>
7 #include <malloc.h> 7 #include <malloc.h>
8 #include <video.h> 8 #include <video.h>
9 #include <video_fb.h> 9 #include <video_fb.h>
10 #include <video_bridge.h> 10 #include <video_bridge.h>
11 #include <video_link.h> 11 #include <video_link.h>
12 12
13 #include <asm/arch/imx-regs.h> 13 #include <asm/arch/imx-regs.h>
14 #include <asm/arch/clock.h> 14 #include <asm/arch/clock.h>
15 #include <asm/arch/sys_proto.h> 15 #include <asm/arch/sys_proto.h>
16 #include <linux/err.h> 16 #include <linux/err.h>
17 #include <asm/io.h> 17 #include <asm/io.h>
18 18
19 #include "../../videomodes.h" 19 #include "../../videomodes.h"
20 #include <linux/string.h> 20 #include <linux/string.h>
21 #include <linux/list.h> 21 #include <linux/list.h>
22 #include <linux/fb.h> 22 #include <linux/fb.h>
23 #include "lcdifv3-regs.h" 23 #include "lcdifv3-regs.h"
24 #include <dm.h> 24 #include <dm.h>
25 #include <dm/device-internal.h> 25 #include <dm/device-internal.h>
26 26
27 #define PS2KHZ(ps) (1000000000UL / (ps)) 27 #define PS2KHZ(ps) (1000000000UL / (ps))
28 #define HZ2PS(hz) (1000000000UL / ((hz) / 1000)) 28 #define HZ2PS(hz) (1000000000UL / ((hz) / 1000))
29 29
30 struct lcdifv3_priv { 30 struct lcdifv3_priv {
31 fdt_addr_t reg_base; 31 fdt_addr_t reg_base;
32 struct udevice *disp_dev; 32 struct udevice *disp_dev;
33
34 u32 thres_low_mul;
35 u32 thres_low_div;
36 u32 thres_high_mul;
37 u32 thres_high_div;
33 }; 38 };
34 39
35 static int lcdifv3_set_pix_fmt(struct lcdifv3_priv *priv, unsigned int format) 40 static int lcdifv3_set_pix_fmt(struct lcdifv3_priv *priv, unsigned int format)
36 { 41 {
37 uint32_t ctrldescl0_5 = 0; 42 uint32_t ctrldescl0_5 = 0;
38 43
39 ctrldescl0_5 = readl((ulong)(priv->reg_base + LCDIFV3_CTRLDESCL0_5)); 44 ctrldescl0_5 = readl((ulong)(priv->reg_base + LCDIFV3_CTRLDESCL0_5));
40 45
41 WARN_ON(ctrldescl0_5 & CTRLDESCL0_5_SHADOW_LOAD_EN); 46 WARN_ON(ctrldescl0_5 & CTRLDESCL0_5_SHADOW_LOAD_EN);
42 47
43 ctrldescl0_5 &= ~(CTRLDESCL0_5_BPP(0xf) | CTRLDESCL0_5_YUV_FORMAT(0x3)); 48 ctrldescl0_5 &= ~(CTRLDESCL0_5_BPP(0xf) | CTRLDESCL0_5_YUV_FORMAT(0x3));
44 49
45 switch (format) { 50 switch (format) {
46 case GDF_16BIT_565RGB: 51 case GDF_16BIT_565RGB:
47 ctrldescl0_5 |= CTRLDESCL0_5_BPP(BPP16_RGB565); 52 ctrldescl0_5 |= CTRLDESCL0_5_BPP(BPP16_RGB565);
48 break; 53 break;
49 case GDF_32BIT_X888RGB: 54 case GDF_32BIT_X888RGB:
50 ctrldescl0_5 |= CTRLDESCL0_5_BPP(BPP32_ARGB8888); 55 ctrldescl0_5 |= CTRLDESCL0_5_BPP(BPP32_ARGB8888);
51 break; 56 break;
52 default: 57 default:
53 printf("unsupported pixel format: %u\n", format); 58 printf("unsupported pixel format: %u\n", format);
54 return -EINVAL; 59 return -EINVAL;
55 } 60 }
56 61
57 writel(ctrldescl0_5, (ulong)(priv->reg_base + LCDIFV3_CTRLDESCL0_5)); 62 writel(ctrldescl0_5, (ulong)(priv->reg_base + LCDIFV3_CTRLDESCL0_5));
58 63
59 return 0; 64 return 0;
60 } 65 }
61 66
62 67
63 static void lcdifv3_set_mode(struct lcdifv3_priv *priv, 68 static void lcdifv3_set_mode(struct lcdifv3_priv *priv,
64 struct ctfb_res_modes *mode) 69 struct ctfb_res_modes *mode)
65 { 70 {
66 u32 disp_size, hsyn_para, vsyn_para, vsyn_hsyn_width, ctrldescl0_1; 71 u32 disp_size, hsyn_para, vsyn_para, vsyn_hsyn_width, ctrldescl0_1;
67 72
68 /* config display timings */ 73 /* config display timings */
69 disp_size = DISP_SIZE_DELTA_Y(mode->yres) | 74 disp_size = DISP_SIZE_DELTA_Y(mode->yres) |
70 DISP_SIZE_DELTA_X(mode->xres); 75 DISP_SIZE_DELTA_X(mode->xres);
71 writel(disp_size, (ulong)(priv->reg_base + LCDIFV3_DISP_SIZE)); 76 writel(disp_size, (ulong)(priv->reg_base + LCDIFV3_DISP_SIZE));
72 77
73 hsyn_para = HSYN_PARA_BP_H(mode->left_margin) | 78 hsyn_para = HSYN_PARA_BP_H(mode->left_margin) |
74 HSYN_PARA_FP_H(mode->right_margin); 79 HSYN_PARA_FP_H(mode->right_margin);
75 writel(hsyn_para, (ulong)(priv->reg_base + LCDIFV3_HSYN_PARA)); 80 writel(hsyn_para, (ulong)(priv->reg_base + LCDIFV3_HSYN_PARA));
76 81
77 vsyn_para = VSYN_PARA_BP_V(mode->upper_margin) | 82 vsyn_para = VSYN_PARA_BP_V(mode->upper_margin) |
78 VSYN_PARA_FP_V(mode->lower_margin); 83 VSYN_PARA_FP_V(mode->lower_margin);
79 writel(vsyn_para, (ulong)(priv->reg_base + LCDIFV3_VSYN_PARA)); 84 writel(vsyn_para, (ulong)(priv->reg_base + LCDIFV3_VSYN_PARA));
80 85
81 vsyn_hsyn_width = VSYN_HSYN_WIDTH_PW_V(mode->vsync_len) | 86 vsyn_hsyn_width = VSYN_HSYN_WIDTH_PW_V(mode->vsync_len) |
82 VSYN_HSYN_WIDTH_PW_H(mode->hsync_len); 87 VSYN_HSYN_WIDTH_PW_H(mode->hsync_len);
83 writel(vsyn_hsyn_width, (ulong)(priv->reg_base + LCDIFV3_VSYN_HSYN_WIDTH)); 88 writel(vsyn_hsyn_width, (ulong)(priv->reg_base + LCDIFV3_VSYN_HSYN_WIDTH));
84 89
85 /* config layer size */ 90 /* config layer size */
86 /* TODO: 32bits alignment for width */ 91 /* TODO: 32bits alignment for width */
87 ctrldescl0_1 = CTRLDESCL0_1_HEIGHT(mode->yres) | 92 ctrldescl0_1 = CTRLDESCL0_1_HEIGHT(mode->yres) |
88 CTRLDESCL0_1_WIDTH(mode->xres); 93 CTRLDESCL0_1_WIDTH(mode->xres);
89 writel(ctrldescl0_1, (ulong)(priv->reg_base + LCDIFV3_CTRLDESCL0_1)); 94 writel(ctrldescl0_1, (ulong)(priv->reg_base + LCDIFV3_CTRLDESCL0_1));
90 95
91 /* Polarities */ 96 /* Polarities */
92 writel(CTRL_INV_HS, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR)); 97 writel(CTRL_INV_HS, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR));
93 writel(CTRL_INV_VS, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR)); 98 writel(CTRL_INV_VS, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR));
94 99
95 /* SEC MIPI DSI specific */ 100 /* SEC MIPI DSI specific */
96 writel(CTRL_INV_PXCK, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR)); 101 writel(CTRL_INV_PXCK, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR));
97 writel(CTRL_INV_DE, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR)); 102 writel(CTRL_INV_DE, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR));
98 103
99 } 104 }
100 105
101 static void lcdifv3_set_bus_fmt(struct lcdifv3_priv *priv) 106 static void lcdifv3_set_bus_fmt(struct lcdifv3_priv *priv)
102 { 107 {
103 uint32_t disp_para = 0; 108 uint32_t disp_para = 0;
104 109
105 disp_para = readl((ulong)(priv->reg_base + LCDIFV3_DISP_PARA)); 110 disp_para = readl((ulong)(priv->reg_base + LCDIFV3_DISP_PARA));
106 disp_para &= DISP_PARA_LINE_PATTERN(0xf); 111 disp_para &= DISP_PARA_LINE_PATTERN(0xf);
107 112
108 /* Fixed to 24 bits output */ 113 /* Fixed to 24 bits output */
109 disp_para |= DISP_PARA_LINE_PATTERN(LP_RGB888_OR_YUV444); 114 disp_para |= DISP_PARA_LINE_PATTERN(LP_RGB888_OR_YUV444);
110 115
111 /* config display mode: default is normal mode */ 116 /* config display mode: default is normal mode */
112 disp_para &= DISP_PARA_DISP_MODE(3); 117 disp_para &= DISP_PARA_DISP_MODE(3);
113 disp_para |= DISP_PARA_DISP_MODE(0); 118 disp_para |= DISP_PARA_DISP_MODE(0);
114 writel(disp_para, (ulong)(priv->reg_base + LCDIFV3_DISP_PARA)); 119 writel(disp_para, (ulong)(priv->reg_base + LCDIFV3_DISP_PARA));
115 } 120 }
116 121
122 static void lcdifv3_enable_plane_panic(struct lcdifv3_priv *priv)
123 {
124 u32 panic_thres, thres_low, thres_high;
125
126 /* apb clock has been enabled */
127
128 /* As suggestion, the thres_low should be 1/3 FIFO,
129 * and thres_high should be 2/3 FIFO (The FIFO size
130 * is 8KB = 512 * 128bit).
131 * threshold = n * 128bit (n: 0 ~ 511)
132 */
133 thres_low = DIV_ROUND_UP(511 * priv->thres_low_mul,
134 priv->thres_low_div);
135 thres_high = DIV_ROUND_UP(511 * priv->thres_high_mul,
136 priv->thres_high_div);
137
138 panic_thres = PANIC0_THRES_PANIC_THRES_LOW(thres_low) |
139 PANIC0_THRES_PANIC_THRES_HIGH(thres_high);
140
141 writel(panic_thres, priv->reg_base + LCDIFV3_PANIC0_THRES);
142
143 /* Enable Panic:
144 *
145 * As designed, the panic won't trigger an irq,
146 * so it is unnecessary to handle this as an irq
147 * and NoC + QoS modules will handle panic
148 * automatically.
149 */
150 writel(INT_ENABLE_D1_PLANE_PANIC_EN,
151 priv->reg_base + LCDIFV3_INT_ENABLE_D1);
152 }
153
117 static void lcdifv3_enable_controller(struct lcdifv3_priv *priv) 154 static void lcdifv3_enable_controller(struct lcdifv3_priv *priv)
118 { 155 {
119 u32 disp_para, ctrldescl0_5; 156 u32 disp_para, ctrldescl0_5;
120 157
121 disp_para = readl((ulong)(priv->reg_base + LCDIFV3_DISP_PARA)); 158 disp_para = readl((ulong)(priv->reg_base + LCDIFV3_DISP_PARA));
122 ctrldescl0_5 = readl((ulong)(priv->reg_base + LCDIFV3_CTRLDESCL0_5)); 159 ctrldescl0_5 = readl((ulong)(priv->reg_base + LCDIFV3_CTRLDESCL0_5));
123 160
124 /* disp on */ 161 /* disp on */
125 disp_para |= DISP_PARA_DISP_ON; 162 disp_para |= DISP_PARA_DISP_ON;
126 writel(disp_para, (ulong)(priv->reg_base + LCDIFV3_DISP_PARA)); 163 writel(disp_para, (ulong)(priv->reg_base + LCDIFV3_DISP_PARA));
127 164
128 /* enable shadow load */ 165 /* enable shadow load */
129 ctrldescl0_5 |= CTRLDESCL0_5_SHADOW_LOAD_EN; 166 ctrldescl0_5 |= CTRLDESCL0_5_SHADOW_LOAD_EN;
130 writel(ctrldescl0_5, (ulong)(priv->reg_base + LCDIFV3_CTRLDESCL0_5)); 167 writel(ctrldescl0_5, (ulong)(priv->reg_base + LCDIFV3_CTRLDESCL0_5));
131 168
132 /* enable layer dma */ 169 /* enable layer dma */
133 ctrldescl0_5 |= CTRLDESCL0_5_EN; 170 ctrldescl0_5 |= CTRLDESCL0_5_EN;
134 writel(ctrldescl0_5, (ulong)(priv->reg_base + LCDIFV3_CTRLDESCL0_5)); 171 writel(ctrldescl0_5, (ulong)(priv->reg_base + LCDIFV3_CTRLDESCL0_5));
135 } 172 }
136 173
137 static void lcdifv3_disable_controller(struct lcdifv3_priv *priv) 174 static void lcdifv3_disable_controller(struct lcdifv3_priv *priv)
138 { 175 {
139 u32 disp_para, ctrldescl0_5; 176 u32 disp_para, ctrldescl0_5;
140 177
141 disp_para = readl((ulong)(priv->reg_base + LCDIFV3_DISP_PARA)); 178 disp_para = readl((ulong)(priv->reg_base + LCDIFV3_DISP_PARA));
142 ctrldescl0_5 = readl((ulong)(priv->reg_base + LCDIFV3_CTRLDESCL0_5)); 179 ctrldescl0_5 = readl((ulong)(priv->reg_base + LCDIFV3_CTRLDESCL0_5));
143 180
144 /* dma off */ 181 /* dma off */
145 ctrldescl0_5 &= ~CTRLDESCL0_5_EN; 182 ctrldescl0_5 &= ~CTRLDESCL0_5_EN;
146 writel(ctrldescl0_5, (ulong)(priv->reg_base + LCDIFV3_CTRLDESCL0_5)); 183 writel(ctrldescl0_5, (ulong)(priv->reg_base + LCDIFV3_CTRLDESCL0_5));
147 184
148 /* disp off */ 185 /* disp off */
149 disp_para &= ~DISP_PARA_DISP_ON; 186 disp_para &= ~DISP_PARA_DISP_ON;
150 writel(disp_para, (ulong)(priv->reg_base + LCDIFV3_DISP_PARA)); 187 writel(disp_para, (ulong)(priv->reg_base + LCDIFV3_DISP_PARA));
151 } 188 }
152 189
153 static void lcdifv3_init(struct udevice *dev, 190 static void lcdifv3_init(struct udevice *dev,
154 struct ctfb_res_modes *mode, unsigned int format) 191 struct ctfb_res_modes *mode, unsigned int format)
155 { 192 {
156 struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); 193 struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
157 struct lcdifv3_priv *priv = dev_get_priv(dev); 194 struct lcdifv3_priv *priv = dev_get_priv(dev);
158 int ret; 195 int ret;
159 196
160 /* Kick in the LCDIF clock */ 197 /* Kick in the LCDIF clock */
161 mxs_set_lcdclk(priv->reg_base, PS2KHZ(mode->pixclock)); 198 mxs_set_lcdclk(priv->reg_base, PS2KHZ(mode->pixclock));
162 199
163 writel(CTRL_SW_RESET, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR)); 200 writel(CTRL_SW_RESET, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR));
164 201
202 /* enable plane FIFO panic */
203 lcdifv3_enable_plane_panic(priv);
204
165 lcdifv3_set_mode(priv, mode); 205 lcdifv3_set_mode(priv, mode);
166 206
167 lcdifv3_set_bus_fmt(priv); 207 lcdifv3_set_bus_fmt(priv);
168 208
169 ret = lcdifv3_set_pix_fmt(priv, format); 209 ret = lcdifv3_set_pix_fmt(priv, format);
170 if (ret) { 210 if (ret) {
171 printf("Fail to init lcdifv3, wrong format %u\n", format); 211 printf("Fail to init lcdifv3, wrong format %u\n", format);
172 return; 212 return;
173 } 213 }
174 214
175 /* Set fb address to primary layer */ 215 /* Set fb address to primary layer */
176 writel(plat->base, (ulong)(priv->reg_base + LCDIFV3_CTRLDESCL_LOW0_4)); 216 writel(plat->base, (ulong)(priv->reg_base + LCDIFV3_CTRLDESCL_LOW0_4));
177 217
178 writel(CTRLDESCL0_3_P_SIZE(1) |CTRLDESCL0_3_T_SIZE(1) | CTRLDESCL0_3_PITCH(mode->xres * 4), 218 writel(CTRLDESCL0_3_P_SIZE(1) |CTRLDESCL0_3_T_SIZE(1) | CTRLDESCL0_3_PITCH(mode->xres * 4),
179 (ulong)(priv->reg_base + LCDIFV3_CTRLDESCL0_3)); 219 (ulong)(priv->reg_base + LCDIFV3_CTRLDESCL0_3));
180 220
181 lcdifv3_enable_controller(priv); 221 lcdifv3_enable_controller(priv);
182 } 222 }
183 223
184 void lcdifv3_power_down(struct lcdifv3_priv *priv) 224 void lcdifv3_power_down(struct lcdifv3_priv *priv)
185 { 225 {
186 int timeout = 1000000; 226 int timeout = 1000000;
187 227
188 /* Disable LCDIF during VBLANK */ 228 /* Disable LCDIF during VBLANK */
189 writel(INT_STATUS_D0_VS_BLANK, 229 writel(INT_STATUS_D0_VS_BLANK,
190 (ulong)(priv->reg_base + LCDIFV3_INT_STATUS_D0)); 230 (ulong)(priv->reg_base + LCDIFV3_INT_STATUS_D0));
191 while (--timeout) { 231 while (--timeout) {
192 if (readl((ulong)(priv->reg_base + LCDIFV3_INT_STATUS_D0)) & 232 if (readl((ulong)(priv->reg_base + LCDIFV3_INT_STATUS_D0)) &
193 INT_STATUS_D0_VS_BLANK) 233 INT_STATUS_D0_VS_BLANK)
194 break; 234 break;
195 udelay(1); 235 udelay(1);
196 } 236 }
197 237
198 lcdifv3_disable_controller(priv); 238 lcdifv3_disable_controller(priv);
199 } 239 }
200 240
201 static int lcdifv3_of_get_timings(struct udevice *dev, 241 static int lcdifv3_of_get_timings(struct udevice *dev,
202 struct display_timing *timings) 242 struct display_timing *timings)
203 { 243 {
204 int ret = 0; 244 int ret = 0;
205 struct lcdifv3_priv *priv = dev_get_priv(dev); 245 struct lcdifv3_priv *priv = dev_get_priv(dev);
206 246
207 priv->disp_dev = video_link_get_next_device(dev); 247 priv->disp_dev = video_link_get_next_device(dev);
208 if (!priv->disp_dev || 248 if (!priv->disp_dev ||
209 (device_get_uclass_id(priv->disp_dev) != UCLASS_VIDEO_BRIDGE 249 (device_get_uclass_id(priv->disp_dev) != UCLASS_VIDEO_BRIDGE
210 && device_get_uclass_id(priv->disp_dev) != UCLASS_DISPLAY)) { 250 && device_get_uclass_id(priv->disp_dev) != UCLASS_DISPLAY)) {
211 251
212 printf("fail to find output device\n"); 252 printf("fail to find output device\n");
213 return -ENODEV; 253 return -ENODEV;
214 } 254 }
215 255
216 debug("disp_dev %s\n", priv->disp_dev->name); 256 debug("disp_dev %s\n", priv->disp_dev->name);
217 257
218 ret = video_link_get_display_timings(timings); 258 ret = video_link_get_display_timings(timings);
219 if (ret) { 259 if (ret) {
220 printf("fail to get display timings\n"); 260 printf("fail to get display timings\n");
221 return ret; 261 return ret;
222 } 262 }
223 263
224 return ret; 264 return ret;
225 } 265 }
226 266
267 static int lcdifv3_check_thres_value(u32 mul, u32 div)
268 {
269 if (!div)
270 return -EINVAL;
271
272 if (mul > div)
273 return -EINVAL;
274
275 return 0;
276 }
277
278 static void lcdifv3_of_parse_thres(struct udevice *dev)
279 {
280 int ret;
281 u32 thres_low[2], thres_high[2];
282 struct lcdifv3_priv *priv = dev_get_priv(dev);
283
284
285 /* default 'thres-low' value: FIFO * 1/3;
286 * default 'thres-high' value: FIFO * 2/3.
287 */
288 priv->thres_low_mul = 1;
289 priv->thres_low_div = 3;
290 priv->thres_high_mul = 2;
291 priv->thres_high_div = 3;
292
293 ret = dev_read_u32_array(dev, "thres-low", thres_low, 2);
294 if (!ret) {
295 /* check the value effectiveness */
296 ret = lcdifv3_check_thres_value(thres_low[0], thres_low[1]);
297 if (!ret) {
298 priv->thres_low_mul = thres_low[0];
299 priv->thres_low_div = thres_low[1];
300 }
301 }
302
303 ret = dev_read_u32_array(dev, "thres-high", thres_high, 2);
304 if (!ret) {
305 /* check the value effectiveness */
306 ret = lcdifv3_check_thres_value(thres_high[0], thres_high[1]);
307 if (!ret) {
308 priv->thres_high_mul = thres_high[0];
309 priv->thres_high_div = thres_high[1];
310 }
311 }
312 }
313
314
227 static int lcdifv3_video_probe(struct udevice *dev) 315 static int lcdifv3_video_probe(struct udevice *dev)
228 { 316 {
229 struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); 317 struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
230 struct video_priv *uc_priv = dev_get_uclass_priv(dev); 318 struct video_priv *uc_priv = dev_get_uclass_priv(dev);
231 struct lcdifv3_priv *priv = dev_get_priv(dev); 319 struct lcdifv3_priv *priv = dev_get_priv(dev);
232 320
233 struct ctfb_res_modes mode; 321 struct ctfb_res_modes mode;
234 struct display_timing timings; 322 struct display_timing timings;
235 323
236 u32 fb_start, fb_end; 324 u32 fb_start, fb_end;
237 int ret; 325 int ret;
238 326
239 debug("%s() plat: base 0x%lx, size 0x%x\n", 327 debug("%s() plat: base 0x%lx, size 0x%x\n",
240 __func__, plat->base, plat->size); 328 __func__, plat->base, plat->size);
241 329
242 priv->reg_base = dev_read_addr(dev); 330 priv->reg_base = dev_read_addr(dev);
243 if (priv->reg_base == FDT_ADDR_T_NONE) { 331 if (priv->reg_base == FDT_ADDR_T_NONE) {
244 dev_err(dev, "lcdif base address is not found\n"); 332 dev_err(dev, "lcdif base address is not found\n");
245 return -EINVAL; 333 return -EINVAL;
246 } 334 }
247 335
248 ret = lcdifv3_of_get_timings(dev, &timings); 336 ret = lcdifv3_of_get_timings(dev, &timings);
249 if (ret) 337 if (ret)
250 return ret; 338 return ret;
339
340 lcdifv3_of_parse_thres(dev);
251 341
252 if (priv->disp_dev) { 342 if (priv->disp_dev) {
253 #if IS_ENABLED(CONFIG_VIDEO_BRIDGE) 343 #if IS_ENABLED(CONFIG_VIDEO_BRIDGE)
254 if (device_get_uclass_id(priv->disp_dev) == UCLASS_VIDEO_BRIDGE) { 344 if (device_get_uclass_id(priv->disp_dev) == UCLASS_VIDEO_BRIDGE) {
255 ret = video_bridge_attach(priv->disp_dev); 345 ret = video_bridge_attach(priv->disp_dev);
256 if (ret) { 346 if (ret) {
257 dev_err(dev, "fail to attach bridge\n"); 347 dev_err(dev, "fail to attach bridge\n");
258 return ret; 348 return ret;
259 } 349 }
260 350
261 ret = video_bridge_set_backlight(priv->disp_dev, 80); 351 ret = video_bridge_set_backlight(priv->disp_dev, 80);
262 if (ret) { 352 if (ret) {
263 dev_err(dev, "fail to set backlight\n"); 353 dev_err(dev, "fail to set backlight\n");
264 return ret; 354 return ret;
265 } 355 }
266 } 356 }
267 #endif 357 #endif
268 } 358 }
269 359
270 mode.xres = timings.hactive.typ; 360 mode.xres = timings.hactive.typ;
271 mode.yres = timings.vactive.typ; 361 mode.yres = timings.vactive.typ;
272 mode.left_margin = timings.hback_porch.typ; 362 mode.left_margin = timings.hback_porch.typ;
273 mode.right_margin = timings.hfront_porch.typ; 363 mode.right_margin = timings.hfront_porch.typ;
274 mode.upper_margin = timings.vback_porch.typ; 364 mode.upper_margin = timings.vback_porch.typ;
275 mode.lower_margin = timings.vfront_porch.typ; 365 mode.lower_margin = timings.vfront_porch.typ;
276 mode.hsync_len = timings.hsync_len.typ; 366 mode.hsync_len = timings.hsync_len.typ;
277 mode.vsync_len = timings.vsync_len.typ; 367 mode.vsync_len = timings.vsync_len.typ;
278 mode.pixclock = HZ2PS(timings.pixelclock.typ); 368 mode.pixclock = HZ2PS(timings.pixelclock.typ);
279 369
280 lcdifv3_init(dev, &mode, GDF_32BIT_X888RGB); 370 lcdifv3_init(dev, &mode, GDF_32BIT_X888RGB);
281 371
282 uc_priv->bpix = VIDEO_BPP32; /* only support 32 BPP now */ 372 uc_priv->bpix = VIDEO_BPP32; /* only support 32 BPP now */
283 uc_priv->xsize = mode.xres; 373 uc_priv->xsize = mode.xres;
284 uc_priv->ysize = mode.yres; 374 uc_priv->ysize = mode.yres;
285 375
286 /* Enable dcache for the frame buffer */ 376 /* Enable dcache for the frame buffer */
287 fb_start = plat->base & ~(MMU_SECTION_SIZE - 1); 377 fb_start = plat->base & ~(MMU_SECTION_SIZE - 1);
288 fb_end = plat->base + plat->size; 378 fb_end = plat->base + plat->size;
289 fb_end = ALIGN(fb_end, 1 << MMU_SECTION_SHIFT); 379 fb_end = ALIGN(fb_end, 1 << MMU_SECTION_SHIFT);
290 mmu_set_region_dcache_behaviour(fb_start, fb_end - fb_start, 380 mmu_set_region_dcache_behaviour(fb_start, fb_end - fb_start,
291 DCACHE_WRITEBACK); 381 DCACHE_WRITEBACK);
292 video_set_flush_dcache(dev, true); 382 video_set_flush_dcache(dev, true);
293 gd->fb_base = plat->base; 383 gd->fb_base = plat->base;
294 384
295 return ret; 385 return ret;
296 } 386 }
297 387
298 static int lcdifv3_video_bind(struct udevice *dev) 388 static int lcdifv3_video_bind(struct udevice *dev)
299 { 389 {
300 struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); 390 struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
301 391
302 /* Max size supported by LCDIF, because in bind, we can't probe panel */ 392 /* Max size supported by LCDIF, because in bind, we can't probe panel */
303 plat->size = 1920 * 1080 *4 * 2; 393 plat->size = 1920 * 1080 *4 * 2;
304 394
305 return 0; 395 return 0;
306 } 396 }
307 397
308 static int lcdifv3_video_remove(struct udevice *dev) 398 static int lcdifv3_video_remove(struct udevice *dev)
309 { 399 {
310 struct lcdifv3_priv *priv = dev_get_priv(dev); 400 struct lcdifv3_priv *priv = dev_get_priv(dev);
311 401
312 debug("%s\n", __func__); 402 debug("%s\n", __func__);
313 403
314 if (priv->disp_dev) 404 if (priv->disp_dev)
315 device_remove(priv->disp_dev, DM_REMOVE_NORMAL); 405 device_remove(priv->disp_dev, DM_REMOVE_NORMAL);
316 406
317 lcdifv3_power_down(priv); 407 lcdifv3_power_down(priv);
318 408
319 return 0; 409 return 0;
320 } 410 }
321 411
322 static const struct udevice_id lcdifv3_video_ids[] = { 412 static const struct udevice_id lcdifv3_video_ids[] = {
323 { .compatible = "fsl,imx8mp-lcdif1" }, 413 { .compatible = "fsl,imx8mp-lcdif1" },
324 { /* sentinel */ } 414 { /* sentinel */ }
325 }; 415 };
326 416
327 U_BOOT_DRIVER(lcdifv3_video) = { 417 U_BOOT_DRIVER(lcdifv3_video) = {
328 .name = "lcdifv3_video", 418 .name = "lcdifv3_video",
329 .id = UCLASS_VIDEO, 419 .id = UCLASS_VIDEO,
330 .of_match = lcdifv3_video_ids, 420 .of_match = lcdifv3_video_ids,
331 .bind = lcdifv3_video_bind, 421 .bind = lcdifv3_video_bind,
332 .probe = lcdifv3_video_probe, 422 .probe = lcdifv3_video_probe,
333 .remove = lcdifv3_video_remove, 423 .remove = lcdifv3_video_remove,
334 .flags = DM_FLAG_PRE_RELOC | DM_FLAG_OS_PREPARE, 424 .flags = DM_FLAG_PRE_RELOC | DM_FLAG_OS_PREPARE,
335 .priv_auto_alloc_size = sizeof(struct lcdifv3_priv), 425 .priv_auto_alloc_size = sizeof(struct lcdifv3_priv),
336 }; 426 };
337 427