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 Side-by-side Diff

drivers/video/nxp/imx/imx_lcdifv3.c
... ... @@ -30,6 +30,11 @@
30 30 struct lcdifv3_priv {
31 31 fdt_addr_t reg_base;
32 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 40 static int lcdifv3_set_pix_fmt(struct lcdifv3_priv *priv, unsigned int format)
... ... @@ -114,6 +119,38 @@
114 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 154 static void lcdifv3_enable_controller(struct lcdifv3_priv *priv)
118 155 {
119 156 u32 disp_para, ctrldescl0_5;
... ... @@ -162,6 +199,9 @@
162 199  
163 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 205 lcdifv3_set_mode(priv, mode);
166 206  
167 207 lcdifv3_set_bus_fmt(priv);
... ... @@ -224,6 +264,54 @@
224 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 315 static int lcdifv3_video_probe(struct udevice *dev)
228 316 {
229 317 struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
... ... @@ -248,6 +336,8 @@
248 336 ret = lcdifv3_of_get_timings(dev, &timings);
249 337 if (ret)
250 338 return ret;
  339 +
  340 + lcdifv3_of_parse_thres(dev);
251 341  
252 342 if (priv->disp_dev) {
253 343 #if IS_ENABLED(CONFIG_VIDEO_BRIDGE)