root/drivers/gpu/drm/amd/display/dc/dc_helper.c

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

DEFINITIONS

This source file includes following definitions.
  1. set_reg_field_value_masks
  2. set_reg_field_values
  3. generic_reg_update_ex
  4. generic_reg_set_ex
  5. dm_read_reg_func
  6. generic_reg_get
  7. generic_reg_get2
  8. generic_reg_get3
  9. generic_reg_get4
  10. generic_reg_get5
  11. generic_reg_get6
  12. generic_reg_get7
  13. generic_reg_get8
  14. generic_reg_wait
  15. generic_write_indirect_reg
  16. generic_read_indirect_reg
  17. generic_indirect_reg_update_ex

   1 /*
   2  * Copyright 2017 Advanced Micro Devices, Inc.
   3  *
   4  * Permission is hereby granted, free of charge, to any person obtaining a
   5  * copy of this software and associated documentation files (the "Software"),
   6  * to deal in the Software without restriction, including without limitation
   7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8  * and/or sell copies of the Software, and to permit persons to whom the
   9  * Software is furnished to do so, subject to the following conditions:
  10  *
  11  * The above copyright notice and this permission notice shall be included in
  12  * all copies or substantial portions of the Software.
  13  *
  14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20  * OTHER DEALINGS IN THE SOFTWARE.
  21  *
  22  */
  23 /*
  24  * dc_helper.c
  25  *
  26  *  Created on: Aug 30, 2016
  27  *      Author: agrodzov
  28  */
  29 
  30 #include <linux/delay.h>
  31 
  32 #include "dm_services.h"
  33 #include <stdarg.h>
  34 
  35 struct dc_reg_value_masks {
  36         uint32_t value;
  37         uint32_t mask;
  38 };
  39 
  40 struct dc_reg_sequence {
  41         uint32_t addr;
  42         struct dc_reg_value_masks value_masks;
  43 };
  44 
  45 static inline void set_reg_field_value_masks(
  46         struct dc_reg_value_masks *field_value_mask,
  47         uint32_t value,
  48         uint32_t mask,
  49         uint8_t shift)
  50 {
  51         ASSERT(mask != 0);
  52 
  53         field_value_mask->value = (field_value_mask->value & ~mask) | (mask & (value << shift));
  54         field_value_mask->mask = field_value_mask->mask | mask;
  55 }
  56 
  57 static void set_reg_field_values(struct dc_reg_value_masks *field_value_mask,
  58                 uint32_t addr, int n,
  59                 uint8_t shift1, uint32_t mask1, uint32_t field_value1,
  60                 va_list ap)
  61 {
  62         uint32_t shift, mask, field_value;
  63         int i = 1;
  64 
  65         /* gather all bits value/mask getting updated in this register */
  66         set_reg_field_value_masks(field_value_mask,
  67                         field_value1, mask1, shift1);
  68 
  69         while (i < n) {
  70                 shift = va_arg(ap, uint32_t);
  71                 mask = va_arg(ap, uint32_t);
  72                 field_value = va_arg(ap, uint32_t);
  73 
  74                 set_reg_field_value_masks(field_value_mask,
  75                                 field_value, mask, shift);
  76                 i++;
  77         }
  78 }
  79 
  80 uint32_t generic_reg_update_ex(const struct dc_context *ctx,
  81                 uint32_t addr, int n,
  82                 uint8_t shift1, uint32_t mask1, uint32_t field_value1,
  83                 ...)
  84 {
  85         struct dc_reg_value_masks field_value_mask = {0};
  86         uint32_t reg_val;
  87         va_list ap;
  88 
  89         va_start(ap, field_value1);
  90 
  91         set_reg_field_values(&field_value_mask, addr, n, shift1, mask1,
  92                         field_value1, ap);
  93 
  94         va_end(ap);
  95 
  96         /* mmio write directly */
  97         reg_val = dm_read_reg(ctx, addr);
  98         reg_val = (reg_val & ~field_value_mask.mask) | field_value_mask.value;
  99         dm_write_reg(ctx, addr, reg_val);
 100         return reg_val;
 101 }
 102 
 103 uint32_t generic_reg_set_ex(const struct dc_context *ctx,
 104                 uint32_t addr, uint32_t reg_val, int n,
 105                 uint8_t shift1, uint32_t mask1, uint32_t field_value1,
 106                 ...)
 107 {
 108         struct dc_reg_value_masks field_value_mask = {0};
 109         va_list ap;
 110 
 111         va_start(ap, field_value1);
 112 
 113         set_reg_field_values(&field_value_mask, addr, n, shift1, mask1,
 114                         field_value1, ap);
 115 
 116         va_end(ap);
 117 
 118 
 119         /* mmio write directly */
 120         reg_val = (reg_val & ~field_value_mask.mask) | field_value_mask.value;
 121         dm_write_reg(ctx, addr, reg_val);
 122         return reg_val;
 123 }
 124 
 125 uint32_t dm_read_reg_func(
 126         const struct dc_context *ctx,
 127         uint32_t address,
 128         const char *func_name)
 129 {
 130         uint32_t value;
 131 #ifdef DM_CHECK_ADDR_0
 132         if (address == 0) {
 133                 DC_ERR("invalid register read; address = 0\n");
 134                 return 0;
 135         }
 136 #endif
 137         value = cgs_read_register(ctx->cgs_device, address);
 138         trace_amdgpu_dc_rreg(&ctx->perf_trace->read_count, address, value);
 139 
 140         return value;
 141 }
 142 
 143 uint32_t generic_reg_get(const struct dc_context *ctx, uint32_t addr,
 144                 uint8_t shift, uint32_t mask, uint32_t *field_value)
 145 {
 146         uint32_t reg_val = dm_read_reg(ctx, addr);
 147         *field_value = get_reg_field_value_ex(reg_val, mask, shift);
 148         return reg_val;
 149 }
 150 
 151 uint32_t generic_reg_get2(const struct dc_context *ctx, uint32_t addr,
 152                 uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
 153                 uint8_t shift2, uint32_t mask2, uint32_t *field_value2)
 154 {
 155         uint32_t reg_val = dm_read_reg(ctx, addr);
 156         *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
 157         *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
 158         return reg_val;
 159 }
 160 
 161 uint32_t generic_reg_get3(const struct dc_context *ctx, uint32_t addr,
 162                 uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
 163                 uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
 164                 uint8_t shift3, uint32_t mask3, uint32_t *field_value3)
 165 {
 166         uint32_t reg_val = dm_read_reg(ctx, addr);
 167         *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
 168         *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
 169         *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
 170         return reg_val;
 171 }
 172 
 173 uint32_t generic_reg_get4(const struct dc_context *ctx, uint32_t addr,
 174                 uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
 175                 uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
 176                 uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
 177                 uint8_t shift4, uint32_t mask4, uint32_t *field_value4)
 178 {
 179         uint32_t reg_val = dm_read_reg(ctx, addr);
 180         *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
 181         *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
 182         *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
 183         *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4);
 184         return reg_val;
 185 }
 186 
 187 uint32_t generic_reg_get5(const struct dc_context *ctx, uint32_t addr,
 188                 uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
 189                 uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
 190                 uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
 191                 uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
 192                 uint8_t shift5, uint32_t mask5, uint32_t *field_value5)
 193 {
 194         uint32_t reg_val = dm_read_reg(ctx, addr);
 195         *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
 196         *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
 197         *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
 198         *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4);
 199         *field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5);
 200         return reg_val;
 201 }
 202 
 203 uint32_t generic_reg_get6(const struct dc_context *ctx, uint32_t addr,
 204                 uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
 205                 uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
 206                 uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
 207                 uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
 208                 uint8_t shift5, uint32_t mask5, uint32_t *field_value5,
 209                 uint8_t shift6, uint32_t mask6, uint32_t *field_value6)
 210 {
 211         uint32_t reg_val = dm_read_reg(ctx, addr);
 212         *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
 213         *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
 214         *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
 215         *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4);
 216         *field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5);
 217         *field_value6 = get_reg_field_value_ex(reg_val, mask6, shift6);
 218         return reg_val;
 219 }
 220 
 221 uint32_t generic_reg_get7(const struct dc_context *ctx, uint32_t addr,
 222                 uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
 223                 uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
 224                 uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
 225                 uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
 226                 uint8_t shift5, uint32_t mask5, uint32_t *field_value5,
 227                 uint8_t shift6, uint32_t mask6, uint32_t *field_value6,
 228                 uint8_t shift7, uint32_t mask7, uint32_t *field_value7)
 229 {
 230         uint32_t reg_val = dm_read_reg(ctx, addr);
 231         *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
 232         *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
 233         *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
 234         *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4);
 235         *field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5);
 236         *field_value6 = get_reg_field_value_ex(reg_val, mask6, shift6);
 237         *field_value7 = get_reg_field_value_ex(reg_val, mask7, shift7);
 238         return reg_val;
 239 }
 240 
 241 uint32_t generic_reg_get8(const struct dc_context *ctx, uint32_t addr,
 242                 uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
 243                 uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
 244                 uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
 245                 uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
 246                 uint8_t shift5, uint32_t mask5, uint32_t *field_value5,
 247                 uint8_t shift6, uint32_t mask6, uint32_t *field_value6,
 248                 uint8_t shift7, uint32_t mask7, uint32_t *field_value7,
 249                 uint8_t shift8, uint32_t mask8, uint32_t *field_value8)
 250 {
 251         uint32_t reg_val = dm_read_reg(ctx, addr);
 252         *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
 253         *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
 254         *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
 255         *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4);
 256         *field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5);
 257         *field_value6 = get_reg_field_value_ex(reg_val, mask6, shift6);
 258         *field_value7 = get_reg_field_value_ex(reg_val, mask7, shift7);
 259         *field_value8 = get_reg_field_value_ex(reg_val, mask8, shift8);
 260         return reg_val;
 261 }
 262 /* note:  va version of this is pretty bad idea, since there is a output parameter pass by pointer
 263  * compiler won't be able to check for size match and is prone to stack corruption type of bugs
 264 
 265 uint32_t generic_reg_get(const struct dc_context *ctx,
 266                 uint32_t addr, int n, ...)
 267 {
 268         uint32_t shift, mask;
 269         uint32_t *field_value;
 270         uint32_t reg_val;
 271         int i = 0;
 272 
 273         reg_val = dm_read_reg(ctx, addr);
 274 
 275         va_list ap;
 276         va_start(ap, n);
 277 
 278         while (i < n) {
 279                 shift = va_arg(ap, uint32_t);
 280                 mask = va_arg(ap, uint32_t);
 281                 field_value = va_arg(ap, uint32_t *);
 282 
 283                 *field_value = get_reg_field_value_ex(reg_val, mask, shift);
 284                 i++;
 285         }
 286 
 287         va_end(ap);
 288 
 289         return reg_val;
 290 }
 291 */
 292 
 293 void generic_reg_wait(const struct dc_context *ctx,
 294         uint32_t addr, uint32_t shift, uint32_t mask, uint32_t condition_value,
 295         unsigned int delay_between_poll_us, unsigned int time_out_num_tries,
 296         const char *func_name, int line)
 297 {
 298         uint32_t field_value;
 299         uint32_t reg_val;
 300         int i;
 301 
 302         /* something is terribly wrong if time out is > 200ms. (5Hz) */
 303         ASSERT(delay_between_poll_us * time_out_num_tries <= 3000000);
 304 
 305         for (i = 0; i <= time_out_num_tries; i++) {
 306                 if (i) {
 307                         if (delay_between_poll_us >= 1000)
 308                                 msleep(delay_between_poll_us/1000);
 309                         else if (delay_between_poll_us > 0)
 310                                 udelay(delay_between_poll_us);
 311                 }
 312 
 313                 reg_val = dm_read_reg(ctx, addr);
 314 
 315                 field_value = get_reg_field_value_ex(reg_val, mask, shift);
 316 
 317                 if (field_value == condition_value) {
 318                         if (i * delay_between_poll_us > 1000 &&
 319                                         !IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
 320                                 DC_LOG_DC("REG_WAIT taking a while: %dms in %s line:%d\n",
 321                                                 delay_between_poll_us * i / 1000,
 322                                                 func_name, line);
 323                         return;
 324                 }
 325         }
 326 
 327         DC_LOG_WARNING("REG_WAIT timeout %dus * %d tries - %s line:%d\n",
 328                         delay_between_poll_us, time_out_num_tries,
 329                         func_name, line);
 330 
 331         if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
 332                 BREAK_TO_DEBUGGER();
 333 }
 334 
 335 void generic_write_indirect_reg(const struct dc_context *ctx,
 336                 uint32_t addr_index, uint32_t addr_data,
 337                 uint32_t index, uint32_t data)
 338 {
 339         dm_write_reg(ctx, addr_index, index);
 340         dm_write_reg(ctx, addr_data, data);
 341 }
 342 
 343 uint32_t generic_read_indirect_reg(const struct dc_context *ctx,
 344                 uint32_t addr_index, uint32_t addr_data,
 345                 uint32_t index)
 346 {
 347         uint32_t value = 0;
 348 
 349         dm_write_reg(ctx, addr_index, index);
 350         value = dm_read_reg(ctx, addr_data);
 351 
 352         return value;
 353 }
 354 
 355 
 356 uint32_t generic_indirect_reg_update_ex(const struct dc_context *ctx,
 357                 uint32_t addr_index, uint32_t addr_data,
 358                 uint32_t index, uint32_t reg_val, int n,
 359                 uint8_t shift1, uint32_t mask1, uint32_t field_value1,
 360                 ...)
 361 {
 362         uint32_t shift, mask, field_value;
 363         int i = 1;
 364 
 365         va_list ap;
 366 
 367         va_start(ap, field_value1);
 368 
 369         reg_val = set_reg_field_value_ex(reg_val, field_value1, mask1, shift1);
 370 
 371         while (i < n) {
 372                 shift = va_arg(ap, uint32_t);
 373                 mask = va_arg(ap, uint32_t);
 374                 field_value = va_arg(ap, uint32_t);
 375 
 376                 reg_val = set_reg_field_value_ex(reg_val, field_value, mask, shift);
 377                 i++;
 378         }
 379 
 380         generic_write_indirect_reg(ctx, addr_index, addr_data, index, reg_val);
 381         va_end(ap);
 382 
 383         return reg_val;
 384 }

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