Commit ea648d52ac6c5329e35047f25b96ed9a4230474b

Authored by Ye Li
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)