1 /* 2 * Copyright 2015 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 * Authors: AMD 23 * 24 */ 25 26 /** 27 * This file defines external dependencies of Display Core. 28 */ 29 30 #ifndef __DM_SERVICES_H__ 31 32 #define __DM_SERVICES_H__ 33 34 /* TODO: remove when DC is complete. */ 35 #include "dm_services_types.h" 36 #include "logger_interface.h" 37 #include "link_service_types.h" 38 39 #undef DEPRECATED 40 41 /* 42 * 43 * general debug capabilities 44 * 45 */ 46 #if defined(CONFIG_DEBUG_KERNEL) || defined(CONFIG_DEBUG_DRIVER) 47 48 #if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB) 49 #define ASSERT_CRITICAL(expr) do { \ 50 if (WARN_ON(!(expr))) { \ 51 kgdb_breakpoint(); \ 52 } \ 53 } while (0) 54 #else 55 #define ASSERT_CRITICAL(expr) do { \ 56 if (WARN_ON(!(expr))) { \ 57 ; \ 58 } \ 59 } while (0) 60 #endif 61 62 #if defined(CONFIG_DEBUG_KERNEL_DC) 63 #define ASSERT(expr) ASSERT_CRITICAL(expr) 64 65 #else 66 #define ASSERT(expr) WARN_ON(!(expr)) 67 #endif 68 69 #define BREAK_TO_DEBUGGER() ASSERT(0) 70 71 #endif /* CONFIG_DEBUG_KERNEL || CONFIG_DEBUG_DRIVER */ 72 73 #define DC_ERR(...) do { \ 74 dm_error(__VA_ARGS__); \ 75 BREAK_TO_DEBUGGER(); \ 76 } while (0) 77 78 #define dm_alloc(size) kzalloc(size, GFP_KERNEL) 79 #define dm_realloc(ptr, size) krealloc(ptr, size, GFP_KERNEL) 80 #define dm_free(ptr) kfree(ptr) 81 82 irq_handler_idx dm_register_interrupt( 83 struct dc_context *ctx, 84 struct dc_interrupt_params *int_params, 85 interrupt_handler ih, 86 void *handler_args); 87 88 89 /* 90 * 91 * GPU registers access 92 * 93 */ 94 95 #define dm_read_reg(ctx, address) \ 96 dm_read_reg_func(ctx, address, __func__) 97 98 static inline uint32_t dm_read_reg_func( 99 const struct dc_context *ctx, 100 uint32_t address, 101 const char *func_name) 102 { 103 uint32_t value; 104 105 if (address == 0) { 106 DC_ERR("invalid register read; address = 0\n"); 107 return 0; 108 } 109 110 value = cgs_read_register(ctx->cgs_device, address); 111 112 return value; 113 } 114 115 #define dm_write_reg(ctx, address, value) \ 116 dm_write_reg_func(ctx, address, value, __func__) 117 118 static inline void dm_write_reg_func( 119 const struct dc_context *ctx, 120 uint32_t address, 121 uint32_t value, 122 const char *func_name) 123 { 124 if (address == 0) { 125 DC_ERR("invalid register write. address = 0"); 126 return; 127 } 128 cgs_write_register(ctx->cgs_device, address, value); 129 } 130 131 static inline uint32_t dm_read_index_reg( 132 const struct dc_context *ctx, 133 enum cgs_ind_reg addr_space, 134 uint32_t index) 135 { 136 return cgs_read_ind_register(ctx->cgs_device, addr_space, index); 137 } 138 139 static inline void dm_write_index_reg( 140 const struct dc_context *ctx, 141 enum cgs_ind_reg addr_space, 142 uint32_t index, 143 uint32_t value) 144 { 145 cgs_write_ind_register(ctx->cgs_device, addr_space, index, value); 146 } 147 148 static inline uint32_t get_reg_field_value_ex( 149 uint32_t reg_value, 150 uint32_t mask, 151 uint8_t shift) 152 { 153 return (mask & reg_value) >> shift; 154 } 155 156 #define get_reg_field_value(reg_value, reg_name, reg_field)\ 157 get_reg_field_value_ex(\ 158 (reg_value),\ 159 reg_name ## __ ## reg_field ## _MASK,\ 160 reg_name ## __ ## reg_field ## __SHIFT) 161 162 static inline uint32_t set_reg_field_value_ex( 163 uint32_t reg_value, 164 uint32_t value, 165 uint32_t mask, 166 uint8_t shift) 167 { 168 ASSERT(mask != 0); 169 return (reg_value & ~mask) | (mask & (value << shift)); 170 } 171 172 #define set_reg_field_value(reg_value, value, reg_name, reg_field)\ 173 (reg_value) = set_reg_field_value_ex(\ 174 (reg_value),\ 175 (value),\ 176 reg_name ## __ ## reg_field ## _MASK,\ 177 reg_name ## __ ## reg_field ## __SHIFT) 178 179 uint32_t generic_reg_update_ex(const struct dc_context *ctx, 180 uint32_t addr, uint32_t reg_val, int n, 181 uint8_t shift1, uint32_t mask1, uint32_t field_value1, ...); 182 183 #define FD(reg_field) reg_field ## __SHIFT, \ 184 reg_field ## _MASK 185 186 /* 187 * return number of poll before condition is met 188 * return 0 if condition is not meet after specified time out tries 189 */ 190 unsigned int generic_reg_wait(const struct dc_context *ctx, 191 uint32_t addr, uint32_t mask, uint32_t shift, uint32_t condition_value, 192 unsigned int delay_between_poll_us, unsigned int time_out_num_tries, 193 const char *func_name); 194 195 196 /* These macros need to be used with soc15 registers in order to retrieve 197 * the actual offset. 198 */ 199 #define REG_OFFSET(reg) (reg + DCE_BASE.instance[0].segment[reg##_BASE_IDX]) 200 #define REG_BIF_OFFSET(reg) (reg + NBIF_BASE.instance[0].segment[reg##_BASE_IDX]) 201 202 #define dm_write_reg_soc15(ctx, reg, inst_offset, value) \ 203 dm_write_reg_func(ctx, reg + DCE_BASE.instance[0].segment[reg##_BASE_IDX] + inst_offset, value, __func__) 204 205 #define dm_read_reg_soc15(ctx, reg, inst_offset) \ 206 dm_read_reg_func(ctx, reg + DCE_BASE.instance[0].segment[reg##_BASE_IDX] + inst_offset, __func__) 207 208 #define generic_reg_update_soc15(ctx, inst_offset, reg_name, n, ...)\ 209 generic_reg_update_ex(ctx, DCE_BASE.instance[0].segment[mm##reg_name##_BASE_IDX] + mm##reg_name + inst_offset, \ 210 dm_read_reg_func(ctx, mm##reg_name + DCE_BASE.instance[0].segment[mm##reg_name##_BASE_IDX] + inst_offset, __func__), \ 211 n, __VA_ARGS__) 212 213 #define generic_reg_set_soc15(ctx, inst_offset, reg_name, n, ...)\ 214 generic_reg_update_ex(ctx, DCE_BASE.instance[0].segment[mm##reg_name##_BASE_IDX] + mm##reg_name + inst_offset, 0, \ 215 n, __VA_ARGS__) 216 217 #define get_reg_field_value_soc15(reg_value, block, reg_num, reg_name, reg_field)\ 218 get_reg_field_value_ex(\ 219 (reg_value),\ 220 block ## reg_num ## _ ## reg_name ## __ ## reg_field ## _MASK,\ 221 block ## reg_num ## _ ## reg_name ## __ ## reg_field ## __SHIFT) 222 223 #define set_reg_field_value_soc15(reg_value, value, block, reg_num, reg_name, reg_field)\ 224 (reg_value) = set_reg_field_value_ex(\ 225 (reg_value),\ 226 (value),\ 227 block ## reg_num ## _ ## reg_name ## __ ## reg_field ## _MASK,\ 228 block ## reg_num ## _ ## reg_name ## __ ## reg_field ## __SHIFT) 229 230 /* TODO get rid of this pos*/ 231 static inline bool wait_reg_func( 232 const struct dc_context *ctx, 233 uint32_t addr, 234 uint32_t mask, 235 uint8_t shift, 236 uint32_t condition_value, 237 unsigned int interval_us, 238 unsigned int timeout_us) 239 { 240 uint32_t field_value; 241 uint32_t reg_val; 242 unsigned int count = 0; 243 244 if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) 245 timeout_us *= 655; /* 6553 give about 30 second before time out */ 246 247 do { 248 /* try once without sleeping */ 249 if (count > 0) { 250 if (interval_us >= 1000) 251 msleep(interval_us/1000); 252 else 253 udelay(interval_us); 254 } 255 reg_val = dm_read_reg(ctx, addr); 256 field_value = get_reg_field_value_ex(reg_val, mask, shift); 257 count += interval_us; 258 259 } while (field_value != condition_value && count <= timeout_us); 260 261 ASSERT(count <= timeout_us); 262 263 return count <= timeout_us; 264 } 265 266 #define wait_reg(ctx, inst_offset, reg_name, reg_field, condition_value)\ 267 wait_reg_func(\ 268 ctx,\ 269 mm##reg_name + inst_offset + DCE_BASE.instance[0].segment[mm##reg_name##_BASE_IDX],\ 270 reg_name ## __ ## reg_field ## _MASK,\ 271 reg_name ## __ ## reg_field ## __SHIFT,\ 272 condition_value,\ 273 20000,\ 274 200000) 275 276 /************************************** 277 * Power Play (PP) interfaces 278 **************************************/ 279 280 /* DAL calls this function to notify PP about clocks it needs for the Mode Set. 281 * This is done *before* it changes DCE clock. 282 * 283 * If required clock is higher than current, then PP will increase the voltage. 284 * 285 * If required clock is lower than current, then PP will defer reduction of 286 * voltage until the call to dc_service_pp_post_dce_clock_change(). 287 * 288 * \input - Contains clocks needed for Mode Set. 289 * 290 * \output - Contains clocks adjusted by PP which DAL should use for Mode Set. 291 * Valid only if function returns zero. 292 * 293 * \returns true - call is successful 294 * false - call failed 295 */ 296 bool dm_pp_pre_dce_clock_change( 297 struct dc_context *ctx, 298 struct dm_pp_gpu_clock_range *requested_state, 299 struct dm_pp_gpu_clock_range *actual_state); 300 301 /* The returned clocks range are 'static' system clocks which will be used for 302 * mode validation purposes. 303 * 304 * \returns true - call is successful 305 * false - call failed 306 */ 307 bool dc_service_get_system_clocks_range( 308 const struct dc_context *ctx, 309 struct dm_pp_gpu_clock_range *sys_clks); 310 311 /* Gets valid clocks levels from pplib 312 * 313 * input: clk_type - display clk / sclk / mem clk 314 * 315 * output: array of valid clock levels for given type in ascending order, 316 * with invalid levels filtered out 317 * 318 */ 319 bool dm_pp_get_clock_levels_by_type( 320 const struct dc_context *ctx, 321 enum dm_pp_clock_type clk_type, 322 struct dm_pp_clock_levels *clk_level_info); 323 324 bool dm_pp_get_clock_levels_by_type_with_latency( 325 const struct dc_context *ctx, 326 enum dm_pp_clock_type clk_type, 327 struct dm_pp_clock_levels_with_latency *clk_level_info); 328 329 bool dm_pp_get_clock_levels_by_type_with_voltage( 330 const struct dc_context *ctx, 331 enum dm_pp_clock_type clk_type, 332 struct dm_pp_clock_levels_with_voltage *clk_level_info); 333 334 bool dm_pp_notify_wm_clock_changes( 335 const struct dc_context *ctx, 336 struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges); 337 338 bool dm_pp_notify_wm_clock_changes_soc15( 339 const struct dc_context *ctx, 340 struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges); 341 342 /* DAL calls this function to notify PP about completion of Mode Set. 343 * For PP it means that current DCE clocks are those which were returned 344 * by dc_service_pp_pre_dce_clock_change(), in the 'output' parameter. 345 * 346 * If the clocks are higher than before, then PP does nothing. 347 * 348 * If the clocks are lower than before, then PP reduces the voltage. 349 * 350 * \returns true - call is successful 351 * false - call failed 352 */ 353 bool dm_pp_apply_display_requirements( 354 const struct dc_context *ctx, 355 const struct dm_pp_display_configuration *pp_display_cfg); 356 357 bool dm_pp_apply_power_level_change_request( 358 const struct dc_context *ctx, 359 struct dm_pp_power_level_change_request *level_change_req); 360 361 bool dm_pp_apply_clock_for_voltage_request( 362 const struct dc_context *ctx, 363 struct dm_pp_clock_for_voltage_req *clock_for_voltage_req); 364 365 bool dm_pp_get_static_clocks( 366 const struct dc_context *ctx, 367 struct dm_pp_static_clock_info *static_clk_info); 368 369 /****** end of PP interfaces ******/ 370 371 struct persistent_data_flag { 372 bool save_per_link; 373 bool save_per_edid; 374 }; 375 376 /* Call to write data in registry editor for persistent data storage. 377 * 378 * \inputs sink - identify edid/link for registry folder creation 379 * module name - identify folders for registry 380 * key name - identify keys within folders for registry 381 * params - value to write in defined folder/key 382 * size - size of the input params 383 * flag - determine whether to save by link or edid 384 * 385 * \returns true - call is successful 386 * false - call failed 387 * 388 * sink module key 389 * ----------------------------------------------------------------------------- 390 * NULL NULL NULL - failure 391 * NULL NULL - - create key with param value 392 * under base folder 393 * NULL - NULL - create module folder under base folder 394 * - NULL NULL - failure 395 * NULL - - - create key under module folder 396 * with no edid/link identification 397 * - NULL - - create key with param value 398 * under base folder 399 * - - NULL - create module folder under base folder 400 * - - - - create key under module folder 401 * with edid/link identification 402 */ 403 bool dm_write_persistent_data(struct dc_context *ctx, 404 const struct dc_sink *sink, 405 const char *module_name, 406 const char *key_name, 407 void *params, 408 unsigned int size, 409 struct persistent_data_flag *flag); 410 411 412 /* Call to read data in registry editor for persistent data storage. 413 * 414 * \inputs sink - identify edid/link for registry folder creation 415 * module name - identify folders for registry 416 * key name - identify keys within folders for registry 417 * size - size of the output params 418 * flag - determine whether it was save by link or edid 419 * 420 * \returns params - value read from defined folder/key 421 * true - call is successful 422 * false - call failed 423 * 424 * sink module key 425 * ----------------------------------------------------------------------------- 426 * NULL NULL NULL - failure 427 * NULL NULL - - read key under base folder 428 * NULL - NULL - failure 429 * - NULL NULL - failure 430 * NULL - - - read key under module folder 431 * with no edid/link identification 432 * - NULL - - read key under base folder 433 * - - NULL - failure 434 * - - - - read key under module folder 435 * with edid/link identification 436 */ 437 bool dm_read_persistent_data(struct dc_context *ctx, 438 const struct dc_sink *sink, 439 const char *module_name, 440 const char *key_name, 441 void *params, 442 unsigned int size, 443 struct persistent_data_flag *flag); 444 445 void dm_delay_in_microseconds 446 (struct dc_context *ctx, unsigned int microSeconds); 447 448 bool dm_query_extended_brightness_caps 449 (struct dc_context *ctx, enum dm_acpi_display_type display, 450 struct dm_acpi_atif_backlight_caps *pCaps); 451 452 bool dm_dmcu_set_pipe(struct dc_context *ctx, unsigned int controller_id); 453 454 /* 455 * 456 * print-out services 457 * 458 */ 459 #define dm_log_to_buffer(buffer, size, fmt, args)\ 460 vsnprintf(buffer, size, fmt, args) 461 462 #endif /* __DM_SERVICES_H__ */ 463