root/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _dpu_vbif_wait_for_xin_halt
  2. _dpu_vbif_apply_dynamic_ot_limit
  3. _dpu_vbif_get_ot_limit
  4. dpu_vbif_set_ot_limit
  5. dpu_vbif_set_qos_remap
  6. dpu_vbif_clear_errors
  7. dpu_vbif_init_memtypes
  8. dpu_debugfs_vbif_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
   3  */
   4 
   5 #define pr_fmt(fmt)     "[drm:%s:%d] " fmt, __func__, __LINE__
   6 
   7 #include <linux/debugfs.h>
   8 #include <linux/delay.h>
   9 
  10 #include "dpu_vbif.h"
  11 #include "dpu_hw_vbif.h"
  12 #include "dpu_trace.h"
  13 
  14 /**
  15  * _dpu_vbif_wait_for_xin_halt - wait for the xin to halt
  16  * @vbif:       Pointer to hardware vbif driver
  17  * @xin_id:     Client interface identifier
  18  * @return:     0 if success; error code otherwise
  19  */
  20 static int _dpu_vbif_wait_for_xin_halt(struct dpu_hw_vbif *vbif, u32 xin_id)
  21 {
  22         ktime_t timeout;
  23         bool status;
  24         int rc;
  25 
  26         if (!vbif || !vbif->cap || !vbif->ops.get_halt_ctrl) {
  27                 DPU_ERROR("invalid arguments vbif %d\n", vbif != 0);
  28                 return -EINVAL;
  29         }
  30 
  31         timeout = ktime_add_us(ktime_get(), vbif->cap->xin_halt_timeout);
  32         for (;;) {
  33                 status = vbif->ops.get_halt_ctrl(vbif, xin_id);
  34                 if (status)
  35                         break;
  36                 if (ktime_compare_safe(ktime_get(), timeout) > 0) {
  37                         status = vbif->ops.get_halt_ctrl(vbif, xin_id);
  38                         break;
  39                 }
  40                 usleep_range(501, 1000);
  41         }
  42 
  43         if (!status) {
  44                 rc = -ETIMEDOUT;
  45                 DPU_ERROR("VBIF %d client %d not halting. TIMEDOUT.\n",
  46                                 vbif->idx - VBIF_0, xin_id);
  47         } else {
  48                 rc = 0;
  49                 DPU_DEBUG("VBIF %d client %d is halted\n",
  50                                 vbif->idx - VBIF_0, xin_id);
  51         }
  52 
  53         return rc;
  54 }
  55 
  56 /**
  57  * _dpu_vbif_apply_dynamic_ot_limit - determine OT based on usecase parameters
  58  * @vbif:       Pointer to hardware vbif driver
  59  * @ot_lim:     Pointer to OT limit to be modified
  60  * @params:     Pointer to usecase parameters
  61  */
  62 static void _dpu_vbif_apply_dynamic_ot_limit(struct dpu_hw_vbif *vbif,
  63                 u32 *ot_lim, struct dpu_vbif_set_ot_params *params)
  64 {
  65         u64 pps;
  66         const struct dpu_vbif_dynamic_ot_tbl *tbl;
  67         u32 i;
  68 
  69         if (!vbif || !(vbif->cap->features & BIT(DPU_VBIF_QOS_OTLIM)))
  70                 return;
  71 
  72         /* Dynamic OT setting done only for WFD */
  73         if (!params->is_wfd)
  74                 return;
  75 
  76         pps = params->frame_rate;
  77         pps *= params->width;
  78         pps *= params->height;
  79 
  80         tbl = params->rd ? &vbif->cap->dynamic_ot_rd_tbl :
  81                         &vbif->cap->dynamic_ot_wr_tbl;
  82 
  83         for (i = 0; i < tbl->count; i++) {
  84                 if (pps <= tbl->cfg[i].pps) {
  85                         *ot_lim = tbl->cfg[i].ot_limit;
  86                         break;
  87                 }
  88         }
  89 
  90         DPU_DEBUG("vbif:%d xin:%d w:%d h:%d fps:%d pps:%llu ot:%u\n",
  91                         vbif->idx - VBIF_0, params->xin_id,
  92                         params->width, params->height, params->frame_rate,
  93                         pps, *ot_lim);
  94 }
  95 
  96 /**
  97  * _dpu_vbif_get_ot_limit - get OT based on usecase & configuration parameters
  98  * @vbif:       Pointer to hardware vbif driver
  99  * @params:     Pointer to usecase parameters
 100  * @return:     OT limit
 101  */
 102 static u32 _dpu_vbif_get_ot_limit(struct dpu_hw_vbif *vbif,
 103         struct dpu_vbif_set_ot_params *params)
 104 {
 105         u32 ot_lim = 0;
 106         u32 val;
 107 
 108         if (!vbif || !vbif->cap) {
 109                 DPU_ERROR("invalid arguments vbif %d\n", vbif != 0);
 110                 return -EINVAL;
 111         }
 112 
 113         if (vbif->cap->default_ot_wr_limit && !params->rd)
 114                 ot_lim = vbif->cap->default_ot_wr_limit;
 115         else if (vbif->cap->default_ot_rd_limit && params->rd)
 116                 ot_lim = vbif->cap->default_ot_rd_limit;
 117 
 118         /*
 119          * If default ot is not set from dt/catalog,
 120          * then do not configure it.
 121          */
 122         if (ot_lim == 0)
 123                 goto exit;
 124 
 125         /* Modify the limits if the target and the use case requires it */
 126         _dpu_vbif_apply_dynamic_ot_limit(vbif, &ot_lim, params);
 127 
 128         if (vbif && vbif->ops.get_limit_conf) {
 129                 val = vbif->ops.get_limit_conf(vbif,
 130                                 params->xin_id, params->rd);
 131                 if (val == ot_lim)
 132                         ot_lim = 0;
 133         }
 134 
 135 exit:
 136         DPU_DEBUG("vbif:%d xin:%d ot_lim:%d\n",
 137                         vbif->idx - VBIF_0, params->xin_id, ot_lim);
 138         return ot_lim;
 139 }
 140 
 141 /**
 142  * dpu_vbif_set_ot_limit - set OT based on usecase & configuration parameters
 143  * @vbif:       Pointer to hardware vbif driver
 144  * @params:     Pointer to usecase parameters
 145  *
 146  * Note this function would block waiting for bus halt.
 147  */
 148 void dpu_vbif_set_ot_limit(struct dpu_kms *dpu_kms,
 149                 struct dpu_vbif_set_ot_params *params)
 150 {
 151         struct dpu_hw_vbif *vbif = NULL;
 152         struct dpu_hw_mdp *mdp;
 153         bool forced_on = false;
 154         u32 ot_lim;
 155         int ret, i;
 156 
 157         if (!dpu_kms) {
 158                 DPU_ERROR("invalid arguments\n");
 159                 return;
 160         }
 161         mdp = dpu_kms->hw_mdp;
 162 
 163         for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) {
 164                 if (dpu_kms->hw_vbif[i] &&
 165                                 dpu_kms->hw_vbif[i]->idx == params->vbif_idx)
 166                         vbif = dpu_kms->hw_vbif[i];
 167         }
 168 
 169         if (!vbif || !mdp) {
 170                 DPU_DEBUG("invalid arguments vbif %d mdp %d\n",
 171                                 vbif != 0, mdp != 0);
 172                 return;
 173         }
 174 
 175         if (!mdp->ops.setup_clk_force_ctrl ||
 176                         !vbif->ops.set_limit_conf ||
 177                         !vbif->ops.set_halt_ctrl)
 178                 return;
 179 
 180         /* set write_gather_en for all write clients */
 181         if (vbif->ops.set_write_gather_en && !params->rd)
 182                 vbif->ops.set_write_gather_en(vbif, params->xin_id);
 183 
 184         ot_lim = _dpu_vbif_get_ot_limit(vbif, params) & 0xFF;
 185 
 186         if (ot_lim == 0)
 187                 return;
 188 
 189         trace_dpu_perf_set_ot(params->num, params->xin_id, ot_lim,
 190                 params->vbif_idx);
 191 
 192         forced_on = mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, true);
 193 
 194         vbif->ops.set_limit_conf(vbif, params->xin_id, params->rd, ot_lim);
 195 
 196         vbif->ops.set_halt_ctrl(vbif, params->xin_id, true);
 197 
 198         ret = _dpu_vbif_wait_for_xin_halt(vbif, params->xin_id);
 199         if (ret)
 200                 trace_dpu_vbif_wait_xin_halt_fail(vbif->idx, params->xin_id);
 201 
 202         vbif->ops.set_halt_ctrl(vbif, params->xin_id, false);
 203 
 204         if (forced_on)
 205                 mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, false);
 206 }
 207 
 208 void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms,
 209                 struct dpu_vbif_set_qos_params *params)
 210 {
 211         struct dpu_hw_vbif *vbif = NULL;
 212         struct dpu_hw_mdp *mdp;
 213         bool forced_on = false;
 214         const struct dpu_vbif_qos_tbl *qos_tbl;
 215         int i;
 216 
 217         if (!dpu_kms || !params || !dpu_kms->hw_mdp) {
 218                 DPU_ERROR("invalid arguments\n");
 219                 return;
 220         }
 221         mdp = dpu_kms->hw_mdp;
 222 
 223         for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) {
 224                 if (dpu_kms->hw_vbif[i] &&
 225                                 dpu_kms->hw_vbif[i]->idx == params->vbif_idx) {
 226                         vbif = dpu_kms->hw_vbif[i];
 227                         break;
 228                 }
 229         }
 230 
 231         if (!vbif || !vbif->cap) {
 232                 DPU_ERROR("invalid vbif %d\n", params->vbif_idx);
 233                 return;
 234         }
 235 
 236         if (!vbif->ops.set_qos_remap || !mdp->ops.setup_clk_force_ctrl) {
 237                 DPU_DEBUG("qos remap not supported\n");
 238                 return;
 239         }
 240 
 241         qos_tbl = params->is_rt ? &vbif->cap->qos_rt_tbl :
 242                         &vbif->cap->qos_nrt_tbl;
 243 
 244         if (!qos_tbl->npriority_lvl || !qos_tbl->priority_lvl) {
 245                 DPU_DEBUG("qos tbl not defined\n");
 246                 return;
 247         }
 248 
 249         forced_on = mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, true);
 250 
 251         for (i = 0; i < qos_tbl->npriority_lvl; i++) {
 252                 DPU_DEBUG("vbif:%d xin:%d lvl:%d/%d\n",
 253                                 params->vbif_idx, params->xin_id, i,
 254                                 qos_tbl->priority_lvl[i]);
 255                 vbif->ops.set_qos_remap(vbif, params->xin_id, i,
 256                                 qos_tbl->priority_lvl[i]);
 257         }
 258 
 259         if (forced_on)
 260                 mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, false);
 261 }
 262 
 263 void dpu_vbif_clear_errors(struct dpu_kms *dpu_kms)
 264 {
 265         struct dpu_hw_vbif *vbif;
 266         u32 i, pnd, src;
 267 
 268         for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) {
 269                 vbif = dpu_kms->hw_vbif[i];
 270                 if (vbif && vbif->ops.clear_errors) {
 271                         vbif->ops.clear_errors(vbif, &pnd, &src);
 272                         if (pnd || src) {
 273                                 DRM_DEBUG_KMS("VBIF %d: pnd 0x%X, src 0x%X\n",
 274                                               vbif->idx - VBIF_0, pnd, src);
 275                         }
 276                 }
 277         }
 278 }
 279 
 280 void dpu_vbif_init_memtypes(struct dpu_kms *dpu_kms)
 281 {
 282         struct dpu_hw_vbif *vbif;
 283         int i, j;
 284 
 285         for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) {
 286                 vbif = dpu_kms->hw_vbif[i];
 287                 if (vbif && vbif->cap && vbif->ops.set_mem_type) {
 288                         for (j = 0; j < vbif->cap->memtype_count; j++)
 289                                 vbif->ops.set_mem_type(
 290                                                 vbif, j, vbif->cap->memtype[j]);
 291                 }
 292         }
 293 }
 294 
 295 #ifdef CONFIG_DEBUG_FS
 296 
 297 void dpu_debugfs_vbif_init(struct dpu_kms *dpu_kms, struct dentry *debugfs_root)
 298 {
 299         char vbif_name[32];
 300         struct dentry *entry, *debugfs_vbif;
 301         int i, j;
 302 
 303         entry = debugfs_create_dir("vbif", debugfs_root);
 304 
 305         for (i = 0; i < dpu_kms->catalog->vbif_count; i++) {
 306                 struct dpu_vbif_cfg *vbif = &dpu_kms->catalog->vbif[i];
 307 
 308                 snprintf(vbif_name, sizeof(vbif_name), "%d", vbif->id);
 309 
 310                 debugfs_vbif = debugfs_create_dir(vbif_name, entry);
 311 
 312                 debugfs_create_u32("features", 0600, debugfs_vbif,
 313                         (u32 *)&vbif->features);
 314 
 315                 debugfs_create_u32("xin_halt_timeout", 0400, debugfs_vbif,
 316                         (u32 *)&vbif->xin_halt_timeout);
 317 
 318                 debugfs_create_u32("default_rd_ot_limit", 0400, debugfs_vbif,
 319                         (u32 *)&vbif->default_ot_rd_limit);
 320 
 321                 debugfs_create_u32("default_wr_ot_limit", 0400, debugfs_vbif,
 322                         (u32 *)&vbif->default_ot_wr_limit);
 323 
 324                 for (j = 0; j < vbif->dynamic_ot_rd_tbl.count; j++) {
 325                         struct dpu_vbif_dynamic_ot_cfg *cfg =
 326                                         &vbif->dynamic_ot_rd_tbl.cfg[j];
 327 
 328                         snprintf(vbif_name, sizeof(vbif_name),
 329                                         "dynamic_ot_rd_%d_pps", j);
 330                         debugfs_create_u64(vbif_name, 0400, debugfs_vbif,
 331                                         (u64 *)&cfg->pps);
 332                         snprintf(vbif_name, sizeof(vbif_name),
 333                                         "dynamic_ot_rd_%d_ot_limit", j);
 334                         debugfs_create_u32(vbif_name, 0400, debugfs_vbif,
 335                                         (u32 *)&cfg->ot_limit);
 336                 }
 337 
 338                 for (j = 0; j < vbif->dynamic_ot_wr_tbl.count; j++) {
 339                         struct dpu_vbif_dynamic_ot_cfg *cfg =
 340                                         &vbif->dynamic_ot_wr_tbl.cfg[j];
 341 
 342                         snprintf(vbif_name, sizeof(vbif_name),
 343                                         "dynamic_ot_wr_%d_pps", j);
 344                         debugfs_create_u64(vbif_name, 0400, debugfs_vbif,
 345                                         (u64 *)&cfg->pps);
 346                         snprintf(vbif_name, sizeof(vbif_name),
 347                                         "dynamic_ot_wr_%d_ot_limit", j);
 348                         debugfs_create_u32(vbif_name, 0400, debugfs_vbif,
 349                                         (u32 *)&cfg->ot_limit);
 350                 }
 351         }
 352 }
 353 #endif

/* [<][>][^][v][top][bottom][index][help] */