root/drivers/gpu/drm/i915/display/intel_bw.c

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

DEFINITIONS

This source file includes following definitions.
  1. icl_pcode_read_mem_global_info
  2. icl_pcode_read_qgv_point_info
  3. icl_get_qgv_points
  4. icl_calc_bw
  5. icl_sagv_max_dclk
  6. icl_get_bw_info
  7. icl_max_bw
  8. intel_bw_init_hw
  9. intel_max_data_rate
  10. intel_bw_crtc_num_active_planes
  11. intel_bw_crtc_data_rate
  12. intel_bw_crtc_update
  13. intel_bw_num_active_planes
  14. intel_bw_data_rate
  15. intel_atomic_get_bw_state
  16. intel_bw_atomic_check
  17. intel_bw_duplicate_state
  18. intel_bw_destroy_state
  19. intel_bw_init

   1 // SPDX-License-Identifier: MIT
   2 /*
   3  * Copyright © 2019 Intel Corporation
   4  */
   5 
   6 #include <drm/drm_atomic_state_helper.h>
   7 
   8 #include "intel_bw.h"
   9 #include "intel_display_types.h"
  10 #include "intel_sideband.h"
  11 
  12 /* Parameters for Qclk Geyserville (QGV) */
  13 struct intel_qgv_point {
  14         u16 dclk, t_rp, t_rdpre, t_rc, t_ras, t_rcd;
  15 };
  16 
  17 struct intel_qgv_info {
  18         struct intel_qgv_point points[3];
  19         u8 num_points;
  20         u8 num_channels;
  21         u8 t_bl;
  22         enum intel_dram_type dram_type;
  23 };
  24 
  25 static int icl_pcode_read_mem_global_info(struct drm_i915_private *dev_priv,
  26                                           struct intel_qgv_info *qi)
  27 {
  28         u32 val = 0;
  29         int ret;
  30 
  31         ret = sandybridge_pcode_read(dev_priv,
  32                                      ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
  33                                      ICL_PCODE_MEM_SS_READ_GLOBAL_INFO,
  34                                      &val, NULL);
  35         if (ret)
  36                 return ret;
  37 
  38         switch (val & 0xf) {
  39         case 0:
  40                 qi->dram_type = INTEL_DRAM_DDR4;
  41                 break;
  42         case 1:
  43                 qi->dram_type = INTEL_DRAM_DDR3;
  44                 break;
  45         case 2:
  46                 qi->dram_type = INTEL_DRAM_LPDDR3;
  47                 break;
  48         case 3:
  49                 qi->dram_type = INTEL_DRAM_LPDDR3;
  50                 break;
  51         default:
  52                 MISSING_CASE(val & 0xf);
  53                 break;
  54         }
  55 
  56         qi->num_channels = (val & 0xf0) >> 4;
  57         qi->num_points = (val & 0xf00) >> 8;
  58 
  59         qi->t_bl = qi->dram_type == INTEL_DRAM_DDR4 ? 4 : 8;
  60 
  61         return 0;
  62 }
  63 
  64 static int icl_pcode_read_qgv_point_info(struct drm_i915_private *dev_priv,
  65                                          struct intel_qgv_point *sp,
  66                                          int point)
  67 {
  68         u32 val = 0, val2 = 0;
  69         int ret;
  70 
  71         ret = sandybridge_pcode_read(dev_priv,
  72                                      ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
  73                                      ICL_PCODE_MEM_SS_READ_QGV_POINT_INFO(point),
  74                                      &val, &val2);
  75         if (ret)
  76                 return ret;
  77 
  78         sp->dclk = val & 0xffff;
  79         sp->t_rp = (val & 0xff0000) >> 16;
  80         sp->t_rcd = (val & 0xff000000) >> 24;
  81 
  82         sp->t_rdpre = val2 & 0xff;
  83         sp->t_ras = (val2 & 0xff00) >> 8;
  84 
  85         sp->t_rc = sp->t_rp + sp->t_ras;
  86 
  87         return 0;
  88 }
  89 
  90 static int icl_get_qgv_points(struct drm_i915_private *dev_priv,
  91                               struct intel_qgv_info *qi)
  92 {
  93         int i, ret;
  94 
  95         ret = icl_pcode_read_mem_global_info(dev_priv, qi);
  96         if (ret)
  97                 return ret;
  98 
  99         if (WARN_ON(qi->num_points > ARRAY_SIZE(qi->points)))
 100                 qi->num_points = ARRAY_SIZE(qi->points);
 101 
 102         for (i = 0; i < qi->num_points; i++) {
 103                 struct intel_qgv_point *sp = &qi->points[i];
 104 
 105                 ret = icl_pcode_read_qgv_point_info(dev_priv, sp, i);
 106                 if (ret)
 107                         return ret;
 108 
 109                 DRM_DEBUG_KMS("QGV %d: DCLK=%d tRP=%d tRDPRE=%d tRAS=%d tRCD=%d tRC=%d\n",
 110                               i, sp->dclk, sp->t_rp, sp->t_rdpre, sp->t_ras,
 111                               sp->t_rcd, sp->t_rc);
 112         }
 113 
 114         return 0;
 115 }
 116 
 117 static int icl_calc_bw(int dclk, int num, int den)
 118 {
 119         /* multiples of 16.666MHz (100/6) */
 120         return DIV_ROUND_CLOSEST(num * dclk * 100, den * 6);
 121 }
 122 
 123 static int icl_sagv_max_dclk(const struct intel_qgv_info *qi)
 124 {
 125         u16 dclk = 0;
 126         int i;
 127 
 128         for (i = 0; i < qi->num_points; i++)
 129                 dclk = max(dclk, qi->points[i].dclk);
 130 
 131         return dclk;
 132 }
 133 
 134 struct intel_sa_info {
 135         u8 deburst, mpagesize, deprogbwlimit, displayrtids;
 136 };
 137 
 138 static const struct intel_sa_info icl_sa_info = {
 139         .deburst = 8,
 140         .mpagesize = 16,
 141         .deprogbwlimit = 25, /* GB/s */
 142         .displayrtids = 128,
 143 };
 144 
 145 static int icl_get_bw_info(struct drm_i915_private *dev_priv)
 146 {
 147         struct intel_qgv_info qi = {};
 148         const struct intel_sa_info *sa = &icl_sa_info;
 149         bool is_y_tile = true; /* assume y tile may be used */
 150         int num_channels;
 151         int deinterleave;
 152         int ipqdepth, ipqdepthpch;
 153         int dclk_max;
 154         int maxdebw;
 155         int i, ret;
 156 
 157         ret = icl_get_qgv_points(dev_priv, &qi);
 158         if (ret) {
 159                 DRM_DEBUG_KMS("Failed to get memory subsystem information, ignoring bandwidth limits");
 160                 return ret;
 161         }
 162         num_channels = qi.num_channels;
 163 
 164         deinterleave = DIV_ROUND_UP(num_channels, is_y_tile ? 4 : 2);
 165         dclk_max = icl_sagv_max_dclk(&qi);
 166 
 167         ipqdepthpch = 16;
 168 
 169         maxdebw = min(sa->deprogbwlimit * 1000,
 170                       icl_calc_bw(dclk_max, 16, 1) * 6 / 10); /* 60% */
 171         ipqdepth = min(ipqdepthpch, sa->displayrtids / num_channels);
 172 
 173         for (i = 0; i < ARRAY_SIZE(dev_priv->max_bw); i++) {
 174                 struct intel_bw_info *bi = &dev_priv->max_bw[i];
 175                 int clpchgroup;
 176                 int j;
 177 
 178                 clpchgroup = (sa->deburst * deinterleave / num_channels) << i;
 179                 bi->num_planes = (ipqdepth - clpchgroup) / clpchgroup + 1;
 180 
 181                 bi->num_qgv_points = qi.num_points;
 182 
 183                 for (j = 0; j < qi.num_points; j++) {
 184                         const struct intel_qgv_point *sp = &qi.points[j];
 185                         int ct, bw;
 186 
 187                         /*
 188                          * Max row cycle time
 189                          *
 190                          * FIXME what is the logic behind the
 191                          * assumed burst length?
 192                          */
 193                         ct = max_t(int, sp->t_rc, sp->t_rp + sp->t_rcd +
 194                                    (clpchgroup - 1) * qi.t_bl + sp->t_rdpre);
 195                         bw = icl_calc_bw(sp->dclk, clpchgroup * 32 * num_channels, ct);
 196 
 197                         bi->deratedbw[j] = min(maxdebw,
 198                                                bw * 9 / 10); /* 90% */
 199 
 200                         DRM_DEBUG_KMS("BW%d / QGV %d: num_planes=%d deratedbw=%u\n",
 201                                       i, j, bi->num_planes, bi->deratedbw[j]);
 202                 }
 203 
 204                 if (bi->num_planes == 1)
 205                         break;
 206         }
 207 
 208         return 0;
 209 }
 210 
 211 static unsigned int icl_max_bw(struct drm_i915_private *dev_priv,
 212                                int num_planes, int qgv_point)
 213 {
 214         int i;
 215 
 216         for (i = 0; i < ARRAY_SIZE(dev_priv->max_bw); i++) {
 217                 const struct intel_bw_info *bi =
 218                         &dev_priv->max_bw[i];
 219 
 220                 /*
 221                  * Pcode will not expose all QGV points when
 222                  * SAGV is forced to off/min/med/max.
 223                  */
 224                 if (qgv_point >= bi->num_qgv_points)
 225                         return UINT_MAX;
 226 
 227                 if (num_planes >= bi->num_planes)
 228                         return bi->deratedbw[qgv_point];
 229         }
 230 
 231         return 0;
 232 }
 233 
 234 void intel_bw_init_hw(struct drm_i915_private *dev_priv)
 235 {
 236         if (IS_GEN(dev_priv, 11))
 237                 icl_get_bw_info(dev_priv);
 238 }
 239 
 240 static unsigned int intel_max_data_rate(struct drm_i915_private *dev_priv,
 241                                         int num_planes)
 242 {
 243         if (IS_GEN(dev_priv, 11))
 244                 /*
 245                  * FIXME with SAGV disabled maybe we can assume
 246                  * point 1 will always be used? Seems to match
 247                  * the behaviour observed in the wild.
 248                  */
 249                 return min3(icl_max_bw(dev_priv, num_planes, 0),
 250                             icl_max_bw(dev_priv, num_planes, 1),
 251                             icl_max_bw(dev_priv, num_planes, 2));
 252         else
 253                 return UINT_MAX;
 254 }
 255 
 256 static unsigned int intel_bw_crtc_num_active_planes(const struct intel_crtc_state *crtc_state)
 257 {
 258         /*
 259          * We assume cursors are small enough
 260          * to not not cause bandwidth problems.
 261          */
 262         return hweight8(crtc_state->active_planes & ~BIT(PLANE_CURSOR));
 263 }
 264 
 265 static unsigned int intel_bw_crtc_data_rate(const struct intel_crtc_state *crtc_state)
 266 {
 267         struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 268         unsigned int data_rate = 0;
 269         enum plane_id plane_id;
 270 
 271         for_each_plane_id_on_crtc(crtc, plane_id) {
 272                 /*
 273                  * We assume cursors are small enough
 274                  * to not not cause bandwidth problems.
 275                  */
 276                 if (plane_id == PLANE_CURSOR)
 277                         continue;
 278 
 279                 data_rate += crtc_state->data_rate[plane_id];
 280         }
 281 
 282         return data_rate;
 283 }
 284 
 285 void intel_bw_crtc_update(struct intel_bw_state *bw_state,
 286                           const struct intel_crtc_state *crtc_state)
 287 {
 288         struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 289 
 290         bw_state->data_rate[crtc->pipe] =
 291                 intel_bw_crtc_data_rate(crtc_state);
 292         bw_state->num_active_planes[crtc->pipe] =
 293                 intel_bw_crtc_num_active_planes(crtc_state);
 294 
 295         DRM_DEBUG_KMS("pipe %c data rate %u num active planes %u\n",
 296                       pipe_name(crtc->pipe),
 297                       bw_state->data_rate[crtc->pipe],
 298                       bw_state->num_active_planes[crtc->pipe]);
 299 }
 300 
 301 static unsigned int intel_bw_num_active_planes(struct drm_i915_private *dev_priv,
 302                                                const struct intel_bw_state *bw_state)
 303 {
 304         unsigned int num_active_planes = 0;
 305         enum pipe pipe;
 306 
 307         for_each_pipe(dev_priv, pipe)
 308                 num_active_planes += bw_state->num_active_planes[pipe];
 309 
 310         return num_active_planes;
 311 }
 312 
 313 static unsigned int intel_bw_data_rate(struct drm_i915_private *dev_priv,
 314                                        const struct intel_bw_state *bw_state)
 315 {
 316         unsigned int data_rate = 0;
 317         enum pipe pipe;
 318 
 319         for_each_pipe(dev_priv, pipe)
 320                 data_rate += bw_state->data_rate[pipe];
 321 
 322         return data_rate;
 323 }
 324 
 325 static struct intel_bw_state *
 326 intel_atomic_get_bw_state(struct intel_atomic_state *state)
 327 {
 328         struct drm_i915_private *dev_priv = to_i915(state->base.dev);
 329         struct drm_private_state *bw_state;
 330 
 331         bw_state = drm_atomic_get_private_obj_state(&state->base,
 332                                                     &dev_priv->bw_obj);
 333         if (IS_ERR(bw_state))
 334                 return ERR_CAST(bw_state);
 335 
 336         return to_intel_bw_state(bw_state);
 337 }
 338 
 339 int intel_bw_atomic_check(struct intel_atomic_state *state)
 340 {
 341         struct drm_i915_private *dev_priv = to_i915(state->base.dev);
 342         struct intel_crtc_state *new_crtc_state, *old_crtc_state;
 343         struct intel_bw_state *bw_state = NULL;
 344         unsigned int data_rate, max_data_rate;
 345         unsigned int num_active_planes;
 346         struct intel_crtc *crtc;
 347         int i;
 348 
 349         /* FIXME earlier gens need some checks too */
 350         if (INTEL_GEN(dev_priv) < 11)
 351                 return 0;
 352 
 353         for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
 354                                             new_crtc_state, i) {
 355                 unsigned int old_data_rate =
 356                         intel_bw_crtc_data_rate(old_crtc_state);
 357                 unsigned int new_data_rate =
 358                         intel_bw_crtc_data_rate(new_crtc_state);
 359                 unsigned int old_active_planes =
 360                         intel_bw_crtc_num_active_planes(old_crtc_state);
 361                 unsigned int new_active_planes =
 362                         intel_bw_crtc_num_active_planes(new_crtc_state);
 363 
 364                 /*
 365                  * Avoid locking the bw state when
 366                  * nothing significant has changed.
 367                  */
 368                 if (old_data_rate == new_data_rate &&
 369                     old_active_planes == new_active_planes)
 370                         continue;
 371 
 372                 bw_state  = intel_atomic_get_bw_state(state);
 373                 if (IS_ERR(bw_state))
 374                         return PTR_ERR(bw_state);
 375 
 376                 bw_state->data_rate[crtc->pipe] = new_data_rate;
 377                 bw_state->num_active_planes[crtc->pipe] = new_active_planes;
 378 
 379                 DRM_DEBUG_KMS("pipe %c data rate %u num active planes %u\n",
 380                               pipe_name(crtc->pipe),
 381                               bw_state->data_rate[crtc->pipe],
 382                               bw_state->num_active_planes[crtc->pipe]);
 383         }
 384 
 385         if (!bw_state)
 386                 return 0;
 387 
 388         data_rate = intel_bw_data_rate(dev_priv, bw_state);
 389         num_active_planes = intel_bw_num_active_planes(dev_priv, bw_state);
 390 
 391         max_data_rate = intel_max_data_rate(dev_priv, num_active_planes);
 392 
 393         data_rate = DIV_ROUND_UP(data_rate, 1000);
 394 
 395         if (data_rate > max_data_rate) {
 396                 DRM_DEBUG_KMS("Bandwidth %u MB/s exceeds max available %d MB/s (%d active planes)\n",
 397                               data_rate, max_data_rate, num_active_planes);
 398                 return -EINVAL;
 399         }
 400 
 401         return 0;
 402 }
 403 
 404 static struct drm_private_state *intel_bw_duplicate_state(struct drm_private_obj *obj)
 405 {
 406         struct intel_bw_state *state;
 407 
 408         state = kmemdup(obj->state, sizeof(*state), GFP_KERNEL);
 409         if (!state)
 410                 return NULL;
 411 
 412         __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base);
 413 
 414         return &state->base;
 415 }
 416 
 417 static void intel_bw_destroy_state(struct drm_private_obj *obj,
 418                                    struct drm_private_state *state)
 419 {
 420         kfree(state);
 421 }
 422 
 423 static const struct drm_private_state_funcs intel_bw_funcs = {
 424         .atomic_duplicate_state = intel_bw_duplicate_state,
 425         .atomic_destroy_state = intel_bw_destroy_state,
 426 };
 427 
 428 int intel_bw_init(struct drm_i915_private *dev_priv)
 429 {
 430         struct intel_bw_state *state;
 431 
 432         state = kzalloc(sizeof(*state), GFP_KERNEL);
 433         if (!state)
 434                 return -ENOMEM;
 435 
 436         drm_atomic_private_obj_init(&dev_priv->drm, &dev_priv->bw_obj,
 437                                     &state->base, &intel_bw_funcs);
 438 
 439         return 0;
 440 }

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