14562236bSHarry Wentland /* 24562236bSHarry Wentland * Copyright 2012-15 Advanced Micro Devices, Inc. 34562236bSHarry Wentland * 44562236bSHarry Wentland * Permission is hereby granted, free of charge, to any person obtaining a 54562236bSHarry Wentland * copy of this software and associated documentation files (the "Software"), 64562236bSHarry Wentland * to deal in the Software without restriction, including without limitation 74562236bSHarry Wentland * the rights to use, copy, modify, merge, publish, distribute, sublicense, 84562236bSHarry Wentland * and/or sell copies of the Software, and to permit persons to whom the 94562236bSHarry Wentland * Software is furnished to do so, subject to the following conditions: 104562236bSHarry Wentland * 114562236bSHarry Wentland * The above copyright notice and this permission notice shall be included in 124562236bSHarry Wentland * all copies or substantial portions of the Software. 134562236bSHarry Wentland * 144562236bSHarry Wentland * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 154562236bSHarry Wentland * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 164562236bSHarry Wentland * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 174562236bSHarry Wentland * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 184562236bSHarry Wentland * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 194562236bSHarry Wentland * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 204562236bSHarry Wentland * OTHER DEALINGS IN THE SOFTWARE. 214562236bSHarry Wentland * 224562236bSHarry Wentland * Authors: AMD 234562236bSHarry Wentland * 244562236bSHarry Wentland */ 254562236bSHarry Wentland #include "dm_services.h" 264562236bSHarry Wentland 274562236bSHarry Wentland #include "resource.h" 284562236bSHarry Wentland #include "include/irq_service_interface.h" 294562236bSHarry Wentland #include "link_encoder.h" 304562236bSHarry Wentland #include "stream_encoder.h" 314562236bSHarry Wentland #include "opp.h" 324562236bSHarry Wentland #include "timing_generator.h" 334562236bSHarry Wentland #include "transform.h" 345ac3d3c9SCharlene Liu #include "core_types.h" 354562236bSHarry Wentland #include "set_mode_types.h" 364562236bSHarry Wentland #include "virtual/virtual_stream_encoder.h" 374562236bSHarry Wentland 384562236bSHarry Wentland #include "dce80/dce80_resource.h" 394562236bSHarry Wentland #include "dce100/dce100_resource.h" 404562236bSHarry Wentland #include "dce110/dce110_resource.h" 414562236bSHarry Wentland #include "dce112/dce112_resource.h" 422c8ad2d5SAlex Deucher #include "dce120/dce120_resource.h" 434562236bSHarry Wentland 444562236bSHarry Wentland enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) 454562236bSHarry Wentland { 464562236bSHarry Wentland enum dce_version dc_version = DCE_VERSION_UNKNOWN; 474562236bSHarry Wentland switch (asic_id.chip_family) { 484562236bSHarry Wentland 494562236bSHarry Wentland case FAMILY_CI: 504562236bSHarry Wentland case FAMILY_KV: 514562236bSHarry Wentland dc_version = DCE_VERSION_8_0; 524562236bSHarry Wentland break; 534562236bSHarry Wentland case FAMILY_CZ: 544562236bSHarry Wentland dc_version = DCE_VERSION_11_0; 554562236bSHarry Wentland break; 564562236bSHarry Wentland 574562236bSHarry Wentland case FAMILY_VI: 584562236bSHarry Wentland if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) || 594562236bSHarry Wentland ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) { 604562236bSHarry Wentland dc_version = DCE_VERSION_10_0; 614562236bSHarry Wentland break; 624562236bSHarry Wentland } 634562236bSHarry Wentland if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) || 64b264d345SJordan Lazare ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || 65b264d345SJordan Lazare ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) { 664562236bSHarry Wentland dc_version = DCE_VERSION_11_2; 674562236bSHarry Wentland } 684562236bSHarry Wentland break; 692c8ad2d5SAlex Deucher case FAMILY_AI: 702c8ad2d5SAlex Deucher dc_version = DCE_VERSION_12_0; 712c8ad2d5SAlex Deucher break; 724562236bSHarry Wentland default: 734562236bSHarry Wentland dc_version = DCE_VERSION_UNKNOWN; 744562236bSHarry Wentland break; 754562236bSHarry Wentland } 764562236bSHarry Wentland return dc_version; 774562236bSHarry Wentland } 784562236bSHarry Wentland 794562236bSHarry Wentland struct resource_pool *dc_create_resource_pool( 804562236bSHarry Wentland struct core_dc *dc, 814562236bSHarry Wentland int num_virtual_links, 824562236bSHarry Wentland enum dce_version dc_version, 834562236bSHarry Wentland struct hw_asic_id asic_id) 844562236bSHarry Wentland { 855ac3d3c9SCharlene Liu struct resource_pool *res_pool = NULL; 864562236bSHarry Wentland 874562236bSHarry Wentland switch (dc_version) { 884562236bSHarry Wentland case DCE_VERSION_8_0: 895ac3d3c9SCharlene Liu res_pool = dce80_create_resource_pool( 904562236bSHarry Wentland num_virtual_links, dc); 915ac3d3c9SCharlene Liu break; 924562236bSHarry Wentland case DCE_VERSION_10_0: 935ac3d3c9SCharlene Liu res_pool = dce100_create_resource_pool( 944562236bSHarry Wentland num_virtual_links, dc); 955ac3d3c9SCharlene Liu break; 964562236bSHarry Wentland case DCE_VERSION_11_0: 975ac3d3c9SCharlene Liu res_pool = dce110_create_resource_pool( 984562236bSHarry Wentland num_virtual_links, dc, asic_id); 995ac3d3c9SCharlene Liu break; 1004562236bSHarry Wentland case DCE_VERSION_11_2: 1015ac3d3c9SCharlene Liu res_pool = dce112_create_resource_pool( 1024562236bSHarry Wentland num_virtual_links, dc); 1035ac3d3c9SCharlene Liu break; 1042c8ad2d5SAlex Deucher case DCE_VERSION_12_0: 1052c8ad2d5SAlex Deucher res_pool = dce120_create_resource_pool( 1062c8ad2d5SAlex Deucher num_virtual_links, dc); 1072c8ad2d5SAlex Deucher break; 1084562236bSHarry Wentland default: 1094562236bSHarry Wentland break; 1104562236bSHarry Wentland } 1115ac3d3c9SCharlene Liu if (res_pool != NULL) { 1125ac3d3c9SCharlene Liu struct firmware_info fw_info = { { 0 } }; 1134562236bSHarry Wentland 1145ac3d3c9SCharlene Liu if (dc->ctx->dc_bios->funcs->get_firmware_info( 1155ac3d3c9SCharlene Liu dc->ctx->dc_bios, &fw_info) == BP_RESULT_OK) { 1165ac3d3c9SCharlene Liu res_pool->ref_clock_inKhz = fw_info.pll_info.crystal_frequency; 1175ac3d3c9SCharlene Liu } else 1185ac3d3c9SCharlene Liu ASSERT_CRITICAL(false); 1195ac3d3c9SCharlene Liu } 1205ac3d3c9SCharlene Liu 1215ac3d3c9SCharlene Liu return res_pool; 1224562236bSHarry Wentland } 1234562236bSHarry Wentland 1244562236bSHarry Wentland void dc_destroy_resource_pool(struct core_dc *dc) 1254562236bSHarry Wentland { 1264562236bSHarry Wentland if (dc) { 1274562236bSHarry Wentland if (dc->res_pool) 1284562236bSHarry Wentland dc->res_pool->funcs->destroy(&dc->res_pool); 1294562236bSHarry Wentland 1304562236bSHarry Wentland if (dc->hwseq) 1314562236bSHarry Wentland dm_free(dc->hwseq); 1324562236bSHarry Wentland } 1334562236bSHarry Wentland } 1344562236bSHarry Wentland 1354562236bSHarry Wentland static void update_num_audio( 1364562236bSHarry Wentland const struct resource_straps *straps, 1374562236bSHarry Wentland unsigned int *num_audio, 1384562236bSHarry Wentland struct audio_support *aud_support) 1394562236bSHarry Wentland { 1404562236bSHarry Wentland if (straps->hdmi_disable == 0) { 1414562236bSHarry Wentland aud_support->hdmi_audio_native = true; 1424562236bSHarry Wentland aud_support->hdmi_audio_on_dongle = true; 1434562236bSHarry Wentland aud_support->dp_audio = true; 1444562236bSHarry Wentland } else { 1454562236bSHarry Wentland if (straps->dc_pinstraps_audio & 0x2) { 1464562236bSHarry Wentland aud_support->hdmi_audio_on_dongle = true; 1474562236bSHarry Wentland aud_support->dp_audio = true; 1484562236bSHarry Wentland } else { 1494562236bSHarry Wentland aud_support->dp_audio = true; 1504562236bSHarry Wentland } 1514562236bSHarry Wentland } 1524562236bSHarry Wentland 1534562236bSHarry Wentland switch (straps->audio_stream_number) { 1544562236bSHarry Wentland case 0: /* multi streams supported */ 1554562236bSHarry Wentland break; 1564562236bSHarry Wentland case 1: /* multi streams not supported */ 1574562236bSHarry Wentland *num_audio = 1; 1584562236bSHarry Wentland break; 1594562236bSHarry Wentland default: 1604562236bSHarry Wentland DC_ERR("DC: unexpected audio fuse!\n"); 16117a96033SJulia Lawall } 1624562236bSHarry Wentland } 1634562236bSHarry Wentland 1644562236bSHarry Wentland bool resource_construct( 1654562236bSHarry Wentland unsigned int num_virtual_links, 1664562236bSHarry Wentland struct core_dc *dc, 1674562236bSHarry Wentland struct resource_pool *pool, 1684562236bSHarry Wentland const struct resource_create_funcs *create_funcs) 1694562236bSHarry Wentland { 1704562236bSHarry Wentland struct dc_context *ctx = dc->ctx; 1714562236bSHarry Wentland const struct resource_caps *caps = pool->res_cap; 1724562236bSHarry Wentland int i; 1734562236bSHarry Wentland unsigned int num_audio = caps->num_audio; 1744562236bSHarry Wentland struct resource_straps straps = {0}; 1754562236bSHarry Wentland 1764562236bSHarry Wentland if (create_funcs->read_dce_straps) 1774562236bSHarry Wentland create_funcs->read_dce_straps(dc->ctx, &straps); 1784562236bSHarry Wentland 1794562236bSHarry Wentland pool->audio_count = 0; 1804562236bSHarry Wentland if (create_funcs->create_audio) { 1814562236bSHarry Wentland /* find the total number of streams available via the 1824562236bSHarry Wentland * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT 1834562236bSHarry Wentland * registers (one for each pin) starting from pin 1 1844562236bSHarry Wentland * up to the max number of audio pins. 1854562236bSHarry Wentland * We stop on the first pin where 1864562236bSHarry Wentland * PORT_CONNECTIVITY == 1 (as instructed by HW team). 1874562236bSHarry Wentland */ 1884562236bSHarry Wentland update_num_audio(&straps, &num_audio, &pool->audio_support); 1894562236bSHarry Wentland for (i = 0; i < pool->pipe_count && i < num_audio; i++) { 1904562236bSHarry Wentland struct audio *aud = create_funcs->create_audio(ctx, i); 1914562236bSHarry Wentland 1924562236bSHarry Wentland if (aud == NULL) { 1934562236bSHarry Wentland DC_ERR("DC: failed to create audio!\n"); 1944562236bSHarry Wentland return false; 1954562236bSHarry Wentland } 1964562236bSHarry Wentland 1974562236bSHarry Wentland if (!aud->funcs->endpoint_valid(aud)) { 1984562236bSHarry Wentland aud->funcs->destroy(&aud); 1994562236bSHarry Wentland break; 2004562236bSHarry Wentland } 2014562236bSHarry Wentland 2024562236bSHarry Wentland pool->audios[i] = aud; 2034562236bSHarry Wentland pool->audio_count++; 2044562236bSHarry Wentland } 2054562236bSHarry Wentland } 2064562236bSHarry Wentland 2074562236bSHarry Wentland pool->stream_enc_count = 0; 2084562236bSHarry Wentland if (create_funcs->create_stream_encoder) { 2094562236bSHarry Wentland for (i = 0; i < caps->num_stream_encoder; i++) { 2104562236bSHarry Wentland pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx); 2114562236bSHarry Wentland if (pool->stream_enc[i] == NULL) 2124562236bSHarry Wentland DC_ERR("DC: failed to create stream_encoder!\n"); 2134562236bSHarry Wentland pool->stream_enc_count++; 2144562236bSHarry Wentland } 2154562236bSHarry Wentland } 2164562236bSHarry Wentland 2174562236bSHarry Wentland for (i = 0; i < num_virtual_links; i++) { 2184562236bSHarry Wentland pool->stream_enc[pool->stream_enc_count] = 2194562236bSHarry Wentland virtual_stream_encoder_create( 2204562236bSHarry Wentland ctx, ctx->dc_bios); 2214562236bSHarry Wentland if (pool->stream_enc[pool->stream_enc_count] == NULL) { 2224562236bSHarry Wentland DC_ERR("DC: failed to create stream_encoder!\n"); 2234562236bSHarry Wentland return false; 2244562236bSHarry Wentland } 2254562236bSHarry Wentland pool->stream_enc_count++; 2264562236bSHarry Wentland } 2274562236bSHarry Wentland 2284562236bSHarry Wentland dc->hwseq = create_funcs->create_hwseq(ctx); 2294562236bSHarry Wentland 2304562236bSHarry Wentland return true; 2314562236bSHarry Wentland } 2324562236bSHarry Wentland 2334562236bSHarry Wentland 2344562236bSHarry Wentland void resource_unreference_clock_source( 2354562236bSHarry Wentland struct resource_context *res_ctx, 2368c737fccSYongqiang Sun struct clock_source **clock_source) 2374562236bSHarry Wentland { 2384562236bSHarry Wentland int i; 2394562236bSHarry Wentland for (i = 0; i < res_ctx->pool->clk_src_count; i++) { 2408c737fccSYongqiang Sun if (res_ctx->pool->clock_sources[i] != *clock_source) 2414562236bSHarry Wentland continue; 2424562236bSHarry Wentland 2434562236bSHarry Wentland res_ctx->clock_source_ref_count[i]--; 2444562236bSHarry Wentland 2454562236bSHarry Wentland if (res_ctx->clock_source_ref_count[i] == 0) 2468c737fccSYongqiang Sun (*clock_source)->funcs->cs_power_down(*clock_source); 2474562236bSHarry Wentland 2484562236bSHarry Wentland break; 2494562236bSHarry Wentland } 2504562236bSHarry Wentland 2518c737fccSYongqiang Sun if (res_ctx->pool->dp_clock_source == *clock_source) { 2524562236bSHarry Wentland res_ctx->dp_clock_source_ref_count--; 2534562236bSHarry Wentland 2544562236bSHarry Wentland if (res_ctx->dp_clock_source_ref_count == 0) 2558c737fccSYongqiang Sun (*clock_source)->funcs->cs_power_down(*clock_source); 2564562236bSHarry Wentland } 2578c737fccSYongqiang Sun *clock_source = NULL; 2584562236bSHarry Wentland } 2594562236bSHarry Wentland 2604562236bSHarry Wentland void resource_reference_clock_source( 2614562236bSHarry Wentland struct resource_context *res_ctx, 2624562236bSHarry Wentland struct clock_source *clock_source) 2634562236bSHarry Wentland { 2644562236bSHarry Wentland int i; 2654562236bSHarry Wentland for (i = 0; i < res_ctx->pool->clk_src_count; i++) { 2664562236bSHarry Wentland if (res_ctx->pool->clock_sources[i] != clock_source) 2674562236bSHarry Wentland continue; 2684562236bSHarry Wentland 2694562236bSHarry Wentland res_ctx->clock_source_ref_count[i]++; 2704562236bSHarry Wentland break; 2714562236bSHarry Wentland } 2724562236bSHarry Wentland 2734562236bSHarry Wentland if (res_ctx->pool->dp_clock_source == clock_source) 2744562236bSHarry Wentland res_ctx->dp_clock_source_ref_count++; 2754562236bSHarry Wentland } 2764562236bSHarry Wentland 2774562236bSHarry Wentland bool resource_are_streams_timing_synchronizable( 2784562236bSHarry Wentland const struct core_stream *stream1, 2794562236bSHarry Wentland const struct core_stream *stream2) 2804562236bSHarry Wentland { 2814562236bSHarry Wentland if (stream1->public.timing.h_total != stream2->public.timing.h_total) 2824562236bSHarry Wentland return false; 2834562236bSHarry Wentland 2844562236bSHarry Wentland if (stream1->public.timing.v_total != stream2->public.timing.v_total) 2854562236bSHarry Wentland return false; 2864562236bSHarry Wentland 2874562236bSHarry Wentland if (stream1->public.timing.h_addressable 2884562236bSHarry Wentland != stream2->public.timing.h_addressable) 2894562236bSHarry Wentland return false; 2904562236bSHarry Wentland 2914562236bSHarry Wentland if (stream1->public.timing.v_addressable 2924562236bSHarry Wentland != stream2->public.timing.v_addressable) 2934562236bSHarry Wentland return false; 2944562236bSHarry Wentland 2954562236bSHarry Wentland if (stream1->public.timing.pix_clk_khz 2964562236bSHarry Wentland != stream2->public.timing.pix_clk_khz) 2974562236bSHarry Wentland return false; 2984562236bSHarry Wentland 2994562236bSHarry Wentland if (stream1->phy_pix_clk != stream2->phy_pix_clk 3007e2fe319SCharlene Liu && (!dc_is_dp_signal(stream1->signal) 3017e2fe319SCharlene Liu || !dc_is_dp_signal(stream2->signal))) 3024562236bSHarry Wentland return false; 3034562236bSHarry Wentland 3044562236bSHarry Wentland return true; 3054562236bSHarry Wentland } 3064562236bSHarry Wentland 3074562236bSHarry Wentland static bool is_sharable_clk_src( 3084562236bSHarry Wentland const struct pipe_ctx *pipe_with_clk_src, 3094562236bSHarry Wentland const struct pipe_ctx *pipe) 3104562236bSHarry Wentland { 3114562236bSHarry Wentland if (pipe_with_clk_src->clock_source == NULL) 3124562236bSHarry Wentland return false; 3134562236bSHarry Wentland 3144562236bSHarry Wentland if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL) 3154562236bSHarry Wentland return false; 3164562236bSHarry Wentland 3174562236bSHarry Wentland if (dc_is_dp_signal(pipe_with_clk_src->stream->signal)) 3184562236bSHarry Wentland return false; 3194562236bSHarry Wentland 3204562236bSHarry Wentland if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal) 3214562236bSHarry Wentland && dc_is_dvi_signal(pipe->stream->signal)) 3224562236bSHarry Wentland return false; 3234562236bSHarry Wentland 3244562236bSHarry Wentland if (dc_is_hdmi_signal(pipe->stream->signal) 3254562236bSHarry Wentland && dc_is_dvi_signal(pipe_with_clk_src->stream->signal)) 3264562236bSHarry Wentland return false; 3274562236bSHarry Wentland 3284562236bSHarry Wentland if (!resource_are_streams_timing_synchronizable( 3294562236bSHarry Wentland pipe_with_clk_src->stream, pipe->stream)) 3304562236bSHarry Wentland return false; 3314562236bSHarry Wentland 3324562236bSHarry Wentland return true; 3334562236bSHarry Wentland } 3344562236bSHarry Wentland 3354562236bSHarry Wentland struct clock_source *resource_find_used_clk_src_for_sharing( 3364562236bSHarry Wentland struct resource_context *res_ctx, 3374562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 3384562236bSHarry Wentland { 3394562236bSHarry Wentland int i; 3404562236bSHarry Wentland 3414562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 3424562236bSHarry Wentland if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx)) 3434562236bSHarry Wentland return res_ctx->pipe_ctx[i].clock_source; 3444562236bSHarry Wentland } 3454562236bSHarry Wentland 3464562236bSHarry Wentland return NULL; 3474562236bSHarry Wentland } 3484562236bSHarry Wentland 3494562236bSHarry Wentland static enum pixel_format convert_pixel_format_to_dalsurface( 3504562236bSHarry Wentland enum surface_pixel_format surface_pixel_format) 3514562236bSHarry Wentland { 3524562236bSHarry Wentland enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 3534562236bSHarry Wentland 3544562236bSHarry Wentland switch (surface_pixel_format) { 3554562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 3564562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_INDEX8; 3574562236bSHarry Wentland break; 3584562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 3594562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_RGB565; 3604562236bSHarry Wentland break; 3614562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 3624562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_RGB565; 3634562236bSHarry Wentland break; 3644562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 3654562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB8888; 3664562236bSHarry Wentland break; 3678693049aSTony Cheng case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 3684562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB8888; 3694562236bSHarry Wentland break; 3704562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 3714562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 3724562236bSHarry Wentland break; 3734562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 3744562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 3754562236bSHarry Wentland break; 3764562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 3774562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS; 3784562236bSHarry Wentland break; 3794562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 3804562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 3814562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_FP16; 3824562236bSHarry Wentland break; 3834562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 3844562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 3854562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_420BPP12; 3864562236bSHarry Wentland break; 387ffbcd19aSVitaly Prosyak case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 388ffbcd19aSVitaly Prosyak case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 389ffbcd19aSVitaly Prosyak dal_pixel_format = PIXEL_FORMAT_420BPP15; 390ffbcd19aSVitaly Prosyak break; 3914562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 3924562236bSHarry Wentland default: 3934562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 3944562236bSHarry Wentland break; 3954562236bSHarry Wentland } 3964562236bSHarry Wentland return dal_pixel_format; 3974562236bSHarry Wentland } 3984562236bSHarry Wentland 3994562236bSHarry Wentland static void rect_swap_helper(struct rect *rect) 4004562236bSHarry Wentland { 4014562236bSHarry Wentland uint32_t temp = 0; 4024562236bSHarry Wentland 4034562236bSHarry Wentland temp = rect->height; 4044562236bSHarry Wentland rect->height = rect->width; 4054562236bSHarry Wentland rect->width = temp; 4064562236bSHarry Wentland 4074562236bSHarry Wentland temp = rect->x; 4084562236bSHarry Wentland rect->x = rect->y; 4094562236bSHarry Wentland rect->y = temp; 4104562236bSHarry Wentland } 4114562236bSHarry Wentland 412b2d0a103SDmytro Laktyushkin static void calculate_viewport(struct pipe_ctx *pipe_ctx) 4134562236bSHarry Wentland { 414b2d0a103SDmytro Laktyushkin const struct dc_surface *surface = &pipe_ctx->surface->public; 4151fbd2cfcSDmytro Laktyushkin const struct dc_stream *stream = &pipe_ctx->stream->public; 416b2d0a103SDmytro Laktyushkin struct scaler_data *data = &pipe_ctx->scl_data; 4174562236bSHarry Wentland struct rect clip = { 0 }; 418b2d0a103SDmytro Laktyushkin int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 419b2d0a103SDmytro Laktyushkin || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; 4201fbd2cfcSDmytro Laktyushkin bool pri_split = pipe_ctx->bottom_pipe && 4211fbd2cfcSDmytro Laktyushkin pipe_ctx->bottom_pipe->surface == pipe_ctx->surface; 4221fbd2cfcSDmytro Laktyushkin bool sec_split = pipe_ctx->top_pipe && 4231fbd2cfcSDmytro Laktyushkin pipe_ctx->top_pipe->surface == pipe_ctx->surface; 4244562236bSHarry Wentland 4257b779c99SVitaly Prosyak if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE || 4267b779c99SVitaly Prosyak stream->timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM) { 4277b779c99SVitaly Prosyak pri_split = false; 4287b779c99SVitaly Prosyak sec_split = false; 4297b779c99SVitaly Prosyak } 4304562236bSHarry Wentland /* The actual clip is an intersection between stream 4314562236bSHarry Wentland * source and surface clip 4324562236bSHarry Wentland */ 4331fbd2cfcSDmytro Laktyushkin clip.x = stream->src.x > surface->clip_rect.x ? 4341fbd2cfcSDmytro Laktyushkin stream->src.x : surface->clip_rect.x; 4354562236bSHarry Wentland 4361fbd2cfcSDmytro Laktyushkin clip.width = stream->src.x + stream->src.width < 4371fbd2cfcSDmytro Laktyushkin surface->clip_rect.x + surface->clip_rect.width ? 4381fbd2cfcSDmytro Laktyushkin stream->src.x + stream->src.width - clip.x : 4391fbd2cfcSDmytro Laktyushkin surface->clip_rect.x + surface->clip_rect.width - clip.x ; 4404562236bSHarry Wentland 4411fbd2cfcSDmytro Laktyushkin clip.y = stream->src.y > surface->clip_rect.y ? 4421fbd2cfcSDmytro Laktyushkin stream->src.y : surface->clip_rect.y; 4434562236bSHarry Wentland 4441fbd2cfcSDmytro Laktyushkin clip.height = stream->src.y + stream->src.height < 4451fbd2cfcSDmytro Laktyushkin surface->clip_rect.y + surface->clip_rect.height ? 4461fbd2cfcSDmytro Laktyushkin stream->src.y + stream->src.height - clip.y : 4471fbd2cfcSDmytro Laktyushkin surface->clip_rect.y + surface->clip_rect.height - clip.y ; 4484562236bSHarry Wentland 4491fbd2cfcSDmytro Laktyushkin /* offset = src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio 4504562236bSHarry Wentland * num_pixels = clip.num_pix * scl_ratio 4514562236bSHarry Wentland */ 4521fbd2cfcSDmytro Laktyushkin data->viewport.x = surface->src_rect.x + (clip.x - surface->dst_rect.x) * 4531fbd2cfcSDmytro Laktyushkin surface->src_rect.width / surface->dst_rect.width; 454b2d0a103SDmytro Laktyushkin data->viewport.width = clip.width * 4551fbd2cfcSDmytro Laktyushkin surface->src_rect.width / surface->dst_rect.width; 4564562236bSHarry Wentland 4571fbd2cfcSDmytro Laktyushkin data->viewport.y = surface->src_rect.y + (clip.y - surface->dst_rect.y) * 4581fbd2cfcSDmytro Laktyushkin surface->src_rect.height / surface->dst_rect.height; 459b2d0a103SDmytro Laktyushkin data->viewport.height = clip.height * 4601fbd2cfcSDmytro Laktyushkin surface->src_rect.height / surface->dst_rect.height; 4614562236bSHarry Wentland 462b2d0a103SDmytro Laktyushkin /* Round down, compensate in init */ 463b2d0a103SDmytro Laktyushkin data->viewport_c.x = data->viewport.x / vpc_div; 464b2d0a103SDmytro Laktyushkin data->viewport_c.y = data->viewport.y / vpc_div; 465b2d0a103SDmytro Laktyushkin data->inits.h_c = (data->viewport.x % vpc_div) != 0 ? 466b2d0a103SDmytro Laktyushkin dal_fixed31_32_half : dal_fixed31_32_zero; 467b2d0a103SDmytro Laktyushkin data->inits.v_c = (data->viewport.y % vpc_div) != 0 ? 468b2d0a103SDmytro Laktyushkin dal_fixed31_32_half : dal_fixed31_32_zero; 469b2d0a103SDmytro Laktyushkin /* Round up, assume original video size always even dimensions */ 470b2d0a103SDmytro Laktyushkin data->viewport_c.width = (data->viewport.width + vpc_div - 1) / vpc_div; 471b2d0a103SDmytro Laktyushkin data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; 472b2d0a103SDmytro Laktyushkin 473b2d0a103SDmytro Laktyushkin /* Handle hsplit */ 4741fbd2cfcSDmytro Laktyushkin if (pri_split || sec_split) { 4751fbd2cfcSDmytro Laktyushkin /* HMirror XOR Secondary_pipe XOR Rotation_180 */ 4761fbd2cfcSDmytro Laktyushkin bool right_view = (sec_split != surface->horizontal_mirror) != 4771fbd2cfcSDmytro Laktyushkin (surface->rotation == ROTATION_ANGLE_180); 4789e6c74ceSDmytro Laktyushkin 4791fbd2cfcSDmytro Laktyushkin if (surface->rotation == ROTATION_ANGLE_90 4801fbd2cfcSDmytro Laktyushkin || surface->rotation == ROTATION_ANGLE_270) 4811fbd2cfcSDmytro Laktyushkin /* Secondary_pipe XOR Rotation_270 */ 4821fbd2cfcSDmytro Laktyushkin right_view = (surface->rotation == ROTATION_ANGLE_270) != sec_split; 4839e6c74ceSDmytro Laktyushkin 4849e6c74ceSDmytro Laktyushkin if (right_view) { 485b2d0a103SDmytro Laktyushkin data->viewport.width /= 2; 486b2d0a103SDmytro Laktyushkin data->viewport_c.width /= 2; 487b2d0a103SDmytro Laktyushkin data->viewport.x += data->viewport.width; 488b2d0a103SDmytro Laktyushkin data->viewport_c.x += data->viewport_c.width; 4899e6c74ceSDmytro Laktyushkin /* Ceil offset pipe */ 490b2d0a103SDmytro Laktyushkin data->viewport.width += data->viewport.width % 2; 491b2d0a103SDmytro Laktyushkin data->viewport_c.width += data->viewport_c.width % 2; 4929e6c74ceSDmytro Laktyushkin } else { 493b2d0a103SDmytro Laktyushkin data->viewport.width /= 2; 494b2d0a103SDmytro Laktyushkin data->viewport_c.width /= 2; 495b2d0a103SDmytro Laktyushkin } 4964562236bSHarry Wentland } 4971fbd2cfcSDmytro Laktyushkin 4981fbd2cfcSDmytro Laktyushkin if (surface->rotation == ROTATION_ANGLE_90 || 4991fbd2cfcSDmytro Laktyushkin surface->rotation == ROTATION_ANGLE_270) { 5001fbd2cfcSDmytro Laktyushkin rect_swap_helper(&data->viewport_c); 5011fbd2cfcSDmytro Laktyushkin rect_swap_helper(&data->viewport); 5021fbd2cfcSDmytro Laktyushkin } 5039e6c74ceSDmytro Laktyushkin } 5044562236bSHarry Wentland 505b2d0a103SDmytro Laktyushkin static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip) 5064562236bSHarry Wentland { 507b2d0a103SDmytro Laktyushkin const struct dc_surface *surface = &pipe_ctx->surface->public; 5084562236bSHarry Wentland struct core_stream *stream = pipe_ctx->stream; 5094562236bSHarry Wentland struct rect clip = surface->clip_rect; 510c802570eSDmytro Laktyushkin int recout_full_x, recout_full_y; 5114562236bSHarry Wentland 5124562236bSHarry Wentland pipe_ctx->scl_data.recout.x = stream->public.dst.x; 5134562236bSHarry Wentland if (stream->public.src.x < clip.x) 5144562236bSHarry Wentland pipe_ctx->scl_data.recout.x += (clip.x 5154562236bSHarry Wentland - stream->public.src.x) * stream->public.dst.width 5164562236bSHarry Wentland / stream->public.src.width; 5174562236bSHarry Wentland 5184562236bSHarry Wentland pipe_ctx->scl_data.recout.width = clip.width * 5194562236bSHarry Wentland stream->public.dst.width / stream->public.src.width; 5204562236bSHarry Wentland if (pipe_ctx->scl_data.recout.width + pipe_ctx->scl_data.recout.x > 5214562236bSHarry Wentland stream->public.dst.x + stream->public.dst.width) 5224562236bSHarry Wentland pipe_ctx->scl_data.recout.width = 5234562236bSHarry Wentland stream->public.dst.x + stream->public.dst.width 5244562236bSHarry Wentland - pipe_ctx->scl_data.recout.x; 5254562236bSHarry Wentland 5264562236bSHarry Wentland pipe_ctx->scl_data.recout.y = stream->public.dst.y; 5274562236bSHarry Wentland if (stream->public.src.y < clip.y) 5284562236bSHarry Wentland pipe_ctx->scl_data.recout.y += (clip.y 5294562236bSHarry Wentland - stream->public.src.y) * stream->public.dst.height 5304562236bSHarry Wentland / stream->public.src.height; 5314562236bSHarry Wentland 5324562236bSHarry Wentland pipe_ctx->scl_data.recout.height = clip.height * 5334562236bSHarry Wentland stream->public.dst.height / stream->public.src.height; 5344562236bSHarry Wentland if (pipe_ctx->scl_data.recout.height + pipe_ctx->scl_data.recout.y > 5354562236bSHarry Wentland stream->public.dst.y + stream->public.dst.height) 5364562236bSHarry Wentland pipe_ctx->scl_data.recout.height = 5374562236bSHarry Wentland stream->public.dst.y + stream->public.dst.height 5384562236bSHarry Wentland - pipe_ctx->scl_data.recout.y; 539b2d0a103SDmytro Laktyushkin 5407b779c99SVitaly Prosyak /* Handle h & vsplit */ 5417b779c99SVitaly Prosyak if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == 5427b779c99SVitaly Prosyak pipe_ctx->surface) { 5437b779c99SVitaly Prosyak if (stream->public.timing.timing_3d_format == 5447b779c99SVitaly Prosyak TIMING_3D_FORMAT_TOP_AND_BOTTOM) { 5457b779c99SVitaly Prosyak pipe_ctx->scl_data.recout.height /= 2; 5467b779c99SVitaly Prosyak pipe_ctx->scl_data.recout.y += pipe_ctx->scl_data.recout.height; 5477b779c99SVitaly Prosyak /* Floor primary pipe, ceil 2ndary pipe */ 5487b779c99SVitaly Prosyak pipe_ctx->scl_data.recout.height += pipe_ctx->scl_data.recout.height % 2; 5497b779c99SVitaly Prosyak } else { 550b2d0a103SDmytro Laktyushkin pipe_ctx->scl_data.recout.width /= 2; 551b2d0a103SDmytro Laktyushkin pipe_ctx->scl_data.recout.x += pipe_ctx->scl_data.recout.width; 552b2d0a103SDmytro Laktyushkin pipe_ctx->scl_data.recout.width += pipe_ctx->scl_data.recout.width % 2; 5537b779c99SVitaly Prosyak } 5547b779c99SVitaly Prosyak } else if (pipe_ctx->bottom_pipe && 5557b779c99SVitaly Prosyak pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { 5567b779c99SVitaly Prosyak if (stream->public.timing.timing_3d_format == 5577b779c99SVitaly Prosyak TIMING_3D_FORMAT_TOP_AND_BOTTOM) 5587b779c99SVitaly Prosyak pipe_ctx->scl_data.recout.height /= 2; 5597b779c99SVitaly Prosyak else 560b2d0a103SDmytro Laktyushkin pipe_ctx->scl_data.recout.width /= 2; 5614562236bSHarry Wentland } 5624562236bSHarry Wentland 563c802570eSDmytro Laktyushkin /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream src offset) 564c802570eSDmytro Laktyushkin * * 1/ stream scaling ratio) - (surf src offset * 1/ full scl 565c802570eSDmytro Laktyushkin * ratio) 566c802570eSDmytro Laktyushkin */ 567c802570eSDmytro Laktyushkin recout_full_x = stream->public.dst.x + (surface->dst_rect.x - stream->public.src.x) 568c802570eSDmytro Laktyushkin * stream->public.dst.width / stream->public.src.width - 569c802570eSDmytro Laktyushkin surface->src_rect.x * surface->dst_rect.width / surface->src_rect.width 570c802570eSDmytro Laktyushkin * stream->public.dst.width / stream->public.src.width; 571c802570eSDmytro Laktyushkin recout_full_y = stream->public.dst.y + (surface->dst_rect.y - stream->public.src.y) 572c802570eSDmytro Laktyushkin * stream->public.dst.height / stream->public.src.height - 573c802570eSDmytro Laktyushkin surface->src_rect.y * surface->dst_rect.height / surface->src_rect.height 574c802570eSDmytro Laktyushkin * stream->public.dst.height / stream->public.src.height; 575c802570eSDmytro Laktyushkin 576c802570eSDmytro Laktyushkin recout_skip->width = pipe_ctx->scl_data.recout.x - recout_full_x; 577c802570eSDmytro Laktyushkin recout_skip->height = pipe_ctx->scl_data.recout.y - recout_full_y; 578b2d0a103SDmytro Laktyushkin } 579b2d0a103SDmytro Laktyushkin 580b2d0a103SDmytro Laktyushkin static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) 5814562236bSHarry Wentland { 582b2d0a103SDmytro Laktyushkin const struct dc_surface *surface = &pipe_ctx->surface->public; 5834562236bSHarry Wentland struct core_stream *stream = pipe_ctx->stream; 5841fbd2cfcSDmytro Laktyushkin const int in_w = stream->public.src.width; 5851fbd2cfcSDmytro Laktyushkin const int in_h = stream->public.src.height; 5861fbd2cfcSDmytro Laktyushkin const int out_w = stream->public.dst.width; 5871fbd2cfcSDmytro Laktyushkin const int out_h = stream->public.dst.height; 5884562236bSHarry Wentland 5894562236bSHarry Wentland pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction( 5904562236bSHarry Wentland surface->src_rect.width, 5914562236bSHarry Wentland surface->dst_rect.width); 5924562236bSHarry Wentland pipe_ctx->scl_data.ratios.vert = dal_fixed31_32_from_fraction( 5934562236bSHarry Wentland surface->src_rect.height, 5944562236bSHarry Wentland surface->dst_rect.height); 5954562236bSHarry Wentland 5964562236bSHarry Wentland if (surface->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE) 5974562236bSHarry Wentland pipe_ctx->scl_data.ratios.horz.value *= 2; 5984562236bSHarry Wentland else if (surface->stereo_format == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM) 5994562236bSHarry Wentland pipe_ctx->scl_data.ratios.vert.value *= 2; 6004562236bSHarry Wentland 6014562236bSHarry Wentland pipe_ctx->scl_data.ratios.vert.value = div64_s64( 6024562236bSHarry Wentland pipe_ctx->scl_data.ratios.vert.value * in_h, out_h); 6034562236bSHarry Wentland pipe_ctx->scl_data.ratios.horz.value = div64_s64( 6044562236bSHarry Wentland pipe_ctx->scl_data.ratios.horz.value * in_w, out_w); 6054562236bSHarry Wentland 6064562236bSHarry Wentland pipe_ctx->scl_data.ratios.horz_c = pipe_ctx->scl_data.ratios.horz; 6074562236bSHarry Wentland pipe_ctx->scl_data.ratios.vert_c = pipe_ctx->scl_data.ratios.vert; 6084562236bSHarry Wentland 609b2d0a103SDmytro Laktyushkin if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP12 610b2d0a103SDmytro Laktyushkin || pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP15) { 6114562236bSHarry Wentland pipe_ctx->scl_data.ratios.horz_c.value /= 2; 6124562236bSHarry Wentland pipe_ctx->scl_data.ratios.vert_c.value /= 2; 6134562236bSHarry Wentland } 6144562236bSHarry Wentland } 6154562236bSHarry Wentland 616b2d0a103SDmytro Laktyushkin static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *recout_skip) 6174562236bSHarry Wentland { 618b2d0a103SDmytro Laktyushkin struct scaler_data *data = &pipe_ctx->scl_data; 619b2d0a103SDmytro Laktyushkin struct rect src = pipe_ctx->surface->public.src_rect; 620b2d0a103SDmytro Laktyushkin int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 621b2d0a103SDmytro Laktyushkin || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; 622b2d0a103SDmytro Laktyushkin 6231fbd2cfcSDmytro Laktyushkin if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || 6241fbd2cfcSDmytro Laktyushkin pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) { 6251fbd2cfcSDmytro Laktyushkin rect_swap_helper(&data->viewport_c); 6261fbd2cfcSDmytro Laktyushkin rect_swap_helper(&data->viewport); 6271fbd2cfcSDmytro Laktyushkin } 6281fbd2cfcSDmytro Laktyushkin 629b2d0a103SDmytro Laktyushkin /* 630b2d0a103SDmytro Laktyushkin * Init calculated according to formula: 631b2d0a103SDmytro Laktyushkin * init = (scaling_ratio + number_of_taps + 1) / 2 632b2d0a103SDmytro Laktyushkin * init_bot = init + scaling_ratio 633b2d0a103SDmytro Laktyushkin * init_c = init + truncated_vp_c_offset(from calculate viewport) 634b2d0a103SDmytro Laktyushkin */ 635b2d0a103SDmytro Laktyushkin data->inits.h = dal_fixed31_32_div_int( 636b2d0a103SDmytro Laktyushkin dal_fixed31_32_add_int(data->ratios.horz, data->taps.h_taps + 1), 2); 637b2d0a103SDmytro Laktyushkin 638b2d0a103SDmytro Laktyushkin data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_div_int( 639b2d0a103SDmytro Laktyushkin dal_fixed31_32_add_int(data->ratios.horz_c, data->taps.h_taps_c + 1), 2)); 640b2d0a103SDmytro Laktyushkin 641b2d0a103SDmytro Laktyushkin data->inits.v = dal_fixed31_32_div_int( 642b2d0a103SDmytro Laktyushkin dal_fixed31_32_add_int(data->ratios.vert, data->taps.v_taps + 1), 2); 643b2d0a103SDmytro Laktyushkin 644b2d0a103SDmytro Laktyushkin data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_div_int( 645b2d0a103SDmytro Laktyushkin dal_fixed31_32_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2)); 646b2d0a103SDmytro Laktyushkin 647b2d0a103SDmytro Laktyushkin 648b2d0a103SDmytro Laktyushkin /* Adjust for viewport end clip-off */ 649b2d0a103SDmytro Laktyushkin if ((data->viewport.x + data->viewport.width) < (src.x + src.width)) { 650b2d0a103SDmytro Laktyushkin int vp_clip = src.x + src.width - data->viewport.width - data->viewport.x; 6511fbd2cfcSDmytro Laktyushkin int int_part = dal_fixed31_32_floor( 6521fbd2cfcSDmytro Laktyushkin dal_fixed31_32_sub(data->inits.h, data->ratios.horz)); 653b2d0a103SDmytro Laktyushkin 6541fbd2cfcSDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 655b2d0a103SDmytro Laktyushkin data->viewport.width += int_part < vp_clip ? int_part : vp_clip; 656b2d0a103SDmytro Laktyushkin } 657b2d0a103SDmytro Laktyushkin if ((data->viewport.y + data->viewport.height) < (src.y + src.height)) { 658b2d0a103SDmytro Laktyushkin int vp_clip = src.y + src.height - data->viewport.height - data->viewport.y; 6591fbd2cfcSDmytro Laktyushkin int int_part = dal_fixed31_32_floor( 6601fbd2cfcSDmytro Laktyushkin dal_fixed31_32_sub(data->inits.v, data->ratios.vert)); 661b2d0a103SDmytro Laktyushkin 6621fbd2cfcSDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 663b2d0a103SDmytro Laktyushkin data->viewport.height += int_part < vp_clip ? int_part : vp_clip; 664b2d0a103SDmytro Laktyushkin } 665b2d0a103SDmytro Laktyushkin if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div) { 666b2d0a103SDmytro Laktyushkin int vp_clip = (src.x + src.width) / vpc_div - 667b2d0a103SDmytro Laktyushkin data->viewport_c.width - data->viewport_c.x; 6681fbd2cfcSDmytro Laktyushkin int int_part = dal_fixed31_32_floor( 6691fbd2cfcSDmytro Laktyushkin dal_fixed31_32_sub(data->inits.h_c, data->ratios.horz_c)); 670b2d0a103SDmytro Laktyushkin 6711fbd2cfcSDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 672b2d0a103SDmytro Laktyushkin data->viewport_c.width += int_part < vp_clip ? int_part : vp_clip; 673b2d0a103SDmytro Laktyushkin } 674b2d0a103SDmytro Laktyushkin if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div) { 675b2d0a103SDmytro Laktyushkin int vp_clip = (src.y + src.height) / vpc_div - 676b2d0a103SDmytro Laktyushkin data->viewport_c.height - data->viewport_c.y; 6771fbd2cfcSDmytro Laktyushkin int int_part = dal_fixed31_32_floor( 6781fbd2cfcSDmytro Laktyushkin dal_fixed31_32_sub(data->inits.v_c, data->ratios.vert_c)); 679b2d0a103SDmytro Laktyushkin 6801fbd2cfcSDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 681b2d0a103SDmytro Laktyushkin data->viewport_c.height += int_part < vp_clip ? int_part : vp_clip; 682b2d0a103SDmytro Laktyushkin } 683b2d0a103SDmytro Laktyushkin 684b2d0a103SDmytro Laktyushkin /* Adjust for non-0 viewport offset */ 685b2d0a103SDmytro Laktyushkin if (data->viewport.x) { 686b2d0a103SDmytro Laktyushkin int int_part; 687b2d0a103SDmytro Laktyushkin 688b2d0a103SDmytro Laktyushkin data->inits.h = dal_fixed31_32_add(data->inits.h, dal_fixed31_32_mul_int( 689b2d0a103SDmytro Laktyushkin data->ratios.horz, recout_skip->width)); 690b2d0a103SDmytro Laktyushkin int_part = dal_fixed31_32_floor(data->inits.h) - data->viewport.x; 691b2d0a103SDmytro Laktyushkin if (int_part < data->taps.h_taps) { 692b2d0a103SDmytro Laktyushkin int int_adj = data->viewport.x >= (data->taps.h_taps - int_part) ? 693b2d0a103SDmytro Laktyushkin (data->taps.h_taps - int_part) : data->viewport.x; 694b2d0a103SDmytro Laktyushkin data->viewport.x -= int_adj; 695b2d0a103SDmytro Laktyushkin data->viewport.width += int_adj; 696b2d0a103SDmytro Laktyushkin int_part += int_adj; 697b2d0a103SDmytro Laktyushkin } else if (int_part > data->taps.h_taps) { 698b2d0a103SDmytro Laktyushkin data->viewport.x += int_part - data->taps.h_taps; 699b2d0a103SDmytro Laktyushkin data->viewport.width -= int_part - data->taps.h_taps; 700b2d0a103SDmytro Laktyushkin int_part = data->taps.h_taps; 701b2d0a103SDmytro Laktyushkin } 702b2d0a103SDmytro Laktyushkin data->inits.h.value &= 0xffffffff; 703b2d0a103SDmytro Laktyushkin data->inits.h = dal_fixed31_32_add_int(data->inits.h, int_part); 704b2d0a103SDmytro Laktyushkin } 705b2d0a103SDmytro Laktyushkin 706b2d0a103SDmytro Laktyushkin if (data->viewport_c.x) { 707b2d0a103SDmytro Laktyushkin int int_part; 708b2d0a103SDmytro Laktyushkin 709b2d0a103SDmytro Laktyushkin data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_mul_int( 710b2d0a103SDmytro Laktyushkin data->ratios.horz_c, recout_skip->width)); 711b2d0a103SDmytro Laktyushkin int_part = dal_fixed31_32_floor(data->inits.h_c) - data->viewport_c.x; 712b2d0a103SDmytro Laktyushkin if (int_part < data->taps.h_taps_c) { 713b2d0a103SDmytro Laktyushkin int int_adj = data->viewport_c.x >= (data->taps.h_taps_c - int_part) ? 714b2d0a103SDmytro Laktyushkin (data->taps.h_taps_c - int_part) : data->viewport_c.x; 715b2d0a103SDmytro Laktyushkin data->viewport_c.x -= int_adj; 716b2d0a103SDmytro Laktyushkin data->viewport_c.width += int_adj; 717b2d0a103SDmytro Laktyushkin int_part += int_adj; 718b2d0a103SDmytro Laktyushkin } else if (int_part > data->taps.h_taps_c) { 719b2d0a103SDmytro Laktyushkin data->viewport_c.x += int_part - data->taps.h_taps_c; 720b2d0a103SDmytro Laktyushkin data->viewport_c.width -= int_part - data->taps.h_taps_c; 721b2d0a103SDmytro Laktyushkin int_part = data->taps.h_taps_c; 722b2d0a103SDmytro Laktyushkin } 723b2d0a103SDmytro Laktyushkin data->inits.h_c.value &= 0xffffffff; 724b2d0a103SDmytro Laktyushkin data->inits.h_c = dal_fixed31_32_add_int(data->inits.h_c, int_part); 725b2d0a103SDmytro Laktyushkin } 726b2d0a103SDmytro Laktyushkin 727b2d0a103SDmytro Laktyushkin if (data->viewport.y) { 728b2d0a103SDmytro Laktyushkin int int_part; 729b2d0a103SDmytro Laktyushkin 730b2d0a103SDmytro Laktyushkin data->inits.v = dal_fixed31_32_add(data->inits.v, dal_fixed31_32_mul_int( 731b2d0a103SDmytro Laktyushkin data->ratios.vert, recout_skip->height)); 732b2d0a103SDmytro Laktyushkin int_part = dal_fixed31_32_floor(data->inits.v) - data->viewport.y; 733b2d0a103SDmytro Laktyushkin if (int_part < data->taps.v_taps) { 734b2d0a103SDmytro Laktyushkin int int_adj = data->viewport.y >= (data->taps.v_taps - int_part) ? 735b2d0a103SDmytro Laktyushkin (data->taps.v_taps - int_part) : data->viewport.y; 736b2d0a103SDmytro Laktyushkin data->viewport.y -= int_adj; 737b2d0a103SDmytro Laktyushkin data->viewport.height += int_adj; 738b2d0a103SDmytro Laktyushkin int_part += int_adj; 739b2d0a103SDmytro Laktyushkin } else if (int_part > data->taps.v_taps) { 740b2d0a103SDmytro Laktyushkin data->viewport.y += int_part - data->taps.v_taps; 741b2d0a103SDmytro Laktyushkin data->viewport.height -= int_part - data->taps.v_taps; 742b2d0a103SDmytro Laktyushkin int_part = data->taps.v_taps; 743b2d0a103SDmytro Laktyushkin } 744b2d0a103SDmytro Laktyushkin data->inits.v.value &= 0xffffffff; 745b2d0a103SDmytro Laktyushkin data->inits.v = dal_fixed31_32_add_int(data->inits.v, int_part); 746b2d0a103SDmytro Laktyushkin } 747b2d0a103SDmytro Laktyushkin 748b2d0a103SDmytro Laktyushkin if (data->viewport_c.y) { 749b2d0a103SDmytro Laktyushkin int int_part; 750b2d0a103SDmytro Laktyushkin 751b2d0a103SDmytro Laktyushkin data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_mul_int( 752b2d0a103SDmytro Laktyushkin data->ratios.vert_c, recout_skip->height)); 753b2d0a103SDmytro Laktyushkin int_part = dal_fixed31_32_floor(data->inits.v_c) - data->viewport_c.y; 754b2d0a103SDmytro Laktyushkin if (int_part < data->taps.v_taps_c) { 755b2d0a103SDmytro Laktyushkin int int_adj = data->viewport_c.y >= (data->taps.v_taps_c - int_part) ? 756b2d0a103SDmytro Laktyushkin (data->taps.v_taps_c - int_part) : data->viewport_c.y; 757b2d0a103SDmytro Laktyushkin data->viewport_c.y -= int_adj; 758b2d0a103SDmytro Laktyushkin data->viewport_c.height += int_adj; 759b2d0a103SDmytro Laktyushkin int_part += int_adj; 760b2d0a103SDmytro Laktyushkin } else if (int_part > data->taps.v_taps_c) { 761b2d0a103SDmytro Laktyushkin data->viewport_c.y += int_part - data->taps.v_taps_c; 762b2d0a103SDmytro Laktyushkin data->viewport_c.height -= int_part - data->taps.v_taps_c; 763b2d0a103SDmytro Laktyushkin int_part = data->taps.v_taps_c; 764b2d0a103SDmytro Laktyushkin } 765b2d0a103SDmytro Laktyushkin data->inits.v_c.value &= 0xffffffff; 766b2d0a103SDmytro Laktyushkin data->inits.v_c = dal_fixed31_32_add_int(data->inits.v_c, int_part); 767b2d0a103SDmytro Laktyushkin } 768b2d0a103SDmytro Laktyushkin 769b2d0a103SDmytro Laktyushkin /* Interlaced inits based on final vert inits */ 770b2d0a103SDmytro Laktyushkin data->inits.v_bot = dal_fixed31_32_add(data->inits.v, data->ratios.vert); 771b2d0a103SDmytro Laktyushkin data->inits.v_c_bot = dal_fixed31_32_add(data->inits.v_c, data->ratios.vert_c); 7721fbd2cfcSDmytro Laktyushkin 7731fbd2cfcSDmytro Laktyushkin if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || 7741fbd2cfcSDmytro Laktyushkin pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) { 7751fbd2cfcSDmytro Laktyushkin rect_swap_helper(&data->viewport_c); 7761fbd2cfcSDmytro Laktyushkin rect_swap_helper(&data->viewport); 7771fbd2cfcSDmytro Laktyushkin } 778b2d0a103SDmytro Laktyushkin } 779b2d0a103SDmytro Laktyushkin 780b2d0a103SDmytro Laktyushkin bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) 781b2d0a103SDmytro Laktyushkin { 782b2d0a103SDmytro Laktyushkin const struct dc_surface *surface = &pipe_ctx->surface->public; 7834562236bSHarry Wentland struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing; 784b2d0a103SDmytro Laktyushkin struct view recout_skip = { 0 }; 785b2d0a103SDmytro Laktyushkin bool res = false; 786b2d0a103SDmytro Laktyushkin 7874562236bSHarry Wentland /* Important: scaling ratio calculation requires pixel format, 7884562236bSHarry Wentland * lb depth calculation requires recout and taps require scaling ratios. 789b2d0a103SDmytro Laktyushkin * Inits require viewport, taps, ratios and recout of split pipe 7904562236bSHarry Wentland */ 791b2d0a103SDmytro Laktyushkin pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface( 792b2d0a103SDmytro Laktyushkin pipe_ctx->surface->public.format); 7934562236bSHarry Wentland 794b2d0a103SDmytro Laktyushkin calculate_scaling_ratios(pipe_ctx); 795b2d0a103SDmytro Laktyushkin 796b2d0a103SDmytro Laktyushkin calculate_viewport(pipe_ctx); 7974562236bSHarry Wentland 7984562236bSHarry Wentland if (pipe_ctx->scl_data.viewport.height < 16 || pipe_ctx->scl_data.viewport.width < 16) 7994562236bSHarry Wentland return false; 8004562236bSHarry Wentland 801b2d0a103SDmytro Laktyushkin calculate_recout(pipe_ctx, &recout_skip); 8024562236bSHarry Wentland 8034562236bSHarry Wentland /** 8044562236bSHarry Wentland * Setting line buffer pixel depth to 24bpp yields banding 8054562236bSHarry Wentland * on certain displays, such as the Sharp 4k 8064562236bSHarry Wentland */ 8074562236bSHarry Wentland pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; 8084562236bSHarry Wentland 8094562236bSHarry Wentland pipe_ctx->scl_data.h_active = timing->h_addressable; 8104562236bSHarry Wentland pipe_ctx->scl_data.v_active = timing->v_addressable; 8114562236bSHarry Wentland 8124562236bSHarry Wentland /* Taps calculations */ 8134562236bSHarry Wentland res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps( 8144562236bSHarry Wentland pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality); 8154562236bSHarry Wentland 8164562236bSHarry Wentland if (!res) { 8174562236bSHarry Wentland /* Try 24 bpp linebuffer */ 8184562236bSHarry Wentland pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; 8194562236bSHarry Wentland 8204562236bSHarry Wentland res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps( 8214562236bSHarry Wentland pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality); 8224562236bSHarry Wentland } 8234562236bSHarry Wentland 824b2d0a103SDmytro Laktyushkin if (res) 8251fbd2cfcSDmytro Laktyushkin /* May need to re-check lb size after this in some obscure scenario */ 826b2d0a103SDmytro Laktyushkin calculate_inits_and_adj_vp(pipe_ctx, &recout_skip); 827b2d0a103SDmytro Laktyushkin 8284562236bSHarry Wentland dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_SCALER, 8294562236bSHarry Wentland "%s: Viewport:\nheight:%d width:%d x:%d " 8304562236bSHarry Wentland "y:%d\n dst_rect:\nheight:%d width:%d x:%d " 8314562236bSHarry Wentland "y:%d\n", 8324562236bSHarry Wentland __func__, 8334562236bSHarry Wentland pipe_ctx->scl_data.viewport.height, 8344562236bSHarry Wentland pipe_ctx->scl_data.viewport.width, 8354562236bSHarry Wentland pipe_ctx->scl_data.viewport.x, 8364562236bSHarry Wentland pipe_ctx->scl_data.viewport.y, 8374562236bSHarry Wentland surface->dst_rect.height, 8384562236bSHarry Wentland surface->dst_rect.width, 8394562236bSHarry Wentland surface->dst_rect.x, 8404562236bSHarry Wentland surface->dst_rect.y); 8414562236bSHarry Wentland 8424562236bSHarry Wentland return res; 8434562236bSHarry Wentland } 8444562236bSHarry Wentland 8454562236bSHarry Wentland 8464562236bSHarry Wentland enum dc_status resource_build_scaling_params_for_context( 8474562236bSHarry Wentland const struct core_dc *dc, 8484562236bSHarry Wentland struct validate_context *context) 8494562236bSHarry Wentland { 8504562236bSHarry Wentland int i; 8514562236bSHarry Wentland 8524562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 8534562236bSHarry Wentland if (context->res_ctx.pipe_ctx[i].surface != NULL && 8544562236bSHarry Wentland context->res_ctx.pipe_ctx[i].stream != NULL) 855b2d0a103SDmytro Laktyushkin if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i])) 856f84a8161STony Cheng return DC_FAIL_SCALING; 8574562236bSHarry Wentland } 8584562236bSHarry Wentland 8594562236bSHarry Wentland return DC_OK; 8604562236bSHarry Wentland } 8614562236bSHarry Wentland 862ab2541b6SAric Cyr static void detach_surfaces_for_stream( 8634562236bSHarry Wentland struct validate_context *context, 864ab2541b6SAric Cyr const struct dc_stream *dc_stream) 8654562236bSHarry Wentland { 8664562236bSHarry Wentland int i; 867ab2541b6SAric Cyr struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); 8684562236bSHarry Wentland 8694562236bSHarry Wentland for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { 8704562236bSHarry Wentland struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i]; 8714562236bSHarry Wentland if (cur_pipe->stream == stream) { 8724562236bSHarry Wentland cur_pipe->surface = NULL; 8734562236bSHarry Wentland cur_pipe->top_pipe = NULL; 8744562236bSHarry Wentland cur_pipe->bottom_pipe = NULL; 8754562236bSHarry Wentland } 8764562236bSHarry Wentland } 8774562236bSHarry Wentland } 8784562236bSHarry Wentland 8794562236bSHarry Wentland struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx) 8804562236bSHarry Wentland { 8814562236bSHarry Wentland int i; 8824562236bSHarry Wentland struct pipe_ctx *secondary_pipe = NULL; 8834562236bSHarry Wentland 8844562236bSHarry Wentland /* 8854562236bSHarry Wentland * search backwards for the second pipe to keep pipe 8864562236bSHarry Wentland * assignment more consistent 8874562236bSHarry Wentland */ 8884562236bSHarry Wentland 8894562236bSHarry Wentland for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) { 8904562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == NULL) { 8914562236bSHarry Wentland secondary_pipe = &res_ctx->pipe_ctx[i]; 8924562236bSHarry Wentland secondary_pipe->pipe_idx = i; 8934562236bSHarry Wentland break; 8944562236bSHarry Wentland } 8954562236bSHarry Wentland } 8964562236bSHarry Wentland 8974562236bSHarry Wentland 8984562236bSHarry Wentland return secondary_pipe; 8994562236bSHarry Wentland } 9004562236bSHarry Wentland 9014562236bSHarry Wentland struct pipe_ctx *resource_get_head_pipe_for_stream( 9024562236bSHarry Wentland struct resource_context *res_ctx, 9034562236bSHarry Wentland const struct core_stream *stream) 9044562236bSHarry Wentland { 9054562236bSHarry Wentland int i; 9064562236bSHarry Wentland for (i = 0; i < res_ctx->pool->pipe_count; i++) { 9074562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == stream && 908e73c1efcSYongqiang Sun res_ctx->pipe_ctx[i].stream_enc) { 9094562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 9104562236bSHarry Wentland break; 9114562236bSHarry Wentland } 9124562236bSHarry Wentland } 9134562236bSHarry Wentland return NULL; 9144562236bSHarry Wentland } 9154562236bSHarry Wentland 9164562236bSHarry Wentland /* 917ab2541b6SAric Cyr * A free_pipe for a stream is defined here as a pipe 918ab2541b6SAric Cyr * that has no surface attached yet 9194562236bSHarry Wentland */ 920ab2541b6SAric Cyr static struct pipe_ctx *acquire_free_pipe_for_stream( 921745cc746SDmytro Laktyushkin struct validate_context *context, 922ab2541b6SAric Cyr const struct dc_stream *dc_stream) 9234562236bSHarry Wentland { 9244562236bSHarry Wentland int i; 925745cc746SDmytro Laktyushkin struct resource_context *res_ctx = &context->res_ctx; 926ab2541b6SAric Cyr struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); 9274562236bSHarry Wentland 9284562236bSHarry Wentland struct pipe_ctx *head_pipe = NULL; 9294562236bSHarry Wentland 9304562236bSHarry Wentland /* Find head pipe, which has the back end set up*/ 9314562236bSHarry Wentland 9324562236bSHarry Wentland head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream); 9334562236bSHarry Wentland 9344562236bSHarry Wentland if (!head_pipe) 9354562236bSHarry Wentland ASSERT(0); 9364562236bSHarry Wentland 9374562236bSHarry Wentland if (!head_pipe->surface) 9384562236bSHarry Wentland return head_pipe; 9394562236bSHarry Wentland 9404562236bSHarry Wentland /* Re-use pipe already acquired for this stream if available*/ 9414562236bSHarry Wentland for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) { 9424562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == stream && 9434562236bSHarry Wentland !res_ctx->pipe_ctx[i].surface) { 9444562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 9454562236bSHarry Wentland } 9464562236bSHarry Wentland } 9474562236bSHarry Wentland 9484562236bSHarry Wentland /* 9494562236bSHarry Wentland * At this point we have no re-useable pipe for this stream and we need 9504562236bSHarry Wentland * to acquire an idle one to satisfy the request 9514562236bSHarry Wentland */ 9524562236bSHarry Wentland 9534562236bSHarry Wentland if(!res_ctx->pool->funcs->acquire_idle_pipe_for_layer) 9544562236bSHarry Wentland return NULL; 9554562236bSHarry Wentland 956745cc746SDmytro Laktyushkin return res_ctx->pool->funcs->acquire_idle_pipe_for_layer(context, stream); 9574562236bSHarry Wentland 9584562236bSHarry Wentland } 9594562236bSHarry Wentland 960ab2541b6SAric Cyr static void release_free_pipes_for_stream( 9614562236bSHarry Wentland struct resource_context *res_ctx, 962ab2541b6SAric Cyr const struct dc_stream *dc_stream) 9634562236bSHarry Wentland { 9644562236bSHarry Wentland int i; 965ab2541b6SAric Cyr struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); 9664562236bSHarry Wentland 9674562236bSHarry Wentland for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) { 9684562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == stream && 9694562236bSHarry Wentland !res_ctx->pipe_ctx[i].surface) { 9704562236bSHarry Wentland res_ctx->pipe_ctx[i].stream = NULL; 9714562236bSHarry Wentland } 9724562236bSHarry Wentland } 9734562236bSHarry Wentland } 9744562236bSHarry Wentland 9754562236bSHarry Wentland bool resource_attach_surfaces_to_context( 9764562236bSHarry Wentland const struct dc_surface * const *surfaces, 9774562236bSHarry Wentland int surface_count, 978ab2541b6SAric Cyr const struct dc_stream *dc_stream, 9794562236bSHarry Wentland struct validate_context *context) 9804562236bSHarry Wentland { 9814562236bSHarry Wentland int i; 9824562236bSHarry Wentland struct pipe_ctx *tail_pipe; 983ab2541b6SAric Cyr struct dc_stream_status *stream_status = NULL; 9844562236bSHarry Wentland 9854562236bSHarry Wentland 9864562236bSHarry Wentland if (surface_count > MAX_SURFACE_NUM) { 9874562236bSHarry Wentland dm_error("Surface: can not attach %d surfaces! Maximum is: %d\n", 9884562236bSHarry Wentland surface_count, MAX_SURFACE_NUM); 9894562236bSHarry Wentland return false; 9904562236bSHarry Wentland } 9914562236bSHarry Wentland 992ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) 993ab2541b6SAric Cyr if (&context->streams[i]->public == dc_stream) { 994ab2541b6SAric Cyr stream_status = &context->stream_status[i]; 9954562236bSHarry Wentland break; 9964562236bSHarry Wentland } 997ab2541b6SAric Cyr if (stream_status == NULL) { 998ab2541b6SAric Cyr dm_error("Existing stream not found; failed to attach surfaces\n"); 9994562236bSHarry Wentland return false; 10004562236bSHarry Wentland } 10014562236bSHarry Wentland 10024562236bSHarry Wentland /* retain new surfaces */ 10034562236bSHarry Wentland for (i = 0; i < surface_count; i++) 10044562236bSHarry Wentland dc_surface_retain(surfaces[i]); 10054562236bSHarry Wentland 1006ab2541b6SAric Cyr detach_surfaces_for_stream(context, dc_stream); 10074562236bSHarry Wentland 10084562236bSHarry Wentland /* release existing surfaces*/ 1009ab2541b6SAric Cyr for (i = 0; i < stream_status->surface_count; i++) 1010ab2541b6SAric Cyr dc_surface_release(stream_status->surfaces[i]); 10114562236bSHarry Wentland 1012ab2541b6SAric Cyr for (i = surface_count; i < stream_status->surface_count; i++) 1013ab2541b6SAric Cyr stream_status->surfaces[i] = NULL; 10144562236bSHarry Wentland 1015ab2541b6SAric Cyr stream_status->surface_count = 0; 10164562236bSHarry Wentland 10174562236bSHarry Wentland if (surface_count == 0) 10184562236bSHarry Wentland return true; 10194562236bSHarry Wentland 10204562236bSHarry Wentland tail_pipe = NULL; 10214562236bSHarry Wentland for (i = 0; i < surface_count; i++) { 10224562236bSHarry Wentland struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]); 1023745cc746SDmytro Laktyushkin struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream(context, dc_stream); 10244562236bSHarry Wentland 10254562236bSHarry Wentland if (!free_pipe) { 1026ab2541b6SAric Cyr stream_status->surfaces[i] = NULL; 10274562236bSHarry Wentland return false; 10284562236bSHarry Wentland } 10294562236bSHarry Wentland 10304562236bSHarry Wentland free_pipe->surface = surface; 10314562236bSHarry Wentland 10324562236bSHarry Wentland if (tail_pipe) { 10334562236bSHarry Wentland free_pipe->top_pipe = tail_pipe; 10344562236bSHarry Wentland tail_pipe->bottom_pipe = free_pipe; 10354562236bSHarry Wentland } 10364562236bSHarry Wentland 10374562236bSHarry Wentland tail_pipe = free_pipe; 10384562236bSHarry Wentland } 10394562236bSHarry Wentland 1040ab2541b6SAric Cyr release_free_pipes_for_stream(&context->res_ctx, dc_stream); 10414562236bSHarry Wentland 10424562236bSHarry Wentland /* assign new surfaces*/ 10434562236bSHarry Wentland for (i = 0; i < surface_count; i++) 1044ab2541b6SAric Cyr stream_status->surfaces[i] = surfaces[i]; 10454562236bSHarry Wentland 1046ab2541b6SAric Cyr stream_status->surface_count = surface_count; 10474562236bSHarry Wentland 10484562236bSHarry Wentland return true; 10494562236bSHarry Wentland } 10504562236bSHarry Wentland 10514562236bSHarry Wentland 10524562236bSHarry Wentland static bool is_timing_changed(const struct core_stream *cur_stream, 10534562236bSHarry Wentland const struct core_stream *new_stream) 10544562236bSHarry Wentland { 10554562236bSHarry Wentland if (cur_stream == NULL) 10564562236bSHarry Wentland return true; 10574562236bSHarry Wentland 10584562236bSHarry Wentland /* If sink pointer changed, it means this is a hotplug, we should do 10594562236bSHarry Wentland * full hw setting. 10604562236bSHarry Wentland */ 10614562236bSHarry Wentland if (cur_stream->sink != new_stream->sink) 10624562236bSHarry Wentland return true; 10634562236bSHarry Wentland 10644562236bSHarry Wentland /* If output color space is changed, need to reprogram info frames */ 10654562236bSHarry Wentland if (cur_stream->public.output_color_space != 10664562236bSHarry Wentland new_stream->public.output_color_space) 10674562236bSHarry Wentland return true; 10684562236bSHarry Wentland 10694562236bSHarry Wentland return memcmp( 10704562236bSHarry Wentland &cur_stream->public.timing, 10714562236bSHarry Wentland &new_stream->public.timing, 10724562236bSHarry Wentland sizeof(struct dc_crtc_timing)) != 0; 10734562236bSHarry Wentland } 10744562236bSHarry Wentland 10754562236bSHarry Wentland static bool are_stream_backends_same( 10764562236bSHarry Wentland const struct core_stream *stream_a, const struct core_stream *stream_b) 10774562236bSHarry Wentland { 10784562236bSHarry Wentland if (stream_a == stream_b) 10794562236bSHarry Wentland return true; 10804562236bSHarry Wentland 10814562236bSHarry Wentland if (stream_a == NULL || stream_b == NULL) 10824562236bSHarry Wentland return false; 10834562236bSHarry Wentland 10844562236bSHarry Wentland if (is_timing_changed(stream_a, stream_b)) 10854562236bSHarry Wentland return false; 10864562236bSHarry Wentland 10874562236bSHarry Wentland return true; 10884562236bSHarry Wentland } 10894562236bSHarry Wentland 1090ab2541b6SAric Cyr bool is_stream_unchanged( 1091ab2541b6SAric Cyr const struct core_stream *old_stream, const struct core_stream *stream) 10924562236bSHarry Wentland { 10934562236bSHarry Wentland 10944562236bSHarry Wentland if (!are_stream_backends_same(old_stream, stream)) 10954562236bSHarry Wentland return false; 10964562236bSHarry Wentland 10974562236bSHarry Wentland return true; 10984562236bSHarry Wentland } 10994562236bSHarry Wentland 11004562236bSHarry Wentland bool resource_validate_attach_surfaces( 11014562236bSHarry Wentland const struct dc_validation_set set[], 11024562236bSHarry Wentland int set_count, 11034562236bSHarry Wentland const struct validate_context *old_context, 11044562236bSHarry Wentland struct validate_context *context) 11054562236bSHarry Wentland { 11064562236bSHarry Wentland int i, j; 11074562236bSHarry Wentland 11084562236bSHarry Wentland for (i = 0; i < set_count; i++) { 1109ab2541b6SAric Cyr for (j = 0; j < old_context->stream_count; j++) 1110ab2541b6SAric Cyr if (is_stream_unchanged( 1111ab2541b6SAric Cyr old_context->streams[j], 1112ab2541b6SAric Cyr context->streams[i])) { 11134562236bSHarry Wentland if (!resource_attach_surfaces_to_context( 1114ab2541b6SAric Cyr old_context->stream_status[j].surfaces, 1115ab2541b6SAric Cyr old_context->stream_status[j].surface_count, 1116ab2541b6SAric Cyr &context->streams[i]->public, 11174562236bSHarry Wentland context)) 11184562236bSHarry Wentland return false; 1119ab2541b6SAric Cyr context->stream_status[i] = old_context->stream_status[j]; 11204562236bSHarry Wentland } 11214562236bSHarry Wentland if (set[i].surface_count != 0) 11224562236bSHarry Wentland if (!resource_attach_surfaces_to_context( 11234562236bSHarry Wentland set[i].surfaces, 11244562236bSHarry Wentland set[i].surface_count, 1125ab2541b6SAric Cyr &context->streams[i]->public, 11264562236bSHarry Wentland context)) 11274562236bSHarry Wentland return false; 11284562236bSHarry Wentland 11294562236bSHarry Wentland } 11304562236bSHarry Wentland 11314562236bSHarry Wentland return true; 11324562236bSHarry Wentland } 11334562236bSHarry Wentland 11344562236bSHarry Wentland /* Maximum TMDS single link pixel clock 165MHz */ 11354562236bSHarry Wentland #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000 11364562236bSHarry Wentland 11374562236bSHarry Wentland static void set_stream_engine_in_use( 11384562236bSHarry Wentland struct resource_context *res_ctx, 11394562236bSHarry Wentland struct stream_encoder *stream_enc) 11404562236bSHarry Wentland { 11414562236bSHarry Wentland int i; 11424562236bSHarry Wentland 11434562236bSHarry Wentland for (i = 0; i < res_ctx->pool->stream_enc_count; i++) { 11444562236bSHarry Wentland if (res_ctx->pool->stream_enc[i] == stream_enc) 11454562236bSHarry Wentland res_ctx->is_stream_enc_acquired[i] = true; 11464562236bSHarry Wentland } 11474562236bSHarry Wentland } 11484562236bSHarry Wentland 11494562236bSHarry Wentland /* TODO: release audio object */ 11504562236bSHarry Wentland static void set_audio_in_use( 11514562236bSHarry Wentland struct resource_context *res_ctx, 11524562236bSHarry Wentland struct audio *audio) 11534562236bSHarry Wentland { 11544562236bSHarry Wentland int i; 11554562236bSHarry Wentland for (i = 0; i < res_ctx->pool->audio_count; i++) { 11564562236bSHarry Wentland if (res_ctx->pool->audios[i] == audio) { 11574562236bSHarry Wentland res_ctx->is_audio_acquired[i] = true; 11584562236bSHarry Wentland } 11594562236bSHarry Wentland } 11604562236bSHarry Wentland } 11614562236bSHarry Wentland 11624562236bSHarry Wentland static int acquire_first_free_pipe( 11634562236bSHarry Wentland struct resource_context *res_ctx, 11644562236bSHarry Wentland struct core_stream *stream) 11654562236bSHarry Wentland { 11664562236bSHarry Wentland int i; 11674562236bSHarry Wentland 11684562236bSHarry Wentland for (i = 0; i < res_ctx->pool->pipe_count; i++) { 11694562236bSHarry Wentland if (!res_ctx->pipe_ctx[i].stream) { 11704562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 11714562236bSHarry Wentland 11724562236bSHarry Wentland pipe_ctx->tg = res_ctx->pool->timing_generators[i]; 11734562236bSHarry Wentland pipe_ctx->mi = res_ctx->pool->mis[i]; 11744562236bSHarry Wentland pipe_ctx->ipp = res_ctx->pool->ipps[i]; 11754562236bSHarry Wentland pipe_ctx->xfm = res_ctx->pool->transforms[i]; 11764562236bSHarry Wentland pipe_ctx->opp = res_ctx->pool->opps[i]; 11774562236bSHarry Wentland pipe_ctx->dis_clk = res_ctx->pool->display_clock; 11784562236bSHarry Wentland pipe_ctx->pipe_idx = i; 11794562236bSHarry Wentland 11804562236bSHarry Wentland pipe_ctx->stream = stream; 11814562236bSHarry Wentland return i; 11824562236bSHarry Wentland } 11834562236bSHarry Wentland } 11844562236bSHarry Wentland return -1; 11854562236bSHarry Wentland } 11864562236bSHarry Wentland 11874562236bSHarry Wentland static struct stream_encoder *find_first_free_match_stream_enc_for_link( 11884562236bSHarry Wentland struct resource_context *res_ctx, 11894562236bSHarry Wentland struct core_stream *stream) 11904562236bSHarry Wentland { 11914562236bSHarry Wentland int i; 11924562236bSHarry Wentland int j = -1; 11934562236bSHarry Wentland struct core_link *link = stream->sink->link; 11944562236bSHarry Wentland 11954562236bSHarry Wentland for (i = 0; i < res_ctx->pool->stream_enc_count; i++) { 11964562236bSHarry Wentland if (!res_ctx->is_stream_enc_acquired[i] && 11974562236bSHarry Wentland res_ctx->pool->stream_enc[i]) { 11984562236bSHarry Wentland /* Store first available for MST second display 11994562236bSHarry Wentland * in daisy chain use case */ 12004562236bSHarry Wentland j = i; 12014562236bSHarry Wentland if (res_ctx->pool->stream_enc[i]->id == 12024562236bSHarry Wentland link->link_enc->preferred_engine) 12034562236bSHarry Wentland return res_ctx->pool->stream_enc[i]; 12044562236bSHarry Wentland } 12054562236bSHarry Wentland } 12064562236bSHarry Wentland 12074562236bSHarry Wentland /* 12084562236bSHarry Wentland * below can happen in cases when stream encoder is acquired: 12094562236bSHarry Wentland * 1) for second MST display in chain, so preferred engine already 12104562236bSHarry Wentland * acquired; 12114562236bSHarry Wentland * 2) for another link, which preferred engine already acquired by any 12124562236bSHarry Wentland * MST configuration. 12134562236bSHarry Wentland * 12144562236bSHarry Wentland * If signal is of DP type and preferred engine not found, return last available 12154562236bSHarry Wentland * 12164562236bSHarry Wentland * TODO - This is just a patch up and a generic solution is 12174562236bSHarry Wentland * required for non DP connectors. 12184562236bSHarry Wentland */ 12194562236bSHarry Wentland 12204562236bSHarry Wentland if (j >= 0 && dc_is_dp_signal(stream->signal)) 12214562236bSHarry Wentland return res_ctx->pool->stream_enc[j]; 12224562236bSHarry Wentland 12234562236bSHarry Wentland return NULL; 12244562236bSHarry Wentland } 12254562236bSHarry Wentland 12264562236bSHarry Wentland static struct audio *find_first_free_audio(struct resource_context *res_ctx) 12274562236bSHarry Wentland { 12284562236bSHarry Wentland int i; 12294562236bSHarry Wentland for (i = 0; i < res_ctx->pool->audio_count; i++) { 12304562236bSHarry Wentland if (res_ctx->is_audio_acquired[i] == false) { 12314562236bSHarry Wentland return res_ctx->pool->audios[i]; 12324562236bSHarry Wentland } 12334562236bSHarry Wentland } 12344562236bSHarry Wentland 12354562236bSHarry Wentland return 0; 12364562236bSHarry Wentland } 12374562236bSHarry Wentland 12384562236bSHarry Wentland static void update_stream_signal(struct core_stream *stream) 12394562236bSHarry Wentland { 12404562236bSHarry Wentland const struct dc_sink *dc_sink = stream->public.sink; 12414562236bSHarry Wentland 12422796eaeeSJoshua Aberback if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) 12432796eaeeSJoshua Aberback stream->signal = stream->sink->link->public.connector_signal; 12442796eaeeSJoshua Aberback else if (dc_sink->sink_signal == SIGNAL_TYPE_DVI_SINGLE_LINK || 12452796eaeeSJoshua Aberback dc_sink->sink_signal == SIGNAL_TYPE_DVI_DUAL_LINK) 12464562236bSHarry Wentland /* For asic supports dual link DVI, we should adjust signal type 12474562236bSHarry Wentland * based on timing pixel clock. If pixel clock more than 165Mhz, 12484562236bSHarry Wentland * signal is dual link, otherwise, single link. 12494562236bSHarry Wentland */ 12502796eaeeSJoshua Aberback if (stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ) 12514562236bSHarry Wentland stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; 12524562236bSHarry Wentland else 12534562236bSHarry Wentland stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; 12542796eaeeSJoshua Aberback else 12552796eaeeSJoshua Aberback stream->signal = dc_sink->sink_signal; 12564562236bSHarry Wentland } 12574562236bSHarry Wentland 12584562236bSHarry Wentland bool resource_is_stream_unchanged( 1259ab2541b6SAric Cyr const struct validate_context *old_context, const struct core_stream *stream) 12604562236bSHarry Wentland { 1261ab2541b6SAric Cyr int i; 12624562236bSHarry Wentland 1263ab2541b6SAric Cyr for (i = 0; i < old_context->stream_count; i++) { 1264ab2541b6SAric Cyr const struct core_stream *old_stream = old_context->streams[i]; 12654562236bSHarry Wentland 12664562236bSHarry Wentland if (are_stream_backends_same(old_stream, stream)) 12674562236bSHarry Wentland return true; 12684562236bSHarry Wentland } 12694562236bSHarry Wentland 12704562236bSHarry Wentland return false; 12714562236bSHarry Wentland } 12724562236bSHarry Wentland 12734562236bSHarry Wentland static void copy_pipe_ctx( 12744562236bSHarry Wentland const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx) 12754562236bSHarry Wentland { 12764562236bSHarry Wentland struct core_surface *surface = to_pipe_ctx->surface; 12774562236bSHarry Wentland struct core_stream *stream = to_pipe_ctx->stream; 12784562236bSHarry Wentland 12794562236bSHarry Wentland *to_pipe_ctx = *from_pipe_ctx; 12804562236bSHarry Wentland to_pipe_ctx->stream = stream; 12814562236bSHarry Wentland if (surface != NULL) 12824562236bSHarry Wentland to_pipe_ctx->surface = surface; 12834562236bSHarry Wentland } 12844562236bSHarry Wentland 12854562236bSHarry Wentland static struct core_stream *find_pll_sharable_stream( 12864562236bSHarry Wentland const struct core_stream *stream_needs_pll, 12874562236bSHarry Wentland struct validate_context *context) 12884562236bSHarry Wentland { 1289ab2541b6SAric Cyr int i; 12904562236bSHarry Wentland 1291ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 1292ab2541b6SAric Cyr struct core_stream *stream_has_pll = context->streams[i]; 12934562236bSHarry Wentland 12944562236bSHarry Wentland /* We are looking for non dp, non virtual stream */ 12954562236bSHarry Wentland if (resource_are_streams_timing_synchronizable( 12964562236bSHarry Wentland stream_needs_pll, stream_has_pll) 12974562236bSHarry Wentland && !dc_is_dp_signal(stream_has_pll->signal) 12984562236bSHarry Wentland && stream_has_pll->sink->link->public.connector_signal 12994562236bSHarry Wentland != SIGNAL_TYPE_VIRTUAL) 13004562236bSHarry Wentland return stream_has_pll; 1301ab2541b6SAric Cyr 13024562236bSHarry Wentland } 13034562236bSHarry Wentland 13044562236bSHarry Wentland return NULL; 13054562236bSHarry Wentland } 13064562236bSHarry Wentland 13074562236bSHarry Wentland static int get_norm_pix_clk(const struct dc_crtc_timing *timing) 13084562236bSHarry Wentland { 13094562236bSHarry Wentland uint32_t pix_clk = timing->pix_clk_khz; 13104562236bSHarry Wentland uint32_t normalized_pix_clk = pix_clk; 13114562236bSHarry Wentland 13124562236bSHarry Wentland if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) 13134562236bSHarry Wentland pix_clk /= 2; 1314cc4d99b8SCharlene Liu if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) { 13154562236bSHarry Wentland switch (timing->display_color_depth) { 13164562236bSHarry Wentland case COLOR_DEPTH_888: 13174562236bSHarry Wentland normalized_pix_clk = pix_clk; 13184562236bSHarry Wentland break; 13194562236bSHarry Wentland case COLOR_DEPTH_101010: 13204562236bSHarry Wentland normalized_pix_clk = (pix_clk * 30) / 24; 13214562236bSHarry Wentland break; 13224562236bSHarry Wentland case COLOR_DEPTH_121212: 13234562236bSHarry Wentland normalized_pix_clk = (pix_clk * 36) / 24; 13244562236bSHarry Wentland break; 13254562236bSHarry Wentland case COLOR_DEPTH_161616: 13264562236bSHarry Wentland normalized_pix_clk = (pix_clk * 48) / 24; 13274562236bSHarry Wentland break; 13284562236bSHarry Wentland default: 13294562236bSHarry Wentland ASSERT(0); 13304562236bSHarry Wentland break; 13314562236bSHarry Wentland } 1332cc4d99b8SCharlene Liu } 13334562236bSHarry Wentland return normalized_pix_clk; 13344562236bSHarry Wentland } 13354562236bSHarry Wentland 13364562236bSHarry Wentland static void calculate_phy_pix_clks( 13374562236bSHarry Wentland const struct core_dc *dc, 13384562236bSHarry Wentland struct validate_context *context) 13394562236bSHarry Wentland { 1340ab2541b6SAric Cyr int i; 13414562236bSHarry Wentland 1342ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 1343ab2541b6SAric Cyr struct core_stream *stream = context->streams[i]; 13444562236bSHarry Wentland 13454562236bSHarry Wentland update_stream_signal(stream); 13464562236bSHarry Wentland 13474562236bSHarry Wentland /* update actual pixel clock on all streams */ 13484562236bSHarry Wentland if (dc_is_hdmi_signal(stream->signal)) 13494562236bSHarry Wentland stream->phy_pix_clk = get_norm_pix_clk( 13504562236bSHarry Wentland &stream->public.timing); 13514562236bSHarry Wentland else 13524562236bSHarry Wentland stream->phy_pix_clk = 13534562236bSHarry Wentland stream->public.timing.pix_clk_khz; 13544562236bSHarry Wentland } 13554562236bSHarry Wentland } 13564562236bSHarry Wentland 13574562236bSHarry Wentland enum dc_status resource_map_pool_resources( 13584562236bSHarry Wentland const struct core_dc *dc, 13594562236bSHarry Wentland struct validate_context *context) 13604562236bSHarry Wentland { 1361ab2541b6SAric Cyr int i, j; 13624562236bSHarry Wentland 13634562236bSHarry Wentland calculate_phy_pix_clks(dc, context); 13644562236bSHarry Wentland 1365ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 1366ab2541b6SAric Cyr struct core_stream *stream = context->streams[i]; 13674562236bSHarry Wentland 13684b679bc3SCharlene Liu if (!resource_is_stream_unchanged(dc->current_context, stream)) { 13694b679bc3SCharlene Liu if (stream != NULL && dc->current_context->streams[i] != NULL) { 13704b679bc3SCharlene Liu stream->bit_depth_params = 13714b679bc3SCharlene Liu dc->current_context->streams[i]->bit_depth_params; 13724b679bc3SCharlene Liu stream->clamping = dc->current_context->streams[i]->clamping; 13734562236bSHarry Wentland continue; 13744b679bc3SCharlene Liu } 13754b679bc3SCharlene Liu } 13767e2fe319SCharlene Liu 13774562236bSHarry Wentland /* mark resources used for stream that is already active */ 1378ab2541b6SAric Cyr for (j = 0; j < MAX_PIPES; j++) { 13794562236bSHarry Wentland struct pipe_ctx *pipe_ctx = 1380ab2541b6SAric Cyr &context->res_ctx.pipe_ctx[j]; 13814562236bSHarry Wentland const struct pipe_ctx *old_pipe_ctx = 1382ab2541b6SAric Cyr &dc->current_context->res_ctx.pipe_ctx[j]; 13834562236bSHarry Wentland 13844562236bSHarry Wentland if (!are_stream_backends_same(old_pipe_ctx->stream, stream)) 13854562236bSHarry Wentland continue; 13864562236bSHarry Wentland 1387268cadbdSYongqiang Sun if (old_pipe_ctx->top_pipe) 1388268cadbdSYongqiang Sun continue; 1389268cadbdSYongqiang Sun 13904562236bSHarry Wentland pipe_ctx->stream = stream; 13914562236bSHarry Wentland copy_pipe_ctx(old_pipe_ctx, pipe_ctx); 13924562236bSHarry Wentland 13938c737fccSYongqiang Sun /* Split pipe resource, do not acquire back end */ 13948c737fccSYongqiang Sun if (!pipe_ctx->stream_enc) 13958c737fccSYongqiang Sun continue; 13968c737fccSYongqiang Sun 13974562236bSHarry Wentland set_stream_engine_in_use( 13984562236bSHarry Wentland &context->res_ctx, 13994562236bSHarry Wentland pipe_ctx->stream_enc); 14004562236bSHarry Wentland 14014562236bSHarry Wentland /* Switch to dp clock source only if there is 14024562236bSHarry Wentland * no non dp stream that shares the same timing 14034562236bSHarry Wentland * with the dp stream. 14044562236bSHarry Wentland */ 14054562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal) && 14064562236bSHarry Wentland !find_pll_sharable_stream(stream, context)) 14074562236bSHarry Wentland pipe_ctx->clock_source = 14084562236bSHarry Wentland context->res_ctx.pool->dp_clock_source; 14094562236bSHarry Wentland 14104562236bSHarry Wentland resource_reference_clock_source( 14114562236bSHarry Wentland &context->res_ctx, 14124562236bSHarry Wentland pipe_ctx->clock_source); 14134562236bSHarry Wentland 14144562236bSHarry Wentland set_audio_in_use(&context->res_ctx, 14154562236bSHarry Wentland pipe_ctx->audio); 14164562236bSHarry Wentland } 14174562236bSHarry Wentland } 14184562236bSHarry Wentland 1419ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 1420ab2541b6SAric Cyr struct core_stream *stream = context->streams[i]; 14214562236bSHarry Wentland struct pipe_ctx *pipe_ctx = NULL; 14224562236bSHarry Wentland int pipe_idx = -1; 14234562236bSHarry Wentland 14244562236bSHarry Wentland if (resource_is_stream_unchanged(dc->current_context, stream)) 14254562236bSHarry Wentland continue; 14264562236bSHarry Wentland /* acquire new resources */ 1427ab2541b6SAric Cyr pipe_idx = acquire_first_free_pipe(&context->res_ctx, stream); 14284562236bSHarry Wentland if (pipe_idx < 0) 14294562236bSHarry Wentland return DC_NO_CONTROLLER_RESOURCE; 14304562236bSHarry Wentland 14314562236bSHarry Wentland 14324562236bSHarry Wentland pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; 14334562236bSHarry Wentland 14344562236bSHarry Wentland pipe_ctx->stream_enc = 14354562236bSHarry Wentland find_first_free_match_stream_enc_for_link( 14364562236bSHarry Wentland &context->res_ctx, stream); 14374562236bSHarry Wentland 14384562236bSHarry Wentland if (!pipe_ctx->stream_enc) 14394562236bSHarry Wentland return DC_NO_STREAM_ENG_RESOURCE; 14404562236bSHarry Wentland 14414562236bSHarry Wentland set_stream_engine_in_use( 14424562236bSHarry Wentland &context->res_ctx, 14434562236bSHarry Wentland pipe_ctx->stream_enc); 14444562236bSHarry Wentland 14454562236bSHarry Wentland /* TODO: Add check if ASIC support and EDID audio */ 14464a9a5d62SZeyu Fan if (!stream->sink->public.converter_disable_audio && 14474562236bSHarry Wentland dc_is_audio_capable_signal(pipe_ctx->stream->signal) && 14484562236bSHarry Wentland stream->public.audio_info.mode_count) { 14494562236bSHarry Wentland pipe_ctx->audio = find_first_free_audio( 14504562236bSHarry Wentland &context->res_ctx); 14514562236bSHarry Wentland 14524562236bSHarry Wentland /* 14534562236bSHarry Wentland * Audio assigned in order first come first get. 14544562236bSHarry Wentland * There are asics which has number of audio 14554562236bSHarry Wentland * resources less then number of pipes 14564562236bSHarry Wentland */ 14574562236bSHarry Wentland if (pipe_ctx->audio) 14584562236bSHarry Wentland set_audio_in_use( 14594562236bSHarry Wentland &context->res_ctx, 14604562236bSHarry Wentland pipe_ctx->audio); 14614562236bSHarry Wentland } 14624562236bSHarry Wentland 1463ab2541b6SAric Cyr context->stream_status[i].primary_otg_inst = pipe_ctx->tg->inst; 14644562236bSHarry Wentland } 14654562236bSHarry Wentland 14664562236bSHarry Wentland return DC_OK; 14674562236bSHarry Wentland } 14684562236bSHarry Wentland 1469ab2541b6SAric Cyr /* first stream in the context is used to populate the rest */ 1470ab2541b6SAric Cyr void validate_guaranteed_copy_streams( 14714562236bSHarry Wentland struct validate_context *context, 1472ab2541b6SAric Cyr int max_streams) 14734562236bSHarry Wentland { 14744562236bSHarry Wentland int i; 14754562236bSHarry Wentland 1476ab2541b6SAric Cyr for (i = 1; i < max_streams; i++) { 1477ab2541b6SAric Cyr context->streams[i] = context->streams[0]; 14784562236bSHarry Wentland 14794562236bSHarry Wentland copy_pipe_ctx(&context->res_ctx.pipe_ctx[0], 14804562236bSHarry Wentland &context->res_ctx.pipe_ctx[i]); 14814562236bSHarry Wentland context->res_ctx.pipe_ctx[i].stream = 14824562236bSHarry Wentland context->res_ctx.pipe_ctx[0].stream; 14834562236bSHarry Wentland 1484ab2541b6SAric Cyr dc_stream_retain(&context->streams[i]->public); 1485ab2541b6SAric Cyr context->stream_count++; 14864562236bSHarry Wentland } 14874562236bSHarry Wentland } 14884562236bSHarry Wentland 14896e4d6beeSTony Cheng static void patch_gamut_packet_checksum( 14906e4d6beeSTony Cheng struct encoder_info_packet *gamut_packet) 14914562236bSHarry Wentland { 14924562236bSHarry Wentland /* For gamut we recalc checksum */ 14936e4d6beeSTony Cheng if (gamut_packet->valid) { 14944562236bSHarry Wentland uint8_t chk_sum = 0; 14954562236bSHarry Wentland uint8_t *ptr; 14964562236bSHarry Wentland uint8_t i; 14974562236bSHarry Wentland 14984562236bSHarry Wentland /*start of the Gamut data. */ 14996e4d6beeSTony Cheng ptr = &gamut_packet->sb[3]; 15004562236bSHarry Wentland 15016e4d6beeSTony Cheng for (i = 0; i <= gamut_packet->sb[1]; i++) 15024562236bSHarry Wentland chk_sum += ptr[i]; 15034562236bSHarry Wentland 15046e4d6beeSTony Cheng gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum); 15051646a6feSAndrew Wong } 15064562236bSHarry Wentland } 15074562236bSHarry Wentland 15084562236bSHarry Wentland static void set_avi_info_frame( 15096e4d6beeSTony Cheng struct encoder_info_packet *info_packet, 15104562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 15114562236bSHarry Wentland { 15124562236bSHarry Wentland struct core_stream *stream = pipe_ctx->stream; 15134562236bSHarry Wentland enum dc_color_space color_space = COLOR_SPACE_UNKNOWN; 15144562236bSHarry Wentland struct info_frame info_frame = { {0} }; 15154562236bSHarry Wentland uint32_t pixel_encoding = 0; 15164562236bSHarry Wentland enum scanning_type scan_type = SCANNING_TYPE_NODATA; 15174562236bSHarry Wentland enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA; 15184562236bSHarry Wentland bool itc = false; 15194562236bSHarry Wentland uint8_t cn0_cn1 = 0; 15204562236bSHarry Wentland uint8_t *check_sum = NULL; 15214562236bSHarry Wentland uint8_t byte_index = 0; 15224562236bSHarry Wentland 15234562236bSHarry Wentland color_space = pipe_ctx->stream->public.output_color_space; 15244562236bSHarry Wentland 15254562236bSHarry Wentland /* Initialize header */ 15264562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.header. 15273e183c5fSDave Airlie info_frame_type = HDMI_INFOFRAME_TYPE_AVI; 15284562236bSHarry Wentland /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall 15294562236bSHarry Wentland * not be used in HDMI 2.0 (Section 10.1) */ 15303e183c5fSDave Airlie info_frame.avi_info_packet.info_packet_hdmi.bits.header.version = 2; 15314562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.header.length = 15323e183c5fSDave Airlie HDMI_AVI_INFOFRAME_SIZE; 15334562236bSHarry Wentland 15344562236bSHarry Wentland /* 15354562236bSHarry Wentland * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built 15364562236bSHarry Wentland * according to HDMI 2.0 spec (Section 10.1) 15374562236bSHarry Wentland */ 15384562236bSHarry Wentland 15394562236bSHarry Wentland switch (stream->public.timing.pixel_encoding) { 15404562236bSHarry Wentland case PIXEL_ENCODING_YCBCR422: 15414562236bSHarry Wentland pixel_encoding = 1; 15424562236bSHarry Wentland break; 15434562236bSHarry Wentland 15444562236bSHarry Wentland case PIXEL_ENCODING_YCBCR444: 15454562236bSHarry Wentland pixel_encoding = 2; 15464562236bSHarry Wentland break; 15474562236bSHarry Wentland case PIXEL_ENCODING_YCBCR420: 15484562236bSHarry Wentland pixel_encoding = 3; 15494562236bSHarry Wentland break; 15504562236bSHarry Wentland 15514562236bSHarry Wentland case PIXEL_ENCODING_RGB: 15524562236bSHarry Wentland default: 15534562236bSHarry Wentland pixel_encoding = 0; 15544562236bSHarry Wentland } 15554562236bSHarry Wentland 15564562236bSHarry Wentland /* Y0_Y1_Y2 : The pixel encoding */ 15574562236bSHarry Wentland /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */ 15584562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.Y0_Y1_Y2 = 15594562236bSHarry Wentland pixel_encoding; 15604562236bSHarry Wentland 15614562236bSHarry Wentland /* A0 = 1 Active Format Information valid */ 15624562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.A0 = 15634562236bSHarry Wentland ACTIVE_FORMAT_VALID; 15644562236bSHarry Wentland 15654562236bSHarry Wentland /* B0, B1 = 3; Bar info data is valid */ 15664562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.B0_B1 = 15674562236bSHarry Wentland BAR_INFO_BOTH_VALID; 15684562236bSHarry Wentland 15694562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.SC0_SC1 = 15704562236bSHarry Wentland PICTURE_SCALING_UNIFORM; 15714562236bSHarry Wentland 15724562236bSHarry Wentland /* S0, S1 : Underscan / Overscan */ 15734562236bSHarry Wentland /* TODO: un-hardcode scan type */ 15744562236bSHarry Wentland scan_type = SCANNING_TYPE_UNDERSCAN; 15754562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.S0_S1 = scan_type; 15764562236bSHarry Wentland 15774562236bSHarry Wentland /* C0, C1 : Colorimetry */ 15788fde5884SCharlene Liu if (color_space == COLOR_SPACE_YCBCR709 || 15798fde5884SCharlene Liu color_space == COLOR_SPACE_YCBCR709_LIMITED) 15804562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = 15814562236bSHarry Wentland COLORIMETRY_ITU709; 15828fde5884SCharlene Liu else if (color_space == COLOR_SPACE_YCBCR601 || 15838fde5884SCharlene Liu color_space == COLOR_SPACE_YCBCR601_LIMITED) 15844562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = 15854562236bSHarry Wentland COLORIMETRY_ITU601; 15868fde5884SCharlene Liu else { 15878fde5884SCharlene Liu if (stream->public.timing.pixel_encoding != PIXEL_ENCODING_RGB) 15888fde5884SCharlene Liu BREAK_TO_DEBUGGER(); 15894562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = 15904562236bSHarry Wentland COLORIMETRY_NO_DATA; 15918fde5884SCharlene Liu } 1592534db198SAmy Zhang if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE || 1593534db198SAmy Zhang color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE || 1594534db198SAmy Zhang color_space == COLOR_SPACE_2020_YCBCR) { 1595534db198SAmy Zhang info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 = 1596534db198SAmy Zhang COLORIMETRYEX_BT2020RGBYCBCR; 1597534db198SAmy Zhang info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = 1598534db198SAmy Zhang COLORIMETRY_EXTENDED; 1599534db198SAmy Zhang } else if (color_space == COLOR_SPACE_ADOBERGB) { 1600534db198SAmy Zhang info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 = 1601534db198SAmy Zhang COLORIMETRYEX_ADOBERGB; 1602534db198SAmy Zhang info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = 1603534db198SAmy Zhang COLORIMETRY_EXTENDED; 1604534db198SAmy Zhang } 1605534db198SAmy Zhang 16064562236bSHarry Wentland /* TODO: un-hardcode aspect ratio */ 16074562236bSHarry Wentland aspect = stream->public.timing.aspect_ratio; 16084562236bSHarry Wentland 16094562236bSHarry Wentland switch (aspect) { 16104562236bSHarry Wentland case ASPECT_RATIO_4_3: 16114562236bSHarry Wentland case ASPECT_RATIO_16_9: 16124562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = aspect; 16134562236bSHarry Wentland break; 16144562236bSHarry Wentland 16154562236bSHarry Wentland case ASPECT_RATIO_NO_DATA: 16164562236bSHarry Wentland case ASPECT_RATIO_64_27: 16174562236bSHarry Wentland case ASPECT_RATIO_256_135: 16184562236bSHarry Wentland default: 16194562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = 0; 16204562236bSHarry Wentland } 16214562236bSHarry Wentland 16224562236bSHarry Wentland /* Active Format Aspect ratio - same as Picture Aspect Ratio. */ 16234562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.R0_R3 = 16244562236bSHarry Wentland ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; 16254562236bSHarry Wentland 16264562236bSHarry Wentland /* TODO: un-hardcode cn0_cn1 and itc */ 16274562236bSHarry Wentland cn0_cn1 = 0; 16284562236bSHarry Wentland itc = false; 16294562236bSHarry Wentland 16304562236bSHarry Wentland if (itc) { 16314562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.ITC = 1; 16324562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.CN0_CN1 = 16334562236bSHarry Wentland cn0_cn1; 16344562236bSHarry Wentland } 16354562236bSHarry Wentland 16364562236bSHarry Wentland /* TODO : We should handle YCC quantization */ 16374562236bSHarry Wentland /* but we do not have matrix calculation */ 16384562236bSHarry Wentland if (color_space == COLOR_SPACE_SRGB) { 16394562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = 16404562236bSHarry Wentland RGB_QUANTIZATION_FULL_RANGE; 16414562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 = 16424562236bSHarry Wentland YYC_QUANTIZATION_FULL_RANGE; 16434562236bSHarry Wentland } else if (color_space == COLOR_SPACE_SRGB_LIMITED) { 16444562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = 16454562236bSHarry Wentland RGB_QUANTIZATION_LIMITED_RANGE; 16464562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 = 16474562236bSHarry Wentland YYC_QUANTIZATION_LIMITED_RANGE; 16484562236bSHarry Wentland } else { 16494562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = 16504562236bSHarry Wentland RGB_QUANTIZATION_DEFAULT_RANGE; 16514562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 = 16524562236bSHarry Wentland YYC_QUANTIZATION_LIMITED_RANGE; 16534562236bSHarry Wentland } 16544562236bSHarry Wentland 16554562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.VIC0_VIC7 = 16564562236bSHarry Wentland stream->public.timing.vic; 16574562236bSHarry Wentland 16584562236bSHarry Wentland /* pixel repetition 16594562236bSHarry Wentland * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel 16604562236bSHarry Wentland * repetition start from 1 */ 16614562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.PR0_PR3 = 0; 16624562236bSHarry Wentland 16634562236bSHarry Wentland /* Bar Info 16644562236bSHarry Wentland * barTop: Line Number of End of Top Bar. 16654562236bSHarry Wentland * barBottom: Line Number of Start of Bottom Bar. 16664562236bSHarry Wentland * barLeft: Pixel Number of End of Left Bar. 16674562236bSHarry Wentland * barRight: Pixel Number of Start of Right Bar. */ 16684562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.bar_top = 16694562236bSHarry Wentland stream->public.timing.v_border_top; 16704562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.bar_bottom = 16714562236bSHarry Wentland (stream->public.timing.v_border_top 16724562236bSHarry Wentland - stream->public.timing.v_border_bottom + 1); 16734562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.bar_left = 16744562236bSHarry Wentland stream->public.timing.h_border_left; 16754562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.bits.bar_right = 16764562236bSHarry Wentland (stream->public.timing.h_total 16774562236bSHarry Wentland - stream->public.timing.h_border_right + 1); 16784562236bSHarry Wentland 16794562236bSHarry Wentland /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ 16804562236bSHarry Wentland check_sum = 16814562236bSHarry Wentland &info_frame. 16824562236bSHarry Wentland avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0]; 16833e183c5fSDave Airlie *check_sum = HDMI_INFOFRAME_TYPE_AVI + HDMI_AVI_INFOFRAME_SIZE + 2; 16844562236bSHarry Wentland 16853e183c5fSDave Airlie for (byte_index = 1; byte_index <= HDMI_AVI_INFOFRAME_SIZE; byte_index++) 16864562236bSHarry Wentland *check_sum += info_frame.avi_info_packet.info_packet_hdmi. 16874562236bSHarry Wentland packet_raw_data.sb[byte_index]; 16884562236bSHarry Wentland 16894562236bSHarry Wentland /* one byte complement */ 16904562236bSHarry Wentland *check_sum = (uint8_t) (0x100 - *check_sum); 16914562236bSHarry Wentland 16924562236bSHarry Wentland /* Store in hw_path_mode */ 16934562236bSHarry Wentland info_packet->hb0 = 16944562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb0; 16954562236bSHarry Wentland info_packet->hb1 = 16964562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb1; 16974562236bSHarry Wentland info_packet->hb2 = 16984562236bSHarry Wentland info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb2; 16994562236bSHarry Wentland 1700e66e4d64SHarry Wentland for (byte_index = 0; byte_index < sizeof(info_frame.avi_info_packet. 1701e66e4d64SHarry Wentland info_packet_hdmi.packet_raw_data.sb); byte_index++) 17024562236bSHarry Wentland info_packet->sb[byte_index] = info_frame.avi_info_packet. 17034562236bSHarry Wentland info_packet_hdmi.packet_raw_data.sb[byte_index]; 17044562236bSHarry Wentland 17054562236bSHarry Wentland info_packet->valid = true; 17064562236bSHarry Wentland } 17074562236bSHarry Wentland 17086e4d6beeSTony Cheng static void set_vendor_info_packet( 17096e4d6beeSTony Cheng struct encoder_info_packet *info_packet, 17106e4d6beeSTony Cheng struct core_stream *stream) 17114562236bSHarry Wentland { 17124562236bSHarry Wentland uint32_t length = 0; 17134562236bSHarry Wentland bool hdmi_vic_mode = false; 17144562236bSHarry Wentland uint8_t checksum = 0; 17154562236bSHarry Wentland uint32_t i = 0; 17164562236bSHarry Wentland enum dc_timing_3d_format format; 17174562236bSHarry Wentland 17184562236bSHarry Wentland format = stream->public.timing.timing_3d_format; 17194562236bSHarry Wentland 17204562236bSHarry Wentland /* Can be different depending on packet content */ 17214562236bSHarry Wentland length = 5; 17224562236bSHarry Wentland 17234562236bSHarry Wentland if (stream->public.timing.hdmi_vic != 0 17244562236bSHarry Wentland && stream->public.timing.h_total >= 3840 17254562236bSHarry Wentland && stream->public.timing.v_total >= 2160) 17264562236bSHarry Wentland hdmi_vic_mode = true; 17274562236bSHarry Wentland 17284562236bSHarry Wentland /* According to HDMI 1.4a CTS, VSIF should be sent 17294562236bSHarry Wentland * for both 3D stereo and HDMI VIC modes. 17304562236bSHarry Wentland * For all other modes, there is no VSIF sent. */ 17314562236bSHarry Wentland 17324562236bSHarry Wentland if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode) 17334562236bSHarry Wentland return; 17344562236bSHarry Wentland 17354562236bSHarry Wentland /* 24bit IEEE Registration identifier (0x000c03). LSB first. */ 17364562236bSHarry Wentland info_packet->sb[1] = 0x03; 17374562236bSHarry Wentland info_packet->sb[2] = 0x0C; 17384562236bSHarry Wentland info_packet->sb[3] = 0x00; 17394562236bSHarry Wentland 17404562236bSHarry Wentland /*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format. 17414562236bSHarry Wentland * The value for HDMI_Video_Format are: 17424562236bSHarry Wentland * 0x0 (0b000) - No additional HDMI video format is presented in this 17434562236bSHarry Wentland * packet 17444562236bSHarry Wentland * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC 17454562236bSHarry Wentland * parameter follows 17464562236bSHarry Wentland * 0x2 (0b010) - 3D format indication present. 3D_Structure and 17474562236bSHarry Wentland * potentially 3D_Ext_Data follows 17484562236bSHarry Wentland * 0x3..0x7 (0b011..0b111) - reserved for future use */ 17494562236bSHarry Wentland if (format != TIMING_3D_FORMAT_NONE) 17504562236bSHarry Wentland info_packet->sb[4] = (2 << 5); 17514562236bSHarry Wentland else if (hdmi_vic_mode) 17524562236bSHarry Wentland info_packet->sb[4] = (1 << 5); 17534562236bSHarry Wentland 17544562236bSHarry Wentland /* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2): 17554562236bSHarry Wentland * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure. 17564562236bSHarry Wentland * The value for 3D_Structure are: 17574562236bSHarry Wentland * 0x0 - Frame Packing 17584562236bSHarry Wentland * 0x1 - Field Alternative 17594562236bSHarry Wentland * 0x2 - Line Alternative 17604562236bSHarry Wentland * 0x3 - Side-by-Side (full) 17614562236bSHarry Wentland * 0x4 - L + depth 17624562236bSHarry Wentland * 0x5 - L + depth + graphics + graphics-depth 17634562236bSHarry Wentland * 0x6 - Top-and-Bottom 17644562236bSHarry Wentland * 0x7 - Reserved for future use 17654562236bSHarry Wentland * 0x8 - Side-by-Side (Half) 17664562236bSHarry Wentland * 0x9..0xE - Reserved for future use 17674562236bSHarry Wentland * 0xF - Not used */ 17684562236bSHarry Wentland switch (format) { 17694562236bSHarry Wentland case TIMING_3D_FORMAT_HW_FRAME_PACKING: 17704562236bSHarry Wentland case TIMING_3D_FORMAT_SW_FRAME_PACKING: 17714562236bSHarry Wentland info_packet->sb[5] = (0x0 << 4); 17724562236bSHarry Wentland break; 17734562236bSHarry Wentland 17744562236bSHarry Wentland case TIMING_3D_FORMAT_SIDE_BY_SIDE: 17754562236bSHarry Wentland case TIMING_3D_FORMAT_SBS_SW_PACKED: 17764562236bSHarry Wentland info_packet->sb[5] = (0x8 << 4); 17774562236bSHarry Wentland length = 6; 17784562236bSHarry Wentland break; 17794562236bSHarry Wentland 17804562236bSHarry Wentland case TIMING_3D_FORMAT_TOP_AND_BOTTOM: 17814562236bSHarry Wentland case TIMING_3D_FORMAT_TB_SW_PACKED: 17824562236bSHarry Wentland info_packet->sb[5] = (0x6 << 4); 17834562236bSHarry Wentland break; 17844562236bSHarry Wentland 17854562236bSHarry Wentland default: 17864562236bSHarry Wentland break; 17874562236bSHarry Wentland } 17884562236bSHarry Wentland 17894562236bSHarry Wentland /*PB5: If PB4 is set to 0x1 (extended resolution format) 17904562236bSHarry Wentland * fill PB5 with the correct HDMI VIC code */ 17914562236bSHarry Wentland if (hdmi_vic_mode) 17924562236bSHarry Wentland info_packet->sb[5] = stream->public.timing.hdmi_vic; 17934562236bSHarry Wentland 17944562236bSHarry Wentland /* Header */ 17953e183c5fSDave Airlie info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR; /* VSIF packet type. */ 17964562236bSHarry Wentland info_packet->hb1 = 0x01; /* Version */ 17974562236bSHarry Wentland 17984562236bSHarry Wentland /* 4 lower bits = Length, 4 higher bits = 0 (reserved) */ 17994562236bSHarry Wentland info_packet->hb2 = (uint8_t) (length); 18004562236bSHarry Wentland 18014562236bSHarry Wentland /* Calculate checksum */ 18024562236bSHarry Wentland checksum = 0; 18034562236bSHarry Wentland checksum += info_packet->hb0; 18044562236bSHarry Wentland checksum += info_packet->hb1; 18054562236bSHarry Wentland checksum += info_packet->hb2; 18064562236bSHarry Wentland 18074562236bSHarry Wentland for (i = 1; i <= length; i++) 18084562236bSHarry Wentland checksum += info_packet->sb[i]; 18094562236bSHarry Wentland 18104562236bSHarry Wentland info_packet->sb[0] = (uint8_t) (0x100 - checksum); 18114562236bSHarry Wentland 18124562236bSHarry Wentland info_packet->valid = true; 18134562236bSHarry Wentland } 18144562236bSHarry Wentland 18156e4d6beeSTony Cheng static void set_spd_info_packet( 18166e4d6beeSTony Cheng struct encoder_info_packet *info_packet, 18176e4d6beeSTony Cheng struct core_stream *stream) 18184562236bSHarry Wentland { 18194562236bSHarry Wentland /* SPD info packet for FreeSync */ 18204562236bSHarry Wentland 18214562236bSHarry Wentland unsigned char checksum = 0; 18224562236bSHarry Wentland unsigned int idx, payload_size = 0; 18234562236bSHarry Wentland 18244562236bSHarry Wentland /* Check if Freesync is supported. Return if false. If true, 18254562236bSHarry Wentland * set the corresponding bit in the info packet 18264562236bSHarry Wentland */ 18274562236bSHarry Wentland if (stream->public.freesync_ctx.supported == false) 18284562236bSHarry Wentland return; 18294562236bSHarry Wentland 18304562236bSHarry Wentland if (dc_is_hdmi_signal(stream->signal)) { 18314562236bSHarry Wentland 18324562236bSHarry Wentland /* HEADER */ 18334562236bSHarry Wentland 18344562236bSHarry Wentland /* HB0 = Packet Type = 0x83 (Source Product 18354562236bSHarry Wentland * Descriptor InfoFrame) 18364562236bSHarry Wentland */ 18373e183c5fSDave Airlie info_packet->hb0 = HDMI_INFOFRAME_TYPE_SPD; 18384562236bSHarry Wentland 18394562236bSHarry Wentland /* HB1 = Version = 0x01 */ 18404562236bSHarry Wentland info_packet->hb1 = 0x01; 18414562236bSHarry Wentland 18424562236bSHarry Wentland /* HB2 = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x08] */ 18434562236bSHarry Wentland info_packet->hb2 = 0x08; 18444562236bSHarry Wentland 18454562236bSHarry Wentland payload_size = 0x08; 18464562236bSHarry Wentland 18474562236bSHarry Wentland } else if (dc_is_dp_signal(stream->signal)) { 18484562236bSHarry Wentland 18494562236bSHarry Wentland /* HEADER */ 18504562236bSHarry Wentland 18514562236bSHarry Wentland /* HB0 = Secondary-data Packet ID = 0 - Only non-zero 18524562236bSHarry Wentland * when used to associate audio related info packets 18534562236bSHarry Wentland */ 18544562236bSHarry Wentland info_packet->hb0 = 0x00; 18554562236bSHarry Wentland 18564562236bSHarry Wentland /* HB1 = Packet Type = 0x83 (Source Product 18574562236bSHarry Wentland * Descriptor InfoFrame) 18584562236bSHarry Wentland */ 18593e183c5fSDave Airlie info_packet->hb1 = HDMI_INFOFRAME_TYPE_SPD; 18604562236bSHarry Wentland 18614562236bSHarry Wentland /* HB2 = [Bits 7:0 = Least significant eight bits - 18624562236bSHarry Wentland * For INFOFRAME, the value must be 1Bh] 18634562236bSHarry Wentland */ 18644562236bSHarry Wentland info_packet->hb2 = 0x1B; 18654562236bSHarry Wentland 18664562236bSHarry Wentland /* HB3 = [Bits 7:2 = INFOFRAME SDP Version Number = 0x1] 18674562236bSHarry Wentland * [Bits 1:0 = Most significant two bits = 0x00] 18684562236bSHarry Wentland */ 18694562236bSHarry Wentland info_packet->hb3 = 0x04; 18704562236bSHarry Wentland 18714562236bSHarry Wentland payload_size = 0x1B; 18724562236bSHarry Wentland } 18734562236bSHarry Wentland 18744562236bSHarry Wentland /* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */ 18754562236bSHarry Wentland info_packet->sb[1] = 0x1A; 18764562236bSHarry Wentland 18774562236bSHarry Wentland /* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */ 18784562236bSHarry Wentland info_packet->sb[2] = 0x00; 18794562236bSHarry Wentland 18804562236bSHarry Wentland /* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */ 18814562236bSHarry Wentland info_packet->sb[3] = 0x00; 18824562236bSHarry Wentland 18834562236bSHarry Wentland /* PB4 = Reserved */ 18844562236bSHarry Wentland info_packet->sb[4] = 0x00; 18854562236bSHarry Wentland 18864562236bSHarry Wentland /* PB5 = Reserved */ 18874562236bSHarry Wentland info_packet->sb[5] = 0x00; 18884562236bSHarry Wentland 18894562236bSHarry Wentland /* PB6 = [Bits 7:3 = Reserved] */ 18904562236bSHarry Wentland info_packet->sb[6] = 0x00; 18914562236bSHarry Wentland 18924562236bSHarry Wentland if (stream->public.freesync_ctx.supported == true) 18934562236bSHarry Wentland /* PB6 = [Bit 0 = FreeSync Supported] */ 18944562236bSHarry Wentland info_packet->sb[6] |= 0x01; 18954562236bSHarry Wentland 18964562236bSHarry Wentland if (stream->public.freesync_ctx.enabled == true) 18974562236bSHarry Wentland /* PB6 = [Bit 1 = FreeSync Enabled] */ 18984562236bSHarry Wentland info_packet->sb[6] |= 0x02; 18994562236bSHarry Wentland 19004562236bSHarry Wentland if (stream->public.freesync_ctx.active == true) 19014562236bSHarry Wentland /* PB6 = [Bit 2 = FreeSync Active] */ 19024562236bSHarry Wentland info_packet->sb[6] |= 0x04; 19034562236bSHarry Wentland 19044562236bSHarry Wentland /* PB7 = FreeSync Minimum refresh rate (Hz) */ 19054562236bSHarry Wentland info_packet->sb[7] = (unsigned char) (stream->public.freesync_ctx. 19064562236bSHarry Wentland min_refresh_in_micro_hz / 1000000); 19074562236bSHarry Wentland 19084562236bSHarry Wentland /* PB8 = FreeSync Maximum refresh rate (Hz) 19094562236bSHarry Wentland * 19104562236bSHarry Wentland * Note: We do not use the maximum capable refresh rate 19114562236bSHarry Wentland * of the panel, because we should never go above the field 19124562236bSHarry Wentland * rate of the mode timing set. 19134562236bSHarry Wentland */ 19144562236bSHarry Wentland info_packet->sb[8] = (unsigned char) (stream->public.freesync_ctx. 19154562236bSHarry Wentland nominal_refresh_in_micro_hz / 1000000); 19164562236bSHarry Wentland 19174562236bSHarry Wentland /* PB9 - PB27 = Reserved */ 19184562236bSHarry Wentland for (idx = 9; idx <= 27; idx++) 19194562236bSHarry Wentland info_packet->sb[idx] = 0x00; 19204562236bSHarry Wentland 19214562236bSHarry Wentland /* Calculate checksum */ 19224562236bSHarry Wentland checksum += info_packet->hb0; 19234562236bSHarry Wentland checksum += info_packet->hb1; 19244562236bSHarry Wentland checksum += info_packet->hb2; 19254562236bSHarry Wentland checksum += info_packet->hb3; 19264562236bSHarry Wentland 19274562236bSHarry Wentland for (idx = 1; idx <= payload_size; idx++) 19284562236bSHarry Wentland checksum += info_packet->sb[idx]; 19294562236bSHarry Wentland 19304562236bSHarry Wentland /* PB0 = Checksum (one byte complement) */ 19314562236bSHarry Wentland info_packet->sb[0] = (unsigned char) (0x100 - checksum); 19324562236bSHarry Wentland 19334562236bSHarry Wentland info_packet->valid = true; 19344562236bSHarry Wentland } 19354562236bSHarry Wentland 19361646a6feSAndrew Wong static void set_hdr_static_info_packet( 19376e4d6beeSTony Cheng struct encoder_info_packet *info_packet, 19381646a6feSAndrew Wong struct core_surface *surface, 19396e4d6beeSTony Cheng struct core_stream *stream) 19401646a6feSAndrew Wong { 1941e5cf325bSHarry Wentland uint16_t i = 0; 19421646a6feSAndrew Wong enum signal_type signal = stream->signal; 1943e5cf325bSHarry Wentland struct dc_hdr_static_metadata hdr_metadata; 1944e5cf325bSHarry Wentland uint32_t data; 19451646a6feSAndrew Wong 19461646a6feSAndrew Wong if (!surface) 19471646a6feSAndrew Wong return; 19481646a6feSAndrew Wong 1949e5cf325bSHarry Wentland hdr_metadata = surface->public.hdr_static_ctx; 19501646a6feSAndrew Wong 195170063a59SAmy Zhang if (!hdr_metadata.hdr_supported) 195210bff005SYongqiang Sun return; 195310bff005SYongqiang Sun 19541646a6feSAndrew Wong if (dc_is_hdmi_signal(signal)) { 19551646a6feSAndrew Wong info_packet->valid = true; 19561646a6feSAndrew Wong 19571646a6feSAndrew Wong info_packet->hb0 = 0x87; 19581646a6feSAndrew Wong info_packet->hb1 = 0x01; 19591646a6feSAndrew Wong info_packet->hb2 = 0x1A; 19601646a6feSAndrew Wong i = 1; 19611646a6feSAndrew Wong } else if (dc_is_dp_signal(signal)) { 19621646a6feSAndrew Wong info_packet->valid = true; 19631646a6feSAndrew Wong 19641646a6feSAndrew Wong info_packet->hb0 = 0x00; 19651646a6feSAndrew Wong info_packet->hb1 = 0x87; 19661646a6feSAndrew Wong info_packet->hb2 = 0x1D; 19671646a6feSAndrew Wong info_packet->hb3 = (0x13 << 2); 19681646a6feSAndrew Wong i = 2; 19691646a6feSAndrew Wong } 19701646a6feSAndrew Wong 19711646a6feSAndrew Wong data = hdr_metadata.is_hdr; 19721646a6feSAndrew Wong info_packet->sb[i++] = data ? 0x02 : 0x00; 19731646a6feSAndrew Wong info_packet->sb[i++] = 0x00; 19741646a6feSAndrew Wong 19751646a6feSAndrew Wong data = hdr_metadata.chromaticity_green_x / 2; 19761646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 19771646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 19781646a6feSAndrew Wong 19791646a6feSAndrew Wong data = hdr_metadata.chromaticity_green_y / 2; 19801646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 19811646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 19821646a6feSAndrew Wong 19831646a6feSAndrew Wong data = hdr_metadata.chromaticity_blue_x / 2; 19841646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 19851646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 19861646a6feSAndrew Wong 19871646a6feSAndrew Wong data = hdr_metadata.chromaticity_blue_y / 2; 19881646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 19891646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 19901646a6feSAndrew Wong 19911646a6feSAndrew Wong data = hdr_metadata.chromaticity_red_x / 2; 19921646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 19931646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 19941646a6feSAndrew Wong 19951646a6feSAndrew Wong data = hdr_metadata.chromaticity_red_y / 2; 19961646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 19971646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 19981646a6feSAndrew Wong 19991646a6feSAndrew Wong data = hdr_metadata.chromaticity_white_point_x / 2; 20001646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 20011646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 20021646a6feSAndrew Wong 20031646a6feSAndrew Wong data = hdr_metadata.chromaticity_white_point_y / 2; 20041646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 20051646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 20061646a6feSAndrew Wong 20071646a6feSAndrew Wong data = hdr_metadata.max_luminance; 20081646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 20091646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 20101646a6feSAndrew Wong 20111646a6feSAndrew Wong data = hdr_metadata.min_luminance; 20121646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 20131646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 20141646a6feSAndrew Wong 20151646a6feSAndrew Wong data = hdr_metadata.maximum_content_light_level; 20161646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 20171646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 20181646a6feSAndrew Wong 20191646a6feSAndrew Wong data = hdr_metadata.maximum_frame_average_light_level; 20201646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 20211646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 20221646a6feSAndrew Wong 20231646a6feSAndrew Wong if (dc_is_hdmi_signal(signal)) { 20241646a6feSAndrew Wong uint32_t checksum = 0; 20251646a6feSAndrew Wong 20261646a6feSAndrew Wong checksum += info_packet->hb0; 20271646a6feSAndrew Wong checksum += info_packet->hb1; 20281646a6feSAndrew Wong checksum += info_packet->hb2; 20291646a6feSAndrew Wong 20301646a6feSAndrew Wong for (i = 1; i <= info_packet->hb2; i++) 20311646a6feSAndrew Wong checksum += info_packet->sb[i]; 20321646a6feSAndrew Wong 20331646a6feSAndrew Wong info_packet->sb[0] = 0x100 - checksum; 20341646a6feSAndrew Wong } else if (dc_is_dp_signal(signal)) { 20351646a6feSAndrew Wong info_packet->sb[0] = 0x01; 20361646a6feSAndrew Wong info_packet->sb[1] = 0x1A; 20371646a6feSAndrew Wong } 20381646a6feSAndrew Wong } 20391646a6feSAndrew Wong 20406e4d6beeSTony Cheng static void set_vsc_info_packet( 20416e4d6beeSTony Cheng struct encoder_info_packet *info_packet, 20426e4d6beeSTony Cheng struct core_stream *stream) 20434562236bSHarry Wentland { 20444562236bSHarry Wentland unsigned int vscPacketRevision = 0; 20454562236bSHarry Wentland unsigned int i; 20464562236bSHarry Wentland 20474562236bSHarry Wentland if (stream->sink->link->public.psr_caps.psr_version != 0) { 20484562236bSHarry Wentland vscPacketRevision = 2; 20494562236bSHarry Wentland } 20504562236bSHarry Wentland 20514562236bSHarry Wentland /* VSC packet not needed based on the features 20524562236bSHarry Wentland * supported by this DP display 20534562236bSHarry Wentland */ 20544562236bSHarry Wentland if (vscPacketRevision == 0) 20554562236bSHarry Wentland return; 20564562236bSHarry Wentland 20574562236bSHarry Wentland if (vscPacketRevision == 0x2) { 20584562236bSHarry Wentland /* Secondary-data Packet ID = 0*/ 20594562236bSHarry Wentland info_packet->hb0 = 0x00; 20604562236bSHarry Wentland /* 07h - Packet Type Value indicating Video 20614562236bSHarry Wentland * Stream Configuration packet 20624562236bSHarry Wentland */ 20634562236bSHarry Wentland info_packet->hb1 = 0x07; 20644562236bSHarry Wentland /* 02h = VSC SDP supporting 3D stereo and PSR 20654562236bSHarry Wentland * (applies to eDP v1.3 or higher). 20664562236bSHarry Wentland */ 20674562236bSHarry Wentland info_packet->hb2 = 0x02; 20684562236bSHarry Wentland /* 08h = VSC packet supporting 3D stereo + PSR 20694562236bSHarry Wentland * (HB2 = 02h). 20704562236bSHarry Wentland */ 20714562236bSHarry Wentland info_packet->hb3 = 0x08; 20724562236bSHarry Wentland 20734562236bSHarry Wentland for (i = 0; i < 28; i++) 20744562236bSHarry Wentland info_packet->sb[i] = 0; 20754562236bSHarry Wentland 20764562236bSHarry Wentland info_packet->valid = true; 20774562236bSHarry Wentland } 20784562236bSHarry Wentland 20794562236bSHarry Wentland /*TODO: stereo 3D support and extend pixel encoding colorimetry*/ 20804562236bSHarry Wentland } 20814562236bSHarry Wentland 20824562236bSHarry Wentland void resource_validate_ctx_destruct(struct validate_context *context) 20834562236bSHarry Wentland { 20844562236bSHarry Wentland int i, j; 20854562236bSHarry Wentland 2086ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 2087ab2541b6SAric Cyr for (j = 0; j < context->stream_status[i].surface_count; j++) 20884562236bSHarry Wentland dc_surface_release( 2089ab2541b6SAric Cyr context->stream_status[i].surfaces[j]); 20904562236bSHarry Wentland 2091ab2541b6SAric Cyr context->stream_status[i].surface_count = 0; 2092ab2541b6SAric Cyr dc_stream_release(&context->streams[i]->public); 2093ab2541b6SAric Cyr context->streams[i] = NULL; 20944562236bSHarry Wentland } 20954562236bSHarry Wentland } 20964562236bSHarry Wentland 20974562236bSHarry Wentland /* 2098ab2541b6SAric Cyr * Copy src_ctx into dst_ctx and retain all surfaces and streams referenced 20994562236bSHarry Wentland * by the src_ctx 21004562236bSHarry Wentland */ 21014562236bSHarry Wentland void resource_validate_ctx_copy_construct( 21024562236bSHarry Wentland const struct validate_context *src_ctx, 21034562236bSHarry Wentland struct validate_context *dst_ctx) 21044562236bSHarry Wentland { 21054562236bSHarry Wentland int i, j; 21064562236bSHarry Wentland 21074562236bSHarry Wentland *dst_ctx = *src_ctx; 21084562236bSHarry Wentland 21094562236bSHarry Wentland for (i = 0; i < dst_ctx->res_ctx.pool->pipe_count; i++) { 21104562236bSHarry Wentland struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i]; 21114562236bSHarry Wentland 21124562236bSHarry Wentland if (cur_pipe->top_pipe) 21134562236bSHarry Wentland cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; 21144562236bSHarry Wentland 21154562236bSHarry Wentland if (cur_pipe->bottom_pipe) 21164562236bSHarry Wentland cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; 21174562236bSHarry Wentland 21184562236bSHarry Wentland } 21194562236bSHarry Wentland 2120ab2541b6SAric Cyr for (i = 0; i < dst_ctx->stream_count; i++) { 2121ab2541b6SAric Cyr dc_stream_retain(&dst_ctx->streams[i]->public); 2122ab2541b6SAric Cyr for (j = 0; j < dst_ctx->stream_status[i].surface_count; j++) 21234562236bSHarry Wentland dc_surface_retain( 2124ab2541b6SAric Cyr dst_ctx->stream_status[i].surfaces[j]); 21254562236bSHarry Wentland } 21264562236bSHarry Wentland } 21274562236bSHarry Wentland 21284562236bSHarry Wentland struct clock_source *dc_resource_find_first_free_pll( 21294562236bSHarry Wentland struct resource_context *res_ctx) 21304562236bSHarry Wentland { 21314562236bSHarry Wentland int i; 21324562236bSHarry Wentland 21334562236bSHarry Wentland for (i = 0; i < res_ctx->pool->clk_src_count; ++i) { 21344562236bSHarry Wentland if (res_ctx->clock_source_ref_count[i] == 0) 21354562236bSHarry Wentland return res_ctx->pool->clock_sources[i]; 21364562236bSHarry Wentland } 21374562236bSHarry Wentland 21384562236bSHarry Wentland return NULL; 21394562236bSHarry Wentland } 21404562236bSHarry Wentland 21414562236bSHarry Wentland void resource_build_info_frame(struct pipe_ctx *pipe_ctx) 21424562236bSHarry Wentland { 21434562236bSHarry Wentland enum signal_type signal = SIGNAL_TYPE_NONE; 21446e4d6beeSTony Cheng struct encoder_info_frame *info = &pipe_ctx->encoder_info_frame; 21454562236bSHarry Wentland 21464562236bSHarry Wentland /* default all packets to invalid */ 21476e4d6beeSTony Cheng info->avi.valid = false; 21486e4d6beeSTony Cheng info->gamut.valid = false; 21496e4d6beeSTony Cheng info->vendor.valid = false; 21506e4d6beeSTony Cheng info->hdrsmd.valid = false; 21516e4d6beeSTony Cheng info->vsc.valid = false; 21524562236bSHarry Wentland 21534562236bSHarry Wentland signal = pipe_ctx->stream->signal; 21544562236bSHarry Wentland 21554562236bSHarry Wentland /* HDMi and DP have different info packets*/ 21564562236bSHarry Wentland if (dc_is_hdmi_signal(signal)) { 21576e4d6beeSTony Cheng set_avi_info_frame(&info->avi, pipe_ctx); 21586e4d6beeSTony Cheng 21596e4d6beeSTony Cheng set_vendor_info_packet(&info->vendor, pipe_ctx->stream); 21606e4d6beeSTony Cheng 21616e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 21626e4d6beeSTony Cheng 21636e4d6beeSTony Cheng set_hdr_static_info_packet(&info->hdrsmd, 21646e4d6beeSTony Cheng pipe_ctx->surface, pipe_ctx->stream); 21656e4d6beeSTony Cheng 2166a33fa99dSHarry Wentland } else if (dc_is_dp_signal(signal)) { 21676e4d6beeSTony Cheng set_vsc_info_packet(&info->vsc, pipe_ctx->stream); 21686e4d6beeSTony Cheng 21696e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 21706e4d6beeSTony Cheng 21716e4d6beeSTony Cheng set_hdr_static_info_packet(&info->hdrsmd, 21726e4d6beeSTony Cheng pipe_ctx->surface, pipe_ctx->stream); 2173a33fa99dSHarry Wentland } 21744562236bSHarry Wentland 21756e4d6beeSTony Cheng patch_gamut_packet_checksum(&info->gamut); 21764562236bSHarry Wentland } 21774562236bSHarry Wentland 21784562236bSHarry Wentland enum dc_status resource_map_clock_resources( 21794562236bSHarry Wentland const struct core_dc *dc, 21804562236bSHarry Wentland struct validate_context *context) 21814562236bSHarry Wentland { 2182ab2541b6SAric Cyr int i, j; 21834562236bSHarry Wentland 21844562236bSHarry Wentland /* acquire new resources */ 2185ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 2186ab2541b6SAric Cyr const struct core_stream *stream = context->streams[i]; 21874562236bSHarry Wentland 21884562236bSHarry Wentland if (resource_is_stream_unchanged(dc->current_context, stream)) 21894562236bSHarry Wentland continue; 21904562236bSHarry Wentland 2191ab2541b6SAric Cyr for (j = 0; j < MAX_PIPES; j++) { 21924562236bSHarry Wentland struct pipe_ctx *pipe_ctx = 2193ab2541b6SAric Cyr &context->res_ctx.pipe_ctx[j]; 21944562236bSHarry Wentland 2195ab2541b6SAric Cyr if (context->res_ctx.pipe_ctx[j].stream != stream) 21964562236bSHarry Wentland continue; 21974562236bSHarry Wentland 21984562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal) 21994562236bSHarry Wentland || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) 22004562236bSHarry Wentland pipe_ctx->clock_source = 22014562236bSHarry Wentland context->res_ctx.pool->dp_clock_source; 22024562236bSHarry Wentland else { 22034562236bSHarry Wentland pipe_ctx->clock_source = NULL; 22044562236bSHarry Wentland 22054562236bSHarry Wentland if (!dc->public.config.disable_disp_pll_sharing) 22064562236bSHarry Wentland resource_find_used_clk_src_for_sharing( 22074562236bSHarry Wentland &context->res_ctx, 22084562236bSHarry Wentland pipe_ctx); 22094562236bSHarry Wentland 22104562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 22114562236bSHarry Wentland pipe_ctx->clock_source = 22124562236bSHarry Wentland dc_resource_find_first_free_pll(&context->res_ctx); 22134562236bSHarry Wentland } 22144562236bSHarry Wentland 22154562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 22164562236bSHarry Wentland return DC_NO_CLOCK_SOURCE_RESOURCE; 22174562236bSHarry Wentland 22184562236bSHarry Wentland resource_reference_clock_source( 22194562236bSHarry Wentland &context->res_ctx, 22204562236bSHarry Wentland pipe_ctx->clock_source); 22214562236bSHarry Wentland 22224562236bSHarry Wentland /* only one cs per stream regardless of mpo */ 22234562236bSHarry Wentland break; 22244562236bSHarry Wentland } 22254562236bSHarry Wentland } 22264562236bSHarry Wentland 22274562236bSHarry Wentland return DC_OK; 22284562236bSHarry Wentland } 22294562236bSHarry Wentland 22304562236bSHarry Wentland /* 22314562236bSHarry Wentland * Note: We need to disable output if clock sources change, 22324562236bSHarry Wentland * since bios does optimization and doesn't apply if changing 22334562236bSHarry Wentland * PHY when not already disabled. 22344562236bSHarry Wentland */ 22354562236bSHarry Wentland bool pipe_need_reprogram( 22364562236bSHarry Wentland struct pipe_ctx *pipe_ctx_old, 22374562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 22384562236bSHarry Wentland { 22394562236bSHarry Wentland if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink) 22404562236bSHarry Wentland return true; 22414562236bSHarry Wentland 22424562236bSHarry Wentland if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal) 22434562236bSHarry Wentland return true; 22444562236bSHarry Wentland 22454562236bSHarry Wentland if (pipe_ctx_old->audio != pipe_ctx->audio) 22464562236bSHarry Wentland return true; 22474562236bSHarry Wentland 22484562236bSHarry Wentland if (pipe_ctx_old->clock_source != pipe_ctx->clock_source 22494562236bSHarry Wentland && pipe_ctx_old->stream != pipe_ctx->stream) 22504562236bSHarry Wentland return true; 22514562236bSHarry Wentland 22524562236bSHarry Wentland if (pipe_ctx_old->stream_enc != pipe_ctx->stream_enc) 22534562236bSHarry Wentland return true; 22544562236bSHarry Wentland 22554562236bSHarry Wentland if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 22564562236bSHarry Wentland return true; 22574562236bSHarry Wentland 22584562236bSHarry Wentland 22594562236bSHarry Wentland return false; 22604562236bSHarry Wentland } 2261