root/drivers/gpu/drm/amd/display/dc/core/dc_stream.c

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

DEFINITIONS

This source file includes following definitions.
  1. update_stream_signal
  2. construct
  3. destruct
  4. dc_stream_retain
  5. dc_stream_free
  6. dc_stream_release
  7. dc_create_stream_for_sink
  8. dc_copy_stream
  9. dc_stream_get_status_from_state
  10. dc_stream_get_status
  11. delay_cursor_until_vupdate
  12. dc_stream_set_cursor_attributes
  13. dc_stream_set_cursor_position
  14. dc_stream_add_writeback
  15. dc_stream_remove_writeback
  16. dc_stream_get_vblank_counter
  17. dc_stream_send_dp_sdp
  18. dc_stream_get_scanoutpos
  19. dc_stream_dmdata_status_done
  20. dc_stream_set_dynamic_metadata
  21. dc_stream_log

   1 /*
   2  * Copyright 2012-15 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 #include <linux/delay.h>
  27 #include <linux/slab.h>
  28 
  29 #include "dm_services.h"
  30 #include "dc.h"
  31 #include "core_types.h"
  32 #include "resource.h"
  33 #include "ipp.h"
  34 #include "timing_generator.h"
  35 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
  36 #include "dcn10/dcn10_hw_sequencer.h"
  37 #endif
  38 
  39 #define DC_LOGGER dc->ctx->logger
  40 
  41 /*******************************************************************************
  42  * Private functions
  43  ******************************************************************************/
  44 void update_stream_signal(struct dc_stream_state *stream, struct dc_sink *sink)
  45 {
  46         if (sink->sink_signal == SIGNAL_TYPE_NONE)
  47                 stream->signal = stream->link->connector_signal;
  48         else
  49                 stream->signal = sink->sink_signal;
  50 
  51         if (dc_is_dvi_signal(stream->signal)) {
  52                 if (stream->ctx->dc->caps.dual_link_dvi &&
  53                         (stream->timing.pix_clk_100hz / 10) > TMDS_MAX_PIXEL_CLOCK &&
  54                         sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK)
  55                         stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK;
  56                 else
  57                         stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
  58         }
  59 }
  60 
  61 static void construct(struct dc_stream_state *stream,
  62         struct dc_sink *dc_sink_data)
  63 {
  64         uint32_t i = 0;
  65 
  66         stream->sink = dc_sink_data;
  67         dc_sink_retain(dc_sink_data);
  68 
  69         stream->ctx = dc_sink_data->ctx;
  70         stream->link = dc_sink_data->link;
  71         stream->sink_patches = dc_sink_data->edid_caps.panel_patch;
  72         stream->converter_disable_audio = dc_sink_data->converter_disable_audio;
  73         stream->qs_bit = dc_sink_data->edid_caps.qs_bit;
  74         stream->qy_bit = dc_sink_data->edid_caps.qy_bit;
  75 
  76         /* Copy audio modes */
  77         /* TODO - Remove this translation */
  78         for (i = 0; i < (dc_sink_data->edid_caps.audio_mode_count); i++)
  79         {
  80                 stream->audio_info.modes[i].channel_count = dc_sink_data->edid_caps.audio_modes[i].channel_count;
  81                 stream->audio_info.modes[i].format_code = dc_sink_data->edid_caps.audio_modes[i].format_code;
  82                 stream->audio_info.modes[i].sample_rates.all = dc_sink_data->edid_caps.audio_modes[i].sample_rate;
  83                 stream->audio_info.modes[i].sample_size = dc_sink_data->edid_caps.audio_modes[i].sample_size;
  84         }
  85         stream->audio_info.mode_count = dc_sink_data->edid_caps.audio_mode_count;
  86         stream->audio_info.audio_latency = dc_sink_data->edid_caps.audio_latency;
  87         stream->audio_info.video_latency = dc_sink_data->edid_caps.video_latency;
  88         memmove(
  89                 stream->audio_info.display_name,
  90                 dc_sink_data->edid_caps.display_name,
  91                 AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS);
  92         stream->audio_info.manufacture_id = dc_sink_data->edid_caps.manufacturer_id;
  93         stream->audio_info.product_id = dc_sink_data->edid_caps.product_id;
  94         stream->audio_info.flags.all = dc_sink_data->edid_caps.speaker_flags;
  95 
  96         if (dc_sink_data->dc_container_id != NULL) {
  97                 struct dc_container_id *dc_container_id = dc_sink_data->dc_container_id;
  98 
  99                 stream->audio_info.port_id[0] = dc_container_id->portId[0];
 100                 stream->audio_info.port_id[1] = dc_container_id->portId[1];
 101         } else {
 102                 /* TODO - WindowDM has implemented,
 103                 other DMs need Unhardcode port_id */
 104                 stream->audio_info.port_id[0] = 0x5558859e;
 105                 stream->audio_info.port_id[1] = 0xd989449;
 106         }
 107 
 108         /* EDID CAP translation for HDMI 2.0 */
 109         stream->timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble;
 110 
 111 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
 112         memset(&stream->timing.dsc_cfg, 0, sizeof(stream->timing.dsc_cfg));
 113         stream->timing.dsc_cfg.num_slices_h = 0;
 114         stream->timing.dsc_cfg.num_slices_v = 0;
 115         stream->timing.dsc_cfg.bits_per_pixel = 128;
 116         stream->timing.dsc_cfg.block_pred_enable = 1;
 117         stream->timing.dsc_cfg.linebuf_depth = 9;
 118         stream->timing.dsc_cfg.version_minor = 2;
 119         stream->timing.dsc_cfg.ycbcr422_simple = 0;
 120 #endif
 121 
 122         update_stream_signal(stream, dc_sink_data);
 123 
 124         stream->out_transfer_func = dc_create_transfer_func();
 125         stream->out_transfer_func->type = TF_TYPE_BYPASS;
 126         stream->out_transfer_func->ctx = stream->ctx;
 127 
 128         stream->stream_id = stream->ctx->dc_stream_id_count;
 129         stream->ctx->dc_stream_id_count++;
 130 }
 131 
 132 static void destruct(struct dc_stream_state *stream)
 133 {
 134         dc_sink_release(stream->sink);
 135         if (stream->out_transfer_func != NULL) {
 136                 dc_transfer_func_release(stream->out_transfer_func);
 137                 stream->out_transfer_func = NULL;
 138         }
 139 }
 140 
 141 void dc_stream_retain(struct dc_stream_state *stream)
 142 {
 143         kref_get(&stream->refcount);
 144 }
 145 
 146 static void dc_stream_free(struct kref *kref)
 147 {
 148         struct dc_stream_state *stream = container_of(kref, struct dc_stream_state, refcount);
 149 
 150         destruct(stream);
 151         kfree(stream);
 152 }
 153 
 154 void dc_stream_release(struct dc_stream_state *stream)
 155 {
 156         if (stream != NULL) {
 157                 kref_put(&stream->refcount, dc_stream_free);
 158         }
 159 }
 160 
 161 struct dc_stream_state *dc_create_stream_for_sink(
 162                 struct dc_sink *sink)
 163 {
 164         struct dc_stream_state *stream;
 165 
 166         if (sink == NULL)
 167                 return NULL;
 168 
 169         stream = kzalloc(sizeof(struct dc_stream_state), GFP_KERNEL);
 170         if (stream == NULL)
 171                 return NULL;
 172 
 173         construct(stream, sink);
 174 
 175         kref_init(&stream->refcount);
 176 
 177         return stream;
 178 }
 179 
 180 struct dc_stream_state *dc_copy_stream(const struct dc_stream_state *stream)
 181 {
 182         struct dc_stream_state *new_stream;
 183 
 184         new_stream = kmemdup(stream, sizeof(struct dc_stream_state), GFP_KERNEL);
 185         if (!new_stream)
 186                 return NULL;
 187 
 188         if (new_stream->sink)
 189                 dc_sink_retain(new_stream->sink);
 190 
 191         if (new_stream->out_transfer_func)
 192                 dc_transfer_func_retain(new_stream->out_transfer_func);
 193 
 194         new_stream->stream_id = new_stream->ctx->dc_stream_id_count;
 195         new_stream->ctx->dc_stream_id_count++;
 196 
 197         kref_init(&new_stream->refcount);
 198 
 199         return new_stream;
 200 }
 201 
 202 /**
 203  * dc_stream_get_status_from_state - Get stream status from given dc state
 204  * @state: DC state to find the stream status in
 205  * @stream: The stream to get the stream status for
 206  *
 207  * The given stream is expected to exist in the given dc state. Otherwise, NULL
 208  * will be returned.
 209  */
 210 struct dc_stream_status *dc_stream_get_status_from_state(
 211         struct dc_state *state,
 212         struct dc_stream_state *stream)
 213 {
 214         uint8_t i;
 215 
 216         for (i = 0; i < state->stream_count; i++) {
 217                 if (stream == state->streams[i])
 218                         return &state->stream_status[i];
 219         }
 220 
 221         return NULL;
 222 }
 223 
 224 /**
 225  * dc_stream_get_status() - Get current stream status of the given stream state
 226  * @stream: The stream to get the stream status for.
 227  *
 228  * The given stream is expected to exist in dc->current_state. Otherwise, NULL
 229  * will be returned.
 230  */
 231 struct dc_stream_status *dc_stream_get_status(
 232         struct dc_stream_state *stream)
 233 {
 234         struct dc *dc = stream->ctx->dc;
 235         return dc_stream_get_status_from_state(dc->current_state, stream);
 236 }
 237 
 238 static void delay_cursor_until_vupdate(struct pipe_ctx *pipe_ctx, struct dc *dc)
 239 {
 240 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
 241         unsigned int vupdate_line;
 242         unsigned int lines_to_vupdate, us_to_vupdate, vpos, nvpos;
 243         struct dc_stream_state *stream = pipe_ctx->stream;
 244         unsigned int us_per_line;
 245 
 246         if (stream->ctx->asic_id.chip_family == FAMILY_RV &&
 247                         ASICREV_IS_RAVEN(stream->ctx->asic_id.hw_internal_rev)) {
 248 
 249                 vupdate_line = get_vupdate_offset_from_vsync(pipe_ctx);
 250                 if (!dc_stream_get_crtc_position(dc, &stream, 1, &vpos, &nvpos))
 251                         return;
 252 
 253                 if (vpos >= vupdate_line)
 254                         return;
 255 
 256                 us_per_line = stream->timing.h_total * 10000 / stream->timing.pix_clk_100hz;
 257                 lines_to_vupdate = vupdate_line - vpos;
 258                 us_to_vupdate = lines_to_vupdate * us_per_line;
 259 
 260                 /* 70 us is a conservative estimate of cursor update time*/
 261                 if (us_to_vupdate < 70)
 262                         udelay(us_to_vupdate);
 263         }
 264 #endif
 265 }
 266 
 267 /**
 268  * dc_stream_set_cursor_attributes() - Update cursor attributes and set cursor surface address
 269  */
 270 bool dc_stream_set_cursor_attributes(
 271         struct dc_stream_state *stream,
 272         const struct dc_cursor_attributes *attributes)
 273 {
 274         int i;
 275         struct dc  *core_dc;
 276         struct resource_context *res_ctx;
 277         struct pipe_ctx *pipe_to_program = NULL;
 278 
 279         if (NULL == stream) {
 280                 dm_error("DC: dc_stream is NULL!\n");
 281                 return false;
 282         }
 283         if (NULL == attributes) {
 284                 dm_error("DC: attributes is NULL!\n");
 285                 return false;
 286         }
 287 
 288         if (attributes->address.quad_part == 0) {
 289                 dm_output_to_console("DC: Cursor address is 0!\n");
 290                 return false;
 291         }
 292 
 293         core_dc = stream->ctx->dc;
 294         res_ctx = &core_dc->current_state->res_ctx;
 295         stream->cursor_attributes = *attributes;
 296 
 297         for (i = 0; i < MAX_PIPES; i++) {
 298                 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
 299 
 300                 if (pipe_ctx->stream != stream)
 301                         continue;
 302 
 303                 if (!pipe_to_program) {
 304                         pipe_to_program = pipe_ctx;
 305 
 306                         delay_cursor_until_vupdate(pipe_ctx, core_dc);
 307                         core_dc->hwss.pipe_control_lock(core_dc, pipe_to_program, true);
 308                 }
 309 
 310                 core_dc->hwss.set_cursor_attribute(pipe_ctx);
 311                 if (core_dc->hwss.set_cursor_sdr_white_level)
 312                         core_dc->hwss.set_cursor_sdr_white_level(pipe_ctx);
 313         }
 314 
 315         if (pipe_to_program)
 316                 core_dc->hwss.pipe_control_lock(core_dc, pipe_to_program, false);
 317 
 318         return true;
 319 }
 320 
 321 bool dc_stream_set_cursor_position(
 322         struct dc_stream_state *stream,
 323         const struct dc_cursor_position *position)
 324 {
 325         int i;
 326         struct dc  *core_dc;
 327         struct resource_context *res_ctx;
 328         struct pipe_ctx *pipe_to_program = NULL;
 329 
 330         if (NULL == stream) {
 331                 dm_error("DC: dc_stream is NULL!\n");
 332                 return false;
 333         }
 334 
 335         if (NULL == position) {
 336                 dm_error("DC: cursor position is NULL!\n");
 337                 return false;
 338         }
 339 
 340         core_dc = stream->ctx->dc;
 341         res_ctx = &core_dc->current_state->res_ctx;
 342         stream->cursor_position = *position;
 343 
 344         for (i = 0; i < MAX_PIPES; i++) {
 345                 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
 346 
 347                 if (pipe_ctx->stream != stream ||
 348                                 (!pipe_ctx->plane_res.mi  && !pipe_ctx->plane_res.hubp) ||
 349                                 !pipe_ctx->plane_state ||
 350                                 (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp) ||
 351                                 (!pipe_ctx->plane_res.ipp && !pipe_ctx->plane_res.dpp))
 352                         continue;
 353 
 354                 if (!pipe_to_program) {
 355                         pipe_to_program = pipe_ctx;
 356 
 357                         delay_cursor_until_vupdate(pipe_ctx, core_dc);
 358                         core_dc->hwss.pipe_control_lock(core_dc, pipe_to_program, true);
 359                 }
 360 
 361                 core_dc->hwss.set_cursor_position(pipe_ctx);
 362         }
 363 
 364         if (pipe_to_program)
 365                 core_dc->hwss.pipe_control_lock(core_dc, pipe_to_program, false);
 366 
 367         return true;
 368 }
 369 
 370 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
 371 bool dc_stream_add_writeback(struct dc *dc,
 372                 struct dc_stream_state *stream,
 373                 struct dc_writeback_info *wb_info)
 374 {
 375         bool isDrc = false;
 376         int i = 0;
 377         struct dwbc *dwb;
 378 
 379         if (stream == NULL) {
 380                 dm_error("DC: dc_stream is NULL!\n");
 381                 return false;
 382         }
 383 
 384         if (wb_info == NULL) {
 385                 dm_error("DC: dc_writeback_info is NULL!\n");
 386                 return false;
 387         }
 388 
 389         if (wb_info->dwb_pipe_inst >= MAX_DWB_PIPES) {
 390                 dm_error("DC: writeback pipe is invalid!\n");
 391                 return false;
 392         }
 393 
 394         wb_info->dwb_params.out_transfer_func = stream->out_transfer_func;
 395 
 396         dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
 397         dwb->dwb_is_drc = false;
 398 
 399         /* recalculate and apply DML parameters */
 400 
 401         for (i = 0; i < stream->num_wb_info; i++) {
 402                 /*dynamic update*/
 403                 if (stream->writeback_info[i].wb_enabled &&
 404                         stream->writeback_info[i].dwb_pipe_inst == wb_info->dwb_pipe_inst) {
 405                         stream->writeback_info[i] = *wb_info;
 406                         isDrc = true;
 407                 }
 408         }
 409 
 410         if (!isDrc) {
 411                 stream->writeback_info[stream->num_wb_info++] = *wb_info;
 412         }
 413 
 414         if (!dc->hwss.update_bandwidth(dc, dc->current_state)) {
 415                 dm_error("DC: update_bandwidth failed!\n");
 416                 return false;
 417         }
 418 
 419         /* enable writeback */
 420         if (dc->hwss.enable_writeback) {
 421                 struct dc_stream_status *stream_status = dc_stream_get_status(stream);
 422                 struct dwbc *dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
 423 
 424                 if (dwb->funcs->is_enabled(dwb)) {
 425                         /* writeback pipe already enabled, only need to update */
 426                         dc->hwss.update_writeback(dc, stream_status, wb_info, dc->current_state);
 427                 } else {
 428                         /* Enable writeback pipe from scratch*/
 429                         dc->hwss.enable_writeback(dc, stream_status, wb_info, dc->current_state);
 430                 }
 431         }
 432 
 433         return true;
 434 }
 435 
 436 bool dc_stream_remove_writeback(struct dc *dc,
 437                 struct dc_stream_state *stream,
 438                 uint32_t dwb_pipe_inst)
 439 {
 440         int i = 0, j = 0;
 441         if (stream == NULL) {
 442                 dm_error("DC: dc_stream is NULL!\n");
 443                 return false;
 444         }
 445 
 446         if (dwb_pipe_inst >= MAX_DWB_PIPES) {
 447                 dm_error("DC: writeback pipe is invalid!\n");
 448                 return false;
 449         }
 450 
 451 //      stream->writeback_info[dwb_pipe_inst].wb_enabled = false;
 452         for (i = 0; i < stream->num_wb_info; i++) {
 453                 /*dynamic update*/
 454                 if (stream->writeback_info[i].wb_enabled &&
 455                         stream->writeback_info[i].dwb_pipe_inst == dwb_pipe_inst) {
 456                         stream->writeback_info[i].wb_enabled = false;
 457                 }
 458         }
 459 
 460         /* remove writeback info for disabled writeback pipes from stream */
 461         for (i = 0, j = 0; i < stream->num_wb_info; i++) {
 462                 if (stream->writeback_info[i].wb_enabled) {
 463                         if (i != j)
 464                                 /* trim the array */
 465                                 stream->writeback_info[j] = stream->writeback_info[i];
 466                         j++;
 467                 }
 468         }
 469         stream->num_wb_info = j;
 470 
 471         /* recalculate and apply DML parameters */
 472         if (!dc->hwss.update_bandwidth(dc, dc->current_state)) {
 473                 dm_error("DC: update_bandwidth failed!\n");
 474                 return false;
 475         }
 476 
 477         /* disable writeback */
 478         if (dc->hwss.disable_writeback)
 479                 dc->hwss.disable_writeback(dc, dwb_pipe_inst);
 480 
 481         return true;
 482 }
 483 #endif
 484 
 485 uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream)
 486 {
 487         uint8_t i;
 488         struct dc  *core_dc = stream->ctx->dc;
 489         struct resource_context *res_ctx =
 490                 &core_dc->current_state->res_ctx;
 491 
 492         for (i = 0; i < MAX_PIPES; i++) {
 493                 struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg;
 494 
 495                 if (res_ctx->pipe_ctx[i].stream != stream)
 496                         continue;
 497 
 498                 return tg->funcs->get_frame_count(tg);
 499         }
 500 
 501         return 0;
 502 }
 503 
 504 bool dc_stream_send_dp_sdp(const struct dc_stream_state *stream,
 505                 const uint8_t *custom_sdp_message,
 506                 unsigned int sdp_message_size)
 507 {
 508         int i;
 509         struct dc  *dc;
 510         struct resource_context *res_ctx;
 511 
 512         if (stream == NULL) {
 513                 dm_error("DC: dc_stream is NULL!\n");
 514                 return false;
 515         }
 516 
 517         dc = stream->ctx->dc;
 518         res_ctx = &dc->current_state->res_ctx;
 519 
 520         for (i = 0; i < MAX_PIPES; i++) {
 521                 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
 522 
 523                 if (pipe_ctx->stream != stream)
 524                         continue;
 525 
 526                 if (dc->hwss.send_immediate_sdp_message != NULL)
 527                         dc->hwss.send_immediate_sdp_message(pipe_ctx,
 528                                                                 custom_sdp_message,
 529                                                                 sdp_message_size);
 530                 else
 531                         DC_LOG_WARNING("%s:send_immediate_sdp_message not implemented on this ASIC\n",
 532                         __func__);
 533 
 534         }
 535 
 536         return true;
 537 }
 538 
 539 bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream,
 540                                   uint32_t *v_blank_start,
 541                                   uint32_t *v_blank_end,
 542                                   uint32_t *h_position,
 543                                   uint32_t *v_position)
 544 {
 545         uint8_t i;
 546         bool ret = false;
 547         struct dc  *core_dc = stream->ctx->dc;
 548         struct resource_context *res_ctx =
 549                 &core_dc->current_state->res_ctx;
 550 
 551         for (i = 0; i < MAX_PIPES; i++) {
 552                 struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg;
 553 
 554                 if (res_ctx->pipe_ctx[i].stream != stream)
 555                         continue;
 556 
 557                 tg->funcs->get_scanoutpos(tg,
 558                                           v_blank_start,
 559                                           v_blank_end,
 560                                           h_position,
 561                                           v_position);
 562 
 563                 ret = true;
 564                 break;
 565         }
 566 
 567         return ret;
 568 }
 569 
 570 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
 571 bool dc_stream_dmdata_status_done(struct dc *dc, struct dc_stream_state *stream)
 572 {
 573         bool status = true;
 574         struct pipe_ctx *pipe = NULL;
 575         int i;
 576 
 577         if (!dc->hwss.dmdata_status_done)
 578                 return false;
 579 
 580         for (i = 0; i < MAX_PIPES; i++) {
 581                 pipe = &dc->current_state->res_ctx.pipe_ctx[i];
 582                 if (pipe->stream == stream)
 583                         break;
 584         }
 585         /* Stream not found, by default we'll assume HUBP fetched dm data */
 586         if (i == MAX_PIPES)
 587                 return true;
 588 
 589         status = dc->hwss.dmdata_status_done(pipe);
 590         return status;
 591 }
 592 
 593 bool dc_stream_set_dynamic_metadata(struct dc *dc,
 594                 struct dc_stream_state *stream,
 595                 struct dc_dmdata_attributes *attr)
 596 {
 597         struct pipe_ctx *pipe_ctx = NULL;
 598         struct hubp *hubp;
 599         int i;
 600 
 601         /* Dynamic metadata is only supported on HDMI or DP */
 602         if (!dc_is_hdmi_signal(stream->signal) && !dc_is_dp_signal(stream->signal))
 603                 return false;
 604 
 605         /* Check hardware support */
 606         if (!dc->hwss.program_dmdata_engine)
 607                 return false;
 608 
 609         for (i = 0; i < MAX_PIPES; i++) {
 610                 pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
 611                 if (pipe_ctx->stream == stream)
 612                         break;
 613         }
 614 
 615         if (i == MAX_PIPES)
 616                 return false;
 617 
 618         hubp = pipe_ctx->plane_res.hubp;
 619         if (hubp == NULL)
 620                 return false;
 621 
 622         pipe_ctx->stream->dmdata_address = attr->address;
 623 
 624         dc->hwss.program_dmdata_engine(pipe_ctx);
 625 
 626         if (hubp->funcs->dmdata_set_attributes != NULL &&
 627                         pipe_ctx->stream->dmdata_address.quad_part != 0) {
 628                 hubp->funcs->dmdata_set_attributes(hubp, attr);
 629         }
 630 
 631         return true;
 632 }
 633 #endif
 634 
 635 void dc_stream_log(const struct dc *dc, const struct dc_stream_state *stream)
 636 {
 637         DC_LOG_DC(
 638                         "core_stream 0x%p: src: %d, %d, %d, %d; dst: %d, %d, %d, %d, colorSpace:%d\n",
 639                         stream,
 640                         stream->src.x,
 641                         stream->src.y,
 642                         stream->src.width,
 643                         stream->src.height,
 644                         stream->dst.x,
 645                         stream->dst.y,
 646                         stream->dst.width,
 647                         stream->dst.height,
 648                         stream->output_color_space);
 649         DC_LOG_DC(
 650                         "\tpix_clk_khz: %d, h_total: %d, v_total: %d, pixelencoder:%d, displaycolorDepth:%d\n",
 651                         stream->timing.pix_clk_100hz / 10,
 652                         stream->timing.h_total,
 653                         stream->timing.v_total,
 654                         stream->timing.pixel_encoding,
 655                         stream->timing.display_color_depth);
 656         DC_LOG_DC(
 657                         "\tlink: %d\n",
 658                         stream->link->link_index);
 659 }

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