Commit ea648d52ac6c5329e35047f25b96ed9a4230474b
1 parent
c512b5679e
Exists in
emb_lf_v2022.04
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) (cherry picked from commit 613092e2fd58ac50f4416f73a37ed47de6275a51) (cherry picked from commit 8eb20299267fd95053e5b00394100ef5563eab7f) (cherry picked from commit ab0f1c62a02228cebd38d8a2360324f767784abe)
Showing 1 changed file with 90 additions and 0 deletions Side-by-side Diff
drivers/video/nxp/imx/imx_lcdifv3.c
... | ... | @@ -35,6 +35,11 @@ |
35 | 35 | struct lcdifv3_priv { |
36 | 36 | fdt_addr_t reg_base; |
37 | 37 | struct udevice *disp_dev; |
38 | + | |
39 | + u32 thres_low_mul; | |
40 | + u32 thres_low_div; | |
41 | + u32 thres_high_mul; | |
42 | + u32 thres_high_div; | |
38 | 43 | }; |
39 | 44 | |
40 | 45 | static int lcdifv3_set_pix_fmt(struct lcdifv3_priv *priv, unsigned int format) |
... | ... | @@ -119,6 +124,38 @@ |
119 | 124 | writel(disp_para, (ulong)(priv->reg_base + LCDIFV3_DISP_PARA)); |
120 | 125 | } |
121 | 126 | |
127 | +static void lcdifv3_enable_plane_panic(struct lcdifv3_priv *priv) | |
128 | +{ | |
129 | + u32 panic_thres, thres_low, thres_high; | |
130 | + | |
131 | + /* apb clock has been enabled */ | |
132 | + | |
133 | + /* As suggestion, the thres_low should be 1/3 FIFO, | |
134 | + * and thres_high should be 2/3 FIFO (The FIFO size | |
135 | + * is 8KB = 512 * 128bit). | |
136 | + * threshold = n * 128bit (n: 0 ~ 511) | |
137 | + */ | |
138 | + thres_low = DIV_ROUND_UP(511 * priv->thres_low_mul, | |
139 | + priv->thres_low_div); | |
140 | + thres_high = DIV_ROUND_UP(511 * priv->thres_high_mul, | |
141 | + priv->thres_high_div); | |
142 | + | |
143 | + panic_thres = PANIC0_THRES_PANIC_THRES_LOW(thres_low) | | |
144 | + PANIC0_THRES_PANIC_THRES_HIGH(thres_high); | |
145 | + | |
146 | + writel(panic_thres, priv->reg_base + LCDIFV3_PANIC0_THRES); | |
147 | + | |
148 | + /* Enable Panic: | |
149 | + * | |
150 | + * As designed, the panic won't trigger an irq, | |
151 | + * so it is unnecessary to handle this as an irq | |
152 | + * and NoC + QoS modules will handle panic | |
153 | + * automatically. | |
154 | + */ | |
155 | + writel(INT_ENABLE_D1_PLANE_PANIC_EN, | |
156 | + priv->reg_base + LCDIFV3_INT_ENABLE_D1); | |
157 | +} | |
158 | + | |
122 | 159 | static void lcdifv3_enable_controller(struct lcdifv3_priv *priv) |
123 | 160 | { |
124 | 161 | u32 disp_para, ctrldescl0_5; |
... | ... | @@ -167,6 +204,9 @@ |
167 | 204 | |
168 | 205 | writel(CTRL_SW_RESET, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR)); |
169 | 206 | |
207 | + /* enable plane FIFO panic */ | |
208 | + lcdifv3_enable_plane_panic(priv); | |
209 | + | |
170 | 210 | lcdifv3_set_mode(priv, mode); |
171 | 211 | |
172 | 212 | lcdifv3_set_bus_fmt(priv); |
... | ... | @@ -229,6 +269,54 @@ |
229 | 269 | return ret; |
230 | 270 | } |
231 | 271 | |
272 | +static int lcdifv3_check_thres_value(u32 mul, u32 div) | |
273 | +{ | |
274 | + if (!div) | |
275 | + return -EINVAL; | |
276 | + | |
277 | + if (mul > div) | |
278 | + return -EINVAL; | |
279 | + | |
280 | + return 0; | |
281 | +} | |
282 | + | |
283 | +static void lcdifv3_of_parse_thres(struct udevice *dev) | |
284 | +{ | |
285 | + int ret; | |
286 | + u32 thres_low[2], thres_high[2]; | |
287 | + struct lcdifv3_priv *priv = dev_get_priv(dev); | |
288 | + | |
289 | + | |
290 | + /* default 'thres-low' value: FIFO * 1/3; | |
291 | + * default 'thres-high' value: FIFO * 2/3. | |
292 | + */ | |
293 | + priv->thres_low_mul = 1; | |
294 | + priv->thres_low_div = 3; | |
295 | + priv->thres_high_mul = 2; | |
296 | + priv->thres_high_div = 3; | |
297 | + | |
298 | + ret = dev_read_u32_array(dev, "thres-low", thres_low, 2); | |
299 | + if (!ret) { | |
300 | + /* check the value effectiveness */ | |
301 | + ret = lcdifv3_check_thres_value(thres_low[0], thres_low[1]); | |
302 | + if (!ret) { | |
303 | + priv->thres_low_mul = thres_low[0]; | |
304 | + priv->thres_low_div = thres_low[1]; | |
305 | + } | |
306 | + } | |
307 | + | |
308 | + ret = dev_read_u32_array(dev, "thres-high", thres_high, 2); | |
309 | + if (!ret) { | |
310 | + /* check the value effectiveness */ | |
311 | + ret = lcdifv3_check_thres_value(thres_high[0], thres_high[1]); | |
312 | + if (!ret) { | |
313 | + priv->thres_high_mul = thres_high[0]; | |
314 | + priv->thres_high_div = thres_high[1]; | |
315 | + } | |
316 | + } | |
317 | +} | |
318 | + | |
319 | + | |
232 | 320 | static int lcdifv3_video_probe(struct udevice *dev) |
233 | 321 | { |
234 | 322 | struct video_uc_plat *plat = dev_get_uclass_plat(dev); |
... | ... | @@ -253,6 +341,8 @@ |
253 | 341 | ret = lcdifv3_of_get_timings(dev, &timings); |
254 | 342 | if (ret) |
255 | 343 | return ret; |
344 | + | |
345 | + lcdifv3_of_parse_thres(dev); | |
256 | 346 | |
257 | 347 | if (priv->disp_dev) { |
258 | 348 | #if IS_ENABLED(CONFIG_VIDEO_BRIDGE) |