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