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" 34d94585a0SYue Hin Lau #include "dpp.h" 355ac3d3c9SCharlene Liu #include "core_types.h" 364562236bSHarry Wentland #include "set_mode_types.h" 374562236bSHarry Wentland #include "virtual/virtual_stream_encoder.h" 383b94a400STao #include "dpcd_defs.h" 394562236bSHarry Wentland 404562236bSHarry Wentland #include "dce80/dce80_resource.h" 414562236bSHarry Wentland #include "dce100/dce100_resource.h" 424562236bSHarry Wentland #include "dce110/dce110_resource.h" 434562236bSHarry Wentland #include "dce112/dce112_resource.h" 44dc37a9a0SLeo (Sunpeng) Li #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 45ff5ef992SAlex Deucher #include "dcn10/dcn10_resource.h" 46ff5ef992SAlex Deucher #endif 472c8ad2d5SAlex Deucher #include "dce120/dce120_resource.h" 485d4b05ddSBhawanpreet Lakha 495d4b05ddSBhawanpreet Lakha #define DC_LOGGER_INIT(logger) 505d4b05ddSBhawanpreet Lakha 514562236bSHarry Wentland enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) 524562236bSHarry Wentland { 534562236bSHarry Wentland enum dce_version dc_version = DCE_VERSION_UNKNOWN; 544562236bSHarry Wentland switch (asic_id.chip_family) { 554562236bSHarry Wentland 564562236bSHarry Wentland case FAMILY_CI: 574562236bSHarry Wentland dc_version = DCE_VERSION_8_0; 584562236bSHarry Wentland break; 59ebfdf0d0SAlex Deucher case FAMILY_KV: 60ebfdf0d0SAlex Deucher if (ASIC_REV_IS_KALINDI(asic_id.hw_internal_rev) || 61ebfdf0d0SAlex Deucher ASIC_REV_IS_BHAVANI(asic_id.hw_internal_rev) || 62ebfdf0d0SAlex Deucher ASIC_REV_IS_GODAVARI(asic_id.hw_internal_rev)) 63ebfdf0d0SAlex Deucher dc_version = DCE_VERSION_8_3; 64ebfdf0d0SAlex Deucher else 65ebfdf0d0SAlex Deucher dc_version = DCE_VERSION_8_1; 66ebfdf0d0SAlex Deucher break; 674562236bSHarry Wentland case FAMILY_CZ: 684562236bSHarry Wentland dc_version = DCE_VERSION_11_0; 694562236bSHarry Wentland break; 704562236bSHarry Wentland 714562236bSHarry Wentland case FAMILY_VI: 724562236bSHarry Wentland if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) || 734562236bSHarry Wentland ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) { 744562236bSHarry Wentland dc_version = DCE_VERSION_10_0; 754562236bSHarry Wentland break; 764562236bSHarry Wentland } 774562236bSHarry Wentland if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) || 78b264d345SJordan Lazare ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || 79b264d345SJordan Lazare ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) { 804562236bSHarry Wentland dc_version = DCE_VERSION_11_2; 814562236bSHarry Wentland } 820c75d5acSJerry (Fangzhi) Zuo if (ASIC_REV_IS_VEGAM(asic_id.hw_internal_rev)) 830c75d5acSJerry (Fangzhi) Zuo dc_version = DCE_VERSION_11_22; 844562236bSHarry Wentland break; 852c8ad2d5SAlex Deucher case FAMILY_AI: 862c8ad2d5SAlex Deucher dc_version = DCE_VERSION_12_0; 872c8ad2d5SAlex Deucher break; 88dc37a9a0SLeo (Sunpeng) Li #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 89ff5ef992SAlex Deucher case FAMILY_RV: 90ff5ef992SAlex Deucher dc_version = DCN_VERSION_1_0; 910e3d73f1SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN1_01) 920e3d73f1SBhawanpreet Lakha if (ASICREV_IS_RAVEN2(asic_id.hw_internal_rev)) 930e3d73f1SBhawanpreet Lakha dc_version = DCN_VERSION_1_01; 940e3d73f1SBhawanpreet Lakha #endif 95ff5ef992SAlex Deucher break; 96ff5ef992SAlex Deucher #endif 974562236bSHarry Wentland default: 984562236bSHarry Wentland dc_version = DCE_VERSION_UNKNOWN; 994562236bSHarry Wentland break; 1004562236bSHarry Wentland } 1014562236bSHarry Wentland return dc_version; 1024562236bSHarry Wentland } 1034562236bSHarry Wentland 1044562236bSHarry Wentland struct resource_pool *dc_create_resource_pool( 105fb3466a4SBhawanpreet Lakha struct dc *dc, 1064562236bSHarry Wentland int num_virtual_links, 1074562236bSHarry Wentland enum dce_version dc_version, 1084562236bSHarry Wentland struct hw_asic_id asic_id) 1094562236bSHarry Wentland { 1105ac3d3c9SCharlene Liu struct resource_pool *res_pool = NULL; 1114562236bSHarry Wentland 1124562236bSHarry Wentland switch (dc_version) { 1134562236bSHarry Wentland case DCE_VERSION_8_0: 1145ac3d3c9SCharlene Liu res_pool = dce80_create_resource_pool( 1154562236bSHarry Wentland num_virtual_links, dc); 1165ac3d3c9SCharlene Liu break; 1177992a629SAlex Deucher case DCE_VERSION_8_1: 1187992a629SAlex Deucher res_pool = dce81_create_resource_pool( 1197992a629SAlex Deucher num_virtual_links, dc); 1207992a629SAlex Deucher break; 1217992a629SAlex Deucher case DCE_VERSION_8_3: 1227992a629SAlex Deucher res_pool = dce83_create_resource_pool( 1237992a629SAlex Deucher num_virtual_links, dc); 1247992a629SAlex Deucher break; 1254562236bSHarry Wentland case DCE_VERSION_10_0: 1265ac3d3c9SCharlene Liu res_pool = dce100_create_resource_pool( 1274562236bSHarry Wentland num_virtual_links, dc); 1285ac3d3c9SCharlene Liu break; 1294562236bSHarry Wentland case DCE_VERSION_11_0: 1305ac3d3c9SCharlene Liu res_pool = dce110_create_resource_pool( 1314562236bSHarry Wentland num_virtual_links, dc, asic_id); 1325ac3d3c9SCharlene Liu break; 1334562236bSHarry Wentland case DCE_VERSION_11_2: 1340c75d5acSJerry (Fangzhi) Zuo case DCE_VERSION_11_22: 1355ac3d3c9SCharlene Liu res_pool = dce112_create_resource_pool( 1364562236bSHarry Wentland num_virtual_links, dc); 1375ac3d3c9SCharlene Liu break; 1382c8ad2d5SAlex Deucher case DCE_VERSION_12_0: 1392c8ad2d5SAlex Deucher res_pool = dce120_create_resource_pool( 1402c8ad2d5SAlex Deucher num_virtual_links, dc); 1412c8ad2d5SAlex Deucher break; 142ff5ef992SAlex Deucher 143dc37a9a0SLeo (Sunpeng) Li #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 144ff5ef992SAlex Deucher case DCN_VERSION_1_0: 1450e3d73f1SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN1_01) 1460e3d73f1SBhawanpreet Lakha case DCN_VERSION_1_01: 1470e3d73f1SBhawanpreet Lakha #endif 148ff5ef992SAlex Deucher res_pool = dcn10_create_resource_pool( 149ff5ef992SAlex Deucher num_virtual_links, dc); 150ff5ef992SAlex Deucher break; 151ff5ef992SAlex Deucher #endif 1523639fa68SZeyu Fan 1533639fa68SZeyu Fan 1544562236bSHarry Wentland default: 1554562236bSHarry Wentland break; 1564562236bSHarry Wentland } 1575ac3d3c9SCharlene Liu if (res_pool != NULL) { 1581515a47bSHarry Wentland struct dc_firmware_info fw_info = { { 0 } }; 1594562236bSHarry Wentland 1605ac3d3c9SCharlene Liu if (dc->ctx->dc_bios->funcs->get_firmware_info( 1615ac3d3c9SCharlene Liu dc->ctx->dc_bios, &fw_info) == BP_RESULT_OK) { 1625ac3d3c9SCharlene Liu res_pool->ref_clock_inKhz = fw_info.pll_info.crystal_frequency; 1635ac3d3c9SCharlene Liu } else 1645ac3d3c9SCharlene Liu ASSERT_CRITICAL(false); 1655ac3d3c9SCharlene Liu } 1665ac3d3c9SCharlene Liu 1675ac3d3c9SCharlene Liu return res_pool; 1684562236bSHarry Wentland } 1694562236bSHarry Wentland 170fb3466a4SBhawanpreet Lakha void dc_destroy_resource_pool(struct dc *dc) 1714562236bSHarry Wentland { 1724562236bSHarry Wentland if (dc) { 1734562236bSHarry Wentland if (dc->res_pool) 1744562236bSHarry Wentland dc->res_pool->funcs->destroy(&dc->res_pool); 1754562236bSHarry Wentland 1762004f45eSHarry Wentland kfree(dc->hwseq); 1774562236bSHarry Wentland } 1784562236bSHarry Wentland } 1794562236bSHarry Wentland 1804562236bSHarry Wentland static void update_num_audio( 1814562236bSHarry Wentland const struct resource_straps *straps, 1824562236bSHarry Wentland unsigned int *num_audio, 1834562236bSHarry Wentland struct audio_support *aud_support) 1844562236bSHarry Wentland { 1854562236bSHarry Wentland aud_support->dp_audio = true; 186b8e9eb72SCharlene Liu aud_support->hdmi_audio_native = false; 187b8e9eb72SCharlene Liu aud_support->hdmi_audio_on_dongle = false; 188b8e9eb72SCharlene Liu 189b8e9eb72SCharlene Liu if (straps->hdmi_disable == 0) { 1904562236bSHarry Wentland if (straps->dc_pinstraps_audio & 0x2) { 1914562236bSHarry Wentland aud_support->hdmi_audio_on_dongle = true; 192b8e9eb72SCharlene Liu aud_support->hdmi_audio_native = true; 1934562236bSHarry Wentland } 1944562236bSHarry Wentland } 1954562236bSHarry Wentland 1964562236bSHarry Wentland switch (straps->audio_stream_number) { 1974562236bSHarry Wentland case 0: /* multi streams supported */ 1984562236bSHarry Wentland break; 1994562236bSHarry Wentland case 1: /* multi streams not supported */ 2004562236bSHarry Wentland *num_audio = 1; 2014562236bSHarry Wentland break; 2024562236bSHarry Wentland default: 2034562236bSHarry Wentland DC_ERR("DC: unexpected audio fuse!\n"); 20417a96033SJulia Lawall } 2054562236bSHarry Wentland } 2064562236bSHarry Wentland 2074562236bSHarry Wentland bool resource_construct( 2084562236bSHarry Wentland unsigned int num_virtual_links, 209fb3466a4SBhawanpreet Lakha struct dc *dc, 2104562236bSHarry Wentland struct resource_pool *pool, 2114562236bSHarry Wentland const struct resource_create_funcs *create_funcs) 2124562236bSHarry Wentland { 2134562236bSHarry Wentland struct dc_context *ctx = dc->ctx; 2144562236bSHarry Wentland const struct resource_caps *caps = pool->res_cap; 2154562236bSHarry Wentland int i; 2164562236bSHarry Wentland unsigned int num_audio = caps->num_audio; 2174562236bSHarry Wentland struct resource_straps straps = {0}; 2184562236bSHarry Wentland 2194562236bSHarry Wentland if (create_funcs->read_dce_straps) 2204562236bSHarry Wentland create_funcs->read_dce_straps(dc->ctx, &straps); 2214562236bSHarry Wentland 2224562236bSHarry Wentland pool->audio_count = 0; 2234562236bSHarry Wentland if (create_funcs->create_audio) { 2244562236bSHarry Wentland /* find the total number of streams available via the 2254562236bSHarry Wentland * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT 2264562236bSHarry Wentland * registers (one for each pin) starting from pin 1 2274562236bSHarry Wentland * up to the max number of audio pins. 2284562236bSHarry Wentland * We stop on the first pin where 2294562236bSHarry Wentland * PORT_CONNECTIVITY == 1 (as instructed by HW team). 2304562236bSHarry Wentland */ 2314562236bSHarry Wentland update_num_audio(&straps, &num_audio, &pool->audio_support); 2324562236bSHarry Wentland for (i = 0; i < pool->pipe_count && i < num_audio; i++) { 2334562236bSHarry Wentland struct audio *aud = create_funcs->create_audio(ctx, i); 2344562236bSHarry Wentland 2354562236bSHarry Wentland if (aud == NULL) { 2364562236bSHarry Wentland DC_ERR("DC: failed to create audio!\n"); 2374562236bSHarry Wentland return false; 2384562236bSHarry Wentland } 2394562236bSHarry Wentland 2404562236bSHarry Wentland if (!aud->funcs->endpoint_valid(aud)) { 2414562236bSHarry Wentland aud->funcs->destroy(&aud); 2424562236bSHarry Wentland break; 2434562236bSHarry Wentland } 2444562236bSHarry Wentland 2454562236bSHarry Wentland pool->audios[i] = aud; 2464562236bSHarry Wentland pool->audio_count++; 2474562236bSHarry Wentland } 2484562236bSHarry Wentland } 2494562236bSHarry Wentland 2504562236bSHarry Wentland pool->stream_enc_count = 0; 2514562236bSHarry Wentland if (create_funcs->create_stream_encoder) { 2524562236bSHarry Wentland for (i = 0; i < caps->num_stream_encoder; i++) { 2534562236bSHarry Wentland pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx); 2544562236bSHarry Wentland if (pool->stream_enc[i] == NULL) 2554562236bSHarry Wentland DC_ERR("DC: failed to create stream_encoder!\n"); 2564562236bSHarry Wentland pool->stream_enc_count++; 2574562236bSHarry Wentland } 2584562236bSHarry Wentland } 2594176664bSCharlene Liu dc->caps.dynamic_audio = false; 2604176664bSCharlene Liu if (pool->audio_count < pool->stream_enc_count) { 2614176664bSCharlene Liu dc->caps.dynamic_audio = true; 2624176664bSCharlene Liu } 2634562236bSHarry Wentland for (i = 0; i < num_virtual_links; i++) { 2644562236bSHarry Wentland pool->stream_enc[pool->stream_enc_count] = 2654562236bSHarry Wentland virtual_stream_encoder_create( 2664562236bSHarry Wentland ctx, ctx->dc_bios); 2674562236bSHarry Wentland if (pool->stream_enc[pool->stream_enc_count] == NULL) { 2684562236bSHarry Wentland DC_ERR("DC: failed to create stream_encoder!\n"); 2694562236bSHarry Wentland return false; 2704562236bSHarry Wentland } 2714562236bSHarry Wentland pool->stream_enc_count++; 2724562236bSHarry Wentland } 2734562236bSHarry Wentland 2744562236bSHarry Wentland dc->hwseq = create_funcs->create_hwseq(ctx); 2754562236bSHarry Wentland 2764562236bSHarry Wentland return true; 2774562236bSHarry Wentland } 278ad8960a6SMikita Lipski static int find_matching_clock_source( 279ad8960a6SMikita Lipski const struct resource_pool *pool, 280ad8960a6SMikita Lipski struct clock_source *clock_source) 281ad8960a6SMikita Lipski { 2824562236bSHarry Wentland 283ad8960a6SMikita Lipski int i; 284ad8960a6SMikita Lipski 285ad8960a6SMikita Lipski for (i = 0; i < pool->clk_src_count; i++) { 286ad8960a6SMikita Lipski if (pool->clock_sources[i] == clock_source) 287ad8960a6SMikita Lipski return i; 288ad8960a6SMikita Lipski } 289ad8960a6SMikita Lipski return -1; 290ad8960a6SMikita Lipski } 2914562236bSHarry Wentland 29221e67d4dSHarry Wentland void resource_unreference_clock_source( 2934562236bSHarry Wentland struct resource_context *res_ctx, 294a2b8659dSTony Cheng const struct resource_pool *pool, 2954a629536SHarry Wentland struct clock_source *clock_source) 2964562236bSHarry Wentland { 297ad8960a6SMikita Lipski int i = find_matching_clock_source(pool, clock_source); 2984a629536SHarry Wentland 299ad8960a6SMikita Lipski if (i > -1) 3004562236bSHarry Wentland res_ctx->clock_source_ref_count[i]--; 3014562236bSHarry Wentland 30221e67d4dSHarry Wentland if (pool->dp_clock_source == clock_source) 3034562236bSHarry Wentland res_ctx->dp_clock_source_ref_count--; 3044562236bSHarry Wentland } 3054562236bSHarry Wentland 3064562236bSHarry Wentland void resource_reference_clock_source( 3074562236bSHarry Wentland struct resource_context *res_ctx, 308a2b8659dSTony Cheng const struct resource_pool *pool, 3094562236bSHarry Wentland struct clock_source *clock_source) 3104562236bSHarry Wentland { 311ad8960a6SMikita Lipski int i = find_matching_clock_source(pool, clock_source); 3124562236bSHarry Wentland 313ad8960a6SMikita Lipski if (i > -1) 3144562236bSHarry Wentland res_ctx->clock_source_ref_count[i]++; 3154562236bSHarry Wentland 316a2b8659dSTony Cheng if (pool->dp_clock_source == clock_source) 3174562236bSHarry Wentland res_ctx->dp_clock_source_ref_count++; 3184562236bSHarry Wentland } 3194562236bSHarry Wentland 320ad8960a6SMikita Lipski int resource_get_clock_source_reference( 321ad8960a6SMikita Lipski struct resource_context *res_ctx, 322ad8960a6SMikita Lipski const struct resource_pool *pool, 323ad8960a6SMikita Lipski struct clock_source *clock_source) 324ad8960a6SMikita Lipski { 325ad8960a6SMikita Lipski int i = find_matching_clock_source(pool, clock_source); 326ad8960a6SMikita Lipski 327ad8960a6SMikita Lipski if (i > -1) 328ad8960a6SMikita Lipski return res_ctx->clock_source_ref_count[i]; 329ad8960a6SMikita Lipski 330ad8960a6SMikita Lipski if (pool->dp_clock_source == clock_source) 331ad8960a6SMikita Lipski return res_ctx->dp_clock_source_ref_count; 332ad8960a6SMikita Lipski 333ad8960a6SMikita Lipski return -1; 334ad8960a6SMikita Lipski } 335ad8960a6SMikita Lipski 3364562236bSHarry Wentland bool resource_are_streams_timing_synchronizable( 3370971c40eSHarry Wentland struct dc_stream_state *stream1, 3380971c40eSHarry Wentland struct dc_stream_state *stream2) 3394562236bSHarry Wentland { 3404fa086b9SLeo (Sunpeng) Li if (stream1->timing.h_total != stream2->timing.h_total) 3414562236bSHarry Wentland return false; 3424562236bSHarry Wentland 3434fa086b9SLeo (Sunpeng) Li if (stream1->timing.v_total != stream2->timing.v_total) 3444562236bSHarry Wentland return false; 3454562236bSHarry Wentland 3464fa086b9SLeo (Sunpeng) Li if (stream1->timing.h_addressable 3474fa086b9SLeo (Sunpeng) Li != stream2->timing.h_addressable) 3484562236bSHarry Wentland return false; 3494562236bSHarry Wentland 3504fa086b9SLeo (Sunpeng) Li if (stream1->timing.v_addressable 3514fa086b9SLeo (Sunpeng) Li != stream2->timing.v_addressable) 3524562236bSHarry Wentland return false; 3534562236bSHarry Wentland 3544fa086b9SLeo (Sunpeng) Li if (stream1->timing.pix_clk_khz 3554fa086b9SLeo (Sunpeng) Li != stream2->timing.pix_clk_khz) 3564562236bSHarry Wentland return false; 3574562236bSHarry Wentland 3583e27e10eSMikita Lipski if (stream1->clamping.c_depth != stream2->clamping.c_depth) 3593e27e10eSMikita Lipski return false; 3603e27e10eSMikita Lipski 3614562236bSHarry Wentland if (stream1->phy_pix_clk != stream2->phy_pix_clk 3627e2fe319SCharlene Liu && (!dc_is_dp_signal(stream1->signal) 3637e2fe319SCharlene Liu || !dc_is_dp_signal(stream2->signal))) 3644562236bSHarry Wentland return false; 3654562236bSHarry Wentland 366d77f778eSCharlene Liu if (stream1->view_format != stream2->view_format) 367d77f778eSCharlene Liu return false; 368d77f778eSCharlene Liu 3694562236bSHarry Wentland return true; 3704562236bSHarry Wentland } 3713e27e10eSMikita Lipski static bool is_dp_and_hdmi_sharable( 3723e27e10eSMikita Lipski struct dc_stream_state *stream1, 3733e27e10eSMikita Lipski struct dc_stream_state *stream2) 3743e27e10eSMikita Lipski { 3753e27e10eSMikita Lipski if (stream1->ctx->dc->caps.disable_dp_clk_share) 3763e27e10eSMikita Lipski return false; 3773e27e10eSMikita Lipski 3783e27e10eSMikita Lipski if (stream1->clamping.c_depth != COLOR_DEPTH_888 || 3793e27e10eSMikita Lipski stream2->clamping.c_depth != COLOR_DEPTH_888) 3803e27e10eSMikita Lipski return false; 3813e27e10eSMikita Lipski 3823e27e10eSMikita Lipski return true; 3833e27e10eSMikita Lipski 3843e27e10eSMikita Lipski } 3854562236bSHarry Wentland 3864562236bSHarry Wentland static bool is_sharable_clk_src( 3874562236bSHarry Wentland const struct pipe_ctx *pipe_with_clk_src, 3884562236bSHarry Wentland const struct pipe_ctx *pipe) 3894562236bSHarry Wentland { 3904562236bSHarry Wentland if (pipe_with_clk_src->clock_source == NULL) 3914562236bSHarry Wentland return false; 3924562236bSHarry Wentland 3934562236bSHarry Wentland if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL) 3944562236bSHarry Wentland return false; 3954562236bSHarry Wentland 3963e27e10eSMikita Lipski if (dc_is_dp_signal(pipe_with_clk_src->stream->signal) || 3973e27e10eSMikita Lipski (dc_is_dp_signal(pipe->stream->signal) && 3983e27e10eSMikita Lipski !is_dp_and_hdmi_sharable(pipe_with_clk_src->stream, 3993e27e10eSMikita Lipski pipe->stream))) 4004562236bSHarry Wentland return false; 4014562236bSHarry Wentland 4024562236bSHarry Wentland if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal) 403fc69009eSMikita Lipski && dc_is_dual_link_signal(pipe->stream->signal)) 4044562236bSHarry Wentland return false; 4054562236bSHarry Wentland 4064562236bSHarry Wentland if (dc_is_hdmi_signal(pipe->stream->signal) 407fc69009eSMikita Lipski && dc_is_dual_link_signal(pipe_with_clk_src->stream->signal)) 4084562236bSHarry Wentland return false; 4094562236bSHarry Wentland 4104562236bSHarry Wentland if (!resource_are_streams_timing_synchronizable( 4114562236bSHarry Wentland pipe_with_clk_src->stream, pipe->stream)) 4124562236bSHarry Wentland return false; 4134562236bSHarry Wentland 4144562236bSHarry Wentland return true; 4154562236bSHarry Wentland } 4164562236bSHarry Wentland 4174562236bSHarry Wentland struct clock_source *resource_find_used_clk_src_for_sharing( 4184562236bSHarry Wentland struct resource_context *res_ctx, 4194562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 4204562236bSHarry Wentland { 4214562236bSHarry Wentland int i; 4224562236bSHarry Wentland 4234562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 4244562236bSHarry Wentland if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx)) 4254562236bSHarry Wentland return res_ctx->pipe_ctx[i].clock_source; 4264562236bSHarry Wentland } 4274562236bSHarry Wentland 4284562236bSHarry Wentland return NULL; 4294562236bSHarry Wentland } 4304562236bSHarry Wentland 4314562236bSHarry Wentland static enum pixel_format convert_pixel_format_to_dalsurface( 4324562236bSHarry Wentland enum surface_pixel_format surface_pixel_format) 4334562236bSHarry Wentland { 4344562236bSHarry Wentland enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 4354562236bSHarry Wentland 4364562236bSHarry Wentland switch (surface_pixel_format) { 4374562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 4384562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_INDEX8; 4394562236bSHarry Wentland break; 4404562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 4414562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_RGB565; 4424562236bSHarry Wentland break; 4434562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 4444562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_RGB565; 4454562236bSHarry Wentland break; 4464562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 4474562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB8888; 4484562236bSHarry Wentland break; 4498693049aSTony Cheng case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 4504562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB8888; 4514562236bSHarry Wentland break; 4524562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 4534562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 4544562236bSHarry Wentland break; 4554562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 4564562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 4574562236bSHarry Wentland break; 4584562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 4594562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS; 4604562236bSHarry Wentland break; 4614562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 4624562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 4634562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_FP16; 4644562236bSHarry Wentland break; 4654562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 4664562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 46787449a90SAnthony Koo dal_pixel_format = PIXEL_FORMAT_420BPP8; 4684562236bSHarry Wentland break; 469ffbcd19aSVitaly Prosyak case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 470ffbcd19aSVitaly Prosyak case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 47187449a90SAnthony Koo dal_pixel_format = PIXEL_FORMAT_420BPP10; 472ffbcd19aSVitaly Prosyak break; 4734562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 4744562236bSHarry Wentland default: 4754562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 4764562236bSHarry Wentland break; 4774562236bSHarry Wentland } 4784562236bSHarry Wentland return dal_pixel_format; 4794562236bSHarry Wentland } 4804562236bSHarry Wentland 4819b6067c0SDmytro Laktyushkin static inline void get_vp_scan_direction( 4829b6067c0SDmytro Laktyushkin enum dc_rotation_angle rotation, 4839b6067c0SDmytro Laktyushkin bool horizontal_mirror, 4849b6067c0SDmytro Laktyushkin bool *orthogonal_rotation, 4859b6067c0SDmytro Laktyushkin bool *flip_vert_scan_dir, 4869b6067c0SDmytro Laktyushkin bool *flip_horz_scan_dir) 4874562236bSHarry Wentland { 4889b6067c0SDmytro Laktyushkin *orthogonal_rotation = false; 4899b6067c0SDmytro Laktyushkin *flip_vert_scan_dir = false; 4909b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = false; 4919b6067c0SDmytro Laktyushkin if (rotation == ROTATION_ANGLE_180) { 4929b6067c0SDmytro Laktyushkin *flip_vert_scan_dir = true; 4939b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = true; 4949b6067c0SDmytro Laktyushkin } else if (rotation == ROTATION_ANGLE_90) { 4959b6067c0SDmytro Laktyushkin *orthogonal_rotation = true; 4969b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = true; 4979b6067c0SDmytro Laktyushkin } else if (rotation == ROTATION_ANGLE_270) { 4989b6067c0SDmytro Laktyushkin *orthogonal_rotation = true; 4999b6067c0SDmytro Laktyushkin *flip_vert_scan_dir = true; 5009b6067c0SDmytro Laktyushkin } 5019b6067c0SDmytro Laktyushkin 5029b6067c0SDmytro Laktyushkin if (horizontal_mirror) 5039b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = !*flip_horz_scan_dir; 5044562236bSHarry Wentland } 5054562236bSHarry Wentland 506b2d0a103SDmytro Laktyushkin static void calculate_viewport(struct pipe_ctx *pipe_ctx) 5074562236bSHarry Wentland { 5083be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 5090971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 5106702a9acSHarry Wentland struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 5113be5262eSHarry Wentland struct rect surf_src = plane_state->src_rect; 5129b6067c0SDmytro Laktyushkin struct rect clip, dest; 51387449a90SAnthony Koo int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 51487449a90SAnthony Koo || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 5151fbd2cfcSDmytro Laktyushkin bool pri_split = pipe_ctx->bottom_pipe && 5163be5262eSHarry Wentland pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; 5171fbd2cfcSDmytro Laktyushkin bool sec_split = pipe_ctx->top_pipe && 5183be5262eSHarry Wentland pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; 5199b6067c0SDmytro Laktyushkin bool orthogonal_rotation, flip_y_start, flip_x_start; 52083d40659SDmytro Laktyushkin 5217f5c22d1SVitaly Prosyak if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || 5227f5c22d1SVitaly Prosyak stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { 5237b779c99SVitaly Prosyak pri_split = false; 5247b779c99SVitaly Prosyak sec_split = false; 5257b779c99SVitaly Prosyak } 52686006a7fSDmytro Laktyushkin 5274562236bSHarry Wentland /* The actual clip is an intersection between stream 5284562236bSHarry Wentland * source and surface clip 5294562236bSHarry Wentland */ 5309b6067c0SDmytro Laktyushkin dest = plane_state->dst_rect; 5313be5262eSHarry Wentland clip.x = stream->src.x > plane_state->clip_rect.x ? 5323be5262eSHarry Wentland stream->src.x : plane_state->clip_rect.x; 5334562236bSHarry Wentland 5341fbd2cfcSDmytro Laktyushkin clip.width = stream->src.x + stream->src.width < 5353be5262eSHarry Wentland plane_state->clip_rect.x + plane_state->clip_rect.width ? 5361fbd2cfcSDmytro Laktyushkin stream->src.x + stream->src.width - clip.x : 5373be5262eSHarry Wentland plane_state->clip_rect.x + plane_state->clip_rect.width - clip.x ; 5384562236bSHarry Wentland 5393be5262eSHarry Wentland clip.y = stream->src.y > plane_state->clip_rect.y ? 5403be5262eSHarry Wentland stream->src.y : plane_state->clip_rect.y; 5414562236bSHarry Wentland 5421fbd2cfcSDmytro Laktyushkin clip.height = stream->src.y + stream->src.height < 5433be5262eSHarry Wentland plane_state->clip_rect.y + plane_state->clip_rect.height ? 5441fbd2cfcSDmytro Laktyushkin stream->src.y + stream->src.height - clip.y : 5453be5262eSHarry Wentland plane_state->clip_rect.y + plane_state->clip_rect.height - clip.y ; 5464562236bSHarry Wentland 5479b6067c0SDmytro Laktyushkin /* 5489b6067c0SDmytro Laktyushkin * Need to calculate how scan origin is shifted in vp space 5499b6067c0SDmytro Laktyushkin * to correctly rotate clip and dst 5509b6067c0SDmytro Laktyushkin */ 5519b6067c0SDmytro Laktyushkin get_vp_scan_direction( 5529b6067c0SDmytro Laktyushkin plane_state->rotation, 5539b6067c0SDmytro Laktyushkin plane_state->horizontal_mirror, 5549b6067c0SDmytro Laktyushkin &orthogonal_rotation, 5559b6067c0SDmytro Laktyushkin &flip_y_start, 5569b6067c0SDmytro Laktyushkin &flip_x_start); 5579b6067c0SDmytro Laktyushkin 5589b6067c0SDmytro Laktyushkin if (orthogonal_rotation) { 5599b6067c0SDmytro Laktyushkin swap(clip.x, clip.y); 5609b6067c0SDmytro Laktyushkin swap(clip.width, clip.height); 5619b6067c0SDmytro Laktyushkin swap(dest.x, dest.y); 5629b6067c0SDmytro Laktyushkin swap(dest.width, dest.height); 5639b6067c0SDmytro Laktyushkin } 5649b6067c0SDmytro Laktyushkin if (flip_x_start) { 5659b6067c0SDmytro Laktyushkin clip.x = dest.x + dest.width - clip.x - clip.width; 5669b6067c0SDmytro Laktyushkin dest.x = 0; 5679b6067c0SDmytro Laktyushkin } 5689b6067c0SDmytro Laktyushkin if (flip_y_start) { 5699b6067c0SDmytro Laktyushkin clip.y = dest.y + dest.height - clip.y - clip.height; 5709b6067c0SDmytro Laktyushkin dest.y = 0; 5719b6067c0SDmytro Laktyushkin } 5729b6067c0SDmytro Laktyushkin 57386006a7fSDmytro Laktyushkin /* offset = surf_src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio 5744562236bSHarry Wentland * num_pixels = clip.num_pix * scl_ratio 5754562236bSHarry Wentland */ 5769b6067c0SDmytro Laktyushkin data->viewport.x = surf_src.x + (clip.x - dest.x) * surf_src.width / dest.width; 5779b6067c0SDmytro Laktyushkin data->viewport.width = clip.width * surf_src.width / dest.width; 5784562236bSHarry Wentland 5799b6067c0SDmytro Laktyushkin data->viewport.y = surf_src.y + (clip.y - dest.y) * surf_src.height / dest.height; 5809b6067c0SDmytro Laktyushkin data->viewport.height = clip.height * surf_src.height / dest.height; 5814562236bSHarry Wentland 5829b6067c0SDmytro Laktyushkin /* Handle split */ 5839b6067c0SDmytro Laktyushkin if (pri_split || sec_split) { 5849b6067c0SDmytro Laktyushkin if (orthogonal_rotation) { 5859b6067c0SDmytro Laktyushkin if (flip_y_start != pri_split) 5869b6067c0SDmytro Laktyushkin data->viewport.height /= 2; 5879b6067c0SDmytro Laktyushkin else { 5889b6067c0SDmytro Laktyushkin data->viewport.y += data->viewport.height / 2; 5899b6067c0SDmytro Laktyushkin /* Ceil offset pipe */ 5909b6067c0SDmytro Laktyushkin data->viewport.height = (data->viewport.height + 1) / 2; 5919b6067c0SDmytro Laktyushkin } 5929b6067c0SDmytro Laktyushkin } else { 5939b6067c0SDmytro Laktyushkin if (flip_x_start != pri_split) 5949b6067c0SDmytro Laktyushkin data->viewport.width /= 2; 5959b6067c0SDmytro Laktyushkin else { 5969b6067c0SDmytro Laktyushkin data->viewport.x += data->viewport.width / 2; 5979b6067c0SDmytro Laktyushkin /* Ceil offset pipe */ 5989b6067c0SDmytro Laktyushkin data->viewport.width = (data->viewport.width + 1) / 2; 5999b6067c0SDmytro Laktyushkin } 6009b6067c0SDmytro Laktyushkin } 6019b6067c0SDmytro Laktyushkin } 6029b5349f7SMartin Tsai 603b2d0a103SDmytro Laktyushkin /* Round down, compensate in init */ 604b2d0a103SDmytro Laktyushkin data->viewport_c.x = data->viewport.x / vpc_div; 605b2d0a103SDmytro Laktyushkin data->viewport_c.y = data->viewport.y / vpc_div; 6069b6067c0SDmytro Laktyushkin data->inits.h_c = (data->viewport.x % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero; 6079b6067c0SDmytro Laktyushkin data->inits.v_c = (data->viewport.y % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero; 6089b6067c0SDmytro Laktyushkin 609b2d0a103SDmytro Laktyushkin /* Round up, assume original video size always even dimensions */ 610b2d0a103SDmytro Laktyushkin data->viewport_c.width = (data->viewport.width + vpc_div - 1) / vpc_div; 611b2d0a103SDmytro Laktyushkin data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; 612b2d0a103SDmytro Laktyushkin } 6131fbd2cfcSDmytro Laktyushkin 6149b6067c0SDmytro Laktyushkin static void calculate_recout(struct pipe_ctx *pipe_ctx) 6154562236bSHarry Wentland { 6163be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 6170971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 6183be5262eSHarry Wentland struct rect surf_clip = plane_state->clip_rect; 6190c31a821SYongqiang Sun bool pri_split = pipe_ctx->bottom_pipe && 6200c31a821SYongqiang Sun pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; 6210c31a821SYongqiang Sun bool sec_split = pipe_ctx->top_pipe && 6220c31a821SYongqiang Sun pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; 623b0131391SDmytro Laktyushkin bool top_bottom_split = stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; 6244562236bSHarry Wentland 6256702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.x = stream->dst.x; 6264fa086b9SLeo (Sunpeng) Li if (stream->src.x < surf_clip.x) 6276702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.x += (surf_clip.x 6284fa086b9SLeo (Sunpeng) Li - stream->src.x) * stream->dst.width 6294fa086b9SLeo (Sunpeng) Li / stream->src.width; 6304562236bSHarry Wentland 6316702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.width = surf_clip.width * 6324fa086b9SLeo (Sunpeng) Li stream->dst.width / stream->src.width; 6336702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.recout.width + pipe_ctx->plane_res.scl_data.recout.x > 6344fa086b9SLeo (Sunpeng) Li stream->dst.x + stream->dst.width) 6356702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.width = 6364fa086b9SLeo (Sunpeng) Li stream->dst.x + stream->dst.width 6376702a9acSHarry Wentland - pipe_ctx->plane_res.scl_data.recout.x; 6384562236bSHarry Wentland 6396702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.y = stream->dst.y; 6404fa086b9SLeo (Sunpeng) Li if (stream->src.y < surf_clip.y) 6416702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.y += (surf_clip.y 6424fa086b9SLeo (Sunpeng) Li - stream->src.y) * stream->dst.height 6434fa086b9SLeo (Sunpeng) Li / stream->src.height; 6444562236bSHarry Wentland 6456702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.height = surf_clip.height * 6464fa086b9SLeo (Sunpeng) Li stream->dst.height / stream->src.height; 6476702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.recout.height + pipe_ctx->plane_res.scl_data.recout.y > 6484fa086b9SLeo (Sunpeng) Li stream->dst.y + stream->dst.height) 6496702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.height = 6504fa086b9SLeo (Sunpeng) Li stream->dst.y + stream->dst.height 6516702a9acSHarry Wentland - pipe_ctx->plane_res.scl_data.recout.y; 652b2d0a103SDmytro Laktyushkin 6539b6067c0SDmytro Laktyushkin /* Handle h & v split, handle rotation using viewport */ 654b0131391SDmytro Laktyushkin if (sec_split && top_bottom_split) { 655b0131391SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.y += 656b0131391SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.height / 2; 6577b779c99SVitaly Prosyak /* Floor primary pipe, ceil 2ndary pipe */ 658b0131391SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.height = 659b0131391SDmytro Laktyushkin (pipe_ctx->plane_res.scl_data.recout.height + 1) / 2; 660b0131391SDmytro Laktyushkin } else if (pri_split && top_bottom_split) 6616702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.height /= 2; 6629b6067c0SDmytro Laktyushkin else if (sec_split) { 6630c31a821SYongqiang Sun pipe_ctx->plane_res.scl_data.recout.x += 6640c31a821SYongqiang Sun pipe_ctx->plane_res.scl_data.recout.width / 2; 6650c31a821SYongqiang Sun /* Ceil offset pipe */ 6660c31a821SYongqiang Sun pipe_ctx->plane_res.scl_data.recout.width = 6670c31a821SYongqiang Sun (pipe_ctx->plane_res.scl_data.recout.width + 1) / 2; 6689b6067c0SDmytro Laktyushkin } else if (pri_split) 6696702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.width /= 2; 6704562236bSHarry Wentland } 671b2d0a103SDmytro Laktyushkin 672b2d0a103SDmytro Laktyushkin static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) 6734562236bSHarry Wentland { 6743be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 6750971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 6763be5262eSHarry Wentland struct rect surf_src = plane_state->src_rect; 6774fa086b9SLeo (Sunpeng) Li const int in_w = stream->src.width; 6784fa086b9SLeo (Sunpeng) Li const int in_h = stream->src.height; 6794fa086b9SLeo (Sunpeng) Li const int out_w = stream->dst.width; 6804fa086b9SLeo (Sunpeng) Li const int out_h = stream->dst.height; 6814562236bSHarry Wentland 6829b6067c0SDmytro Laktyushkin /*Swap surf_src height and width since scaling ratios are in recout rotation*/ 6833be5262eSHarry Wentland if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 6843be5262eSHarry Wentland pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 6859b6067c0SDmytro Laktyushkin swap(surf_src.height, surf_src.width); 68686006a7fSDmytro Laktyushkin 687eb0e5154SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_from_fraction( 68886006a7fSDmytro Laktyushkin surf_src.width, 6893be5262eSHarry Wentland plane_state->dst_rect.width); 690eb0e5154SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_from_fraction( 69186006a7fSDmytro Laktyushkin surf_src.height, 6923be5262eSHarry Wentland plane_state->dst_rect.height); 6934562236bSHarry Wentland 6944fa086b9SLeo (Sunpeng) Li if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) 6956702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value *= 2; 6964fa086b9SLeo (Sunpeng) Li else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) 6976702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value *= 2; 6984562236bSHarry Wentland 6996702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value = div64_s64( 7006702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value * in_h, out_h); 7016702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value = div64_s64( 7026702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value * in_w, out_w); 7034562236bSHarry Wentland 7046702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz_c = pipe_ctx->plane_res.scl_data.ratios.horz; 7056702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert_c = pipe_ctx->plane_res.scl_data.ratios.vert; 7064562236bSHarry Wentland 7076702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP8 7086702a9acSHarry Wentland || pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP10) { 7096702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz_c.value /= 2; 7106702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert_c.value /= 2; 7114562236bSHarry Wentland } 7120002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_truncate( 7130002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz, 19); 7140002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_truncate( 7150002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert, 19); 7160002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz_c = dc_fixpt_truncate( 7170002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz_c, 19); 7180002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert_c = dc_fixpt_truncate( 7190002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert_c, 19); 7204562236bSHarry Wentland } 7214562236bSHarry Wentland 7229b6067c0SDmytro Laktyushkin static inline void adjust_vp_and_init_for_seamless_clip( 7239b6067c0SDmytro Laktyushkin bool flip_scan_dir, 7249b6067c0SDmytro Laktyushkin int recout_skip, 7259b6067c0SDmytro Laktyushkin int src_size, 7269b6067c0SDmytro Laktyushkin int taps, 7279b6067c0SDmytro Laktyushkin struct fixed31_32 ratio, 7289b6067c0SDmytro Laktyushkin struct fixed31_32 *init, 7299b6067c0SDmytro Laktyushkin int *vp_offset, 7309b6067c0SDmytro Laktyushkin int *vp_size) 7314562236bSHarry Wentland { 7329b6067c0SDmytro Laktyushkin if (!flip_scan_dir) { 7339b6067c0SDmytro Laktyushkin /* Adjust for viewport end clip-off */ 7349b6067c0SDmytro Laktyushkin if ((*vp_offset + *vp_size) < src_size) { 7359b6067c0SDmytro Laktyushkin int vp_clip = src_size - *vp_size - *vp_offset; 7369b6067c0SDmytro Laktyushkin int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio)); 7379b6067c0SDmytro Laktyushkin 7389b6067c0SDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 7399b6067c0SDmytro Laktyushkin *vp_size += int_part < vp_clip ? int_part : vp_clip; 7409b6067c0SDmytro Laktyushkin } 7419b6067c0SDmytro Laktyushkin 7429b6067c0SDmytro Laktyushkin /* Adjust for non-0 viewport offset */ 7439b6067c0SDmytro Laktyushkin if (*vp_offset) { 7449b6067c0SDmytro Laktyushkin int int_part; 7459b6067c0SDmytro Laktyushkin 7469b6067c0SDmytro Laktyushkin *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip)); 7479b6067c0SDmytro Laktyushkin int_part = dc_fixpt_floor(*init) - *vp_offset; 7489b6067c0SDmytro Laktyushkin if (int_part < taps) { 7499b6067c0SDmytro Laktyushkin int int_adj = *vp_offset >= (taps - int_part) ? 7509b6067c0SDmytro Laktyushkin (taps - int_part) : *vp_offset; 7519b6067c0SDmytro Laktyushkin *vp_offset -= int_adj; 7529b6067c0SDmytro Laktyushkin *vp_size += int_adj; 7539b6067c0SDmytro Laktyushkin int_part += int_adj; 7549b6067c0SDmytro Laktyushkin } else if (int_part > taps) { 7559b6067c0SDmytro Laktyushkin *vp_offset += int_part - taps; 7569b6067c0SDmytro Laktyushkin *vp_size -= int_part - taps; 7579b6067c0SDmytro Laktyushkin int_part = taps; 7589b6067c0SDmytro Laktyushkin } 7599b6067c0SDmytro Laktyushkin init->value &= 0xffffffff; 7609b6067c0SDmytro Laktyushkin *init = dc_fixpt_add_int(*init, int_part); 7619b6067c0SDmytro Laktyushkin } 7629b6067c0SDmytro Laktyushkin } else { 7639b6067c0SDmytro Laktyushkin /* Adjust for non-0 viewport offset */ 7649b6067c0SDmytro Laktyushkin if (*vp_offset) { 7659b6067c0SDmytro Laktyushkin int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio)); 7669b6067c0SDmytro Laktyushkin 7679b6067c0SDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 7689b6067c0SDmytro Laktyushkin *vp_size += int_part < *vp_offset ? int_part : *vp_offset; 7699b6067c0SDmytro Laktyushkin *vp_offset -= int_part < *vp_offset ? int_part : *vp_offset; 7709b6067c0SDmytro Laktyushkin } 7719b6067c0SDmytro Laktyushkin 7729b6067c0SDmytro Laktyushkin /* Adjust for viewport end clip-off */ 7739b6067c0SDmytro Laktyushkin if ((*vp_offset + *vp_size) < src_size) { 7749b6067c0SDmytro Laktyushkin int int_part; 7759b6067c0SDmytro Laktyushkin int end_offset = src_size - *vp_offset - *vp_size; 7769b6067c0SDmytro Laktyushkin 7779b6067c0SDmytro Laktyushkin /* 7789b6067c0SDmytro Laktyushkin * this is init if vp had no offset, keep in mind this is from the 7799b6067c0SDmytro Laktyushkin * right side of vp due to scan direction 7809b6067c0SDmytro Laktyushkin */ 7819b6067c0SDmytro Laktyushkin *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip)); 7829b6067c0SDmytro Laktyushkin /* 7839b6067c0SDmytro Laktyushkin * this is the difference between first pixel of viewport available to read 7849b6067c0SDmytro Laktyushkin * and init position, takning into account scan direction 7859b6067c0SDmytro Laktyushkin */ 7869b6067c0SDmytro Laktyushkin int_part = dc_fixpt_floor(*init) - end_offset; 7879b6067c0SDmytro Laktyushkin if (int_part < taps) { 7889b6067c0SDmytro Laktyushkin int int_adj = end_offset >= (taps - int_part) ? 7899b6067c0SDmytro Laktyushkin (taps - int_part) : end_offset; 7909b6067c0SDmytro Laktyushkin *vp_size += int_adj; 7919b6067c0SDmytro Laktyushkin int_part += int_adj; 7929b6067c0SDmytro Laktyushkin } else if (int_part > taps) { 7939b6067c0SDmytro Laktyushkin *vp_size += int_part - taps; 7949b6067c0SDmytro Laktyushkin int_part = taps; 7959b6067c0SDmytro Laktyushkin } 7969b6067c0SDmytro Laktyushkin init->value &= 0xffffffff; 7979b6067c0SDmytro Laktyushkin *init = dc_fixpt_add_int(*init, int_part); 7989b6067c0SDmytro Laktyushkin } 7999b6067c0SDmytro Laktyushkin } 8009b6067c0SDmytro Laktyushkin } 8019b6067c0SDmytro Laktyushkin 8029b6067c0SDmytro Laktyushkin static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx) 8039b6067c0SDmytro Laktyushkin { 8049b6067c0SDmytro Laktyushkin const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 8059b6067c0SDmytro Laktyushkin const struct dc_stream_state *stream = pipe_ctx->stream; 8066702a9acSHarry Wentland struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 8073be5262eSHarry Wentland struct rect src = pipe_ctx->plane_state->src_rect; 8089b6067c0SDmytro Laktyushkin int recout_skip_h, recout_skip_v, surf_size_h, surf_size_v; 80987449a90SAnthony Koo int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 81087449a90SAnthony Koo || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 8119b6067c0SDmytro Laktyushkin bool orthogonal_rotation, flip_vert_scan_dir, flip_horz_scan_dir; 812b2d0a103SDmytro Laktyushkin 813b0131391SDmytro Laktyushkin /* 814b0131391SDmytro Laktyushkin * Need to calculate the scan direction for viewport to make adjustments 815b0131391SDmytro Laktyushkin */ 8169b6067c0SDmytro Laktyushkin get_vp_scan_direction( 8179b6067c0SDmytro Laktyushkin plane_state->rotation, 8189b6067c0SDmytro Laktyushkin plane_state->horizontal_mirror, 8199b6067c0SDmytro Laktyushkin &orthogonal_rotation, 8209b6067c0SDmytro Laktyushkin &flip_vert_scan_dir, 8219b6067c0SDmytro Laktyushkin &flip_horz_scan_dir); 822b0131391SDmytro Laktyushkin 8239b6067c0SDmytro Laktyushkin /* Calculate src rect rotation adjusted to recout space */ 8249b6067c0SDmytro Laktyushkin surf_size_h = src.x + src.width; 8259b6067c0SDmytro Laktyushkin surf_size_v = src.y + src.height; 8269b6067c0SDmytro Laktyushkin if (flip_horz_scan_dir) 8279b6067c0SDmytro Laktyushkin src.x = 0; 8289b6067c0SDmytro Laktyushkin if (flip_vert_scan_dir) 8299b6067c0SDmytro Laktyushkin src.y = 0; 8309b6067c0SDmytro Laktyushkin if (orthogonal_rotation) { 8319b6067c0SDmytro Laktyushkin swap(src.x, src.y); 8329b6067c0SDmytro Laktyushkin swap(src.width, src.height); 8339b5349f7SMartin Tsai } 8341fbd2cfcSDmytro Laktyushkin 8359b6067c0SDmytro Laktyushkin /* Recout matching initial vp offset = recout_offset - (stream dst offset + 8369b6067c0SDmytro Laktyushkin * ((surf dst offset - stream src offset) * 1/ stream scaling ratio) 8379b6067c0SDmytro Laktyushkin * - (surf surf_src offset * 1/ full scl ratio)) 8389b6067c0SDmytro Laktyushkin */ 8399b6067c0SDmytro Laktyushkin recout_skip_h = data->recout.x - (stream->dst.x + (plane_state->dst_rect.x - stream->src.x) 8409b6067c0SDmytro Laktyushkin * stream->dst.width / stream->src.width - 8419b6067c0SDmytro Laktyushkin src.x * plane_state->dst_rect.width / src.width 8429b6067c0SDmytro Laktyushkin * stream->dst.width / stream->src.width); 8439b6067c0SDmytro Laktyushkin recout_skip_v = data->recout.y - (stream->dst.y + (plane_state->dst_rect.y - stream->src.y) 8449b6067c0SDmytro Laktyushkin * stream->dst.height / stream->src.height - 8459b6067c0SDmytro Laktyushkin src.y * plane_state->dst_rect.height / src.height 8469b6067c0SDmytro Laktyushkin * stream->dst.height / stream->src.height); 8479b6067c0SDmytro Laktyushkin if (orthogonal_rotation) 8489b6067c0SDmytro Laktyushkin swap(recout_skip_h, recout_skip_v); 849b2d0a103SDmytro Laktyushkin /* 850b2d0a103SDmytro Laktyushkin * Init calculated according to formula: 851b2d0a103SDmytro Laktyushkin * init = (scaling_ratio + number_of_taps + 1) / 2 852b2d0a103SDmytro Laktyushkin * init_bot = init + scaling_ratio 853b2d0a103SDmytro Laktyushkin * init_c = init + truncated_vp_c_offset(from calculate viewport) 854b2d0a103SDmytro Laktyushkin */ 8550002d3acSDmytro Laktyushkin data->inits.h = dc_fixpt_truncate(dc_fixpt_div_int( 8560002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.horz, data->taps.h_taps + 1), 2), 19); 857b2d0a103SDmytro Laktyushkin 8580002d3acSDmytro Laktyushkin data->inits.h_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.h_c, dc_fixpt_div_int( 8590002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.horz_c, data->taps.h_taps_c + 1), 2)), 19); 860b2d0a103SDmytro Laktyushkin 8610002d3acSDmytro Laktyushkin data->inits.v = dc_fixpt_truncate(dc_fixpt_div_int( 8620002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.vert, data->taps.v_taps + 1), 2), 19); 863b2d0a103SDmytro Laktyushkin 8640002d3acSDmytro Laktyushkin data->inits.v_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.v_c, dc_fixpt_div_int( 8650002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2)), 19); 8660002d3acSDmytro Laktyushkin 8679a08f51fSDmytro Laktyushkin /* 8689b6067c0SDmytro Laktyushkin * Taps, inits and scaling ratios are in recout space need to rotate 8699b6067c0SDmytro Laktyushkin * to viewport rotation before adjustment 8709a08f51fSDmytro Laktyushkin */ 8719b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 8729b6067c0SDmytro Laktyushkin flip_horz_scan_dir, 8739b6067c0SDmytro Laktyushkin recout_skip_h, 8749b6067c0SDmytro Laktyushkin surf_size_h, 8759b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.v_taps : data->taps.h_taps, 8769b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.vert : data->ratios.horz, 8779b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.v : &data->inits.h, 8789b6067c0SDmytro Laktyushkin &data->viewport.x, 8799b6067c0SDmytro Laktyushkin &data->viewport.width); 8809b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 8819b6067c0SDmytro Laktyushkin flip_horz_scan_dir, 8829b6067c0SDmytro Laktyushkin recout_skip_h, 8839b6067c0SDmytro Laktyushkin surf_size_h / vpc_div, 8849b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.v_taps_c : data->taps.h_taps_c, 8859b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.vert_c : data->ratios.horz_c, 8869b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.v_c : &data->inits.h_c, 8879b6067c0SDmytro Laktyushkin &data->viewport_c.x, 8889b6067c0SDmytro Laktyushkin &data->viewport_c.width); 8899b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 8909b6067c0SDmytro Laktyushkin flip_vert_scan_dir, 8919b6067c0SDmytro Laktyushkin recout_skip_v, 8929b6067c0SDmytro Laktyushkin surf_size_v, 8939b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.h_taps : data->taps.v_taps, 8949b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.horz : data->ratios.vert, 8959b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.h : &data->inits.v, 8969b6067c0SDmytro Laktyushkin &data->viewport.y, 8979b6067c0SDmytro Laktyushkin &data->viewport.height); 8989b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 8999b6067c0SDmytro Laktyushkin flip_vert_scan_dir, 9009b6067c0SDmytro Laktyushkin recout_skip_v, 9019b6067c0SDmytro Laktyushkin surf_size_v / vpc_div, 9029b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.h_taps_c : data->taps.v_taps_c, 9039b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.horz_c : data->ratios.vert_c, 9049b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.h_c : &data->inits.v_c, 9059b6067c0SDmytro Laktyushkin &data->viewport_c.y, 9069b6067c0SDmytro Laktyushkin &data->viewport_c.height); 907b2d0a103SDmytro Laktyushkin 908b2d0a103SDmytro Laktyushkin /* Interlaced inits based on final vert inits */ 909eb0e5154SDmytro Laktyushkin data->inits.v_bot = dc_fixpt_add(data->inits.v, data->ratios.vert); 910eb0e5154SDmytro Laktyushkin data->inits.v_c_bot = dc_fixpt_add(data->inits.v_c, data->ratios.vert_c); 9111fbd2cfcSDmytro Laktyushkin 912b2d0a103SDmytro Laktyushkin } 913b2d0a103SDmytro Laktyushkin 914b2d0a103SDmytro Laktyushkin bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) 915b2d0a103SDmytro Laktyushkin { 9163be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 9174fa086b9SLeo (Sunpeng) Li struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 918b2d0a103SDmytro Laktyushkin bool res = false; 9195d4b05ddSBhawanpreet Lakha DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); 9204562236bSHarry Wentland /* Important: scaling ratio calculation requires pixel format, 9214562236bSHarry Wentland * lb depth calculation requires recout and taps require scaling ratios. 922b2d0a103SDmytro Laktyushkin * Inits require viewport, taps, ratios and recout of split pipe 9234562236bSHarry Wentland */ 9246702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface( 9253be5262eSHarry Wentland pipe_ctx->plane_state->format); 9264562236bSHarry Wentland 927b2d0a103SDmytro Laktyushkin calculate_scaling_ratios(pipe_ctx); 928b2d0a103SDmytro Laktyushkin 929b2d0a103SDmytro Laktyushkin calculate_viewport(pipe_ctx); 9304562236bSHarry Wentland 9316702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.viewport.height < 16 || pipe_ctx->plane_res.scl_data.viewport.width < 16) 9324562236bSHarry Wentland return false; 9334562236bSHarry Wentland 9349b6067c0SDmytro Laktyushkin calculate_recout(pipe_ctx); 9354562236bSHarry Wentland 9364562236bSHarry Wentland /** 9374562236bSHarry Wentland * Setting line buffer pixel depth to 24bpp yields banding 9384562236bSHarry Wentland * on certain displays, such as the Sharp 4k 9394562236bSHarry Wentland */ 9406702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; 9414562236bSHarry Wentland 942199e458aSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left; 94358bb0e63SAndrew Jiang pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top; 944199e458aSDmytro Laktyushkin 94558bb0e63SAndrew Jiang pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right; 94658bb0e63SAndrew Jiang pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + timing->v_border_top + timing->v_border_bottom; 9471b6c8067SBhawanpreet Lakha 9484562236bSHarry Wentland /* Taps calculations */ 949d94585a0SYue Hin Lau if (pipe_ctx->plane_res.xfm != NULL) 95086a66c4eSHarry Wentland res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 95186a66c4eSHarry Wentland pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 9524562236bSHarry Wentland 953d94585a0SYue Hin Lau if (pipe_ctx->plane_res.dpp != NULL) 954d94585a0SYue Hin Lau res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 955d94585a0SYue Hin Lau pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 9564562236bSHarry Wentland if (!res) { 9574562236bSHarry Wentland /* Try 24 bpp linebuffer */ 9586702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; 9594562236bSHarry Wentland 9601b6c8067SBhawanpreet Lakha if (pipe_ctx->plane_res.xfm != NULL) 96186a66c4eSHarry Wentland res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 9621b6c8067SBhawanpreet Lakha pipe_ctx->plane_res.xfm, 9631b6c8067SBhawanpreet Lakha &pipe_ctx->plane_res.scl_data, 9641b6c8067SBhawanpreet Lakha &plane_state->scaling_quality); 965d94585a0SYue Hin Lau 9661b6c8067SBhawanpreet Lakha if (pipe_ctx->plane_res.dpp != NULL) 967d94585a0SYue Hin Lau res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 9681b6c8067SBhawanpreet Lakha pipe_ctx->plane_res.dpp, 9691b6c8067SBhawanpreet Lakha &pipe_ctx->plane_res.scl_data, 9701b6c8067SBhawanpreet Lakha &plane_state->scaling_quality); 9714562236bSHarry Wentland } 9724562236bSHarry Wentland 973b2d0a103SDmytro Laktyushkin if (res) 9741fbd2cfcSDmytro Laktyushkin /* May need to re-check lb size after this in some obscure scenario */ 9759b6067c0SDmytro Laktyushkin calculate_inits_and_adj_vp(pipe_ctx); 976b2d0a103SDmytro Laktyushkin 9771296423bSBhawanpreet Lakha DC_LOG_SCALER( 9784562236bSHarry Wentland "%s: Viewport:\nheight:%d width:%d x:%d " 9794562236bSHarry Wentland "y:%d\n dst_rect:\nheight:%d width:%d x:%d " 9804562236bSHarry Wentland "y:%d\n", 9814562236bSHarry Wentland __func__, 9826702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.height, 9836702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.width, 9846702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.x, 9856702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.y, 9863be5262eSHarry Wentland plane_state->dst_rect.height, 9873be5262eSHarry Wentland plane_state->dst_rect.width, 9883be5262eSHarry Wentland plane_state->dst_rect.x, 9893be5262eSHarry Wentland plane_state->dst_rect.y); 9904562236bSHarry Wentland 9914562236bSHarry Wentland return res; 9924562236bSHarry Wentland } 9934562236bSHarry Wentland 9944562236bSHarry Wentland 9954562236bSHarry Wentland enum dc_status resource_build_scaling_params_for_context( 996fb3466a4SBhawanpreet Lakha const struct dc *dc, 997608ac7bbSJerry Zuo struct dc_state *context) 9984562236bSHarry Wentland { 9994562236bSHarry Wentland int i; 10004562236bSHarry Wentland 10014562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 10023be5262eSHarry Wentland if (context->res_ctx.pipe_ctx[i].plane_state != NULL && 10034562236bSHarry Wentland context->res_ctx.pipe_ctx[i].stream != NULL) 1004b2d0a103SDmytro Laktyushkin if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i])) 1005f84a8161STony Cheng return DC_FAIL_SCALING; 10064562236bSHarry Wentland } 10074562236bSHarry Wentland 10084562236bSHarry Wentland return DC_OK; 10094562236bSHarry Wentland } 10104562236bSHarry Wentland 1011a2b8659dSTony Cheng struct pipe_ctx *find_idle_secondary_pipe( 1012a2b8659dSTony Cheng struct resource_context *res_ctx, 1013a2b8659dSTony Cheng const struct resource_pool *pool) 10144562236bSHarry Wentland { 10154562236bSHarry Wentland int i; 10164562236bSHarry Wentland struct pipe_ctx *secondary_pipe = NULL; 10174562236bSHarry Wentland 10184562236bSHarry Wentland /* 10194562236bSHarry Wentland * search backwards for the second pipe to keep pipe 10204562236bSHarry Wentland * assignment more consistent 10214562236bSHarry Wentland */ 10224562236bSHarry Wentland 1023a2b8659dSTony Cheng for (i = pool->pipe_count - 1; i >= 0; i--) { 10244562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == NULL) { 10254562236bSHarry Wentland secondary_pipe = &res_ctx->pipe_ctx[i]; 10264562236bSHarry Wentland secondary_pipe->pipe_idx = i; 10274562236bSHarry Wentland break; 10284562236bSHarry Wentland } 10294562236bSHarry Wentland } 10304562236bSHarry Wentland 10314562236bSHarry Wentland 10324562236bSHarry Wentland return secondary_pipe; 10334562236bSHarry Wentland } 10344562236bSHarry Wentland 10354562236bSHarry Wentland struct pipe_ctx *resource_get_head_pipe_for_stream( 10364562236bSHarry Wentland struct resource_context *res_ctx, 10370971c40eSHarry Wentland struct dc_stream_state *stream) 10384562236bSHarry Wentland { 10394562236bSHarry Wentland int i; 1040a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 10414562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == stream && 10421dc90497SAndrey Grodzovsky !res_ctx->pipe_ctx[i].top_pipe) { 10434562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 10444562236bSHarry Wentland break; 10454562236bSHarry Wentland } 10464562236bSHarry Wentland } 10474562236bSHarry Wentland return NULL; 10484562236bSHarry Wentland } 10494562236bSHarry Wentland 105019f89e23SAndrey Grodzovsky static struct pipe_ctx *resource_get_tail_pipe_for_stream( 105119f89e23SAndrey Grodzovsky struct resource_context *res_ctx, 105219f89e23SAndrey Grodzovsky struct dc_stream_state *stream) 105319f89e23SAndrey Grodzovsky { 105419f89e23SAndrey Grodzovsky struct pipe_ctx *head_pipe, *tail_pipe; 105519f89e23SAndrey Grodzovsky head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream); 105619f89e23SAndrey Grodzovsky 105719f89e23SAndrey Grodzovsky if (!head_pipe) 105819f89e23SAndrey Grodzovsky return NULL; 105919f89e23SAndrey Grodzovsky 106019f89e23SAndrey Grodzovsky tail_pipe = head_pipe->bottom_pipe; 106119f89e23SAndrey Grodzovsky 106219f89e23SAndrey Grodzovsky while (tail_pipe) { 106319f89e23SAndrey Grodzovsky head_pipe = tail_pipe; 106419f89e23SAndrey Grodzovsky tail_pipe = tail_pipe->bottom_pipe; 106519f89e23SAndrey Grodzovsky } 106619f89e23SAndrey Grodzovsky 106719f89e23SAndrey Grodzovsky return head_pipe; 106819f89e23SAndrey Grodzovsky } 106919f89e23SAndrey Grodzovsky 10704562236bSHarry Wentland /* 1071ab2541b6SAric Cyr * A free_pipe for a stream is defined here as a pipe 1072ab2541b6SAric Cyr * that has no surface attached yet 10734562236bSHarry Wentland */ 1074ab2541b6SAric Cyr static struct pipe_ctx *acquire_free_pipe_for_stream( 1075608ac7bbSJerry Zuo struct dc_state *context, 1076a2b8659dSTony Cheng const struct resource_pool *pool, 10770971c40eSHarry Wentland struct dc_stream_state *stream) 10784562236bSHarry Wentland { 10794562236bSHarry Wentland int i; 1080745cc746SDmytro Laktyushkin struct resource_context *res_ctx = &context->res_ctx; 10814562236bSHarry Wentland 10824562236bSHarry Wentland struct pipe_ctx *head_pipe = NULL; 10834562236bSHarry Wentland 10844562236bSHarry Wentland /* Find head pipe, which has the back end set up*/ 10854562236bSHarry Wentland 10864562236bSHarry Wentland head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream); 10874562236bSHarry Wentland 1088e41ab030SHarry Wentland if (!head_pipe) { 10894562236bSHarry Wentland ASSERT(0); 1090e41ab030SHarry Wentland return NULL; 1091e41ab030SHarry Wentland } 10924562236bSHarry Wentland 10933be5262eSHarry Wentland if (!head_pipe->plane_state) 10944562236bSHarry Wentland return head_pipe; 10954562236bSHarry Wentland 10964562236bSHarry Wentland /* Re-use pipe already acquired for this stream if available*/ 1097a2b8659dSTony Cheng for (i = pool->pipe_count - 1; i >= 0; i--) { 10984562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == stream && 10993be5262eSHarry Wentland !res_ctx->pipe_ctx[i].plane_state) { 11004562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 11014562236bSHarry Wentland } 11024562236bSHarry Wentland } 11034562236bSHarry Wentland 11044562236bSHarry Wentland /* 11054562236bSHarry Wentland * At this point we have no re-useable pipe for this stream and we need 11064562236bSHarry Wentland * to acquire an idle one to satisfy the request 11074562236bSHarry Wentland */ 11084562236bSHarry Wentland 1109a2b8659dSTony Cheng if (!pool->funcs->acquire_idle_pipe_for_layer) 11104562236bSHarry Wentland return NULL; 11114562236bSHarry Wentland 1112a2b8659dSTony Cheng return pool->funcs->acquire_idle_pipe_for_layer(context, pool, stream); 11134562236bSHarry Wentland 11144562236bSHarry Wentland } 11154562236bSHarry Wentland 1116dc37a9a0SLeo (Sunpeng) Li #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 11170f9a536fSDmytro Laktyushkin static int acquire_first_split_pipe( 11180f9a536fSDmytro Laktyushkin struct resource_context *res_ctx, 11190f9a536fSDmytro Laktyushkin const struct resource_pool *pool, 11200971c40eSHarry Wentland struct dc_stream_state *stream) 11210f9a536fSDmytro Laktyushkin { 11220f9a536fSDmytro Laktyushkin int i; 11230f9a536fSDmytro Laktyushkin 11240f9a536fSDmytro Laktyushkin for (i = 0; i < pool->pipe_count; i++) { 11250f9a536fSDmytro Laktyushkin struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 11260f9a536fSDmytro Laktyushkin 11270f9a536fSDmytro Laktyushkin if (pipe_ctx->top_pipe && 11283be5262eSHarry Wentland pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state) { 11290f9a536fSDmytro Laktyushkin pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; 11300f9a536fSDmytro Laktyushkin if (pipe_ctx->bottom_pipe) 11310f9a536fSDmytro Laktyushkin pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; 11320f9a536fSDmytro Laktyushkin 11330f9a536fSDmytro Laktyushkin memset(pipe_ctx, 0, sizeof(*pipe_ctx)); 11346b670fa9SHarry Wentland pipe_ctx->stream_res.tg = pool->timing_generators[i]; 11358feabd03SYue Hin Lau pipe_ctx->plane_res.hubp = pool->hubps[i]; 113686a66c4eSHarry Wentland pipe_ctx->plane_res.ipp = pool->ipps[i]; 1137d94585a0SYue Hin Lau pipe_ctx->plane_res.dpp = pool->dpps[i]; 1138a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp = pool->opps[i]; 1139e07f541fSYongqiang Sun pipe_ctx->plane_res.mpcc_inst = pool->dpps[i]->inst; 11400f9a536fSDmytro Laktyushkin pipe_ctx->pipe_idx = i; 11410f9a536fSDmytro Laktyushkin 11420f9a536fSDmytro Laktyushkin pipe_ctx->stream = stream; 11430f9a536fSDmytro Laktyushkin return i; 11440f9a536fSDmytro Laktyushkin } 11450f9a536fSDmytro Laktyushkin } 11460f9a536fSDmytro Laktyushkin return -1; 11470f9a536fSDmytro Laktyushkin } 11480f9a536fSDmytro Laktyushkin #endif 11490f9a536fSDmytro Laktyushkin 115019f89e23SAndrey Grodzovsky bool dc_add_plane_to_context( 115119f89e23SAndrey Grodzovsky const struct dc *dc, 11520971c40eSHarry Wentland struct dc_stream_state *stream, 115319f89e23SAndrey Grodzovsky struct dc_plane_state *plane_state, 1154608ac7bbSJerry Zuo struct dc_state *context) 11554562236bSHarry Wentland { 11564562236bSHarry Wentland int i; 115719f89e23SAndrey Grodzovsky struct resource_pool *pool = dc->res_pool; 115819f89e23SAndrey Grodzovsky struct pipe_ctx *head_pipe, *tail_pipe, *free_pipe; 1159ab2541b6SAric Cyr struct dc_stream_status *stream_status = NULL; 11604562236bSHarry Wentland 1161ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) 11624fa086b9SLeo (Sunpeng) Li if (context->streams[i] == stream) { 1163ab2541b6SAric Cyr stream_status = &context->stream_status[i]; 11644562236bSHarry Wentland break; 11654562236bSHarry Wentland } 1166ab2541b6SAric Cyr if (stream_status == NULL) { 116719f89e23SAndrey Grodzovsky dm_error("Existing stream not found; failed to attach surface!\n"); 116819f89e23SAndrey Grodzovsky return false; 116919f89e23SAndrey Grodzovsky } 117019f89e23SAndrey Grodzovsky 117119f89e23SAndrey Grodzovsky 117219f89e23SAndrey Grodzovsky if (stream_status->plane_count == MAX_SURFACE_NUM) { 117319f89e23SAndrey Grodzovsky dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n", 117419f89e23SAndrey Grodzovsky plane_state, MAX_SURFACE_NUM); 117519f89e23SAndrey Grodzovsky return false; 117619f89e23SAndrey Grodzovsky } 117719f89e23SAndrey Grodzovsky 117819f89e23SAndrey Grodzovsky head_pipe = resource_get_head_pipe_for_stream(&context->res_ctx, stream); 117919f89e23SAndrey Grodzovsky 118019f89e23SAndrey Grodzovsky if (!head_pipe) { 118119f89e23SAndrey Grodzovsky dm_error("Head pipe not found for stream_state %p !\n", stream); 11824562236bSHarry Wentland return false; 11834562236bSHarry Wentland } 11844562236bSHarry Wentland 118500737c59SEric Bernstein tail_pipe = resource_get_tail_pipe_for_stream(&context->res_ctx, stream); 118600737c59SEric Bernstein ASSERT(tail_pipe); 118700737c59SEric Bernstein 118819f89e23SAndrey Grodzovsky free_pipe = acquire_free_pipe_for_stream(context, pool, stream); 11894562236bSHarry Wentland 1190dc37a9a0SLeo (Sunpeng) Li #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 11910f9a536fSDmytro Laktyushkin if (!free_pipe) { 11920f9a536fSDmytro Laktyushkin int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 11930f9a536fSDmytro Laktyushkin if (pipe_idx >= 0) 11940f9a536fSDmytro Laktyushkin free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; 11950f9a536fSDmytro Laktyushkin } 11960f9a536fSDmytro Laktyushkin #endif 1197abb4986eSAndrew Jiang if (!free_pipe) 11984562236bSHarry Wentland return false; 11994562236bSHarry Wentland 1200abb4986eSAndrew Jiang /* retain new surfaces */ 1201abb4986eSAndrew Jiang dc_plane_state_retain(plane_state); 12023be5262eSHarry Wentland free_pipe->plane_state = plane_state; 12034562236bSHarry Wentland 120419f89e23SAndrey Grodzovsky if (head_pipe != free_pipe) { 12056b670fa9SHarry Wentland free_pipe->stream_res.tg = tail_pipe->stream_res.tg; 12069aef1a31SSivapiriyanKumarasamy free_pipe->stream_res.abm = tail_pipe->stream_res.abm; 1207a6a6cb34SHarry Wentland free_pipe->stream_res.opp = tail_pipe->stream_res.opp; 12088e9c4c8cSHarry Wentland free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; 1209afaacef4SHarry Wentland free_pipe->stream_res.audio = tail_pipe->stream_res.audio; 1210cfe4645eSDmytro Laktyushkin free_pipe->clock_source = tail_pipe->clock_source; 12114562236bSHarry Wentland free_pipe->top_pipe = tail_pipe; 12124562236bSHarry Wentland tail_pipe->bottom_pipe = free_pipe; 12134562236bSHarry Wentland } 12144562236bSHarry Wentland 12154562236bSHarry Wentland /* assign new surfaces*/ 121619f89e23SAndrey Grodzovsky stream_status->plane_states[stream_status->plane_count] = plane_state; 12174562236bSHarry Wentland 121819f89e23SAndrey Grodzovsky stream_status->plane_count++; 12194562236bSHarry Wentland 12204562236bSHarry Wentland return true; 12214562236bSHarry Wentland } 12224562236bSHarry Wentland 122319f89e23SAndrey Grodzovsky bool dc_remove_plane_from_context( 122419f89e23SAndrey Grodzovsky const struct dc *dc, 122519f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 122619f89e23SAndrey Grodzovsky struct dc_plane_state *plane_state, 1227608ac7bbSJerry Zuo struct dc_state *context) 122819f89e23SAndrey Grodzovsky { 122919f89e23SAndrey Grodzovsky int i; 123019f89e23SAndrey Grodzovsky struct dc_stream_status *stream_status = NULL; 123119f89e23SAndrey Grodzovsky struct resource_pool *pool = dc->res_pool; 123219f89e23SAndrey Grodzovsky 123319f89e23SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 123419f89e23SAndrey Grodzovsky if (context->streams[i] == stream) { 123519f89e23SAndrey Grodzovsky stream_status = &context->stream_status[i]; 123619f89e23SAndrey Grodzovsky break; 123719f89e23SAndrey Grodzovsky } 123819f89e23SAndrey Grodzovsky 123919f89e23SAndrey Grodzovsky if (stream_status == NULL) { 124019f89e23SAndrey Grodzovsky dm_error("Existing stream not found; failed to remove plane.\n"); 124119f89e23SAndrey Grodzovsky return false; 124219f89e23SAndrey Grodzovsky } 124319f89e23SAndrey Grodzovsky 124419f89e23SAndrey Grodzovsky /* release pipe for plane*/ 124519f89e23SAndrey Grodzovsky for (i = pool->pipe_count - 1; i >= 0; i--) { 124619f89e23SAndrey Grodzovsky struct pipe_ctx *pipe_ctx; 124719f89e23SAndrey Grodzovsky 124819f89e23SAndrey Grodzovsky if (context->res_ctx.pipe_ctx[i].plane_state == plane_state) { 124919f89e23SAndrey Grodzovsky pipe_ctx = &context->res_ctx.pipe_ctx[i]; 125019f89e23SAndrey Grodzovsky 125119f89e23SAndrey Grodzovsky if (pipe_ctx->top_pipe) 125219f89e23SAndrey Grodzovsky pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; 125319f89e23SAndrey Grodzovsky 125419f89e23SAndrey Grodzovsky /* Second condition is to avoid setting NULL to top pipe 125519f89e23SAndrey Grodzovsky * of tail pipe making it look like head pipe in subsequent 125619f89e23SAndrey Grodzovsky * deletes 125719f89e23SAndrey Grodzovsky */ 125819f89e23SAndrey Grodzovsky if (pipe_ctx->bottom_pipe && pipe_ctx->top_pipe) 125919f89e23SAndrey Grodzovsky pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; 126019f89e23SAndrey Grodzovsky 126119f89e23SAndrey Grodzovsky /* 126219f89e23SAndrey Grodzovsky * For head pipe detach surfaces from pipe for tail 126319f89e23SAndrey Grodzovsky * pipe just zero it out 126419f89e23SAndrey Grodzovsky */ 126519f89e23SAndrey Grodzovsky if (!pipe_ctx->top_pipe) { 126619f89e23SAndrey Grodzovsky pipe_ctx->plane_state = NULL; 126719f89e23SAndrey Grodzovsky pipe_ctx->bottom_pipe = NULL; 126819f89e23SAndrey Grodzovsky } else { 126919f89e23SAndrey Grodzovsky memset(pipe_ctx, 0, sizeof(*pipe_ctx)); 127019f89e23SAndrey Grodzovsky } 127119f89e23SAndrey Grodzovsky } 127219f89e23SAndrey Grodzovsky } 127319f89e23SAndrey Grodzovsky 127419f89e23SAndrey Grodzovsky 127519f89e23SAndrey Grodzovsky for (i = 0; i < stream_status->plane_count; i++) { 127619f89e23SAndrey Grodzovsky if (stream_status->plane_states[i] == plane_state) { 127719f89e23SAndrey Grodzovsky 127819f89e23SAndrey Grodzovsky dc_plane_state_release(stream_status->plane_states[i]); 127919f89e23SAndrey Grodzovsky break; 128019f89e23SAndrey Grodzovsky } 128119f89e23SAndrey Grodzovsky } 128219f89e23SAndrey Grodzovsky 128319f89e23SAndrey Grodzovsky if (i == stream_status->plane_count) { 128419f89e23SAndrey Grodzovsky dm_error("Existing plane_state not found; failed to detach it!\n"); 128519f89e23SAndrey Grodzovsky return false; 128619f89e23SAndrey Grodzovsky } 128719f89e23SAndrey Grodzovsky 128819f89e23SAndrey Grodzovsky stream_status->plane_count--; 128919f89e23SAndrey Grodzovsky 1290abb4986eSAndrew Jiang /* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */ 1291abb4986eSAndrew Jiang for (; i < stream_status->plane_count; i++) 129219f89e23SAndrey Grodzovsky stream_status->plane_states[i] = stream_status->plane_states[i + 1]; 129319f89e23SAndrey Grodzovsky 129419f89e23SAndrey Grodzovsky stream_status->plane_states[stream_status->plane_count] = NULL; 129519f89e23SAndrey Grodzovsky 129619f89e23SAndrey Grodzovsky return true; 129719f89e23SAndrey Grodzovsky } 129819f89e23SAndrey Grodzovsky 129919f89e23SAndrey Grodzovsky bool dc_rem_all_planes_for_stream( 130019f89e23SAndrey Grodzovsky const struct dc *dc, 130119f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 1302608ac7bbSJerry Zuo struct dc_state *context) 130319f89e23SAndrey Grodzovsky { 130419f89e23SAndrey Grodzovsky int i, old_plane_count; 130519f89e23SAndrey Grodzovsky struct dc_stream_status *stream_status = NULL; 130619f89e23SAndrey Grodzovsky struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 }; 130719f89e23SAndrey Grodzovsky 130819f89e23SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 130919f89e23SAndrey Grodzovsky if (context->streams[i] == stream) { 131019f89e23SAndrey Grodzovsky stream_status = &context->stream_status[i]; 131119f89e23SAndrey Grodzovsky break; 131219f89e23SAndrey Grodzovsky } 131319f89e23SAndrey Grodzovsky 131419f89e23SAndrey Grodzovsky if (stream_status == NULL) { 131519f89e23SAndrey Grodzovsky dm_error("Existing stream %p not found!\n", stream); 131619f89e23SAndrey Grodzovsky return false; 131719f89e23SAndrey Grodzovsky } 131819f89e23SAndrey Grodzovsky 131919f89e23SAndrey Grodzovsky old_plane_count = stream_status->plane_count; 132019f89e23SAndrey Grodzovsky 132119f89e23SAndrey Grodzovsky for (i = 0; i < old_plane_count; i++) 132219f89e23SAndrey Grodzovsky del_planes[i] = stream_status->plane_states[i]; 132319f89e23SAndrey Grodzovsky 132419f89e23SAndrey Grodzovsky for (i = 0; i < old_plane_count; i++) 132519f89e23SAndrey Grodzovsky if (!dc_remove_plane_from_context(dc, stream, del_planes[i], context)) 132619f89e23SAndrey Grodzovsky return false; 132719f89e23SAndrey Grodzovsky 132819f89e23SAndrey Grodzovsky return true; 132919f89e23SAndrey Grodzovsky } 133019f89e23SAndrey Grodzovsky 133119f89e23SAndrey Grodzovsky static bool add_all_planes_for_stream( 133219f89e23SAndrey Grodzovsky const struct dc *dc, 133319f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 133419f89e23SAndrey Grodzovsky const struct dc_validation_set set[], 133519f89e23SAndrey Grodzovsky int set_count, 1336608ac7bbSJerry Zuo struct dc_state *context) 133719f89e23SAndrey Grodzovsky { 133819f89e23SAndrey Grodzovsky int i, j; 133919f89e23SAndrey Grodzovsky 134019f89e23SAndrey Grodzovsky for (i = 0; i < set_count; i++) 134119f89e23SAndrey Grodzovsky if (set[i].stream == stream) 134219f89e23SAndrey Grodzovsky break; 134319f89e23SAndrey Grodzovsky 134419f89e23SAndrey Grodzovsky if (i == set_count) { 134519f89e23SAndrey Grodzovsky dm_error("Stream %p not found in set!\n", stream); 134619f89e23SAndrey Grodzovsky return false; 134719f89e23SAndrey Grodzovsky } 134819f89e23SAndrey Grodzovsky 134919f89e23SAndrey Grodzovsky for (j = 0; j < set[i].plane_count; j++) 135019f89e23SAndrey Grodzovsky if (!dc_add_plane_to_context(dc, stream, set[i].plane_states[j], context)) 135119f89e23SAndrey Grodzovsky return false; 135219f89e23SAndrey Grodzovsky 135319f89e23SAndrey Grodzovsky return true; 135419f89e23SAndrey Grodzovsky } 135519f89e23SAndrey Grodzovsky 135619f89e23SAndrey Grodzovsky bool dc_add_all_planes_for_stream( 135719f89e23SAndrey Grodzovsky const struct dc *dc, 135819f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 135919f89e23SAndrey Grodzovsky struct dc_plane_state * const *plane_states, 136019f89e23SAndrey Grodzovsky int plane_count, 1361608ac7bbSJerry Zuo struct dc_state *context) 136219f89e23SAndrey Grodzovsky { 136319f89e23SAndrey Grodzovsky struct dc_validation_set set; 136419f89e23SAndrey Grodzovsky int i; 136519f89e23SAndrey Grodzovsky 136619f89e23SAndrey Grodzovsky set.stream = stream; 136719f89e23SAndrey Grodzovsky set.plane_count = plane_count; 136819f89e23SAndrey Grodzovsky 136919f89e23SAndrey Grodzovsky for (i = 0; i < plane_count; i++) 137019f89e23SAndrey Grodzovsky set.plane_states[i] = plane_states[i]; 137119f89e23SAndrey Grodzovsky 137219f89e23SAndrey Grodzovsky return add_all_planes_for_stream(dc, stream, &set, 1, context); 137319f89e23SAndrey Grodzovsky } 137419f89e23SAndrey Grodzovsky 137519f89e23SAndrey Grodzovsky 13766b622181SJulian Parkin static bool is_hdr_static_meta_changed(struct dc_stream_state *cur_stream, 13776b622181SJulian Parkin struct dc_stream_state *new_stream) 13786b622181SJulian Parkin { 13796b622181SJulian Parkin if (cur_stream == NULL) 13806b622181SJulian Parkin return true; 13816b622181SJulian Parkin 13826b622181SJulian Parkin if (memcmp(&cur_stream->hdr_static_metadata, 13836b622181SJulian Parkin &new_stream->hdr_static_metadata, 13846b622181SJulian Parkin sizeof(struct dc_info_packet)) != 0) 13856b622181SJulian Parkin return true; 13866b622181SJulian Parkin 13876b622181SJulian Parkin return false; 13886b622181SJulian Parkin } 13894562236bSHarry Wentland 13901336926fSAlvin lee static bool is_vsc_info_packet_changed(struct dc_stream_state *cur_stream, 13911336926fSAlvin lee struct dc_stream_state *new_stream) 13921336926fSAlvin lee { 13931336926fSAlvin lee if (cur_stream == NULL) 13941336926fSAlvin lee return true; 13951336926fSAlvin lee 13961336926fSAlvin lee if (memcmp(&cur_stream->vsc_infopacket, 13971336926fSAlvin lee &new_stream->vsc_infopacket, 13981336926fSAlvin lee sizeof(struct dc_info_packet)) != 0) 13991336926fSAlvin lee return true; 14001336926fSAlvin lee 14011336926fSAlvin lee return false; 14021336926fSAlvin lee } 14031336926fSAlvin lee 14040971c40eSHarry Wentland static bool is_timing_changed(struct dc_stream_state *cur_stream, 14050971c40eSHarry Wentland struct dc_stream_state *new_stream) 14064562236bSHarry Wentland { 14074562236bSHarry Wentland if (cur_stream == NULL) 14084562236bSHarry Wentland return true; 14094562236bSHarry Wentland 14104562236bSHarry Wentland /* If sink pointer changed, it means this is a hotplug, we should do 14114562236bSHarry Wentland * full hw setting. 14124562236bSHarry Wentland */ 14134562236bSHarry Wentland if (cur_stream->sink != new_stream->sink) 14144562236bSHarry Wentland return true; 14154562236bSHarry Wentland 14164562236bSHarry Wentland /* If output color space is changed, need to reprogram info frames */ 14174fa086b9SLeo (Sunpeng) Li if (cur_stream->output_color_space != new_stream->output_color_space) 14184562236bSHarry Wentland return true; 14194562236bSHarry Wentland 14204562236bSHarry Wentland return memcmp( 14214fa086b9SLeo (Sunpeng) Li &cur_stream->timing, 14224fa086b9SLeo (Sunpeng) Li &new_stream->timing, 14234562236bSHarry Wentland sizeof(struct dc_crtc_timing)) != 0; 14244562236bSHarry Wentland } 14254562236bSHarry Wentland 14264562236bSHarry Wentland static bool are_stream_backends_same( 14270971c40eSHarry Wentland struct dc_stream_state *stream_a, struct dc_stream_state *stream_b) 14284562236bSHarry Wentland { 14294562236bSHarry Wentland if (stream_a == stream_b) 14304562236bSHarry Wentland return true; 14314562236bSHarry Wentland 14324562236bSHarry Wentland if (stream_a == NULL || stream_b == NULL) 14334562236bSHarry Wentland return false; 14344562236bSHarry Wentland 14354562236bSHarry Wentland if (is_timing_changed(stream_a, stream_b)) 14364562236bSHarry Wentland return false; 14374562236bSHarry Wentland 14386b622181SJulian Parkin if (is_hdr_static_meta_changed(stream_a, stream_b)) 14396b622181SJulian Parkin return false; 14406b622181SJulian Parkin 14411e7e86c4SSamson Tam if (stream_a->dpms_off != stream_b->dpms_off) 14421e7e86c4SSamson Tam return false; 14431e7e86c4SSamson Tam 14441336926fSAlvin lee if (is_vsc_info_packet_changed(stream_a, stream_b)) 14451336926fSAlvin lee return false; 14461336926fSAlvin lee 14474562236bSHarry Wentland return true; 14484562236bSHarry Wentland } 14494562236bSHarry Wentland 1450d54d29dbSBhawanpreet Lakha bool dc_is_stream_unchanged( 14510971c40eSHarry Wentland struct dc_stream_state *old_stream, struct dc_stream_state *stream) 14524562236bSHarry Wentland { 14534562236bSHarry Wentland 14544562236bSHarry Wentland if (!are_stream_backends_same(old_stream, stream)) 14554562236bSHarry Wentland return false; 14564562236bSHarry Wentland 14574562236bSHarry Wentland return true; 14584562236bSHarry Wentland } 14594562236bSHarry Wentland 14609a5d9c48SLeo (Sunpeng) Li bool dc_is_stream_scaling_unchanged( 14619a5d9c48SLeo (Sunpeng) Li struct dc_stream_state *old_stream, struct dc_stream_state *stream) 14629a5d9c48SLeo (Sunpeng) Li { 14639a5d9c48SLeo (Sunpeng) Li if (old_stream == stream) 14649a5d9c48SLeo (Sunpeng) Li return true; 14659a5d9c48SLeo (Sunpeng) Li 14669a5d9c48SLeo (Sunpeng) Li if (old_stream == NULL || stream == NULL) 14679a5d9c48SLeo (Sunpeng) Li return false; 14689a5d9c48SLeo (Sunpeng) Li 14699a5d9c48SLeo (Sunpeng) Li if (memcmp(&old_stream->src, 14709a5d9c48SLeo (Sunpeng) Li &stream->src, 14719a5d9c48SLeo (Sunpeng) Li sizeof(struct rect)) != 0) 14729a5d9c48SLeo (Sunpeng) Li return false; 14739a5d9c48SLeo (Sunpeng) Li 14749a5d9c48SLeo (Sunpeng) Li if (memcmp(&old_stream->dst, 14759a5d9c48SLeo (Sunpeng) Li &stream->dst, 14769a5d9c48SLeo (Sunpeng) Li sizeof(struct rect)) != 0) 14779a5d9c48SLeo (Sunpeng) Li return false; 14789a5d9c48SLeo (Sunpeng) Li 14799a5d9c48SLeo (Sunpeng) Li return true; 14809a5d9c48SLeo (Sunpeng) Li } 14819a5d9c48SLeo (Sunpeng) Li 14821dc90497SAndrey Grodzovsky static void update_stream_engine_usage( 14834562236bSHarry Wentland struct resource_context *res_ctx, 1484a2b8659dSTony Cheng const struct resource_pool *pool, 14851dc90497SAndrey Grodzovsky struct stream_encoder *stream_enc, 14861dc90497SAndrey Grodzovsky bool acquired) 14874562236bSHarry Wentland { 14884562236bSHarry Wentland int i; 14894562236bSHarry Wentland 1490a2b8659dSTony Cheng for (i = 0; i < pool->stream_enc_count; i++) { 1491a2b8659dSTony Cheng if (pool->stream_enc[i] == stream_enc) 14921dc90497SAndrey Grodzovsky res_ctx->is_stream_enc_acquired[i] = acquired; 14934562236bSHarry Wentland } 14944562236bSHarry Wentland } 14954562236bSHarry Wentland 14964562236bSHarry Wentland /* TODO: release audio object */ 14974176664bSCharlene Liu void update_audio_usage( 14984562236bSHarry Wentland struct resource_context *res_ctx, 1499a2b8659dSTony Cheng const struct resource_pool *pool, 15001dc90497SAndrey Grodzovsky struct audio *audio, 15011dc90497SAndrey Grodzovsky bool acquired) 15024562236bSHarry Wentland { 15034562236bSHarry Wentland int i; 1504a2b8659dSTony Cheng for (i = 0; i < pool->audio_count; i++) { 1505a2b8659dSTony Cheng if (pool->audios[i] == audio) 15061dc90497SAndrey Grodzovsky res_ctx->is_audio_acquired[i] = acquired; 15074562236bSHarry Wentland } 15084562236bSHarry Wentland } 15094562236bSHarry Wentland 15104562236bSHarry Wentland static int acquire_first_free_pipe( 15114562236bSHarry Wentland struct resource_context *res_ctx, 1512a2b8659dSTony Cheng const struct resource_pool *pool, 15130971c40eSHarry Wentland struct dc_stream_state *stream) 15144562236bSHarry Wentland { 15154562236bSHarry Wentland int i; 15164562236bSHarry Wentland 1517a2b8659dSTony Cheng for (i = 0; i < pool->pipe_count; i++) { 15184562236bSHarry Wentland if (!res_ctx->pipe_ctx[i].stream) { 15194562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 15204562236bSHarry Wentland 15216b670fa9SHarry Wentland pipe_ctx->stream_res.tg = pool->timing_generators[i]; 152286a66c4eSHarry Wentland pipe_ctx->plane_res.mi = pool->mis[i]; 15238feabd03SYue Hin Lau pipe_ctx->plane_res.hubp = pool->hubps[i]; 152486a66c4eSHarry Wentland pipe_ctx->plane_res.ipp = pool->ipps[i]; 152586a66c4eSHarry Wentland pipe_ctx->plane_res.xfm = pool->transforms[i]; 1526d94585a0SYue Hin Lau pipe_ctx->plane_res.dpp = pool->dpps[i]; 1527a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp = pool->opps[i]; 1528bc373a89SRoman Li if (pool->dpps[i]) 1529e07f541fSYongqiang Sun pipe_ctx->plane_res.mpcc_inst = pool->dpps[i]->inst; 15304562236bSHarry Wentland pipe_ctx->pipe_idx = i; 15314562236bSHarry Wentland 1532ff5ef992SAlex Deucher 15334562236bSHarry Wentland pipe_ctx->stream = stream; 15344562236bSHarry Wentland return i; 15354562236bSHarry Wentland } 15364562236bSHarry Wentland } 15374562236bSHarry Wentland return -1; 15384562236bSHarry Wentland } 15394562236bSHarry Wentland 15404562236bSHarry Wentland static struct stream_encoder *find_first_free_match_stream_enc_for_link( 15414562236bSHarry Wentland struct resource_context *res_ctx, 1542a2b8659dSTony Cheng const struct resource_pool *pool, 15430971c40eSHarry Wentland struct dc_stream_state *stream) 15444562236bSHarry Wentland { 15454562236bSHarry Wentland int i; 15464562236bSHarry Wentland int j = -1; 1547d0778ebfSHarry Wentland struct dc_link *link = stream->sink->link; 15484562236bSHarry Wentland 1549a2b8659dSTony Cheng for (i = 0; i < pool->stream_enc_count; i++) { 15504562236bSHarry Wentland if (!res_ctx->is_stream_enc_acquired[i] && 1551a2b8659dSTony Cheng pool->stream_enc[i]) { 15524562236bSHarry Wentland /* Store first available for MST second display 15534562236bSHarry Wentland * in daisy chain use case */ 15544562236bSHarry Wentland j = i; 1555a2b8659dSTony Cheng if (pool->stream_enc[i]->id == 15564562236bSHarry Wentland link->link_enc->preferred_engine) 1557a2b8659dSTony Cheng return pool->stream_enc[i]; 15584562236bSHarry Wentland } 15594562236bSHarry Wentland } 15604562236bSHarry Wentland 15614562236bSHarry Wentland /* 15624562236bSHarry Wentland * below can happen in cases when stream encoder is acquired: 15634562236bSHarry Wentland * 1) for second MST display in chain, so preferred engine already 15644562236bSHarry Wentland * acquired; 15654562236bSHarry Wentland * 2) for another link, which preferred engine already acquired by any 15664562236bSHarry Wentland * MST configuration. 15674562236bSHarry Wentland * 15684562236bSHarry Wentland * If signal is of DP type and preferred engine not found, return last available 15694562236bSHarry Wentland * 15704562236bSHarry Wentland * TODO - This is just a patch up and a generic solution is 15714562236bSHarry Wentland * required for non DP connectors. 15724562236bSHarry Wentland */ 15734562236bSHarry Wentland 1574cae50a43SEric Yang if (j >= 0 && link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT) 1575a2b8659dSTony Cheng return pool->stream_enc[j]; 15764562236bSHarry Wentland 15774562236bSHarry Wentland return NULL; 15784562236bSHarry Wentland } 15794562236bSHarry Wentland 1580a2b8659dSTony Cheng static struct audio *find_first_free_audio( 1581a2b8659dSTony Cheng struct resource_context *res_ctx, 1582cfb071f7SCharlene Liu const struct resource_pool *pool, 1583cfb071f7SCharlene Liu enum engine_id id) 15844562236bSHarry Wentland { 15854562236bSHarry Wentland int i; 1586a2b8659dSTony Cheng for (i = 0; i < pool->audio_count; i++) { 15874176664bSCharlene Liu if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) { 1588cfb071f7SCharlene Liu /*we have enough audio endpoint, find the matching inst*/ 1589cfb071f7SCharlene Liu if (id != i) 1590cfb071f7SCharlene Liu continue; 1591cfb071f7SCharlene Liu 1592a2b8659dSTony Cheng return pool->audios[i]; 15934562236bSHarry Wentland } 15944562236bSHarry Wentland } 159566bfd4fdSCharlene Liu /*not found the matching one, first come first serve*/ 15964176664bSCharlene Liu for (i = 0; i < pool->audio_count; i++) { 15974176664bSCharlene Liu if (res_ctx->is_audio_acquired[i] == false) { 15984176664bSCharlene Liu return pool->audios[i]; 15994176664bSCharlene Liu } 16004176664bSCharlene Liu } 16014562236bSHarry Wentland return 0; 16024562236bSHarry Wentland } 16034562236bSHarry Wentland 16044562236bSHarry Wentland bool resource_is_stream_unchanged( 1605608ac7bbSJerry Zuo struct dc_state *old_context, struct dc_stream_state *stream) 16064562236bSHarry Wentland { 1607ab2541b6SAric Cyr int i; 16084562236bSHarry Wentland 1609ab2541b6SAric Cyr for (i = 0; i < old_context->stream_count; i++) { 16100971c40eSHarry Wentland struct dc_stream_state *old_stream = old_context->streams[i]; 16114562236bSHarry Wentland 16124562236bSHarry Wentland if (are_stream_backends_same(old_stream, stream)) 16134562236bSHarry Wentland return true; 16144562236bSHarry Wentland } 16154562236bSHarry Wentland 16164562236bSHarry Wentland return false; 16174562236bSHarry Wentland } 16184562236bSHarry Wentland 161913ab1b44SYongqiang Sun enum dc_status dc_add_stream_to_ctx( 16201dc90497SAndrey Grodzovsky struct dc *dc, 1621608ac7bbSJerry Zuo struct dc_state *new_ctx, 16221dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 16231dc90497SAndrey Grodzovsky { 16241dc90497SAndrey Grodzovsky enum dc_status res; 1625eb9714a2SWenjing Liu DC_LOGGER_INIT(dc->ctx->logger); 16261dc90497SAndrey Grodzovsky 1627ece4147fSKen Chalmers if (new_ctx->stream_count >= dc->res_pool->timing_generator_count) { 1628eb9714a2SWenjing Liu DC_LOG_WARNING("Max streams reached, can't add stream %p !\n", stream); 16291dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 16301dc90497SAndrey Grodzovsky } 16311dc90497SAndrey Grodzovsky 16321dc90497SAndrey Grodzovsky new_ctx->streams[new_ctx->stream_count] = stream; 16331dc90497SAndrey Grodzovsky dc_stream_retain(stream); 16341dc90497SAndrey Grodzovsky new_ctx->stream_count++; 16351dc90497SAndrey Grodzovsky 16361dc90497SAndrey Grodzovsky res = dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream); 16371dc90497SAndrey Grodzovsky if (res != DC_OK) 1638eb9714a2SWenjing Liu DC_LOG_WARNING("Adding stream %p to context failed with err %d!\n", stream, res); 16391dc90497SAndrey Grodzovsky 164013ab1b44SYongqiang Sun return res; 16411dc90497SAndrey Grodzovsky } 16421dc90497SAndrey Grodzovsky 164362c933f9SYongqiang Sun enum dc_status dc_remove_stream_from_ctx( 16441dc90497SAndrey Grodzovsky struct dc *dc, 1645608ac7bbSJerry Zuo struct dc_state *new_ctx, 16461dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 16471dc90497SAndrey Grodzovsky { 164819f89e23SAndrey Grodzovsky int i; 16491dc90497SAndrey Grodzovsky struct dc_context *dc_ctx = dc->ctx; 16501dc90497SAndrey Grodzovsky struct pipe_ctx *del_pipe = NULL; 16511dc90497SAndrey Grodzovsky 165219f89e23SAndrey Grodzovsky /* Release primary pipe */ 16531dc90497SAndrey Grodzovsky for (i = 0; i < MAX_PIPES; i++) { 165419f89e23SAndrey Grodzovsky if (new_ctx->res_ctx.pipe_ctx[i].stream == stream && 165519f89e23SAndrey Grodzovsky !new_ctx->res_ctx.pipe_ctx[i].top_pipe) { 16561dc90497SAndrey Grodzovsky del_pipe = &new_ctx->res_ctx.pipe_ctx[i]; 16571dc90497SAndrey Grodzovsky 165819f89e23SAndrey Grodzovsky ASSERT(del_pipe->stream_res.stream_enc); 16591dc90497SAndrey Grodzovsky update_stream_engine_usage( 16601dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 16611dc90497SAndrey Grodzovsky dc->res_pool, 16621dc90497SAndrey Grodzovsky del_pipe->stream_res.stream_enc, 16631dc90497SAndrey Grodzovsky false); 16641dc90497SAndrey Grodzovsky 16651dc90497SAndrey Grodzovsky if (del_pipe->stream_res.audio) 16661dc90497SAndrey Grodzovsky update_audio_usage( 16671dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 16681dc90497SAndrey Grodzovsky dc->res_pool, 16691dc90497SAndrey Grodzovsky del_pipe->stream_res.audio, 16701dc90497SAndrey Grodzovsky false); 16711dc90497SAndrey Grodzovsky 16729d0dcecdSHarry Wentland resource_unreference_clock_source(&new_ctx->res_ctx, 16739d0dcecdSHarry Wentland dc->res_pool, 16749d0dcecdSHarry Wentland del_pipe->clock_source); 16759d0dcecdSHarry Wentland 1676e56ae556SNikola Cornij if (dc->res_pool->funcs->remove_stream_from_ctx) 1677e56ae556SNikola Cornij dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream); 1678e56ae556SNikola Cornij 16791dc90497SAndrey Grodzovsky memset(del_pipe, 0, sizeof(*del_pipe)); 168019f89e23SAndrey Grodzovsky 168119f89e23SAndrey Grodzovsky break; 16821dc90497SAndrey Grodzovsky } 16831dc90497SAndrey Grodzovsky } 16841dc90497SAndrey Grodzovsky 16851dc90497SAndrey Grodzovsky if (!del_pipe) { 16861dc90497SAndrey Grodzovsky DC_ERROR("Pipe not found for stream %p !\n", stream); 16871dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 16881dc90497SAndrey Grodzovsky } 16891dc90497SAndrey Grodzovsky 16901dc90497SAndrey Grodzovsky for (i = 0; i < new_ctx->stream_count; i++) 16911dc90497SAndrey Grodzovsky if (new_ctx->streams[i] == stream) 16921dc90497SAndrey Grodzovsky break; 16931dc90497SAndrey Grodzovsky 16941dc90497SAndrey Grodzovsky if (new_ctx->streams[i] != stream) { 16951dc90497SAndrey Grodzovsky DC_ERROR("Context doesn't have stream %p !\n", stream); 16961dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 16971dc90497SAndrey Grodzovsky } 16981dc90497SAndrey Grodzovsky 16991dc90497SAndrey Grodzovsky dc_stream_release(new_ctx->streams[i]); 17001dc90497SAndrey Grodzovsky new_ctx->stream_count--; 17011dc90497SAndrey Grodzovsky 17021dc90497SAndrey Grodzovsky /* Trim back arrays */ 17031dc90497SAndrey Grodzovsky for (; i < new_ctx->stream_count; i++) { 17041dc90497SAndrey Grodzovsky new_ctx->streams[i] = new_ctx->streams[i + 1]; 17051dc90497SAndrey Grodzovsky new_ctx->stream_status[i] = new_ctx->stream_status[i + 1]; 17061dc90497SAndrey Grodzovsky } 17071dc90497SAndrey Grodzovsky 17081dc90497SAndrey Grodzovsky new_ctx->streams[new_ctx->stream_count] = NULL; 17091dc90497SAndrey Grodzovsky memset( 17101dc90497SAndrey Grodzovsky &new_ctx->stream_status[new_ctx->stream_count], 17111dc90497SAndrey Grodzovsky 0, 17121dc90497SAndrey Grodzovsky sizeof(new_ctx->stream_status[0])); 17131dc90497SAndrey Grodzovsky 17141dc90497SAndrey Grodzovsky return DC_OK; 17151dc90497SAndrey Grodzovsky } 17161dc90497SAndrey Grodzovsky 17170971c40eSHarry Wentland static struct dc_stream_state *find_pll_sharable_stream( 17180971c40eSHarry Wentland struct dc_stream_state *stream_needs_pll, 1719608ac7bbSJerry Zuo struct dc_state *context) 17204562236bSHarry Wentland { 1721ab2541b6SAric Cyr int i; 17224562236bSHarry Wentland 1723ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 17240971c40eSHarry Wentland struct dc_stream_state *stream_has_pll = context->streams[i]; 17254562236bSHarry Wentland 17264562236bSHarry Wentland /* We are looking for non dp, non virtual stream */ 17274562236bSHarry Wentland if (resource_are_streams_timing_synchronizable( 17284562236bSHarry Wentland stream_needs_pll, stream_has_pll) 17294562236bSHarry Wentland && !dc_is_dp_signal(stream_has_pll->signal) 1730d0778ebfSHarry Wentland && stream_has_pll->sink->link->connector_signal 17314562236bSHarry Wentland != SIGNAL_TYPE_VIRTUAL) 17324562236bSHarry Wentland return stream_has_pll; 1733ab2541b6SAric Cyr 17344562236bSHarry Wentland } 17354562236bSHarry Wentland 17364562236bSHarry Wentland return NULL; 17374562236bSHarry Wentland } 17384562236bSHarry Wentland 17394562236bSHarry Wentland static int get_norm_pix_clk(const struct dc_crtc_timing *timing) 17404562236bSHarry Wentland { 17414562236bSHarry Wentland uint32_t pix_clk = timing->pix_clk_khz; 17424562236bSHarry Wentland uint32_t normalized_pix_clk = pix_clk; 17434562236bSHarry Wentland 17444562236bSHarry Wentland if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) 17454562236bSHarry Wentland pix_clk /= 2; 1746cc4d99b8SCharlene Liu if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) { 17474562236bSHarry Wentland switch (timing->display_color_depth) { 17484562236bSHarry Wentland case COLOR_DEPTH_888: 17494562236bSHarry Wentland normalized_pix_clk = pix_clk; 17504562236bSHarry Wentland break; 17514562236bSHarry Wentland case COLOR_DEPTH_101010: 17524562236bSHarry Wentland normalized_pix_clk = (pix_clk * 30) / 24; 17534562236bSHarry Wentland break; 17544562236bSHarry Wentland case COLOR_DEPTH_121212: 17554562236bSHarry Wentland normalized_pix_clk = (pix_clk * 36) / 24; 17564562236bSHarry Wentland break; 17574562236bSHarry Wentland case COLOR_DEPTH_161616: 17584562236bSHarry Wentland normalized_pix_clk = (pix_clk * 48) / 24; 17594562236bSHarry Wentland break; 17604562236bSHarry Wentland default: 17614562236bSHarry Wentland ASSERT(0); 17624562236bSHarry Wentland break; 17634562236bSHarry Wentland } 1764cc4d99b8SCharlene Liu } 17654562236bSHarry Wentland return normalized_pix_clk; 17664562236bSHarry Wentland } 17674562236bSHarry Wentland 17680971c40eSHarry Wentland static void calculate_phy_pix_clks(struct dc_stream_state *stream) 17694562236bSHarry Wentland { 17704562236bSHarry Wentland /* update actual pixel clock on all streams */ 17714562236bSHarry Wentland if (dc_is_hdmi_signal(stream->signal)) 17724562236bSHarry Wentland stream->phy_pix_clk = get_norm_pix_clk( 17734fa086b9SLeo (Sunpeng) Li &stream->timing); 17744562236bSHarry Wentland else 17754562236bSHarry Wentland stream->phy_pix_clk = 17764fa086b9SLeo (Sunpeng) Li stream->timing.pix_clk_khz; 177739c03e00SCharlene Liu 177839c03e00SCharlene Liu if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) 177939c03e00SCharlene Liu stream->phy_pix_clk *= 2; 17804562236bSHarry Wentland } 17814562236bSHarry Wentland 17824562236bSHarry Wentland enum dc_status resource_map_pool_resources( 1783fb3466a4SBhawanpreet Lakha const struct dc *dc, 1784608ac7bbSJerry Zuo struct dc_state *context, 17851dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 17864562236bSHarry Wentland { 1787a2b8659dSTony Cheng const struct resource_pool *pool = dc->res_pool; 17881dc90497SAndrey Grodzovsky int i; 17891dc90497SAndrey Grodzovsky struct dc_context *dc_ctx = dc->ctx; 17901dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = NULL; 17911dc90497SAndrey Grodzovsky int pipe_idx = -1; 17924562236bSHarry Wentland 17931dc90497SAndrey Grodzovsky /* TODO Check if this is needed */ 17941dc90497SAndrey Grodzovsky /*if (!resource_is_stream_unchanged(old_context, stream)) { 1795430ef426SDmytro Laktyushkin if (stream != NULL && old_context->streams[i] != NULL) { 17964b679bc3SCharlene Liu stream->bit_depth_params = 1797430ef426SDmytro Laktyushkin old_context->streams[i]->bit_depth_params; 1798430ef426SDmytro Laktyushkin stream->clamping = old_context->streams[i]->clamping; 17994562236bSHarry Wentland continue; 18004b679bc3SCharlene Liu } 18014b679bc3SCharlene Liu } 18024562236bSHarry Wentland */ 18034562236bSHarry Wentland 180408e1c28dSYogesh Mohan Marimuthu calculate_phy_pix_clks(stream); 180508e1c28dSYogesh Mohan Marimuthu 18064562236bSHarry Wentland /* acquire new resources */ 18075d11e9fcSDmytro Laktyushkin pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); 18081dc90497SAndrey Grodzovsky 1809dc37a9a0SLeo (Sunpeng) Li #ifdef CONFIG_DRM_AMD_DC_DCN1_0 18105d11e9fcSDmytro Laktyushkin if (pipe_idx < 0) 181113ab1b44SYongqiang Sun pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 181294c6d735SHarry Wentland #endif 181313ab1b44SYongqiang Sun 1814c5b38aecSDmytro Laktyushkin if (pipe_idx < 0 || context->res_ctx.pipe_ctx[pipe_idx].stream_res.tg == NULL) 18154562236bSHarry Wentland return DC_NO_CONTROLLER_RESOURCE; 18164562236bSHarry Wentland 18174562236bSHarry Wentland pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; 18184562236bSHarry Wentland 18198e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc = 18204562236bSHarry Wentland find_first_free_match_stream_enc_for_link( 1821a2b8659dSTony Cheng &context->res_ctx, pool, stream); 18224562236bSHarry Wentland 18238e9c4c8cSHarry Wentland if (!pipe_ctx->stream_res.stream_enc) 18244562236bSHarry Wentland return DC_NO_STREAM_ENG_RESOURCE; 18254562236bSHarry Wentland 18261dc90497SAndrey Grodzovsky update_stream_engine_usage( 1827a2b8659dSTony Cheng &context->res_ctx, pool, 18281dc90497SAndrey Grodzovsky pipe_ctx->stream_res.stream_enc, 18291dc90497SAndrey Grodzovsky true); 18304562236bSHarry Wentland 18314562236bSHarry Wentland /* TODO: Add check if ASIC support and EDID audio */ 1832b73a22d3SHarry Wentland if (!stream->sink->converter_disable_audio && 18334562236bSHarry Wentland dc_is_audio_capable_signal(pipe_ctx->stream->signal) && 18344fa086b9SLeo (Sunpeng) Li stream->audio_info.mode_count) { 1835afaacef4SHarry Wentland pipe_ctx->stream_res.audio = find_first_free_audio( 1836cfb071f7SCharlene Liu &context->res_ctx, pool, pipe_ctx->stream_res.stream_enc->id); 18374562236bSHarry Wentland 18384562236bSHarry Wentland /* 18394562236bSHarry Wentland * Audio assigned in order first come first get. 18404562236bSHarry Wentland * There are asics which has number of audio 18414562236bSHarry Wentland * resources less then number of pipes 18424562236bSHarry Wentland */ 1843afaacef4SHarry Wentland if (pipe_ctx->stream_res.audio) 18441dc90497SAndrey Grodzovsky update_audio_usage(&context->res_ctx, pool, 18451dc90497SAndrey Grodzovsky pipe_ctx->stream_res.audio, true); 18464562236bSHarry Wentland } 18474562236bSHarry Wentland 18489aef1a31SSivapiriyanKumarasamy /* Add ABM to the resource if on EDP */ 18499aef1a31SSivapiriyanKumarasamy if (pipe_ctx->stream && dc_is_embedded_signal(pipe_ctx->stream->signal)) 18509aef1a31SSivapiriyanKumarasamy pipe_ctx->stream_res.abm = pool->abm; 18519aef1a31SSivapiriyanKumarasamy 18521dc90497SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 18531dc90497SAndrey Grodzovsky if (context->streams[i] == stream) { 18546b670fa9SHarry Wentland context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; 18550f0bdca5SWenjing Liu context->stream_status[i].stream_enc_inst = pipe_ctx->stream_res.stream_enc->id; 18561dc90497SAndrey Grodzovsky return DC_OK; 18574562236bSHarry Wentland } 18584562236bSHarry Wentland 18591dc90497SAndrey Grodzovsky DC_ERROR("Stream %p not found in new ctx!\n", stream); 18601dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 18614562236bSHarry Wentland } 18624562236bSHarry Wentland 1863f36cc577SBhawanpreet Lakha void dc_resource_state_copy_construct_current( 18641dc90497SAndrey Grodzovsky const struct dc *dc, 1865608ac7bbSJerry Zuo struct dc_state *dst_ctx) 18661dc90497SAndrey Grodzovsky { 1867f36cc577SBhawanpreet Lakha dc_resource_state_copy_construct(dc->current_state, dst_ctx); 18681dc90497SAndrey Grodzovsky } 18691dc90497SAndrey Grodzovsky 1870ab8db3e1SAndrey Grodzovsky 1871ab8db3e1SAndrey Grodzovsky void dc_resource_state_construct( 1872ab8db3e1SAndrey Grodzovsky const struct dc *dc, 1873ab8db3e1SAndrey Grodzovsky struct dc_state *dst_ctx) 1874ab8db3e1SAndrey Grodzovsky { 187584e7fc05SDmytro Laktyushkin dst_ctx->dccg = dc->res_pool->clk_mgr; 1876ab8db3e1SAndrey Grodzovsky } 1877ab8db3e1SAndrey Grodzovsky 1878e750d56dSYongqiang Sun enum dc_status dc_validate_global_state( 18791dc90497SAndrey Grodzovsky struct dc *dc, 1880608ac7bbSJerry Zuo struct dc_state *new_ctx) 18811dc90497SAndrey Grodzovsky { 18821dc90497SAndrey Grodzovsky enum dc_status result = DC_ERROR_UNEXPECTED; 18831dc90497SAndrey Grodzovsky int i, j; 18841dc90497SAndrey Grodzovsky 1885e41ab030SHarry Wentland if (!new_ctx) 1886e41ab030SHarry Wentland return DC_ERROR_UNEXPECTED; 1887e41ab030SHarry Wentland 1888d596e5d0SYongqiang Sun if (dc->res_pool->funcs->validate_global) { 1889d596e5d0SYongqiang Sun result = dc->res_pool->funcs->validate_global(dc, new_ctx); 1890d596e5d0SYongqiang Sun if (result != DC_OK) 1891d596e5d0SYongqiang Sun return result; 1892d596e5d0SYongqiang Sun } 18931dc90497SAndrey Grodzovsky 1894e41ab030SHarry Wentland for (i = 0; i < new_ctx->stream_count; i++) { 18951dc90497SAndrey Grodzovsky struct dc_stream_state *stream = new_ctx->streams[i]; 18961dc90497SAndrey Grodzovsky 18971dc90497SAndrey Grodzovsky for (j = 0; j < dc->res_pool->pipe_count; j++) { 18981dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[j]; 18991dc90497SAndrey Grodzovsky 19001dc90497SAndrey Grodzovsky if (pipe_ctx->stream != stream) 19011dc90497SAndrey Grodzovsky continue; 19021dc90497SAndrey Grodzovsky 190374eac5f3SSu Sung Chung if (dc->res_pool->funcs->get_default_swizzle_mode && 190474eac5f3SSu Sung Chung pipe_ctx->plane_state && 190574eac5f3SSu Sung Chung pipe_ctx->plane_state->tiling_info.gfx9.swizzle == DC_SW_UNKNOWN) { 190674eac5f3SSu Sung Chung result = dc->res_pool->funcs->get_default_swizzle_mode(pipe_ctx->plane_state); 190774eac5f3SSu Sung Chung if (result != DC_OK) 190874eac5f3SSu Sung Chung return result; 190974eac5f3SSu Sung Chung } 191074eac5f3SSu Sung Chung 19111dc90497SAndrey Grodzovsky /* Switch to dp clock source only if there is 19121dc90497SAndrey Grodzovsky * no non dp stream that shares the same timing 19131dc90497SAndrey Grodzovsky * with the dp stream. 19141dc90497SAndrey Grodzovsky */ 19151dc90497SAndrey Grodzovsky if (dc_is_dp_signal(pipe_ctx->stream->signal) && 19161dc90497SAndrey Grodzovsky !find_pll_sharable_stream(stream, new_ctx)) { 19171dc90497SAndrey Grodzovsky 19189d0dcecdSHarry Wentland resource_unreference_clock_source( 19191dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 19201dc90497SAndrey Grodzovsky dc->res_pool, 19219d0dcecdSHarry Wentland pipe_ctx->clock_source); 19224a629536SHarry Wentland 19231dc90497SAndrey Grodzovsky pipe_ctx->clock_source = dc->res_pool->dp_clock_source; 19241dc90497SAndrey Grodzovsky resource_reference_clock_source( 19251dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 19261dc90497SAndrey Grodzovsky dc->res_pool, 19271dc90497SAndrey Grodzovsky pipe_ctx->clock_source); 19281dc90497SAndrey Grodzovsky } 19291dc90497SAndrey Grodzovsky } 19301dc90497SAndrey Grodzovsky } 19311dc90497SAndrey Grodzovsky 19321dc90497SAndrey Grodzovsky result = resource_build_scaling_params_for_context(dc, new_ctx); 19331dc90497SAndrey Grodzovsky 19341dc90497SAndrey Grodzovsky if (result == DC_OK) 19351dc90497SAndrey Grodzovsky if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx)) 19361dc90497SAndrey Grodzovsky result = DC_FAIL_BANDWIDTH_VALIDATE; 19371dc90497SAndrey Grodzovsky 19381dc90497SAndrey Grodzovsky return result; 19391dc90497SAndrey Grodzovsky } 19401dc90497SAndrey Grodzovsky 19416e4d6beeSTony Cheng static void patch_gamut_packet_checksum( 1942e09b6473SAnthony Koo struct dc_info_packet *gamut_packet) 19434562236bSHarry Wentland { 19444562236bSHarry Wentland /* For gamut we recalc checksum */ 19456e4d6beeSTony Cheng if (gamut_packet->valid) { 19464562236bSHarry Wentland uint8_t chk_sum = 0; 19474562236bSHarry Wentland uint8_t *ptr; 19484562236bSHarry Wentland uint8_t i; 19494562236bSHarry Wentland 19504562236bSHarry Wentland /*start of the Gamut data. */ 19516e4d6beeSTony Cheng ptr = &gamut_packet->sb[3]; 19524562236bSHarry Wentland 19536e4d6beeSTony Cheng for (i = 0; i <= gamut_packet->sb[1]; i++) 19544562236bSHarry Wentland chk_sum += ptr[i]; 19554562236bSHarry Wentland 19566e4d6beeSTony Cheng gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum); 19571646a6feSAndrew Wong } 19584562236bSHarry Wentland } 19594562236bSHarry Wentland 19604562236bSHarry Wentland static void set_avi_info_frame( 1961e09b6473SAnthony Koo struct dc_info_packet *info_packet, 19624562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 19634562236bSHarry Wentland { 19640971c40eSHarry Wentland struct dc_stream_state *stream = pipe_ctx->stream; 19654562236bSHarry Wentland enum dc_color_space color_space = COLOR_SPACE_UNKNOWN; 19664562236bSHarry Wentland uint32_t pixel_encoding = 0; 19674562236bSHarry Wentland enum scanning_type scan_type = SCANNING_TYPE_NODATA; 19684562236bSHarry Wentland enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA; 19694562236bSHarry Wentland bool itc = false; 197050e27654SZeyu Fan uint8_t itc_value = 0; 19714562236bSHarry Wentland uint8_t cn0_cn1 = 0; 197250e27654SZeyu Fan unsigned int cn0_cn1_value = 0; 19734562236bSHarry Wentland uint8_t *check_sum = NULL; 19744562236bSHarry Wentland uint8_t byte_index = 0; 1975754e3673SAnthony Koo union hdmi_info_packet hdmi_info; 197650e27654SZeyu Fan union display_content_support support = {0}; 19774fa086b9SLeo (Sunpeng) Li unsigned int vic = pipe_ctx->stream->timing.vic; 197815e17335SCharlene Liu enum dc_timing_3d_format format; 19794562236bSHarry Wentland 1980754e3673SAnthony Koo memset(&hdmi_info, 0, sizeof(union hdmi_info_packet)); 1981754e3673SAnthony Koo 19824fa086b9SLeo (Sunpeng) Li color_space = pipe_ctx->stream->output_color_space; 1983e5f2038eSCharlene Liu if (color_space == COLOR_SPACE_UNKNOWN) 19844fa086b9SLeo (Sunpeng) Li color_space = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ? 1985e5f2038eSCharlene Liu COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709; 19864562236bSHarry Wentland 19874562236bSHarry Wentland /* Initialize header */ 1988e09b6473SAnthony Koo hdmi_info.bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI; 19894562236bSHarry Wentland /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall 19904562236bSHarry Wentland * not be used in HDMI 2.0 (Section 10.1) */ 1991e09b6473SAnthony Koo hdmi_info.bits.header.version = 2; 1992e09b6473SAnthony Koo hdmi_info.bits.header.length = HDMI_AVI_INFOFRAME_SIZE; 19934562236bSHarry Wentland 19944562236bSHarry Wentland /* 19954562236bSHarry Wentland * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built 19964562236bSHarry Wentland * according to HDMI 2.0 spec (Section 10.1) 19974562236bSHarry Wentland */ 19984562236bSHarry Wentland 19994fa086b9SLeo (Sunpeng) Li switch (stream->timing.pixel_encoding) { 20004562236bSHarry Wentland case PIXEL_ENCODING_YCBCR422: 20014562236bSHarry Wentland pixel_encoding = 1; 20024562236bSHarry Wentland break; 20034562236bSHarry Wentland 20044562236bSHarry Wentland case PIXEL_ENCODING_YCBCR444: 20054562236bSHarry Wentland pixel_encoding = 2; 20064562236bSHarry Wentland break; 20074562236bSHarry Wentland case PIXEL_ENCODING_YCBCR420: 20084562236bSHarry Wentland pixel_encoding = 3; 20094562236bSHarry Wentland break; 20104562236bSHarry Wentland 20114562236bSHarry Wentland case PIXEL_ENCODING_RGB: 20124562236bSHarry Wentland default: 20134562236bSHarry Wentland pixel_encoding = 0; 20144562236bSHarry Wentland } 20154562236bSHarry Wentland 20164562236bSHarry Wentland /* Y0_Y1_Y2 : The pixel encoding */ 20174562236bSHarry Wentland /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */ 2018e09b6473SAnthony Koo hdmi_info.bits.Y0_Y1_Y2 = pixel_encoding; 20194562236bSHarry Wentland 20204562236bSHarry Wentland /* A0 = 1 Active Format Information valid */ 2021e09b6473SAnthony Koo hdmi_info.bits.A0 = ACTIVE_FORMAT_VALID; 20224562236bSHarry Wentland 20234562236bSHarry Wentland /* B0, B1 = 3; Bar info data is valid */ 2024e09b6473SAnthony Koo hdmi_info.bits.B0_B1 = BAR_INFO_BOTH_VALID; 20254562236bSHarry Wentland 2026e09b6473SAnthony Koo hdmi_info.bits.SC0_SC1 = PICTURE_SCALING_UNIFORM; 20274562236bSHarry Wentland 20284562236bSHarry Wentland /* S0, S1 : Underscan / Overscan */ 20294562236bSHarry Wentland /* TODO: un-hardcode scan type */ 20304562236bSHarry Wentland scan_type = SCANNING_TYPE_UNDERSCAN; 2031e09b6473SAnthony Koo hdmi_info.bits.S0_S1 = scan_type; 20324562236bSHarry Wentland 20334562236bSHarry Wentland /* C0, C1 : Colorimetry */ 20348fde5884SCharlene Liu if (color_space == COLOR_SPACE_YCBCR709 || 203515e17335SCharlene Liu color_space == COLOR_SPACE_YCBCR709_LIMITED) 2036e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709; 20378fde5884SCharlene Liu else if (color_space == COLOR_SPACE_YCBCR601 || 20388fde5884SCharlene Liu color_space == COLOR_SPACE_YCBCR601_LIMITED) 2039e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_ITU601; 20408fde5884SCharlene Liu else { 2041e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_NO_DATA; 20428fde5884SCharlene Liu } 2043534db198SAmy Zhang if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE || 2044534db198SAmy Zhang color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE || 2045534db198SAmy Zhang color_space == COLOR_SPACE_2020_YCBCR) { 2046e09b6473SAnthony Koo hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR; 2047e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; 2048534db198SAmy Zhang } else if (color_space == COLOR_SPACE_ADOBERGB) { 2049e09b6473SAnthony Koo hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB; 2050e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; 2051534db198SAmy Zhang } 2052534db198SAmy Zhang 20534562236bSHarry Wentland /* TODO: un-hardcode aspect ratio */ 20544fa086b9SLeo (Sunpeng) Li aspect = stream->timing.aspect_ratio; 20554562236bSHarry Wentland 20564562236bSHarry Wentland switch (aspect) { 20574562236bSHarry Wentland case ASPECT_RATIO_4_3: 20584562236bSHarry Wentland case ASPECT_RATIO_16_9: 2059e09b6473SAnthony Koo hdmi_info.bits.M0_M1 = aspect; 20604562236bSHarry Wentland break; 20614562236bSHarry Wentland 20624562236bSHarry Wentland case ASPECT_RATIO_NO_DATA: 20634562236bSHarry Wentland case ASPECT_RATIO_64_27: 20644562236bSHarry Wentland case ASPECT_RATIO_256_135: 20654562236bSHarry Wentland default: 2066e09b6473SAnthony Koo hdmi_info.bits.M0_M1 = 0; 20674562236bSHarry Wentland } 20684562236bSHarry Wentland 20694562236bSHarry Wentland /* Active Format Aspect ratio - same as Picture Aspect Ratio. */ 2070e09b6473SAnthony Koo hdmi_info.bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; 20714562236bSHarry Wentland 20724562236bSHarry Wentland /* TODO: un-hardcode cn0_cn1 and itc */ 207350e27654SZeyu Fan 20744562236bSHarry Wentland cn0_cn1 = 0; 207550e27654SZeyu Fan cn0_cn1_value = 0; 207650e27654SZeyu Fan 207750e27654SZeyu Fan itc = true; 207850e27654SZeyu Fan itc_value = 1; 207950e27654SZeyu Fan 20804fa086b9SLeo (Sunpeng) Li support = stream->sink->edid_caps.content_support; 20814562236bSHarry Wentland 20824562236bSHarry Wentland if (itc) { 208350e27654SZeyu Fan if (!support.bits.valid_content_type) { 208450e27654SZeyu Fan cn0_cn1_value = 0; 208550e27654SZeyu Fan } else { 208650e27654SZeyu Fan if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) { 208750e27654SZeyu Fan if (support.bits.graphics_content == 1) { 208850e27654SZeyu Fan cn0_cn1_value = 0; 208950e27654SZeyu Fan } 209050e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) { 209150e27654SZeyu Fan if (support.bits.photo_content == 1) { 209250e27654SZeyu Fan cn0_cn1_value = 1; 209350e27654SZeyu Fan } else { 209450e27654SZeyu Fan cn0_cn1_value = 0; 209550e27654SZeyu Fan itc_value = 0; 209650e27654SZeyu Fan } 209750e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) { 209850e27654SZeyu Fan if (support.bits.cinema_content == 1) { 209950e27654SZeyu Fan cn0_cn1_value = 2; 210050e27654SZeyu Fan } else { 210150e27654SZeyu Fan cn0_cn1_value = 0; 210250e27654SZeyu Fan itc_value = 0; 210350e27654SZeyu Fan } 210450e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) { 210550e27654SZeyu Fan if (support.bits.game_content == 1) { 210650e27654SZeyu Fan cn0_cn1_value = 3; 210750e27654SZeyu Fan } else { 210850e27654SZeyu Fan cn0_cn1_value = 0; 210950e27654SZeyu Fan itc_value = 0; 211050e27654SZeyu Fan } 211150e27654SZeyu Fan } 211250e27654SZeyu Fan } 2113e09b6473SAnthony Koo hdmi_info.bits.CN0_CN1 = cn0_cn1_value; 2114e09b6473SAnthony Koo hdmi_info.bits.ITC = itc_value; 21154562236bSHarry Wentland } 21164562236bSHarry Wentland 21174562236bSHarry Wentland /* TODO : We should handle YCC quantization */ 21184562236bSHarry Wentland /* but we do not have matrix calculation */ 21194fa086b9SLeo (Sunpeng) Li if (stream->sink->edid_caps.qs_bit == 1 && 21204fa086b9SLeo (Sunpeng) Li stream->sink->edid_caps.qy_bit == 1) { 212150e27654SZeyu Fan if (color_space == COLOR_SPACE_SRGB || 212250e27654SZeyu Fan color_space == COLOR_SPACE_2020_RGB_FULLRANGE) { 2123e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; 2124e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_FULL_RANGE; 212550e27654SZeyu Fan } else if (color_space == COLOR_SPACE_SRGB_LIMITED || 212650e27654SZeyu Fan color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) { 2127e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE; 2128e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 21294562236bSHarry Wentland } else { 2130e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 2131e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 21324562236bSHarry Wentland } 213350e27654SZeyu Fan } else { 2134e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 2135e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 213650e27654SZeyu Fan } 213750e27654SZeyu Fan 213815e17335SCharlene Liu ///VIC 21394fa086b9SLeo (Sunpeng) Li format = stream->timing.timing_3d_format; 214015e17335SCharlene Liu /*todo, add 3DStereo support*/ 214115e17335SCharlene Liu if (format != TIMING_3D_FORMAT_NONE) { 214215e17335SCharlene Liu // Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled 21434fa086b9SLeo (Sunpeng) Li switch (pipe_ctx->stream->timing.hdmi_vic) { 214415e17335SCharlene Liu case 1: 214515e17335SCharlene Liu vic = 95; 214615e17335SCharlene Liu break; 214715e17335SCharlene Liu case 2: 214815e17335SCharlene Liu vic = 94; 214915e17335SCharlene Liu break; 215015e17335SCharlene Liu case 3: 215115e17335SCharlene Liu vic = 93; 215215e17335SCharlene Liu break; 215315e17335SCharlene Liu case 4: 215415e17335SCharlene Liu vic = 98; 215515e17335SCharlene Liu break; 215615e17335SCharlene Liu default: 215715e17335SCharlene Liu break; 215815e17335SCharlene Liu } 215915e17335SCharlene Liu } 2160e09b6473SAnthony Koo hdmi_info.bits.VIC0_VIC7 = vic; 21614562236bSHarry Wentland 21624562236bSHarry Wentland /* pixel repetition 21634562236bSHarry Wentland * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel 21644562236bSHarry Wentland * repetition start from 1 */ 2165e09b6473SAnthony Koo hdmi_info.bits.PR0_PR3 = 0; 21664562236bSHarry Wentland 21674562236bSHarry Wentland /* Bar Info 21684562236bSHarry Wentland * barTop: Line Number of End of Top Bar. 21694562236bSHarry Wentland * barBottom: Line Number of Start of Bottom Bar. 21704562236bSHarry Wentland * barLeft: Pixel Number of End of Left Bar. 21714562236bSHarry Wentland * barRight: Pixel Number of Start of Right Bar. */ 2172e09b6473SAnthony Koo hdmi_info.bits.bar_top = stream->timing.v_border_top; 2173e09b6473SAnthony Koo hdmi_info.bits.bar_bottom = (stream->timing.v_total 21744fa086b9SLeo (Sunpeng) Li - stream->timing.v_border_bottom + 1); 2175e09b6473SAnthony Koo hdmi_info.bits.bar_left = stream->timing.h_border_left; 2176e09b6473SAnthony Koo hdmi_info.bits.bar_right = (stream->timing.h_total 21774fa086b9SLeo (Sunpeng) Li - stream->timing.h_border_right + 1); 21784562236bSHarry Wentland 21794562236bSHarry Wentland /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ 2180e09b6473SAnthony Koo check_sum = &hdmi_info.packet_raw_data.sb[0]; 2181e8d726b7SReza Amini 21823e183c5fSDave Airlie *check_sum = HDMI_INFOFRAME_TYPE_AVI + HDMI_AVI_INFOFRAME_SIZE + 2; 21834562236bSHarry Wentland 21843e183c5fSDave Airlie for (byte_index = 1; byte_index <= HDMI_AVI_INFOFRAME_SIZE; byte_index++) 2185e09b6473SAnthony Koo *check_sum += hdmi_info.packet_raw_data.sb[byte_index]; 21864562236bSHarry Wentland 21874562236bSHarry Wentland /* one byte complement */ 21884562236bSHarry Wentland *check_sum = (uint8_t) (0x100 - *check_sum); 21894562236bSHarry Wentland 21904562236bSHarry Wentland /* Store in hw_path_mode */ 2191e09b6473SAnthony Koo info_packet->hb0 = hdmi_info.packet_raw_data.hb0; 2192e09b6473SAnthony Koo info_packet->hb1 = hdmi_info.packet_raw_data.hb1; 2193e09b6473SAnthony Koo info_packet->hb2 = hdmi_info.packet_raw_data.hb2; 21944562236bSHarry Wentland 2195e09b6473SAnthony Koo for (byte_index = 0; byte_index < sizeof(hdmi_info.packet_raw_data.sb); byte_index++) 2196e09b6473SAnthony Koo info_packet->sb[byte_index] = hdmi_info.packet_raw_data.sb[byte_index]; 21974562236bSHarry Wentland 21984562236bSHarry Wentland info_packet->valid = true; 21994562236bSHarry Wentland } 22004562236bSHarry Wentland 22016e4d6beeSTony Cheng static void set_vendor_info_packet( 2202e09b6473SAnthony Koo struct dc_info_packet *info_packet, 22030971c40eSHarry Wentland struct dc_stream_state *stream) 22044562236bSHarry Wentland { 22054562236bSHarry Wentland uint32_t length = 0; 22064562236bSHarry Wentland bool hdmi_vic_mode = false; 22074562236bSHarry Wentland uint8_t checksum = 0; 22084562236bSHarry Wentland uint32_t i = 0; 22094562236bSHarry Wentland enum dc_timing_3d_format format; 221015e17335SCharlene Liu // Can be different depending on packet content /*todo*/ 221115e17335SCharlene Liu // unsigned int length = pPathMode->dolbyVision ? 24 : 5; 221215e17335SCharlene Liu 221315e17335SCharlene Liu info_packet->valid = false; 22144562236bSHarry Wentland 22154fa086b9SLeo (Sunpeng) Li format = stream->timing.timing_3d_format; 22164fa086b9SLeo (Sunpeng) Li if (stream->view_format == VIEW_3D_FORMAT_NONE) 22177f5c22d1SVitaly Prosyak format = TIMING_3D_FORMAT_NONE; 22184562236bSHarry Wentland 22194562236bSHarry Wentland /* Can be different depending on packet content */ 22204562236bSHarry Wentland length = 5; 22214562236bSHarry Wentland 22224fa086b9SLeo (Sunpeng) Li if (stream->timing.hdmi_vic != 0 22234fa086b9SLeo (Sunpeng) Li && stream->timing.h_total >= 3840 22244fa086b9SLeo (Sunpeng) Li && stream->timing.v_total >= 2160) 22254562236bSHarry Wentland hdmi_vic_mode = true; 22264562236bSHarry Wentland 22274562236bSHarry Wentland /* According to HDMI 1.4a CTS, VSIF should be sent 22284562236bSHarry Wentland * for both 3D stereo and HDMI VIC modes. 22294562236bSHarry Wentland * For all other modes, there is no VSIF sent. */ 22304562236bSHarry Wentland 22314562236bSHarry Wentland if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode) 22324562236bSHarry Wentland return; 22334562236bSHarry Wentland 22344562236bSHarry Wentland /* 24bit IEEE Registration identifier (0x000c03). LSB first. */ 22354562236bSHarry Wentland info_packet->sb[1] = 0x03; 22364562236bSHarry Wentland info_packet->sb[2] = 0x0C; 22374562236bSHarry Wentland info_packet->sb[3] = 0x00; 22384562236bSHarry Wentland 22394562236bSHarry Wentland /*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format. 22404562236bSHarry Wentland * The value for HDMI_Video_Format are: 22414562236bSHarry Wentland * 0x0 (0b000) - No additional HDMI video format is presented in this 22424562236bSHarry Wentland * packet 22434562236bSHarry Wentland * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC 22444562236bSHarry Wentland * parameter follows 22454562236bSHarry Wentland * 0x2 (0b010) - 3D format indication present. 3D_Structure and 22464562236bSHarry Wentland * potentially 3D_Ext_Data follows 22474562236bSHarry Wentland * 0x3..0x7 (0b011..0b111) - reserved for future use */ 22484562236bSHarry Wentland if (format != TIMING_3D_FORMAT_NONE) 22494562236bSHarry Wentland info_packet->sb[4] = (2 << 5); 22504562236bSHarry Wentland else if (hdmi_vic_mode) 22514562236bSHarry Wentland info_packet->sb[4] = (1 << 5); 22524562236bSHarry Wentland 22534562236bSHarry Wentland /* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2): 22544562236bSHarry Wentland * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure. 22554562236bSHarry Wentland * The value for 3D_Structure are: 22564562236bSHarry Wentland * 0x0 - Frame Packing 22574562236bSHarry Wentland * 0x1 - Field Alternative 22584562236bSHarry Wentland * 0x2 - Line Alternative 22594562236bSHarry Wentland * 0x3 - Side-by-Side (full) 22604562236bSHarry Wentland * 0x4 - L + depth 22614562236bSHarry Wentland * 0x5 - L + depth + graphics + graphics-depth 22624562236bSHarry Wentland * 0x6 - Top-and-Bottom 22634562236bSHarry Wentland * 0x7 - Reserved for future use 22644562236bSHarry Wentland * 0x8 - Side-by-Side (Half) 22654562236bSHarry Wentland * 0x9..0xE - Reserved for future use 22664562236bSHarry Wentland * 0xF - Not used */ 22674562236bSHarry Wentland switch (format) { 22684562236bSHarry Wentland case TIMING_3D_FORMAT_HW_FRAME_PACKING: 22694562236bSHarry Wentland case TIMING_3D_FORMAT_SW_FRAME_PACKING: 22704562236bSHarry Wentland info_packet->sb[5] = (0x0 << 4); 22714562236bSHarry Wentland break; 22724562236bSHarry Wentland 22734562236bSHarry Wentland case TIMING_3D_FORMAT_SIDE_BY_SIDE: 22744562236bSHarry Wentland case TIMING_3D_FORMAT_SBS_SW_PACKED: 22754562236bSHarry Wentland info_packet->sb[5] = (0x8 << 4); 22764562236bSHarry Wentland length = 6; 22774562236bSHarry Wentland break; 22784562236bSHarry Wentland 22794562236bSHarry Wentland case TIMING_3D_FORMAT_TOP_AND_BOTTOM: 22804562236bSHarry Wentland case TIMING_3D_FORMAT_TB_SW_PACKED: 22814562236bSHarry Wentland info_packet->sb[5] = (0x6 << 4); 22824562236bSHarry Wentland break; 22834562236bSHarry Wentland 22844562236bSHarry Wentland default: 22854562236bSHarry Wentland break; 22864562236bSHarry Wentland } 22874562236bSHarry Wentland 22884562236bSHarry Wentland /*PB5: If PB4 is set to 0x1 (extended resolution format) 22894562236bSHarry Wentland * fill PB5 with the correct HDMI VIC code */ 22904562236bSHarry Wentland if (hdmi_vic_mode) 22914fa086b9SLeo (Sunpeng) Li info_packet->sb[5] = stream->timing.hdmi_vic; 22924562236bSHarry Wentland 22934562236bSHarry Wentland /* Header */ 22943e183c5fSDave Airlie info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR; /* VSIF packet type. */ 22954562236bSHarry Wentland info_packet->hb1 = 0x01; /* Version */ 22964562236bSHarry Wentland 22974562236bSHarry Wentland /* 4 lower bits = Length, 4 higher bits = 0 (reserved) */ 22984562236bSHarry Wentland info_packet->hb2 = (uint8_t) (length); 22994562236bSHarry Wentland 23004562236bSHarry Wentland /* Calculate checksum */ 23014562236bSHarry Wentland checksum = 0; 23024562236bSHarry Wentland checksum += info_packet->hb0; 23034562236bSHarry Wentland checksum += info_packet->hb1; 23044562236bSHarry Wentland checksum += info_packet->hb2; 23054562236bSHarry Wentland 23064562236bSHarry Wentland for (i = 1; i <= length; i++) 23074562236bSHarry Wentland checksum += info_packet->sb[i]; 23084562236bSHarry Wentland 23094562236bSHarry Wentland info_packet->sb[0] = (uint8_t) (0x100 - checksum); 23104562236bSHarry Wentland 23114562236bSHarry Wentland info_packet->valid = true; 23124562236bSHarry Wentland } 23134562236bSHarry Wentland 23146e4d6beeSTony Cheng static void set_spd_info_packet( 2315e09b6473SAnthony Koo struct dc_info_packet *info_packet, 23160971c40eSHarry Wentland struct dc_stream_state *stream) 23174562236bSHarry Wentland { 23184562236bSHarry Wentland /* SPD info packet for FreeSync */ 23194562236bSHarry Wentland 23204562236bSHarry Wentland /* Check if Freesync is supported. Return if false. If true, 23214562236bSHarry Wentland * set the corresponding bit in the info packet 23224562236bSHarry Wentland */ 232398e6436dSAnthony Koo if (!stream->vrr_infopacket.valid) 23244562236bSHarry Wentland return; 23254562236bSHarry Wentland 232698e6436dSAnthony Koo *info_packet = stream->vrr_infopacket; 23274562236bSHarry Wentland } 23284562236bSHarry Wentland 23291646a6feSAndrew Wong static void set_hdr_static_info_packet( 2330e09b6473SAnthony Koo struct dc_info_packet *info_packet, 23310971c40eSHarry Wentland struct dc_stream_state *stream) 23321646a6feSAndrew Wong { 23330eeef690SAnthony Koo /* HDR Static Metadata info packet for HDR10 */ 23341646a6feSAndrew Wong 2335a10dc97aSKrunoslav Kovac if (!stream->hdr_static_metadata.valid || 2336a10dc97aSKrunoslav Kovac stream->use_dynamic_meta) 233710bff005SYongqiang Sun return; 233810bff005SYongqiang Sun 23390eeef690SAnthony Koo *info_packet = stream->hdr_static_metadata; 23401646a6feSAndrew Wong } 23411646a6feSAndrew Wong 23426e4d6beeSTony Cheng static void set_vsc_info_packet( 2343e09b6473SAnthony Koo struct dc_info_packet *info_packet, 23440971c40eSHarry Wentland struct dc_stream_state *stream) 23454562236bSHarry Wentland { 23461336926fSAlvin lee if (!stream->vsc_infopacket.valid) 23474562236bSHarry Wentland return; 23484562236bSHarry Wentland 23491336926fSAlvin lee *info_packet = stream->vsc_infopacket; 23504562236bSHarry Wentland } 23514562236bSHarry Wentland 2352f36cc577SBhawanpreet Lakha void dc_resource_state_destruct(struct dc_state *context) 23534562236bSHarry Wentland { 23544562236bSHarry Wentland int i, j; 23554562236bSHarry Wentland 2356ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 23573be5262eSHarry Wentland for (j = 0; j < context->stream_status[i].plane_count; j++) 23583be5262eSHarry Wentland dc_plane_state_release( 23593be5262eSHarry Wentland context->stream_status[i].plane_states[j]); 23604562236bSHarry Wentland 23613be5262eSHarry Wentland context->stream_status[i].plane_count = 0; 23624fa086b9SLeo (Sunpeng) Li dc_stream_release(context->streams[i]); 2363ab2541b6SAric Cyr context->streams[i] = NULL; 23644562236bSHarry Wentland } 23654562236bSHarry Wentland } 23664562236bSHarry Wentland 23674562236bSHarry Wentland /* 2368ab2541b6SAric Cyr * Copy src_ctx into dst_ctx and retain all surfaces and streams referenced 23694562236bSHarry Wentland * by the src_ctx 23704562236bSHarry Wentland */ 2371f36cc577SBhawanpreet Lakha void dc_resource_state_copy_construct( 2372608ac7bbSJerry Zuo const struct dc_state *src_ctx, 2373608ac7bbSJerry Zuo struct dc_state *dst_ctx) 23744562236bSHarry Wentland { 23754562236bSHarry Wentland int i, j; 23768ee5702aSDave Airlie struct kref refcount = dst_ctx->refcount; 23774562236bSHarry Wentland 23784562236bSHarry Wentland *dst_ctx = *src_ctx; 23794562236bSHarry Wentland 2380a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 23814562236bSHarry Wentland struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i]; 23824562236bSHarry Wentland 23834562236bSHarry Wentland if (cur_pipe->top_pipe) 23844562236bSHarry Wentland cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; 23854562236bSHarry Wentland 23864562236bSHarry Wentland if (cur_pipe->bottom_pipe) 23874562236bSHarry Wentland cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; 23884562236bSHarry Wentland 23894562236bSHarry Wentland } 23904562236bSHarry Wentland 2391ab2541b6SAric Cyr for (i = 0; i < dst_ctx->stream_count; i++) { 23924fa086b9SLeo (Sunpeng) Li dc_stream_retain(dst_ctx->streams[i]); 23933be5262eSHarry Wentland for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++) 23943be5262eSHarry Wentland dc_plane_state_retain( 23953be5262eSHarry Wentland dst_ctx->stream_status[i].plane_states[j]); 23964562236bSHarry Wentland } 23979a3afbb3SAndrey Grodzovsky 23989a3afbb3SAndrey Grodzovsky /* context refcount should not be overridden */ 23998ee5702aSDave Airlie dst_ctx->refcount = refcount; 24009a3afbb3SAndrey Grodzovsky 24014562236bSHarry Wentland } 24024562236bSHarry Wentland 24034562236bSHarry Wentland struct clock_source *dc_resource_find_first_free_pll( 2404a2b8659dSTony Cheng struct resource_context *res_ctx, 2405a2b8659dSTony Cheng const struct resource_pool *pool) 24064562236bSHarry Wentland { 24074562236bSHarry Wentland int i; 24084562236bSHarry Wentland 2409a2b8659dSTony Cheng for (i = 0; i < pool->clk_src_count; ++i) { 24104562236bSHarry Wentland if (res_ctx->clock_source_ref_count[i] == 0) 2411a2b8659dSTony Cheng return pool->clock_sources[i]; 24124562236bSHarry Wentland } 24134562236bSHarry Wentland 24144562236bSHarry Wentland return NULL; 24154562236bSHarry Wentland } 24164562236bSHarry Wentland 24174562236bSHarry Wentland void resource_build_info_frame(struct pipe_ctx *pipe_ctx) 24184562236bSHarry Wentland { 24194562236bSHarry Wentland enum signal_type signal = SIGNAL_TYPE_NONE; 242096c50c0dSHarry Wentland struct encoder_info_frame *info = &pipe_ctx->stream_res.encoder_info_frame; 24214562236bSHarry Wentland 24224562236bSHarry Wentland /* default all packets to invalid */ 24236e4d6beeSTony Cheng info->avi.valid = false; 24246e4d6beeSTony Cheng info->gamut.valid = false; 24256e4d6beeSTony Cheng info->vendor.valid = false; 2426630e3573SJeff Smith info->spd.valid = false; 24276e4d6beeSTony Cheng info->hdrsmd.valid = false; 24286e4d6beeSTony Cheng info->vsc.valid = false; 24294562236bSHarry Wentland 24304562236bSHarry Wentland signal = pipe_ctx->stream->signal; 24314562236bSHarry Wentland 24324562236bSHarry Wentland /* HDMi and DP have different info packets*/ 24334562236bSHarry Wentland if (dc_is_hdmi_signal(signal)) { 24346e4d6beeSTony Cheng set_avi_info_frame(&info->avi, pipe_ctx); 24356e4d6beeSTony Cheng 24366e4d6beeSTony Cheng set_vendor_info_packet(&info->vendor, pipe_ctx->stream); 24376e4d6beeSTony Cheng 24386e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 24396e4d6beeSTony Cheng 244056ef6ed9SAnthony Koo set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 24416e4d6beeSTony Cheng 2442a33fa99dSHarry Wentland } else if (dc_is_dp_signal(signal)) { 24436e4d6beeSTony Cheng set_vsc_info_packet(&info->vsc, pipe_ctx->stream); 24446e4d6beeSTony Cheng 24456e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 24466e4d6beeSTony Cheng 244756ef6ed9SAnthony Koo set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 2448a33fa99dSHarry Wentland } 24494562236bSHarry Wentland 24506e4d6beeSTony Cheng patch_gamut_packet_checksum(&info->gamut); 24514562236bSHarry Wentland } 24524562236bSHarry Wentland 24534562236bSHarry Wentland enum dc_status resource_map_clock_resources( 2454fb3466a4SBhawanpreet Lakha const struct dc *dc, 2455608ac7bbSJerry Zuo struct dc_state *context, 24561dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 24574562236bSHarry Wentland { 24584562236bSHarry Wentland /* acquire new resources */ 24591dc90497SAndrey Grodzovsky const struct resource_pool *pool = dc->res_pool; 24601dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream( 24611dc90497SAndrey Grodzovsky &context->res_ctx, stream); 24624562236bSHarry Wentland 24631dc90497SAndrey Grodzovsky if (!pipe_ctx) 24641dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 24654562236bSHarry Wentland 24664562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal) 24674562236bSHarry Wentland || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) 2468a2b8659dSTony Cheng pipe_ctx->clock_source = pool->dp_clock_source; 24694562236bSHarry Wentland else { 24704562236bSHarry Wentland pipe_ctx->clock_source = NULL; 24714562236bSHarry Wentland 2472fb3466a4SBhawanpreet Lakha if (!dc->config.disable_disp_pll_sharing) 24734ed4e51bSMikita Lipski pipe_ctx->clock_source = resource_find_used_clk_src_for_sharing( 24744562236bSHarry Wentland &context->res_ctx, 24754562236bSHarry Wentland pipe_ctx); 24764562236bSHarry Wentland 24774562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 24784562236bSHarry Wentland pipe_ctx->clock_source = 2479a2b8659dSTony Cheng dc_resource_find_first_free_pll( 2480a2b8659dSTony Cheng &context->res_ctx, 2481a2b8659dSTony Cheng pool); 24824562236bSHarry Wentland } 24834562236bSHarry Wentland 24844562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 24854562236bSHarry Wentland return DC_NO_CLOCK_SOURCE_RESOURCE; 24864562236bSHarry Wentland 24874562236bSHarry Wentland resource_reference_clock_source( 2488a2b8659dSTony Cheng &context->res_ctx, pool, 24894562236bSHarry Wentland pipe_ctx->clock_source); 24904562236bSHarry Wentland 24914562236bSHarry Wentland return DC_OK; 24924562236bSHarry Wentland } 24934562236bSHarry Wentland 24944562236bSHarry Wentland /* 24954562236bSHarry Wentland * Note: We need to disable output if clock sources change, 24964562236bSHarry Wentland * since bios does optimization and doesn't apply if changing 24974562236bSHarry Wentland * PHY when not already disabled. 24984562236bSHarry Wentland */ 24994562236bSHarry Wentland bool pipe_need_reprogram( 25004562236bSHarry Wentland struct pipe_ctx *pipe_ctx_old, 25014562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 25024562236bSHarry Wentland { 2503cfe4645eSDmytro Laktyushkin if (!pipe_ctx_old->stream) 2504cfe4645eSDmytro Laktyushkin return false; 2505cfe4645eSDmytro Laktyushkin 25064562236bSHarry Wentland if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink) 25074562236bSHarry Wentland return true; 25084562236bSHarry Wentland 25094562236bSHarry Wentland if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal) 25104562236bSHarry Wentland return true; 25114562236bSHarry Wentland 2512afaacef4SHarry Wentland if (pipe_ctx_old->stream_res.audio != pipe_ctx->stream_res.audio) 25134562236bSHarry Wentland return true; 25144562236bSHarry Wentland 25154562236bSHarry Wentland if (pipe_ctx_old->clock_source != pipe_ctx->clock_source 25164562236bSHarry Wentland && pipe_ctx_old->stream != pipe_ctx->stream) 25174562236bSHarry Wentland return true; 25184562236bSHarry Wentland 25198e9c4c8cSHarry Wentland if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc) 25204562236bSHarry Wentland return true; 25214562236bSHarry Wentland 25224562236bSHarry Wentland if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 25234562236bSHarry Wentland return true; 25244562236bSHarry Wentland 25256b622181SJulian Parkin if (is_hdr_static_meta_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 25266b622181SJulian Parkin return true; 25274562236bSHarry Wentland 25281e7e86c4SSamson Tam if (pipe_ctx_old->stream->dpms_off != pipe_ctx->stream->dpms_off) 25291e7e86c4SSamson Tam return true; 25301e7e86c4SSamson Tam 25311336926fSAlvin lee if (is_vsc_info_packet_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 25321336926fSAlvin lee return true; 25331336926fSAlvin lee 25344562236bSHarry Wentland return false; 25354562236bSHarry Wentland } 2536529cad0fSDing Wang 25370971c40eSHarry Wentland void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, 2538529cad0fSDing Wang struct bit_depth_reduction_params *fmt_bit_depth) 2539529cad0fSDing Wang { 25404fa086b9SLeo (Sunpeng) Li enum dc_dither_option option = stream->dither_option; 2541529cad0fSDing Wang enum dc_pixel_encoding pixel_encoding = 25424fa086b9SLeo (Sunpeng) Li stream->timing.pixel_encoding; 2543529cad0fSDing Wang 2544529cad0fSDing Wang memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); 2545529cad0fSDing Wang 2546603767f9STony Cheng if (option == DITHER_OPTION_DEFAULT) { 2547603767f9STony Cheng switch (stream->timing.display_color_depth) { 2548603767f9STony Cheng case COLOR_DEPTH_666: 2549603767f9STony Cheng option = DITHER_OPTION_SPATIAL6; 2550603767f9STony Cheng break; 2551603767f9STony Cheng case COLOR_DEPTH_888: 2552603767f9STony Cheng option = DITHER_OPTION_SPATIAL8; 2553603767f9STony Cheng break; 2554603767f9STony Cheng case COLOR_DEPTH_101010: 2555603767f9STony Cheng option = DITHER_OPTION_SPATIAL10; 2556603767f9STony Cheng break; 2557603767f9STony Cheng default: 2558603767f9STony Cheng option = DITHER_OPTION_DISABLE; 2559603767f9STony Cheng } 2560603767f9STony Cheng } 2561603767f9STony Cheng 2562529cad0fSDing Wang if (option == DITHER_OPTION_DISABLE) 2563529cad0fSDing Wang return; 2564529cad0fSDing Wang 2565529cad0fSDing Wang if (option == DITHER_OPTION_TRUN6) { 2566529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2567529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 0; 2568529cad0fSDing Wang } else if (option == DITHER_OPTION_TRUN8 || 2569529cad0fSDing Wang option == DITHER_OPTION_TRUN8_SPATIAL6 || 2570529cad0fSDing Wang option == DITHER_OPTION_TRUN8_FM6) { 2571529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2572529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 1; 2573529cad0fSDing Wang } else if (option == DITHER_OPTION_TRUN10 || 2574529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL6 || 2575529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8 || 2576529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM8 || 2577529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM6 || 2578529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2579529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2580529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2581529cad0fSDing Wang } 2582529cad0fSDing Wang 2583529cad0fSDing Wang /* special case - Formatter can only reduce by 4 bits at most. 2584529cad0fSDing Wang * When reducing from 12 to 6 bits, 2585529cad0fSDing Wang * HW recommends we use trunc with round mode 2586529cad0fSDing Wang * (if we did nothing, trunc to 10 bits would be used) 2587529cad0fSDing Wang * note that any 12->10 bit reduction is ignored prior to DCE8, 2588529cad0fSDing Wang * as the input was 10 bits. 2589529cad0fSDing Wang */ 2590529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2591529cad0fSDing Wang option == DITHER_OPTION_SPATIAL6 || 2592529cad0fSDing Wang option == DITHER_OPTION_FM6) { 2593529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2594529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2595529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_MODE = 1; 2596529cad0fSDing Wang } 2597529cad0fSDing Wang 2598529cad0fSDing Wang /* spatial dither 2599529cad0fSDing Wang * note that spatial modes 1-3 are never used 2600529cad0fSDing Wang */ 2601529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2602529cad0fSDing Wang option == DITHER_OPTION_SPATIAL6 || 2603529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL6 || 2604529cad0fSDing Wang option == DITHER_OPTION_TRUN8_SPATIAL6) { 2605529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2606529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0; 2607529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2608529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2609529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2610529cad0fSDing Wang } else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM || 2611529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8 || 2612529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8_FM6 || 2613529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8 || 2614529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2615529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2616529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1; 2617529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2618529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2619529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2620529cad0fSDing Wang } else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM || 2621529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10 || 2622529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM8 || 2623529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM6) { 2624529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2625529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2; 2626529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2627529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2628529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2629529cad0fSDing Wang } 2630529cad0fSDing Wang 2631529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6 || 2632529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8 || 2633529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10) { 2634529cad0fSDing Wang fmt_bit_depth->flags.FRAME_RANDOM = 0; 2635529cad0fSDing Wang } else { 2636529cad0fSDing Wang fmt_bit_depth->flags.FRAME_RANDOM = 1; 2637529cad0fSDing Wang } 2638529cad0fSDing Wang 2639529cad0fSDing Wang ////////////////////// 2640529cad0fSDing Wang //// temporal dither 2641529cad0fSDing Wang ////////////////////// 2642529cad0fSDing Wang if (option == DITHER_OPTION_FM6 || 2643529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8_FM6 || 2644529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM6 || 2645529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM6 || 2646529cad0fSDing Wang option == DITHER_OPTION_TRUN8_FM6 || 2647529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2648529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2649529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0; 2650529cad0fSDing Wang } else if (option == DITHER_OPTION_FM8 || 2651529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM8 || 2652529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM8) { 2653529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2654529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1; 2655529cad0fSDing Wang } else if (option == DITHER_OPTION_FM10) { 2656529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2657529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2; 2658529cad0fSDing Wang } 2659529cad0fSDing Wang 2660529cad0fSDing Wang fmt_bit_depth->pixel_encoding = pixel_encoding; 2661529cad0fSDing Wang } 26629345d987SAndrey Grodzovsky 266362c933f9SYongqiang Sun enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) 26649345d987SAndrey Grodzovsky { 2665fb3466a4SBhawanpreet Lakha struct dc *core_dc = dc; 26664fa086b9SLeo (Sunpeng) Li struct dc_link *link = stream->sink->link; 26679345d987SAndrey Grodzovsky struct timing_generator *tg = core_dc->res_pool->timing_generators[0]; 26689345d987SAndrey Grodzovsky enum dc_status res = DC_OK; 26699345d987SAndrey Grodzovsky 26704fa086b9SLeo (Sunpeng) Li calculate_phy_pix_clks(stream); 26719345d987SAndrey Grodzovsky 26724fa086b9SLeo (Sunpeng) Li if (!tg->funcs->validate_timing(tg, &stream->timing)) 26739345d987SAndrey Grodzovsky res = DC_FAIL_CONTROLLER_VALIDATE; 26749345d987SAndrey Grodzovsky 26759345d987SAndrey Grodzovsky if (res == DC_OK) 26769345d987SAndrey Grodzovsky if (!link->link_enc->funcs->validate_output_with_stream( 26774fa086b9SLeo (Sunpeng) Li link->link_enc, stream)) 26789345d987SAndrey Grodzovsky res = DC_FAIL_ENC_VALIDATE; 26799345d987SAndrey Grodzovsky 26809345d987SAndrey Grodzovsky /* TODO: validate audio ASIC caps, encoder */ 26819345d987SAndrey Grodzovsky 26829345d987SAndrey Grodzovsky if (res == DC_OK) 26834fa086b9SLeo (Sunpeng) Li res = dc_link_validate_mode_timing(stream, 26849345d987SAndrey Grodzovsky link, 26854fa086b9SLeo (Sunpeng) Li &stream->timing); 26869345d987SAndrey Grodzovsky 268762c933f9SYongqiang Sun return res; 26889345d987SAndrey Grodzovsky } 2689792671d7SAndrey Grodzovsky 269062c933f9SYongqiang Sun enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) 2691792671d7SAndrey Grodzovsky { 269262c933f9SYongqiang Sun enum dc_status res = DC_OK; 269362c933f9SYongqiang Sun 2694792671d7SAndrey Grodzovsky /* TODO For now validates pixel format only */ 26958e7095b9SDmytro Laktyushkin if (dc->res_pool->funcs->validate_plane) 269662c933f9SYongqiang Sun return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps); 2697792671d7SAndrey Grodzovsky 269862c933f9SYongqiang Sun return res; 2699792671d7SAndrey Grodzovsky } 270074eac5f3SSu Sung Chung 270174eac5f3SSu Sung Chung unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format) 270274eac5f3SSu Sung Chung { 270374eac5f3SSu Sung Chung switch (format) { 270474eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 270574eac5f3SSu Sung Chung return 8; 270674eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 270774eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 270874eac5f3SSu Sung Chung return 12; 270974eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 271074eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 271174eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 271274eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 271374eac5f3SSu Sung Chung return 16; 271474eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 271574eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 271674eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 271774eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 271874eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 271974eac5f3SSu Sung Chung return 32; 272074eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 272174eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 272274eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 272374eac5f3SSu Sung Chung return 64; 272474eac5f3SSu Sung Chung default: 272574eac5f3SSu Sung Chung ASSERT_CRITICAL(false); 272674eac5f3SSu Sung Chung return -1; 272774eac5f3SSu Sung Chung } 272874eac5f3SSu Sung Chung } 2729