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 */ 254fc4dca8SSam Ravnborg 264fc4dca8SSam Ravnborg #include <linux/slab.h> 274fc4dca8SSam Ravnborg 284562236bSHarry Wentland #include "dm_services.h" 294562236bSHarry Wentland 304562236bSHarry Wentland #include "resource.h" 314562236bSHarry Wentland #include "include/irq_service_interface.h" 324562236bSHarry Wentland #include "link_encoder.h" 334562236bSHarry Wentland #include "stream_encoder.h" 344562236bSHarry Wentland #include "opp.h" 354562236bSHarry Wentland #include "timing_generator.h" 364562236bSHarry Wentland #include "transform.h" 3733d7598dSJun Lei #include "dccg.h" 3833d7598dSJun Lei #include "dchubbub.h" 39d94585a0SYue Hin Lau #include "dpp.h" 405ac3d3c9SCharlene Liu #include "core_types.h" 414562236bSHarry Wentland #include "set_mode_types.h" 424562236bSHarry Wentland #include "virtual/virtual_stream_encoder.h" 433b94a400STao #include "dpcd_defs.h" 44*0d4b4253SJimmy Kizito #include "link_enc_cfg.h" 45f01ee019SFangzhi Zuo #include "dc_link_dp.h" 464562236bSHarry Wentland 47683b5950SMauro Rossi #if defined(CONFIG_DRM_AMD_DC_SI) 48683b5950SMauro Rossi #include "dce60/dce60_resource.h" 49683b5950SMauro Rossi #endif 504562236bSHarry Wentland #include "dce80/dce80_resource.h" 514562236bSHarry Wentland #include "dce100/dce100_resource.h" 524562236bSHarry Wentland #include "dce110/dce110_resource.h" 534562236bSHarry Wentland #include "dce112/dce112_resource.h" 54cf2156e2SAlex Deucher #include "dce120/dce120_resource.h" 55b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 56ff5ef992SAlex Deucher #include "dcn10/dcn10_resource.h" 577ed4e635SHarry Wentland #include "dcn20/dcn20_resource.h" 58e22ece54SBhawanpreet Lakha #include "dcn21/dcn21_resource.h" 5920f2ffe5SAlex Deucher #include "dcn30/dcn30_resource.h" 6020f2ffe5SAlex Deucher #include "dcn301/dcn301_resource.h" 6120f2ffe5SAlex Deucher #include "dcn302/dcn302_resource.h" 62cd6d421eSAurabindo Pillai #include "dcn303/dcn303_resource.h" 638fe44c08SAlex Deucher #include "dcn31/dcn31_resource.h" 6436d26912SBhawanpreet Lakha #endif 655d4b05ddSBhawanpreet Lakha 665d4b05ddSBhawanpreet Lakha #define DC_LOGGER_INIT(logger) 675d4b05ddSBhawanpreet Lakha 684562236bSHarry Wentland enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) 694562236bSHarry Wentland { 704562236bSHarry Wentland enum dce_version dc_version = DCE_VERSION_UNKNOWN; 714562236bSHarry Wentland switch (asic_id.chip_family) { 724562236bSHarry Wentland 73683b5950SMauro Rossi #if defined(CONFIG_DRM_AMD_DC_SI) 74683b5950SMauro Rossi case FAMILY_SI: 75683b5950SMauro Rossi if (ASIC_REV_IS_TAHITI_P(asic_id.hw_internal_rev) || 76683b5950SMauro Rossi ASIC_REV_IS_PITCAIRN_PM(asic_id.hw_internal_rev) || 77683b5950SMauro Rossi ASIC_REV_IS_CAPEVERDE_M(asic_id.hw_internal_rev)) 78683b5950SMauro Rossi dc_version = DCE_VERSION_6_0; 79683b5950SMauro Rossi else if (ASIC_REV_IS_OLAND_M(asic_id.hw_internal_rev)) 80683b5950SMauro Rossi dc_version = DCE_VERSION_6_4; 81683b5950SMauro Rossi else 82683b5950SMauro Rossi dc_version = DCE_VERSION_6_1; 83683b5950SMauro Rossi break; 84683b5950SMauro Rossi #endif 854562236bSHarry Wentland case FAMILY_CI: 864562236bSHarry Wentland dc_version = DCE_VERSION_8_0; 874562236bSHarry Wentland break; 88ebfdf0d0SAlex Deucher case FAMILY_KV: 89ebfdf0d0SAlex Deucher if (ASIC_REV_IS_KALINDI(asic_id.hw_internal_rev) || 90ebfdf0d0SAlex Deucher ASIC_REV_IS_BHAVANI(asic_id.hw_internal_rev) || 91ebfdf0d0SAlex Deucher ASIC_REV_IS_GODAVARI(asic_id.hw_internal_rev)) 92ebfdf0d0SAlex Deucher dc_version = DCE_VERSION_8_3; 93ebfdf0d0SAlex Deucher else 94ebfdf0d0SAlex Deucher dc_version = DCE_VERSION_8_1; 95ebfdf0d0SAlex Deucher break; 964562236bSHarry Wentland case FAMILY_CZ: 974562236bSHarry Wentland dc_version = DCE_VERSION_11_0; 984562236bSHarry Wentland break; 994562236bSHarry Wentland 1004562236bSHarry Wentland case FAMILY_VI: 1014562236bSHarry Wentland if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) || 1024562236bSHarry Wentland ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) { 1034562236bSHarry Wentland dc_version = DCE_VERSION_10_0; 1044562236bSHarry Wentland break; 1054562236bSHarry Wentland } 1064562236bSHarry Wentland if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) || 107b264d345SJordan Lazare ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || 108b264d345SJordan Lazare ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) { 1094562236bSHarry Wentland dc_version = DCE_VERSION_11_2; 1104562236bSHarry Wentland } 1110c75d5acSJerry (Fangzhi) Zuo if (ASIC_REV_IS_VEGAM(asic_id.hw_internal_rev)) 1120c75d5acSJerry (Fangzhi) Zuo dc_version = DCE_VERSION_11_22; 1134562236bSHarry Wentland break; 1142c8ad2d5SAlex Deucher case FAMILY_AI: 115b8b6ce89SLeo Li if (ASICREV_IS_VEGA20_P(asic_id.hw_internal_rev)) 116b8b6ce89SLeo Li dc_version = DCE_VERSION_12_1; 117b8b6ce89SLeo Li else 1182c8ad2d5SAlex Deucher dc_version = DCE_VERSION_12_0; 1192c8ad2d5SAlex Deucher break; 120b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 121ff5ef992SAlex Deucher case FAMILY_RV: 122ff5ef992SAlex Deucher dc_version = DCN_VERSION_1_0; 1230e3d73f1SBhawanpreet Lakha if (ASICREV_IS_RAVEN2(asic_id.hw_internal_rev)) 1240e3d73f1SBhawanpreet Lakha dc_version = DCN_VERSION_1_01; 125e22ece54SBhawanpreet Lakha if (ASICREV_IS_RENOIR(asic_id.hw_internal_rev)) 126e22ece54SBhawanpreet Lakha dc_version = DCN_VERSION_2_1; 1279ba93114SRoman Li if (ASICREV_IS_GREEN_SARDINE(asic_id.hw_internal_rev)) 1289ba93114SRoman Li dc_version = DCN_VERSION_2_1; 129ff5ef992SAlex Deucher break; 1307ed4e635SHarry Wentland 1317ed4e635SHarry Wentland case FAMILY_NV: 1327ed4e635SHarry Wentland dc_version = DCN_VERSION_2_0; 1335dba4991SBhawanpreet Lakha if (ASICREV_IS_SIENNA_CICHLID_P(asic_id.hw_internal_rev)) 1345dba4991SBhawanpreet Lakha dc_version = DCN_VERSION_3_0; 13536d26912SBhawanpreet Lakha if (ASICREV_IS_DIMGREY_CAVEFISH_P(asic_id.hw_internal_rev)) 13636d26912SBhawanpreet Lakha dc_version = DCN_VERSION_3_02; 137cd6d421eSAurabindo Pillai if (ASICREV_IS_BEIGE_GOBY_P(asic_id.hw_internal_rev)) 138cd6d421eSAurabindo Pillai dc_version = DCN_VERSION_3_03; 1397ed4e635SHarry Wentland break; 1403a83e4e6SRoman Li 1413a83e4e6SRoman Li case FAMILY_VGH: 1423a83e4e6SRoman Li dc_version = DCN_VERSION_3_01; 1433a83e4e6SRoman Li break; 1442083640fSNicholas Kazlauskas 1452083640fSNicholas Kazlauskas case FAMILY_YELLOW_CARP: 1462083640fSNicholas Kazlauskas if (ASICREV_IS_YELLOW_CARP(asic_id.hw_internal_rev)) 1472083640fSNicholas Kazlauskas dc_version = DCN_VERSION_3_1; 1482083640fSNicholas Kazlauskas break; 1492083640fSNicholas Kazlauskas #endif 1502083640fSNicholas Kazlauskas 1514562236bSHarry Wentland default: 1524562236bSHarry Wentland dc_version = DCE_VERSION_UNKNOWN; 1534562236bSHarry Wentland break; 1544562236bSHarry Wentland } 1554562236bSHarry Wentland return dc_version; 1564562236bSHarry Wentland } 1574562236bSHarry Wentland 158d9673c92SHarry Wentland struct resource_pool *dc_create_resource_pool(struct dc *dc, 159d9673c92SHarry Wentland const struct dc_init_data *init_data, 160d9673c92SHarry Wentland enum dce_version dc_version) 1614562236bSHarry Wentland { 1625ac3d3c9SCharlene Liu struct resource_pool *res_pool = NULL; 1634562236bSHarry Wentland 1644562236bSHarry Wentland switch (dc_version) { 165683b5950SMauro Rossi #if defined(CONFIG_DRM_AMD_DC_SI) 166683b5950SMauro Rossi case DCE_VERSION_6_0: 167683b5950SMauro Rossi res_pool = dce60_create_resource_pool( 168683b5950SMauro Rossi init_data->num_virtual_links, dc); 169683b5950SMauro Rossi break; 170683b5950SMauro Rossi case DCE_VERSION_6_1: 171683b5950SMauro Rossi res_pool = dce61_create_resource_pool( 172683b5950SMauro Rossi init_data->num_virtual_links, dc); 173683b5950SMauro Rossi break; 174683b5950SMauro Rossi case DCE_VERSION_6_4: 175683b5950SMauro Rossi res_pool = dce64_create_resource_pool( 176683b5950SMauro Rossi init_data->num_virtual_links, dc); 177683b5950SMauro Rossi break; 178683b5950SMauro Rossi #endif 1794562236bSHarry Wentland case DCE_VERSION_8_0: 1805ac3d3c9SCharlene Liu res_pool = dce80_create_resource_pool( 181d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1825ac3d3c9SCharlene Liu break; 1837992a629SAlex Deucher case DCE_VERSION_8_1: 1847992a629SAlex Deucher res_pool = dce81_create_resource_pool( 185d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1867992a629SAlex Deucher break; 1877992a629SAlex Deucher case DCE_VERSION_8_3: 1887992a629SAlex Deucher res_pool = dce83_create_resource_pool( 189d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1907992a629SAlex Deucher break; 1914562236bSHarry Wentland case DCE_VERSION_10_0: 1925ac3d3c9SCharlene Liu res_pool = dce100_create_resource_pool( 193d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1945ac3d3c9SCharlene Liu break; 1954562236bSHarry Wentland case DCE_VERSION_11_0: 1965ac3d3c9SCharlene Liu res_pool = dce110_create_resource_pool( 197d9673c92SHarry Wentland init_data->num_virtual_links, dc, 198d9673c92SHarry Wentland init_data->asic_id); 1995ac3d3c9SCharlene Liu break; 2004562236bSHarry Wentland case DCE_VERSION_11_2: 2010c75d5acSJerry (Fangzhi) Zuo case DCE_VERSION_11_22: 2025ac3d3c9SCharlene Liu res_pool = dce112_create_resource_pool( 203d9673c92SHarry Wentland init_data->num_virtual_links, dc); 2045ac3d3c9SCharlene Liu break; 2052c8ad2d5SAlex Deucher case DCE_VERSION_12_0: 206b8b6ce89SLeo Li case DCE_VERSION_12_1: 2072c8ad2d5SAlex Deucher res_pool = dce120_create_resource_pool( 208d9673c92SHarry Wentland init_data->num_virtual_links, dc); 2092c8ad2d5SAlex Deucher break; 210ff5ef992SAlex Deucher 211b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 212ff5ef992SAlex Deucher case DCN_VERSION_1_0: 2130e3d73f1SBhawanpreet Lakha case DCN_VERSION_1_01: 214d9673c92SHarry Wentland res_pool = dcn10_create_resource_pool(init_data, dc); 215ff5ef992SAlex Deucher break; 2167ed4e635SHarry Wentland case DCN_VERSION_2_0: 2177ed4e635SHarry Wentland res_pool = dcn20_create_resource_pool(init_data, dc); 2187ed4e635SHarry Wentland break; 219e22ece54SBhawanpreet Lakha case DCN_VERSION_2_1: 220e22ece54SBhawanpreet Lakha res_pool = dcn21_create_resource_pool(init_data, dc); 221e22ece54SBhawanpreet Lakha break; 2225dba4991SBhawanpreet Lakha case DCN_VERSION_3_0: 2235dba4991SBhawanpreet Lakha res_pool = dcn30_create_resource_pool(init_data, dc); 2245dba4991SBhawanpreet Lakha break; 2253a83e4e6SRoman Li case DCN_VERSION_3_01: 2263a83e4e6SRoman Li res_pool = dcn301_create_resource_pool(init_data, dc); 2273a83e4e6SRoman Li break; 22836d26912SBhawanpreet Lakha case DCN_VERSION_3_02: 22936d26912SBhawanpreet Lakha res_pool = dcn302_create_resource_pool(init_data, dc); 23036d26912SBhawanpreet Lakha break; 231cd6d421eSAurabindo Pillai case DCN_VERSION_3_03: 232cd6d421eSAurabindo Pillai res_pool = dcn303_create_resource_pool(init_data, dc); 233cd6d421eSAurabindo Pillai break; 2342083640fSNicholas Kazlauskas case DCN_VERSION_3_1: 2352083640fSNicholas Kazlauskas res_pool = dcn31_create_resource_pool(init_data, dc); 2362083640fSNicholas Kazlauskas break; 2372083640fSNicholas Kazlauskas #endif 2384562236bSHarry Wentland default: 2394562236bSHarry Wentland break; 2404562236bSHarry Wentland } 241f49cfa27Shersen wu 2425ac3d3c9SCharlene Liu if (res_pool != NULL) { 2439adc8050SDmytro Laktyushkin if (dc->ctx->dc_bios->fw_info_valid) { 24441a5a2a8Shersen wu res_pool->ref_clocks.xtalin_clock_inKhz = 2459adc8050SDmytro Laktyushkin dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency; 24641a5a2a8Shersen wu /* initialize with firmware data first, no all 24741a5a2a8Shersen wu * ASIC have DCCG SW component. FPGA or 24841a5a2a8Shersen wu * simulation need initialization of 24941a5a2a8Shersen wu * dccg_ref_clock_inKhz, dchub_ref_clock_inKhz 25041a5a2a8Shersen wu * with xtalin_clock_inKhz 25141a5a2a8Shersen wu */ 25241a5a2a8Shersen wu res_pool->ref_clocks.dccg_ref_clock_inKhz = 25341a5a2a8Shersen wu res_pool->ref_clocks.xtalin_clock_inKhz; 25441a5a2a8Shersen wu res_pool->ref_clocks.dchub_ref_clock_inKhz = 25541a5a2a8Shersen wu res_pool->ref_clocks.xtalin_clock_inKhz; 2565ac3d3c9SCharlene Liu } else 2575ac3d3c9SCharlene Liu ASSERT_CRITICAL(false); 2585ac3d3c9SCharlene Liu } 2595ac3d3c9SCharlene Liu 2605ac3d3c9SCharlene Liu return res_pool; 2614562236bSHarry Wentland } 2624562236bSHarry Wentland 263fb3466a4SBhawanpreet Lakha void dc_destroy_resource_pool(struct dc *dc) 2644562236bSHarry Wentland { 2654562236bSHarry Wentland if (dc) { 2664562236bSHarry Wentland if (dc->res_pool) 2674562236bSHarry Wentland dc->res_pool->funcs->destroy(&dc->res_pool); 2684562236bSHarry Wentland 2692004f45eSHarry Wentland kfree(dc->hwseq); 2704562236bSHarry Wentland } 2714562236bSHarry Wentland } 2724562236bSHarry Wentland 2734562236bSHarry Wentland static void update_num_audio( 2744562236bSHarry Wentland const struct resource_straps *straps, 2754562236bSHarry Wentland unsigned int *num_audio, 2764562236bSHarry Wentland struct audio_support *aud_support) 2774562236bSHarry Wentland { 2784562236bSHarry Wentland aud_support->dp_audio = true; 279b8e9eb72SCharlene Liu aud_support->hdmi_audio_native = false; 280b8e9eb72SCharlene Liu aud_support->hdmi_audio_on_dongle = false; 281b8e9eb72SCharlene Liu 282b8e9eb72SCharlene Liu if (straps->hdmi_disable == 0) { 2834562236bSHarry Wentland if (straps->dc_pinstraps_audio & 0x2) { 2844562236bSHarry Wentland aud_support->hdmi_audio_on_dongle = true; 285b8e9eb72SCharlene Liu aud_support->hdmi_audio_native = true; 2864562236bSHarry Wentland } 2874562236bSHarry Wentland } 2884562236bSHarry Wentland 2894562236bSHarry Wentland switch (straps->audio_stream_number) { 2904562236bSHarry Wentland case 0: /* multi streams supported */ 2914562236bSHarry Wentland break; 2924562236bSHarry Wentland case 1: /* multi streams not supported */ 2934562236bSHarry Wentland *num_audio = 1; 2944562236bSHarry Wentland break; 2954562236bSHarry Wentland default: 2964562236bSHarry Wentland DC_ERR("DC: unexpected audio fuse!\n"); 29717a96033SJulia Lawall } 2984562236bSHarry Wentland } 2994562236bSHarry Wentland 3004562236bSHarry Wentland bool resource_construct( 3014562236bSHarry Wentland unsigned int num_virtual_links, 302fb3466a4SBhawanpreet Lakha struct dc *dc, 3034562236bSHarry Wentland struct resource_pool *pool, 3044562236bSHarry Wentland const struct resource_create_funcs *create_funcs) 3054562236bSHarry Wentland { 3064562236bSHarry Wentland struct dc_context *ctx = dc->ctx; 3074562236bSHarry Wentland const struct resource_caps *caps = pool->res_cap; 3084562236bSHarry Wentland int i; 3094562236bSHarry Wentland unsigned int num_audio = caps->num_audio; 3104562236bSHarry Wentland struct resource_straps straps = {0}; 3114562236bSHarry Wentland 3124562236bSHarry Wentland if (create_funcs->read_dce_straps) 3134562236bSHarry Wentland create_funcs->read_dce_straps(dc->ctx, &straps); 3144562236bSHarry Wentland 3154562236bSHarry Wentland pool->audio_count = 0; 3164562236bSHarry Wentland if (create_funcs->create_audio) { 3174562236bSHarry Wentland /* find the total number of streams available via the 3184562236bSHarry Wentland * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT 3194562236bSHarry Wentland * registers (one for each pin) starting from pin 1 3204562236bSHarry Wentland * up to the max number of audio pins. 3214562236bSHarry Wentland * We stop on the first pin where 3224562236bSHarry Wentland * PORT_CONNECTIVITY == 1 (as instructed by HW team). 3234562236bSHarry Wentland */ 3244562236bSHarry Wentland update_num_audio(&straps, &num_audio, &pool->audio_support); 3255feb9f07STai Man for (i = 0; i < caps->num_audio; i++) { 3264562236bSHarry Wentland struct audio *aud = create_funcs->create_audio(ctx, i); 3274562236bSHarry Wentland 3284562236bSHarry Wentland if (aud == NULL) { 3294562236bSHarry Wentland DC_ERR("DC: failed to create audio!\n"); 3304562236bSHarry Wentland return false; 3314562236bSHarry Wentland } 3324562236bSHarry Wentland if (!aud->funcs->endpoint_valid(aud)) { 3334562236bSHarry Wentland aud->funcs->destroy(&aud); 3344562236bSHarry Wentland break; 3354562236bSHarry Wentland } 3364562236bSHarry Wentland pool->audios[i] = aud; 3374562236bSHarry Wentland pool->audio_count++; 3384562236bSHarry Wentland } 3394562236bSHarry Wentland } 3404562236bSHarry Wentland 3414562236bSHarry Wentland pool->stream_enc_count = 0; 3424562236bSHarry Wentland if (create_funcs->create_stream_encoder) { 3434562236bSHarry Wentland for (i = 0; i < caps->num_stream_encoder; i++) { 3444562236bSHarry Wentland pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx); 3454562236bSHarry Wentland if (pool->stream_enc[i] == NULL) 3464562236bSHarry Wentland DC_ERR("DC: failed to create stream_encoder!\n"); 3474562236bSHarry Wentland pool->stream_enc_count++; 3484562236bSHarry Wentland } 3494562236bSHarry Wentland } 350929c3aaaSEric Bernstein 35120f2ffe5SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN) 352f01ee019SFangzhi Zuo pool->hpo_dp_stream_enc_count = 0; 353f01ee019SFangzhi Zuo if (create_funcs->create_hpo_dp_stream_encoder) { 354f01ee019SFangzhi Zuo for (i = 0; i < caps->num_hpo_dp_stream_encoder; i++) { 355f01ee019SFangzhi Zuo pool->hpo_dp_stream_enc[i] = create_funcs->create_hpo_dp_stream_encoder(i+ENGINE_ID_HPO_DP_0, ctx); 356f01ee019SFangzhi Zuo if (pool->hpo_dp_stream_enc[i] == NULL) 357f01ee019SFangzhi Zuo DC_ERR("DC: failed to create HPO DP stream encoder!\n"); 358f01ee019SFangzhi Zuo pool->hpo_dp_stream_enc_count++; 359f01ee019SFangzhi Zuo 360f01ee019SFangzhi Zuo } 361f01ee019SFangzhi Zuo } 362f01ee019SFangzhi Zuo 363f01ee019SFangzhi Zuo pool->hpo_dp_link_enc_count = 0; 364f01ee019SFangzhi Zuo if (create_funcs->create_hpo_dp_link_encoder) { 365f01ee019SFangzhi Zuo for (i = 0; i < caps->num_hpo_dp_link_encoder; i++) { 366f01ee019SFangzhi Zuo pool->hpo_dp_link_enc[i] = create_funcs->create_hpo_dp_link_encoder(i, ctx); 367f01ee019SFangzhi Zuo if (pool->hpo_dp_link_enc[i] == NULL) 368f01ee019SFangzhi Zuo DC_ERR("DC: failed to create HPO DP link encoder!\n"); 369f01ee019SFangzhi Zuo pool->hpo_dp_link_enc_count++; 370f01ee019SFangzhi Zuo } 371f01ee019SFangzhi Zuo } 372f01ee019SFangzhi Zuo #endif 373f01ee019SFangzhi Zuo 374f01ee019SFangzhi Zuo #if defined(CONFIG_DRM_AMD_DC_DCN) 3755dba4991SBhawanpreet Lakha for (i = 0; i < caps->num_mpc_3dlut; i++) { 3765dba4991SBhawanpreet Lakha pool->mpc_lut[i] = dc_create_3dlut_func(); 3775dba4991SBhawanpreet Lakha if (pool->mpc_lut[i] == NULL) 3785dba4991SBhawanpreet Lakha DC_ERR("DC: failed to create MPC 3dlut!\n"); 3795dba4991SBhawanpreet Lakha pool->mpc_shaper[i] = dc_create_transfer_func(); 3805dba4991SBhawanpreet Lakha if (pool->mpc_shaper[i] == NULL) 3815dba4991SBhawanpreet Lakha DC_ERR("DC: failed to create MPC shaper!\n"); 3825dba4991SBhawanpreet Lakha } 3835dba4991SBhawanpreet Lakha #endif 3844176664bSCharlene Liu dc->caps.dynamic_audio = false; 3854176664bSCharlene Liu if (pool->audio_count < pool->stream_enc_count) { 3864176664bSCharlene Liu dc->caps.dynamic_audio = true; 3874176664bSCharlene Liu } 3884562236bSHarry Wentland for (i = 0; i < num_virtual_links; i++) { 3894562236bSHarry Wentland pool->stream_enc[pool->stream_enc_count] = 3904562236bSHarry Wentland virtual_stream_encoder_create( 3914562236bSHarry Wentland ctx, ctx->dc_bios); 3924562236bSHarry Wentland if (pool->stream_enc[pool->stream_enc_count] == NULL) { 3934562236bSHarry Wentland DC_ERR("DC: failed to create stream_encoder!\n"); 3944562236bSHarry Wentland return false; 3954562236bSHarry Wentland } 3964562236bSHarry Wentland pool->stream_enc_count++; 3974562236bSHarry Wentland } 3984562236bSHarry Wentland 3994562236bSHarry Wentland dc->hwseq = create_funcs->create_hwseq(ctx); 4004562236bSHarry Wentland 4014562236bSHarry Wentland return true; 4024562236bSHarry Wentland } 403ad8960a6SMikita Lipski static int find_matching_clock_source( 404ad8960a6SMikita Lipski const struct resource_pool *pool, 405ad8960a6SMikita Lipski struct clock_source *clock_source) 406ad8960a6SMikita Lipski { 4074562236bSHarry Wentland 408ad8960a6SMikita Lipski int i; 409ad8960a6SMikita Lipski 410ad8960a6SMikita Lipski for (i = 0; i < pool->clk_src_count; i++) { 411ad8960a6SMikita Lipski if (pool->clock_sources[i] == clock_source) 412ad8960a6SMikita Lipski return i; 413ad8960a6SMikita Lipski } 414ad8960a6SMikita Lipski return -1; 415ad8960a6SMikita Lipski } 4164562236bSHarry Wentland 41721e67d4dSHarry Wentland void resource_unreference_clock_source( 4184562236bSHarry Wentland struct resource_context *res_ctx, 419a2b8659dSTony Cheng const struct resource_pool *pool, 4204a629536SHarry Wentland struct clock_source *clock_source) 4214562236bSHarry Wentland { 422ad8960a6SMikita Lipski int i = find_matching_clock_source(pool, clock_source); 4234a629536SHarry Wentland 424ad8960a6SMikita Lipski if (i > -1) 4254562236bSHarry Wentland res_ctx->clock_source_ref_count[i]--; 4264562236bSHarry Wentland 42721e67d4dSHarry Wentland if (pool->dp_clock_source == clock_source) 4284562236bSHarry Wentland res_ctx->dp_clock_source_ref_count--; 4294562236bSHarry Wentland } 4304562236bSHarry Wentland 4314562236bSHarry Wentland void resource_reference_clock_source( 4324562236bSHarry Wentland struct resource_context *res_ctx, 433a2b8659dSTony Cheng const struct resource_pool *pool, 4344562236bSHarry Wentland struct clock_source *clock_source) 4354562236bSHarry Wentland { 436ad8960a6SMikita Lipski int i = find_matching_clock_source(pool, clock_source); 4374562236bSHarry Wentland 438ad8960a6SMikita Lipski if (i > -1) 4394562236bSHarry Wentland res_ctx->clock_source_ref_count[i]++; 4404562236bSHarry Wentland 441a2b8659dSTony Cheng if (pool->dp_clock_source == clock_source) 4424562236bSHarry Wentland res_ctx->dp_clock_source_ref_count++; 4434562236bSHarry Wentland } 4444562236bSHarry Wentland 445ad8960a6SMikita Lipski int resource_get_clock_source_reference( 446ad8960a6SMikita Lipski struct resource_context *res_ctx, 447ad8960a6SMikita Lipski const struct resource_pool *pool, 448ad8960a6SMikita Lipski struct clock_source *clock_source) 449ad8960a6SMikita Lipski { 450ad8960a6SMikita Lipski int i = find_matching_clock_source(pool, clock_source); 451ad8960a6SMikita Lipski 452ad8960a6SMikita Lipski if (i > -1) 453ad8960a6SMikita Lipski return res_ctx->clock_source_ref_count[i]; 454ad8960a6SMikita Lipski 455ad8960a6SMikita Lipski if (pool->dp_clock_source == clock_source) 456ad8960a6SMikita Lipski return res_ctx->dp_clock_source_ref_count; 457ad8960a6SMikita Lipski 458ad8960a6SMikita Lipski return -1; 459ad8960a6SMikita Lipski } 460ad8960a6SMikita Lipski 46177a2b726SVladimir Stempen bool resource_are_vblanks_synchronizable( 46277a2b726SVladimir Stempen struct dc_stream_state *stream1, 46377a2b726SVladimir Stempen struct dc_stream_state *stream2) 46477a2b726SVladimir Stempen { 46577a2b726SVladimir Stempen uint32_t base60_refresh_rates[] = {10, 20, 5}; 46677a2b726SVladimir Stempen uint8_t i; 467d0b3bbd3SJiapeng Chong uint8_t rr_count = ARRAY_SIZE(base60_refresh_rates); 468783bf403SVladimir Stempen uint64_t frame_time_diff; 46977a2b726SVladimir Stempen 47077a2b726SVladimir Stempen if (stream1->ctx->dc->config.vblank_alignment_dto_params && 47177a2b726SVladimir Stempen stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0 && 47277a2b726SVladimir Stempen dc_is_dp_signal(stream1->signal) && 47377a2b726SVladimir Stempen dc_is_dp_signal(stream2->signal) && 47477a2b726SVladimir Stempen false == stream1->has_non_synchronizable_pclk && 47577a2b726SVladimir Stempen false == stream2->has_non_synchronizable_pclk && 47677a2b726SVladimir Stempen stream1->timing.flags.VBLANK_SYNCHRONIZABLE && 47777a2b726SVladimir Stempen stream2->timing.flags.VBLANK_SYNCHRONIZABLE) { 47877a2b726SVladimir Stempen /* disable refresh rates higher than 60Hz for now */ 47977a2b726SVladimir Stempen if (stream1->timing.pix_clk_100hz*100/stream1->timing.h_total/ 48077a2b726SVladimir Stempen stream1->timing.v_total > 60) 48177a2b726SVladimir Stempen return false; 48277a2b726SVladimir Stempen if (stream2->timing.pix_clk_100hz*100/stream2->timing.h_total/ 48377a2b726SVladimir Stempen stream2->timing.v_total > 60) 48477a2b726SVladimir Stempen return false; 485783bf403SVladimir Stempen frame_time_diff = (uint64_t)10000 * 48677a2b726SVladimir Stempen stream1->timing.h_total * 48777a2b726SVladimir Stempen stream1->timing.v_total * 488783bf403SVladimir Stempen stream2->timing.pix_clk_100hz; 489783bf403SVladimir Stempen frame_time_diff = div_u64(frame_time_diff, stream1->timing.pix_clk_100hz); 490783bf403SVladimir Stempen frame_time_diff = div_u64(frame_time_diff, stream2->timing.h_total); 491783bf403SVladimir Stempen frame_time_diff = div_u64(frame_time_diff, stream2->timing.v_total); 49277a2b726SVladimir Stempen for (i = 0; i < rr_count; i++) { 493783bf403SVladimir Stempen int64_t diff = (int64_t)div_u64(frame_time_diff * base60_refresh_rates[i], 10) - 10000; 49477a2b726SVladimir Stempen 49577a2b726SVladimir Stempen if (diff < 0) 49677a2b726SVladimir Stempen diff = -diff; 49777a2b726SVladimir Stempen if (diff < stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff) 49877a2b726SVladimir Stempen return true; 49977a2b726SVladimir Stempen } 50077a2b726SVladimir Stempen } 50177a2b726SVladimir Stempen return false; 50277a2b726SVladimir Stempen } 50377a2b726SVladimir Stempen 5044562236bSHarry Wentland bool resource_are_streams_timing_synchronizable( 5050971c40eSHarry Wentland struct dc_stream_state *stream1, 5060971c40eSHarry Wentland struct dc_stream_state *stream2) 5074562236bSHarry Wentland { 5084fa086b9SLeo (Sunpeng) Li if (stream1->timing.h_total != stream2->timing.h_total) 5094562236bSHarry Wentland return false; 5104562236bSHarry Wentland 5114fa086b9SLeo (Sunpeng) Li if (stream1->timing.v_total != stream2->timing.v_total) 5124562236bSHarry Wentland return false; 5134562236bSHarry Wentland 5144fa086b9SLeo (Sunpeng) Li if (stream1->timing.h_addressable 5154fa086b9SLeo (Sunpeng) Li != stream2->timing.h_addressable) 5164562236bSHarry Wentland return false; 5174562236bSHarry Wentland 5184fa086b9SLeo (Sunpeng) Li if (stream1->timing.v_addressable 5194fa086b9SLeo (Sunpeng) Li != stream2->timing.v_addressable) 5204562236bSHarry Wentland return false; 5214562236bSHarry Wentland 5228582aea2SDavid Galiffi if (stream1->timing.v_front_porch 5238582aea2SDavid Galiffi != stream2->timing.v_front_porch) 5248582aea2SDavid Galiffi return false; 5258582aea2SDavid Galiffi 526380604e2SKen Chalmers if (stream1->timing.pix_clk_100hz 527380604e2SKen Chalmers != stream2->timing.pix_clk_100hz) 5284562236bSHarry Wentland return false; 5294562236bSHarry Wentland 5303e27e10eSMikita Lipski if (stream1->clamping.c_depth != stream2->clamping.c_depth) 5313e27e10eSMikita Lipski return false; 5323e27e10eSMikita Lipski 5334562236bSHarry Wentland if (stream1->phy_pix_clk != stream2->phy_pix_clk 5347e2fe319SCharlene Liu && (!dc_is_dp_signal(stream1->signal) 5357e2fe319SCharlene Liu || !dc_is_dp_signal(stream2->signal))) 5364562236bSHarry Wentland return false; 5374562236bSHarry Wentland 538d77f778eSCharlene Liu if (stream1->view_format != stream2->view_format) 539d77f778eSCharlene Liu return false; 540d77f778eSCharlene Liu 5410460f9abSJun Lei if (stream1->ignore_msa_timing_param || stream2->ignore_msa_timing_param) 5420460f9abSJun Lei return false; 5430460f9abSJun Lei 5444562236bSHarry Wentland return true; 5454562236bSHarry Wentland } 5463e27e10eSMikita Lipski static bool is_dp_and_hdmi_sharable( 5473e27e10eSMikita Lipski struct dc_stream_state *stream1, 5483e27e10eSMikita Lipski struct dc_stream_state *stream2) 5493e27e10eSMikita Lipski { 5503e27e10eSMikita Lipski if (stream1->ctx->dc->caps.disable_dp_clk_share) 5513e27e10eSMikita Lipski return false; 5523e27e10eSMikita Lipski 5533e27e10eSMikita Lipski if (stream1->clamping.c_depth != COLOR_DEPTH_888 || 5543e27e10eSMikita Lipski stream2->clamping.c_depth != COLOR_DEPTH_888) 5553e27e10eSMikita Lipski return false; 5563e27e10eSMikita Lipski 5573e27e10eSMikita Lipski return true; 5583e27e10eSMikita Lipski 5593e27e10eSMikita Lipski } 5604562236bSHarry Wentland 5614562236bSHarry Wentland static bool is_sharable_clk_src( 5624562236bSHarry Wentland const struct pipe_ctx *pipe_with_clk_src, 5634562236bSHarry Wentland const struct pipe_ctx *pipe) 5644562236bSHarry Wentland { 5654562236bSHarry Wentland if (pipe_with_clk_src->clock_source == NULL) 5664562236bSHarry Wentland return false; 5674562236bSHarry Wentland 5684562236bSHarry Wentland if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL) 5694562236bSHarry Wentland return false; 5704562236bSHarry Wentland 5713e27e10eSMikita Lipski if (dc_is_dp_signal(pipe_with_clk_src->stream->signal) || 5723e27e10eSMikita Lipski (dc_is_dp_signal(pipe->stream->signal) && 5733e27e10eSMikita Lipski !is_dp_and_hdmi_sharable(pipe_with_clk_src->stream, 5743e27e10eSMikita Lipski pipe->stream))) 5754562236bSHarry Wentland return false; 5764562236bSHarry Wentland 5774562236bSHarry Wentland if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal) 578fc69009eSMikita Lipski && dc_is_dual_link_signal(pipe->stream->signal)) 5794562236bSHarry Wentland return false; 5804562236bSHarry Wentland 5814562236bSHarry Wentland if (dc_is_hdmi_signal(pipe->stream->signal) 582fc69009eSMikita Lipski && dc_is_dual_link_signal(pipe_with_clk_src->stream->signal)) 5834562236bSHarry Wentland return false; 5844562236bSHarry Wentland 5854562236bSHarry Wentland if (!resource_are_streams_timing_synchronizable( 5864562236bSHarry Wentland pipe_with_clk_src->stream, pipe->stream)) 5874562236bSHarry Wentland return false; 5884562236bSHarry Wentland 5894562236bSHarry Wentland return true; 5904562236bSHarry Wentland } 5914562236bSHarry Wentland 5924562236bSHarry Wentland struct clock_source *resource_find_used_clk_src_for_sharing( 5934562236bSHarry Wentland struct resource_context *res_ctx, 5944562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 5954562236bSHarry Wentland { 5964562236bSHarry Wentland int i; 5974562236bSHarry Wentland 5984562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 5994562236bSHarry Wentland if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx)) 6004562236bSHarry Wentland return res_ctx->pipe_ctx[i].clock_source; 6014562236bSHarry Wentland } 6024562236bSHarry Wentland 6034562236bSHarry Wentland return NULL; 6044562236bSHarry Wentland } 6054562236bSHarry Wentland 6064562236bSHarry Wentland static enum pixel_format convert_pixel_format_to_dalsurface( 6074562236bSHarry Wentland enum surface_pixel_format surface_pixel_format) 6084562236bSHarry Wentland { 6094562236bSHarry Wentland enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 6104562236bSHarry Wentland 6114562236bSHarry Wentland switch (surface_pixel_format) { 6124562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 6134562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_INDEX8; 6144562236bSHarry Wentland break; 6154562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 6164562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_RGB565; 6174562236bSHarry Wentland break; 6184562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 6194562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_RGB565; 6204562236bSHarry Wentland break; 6214562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 6224562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB8888; 6234562236bSHarry Wentland break; 6248693049aSTony Cheng case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 6254562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB8888; 6264562236bSHarry Wentland break; 6274562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 6284562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 6294562236bSHarry Wentland break; 6304562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 6314562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 6324562236bSHarry Wentland break; 6334562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 6344562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS; 6354562236bSHarry Wentland break; 6364562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 6374562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 6384562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_FP16; 6394562236bSHarry Wentland break; 6404562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 6414562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 64287449a90SAnthony Koo dal_pixel_format = PIXEL_FORMAT_420BPP8; 6434562236bSHarry Wentland break; 644ffbcd19aSVitaly Prosyak case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 645ffbcd19aSVitaly Prosyak case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 64687449a90SAnthony Koo dal_pixel_format = PIXEL_FORMAT_420BPP10; 647ffbcd19aSVitaly Prosyak break; 6484562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 649050cd3d6SMario Kleiner case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: 6504562236bSHarry Wentland default: 6514562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 6524562236bSHarry Wentland break; 6534562236bSHarry Wentland } 6544562236bSHarry Wentland return dal_pixel_format; 6554562236bSHarry Wentland } 6564562236bSHarry Wentland 6579b6067c0SDmytro Laktyushkin static inline void get_vp_scan_direction( 6589b6067c0SDmytro Laktyushkin enum dc_rotation_angle rotation, 6599b6067c0SDmytro Laktyushkin bool horizontal_mirror, 6609b6067c0SDmytro Laktyushkin bool *orthogonal_rotation, 6619b6067c0SDmytro Laktyushkin bool *flip_vert_scan_dir, 6629b6067c0SDmytro Laktyushkin bool *flip_horz_scan_dir) 6634562236bSHarry Wentland { 6649b6067c0SDmytro Laktyushkin *orthogonal_rotation = false; 6659b6067c0SDmytro Laktyushkin *flip_vert_scan_dir = false; 6669b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = false; 6679b6067c0SDmytro Laktyushkin if (rotation == ROTATION_ANGLE_180) { 6689b6067c0SDmytro Laktyushkin *flip_vert_scan_dir = true; 6699b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = true; 6709b6067c0SDmytro Laktyushkin } else if (rotation == ROTATION_ANGLE_90) { 6719b6067c0SDmytro Laktyushkin *orthogonal_rotation = true; 6729b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = true; 6739b6067c0SDmytro Laktyushkin } else if (rotation == ROTATION_ANGLE_270) { 6749b6067c0SDmytro Laktyushkin *orthogonal_rotation = true; 6759b6067c0SDmytro Laktyushkin *flip_vert_scan_dir = true; 6769b6067c0SDmytro Laktyushkin } 6779b6067c0SDmytro Laktyushkin 6789b6067c0SDmytro Laktyushkin if (horizontal_mirror) 6799b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = !*flip_horz_scan_dir; 6804562236bSHarry Wentland } 6814562236bSHarry Wentland 682570bc18cSDmytro Laktyushkin int get_num_mpc_splits(struct pipe_ctx *pipe) 683570bc18cSDmytro Laktyushkin { 684570bc18cSDmytro Laktyushkin int mpc_split_count = 0; 685570bc18cSDmytro Laktyushkin struct pipe_ctx *other_pipe = pipe->bottom_pipe; 686570bc18cSDmytro Laktyushkin 687570bc18cSDmytro Laktyushkin while (other_pipe && other_pipe->plane_state == pipe->plane_state) { 688570bc18cSDmytro Laktyushkin mpc_split_count++; 689570bc18cSDmytro Laktyushkin other_pipe = other_pipe->bottom_pipe; 690570bc18cSDmytro Laktyushkin } 691570bc18cSDmytro Laktyushkin other_pipe = pipe->top_pipe; 692570bc18cSDmytro Laktyushkin while (other_pipe && other_pipe->plane_state == pipe->plane_state) { 693570bc18cSDmytro Laktyushkin mpc_split_count++; 694570bc18cSDmytro Laktyushkin other_pipe = other_pipe->top_pipe; 695570bc18cSDmytro Laktyushkin } 696570bc18cSDmytro Laktyushkin 697570bc18cSDmytro Laktyushkin return mpc_split_count; 698570bc18cSDmytro Laktyushkin } 699570bc18cSDmytro Laktyushkin 700228a10d4SAlex Deucher int get_num_odm_splits(struct pipe_ctx *pipe) 701228a10d4SAlex Deucher { 702228a10d4SAlex Deucher int odm_split_count = 0; 703228a10d4SAlex Deucher struct pipe_ctx *next_pipe = pipe->next_odm_pipe; 704228a10d4SAlex Deucher while (next_pipe) { 705228a10d4SAlex Deucher odm_split_count++; 706228a10d4SAlex Deucher next_pipe = next_pipe->next_odm_pipe; 707228a10d4SAlex Deucher } 708228a10d4SAlex Deucher pipe = pipe->prev_odm_pipe; 709228a10d4SAlex Deucher while (pipe) { 710228a10d4SAlex Deucher odm_split_count++; 711228a10d4SAlex Deucher pipe = pipe->prev_odm_pipe; 712228a10d4SAlex Deucher } 713228a10d4SAlex Deucher return odm_split_count; 714228a10d4SAlex Deucher } 715228a10d4SAlex Deucher 7165bf24270SDmytro Laktyushkin static void calculate_split_count_and_index(struct pipe_ctx *pipe_ctx, int *split_count, int *split_idx) 7175bf24270SDmytro Laktyushkin { 7185bf24270SDmytro Laktyushkin *split_count = get_num_odm_splits(pipe_ctx); 7195bf24270SDmytro Laktyushkin *split_idx = 0; 7205bf24270SDmytro Laktyushkin if (*split_count == 0) { 7215bf24270SDmytro Laktyushkin /*Check for mpc split*/ 7225bf24270SDmytro Laktyushkin struct pipe_ctx *split_pipe = pipe_ctx->top_pipe; 7235bf24270SDmytro Laktyushkin 724570bc18cSDmytro Laktyushkin *split_count = get_num_mpc_splits(pipe_ctx); 7255bf24270SDmytro Laktyushkin while (split_pipe && split_pipe->plane_state == pipe_ctx->plane_state) { 7265bf24270SDmytro Laktyushkin (*split_idx)++; 7275bf24270SDmytro Laktyushkin split_pipe = split_pipe->top_pipe; 7285bf24270SDmytro Laktyushkin } 7295bf24270SDmytro Laktyushkin } else { 7305bf24270SDmytro Laktyushkin /*Get odm split index*/ 7315bf24270SDmytro Laktyushkin struct pipe_ctx *split_pipe = pipe_ctx->prev_odm_pipe; 7325bf24270SDmytro Laktyushkin 7335bf24270SDmytro Laktyushkin while (split_pipe) { 7345bf24270SDmytro Laktyushkin (*split_idx)++; 7355bf24270SDmytro Laktyushkin split_pipe = split_pipe->prev_odm_pipe; 7365bf24270SDmytro Laktyushkin } 7375bf24270SDmytro Laktyushkin } 7385bf24270SDmytro Laktyushkin } 7395bf24270SDmytro Laktyushkin 7409b6067c0SDmytro Laktyushkin /* 7416566cae7SDmytro Laktyushkin * This is a preliminary vp size calculation to allow us to check taps support. 7426566cae7SDmytro Laktyushkin * The result is completely overridden afterwards. 7439b6067c0SDmytro Laktyushkin */ 7446566cae7SDmytro Laktyushkin static void calculate_viewport_size(struct pipe_ctx *pipe_ctx) 7456566cae7SDmytro Laktyushkin { 7466566cae7SDmytro Laktyushkin struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 7479b6067c0SDmytro Laktyushkin 7486566cae7SDmytro Laktyushkin data->viewport.width = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.horz, data->recout.width)); 7496566cae7SDmytro Laktyushkin data->viewport.height = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.vert, data->recout.height)); 7506566cae7SDmytro Laktyushkin data->viewport_c.width = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.horz_c, data->recout.width)); 7516566cae7SDmytro Laktyushkin data->viewport_c.height = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.vert_c, data->recout.height)); 7526566cae7SDmytro Laktyushkin if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 7536566cae7SDmytro Laktyushkin pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) { 7546566cae7SDmytro Laktyushkin swap(data->viewport.width, data->viewport.height); 7556566cae7SDmytro Laktyushkin swap(data->viewport_c.width, data->viewport_c.height); 7569b6067c0SDmytro Laktyushkin } 757b2d0a103SDmytro Laktyushkin } 7581fbd2cfcSDmytro Laktyushkin 7599b6067c0SDmytro Laktyushkin static void calculate_recout(struct pipe_ctx *pipe_ctx) 7604562236bSHarry Wentland { 7613be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 7620971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 7635bf24270SDmytro Laktyushkin struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 7643be5262eSHarry Wentland struct rect surf_clip = plane_state->clip_rect; 7656566cae7SDmytro Laktyushkin bool split_tb = stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; 7666566cae7SDmytro Laktyushkin int split_count, split_idx; 7674562236bSHarry Wentland 7685bf24270SDmytro Laktyushkin calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); 7696566cae7SDmytro Laktyushkin if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) 7706566cae7SDmytro Laktyushkin split_idx = 0; 7715bf24270SDmytro Laktyushkin 77205e3d830SWesley Chalmers /* 77305e3d830SWesley Chalmers * Only the leftmost ODM pipe should be offset by a nonzero distance 77405e3d830SWesley Chalmers */ 7756566cae7SDmytro Laktyushkin if (!pipe_ctx->prev_odm_pipe || split_idx == split_count) { 7765bf24270SDmytro Laktyushkin data->recout.x = stream->dst.x; 7774fa086b9SLeo (Sunpeng) Li if (stream->src.x < surf_clip.x) 7785bf24270SDmytro Laktyushkin data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width 7794fa086b9SLeo (Sunpeng) Li / stream->src.width; 78025b31581SWesley Chalmers } else 78125b31581SWesley Chalmers data->recout.x = 0; 78225b31581SWesley Chalmers 78384aef2abSDmytro Laktyushkin if (stream->src.x > surf_clip.x) 78484aef2abSDmytro Laktyushkin surf_clip.width -= stream->src.x - surf_clip.x; 7855bf24270SDmytro Laktyushkin data->recout.width = surf_clip.width * stream->dst.width / stream->src.width; 7865bf24270SDmytro Laktyushkin if (data->recout.width + data->recout.x > stream->dst.x + stream->dst.width) 7875bf24270SDmytro Laktyushkin data->recout.width = stream->dst.x + stream->dst.width - data->recout.x; 7884562236bSHarry Wentland 7895bf24270SDmytro Laktyushkin data->recout.y = stream->dst.y; 7904fa086b9SLeo (Sunpeng) Li if (stream->src.y < surf_clip.y) 7915bf24270SDmytro Laktyushkin data->recout.y += (surf_clip.y - stream->src.y) * stream->dst.height 7924fa086b9SLeo (Sunpeng) Li / stream->src.height; 79384aef2abSDmytro Laktyushkin else if (stream->src.y > surf_clip.y) 79484aef2abSDmytro Laktyushkin surf_clip.height -= stream->src.y - surf_clip.y; 7954562236bSHarry Wentland 7965bf24270SDmytro Laktyushkin data->recout.height = surf_clip.height * stream->dst.height / stream->src.height; 7975bf24270SDmytro Laktyushkin if (data->recout.height + data->recout.y > stream->dst.y + stream->dst.height) 7985bf24270SDmytro Laktyushkin data->recout.height = stream->dst.y + stream->dst.height - data->recout.y; 799b2d0a103SDmytro Laktyushkin 8006566cae7SDmytro Laktyushkin /* Handle h & v split */ 8016566cae7SDmytro Laktyushkin if (split_tb) { 8026566cae7SDmytro Laktyushkin ASSERT(data->recout.height % 2 == 0); 8035bf24270SDmytro Laktyushkin data->recout.height /= 2; 8046566cae7SDmytro Laktyushkin } else if (split_count) { 8056566cae7SDmytro Laktyushkin if (!pipe_ctx->next_odm_pipe && !pipe_ctx->prev_odm_pipe) { 8065bf24270SDmytro Laktyushkin /* extra pixels in the division remainder need to go to pipes after 8075bf24270SDmytro Laktyushkin * the extra pixel index minus one(epimo) defined here as: 8085bf24270SDmytro Laktyushkin */ 8095bf24270SDmytro Laktyushkin int epimo = split_count - data->recout.width % (split_count + 1); 8105bf24270SDmytro Laktyushkin 8115bf24270SDmytro Laktyushkin data->recout.x += (data->recout.width / (split_count + 1)) * split_idx; 8125bf24270SDmytro Laktyushkin if (split_idx > epimo) 8135bf24270SDmytro Laktyushkin data->recout.x += split_idx - epimo - 1; 8146566cae7SDmytro Laktyushkin ASSERT(stream->view_format != VIEW_3D_FORMAT_SIDE_BY_SIDE || data->recout.width % 2 == 0); 8155bf24270SDmytro Laktyushkin data->recout.width = data->recout.width / (split_count + 1) + (split_idx > epimo ? 1 : 0); 8166566cae7SDmytro Laktyushkin } else { 8176566cae7SDmytro Laktyushkin /* odm */ 8186566cae7SDmytro Laktyushkin if (split_idx == split_count) { 8196566cae7SDmytro Laktyushkin /* rightmost pipe is the remainder recout */ 8206566cae7SDmytro Laktyushkin data->recout.width -= data->h_active * split_count - data->recout.x; 821665f2850SAric Cyr 822665f2850SAric Cyr /* ODM combine cases with MPO we can get negative widths */ 823665f2850SAric Cyr if (data->recout.width < 0) 824665f2850SAric Cyr data->recout.width = 0; 825665f2850SAric Cyr 8266566cae7SDmytro Laktyushkin data->recout.x = 0; 8276566cae7SDmytro Laktyushkin } else 8286566cae7SDmytro Laktyushkin data->recout.width = data->h_active - data->recout.x; 8296566cae7SDmytro Laktyushkin } 8305bf24270SDmytro Laktyushkin } 8314562236bSHarry Wentland } 832b2d0a103SDmytro Laktyushkin 833b2d0a103SDmytro Laktyushkin static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) 8344562236bSHarry Wentland { 8353be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 8360971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 8373be5262eSHarry Wentland struct rect surf_src = plane_state->src_rect; 8384fa086b9SLeo (Sunpeng) Li const int in_w = stream->src.width; 8394fa086b9SLeo (Sunpeng) Li const int in_h = stream->src.height; 8404fa086b9SLeo (Sunpeng) Li const int out_w = stream->dst.width; 8414fa086b9SLeo (Sunpeng) Li const int out_h = stream->dst.height; 8424562236bSHarry Wentland 8439b6067c0SDmytro Laktyushkin /*Swap surf_src height and width since scaling ratios are in recout rotation*/ 8443be5262eSHarry Wentland if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 8453be5262eSHarry Wentland pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 8469b6067c0SDmytro Laktyushkin swap(surf_src.height, surf_src.width); 84786006a7fSDmytro Laktyushkin 848eb0e5154SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_from_fraction( 84986006a7fSDmytro Laktyushkin surf_src.width, 8503be5262eSHarry Wentland plane_state->dst_rect.width); 851eb0e5154SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_from_fraction( 85286006a7fSDmytro Laktyushkin surf_src.height, 8533be5262eSHarry Wentland plane_state->dst_rect.height); 8544562236bSHarry Wentland 8554fa086b9SLeo (Sunpeng) Li if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) 8566702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value *= 2; 8574fa086b9SLeo (Sunpeng) Li else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) 8586702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value *= 2; 8594562236bSHarry Wentland 8606702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value = div64_s64( 8616702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value * in_h, out_h); 8626702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value = div64_s64( 8636702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value * in_w, out_w); 8644562236bSHarry Wentland 8656702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz_c = pipe_ctx->plane_res.scl_data.ratios.horz; 8666702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert_c = pipe_ctx->plane_res.scl_data.ratios.vert; 8674562236bSHarry Wentland 8686702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP8 8696702a9acSHarry Wentland || pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP10) { 8706702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz_c.value /= 2; 8716702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert_c.value /= 2; 8724562236bSHarry Wentland } 8730002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_truncate( 8740002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz, 19); 8750002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_truncate( 8760002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert, 19); 8770002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz_c = dc_fixpt_truncate( 8780002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz_c, 19); 8790002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert_c = dc_fixpt_truncate( 8800002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert_c, 19); 8814562236bSHarry Wentland } 8824562236bSHarry Wentland 8836566cae7SDmytro Laktyushkin 8846566cae7SDmytro Laktyushkin /* 8856566cae7SDmytro Laktyushkin * We completely calculate vp offset, size and inits here based entirely on scaling 8866566cae7SDmytro Laktyushkin * ratios and recout for pixel perfect pipe combine. 8876566cae7SDmytro Laktyushkin */ 8886566cae7SDmytro Laktyushkin static void calculate_init_and_vp( 8899b6067c0SDmytro Laktyushkin bool flip_scan_dir, 8906566cae7SDmytro Laktyushkin int recout_offset_within_recout_full, 8916566cae7SDmytro Laktyushkin int recout_size, 8929b6067c0SDmytro Laktyushkin int src_size, 8939b6067c0SDmytro Laktyushkin int taps, 8949b6067c0SDmytro Laktyushkin struct fixed31_32 ratio, 8959b6067c0SDmytro Laktyushkin struct fixed31_32 *init, 8969b6067c0SDmytro Laktyushkin int *vp_offset, 8979b6067c0SDmytro Laktyushkin int *vp_size) 8984562236bSHarry Wentland { 8996566cae7SDmytro Laktyushkin struct fixed31_32 temp; 9009b6067c0SDmytro Laktyushkin int int_part; 9019b6067c0SDmytro Laktyushkin 9026566cae7SDmytro Laktyushkin /* 9036566cae7SDmytro Laktyushkin * First of the taps starts sampling pixel number <init_int_part> corresponding to recout 9046566cae7SDmytro Laktyushkin * pixel 1. Next recout pixel samples int part of <init + scaling ratio> and so on. 9056566cae7SDmytro Laktyushkin * All following calculations are based on this logic. 9066566cae7SDmytro Laktyushkin * 9076566cae7SDmytro Laktyushkin * Init calculated according to formula: 9086566cae7SDmytro Laktyushkin * init = (scaling_ratio + number_of_taps + 1) / 2 9096566cae7SDmytro Laktyushkin * init_bot = init + scaling_ratio 9106566cae7SDmytro Laktyushkin * to get pixel perfect combine add the fraction from calculating vp offset 9116566cae7SDmytro Laktyushkin */ 9126566cae7SDmytro Laktyushkin temp = dc_fixpt_mul_int(ratio, recout_offset_within_recout_full); 9136566cae7SDmytro Laktyushkin *vp_offset = dc_fixpt_floor(temp); 9146566cae7SDmytro Laktyushkin temp.value &= 0xffffffff; 9156566cae7SDmytro Laktyushkin *init = dc_fixpt_truncate(dc_fixpt_add(dc_fixpt_div_int( 9166566cae7SDmytro Laktyushkin dc_fixpt_add_int(ratio, taps + 1), 2), temp), 19); 9176566cae7SDmytro Laktyushkin /* 9186566cae7SDmytro Laktyushkin * If viewport has non 0 offset and there are more taps than covered by init then 9196566cae7SDmytro Laktyushkin * we should decrease the offset and increase init so we are never sampling 9206566cae7SDmytro Laktyushkin * outside of viewport. 9216566cae7SDmytro Laktyushkin */ 9226566cae7SDmytro Laktyushkin int_part = dc_fixpt_floor(*init); 9239b6067c0SDmytro Laktyushkin if (int_part < taps) { 9246566cae7SDmytro Laktyushkin int_part = taps - int_part; 9256566cae7SDmytro Laktyushkin if (int_part > *vp_offset) 9266566cae7SDmytro Laktyushkin int_part = *vp_offset; 9276566cae7SDmytro Laktyushkin *vp_offset -= int_part; 9289b6067c0SDmytro Laktyushkin *init = dc_fixpt_add_int(*init, int_part); 9299b6067c0SDmytro Laktyushkin } 9309b6067c0SDmytro Laktyushkin /* 9316566cae7SDmytro Laktyushkin * If taps are sampling outside of viewport at end of recout and there are more pixels 9326566cae7SDmytro Laktyushkin * available in the surface we should increase the viewport size, regardless set vp to 9336566cae7SDmytro Laktyushkin * only what is used. 9349b6067c0SDmytro Laktyushkin */ 9356566cae7SDmytro Laktyushkin temp = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_size - 1)); 9366566cae7SDmytro Laktyushkin *vp_size = dc_fixpt_floor(temp); 9376566cae7SDmytro Laktyushkin if (*vp_size + *vp_offset > src_size) 9386566cae7SDmytro Laktyushkin *vp_size = src_size - *vp_offset; 9396566cae7SDmytro Laktyushkin 9406566cae7SDmytro Laktyushkin /* We did all the math assuming we are scanning same direction as display does, 9416566cae7SDmytro Laktyushkin * however mirror/rotation changes how vp scans vs how it is offset. If scan direction 9426566cae7SDmytro Laktyushkin * is flipped we simply need to calculate offset from the other side of plane. 9436566cae7SDmytro Laktyushkin * Note that outside of viewport all scaling hardware works in recout space. 9449b6067c0SDmytro Laktyushkin */ 9456566cae7SDmytro Laktyushkin if (flip_scan_dir) 9466566cae7SDmytro Laktyushkin *vp_offset = src_size - *vp_offset - *vp_size; 9479b6067c0SDmytro Laktyushkin } 9489b6067c0SDmytro Laktyushkin 9496566cae7SDmytro Laktyushkin static void calculate_inits_and_viewports(struct pipe_ctx *pipe_ctx) 9509b6067c0SDmytro Laktyushkin { 9519b6067c0SDmytro Laktyushkin const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 9529b6067c0SDmytro Laktyushkin const struct dc_stream_state *stream = pipe_ctx->stream; 9536702a9acSHarry Wentland struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 9546566cae7SDmytro Laktyushkin struct rect src = plane_state->src_rect; 95587449a90SAnthony Koo int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 95687449a90SAnthony Koo || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 9576566cae7SDmytro Laktyushkin int split_count, split_idx, ro_lb, ro_tb, recout_full_x, recout_full_y; 9589b6067c0SDmytro Laktyushkin bool orthogonal_rotation, flip_vert_scan_dir, flip_horz_scan_dir; 9596566cae7SDmytro Laktyushkin 9606566cae7SDmytro Laktyushkin calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); 9616566cae7SDmytro Laktyushkin /* 9626566cae7SDmytro Laktyushkin * recout full is what the recout would have been if we didnt clip 9636566cae7SDmytro Laktyushkin * the source plane at all. We only care about left(ro_lb) and top(ro_tb) 9646566cae7SDmytro Laktyushkin * offsets of recout within recout full because those are the directions 9656566cae7SDmytro Laktyushkin * we scan from and therefore the only ones that affect inits. 9666566cae7SDmytro Laktyushkin */ 9676566cae7SDmytro Laktyushkin recout_full_x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x) 9686566cae7SDmytro Laktyushkin * stream->dst.width / stream->src.width; 9696566cae7SDmytro Laktyushkin recout_full_y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y) 9706566cae7SDmytro Laktyushkin * stream->dst.height / stream->src.height; 9716566cae7SDmytro Laktyushkin if (pipe_ctx->prev_odm_pipe && split_idx) 9726566cae7SDmytro Laktyushkin ro_lb = data->h_active * split_idx - recout_full_x; 9736566cae7SDmytro Laktyushkin else 9746566cae7SDmytro Laktyushkin ro_lb = data->recout.x - recout_full_x; 9756566cae7SDmytro Laktyushkin ro_tb = data->recout.y - recout_full_y; 9766566cae7SDmytro Laktyushkin ASSERT(ro_lb >= 0 && ro_tb >= 0); 977b2d0a103SDmytro Laktyushkin 978b0131391SDmytro Laktyushkin /* 9796566cae7SDmytro Laktyushkin * Work in recout rotation since that requires less transformations 980b0131391SDmytro Laktyushkin */ 9819b6067c0SDmytro Laktyushkin get_vp_scan_direction( 9829b6067c0SDmytro Laktyushkin plane_state->rotation, 9839b6067c0SDmytro Laktyushkin plane_state->horizontal_mirror, 9849b6067c0SDmytro Laktyushkin &orthogonal_rotation, 9859b6067c0SDmytro Laktyushkin &flip_vert_scan_dir, 9869b6067c0SDmytro Laktyushkin &flip_horz_scan_dir); 987b0131391SDmytro Laktyushkin 9889b6067c0SDmytro Laktyushkin if (orthogonal_rotation) { 9899b6067c0SDmytro Laktyushkin swap(src.width, src.height); 9906566cae7SDmytro Laktyushkin swap(flip_vert_scan_dir, flip_horz_scan_dir); 9919b5349f7SMartin Tsai } 9921fbd2cfcSDmytro Laktyushkin 9936566cae7SDmytro Laktyushkin calculate_init_and_vp( 9949b6067c0SDmytro Laktyushkin flip_horz_scan_dir, 9956566cae7SDmytro Laktyushkin ro_lb, 9966566cae7SDmytro Laktyushkin data->recout.width, 9976566cae7SDmytro Laktyushkin src.width, 9986566cae7SDmytro Laktyushkin data->taps.h_taps, 9996566cae7SDmytro Laktyushkin data->ratios.horz, 10006566cae7SDmytro Laktyushkin &data->inits.h, 10019b6067c0SDmytro Laktyushkin &data->viewport.x, 10029b6067c0SDmytro Laktyushkin &data->viewport.width); 10036566cae7SDmytro Laktyushkin calculate_init_and_vp( 10049b6067c0SDmytro Laktyushkin flip_horz_scan_dir, 10056566cae7SDmytro Laktyushkin ro_lb, 10066566cae7SDmytro Laktyushkin data->recout.width, 10076566cae7SDmytro Laktyushkin src.width / vpc_div, 10086566cae7SDmytro Laktyushkin data->taps.h_taps_c, 10096566cae7SDmytro Laktyushkin data->ratios.horz_c, 10106566cae7SDmytro Laktyushkin &data->inits.h_c, 10119b6067c0SDmytro Laktyushkin &data->viewport_c.x, 10129b6067c0SDmytro Laktyushkin &data->viewport_c.width); 10136566cae7SDmytro Laktyushkin calculate_init_and_vp( 10149b6067c0SDmytro Laktyushkin flip_vert_scan_dir, 10156566cae7SDmytro Laktyushkin ro_tb, 10166566cae7SDmytro Laktyushkin data->recout.height, 10176566cae7SDmytro Laktyushkin src.height, 10186566cae7SDmytro Laktyushkin data->taps.v_taps, 10196566cae7SDmytro Laktyushkin data->ratios.vert, 10206566cae7SDmytro Laktyushkin &data->inits.v, 10219b6067c0SDmytro Laktyushkin &data->viewport.y, 10229b6067c0SDmytro Laktyushkin &data->viewport.height); 10236566cae7SDmytro Laktyushkin calculate_init_and_vp( 10249b6067c0SDmytro Laktyushkin flip_vert_scan_dir, 10256566cae7SDmytro Laktyushkin ro_tb, 10266566cae7SDmytro Laktyushkin data->recout.height, 10276566cae7SDmytro Laktyushkin src.height / vpc_div, 10286566cae7SDmytro Laktyushkin data->taps.v_taps_c, 10296566cae7SDmytro Laktyushkin data->ratios.vert_c, 10306566cae7SDmytro Laktyushkin &data->inits.v_c, 10319b6067c0SDmytro Laktyushkin &data->viewport_c.y, 10329b6067c0SDmytro Laktyushkin &data->viewport_c.height); 10336566cae7SDmytro Laktyushkin if (orthogonal_rotation) { 10346566cae7SDmytro Laktyushkin swap(data->viewport.x, data->viewport.y); 10356566cae7SDmytro Laktyushkin swap(data->viewport.width, data->viewport.height); 10366566cae7SDmytro Laktyushkin swap(data->viewport_c.x, data->viewport_c.y); 10376566cae7SDmytro Laktyushkin swap(data->viewport_c.width, data->viewport_c.height); 1038b2d0a103SDmytro Laktyushkin } 10396566cae7SDmytro Laktyushkin data->viewport.x += src.x; 10406566cae7SDmytro Laktyushkin data->viewport.y += src.y; 10416566cae7SDmytro Laktyushkin ASSERT(src.x % vpc_div == 0 && src.y % vpc_div == 0); 10426566cae7SDmytro Laktyushkin data->viewport_c.x += src.x / vpc_div; 10436566cae7SDmytro Laktyushkin data->viewport_c.y += src.y / vpc_div; 104489d07b66SSamson Tam } 104589d07b66SSamson Tam 1046b2d0a103SDmytro Laktyushkin bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) 1047b2d0a103SDmytro Laktyushkin { 10483be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 10494fa086b9SLeo (Sunpeng) Li struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 1050b2d0a103SDmytro Laktyushkin bool res = false; 10515d4b05ddSBhawanpreet Lakha DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); 10526566cae7SDmytro Laktyushkin 10536702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface( 10543be5262eSHarry Wentland pipe_ctx->plane_state->format); 10554562236bSHarry Wentland 10566566cae7SDmytro Laktyushkin /* Timing borders are part of vactive that we are also supposed to skip in addition 10576566cae7SDmytro Laktyushkin * to any stream dst offset. Since dm logic assumes dst is in addressable 10584dc8e494SCai Huoqing * space we need to add the left and top borders to dst offsets temporarily. 10596566cae7SDmytro Laktyushkin * TODO: fix in DM, stream dst is supposed to be in vactive 10606566cae7SDmytro Laktyushkin */ 10616566cae7SDmytro Laktyushkin pipe_ctx->stream->dst.x += timing->h_border_left; 10626566cae7SDmytro Laktyushkin pipe_ctx->stream->dst.y += timing->v_border_top; 1063b2d0a103SDmytro Laktyushkin 10646566cae7SDmytro Laktyushkin /* Calculate H and V active size */ 10656566cae7SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable + 10666566cae7SDmytro Laktyushkin timing->h_border_left + timing->h_border_right; 10676566cae7SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + 10686566cae7SDmytro Laktyushkin timing->v_border_top + timing->v_border_bottom; 10696566cae7SDmytro Laktyushkin if (pipe_ctx->next_odm_pipe || pipe_ctx->prev_odm_pipe) 10706566cae7SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.h_active /= get_num_odm_splits(pipe_ctx) + 1; 10714562236bSHarry Wentland 10726566cae7SDmytro Laktyushkin /* depends on h_active */ 10739b6067c0SDmytro Laktyushkin calculate_recout(pipe_ctx); 10746566cae7SDmytro Laktyushkin /* depends on pixel format */ 10756566cae7SDmytro Laktyushkin calculate_scaling_ratios(pipe_ctx); 10766566cae7SDmytro Laktyushkin /* depends on scaling ratios and recout, does not calculate offset yet */ 10776566cae7SDmytro Laktyushkin calculate_viewport_size(pipe_ctx); 10784562236bSHarry Wentland 1079e13c2ea2SJaehyun Chung /* Stopgap for validation of ODM + MPO on one side of screen case */ 1080e13c2ea2SJaehyun Chung if (pipe_ctx->plane_res.scl_data.viewport.height < 1 || 1081e13c2ea2SJaehyun Chung pipe_ctx->plane_res.scl_data.viewport.width < 1) 1082e13c2ea2SJaehyun Chung return false; 1083e13c2ea2SJaehyun Chung 10846566cae7SDmytro Laktyushkin /* 10856566cae7SDmytro Laktyushkin * LB calculations depend on vp size, h/v_active and scaling ratios 10864562236bSHarry Wentland * Setting line buffer pixel depth to 24bpp yields banding 1087a316db72SMario Kleiner * on certain displays, such as the Sharp 4k. 36bpp is needed 1088a316db72SMario Kleiner * to support SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 and 1089a316db72SMario Kleiner * SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616 with actual > 10 bpc 109072a7cf0aSMario Kleiner * precision on at least DCN display engines. However, at least 109172a7cf0aSMario Kleiner * Carrizo with DCE_VERSION_11_0 does not like 36 bpp lb depth, 109272a7cf0aSMario Kleiner * so use only 30 bpp on DCE_VERSION_11_0. Testing with DCE 11.2 and 8.3 109372a7cf0aSMario Kleiner * did not show such problems, so this seems to be the exception. 10944562236bSHarry Wentland */ 1095353ca0faSLiviu Dudau if (plane_state->ctx->dce_version > DCE_VERSION_11_0) 1096a316db72SMario Kleiner pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_36BPP; 109772a7cf0aSMario Kleiner else 109872a7cf0aSMario Kleiner pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; 109972a7cf0aSMario Kleiner 110033eef72fSEric Bernstein pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha; 11014562236bSHarry Wentland 1102d94585a0SYue Hin Lau if (pipe_ctx->plane_res.xfm != NULL) 110386a66c4eSHarry Wentland res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 110486a66c4eSHarry Wentland pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 11054562236bSHarry Wentland 1106d94585a0SYue Hin Lau if (pipe_ctx->plane_res.dpp != NULL) 1107d94585a0SYue Hin Lau res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 1108d94585a0SYue Hin Lau pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 1109f7938bc0SReza Amini 1110f7938bc0SReza Amini 11114562236bSHarry Wentland if (!res) { 11124562236bSHarry Wentland /* Try 24 bpp linebuffer */ 11136702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; 11144562236bSHarry Wentland 11151b6c8067SBhawanpreet Lakha if (pipe_ctx->plane_res.xfm != NULL) 111686a66c4eSHarry Wentland res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 11171b6c8067SBhawanpreet Lakha pipe_ctx->plane_res.xfm, 11181b6c8067SBhawanpreet Lakha &pipe_ctx->plane_res.scl_data, 11191b6c8067SBhawanpreet Lakha &plane_state->scaling_quality); 1120d94585a0SYue Hin Lau 11211b6c8067SBhawanpreet Lakha if (pipe_ctx->plane_res.dpp != NULL) 1122d94585a0SYue Hin Lau res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 11231b6c8067SBhawanpreet Lakha pipe_ctx->plane_res.dpp, 11241b6c8067SBhawanpreet Lakha &pipe_ctx->plane_res.scl_data, 11251b6c8067SBhawanpreet Lakha &plane_state->scaling_quality); 11264562236bSHarry Wentland } 11274562236bSHarry Wentland 11286566cae7SDmytro Laktyushkin /* 11296566cae7SDmytro Laktyushkin * Depends on recout, scaling ratios, h_active and taps 11306566cae7SDmytro Laktyushkin * May need to re-check lb size after this in some obscure scenario 11316566cae7SDmytro Laktyushkin */ 1132b2d0a103SDmytro Laktyushkin if (res) 11336566cae7SDmytro Laktyushkin calculate_inits_and_viewports(pipe_ctx); 11346566cae7SDmytro Laktyushkin 11356566cae7SDmytro Laktyushkin /* 11366566cae7SDmytro Laktyushkin * Handle side by side and top bottom 3d recout offsets after vp calculation 11376566cae7SDmytro Laktyushkin * since 3d is special and needs to calculate vp as if there is no recout offset 11386566cae7SDmytro Laktyushkin * This may break with rotation, good thing we aren't mixing hw rotation and 3d 11396566cae7SDmytro Laktyushkin */ 11406566cae7SDmytro Laktyushkin if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->plane_state == plane_state) { 11416566cae7SDmytro Laktyushkin ASSERT(plane_state->rotation == ROTATION_ANGLE_0 || 11426566cae7SDmytro Laktyushkin (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_TOP_AND_BOTTOM && 11436566cae7SDmytro Laktyushkin pipe_ctx->stream->view_format != VIEW_3D_FORMAT_SIDE_BY_SIDE)); 11446566cae7SDmytro Laktyushkin if (pipe_ctx->stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) 11456566cae7SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.y += pipe_ctx->plane_res.scl_data.recout.height; 11466566cae7SDmytro Laktyushkin else if (pipe_ctx->stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) 11476566cae7SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.x += pipe_ctx->plane_res.scl_data.recout.width; 11486566cae7SDmytro Laktyushkin } 11496566cae7SDmytro Laktyushkin 11506566cae7SDmytro Laktyushkin if (pipe_ctx->plane_res.scl_data.viewport.height < MIN_VIEWPORT_SIZE || 11516566cae7SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE) 11526566cae7SDmytro Laktyushkin res = false; 1153b2d0a103SDmytro Laktyushkin 11543c0dcf9fSDmytro Laktyushkin DC_LOG_SCALER("%s pipe %d:\nViewport: height:%d width:%d x:%d y:%d Recout: height:%d width:%d x:%d y:%d HACTIVE:%d VACTIVE:%d\n" 11553c0dcf9fSDmytro Laktyushkin "src_rect: height:%d width:%d x:%d y:%d dst_rect: height:%d width:%d x:%d y:%d clip_rect: height:%d width:%d x:%d y:%d\n", 11564562236bSHarry Wentland __func__, 11573c0dcf9fSDmytro Laktyushkin pipe_ctx->pipe_idx, 11586702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.height, 11596702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.width, 11606702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.x, 11616702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.y, 11623c0dcf9fSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.height, 11633c0dcf9fSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.width, 11643c0dcf9fSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.x, 11653c0dcf9fSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.y, 11663c0dcf9fSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.h_active, 11673c0dcf9fSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.v_active, 11683c0dcf9fSDmytro Laktyushkin plane_state->src_rect.height, 11693c0dcf9fSDmytro Laktyushkin plane_state->src_rect.width, 11703c0dcf9fSDmytro Laktyushkin plane_state->src_rect.x, 11713c0dcf9fSDmytro Laktyushkin plane_state->src_rect.y, 11723be5262eSHarry Wentland plane_state->dst_rect.height, 11733be5262eSHarry Wentland plane_state->dst_rect.width, 11743be5262eSHarry Wentland plane_state->dst_rect.x, 11753c0dcf9fSDmytro Laktyushkin plane_state->dst_rect.y, 11763c0dcf9fSDmytro Laktyushkin plane_state->clip_rect.height, 11773c0dcf9fSDmytro Laktyushkin plane_state->clip_rect.width, 11783c0dcf9fSDmytro Laktyushkin plane_state->clip_rect.x, 11793c0dcf9fSDmytro Laktyushkin plane_state->clip_rect.y); 11804562236bSHarry Wentland 11816566cae7SDmytro Laktyushkin pipe_ctx->stream->dst.x -= timing->h_border_left; 11826566cae7SDmytro Laktyushkin pipe_ctx->stream->dst.y -= timing->v_border_top; 118389d07b66SSamson Tam 11844562236bSHarry Wentland return res; 11854562236bSHarry Wentland } 11864562236bSHarry Wentland 11874562236bSHarry Wentland 11884562236bSHarry Wentland enum dc_status resource_build_scaling_params_for_context( 1189fb3466a4SBhawanpreet Lakha const struct dc *dc, 1190608ac7bbSJerry Zuo struct dc_state *context) 11914562236bSHarry Wentland { 11924562236bSHarry Wentland int i; 11934562236bSHarry Wentland 11944562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 11953be5262eSHarry Wentland if (context->res_ctx.pipe_ctx[i].plane_state != NULL && 11964562236bSHarry Wentland context->res_ctx.pipe_ctx[i].stream != NULL) 1197b2d0a103SDmytro Laktyushkin if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i])) 1198f84a8161STony Cheng return DC_FAIL_SCALING; 11994562236bSHarry Wentland } 12004562236bSHarry Wentland 12014562236bSHarry Wentland return DC_OK; 12024562236bSHarry Wentland } 12034562236bSHarry Wentland 1204a2b8659dSTony Cheng struct pipe_ctx *find_idle_secondary_pipe( 1205a2b8659dSTony Cheng struct resource_context *res_ctx, 12065581192dSJun Lei const struct resource_pool *pool, 12075581192dSJun Lei const struct pipe_ctx *primary_pipe) 12084562236bSHarry Wentland { 12094562236bSHarry Wentland int i; 12104562236bSHarry Wentland struct pipe_ctx *secondary_pipe = NULL; 12114562236bSHarry Wentland 12124562236bSHarry Wentland /* 12135581192dSJun Lei * We add a preferred pipe mapping to avoid the chance that 12145581192dSJun Lei * MPCCs already in use will need to be reassigned to other trees. 12155581192dSJun Lei * For example, if we went with the strict, assign backwards logic: 12165581192dSJun Lei * 12175581192dSJun Lei * (State 1) 12185581192dSJun Lei * Display A on, no surface, top pipe = 0 12195581192dSJun Lei * Display B on, no surface, top pipe = 1 12205581192dSJun Lei * 12215581192dSJun Lei * (State 2) 12225581192dSJun Lei * Display A on, no surface, top pipe = 0 12235581192dSJun Lei * Display B on, surface enable, top pipe = 1, bottom pipe = 5 12245581192dSJun Lei * 12255581192dSJun Lei * (State 3) 12265581192dSJun Lei * Display A on, surface enable, top pipe = 0, bottom pipe = 5 12275581192dSJun Lei * Display B on, surface enable, top pipe = 1, bottom pipe = 4 12285581192dSJun Lei * 12295581192dSJun Lei * The state 2->3 transition requires remapping MPCC 5 from display B 12305581192dSJun Lei * to display A. 12315581192dSJun Lei * 12325581192dSJun Lei * However, with the preferred pipe logic, state 2 would look like: 12335581192dSJun Lei * 12345581192dSJun Lei * (State 2) 12355581192dSJun Lei * Display A on, no surface, top pipe = 0 12365581192dSJun Lei * Display B on, surface enable, top pipe = 1, bottom pipe = 4 12375581192dSJun Lei * 12385581192dSJun Lei * This would then cause 2->3 to not require remapping any MPCCs. 12395581192dSJun Lei */ 12405581192dSJun Lei if (primary_pipe) { 12415581192dSJun Lei int preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx; 12425581192dSJun Lei if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) { 12435581192dSJun Lei secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx]; 12445581192dSJun Lei secondary_pipe->pipe_idx = preferred_pipe_idx; 12455581192dSJun Lei } 12465581192dSJun Lei } 12475581192dSJun Lei 12485581192dSJun Lei /* 12494562236bSHarry Wentland * search backwards for the second pipe to keep pipe 12504562236bSHarry Wentland * assignment more consistent 12514562236bSHarry Wentland */ 12525581192dSJun Lei if (!secondary_pipe) 1253a2b8659dSTony Cheng for (i = pool->pipe_count - 1; i >= 0; i--) { 12544562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == NULL) { 12554562236bSHarry Wentland secondary_pipe = &res_ctx->pipe_ctx[i]; 12564562236bSHarry Wentland secondary_pipe->pipe_idx = i; 12574562236bSHarry Wentland break; 12584562236bSHarry Wentland } 12594562236bSHarry Wentland } 12604562236bSHarry Wentland 12614562236bSHarry Wentland return secondary_pipe; 12624562236bSHarry Wentland } 12634562236bSHarry Wentland 12644562236bSHarry Wentland struct pipe_ctx *resource_get_head_pipe_for_stream( 12654562236bSHarry Wentland struct resource_context *res_ctx, 12660971c40eSHarry Wentland struct dc_stream_state *stream) 12674562236bSHarry Wentland { 12684562236bSHarry Wentland int i; 126922498036SDmytro Laktyushkin 1270a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 1271b1f6d01cSDmytro Laktyushkin if (res_ctx->pipe_ctx[i].stream == stream 1272b1f6d01cSDmytro Laktyushkin && !res_ctx->pipe_ctx[i].top_pipe 127322498036SDmytro Laktyushkin && !res_ctx->pipe_ctx[i].prev_odm_pipe) 12744562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 12754562236bSHarry Wentland } 12764562236bSHarry Wentland return NULL; 12774562236bSHarry Wentland } 12784562236bSHarry Wentland 1279b1f6d01cSDmytro Laktyushkin static struct pipe_ctx *resource_get_tail_pipe( 128019f89e23SAndrey Grodzovsky struct resource_context *res_ctx, 1281b1f6d01cSDmytro Laktyushkin struct pipe_ctx *head_pipe) 128219f89e23SAndrey Grodzovsky { 1283b1f6d01cSDmytro Laktyushkin struct pipe_ctx *tail_pipe; 128419f89e23SAndrey Grodzovsky 128519f89e23SAndrey Grodzovsky tail_pipe = head_pipe->bottom_pipe; 128619f89e23SAndrey Grodzovsky 128719f89e23SAndrey Grodzovsky while (tail_pipe) { 128819f89e23SAndrey Grodzovsky head_pipe = tail_pipe; 128919f89e23SAndrey Grodzovsky tail_pipe = tail_pipe->bottom_pipe; 129019f89e23SAndrey Grodzovsky } 129119f89e23SAndrey Grodzovsky 129219f89e23SAndrey Grodzovsky return head_pipe; 129319f89e23SAndrey Grodzovsky } 129419f89e23SAndrey Grodzovsky 12954562236bSHarry Wentland /* 1296ab2541b6SAric Cyr * A free_pipe for a stream is defined here as a pipe 1297ab2541b6SAric Cyr * that has no surface attached yet 12984562236bSHarry Wentland */ 1299b1f6d01cSDmytro Laktyushkin static struct pipe_ctx *acquire_free_pipe_for_head( 1300608ac7bbSJerry Zuo struct dc_state *context, 1301a2b8659dSTony Cheng const struct resource_pool *pool, 1302b1f6d01cSDmytro Laktyushkin struct pipe_ctx *head_pipe) 13034562236bSHarry Wentland { 13044562236bSHarry Wentland int i; 1305745cc746SDmytro Laktyushkin struct resource_context *res_ctx = &context->res_ctx; 13064562236bSHarry Wentland 13073be5262eSHarry Wentland if (!head_pipe->plane_state) 13084562236bSHarry Wentland return head_pipe; 13094562236bSHarry Wentland 13104562236bSHarry Wentland /* Re-use pipe already acquired for this stream if available*/ 1311a2b8659dSTony Cheng for (i = pool->pipe_count - 1; i >= 0; i--) { 1312b1f6d01cSDmytro Laktyushkin if (res_ctx->pipe_ctx[i].stream == head_pipe->stream && 13133be5262eSHarry Wentland !res_ctx->pipe_ctx[i].plane_state) { 13144562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 13154562236bSHarry Wentland } 13164562236bSHarry Wentland } 13174562236bSHarry Wentland 13184562236bSHarry Wentland /* 13194562236bSHarry Wentland * At this point we have no re-useable pipe for this stream and we need 13204562236bSHarry Wentland * to acquire an idle one to satisfy the request 13214562236bSHarry Wentland */ 13224562236bSHarry Wentland 1323a2b8659dSTony Cheng if (!pool->funcs->acquire_idle_pipe_for_layer) 13244562236bSHarry Wentland return NULL; 13254562236bSHarry Wentland 1326b1f6d01cSDmytro Laktyushkin return pool->funcs->acquire_idle_pipe_for_layer(context, pool, head_pipe->stream); 13274562236bSHarry Wentland } 13284562236bSHarry Wentland 1329b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 13300f9a536fSDmytro Laktyushkin static int acquire_first_split_pipe( 13310f9a536fSDmytro Laktyushkin struct resource_context *res_ctx, 13320f9a536fSDmytro Laktyushkin const struct resource_pool *pool, 13330971c40eSHarry Wentland struct dc_stream_state *stream) 13340f9a536fSDmytro Laktyushkin { 13350f9a536fSDmytro Laktyushkin int i; 13360f9a536fSDmytro Laktyushkin 13370f9a536fSDmytro Laktyushkin for (i = 0; i < pool->pipe_count; i++) { 133879592db3SDmytro Laktyushkin struct pipe_ctx *split_pipe = &res_ctx->pipe_ctx[i]; 13390f9a536fSDmytro Laktyushkin 1340b1f6d01cSDmytro Laktyushkin if (split_pipe->top_pipe && 134179592db3SDmytro Laktyushkin split_pipe->top_pipe->plane_state == split_pipe->plane_state) { 134279592db3SDmytro Laktyushkin split_pipe->top_pipe->bottom_pipe = split_pipe->bottom_pipe; 134379592db3SDmytro Laktyushkin if (split_pipe->bottom_pipe) 134479592db3SDmytro Laktyushkin split_pipe->bottom_pipe->top_pipe = split_pipe->top_pipe; 13450f9a536fSDmytro Laktyushkin 134679592db3SDmytro Laktyushkin if (split_pipe->top_pipe->plane_state) 134779592db3SDmytro Laktyushkin resource_build_scaling_params(split_pipe->top_pipe); 13480f9a536fSDmytro Laktyushkin 134979592db3SDmytro Laktyushkin memset(split_pipe, 0, sizeof(*split_pipe)); 135079592db3SDmytro Laktyushkin split_pipe->stream_res.tg = pool->timing_generators[i]; 135179592db3SDmytro Laktyushkin split_pipe->plane_res.hubp = pool->hubps[i]; 135279592db3SDmytro Laktyushkin split_pipe->plane_res.ipp = pool->ipps[i]; 135379592db3SDmytro Laktyushkin split_pipe->plane_res.dpp = pool->dpps[i]; 135479592db3SDmytro Laktyushkin split_pipe->stream_res.opp = pool->opps[i]; 135579592db3SDmytro Laktyushkin split_pipe->plane_res.mpcc_inst = pool->dpps[i]->inst; 135679592db3SDmytro Laktyushkin split_pipe->pipe_idx = i; 135779592db3SDmytro Laktyushkin 135879592db3SDmytro Laktyushkin split_pipe->stream = stream; 13590f9a536fSDmytro Laktyushkin return i; 13600f9a536fSDmytro Laktyushkin } 13610f9a536fSDmytro Laktyushkin } 13620f9a536fSDmytro Laktyushkin return -1; 13630f9a536fSDmytro Laktyushkin } 13640f9a536fSDmytro Laktyushkin #endif 13650f9a536fSDmytro Laktyushkin 136619f89e23SAndrey Grodzovsky bool dc_add_plane_to_context( 136719f89e23SAndrey Grodzovsky const struct dc *dc, 13680971c40eSHarry Wentland struct dc_stream_state *stream, 136919f89e23SAndrey Grodzovsky struct dc_plane_state *plane_state, 1370608ac7bbSJerry Zuo struct dc_state *context) 13714562236bSHarry Wentland { 13724562236bSHarry Wentland int i; 137319f89e23SAndrey Grodzovsky struct resource_pool *pool = dc->res_pool; 137419f89e23SAndrey Grodzovsky struct pipe_ctx *head_pipe, *tail_pipe, *free_pipe; 1375ab2541b6SAric Cyr struct dc_stream_status *stream_status = NULL; 13764562236bSHarry Wentland 1377ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) 13784fa086b9SLeo (Sunpeng) Li if (context->streams[i] == stream) { 1379ab2541b6SAric Cyr stream_status = &context->stream_status[i]; 13804562236bSHarry Wentland break; 13814562236bSHarry Wentland } 1382ab2541b6SAric Cyr if (stream_status == NULL) { 138319f89e23SAndrey Grodzovsky dm_error("Existing stream not found; failed to attach surface!\n"); 138419f89e23SAndrey Grodzovsky return false; 138519f89e23SAndrey Grodzovsky } 138619f89e23SAndrey Grodzovsky 138719f89e23SAndrey Grodzovsky 138819f89e23SAndrey Grodzovsky if (stream_status->plane_count == MAX_SURFACE_NUM) { 138919f89e23SAndrey Grodzovsky dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n", 139019f89e23SAndrey Grodzovsky plane_state, MAX_SURFACE_NUM); 139119f89e23SAndrey Grodzovsky return false; 139219f89e23SAndrey Grodzovsky } 139319f89e23SAndrey Grodzovsky 139419f89e23SAndrey Grodzovsky head_pipe = resource_get_head_pipe_for_stream(&context->res_ctx, stream); 139519f89e23SAndrey Grodzovsky 139619f89e23SAndrey Grodzovsky if (!head_pipe) { 139719f89e23SAndrey Grodzovsky dm_error("Head pipe not found for stream_state %p !\n", stream); 13984562236bSHarry Wentland return false; 13994562236bSHarry Wentland } 14004562236bSHarry Wentland 1401b1f6d01cSDmytro Laktyushkin /* retain new surface, but only once per stream */ 1402b1f6d01cSDmytro Laktyushkin dc_plane_state_retain(plane_state); 1403b1f6d01cSDmytro Laktyushkin 1404b1f6d01cSDmytro Laktyushkin while (head_pipe) { 1405b1f6d01cSDmytro Laktyushkin free_pipe = acquire_free_pipe_for_head(context, pool, head_pipe); 14064562236bSHarry Wentland 1407b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 14080f9a536fSDmytro Laktyushkin if (!free_pipe) { 14090f9a536fSDmytro Laktyushkin int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 14100f9a536fSDmytro Laktyushkin if (pipe_idx >= 0) 14110f9a536fSDmytro Laktyushkin free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; 14120f9a536fSDmytro Laktyushkin } 14130f9a536fSDmytro Laktyushkin #endif 1414b1f6d01cSDmytro Laktyushkin if (!free_pipe) { 1415b1f6d01cSDmytro Laktyushkin dc_plane_state_release(plane_state); 14164562236bSHarry Wentland return false; 1417b1f6d01cSDmytro Laktyushkin } 14184562236bSHarry Wentland 14193be5262eSHarry Wentland free_pipe->plane_state = plane_state; 14204562236bSHarry Wentland 142119f89e23SAndrey Grodzovsky if (head_pipe != free_pipe) { 14225b5c1777SJosip Pavic tail_pipe = resource_get_tail_pipe(&context->res_ctx, head_pipe); 14235b5c1777SJosip Pavic ASSERT(tail_pipe); 14246b670fa9SHarry Wentland free_pipe->stream_res.tg = tail_pipe->stream_res.tg; 14259aef1a31SSivapiriyanKumarasamy free_pipe->stream_res.abm = tail_pipe->stream_res.abm; 1426a6a6cb34SHarry Wentland free_pipe->stream_res.opp = tail_pipe->stream_res.opp; 14278e9c4c8cSHarry Wentland free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; 1428afaacef4SHarry Wentland free_pipe->stream_res.audio = tail_pipe->stream_res.audio; 1429cfe4645eSDmytro Laktyushkin free_pipe->clock_source = tail_pipe->clock_source; 14304562236bSHarry Wentland free_pipe->top_pipe = tail_pipe; 14314562236bSHarry Wentland tail_pipe->bottom_pipe = free_pipe; 14322e7b43e6SDmytro Laktyushkin if (!free_pipe->next_odm_pipe && tail_pipe->next_odm_pipe && tail_pipe->next_odm_pipe->bottom_pipe) { 14332e7b43e6SDmytro Laktyushkin free_pipe->next_odm_pipe = tail_pipe->next_odm_pipe->bottom_pipe; 14342e7b43e6SDmytro Laktyushkin tail_pipe->next_odm_pipe->bottom_pipe->prev_odm_pipe = free_pipe; 14352e7b43e6SDmytro Laktyushkin } 14362e7b43e6SDmytro Laktyushkin if (!free_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe->bottom_pipe) { 14372e7b43e6SDmytro Laktyushkin free_pipe->prev_odm_pipe = tail_pipe->prev_odm_pipe->bottom_pipe; 14382e7b43e6SDmytro Laktyushkin tail_pipe->prev_odm_pipe->bottom_pipe->next_odm_pipe = free_pipe; 14392e7b43e6SDmytro Laktyushkin } 14404562236bSHarry Wentland } 1441b1f6d01cSDmytro Laktyushkin head_pipe = head_pipe->next_odm_pipe; 1442b1f6d01cSDmytro Laktyushkin } 14434562236bSHarry Wentland /* assign new surfaces*/ 144419f89e23SAndrey Grodzovsky stream_status->plane_states[stream_status->plane_count] = plane_state; 14454562236bSHarry Wentland 144619f89e23SAndrey Grodzovsky stream_status->plane_count++; 14474562236bSHarry Wentland 14484562236bSHarry Wentland return true; 14494562236bSHarry Wentland } 14504562236bSHarry Wentland 145119f89e23SAndrey Grodzovsky bool dc_remove_plane_from_context( 145219f89e23SAndrey Grodzovsky const struct dc *dc, 145319f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 145419f89e23SAndrey Grodzovsky struct dc_plane_state *plane_state, 1455608ac7bbSJerry Zuo struct dc_state *context) 145619f89e23SAndrey Grodzovsky { 145719f89e23SAndrey Grodzovsky int i; 145819f89e23SAndrey Grodzovsky struct dc_stream_status *stream_status = NULL; 145919f89e23SAndrey Grodzovsky struct resource_pool *pool = dc->res_pool; 146019f89e23SAndrey Grodzovsky 146119f89e23SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 146219f89e23SAndrey Grodzovsky if (context->streams[i] == stream) { 146319f89e23SAndrey Grodzovsky stream_status = &context->stream_status[i]; 146419f89e23SAndrey Grodzovsky break; 146519f89e23SAndrey Grodzovsky } 146619f89e23SAndrey Grodzovsky 146719f89e23SAndrey Grodzovsky if (stream_status == NULL) { 146819f89e23SAndrey Grodzovsky dm_error("Existing stream not found; failed to remove plane.\n"); 146919f89e23SAndrey Grodzovsky return false; 147019f89e23SAndrey Grodzovsky } 147119f89e23SAndrey Grodzovsky 147219f89e23SAndrey Grodzovsky /* release pipe for plane*/ 147319f89e23SAndrey Grodzovsky for (i = pool->pipe_count - 1; i >= 0; i--) { 14746ffaa6fcSDmytro Laktyushkin struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 147519f89e23SAndrey Grodzovsky 14766ffaa6fcSDmytro Laktyushkin if (pipe_ctx->plane_state == plane_state) { 147719f89e23SAndrey Grodzovsky if (pipe_ctx->top_pipe) 147819f89e23SAndrey Grodzovsky pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; 147919f89e23SAndrey Grodzovsky 148019f89e23SAndrey Grodzovsky /* Second condition is to avoid setting NULL to top pipe 148119f89e23SAndrey Grodzovsky * of tail pipe making it look like head pipe in subsequent 148219f89e23SAndrey Grodzovsky * deletes 148319f89e23SAndrey Grodzovsky */ 148419f89e23SAndrey Grodzovsky if (pipe_ctx->bottom_pipe && pipe_ctx->top_pipe) 148519f89e23SAndrey Grodzovsky pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; 148619f89e23SAndrey Grodzovsky 148719f89e23SAndrey Grodzovsky /* 148819f89e23SAndrey Grodzovsky * For head pipe detach surfaces from pipe for tail 148919f89e23SAndrey Grodzovsky * pipe just zero it out 149019f89e23SAndrey Grodzovsky */ 1491b1f6d01cSDmytro Laktyushkin if (!pipe_ctx->top_pipe) 149219f89e23SAndrey Grodzovsky pipe_ctx->plane_state = NULL; 1493b1f6d01cSDmytro Laktyushkin else 149419f89e23SAndrey Grodzovsky memset(pipe_ctx, 0, sizeof(*pipe_ctx)); 149519f89e23SAndrey Grodzovsky } 149619f89e23SAndrey Grodzovsky } 149719f89e23SAndrey Grodzovsky 149819f89e23SAndrey Grodzovsky 149919f89e23SAndrey Grodzovsky for (i = 0; i < stream_status->plane_count; i++) { 150019f89e23SAndrey Grodzovsky if (stream_status->plane_states[i] == plane_state) { 150119f89e23SAndrey Grodzovsky 150219f89e23SAndrey Grodzovsky dc_plane_state_release(stream_status->plane_states[i]); 150319f89e23SAndrey Grodzovsky break; 150419f89e23SAndrey Grodzovsky } 150519f89e23SAndrey Grodzovsky } 150619f89e23SAndrey Grodzovsky 150719f89e23SAndrey Grodzovsky if (i == stream_status->plane_count) { 150819f89e23SAndrey Grodzovsky dm_error("Existing plane_state not found; failed to detach it!\n"); 150919f89e23SAndrey Grodzovsky return false; 151019f89e23SAndrey Grodzovsky } 151119f89e23SAndrey Grodzovsky 151219f89e23SAndrey Grodzovsky stream_status->plane_count--; 151319f89e23SAndrey Grodzovsky 1514abb4986eSAndrew Jiang /* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */ 1515abb4986eSAndrew Jiang for (; i < stream_status->plane_count; i++) 151619f89e23SAndrey Grodzovsky stream_status->plane_states[i] = stream_status->plane_states[i + 1]; 151719f89e23SAndrey Grodzovsky 151819f89e23SAndrey Grodzovsky stream_status->plane_states[stream_status->plane_count] = NULL; 151919f89e23SAndrey Grodzovsky 152019f89e23SAndrey Grodzovsky return true; 152119f89e23SAndrey Grodzovsky } 152219f89e23SAndrey Grodzovsky 152319f89e23SAndrey Grodzovsky bool dc_rem_all_planes_for_stream( 152419f89e23SAndrey Grodzovsky const struct dc *dc, 152519f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 1526608ac7bbSJerry Zuo struct dc_state *context) 152719f89e23SAndrey Grodzovsky { 152819f89e23SAndrey Grodzovsky int i, old_plane_count; 152919f89e23SAndrey Grodzovsky struct dc_stream_status *stream_status = NULL; 153019f89e23SAndrey Grodzovsky struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 }; 153119f89e23SAndrey Grodzovsky 153219f89e23SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 153319f89e23SAndrey Grodzovsky if (context->streams[i] == stream) { 153419f89e23SAndrey Grodzovsky stream_status = &context->stream_status[i]; 153519f89e23SAndrey Grodzovsky break; 153619f89e23SAndrey Grodzovsky } 153719f89e23SAndrey Grodzovsky 153819f89e23SAndrey Grodzovsky if (stream_status == NULL) { 153919f89e23SAndrey Grodzovsky dm_error("Existing stream %p not found!\n", stream); 154019f89e23SAndrey Grodzovsky return false; 154119f89e23SAndrey Grodzovsky } 154219f89e23SAndrey Grodzovsky 154319f89e23SAndrey Grodzovsky old_plane_count = stream_status->plane_count; 154419f89e23SAndrey Grodzovsky 154519f89e23SAndrey Grodzovsky for (i = 0; i < old_plane_count; i++) 154619f89e23SAndrey Grodzovsky del_planes[i] = stream_status->plane_states[i]; 154719f89e23SAndrey Grodzovsky 154819f89e23SAndrey Grodzovsky for (i = 0; i < old_plane_count; i++) 154919f89e23SAndrey Grodzovsky if (!dc_remove_plane_from_context(dc, stream, del_planes[i], context)) 155019f89e23SAndrey Grodzovsky return false; 155119f89e23SAndrey Grodzovsky 155219f89e23SAndrey Grodzovsky return true; 155319f89e23SAndrey Grodzovsky } 155419f89e23SAndrey Grodzovsky 155519f89e23SAndrey Grodzovsky static bool add_all_planes_for_stream( 155619f89e23SAndrey Grodzovsky const struct dc *dc, 155719f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 155819f89e23SAndrey Grodzovsky const struct dc_validation_set set[], 155919f89e23SAndrey Grodzovsky int set_count, 1560608ac7bbSJerry Zuo struct dc_state *context) 156119f89e23SAndrey Grodzovsky { 156219f89e23SAndrey Grodzovsky int i, j; 156319f89e23SAndrey Grodzovsky 156419f89e23SAndrey Grodzovsky for (i = 0; i < set_count; i++) 156519f89e23SAndrey Grodzovsky if (set[i].stream == stream) 156619f89e23SAndrey Grodzovsky break; 156719f89e23SAndrey Grodzovsky 156819f89e23SAndrey Grodzovsky if (i == set_count) { 156919f89e23SAndrey Grodzovsky dm_error("Stream %p not found in set!\n", stream); 157019f89e23SAndrey Grodzovsky return false; 157119f89e23SAndrey Grodzovsky } 157219f89e23SAndrey Grodzovsky 157319f89e23SAndrey Grodzovsky for (j = 0; j < set[i].plane_count; j++) 157419f89e23SAndrey Grodzovsky if (!dc_add_plane_to_context(dc, stream, set[i].plane_states[j], context)) 157519f89e23SAndrey Grodzovsky return false; 157619f89e23SAndrey Grodzovsky 157719f89e23SAndrey Grodzovsky return true; 157819f89e23SAndrey Grodzovsky } 157919f89e23SAndrey Grodzovsky 158019f89e23SAndrey Grodzovsky bool dc_add_all_planes_for_stream( 158119f89e23SAndrey Grodzovsky const struct dc *dc, 158219f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 158319f89e23SAndrey Grodzovsky struct dc_plane_state * const *plane_states, 158419f89e23SAndrey Grodzovsky int plane_count, 1585608ac7bbSJerry Zuo struct dc_state *context) 158619f89e23SAndrey Grodzovsky { 158719f89e23SAndrey Grodzovsky struct dc_validation_set set; 158819f89e23SAndrey Grodzovsky int i; 158919f89e23SAndrey Grodzovsky 159019f89e23SAndrey Grodzovsky set.stream = stream; 159119f89e23SAndrey Grodzovsky set.plane_count = plane_count; 159219f89e23SAndrey Grodzovsky 159319f89e23SAndrey Grodzovsky for (i = 0; i < plane_count; i++) 159419f89e23SAndrey Grodzovsky set.plane_states[i] = plane_states[i]; 159519f89e23SAndrey Grodzovsky 159619f89e23SAndrey Grodzovsky return add_all_planes_for_stream(dc, stream, &set, 1, context); 159719f89e23SAndrey Grodzovsky } 159819f89e23SAndrey Grodzovsky 15990971c40eSHarry Wentland static bool is_timing_changed(struct dc_stream_state *cur_stream, 16000971c40eSHarry Wentland struct dc_stream_state *new_stream) 16014562236bSHarry Wentland { 16024562236bSHarry Wentland if (cur_stream == NULL) 16034562236bSHarry Wentland return true; 16044562236bSHarry Wentland 16054562236bSHarry Wentland /* If output color space is changed, need to reprogram info frames */ 16064fa086b9SLeo (Sunpeng) Li if (cur_stream->output_color_space != new_stream->output_color_space) 16074562236bSHarry Wentland return true; 16084562236bSHarry Wentland 16094562236bSHarry Wentland return memcmp( 16104fa086b9SLeo (Sunpeng) Li &cur_stream->timing, 16114fa086b9SLeo (Sunpeng) Li &new_stream->timing, 16124562236bSHarry Wentland sizeof(struct dc_crtc_timing)) != 0; 16134562236bSHarry Wentland } 16144562236bSHarry Wentland 16154562236bSHarry Wentland static bool are_stream_backends_same( 16160971c40eSHarry Wentland struct dc_stream_state *stream_a, struct dc_stream_state *stream_b) 16174562236bSHarry Wentland { 16184562236bSHarry Wentland if (stream_a == stream_b) 16194562236bSHarry Wentland return true; 16204562236bSHarry Wentland 16214562236bSHarry Wentland if (stream_a == NULL || stream_b == NULL) 16224562236bSHarry Wentland return false; 16234562236bSHarry Wentland 16244562236bSHarry Wentland if (is_timing_changed(stream_a, stream_b)) 16254562236bSHarry Wentland return false; 16264562236bSHarry Wentland 16271e7e86c4SSamson Tam if (stream_a->dpms_off != stream_b->dpms_off) 16281e7e86c4SSamson Tam return false; 16291e7e86c4SSamson Tam 16304562236bSHarry Wentland return true; 16314562236bSHarry Wentland } 16324562236bSHarry Wentland 1633625a15bfSLee Jones /* 16342119aa17SDavid Francis * dc_is_stream_unchanged() - Compare two stream states for equivalence. 16352119aa17SDavid Francis * 16362119aa17SDavid Francis * Checks if there a difference between the two states 16372119aa17SDavid Francis * that would require a mode change. 16382119aa17SDavid Francis * 16392119aa17SDavid Francis * Does not compare cursor position or attributes. 16402119aa17SDavid Francis */ 1641d54d29dbSBhawanpreet Lakha bool dc_is_stream_unchanged( 16420971c40eSHarry Wentland struct dc_stream_state *old_stream, struct dc_stream_state *stream) 16434562236bSHarry Wentland { 16444562236bSHarry Wentland 16454562236bSHarry Wentland if (!are_stream_backends_same(old_stream, stream)) 16464562236bSHarry Wentland return false; 16474562236bSHarry Wentland 16480460f9abSJun Lei if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param) 16490460f9abSJun Lei return false; 16500460f9abSJun Lei 16514562236bSHarry Wentland return true; 16524562236bSHarry Wentland } 16534562236bSHarry Wentland 1654625a15bfSLee Jones /* 16552119aa17SDavid Francis * dc_is_stream_scaling_unchanged() - Compare scaling rectangles of two streams. 16562119aa17SDavid Francis */ 16579a5d9c48SLeo (Sunpeng) Li bool dc_is_stream_scaling_unchanged( 16589a5d9c48SLeo (Sunpeng) Li struct dc_stream_state *old_stream, struct dc_stream_state *stream) 16599a5d9c48SLeo (Sunpeng) Li { 16609a5d9c48SLeo (Sunpeng) Li if (old_stream == stream) 16619a5d9c48SLeo (Sunpeng) Li return true; 16629a5d9c48SLeo (Sunpeng) Li 16639a5d9c48SLeo (Sunpeng) Li if (old_stream == NULL || stream == NULL) 16649a5d9c48SLeo (Sunpeng) Li return false; 16659a5d9c48SLeo (Sunpeng) Li 16669a5d9c48SLeo (Sunpeng) Li if (memcmp(&old_stream->src, 16679a5d9c48SLeo (Sunpeng) Li &stream->src, 16689a5d9c48SLeo (Sunpeng) Li sizeof(struct rect)) != 0) 16699a5d9c48SLeo (Sunpeng) Li return false; 16709a5d9c48SLeo (Sunpeng) Li 16719a5d9c48SLeo (Sunpeng) Li if (memcmp(&old_stream->dst, 16729a5d9c48SLeo (Sunpeng) Li &stream->dst, 16739a5d9c48SLeo (Sunpeng) Li sizeof(struct rect)) != 0) 16749a5d9c48SLeo (Sunpeng) Li return false; 16759a5d9c48SLeo (Sunpeng) Li 16769a5d9c48SLeo (Sunpeng) Li return true; 16779a5d9c48SLeo (Sunpeng) Li } 16789a5d9c48SLeo (Sunpeng) Li 16791dc90497SAndrey Grodzovsky static void update_stream_engine_usage( 16804562236bSHarry Wentland struct resource_context *res_ctx, 1681a2b8659dSTony Cheng const struct resource_pool *pool, 16821dc90497SAndrey Grodzovsky struct stream_encoder *stream_enc, 16831dc90497SAndrey Grodzovsky bool acquired) 16844562236bSHarry Wentland { 16854562236bSHarry Wentland int i; 16864562236bSHarry Wentland 1687a2b8659dSTony Cheng for (i = 0; i < pool->stream_enc_count; i++) { 1688a2b8659dSTony Cheng if (pool->stream_enc[i] == stream_enc) 16891dc90497SAndrey Grodzovsky res_ctx->is_stream_enc_acquired[i] = acquired; 16904562236bSHarry Wentland } 16914562236bSHarry Wentland } 16924562236bSHarry Wentland 1693f01ee019SFangzhi Zuo #if defined(CONFIG_DRM_AMD_DC_DCN) 1694f01ee019SFangzhi Zuo static void update_hpo_dp_stream_engine_usage( 1695f01ee019SFangzhi Zuo struct resource_context *res_ctx, 1696f01ee019SFangzhi Zuo const struct resource_pool *pool, 1697f01ee019SFangzhi Zuo struct hpo_dp_stream_encoder *hpo_dp_stream_enc, 1698f01ee019SFangzhi Zuo bool acquired) 1699f01ee019SFangzhi Zuo { 1700f01ee019SFangzhi Zuo int i; 1701f01ee019SFangzhi Zuo 1702f01ee019SFangzhi Zuo for (i = 0; i < pool->hpo_dp_stream_enc_count; i++) { 1703f01ee019SFangzhi Zuo if (pool->hpo_dp_stream_enc[i] == hpo_dp_stream_enc) 1704f01ee019SFangzhi Zuo res_ctx->is_hpo_dp_stream_enc_acquired[i] = acquired; 1705f01ee019SFangzhi Zuo } 1706f01ee019SFangzhi Zuo } 1707f01ee019SFangzhi Zuo #endif 1708f01ee019SFangzhi Zuo 17094562236bSHarry Wentland /* TODO: release audio object */ 17104176664bSCharlene Liu void update_audio_usage( 17114562236bSHarry Wentland struct resource_context *res_ctx, 1712a2b8659dSTony Cheng const struct resource_pool *pool, 17131dc90497SAndrey Grodzovsky struct audio *audio, 17141dc90497SAndrey Grodzovsky bool acquired) 17154562236bSHarry Wentland { 17164562236bSHarry Wentland int i; 1717a2b8659dSTony Cheng for (i = 0; i < pool->audio_count; i++) { 1718a2b8659dSTony Cheng if (pool->audios[i] == audio) 17191dc90497SAndrey Grodzovsky res_ctx->is_audio_acquired[i] = acquired; 17204562236bSHarry Wentland } 17214562236bSHarry Wentland } 17224562236bSHarry Wentland 17234562236bSHarry Wentland static int acquire_first_free_pipe( 17244562236bSHarry Wentland struct resource_context *res_ctx, 1725a2b8659dSTony Cheng const struct resource_pool *pool, 17260971c40eSHarry Wentland struct dc_stream_state *stream) 17274562236bSHarry Wentland { 17284562236bSHarry Wentland int i; 17294562236bSHarry Wentland 1730a2b8659dSTony Cheng for (i = 0; i < pool->pipe_count; i++) { 17314562236bSHarry Wentland if (!res_ctx->pipe_ctx[i].stream) { 17324562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 17334562236bSHarry Wentland 17346b670fa9SHarry Wentland pipe_ctx->stream_res.tg = pool->timing_generators[i]; 173586a66c4eSHarry Wentland pipe_ctx->plane_res.mi = pool->mis[i]; 17368feabd03SYue Hin Lau pipe_ctx->plane_res.hubp = pool->hubps[i]; 173786a66c4eSHarry Wentland pipe_ctx->plane_res.ipp = pool->ipps[i]; 173886a66c4eSHarry Wentland pipe_ctx->plane_res.xfm = pool->transforms[i]; 1739d94585a0SYue Hin Lau pipe_ctx->plane_res.dpp = pool->dpps[i]; 1740a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp = pool->opps[i]; 1741bc373a89SRoman Li if (pool->dpps[i]) 1742e07f541fSYongqiang Sun pipe_ctx->plane_res.mpcc_inst = pool->dpps[i]->inst; 17434562236bSHarry Wentland pipe_ctx->pipe_idx = i; 17444562236bSHarry Wentland 1745ff5ef992SAlex Deucher 17464562236bSHarry Wentland pipe_ctx->stream = stream; 17474562236bSHarry Wentland return i; 17484562236bSHarry Wentland } 17494562236bSHarry Wentland } 17504562236bSHarry Wentland return -1; 17514562236bSHarry Wentland } 17524562236bSHarry Wentland 1753f01ee019SFangzhi Zuo #if defined(CONFIG_DRM_AMD_DC_DCN) 1754f01ee019SFangzhi Zuo static struct hpo_dp_stream_encoder *find_first_free_match_hpo_dp_stream_enc_for_link( 1755f01ee019SFangzhi Zuo struct resource_context *res_ctx, 1756f01ee019SFangzhi Zuo const struct resource_pool *pool, 1757f01ee019SFangzhi Zuo struct dc_stream_state *stream) 1758f01ee019SFangzhi Zuo { 1759f01ee019SFangzhi Zuo int i; 1760f01ee019SFangzhi Zuo 1761f01ee019SFangzhi Zuo for (i = 0; i < pool->hpo_dp_stream_enc_count; i++) { 1762f01ee019SFangzhi Zuo if (!res_ctx->is_hpo_dp_stream_enc_acquired[i] && 1763f01ee019SFangzhi Zuo pool->hpo_dp_stream_enc[i]) { 1764f01ee019SFangzhi Zuo 1765f01ee019SFangzhi Zuo return pool->hpo_dp_stream_enc[i]; 1766f01ee019SFangzhi Zuo } 1767f01ee019SFangzhi Zuo } 1768f01ee019SFangzhi Zuo 1769f01ee019SFangzhi Zuo return NULL; 1770f01ee019SFangzhi Zuo } 1771f01ee019SFangzhi Zuo #endif 1772f01ee019SFangzhi Zuo 1773a2b8659dSTony Cheng static struct audio *find_first_free_audio( 1774a2b8659dSTony Cheng struct resource_context *res_ctx, 1775cfb071f7SCharlene Liu const struct resource_pool *pool, 1776f24b0522SPaul Hsieh enum engine_id id, 1777f24b0522SPaul Hsieh enum dce_version dc_version) 17784562236bSHarry Wentland { 1779b5a41620SCharlene Liu int i, available_audio_count; 1780b5a41620SCharlene Liu 1781b5a41620SCharlene Liu available_audio_count = pool->audio_count; 1782b5a41620SCharlene Liu 1783b5a41620SCharlene Liu for (i = 0; i < available_audio_count; i++) { 17844176664bSCharlene Liu if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) { 1785cfb071f7SCharlene Liu /*we have enough audio endpoint, find the matching inst*/ 1786cfb071f7SCharlene Liu if (id != i) 1787cfb071f7SCharlene Liu continue; 1788a2b8659dSTony Cheng return pool->audios[i]; 17894562236bSHarry Wentland } 17904562236bSHarry Wentland } 17915feb9f07STai Man 17925feb9f07STai Man /* use engine id to find free audio */ 1793b5a41620SCharlene Liu if ((id < available_audio_count) && (res_ctx->is_audio_acquired[id] == false)) { 17945feb9f07STai Man return pool->audios[id]; 17955feb9f07STai Man } 179666bfd4fdSCharlene Liu /*not found the matching one, first come first serve*/ 1797b5a41620SCharlene Liu for (i = 0; i < available_audio_count; i++) { 17984176664bSCharlene Liu if (res_ctx->is_audio_acquired[i] == false) { 17994176664bSCharlene Liu return pool->audios[i]; 18004176664bSCharlene Liu } 18014176664bSCharlene Liu } 18024562236bSHarry Wentland return 0; 18034562236bSHarry Wentland } 18044562236bSHarry Wentland 1805625a15bfSLee Jones /* 18062119aa17SDavid Francis * dc_add_stream_to_ctx() - Add a new dc_stream_state to a dc_state. 18072119aa17SDavid Francis */ 180813ab1b44SYongqiang Sun enum dc_status dc_add_stream_to_ctx( 18091dc90497SAndrey Grodzovsky struct dc *dc, 1810608ac7bbSJerry Zuo struct dc_state *new_ctx, 18111dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 18121dc90497SAndrey Grodzovsky { 18131dc90497SAndrey Grodzovsky enum dc_status res; 1814eb9714a2SWenjing Liu DC_LOGGER_INIT(dc->ctx->logger); 18151dc90497SAndrey Grodzovsky 1816ece4147fSKen Chalmers if (new_ctx->stream_count >= dc->res_pool->timing_generator_count) { 1817eb9714a2SWenjing Liu DC_LOG_WARNING("Max streams reached, can't add stream %p !\n", stream); 18181dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 18191dc90497SAndrey Grodzovsky } 18201dc90497SAndrey Grodzovsky 18211dc90497SAndrey Grodzovsky new_ctx->streams[new_ctx->stream_count] = stream; 18221dc90497SAndrey Grodzovsky dc_stream_retain(stream); 18231dc90497SAndrey Grodzovsky new_ctx->stream_count++; 18241dc90497SAndrey Grodzovsky 18251dc90497SAndrey Grodzovsky res = dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream); 18261dc90497SAndrey Grodzovsky if (res != DC_OK) 1827eb9714a2SWenjing Liu DC_LOG_WARNING("Adding stream %p to context failed with err %d!\n", stream, res); 18281dc90497SAndrey Grodzovsky 182913ab1b44SYongqiang Sun return res; 18301dc90497SAndrey Grodzovsky } 18311dc90497SAndrey Grodzovsky 1832625a15bfSLee Jones /* 18332119aa17SDavid Francis * dc_remove_stream_from_ctx() - Remove a stream from a dc_state. 18342119aa17SDavid Francis */ 183562c933f9SYongqiang Sun enum dc_status dc_remove_stream_from_ctx( 18361dc90497SAndrey Grodzovsky struct dc *dc, 1837608ac7bbSJerry Zuo struct dc_state *new_ctx, 18381dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 18391dc90497SAndrey Grodzovsky { 184019f89e23SAndrey Grodzovsky int i; 18411dc90497SAndrey Grodzovsky struct dc_context *dc_ctx = dc->ctx; 184222498036SDmytro Laktyushkin struct pipe_ctx *del_pipe = resource_get_head_pipe_for_stream(&new_ctx->res_ctx, stream); 184322498036SDmytro Laktyushkin struct pipe_ctx *odm_pipe; 184422498036SDmytro Laktyushkin 184522498036SDmytro Laktyushkin if (!del_pipe) { 184622498036SDmytro Laktyushkin DC_ERROR("Pipe not found for stream %p !\n", stream); 184722498036SDmytro Laktyushkin return DC_ERROR_UNEXPECTED; 184822498036SDmytro Laktyushkin } 184922498036SDmytro Laktyushkin 185022498036SDmytro Laktyushkin odm_pipe = del_pipe->next_odm_pipe; 18511dc90497SAndrey Grodzovsky 185219f89e23SAndrey Grodzovsky /* Release primary pipe */ 185319f89e23SAndrey Grodzovsky ASSERT(del_pipe->stream_res.stream_enc); 18541dc90497SAndrey Grodzovsky update_stream_engine_usage( 18551dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 18561dc90497SAndrey Grodzovsky dc->res_pool, 18571dc90497SAndrey Grodzovsky del_pipe->stream_res.stream_enc, 18581dc90497SAndrey Grodzovsky false); 1859f42ef862SJimmy Kizito /* Release link encoder from stream in new dc_state. */ 1860f42ef862SJimmy Kizito if (dc->res_pool->funcs->link_enc_unassign) 1861f42ef862SJimmy Kizito dc->res_pool->funcs->link_enc_unassign(new_ctx, del_pipe->stream); 18621dc90497SAndrey Grodzovsky 1863f01ee019SFangzhi Zuo #if defined(CONFIG_DRM_AMD_DC_DCN) 1864f01ee019SFangzhi Zuo if (is_dp_128b_132b_signal(del_pipe)) { 1865f01ee019SFangzhi Zuo update_hpo_dp_stream_engine_usage( 1866f01ee019SFangzhi Zuo &new_ctx->res_ctx, dc->res_pool, 1867f01ee019SFangzhi Zuo del_pipe->stream_res.hpo_dp_stream_enc, 1868f01ee019SFangzhi Zuo false); 1869f01ee019SFangzhi Zuo } 1870f01ee019SFangzhi Zuo #endif 1871f01ee019SFangzhi Zuo 18721dc90497SAndrey Grodzovsky if (del_pipe->stream_res.audio) 18731dc90497SAndrey Grodzovsky update_audio_usage( 18741dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 18751dc90497SAndrey Grodzovsky dc->res_pool, 18761dc90497SAndrey Grodzovsky del_pipe->stream_res.audio, 18771dc90497SAndrey Grodzovsky false); 18781dc90497SAndrey Grodzovsky 18799d0dcecdSHarry Wentland resource_unreference_clock_source(&new_ctx->res_ctx, 18809d0dcecdSHarry Wentland dc->res_pool, 18819d0dcecdSHarry Wentland del_pipe->clock_source); 18829d0dcecdSHarry Wentland 1883e56ae556SNikola Cornij if (dc->res_pool->funcs->remove_stream_from_ctx) 1884e56ae556SNikola Cornij dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream); 1885e56ae556SNikola Cornij 188622498036SDmytro Laktyushkin while (odm_pipe) { 188722498036SDmytro Laktyushkin struct pipe_ctx *next_odm_pipe = odm_pipe->next_odm_pipe; 188822498036SDmytro Laktyushkin 188922498036SDmytro Laktyushkin memset(odm_pipe, 0, sizeof(*odm_pipe)); 189022498036SDmytro Laktyushkin odm_pipe = next_odm_pipe; 189122498036SDmytro Laktyushkin } 18921dc90497SAndrey Grodzovsky memset(del_pipe, 0, sizeof(*del_pipe)); 18936ffaa6fcSDmytro Laktyushkin 18941dc90497SAndrey Grodzovsky for (i = 0; i < new_ctx->stream_count; i++) 18951dc90497SAndrey Grodzovsky if (new_ctx->streams[i] == stream) 18961dc90497SAndrey Grodzovsky break; 18971dc90497SAndrey Grodzovsky 18981dc90497SAndrey Grodzovsky if (new_ctx->streams[i] != stream) { 18991dc90497SAndrey Grodzovsky DC_ERROR("Context doesn't have stream %p !\n", stream); 19001dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 19011dc90497SAndrey Grodzovsky } 19021dc90497SAndrey Grodzovsky 19031dc90497SAndrey Grodzovsky dc_stream_release(new_ctx->streams[i]); 19041dc90497SAndrey Grodzovsky new_ctx->stream_count--; 19051dc90497SAndrey Grodzovsky 19061dc90497SAndrey Grodzovsky /* Trim back arrays */ 19071dc90497SAndrey Grodzovsky for (; i < new_ctx->stream_count; i++) { 19081dc90497SAndrey Grodzovsky new_ctx->streams[i] = new_ctx->streams[i + 1]; 19091dc90497SAndrey Grodzovsky new_ctx->stream_status[i] = new_ctx->stream_status[i + 1]; 19101dc90497SAndrey Grodzovsky } 19111dc90497SAndrey Grodzovsky 19121dc90497SAndrey Grodzovsky new_ctx->streams[new_ctx->stream_count] = NULL; 19131dc90497SAndrey Grodzovsky memset( 19141dc90497SAndrey Grodzovsky &new_ctx->stream_status[new_ctx->stream_count], 19151dc90497SAndrey Grodzovsky 0, 19161dc90497SAndrey Grodzovsky sizeof(new_ctx->stream_status[0])); 19171dc90497SAndrey Grodzovsky 19181dc90497SAndrey Grodzovsky return DC_OK; 19191dc90497SAndrey Grodzovsky } 19201dc90497SAndrey Grodzovsky 19210971c40eSHarry Wentland static struct dc_stream_state *find_pll_sharable_stream( 19220971c40eSHarry Wentland struct dc_stream_state *stream_needs_pll, 1923608ac7bbSJerry Zuo struct dc_state *context) 19244562236bSHarry Wentland { 1925ab2541b6SAric Cyr int i; 19264562236bSHarry Wentland 1927ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 19280971c40eSHarry Wentland struct dc_stream_state *stream_has_pll = context->streams[i]; 19294562236bSHarry Wentland 19304562236bSHarry Wentland /* We are looking for non dp, non virtual stream */ 19314562236bSHarry Wentland if (resource_are_streams_timing_synchronizable( 19324562236bSHarry Wentland stream_needs_pll, stream_has_pll) 19334562236bSHarry Wentland && !dc_is_dp_signal(stream_has_pll->signal) 1934ceb3dbb4SJun Lei && stream_has_pll->link->connector_signal 19354562236bSHarry Wentland != SIGNAL_TYPE_VIRTUAL) 19364562236bSHarry Wentland return stream_has_pll; 1937ab2541b6SAric Cyr 19384562236bSHarry Wentland } 19394562236bSHarry Wentland 19404562236bSHarry Wentland return NULL; 19414562236bSHarry Wentland } 19424562236bSHarry Wentland 19434562236bSHarry Wentland static int get_norm_pix_clk(const struct dc_crtc_timing *timing) 19444562236bSHarry Wentland { 1945380604e2SKen Chalmers uint32_t pix_clk = timing->pix_clk_100hz; 19464562236bSHarry Wentland uint32_t normalized_pix_clk = pix_clk; 19474562236bSHarry Wentland 19484562236bSHarry Wentland if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) 19494562236bSHarry Wentland pix_clk /= 2; 1950cc4d99b8SCharlene Liu if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) { 19514562236bSHarry Wentland switch (timing->display_color_depth) { 19528897810aSJulian Parkin case COLOR_DEPTH_666: 19534562236bSHarry Wentland case COLOR_DEPTH_888: 19544562236bSHarry Wentland normalized_pix_clk = pix_clk; 19554562236bSHarry Wentland break; 19564562236bSHarry Wentland case COLOR_DEPTH_101010: 19574562236bSHarry Wentland normalized_pix_clk = (pix_clk * 30) / 24; 19584562236bSHarry Wentland break; 19594562236bSHarry Wentland case COLOR_DEPTH_121212: 19604562236bSHarry Wentland normalized_pix_clk = (pix_clk * 36) / 24; 19614562236bSHarry Wentland break; 19624562236bSHarry Wentland case COLOR_DEPTH_161616: 19634562236bSHarry Wentland normalized_pix_clk = (pix_clk * 48) / 24; 19644562236bSHarry Wentland break; 19654562236bSHarry Wentland default: 19664562236bSHarry Wentland ASSERT(0); 19674562236bSHarry Wentland break; 19684562236bSHarry Wentland } 1969cc4d99b8SCharlene Liu } 19704562236bSHarry Wentland return normalized_pix_clk; 19714562236bSHarry Wentland } 19724562236bSHarry Wentland 19730971c40eSHarry Wentland static void calculate_phy_pix_clks(struct dc_stream_state *stream) 19744562236bSHarry Wentland { 19754562236bSHarry Wentland /* update actual pixel clock on all streams */ 19764562236bSHarry Wentland if (dc_is_hdmi_signal(stream->signal)) 19774562236bSHarry Wentland stream->phy_pix_clk = get_norm_pix_clk( 1978380604e2SKen Chalmers &stream->timing) / 10; 19794562236bSHarry Wentland else 19804562236bSHarry Wentland stream->phy_pix_clk = 1981380604e2SKen Chalmers stream->timing.pix_clk_100hz / 10; 198239c03e00SCharlene Liu 198339c03e00SCharlene Liu if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) 198439c03e00SCharlene Liu stream->phy_pix_clk *= 2; 19854562236bSHarry Wentland } 19864562236bSHarry Wentland 1987d2d7885fSAnthony Koo static int acquire_resource_from_hw_enabled_state( 1988d2d7885fSAnthony Koo struct resource_context *res_ctx, 1989d2d7885fSAnthony Koo const struct resource_pool *pool, 1990d2d7885fSAnthony Koo struct dc_stream_state *stream) 1991d2d7885fSAnthony Koo { 1992d2d7885fSAnthony Koo struct dc_link *link = stream->link; 199308b66279SMartin Leung unsigned int i, inst, tg_inst = 0; 1994d2d7885fSAnthony Koo 1995d2d7885fSAnthony Koo /* Check for enabled DIG to identify enabled display */ 1996d2d7885fSAnthony Koo if (!link->link_enc->funcs->is_dig_enabled(link->link_enc)) 1997d2d7885fSAnthony Koo return -1; 1998d2d7885fSAnthony Koo 19995ec43edaSMartin Leung inst = link->link_enc->funcs->get_dig_frontend(link->link_enc); 2000d2d7885fSAnthony Koo 20017f7652eeSMartin Leung if (inst == ENGINE_ID_UNKNOWN) 200275441d9dSMikita Lipski return -1; 2003d2d7885fSAnthony Koo 20047f7652eeSMartin Leung for (i = 0; i < pool->stream_enc_count; i++) { 20057f7652eeSMartin Leung if (pool->stream_enc[i]->id == inst) { 20067f7652eeSMartin Leung tg_inst = pool->stream_enc[i]->funcs->dig_source_otg( 20077f7652eeSMartin Leung pool->stream_enc[i]); 20087f7652eeSMartin Leung break; 20097f7652eeSMartin Leung } 20107f7652eeSMartin Leung } 2011d2d7885fSAnthony Koo 20127f7652eeSMartin Leung // tg_inst not found 20137f7652eeSMartin Leung if (i == pool->stream_enc_count) 201475441d9dSMikita Lipski return -1; 20155ec43edaSMartin Leung 20165ec43edaSMartin Leung if (tg_inst >= pool->timing_generator_count) 201775441d9dSMikita Lipski return -1; 20185ec43edaSMartin Leung 20195ec43edaSMartin Leung if (!res_ctx->pipe_ctx[tg_inst].stream) { 20205ec43edaSMartin Leung struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[tg_inst]; 20215ec43edaSMartin Leung 20225ec43edaSMartin Leung pipe_ctx->stream_res.tg = pool->timing_generators[tg_inst]; 20235ec43edaSMartin Leung pipe_ctx->plane_res.mi = pool->mis[tg_inst]; 20245ec43edaSMartin Leung pipe_ctx->plane_res.hubp = pool->hubps[tg_inst]; 20255ec43edaSMartin Leung pipe_ctx->plane_res.ipp = pool->ipps[tg_inst]; 20265ec43edaSMartin Leung pipe_ctx->plane_res.xfm = pool->transforms[tg_inst]; 20275ec43edaSMartin Leung pipe_ctx->plane_res.dpp = pool->dpps[tg_inst]; 20285ec43edaSMartin Leung pipe_ctx->stream_res.opp = pool->opps[tg_inst]; 20295ec43edaSMartin Leung 2030ccce745cSMartin Leung if (pool->dpps[tg_inst]) { 20315ec43edaSMartin Leung pipe_ctx->plane_res.mpcc_inst = pool->dpps[tg_inst]->inst; 2032ccce745cSMartin Leung 2033ccce745cSMartin Leung // Read DPP->MPCC->OPP Pipe from HW State 2034ccce745cSMartin Leung if (pool->mpc->funcs->read_mpcc_state) { 2035ccce745cSMartin Leung struct mpcc_state s = {0}; 2036ccce745cSMartin Leung 2037ccce745cSMartin Leung pool->mpc->funcs->read_mpcc_state(pool->mpc, pipe_ctx->plane_res.mpcc_inst, &s); 2038ccce745cSMartin Leung 2039ccce745cSMartin Leung if (s.dpp_id < MAX_MPCC) 2040ccce745cSMartin Leung pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].dpp_id = s.dpp_id; 2041ccce745cSMartin Leung 2042ccce745cSMartin Leung if (s.bot_mpcc_id < MAX_MPCC) 2043ccce745cSMartin Leung pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].mpcc_bot = 2044ccce745cSMartin Leung &pool->mpc->mpcc_array[s.bot_mpcc_id]; 2045ccce745cSMartin Leung 2046ccce745cSMartin Leung if (s.opp_id < MAX_OPP) 2047ccce745cSMartin Leung pipe_ctx->stream_res.opp->mpc_tree_params.opp_id = s.opp_id; 2048ccce745cSMartin Leung } 2049ccce745cSMartin Leung } 20505ec43edaSMartin Leung pipe_ctx->pipe_idx = tg_inst; 2051d2d7885fSAnthony Koo 2052d2d7885fSAnthony Koo pipe_ctx->stream = stream; 20535ec43edaSMartin Leung return tg_inst; 2054d2d7885fSAnthony Koo } 2055d2d7885fSAnthony Koo 2056d2d7885fSAnthony Koo return -1; 2057d2d7885fSAnthony Koo } 2058d2d7885fSAnthony Koo 205996b5e3e1SRaymond Yang static void mark_seamless_boot_stream( 206096b5e3e1SRaymond Yang const struct dc *dc, 206196b5e3e1SRaymond Yang struct dc_stream_state *stream) 206296b5e3e1SRaymond Yang { 206396b5e3e1SRaymond Yang struct dc_bios *dcb = dc->ctx->dc_bios; 206496b5e3e1SRaymond Yang 206596b5e3e1SRaymond Yang /* TODO: Check Linux */ 206696b5e3e1SRaymond Yang if (dc->config.allow_seamless_boot_optimization && 206796b5e3e1SRaymond Yang !dcb->funcs->is_accelerated_mode(dcb)) { 206896b5e3e1SRaymond Yang if (dc_validate_seamless_boot_timing(dc, stream->sink, &stream->timing)) 206996b5e3e1SRaymond Yang stream->apply_seamless_boot_optimization = true; 207096b5e3e1SRaymond Yang } 207196b5e3e1SRaymond Yang } 207296b5e3e1SRaymond Yang 20734562236bSHarry Wentland enum dc_status resource_map_pool_resources( 2074fb3466a4SBhawanpreet Lakha const struct dc *dc, 2075608ac7bbSJerry Zuo struct dc_state *context, 20761dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 20774562236bSHarry Wentland { 2078a2b8659dSTony Cheng const struct resource_pool *pool = dc->res_pool; 20791dc90497SAndrey Grodzovsky int i; 20801dc90497SAndrey Grodzovsky struct dc_context *dc_ctx = dc->ctx; 20811dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = NULL; 20821dc90497SAndrey Grodzovsky int pipe_idx = -1; 20834562236bSHarry Wentland 208408e1c28dSYogesh Mohan Marimuthu calculate_phy_pix_clks(stream); 208508e1c28dSYogesh Mohan Marimuthu 208696b5e3e1SRaymond Yang mark_seamless_boot_stream(dc, stream); 208746570f09SAnthony Koo 208896b5e3e1SRaymond Yang if (stream->apply_seamless_boot_optimization) { 2089d2d7885fSAnthony Koo pipe_idx = acquire_resource_from_hw_enabled_state( 2090d2d7885fSAnthony Koo &context->res_ctx, 2091d2d7885fSAnthony Koo pool, 2092d2d7885fSAnthony Koo stream); 209396b5e3e1SRaymond Yang if (pipe_idx < 0) 209496b5e3e1SRaymond Yang /* hw resource was assigned to other stream */ 209596b5e3e1SRaymond Yang stream->apply_seamless_boot_optimization = false; 209696b5e3e1SRaymond Yang } 2097d2d7885fSAnthony Koo 2098d2d7885fSAnthony Koo if (pipe_idx < 0) 20994562236bSHarry Wentland /* acquire new resources */ 21005d11e9fcSDmytro Laktyushkin pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); 21011dc90497SAndrey Grodzovsky 2102b86a1aa3SBhawanpreet Lakha #ifdef CONFIG_DRM_AMD_DC_DCN 21035d11e9fcSDmytro Laktyushkin if (pipe_idx < 0) 210413ab1b44SYongqiang Sun pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 210594c6d735SHarry Wentland #endif 210613ab1b44SYongqiang Sun 2107c5b38aecSDmytro Laktyushkin if (pipe_idx < 0 || context->res_ctx.pipe_ctx[pipe_idx].stream_res.tg == NULL) 21084562236bSHarry Wentland return DC_NO_CONTROLLER_RESOURCE; 21094562236bSHarry Wentland 21104562236bSHarry Wentland pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; 21114562236bSHarry Wentland 21128e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc = 211378cc70b1SWesley Chalmers dc->res_pool->funcs->find_first_free_match_stream_enc_for_link( 2114a2b8659dSTony Cheng &context->res_ctx, pool, stream); 21154562236bSHarry Wentland 21168e9c4c8cSHarry Wentland if (!pipe_ctx->stream_res.stream_enc) 211738684e46SEric Bernstein return DC_NO_STREAM_ENC_RESOURCE; 21184562236bSHarry Wentland 21191dc90497SAndrey Grodzovsky update_stream_engine_usage( 2120a2b8659dSTony Cheng &context->res_ctx, pool, 21211dc90497SAndrey Grodzovsky pipe_ctx->stream_res.stream_enc, 21221dc90497SAndrey Grodzovsky true); 21234562236bSHarry Wentland 2124f01ee019SFangzhi Zuo #if defined(CONFIG_DRM_AMD_DC_DCN) 2125f01ee019SFangzhi Zuo /* Allocate DP HPO Stream Encoder based on signal, hw capabilities 2126f01ee019SFangzhi Zuo * and link settings 2127f01ee019SFangzhi Zuo */ 2128f01ee019SFangzhi Zuo if (dc_is_dp_signal(stream->signal) && 2129f01ee019SFangzhi Zuo dc->caps.dp_hpo) { 2130f01ee019SFangzhi Zuo struct dc_link_settings link_settings = {0}; 2131f01ee019SFangzhi Zuo 2132f01ee019SFangzhi Zuo decide_link_settings(stream, &link_settings); 2133f01ee019SFangzhi Zuo if (dp_get_link_encoding_format(&link_settings) == DP_128b_132b_ENCODING) { 2134f01ee019SFangzhi Zuo pipe_ctx->stream_res.hpo_dp_stream_enc = 2135f01ee019SFangzhi Zuo find_first_free_match_hpo_dp_stream_enc_for_link( 2136f01ee019SFangzhi Zuo &context->res_ctx, pool, stream); 2137f01ee019SFangzhi Zuo 2138f01ee019SFangzhi Zuo if (!pipe_ctx->stream_res.hpo_dp_stream_enc) 2139f01ee019SFangzhi Zuo return DC_NO_STREAM_ENC_RESOURCE; 2140f01ee019SFangzhi Zuo 2141f01ee019SFangzhi Zuo update_hpo_dp_stream_engine_usage( 2142f01ee019SFangzhi Zuo &context->res_ctx, pool, 2143f01ee019SFangzhi Zuo pipe_ctx->stream_res.hpo_dp_stream_enc, 2144f01ee019SFangzhi Zuo true); 2145f01ee019SFangzhi Zuo } 2146f01ee019SFangzhi Zuo } 2147f01ee019SFangzhi Zuo #endif 2148f01ee019SFangzhi Zuo 21494562236bSHarry Wentland /* TODO: Add check if ASIC support and EDID audio */ 2150ceb3dbb4SJun Lei if (!stream->converter_disable_audio && 21514562236bSHarry Wentland dc_is_audio_capable_signal(pipe_ctx->stream->signal) && 2152ce08aad3SAlvin Lee stream->audio_info.mode_count && stream->audio_info.flags.all) { 2153afaacef4SHarry Wentland pipe_ctx->stream_res.audio = find_first_free_audio( 2154f24b0522SPaul Hsieh &context->res_ctx, pool, pipe_ctx->stream_res.stream_enc->id, dc_ctx->dce_version); 21554562236bSHarry Wentland 21564562236bSHarry Wentland /* 21574562236bSHarry Wentland * Audio assigned in order first come first get. 21584562236bSHarry Wentland * There are asics which has number of audio 21594562236bSHarry Wentland * resources less then number of pipes 21604562236bSHarry Wentland */ 2161afaacef4SHarry Wentland if (pipe_ctx->stream_res.audio) 21621dc90497SAndrey Grodzovsky update_audio_usage(&context->res_ctx, pool, 21631dc90497SAndrey Grodzovsky pipe_ctx->stream_res.audio, true); 21644562236bSHarry Wentland } 21654562236bSHarry Wentland 21669aef1a31SSivapiriyanKumarasamy /* Add ABM to the resource if on EDP */ 21675dba4991SBhawanpreet Lakha if (pipe_ctx->stream && dc_is_embedded_signal(pipe_ctx->stream->signal)) { 216820f2ffe5SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN) 21695dba4991SBhawanpreet Lakha if (pool->abm) 21709aef1a31SSivapiriyanKumarasamy pipe_ctx->stream_res.abm = pool->abm; 21715dba4991SBhawanpreet Lakha else 21725dba4991SBhawanpreet Lakha pipe_ctx->stream_res.abm = pool->multiple_abms[pipe_ctx->stream_res.tg->inst]; 21735dba4991SBhawanpreet Lakha #else 21745dba4991SBhawanpreet Lakha pipe_ctx->stream_res.abm = pool->abm; 21755dba4991SBhawanpreet Lakha #endif 21765dba4991SBhawanpreet Lakha } 21779aef1a31SSivapiriyanKumarasamy 21781dc90497SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 21791dc90497SAndrey Grodzovsky if (context->streams[i] == stream) { 21806b670fa9SHarry Wentland context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; 21813f0940f8SCharlene Liu context->stream_status[i].stream_enc_inst = pipe_ctx->stream_res.stream_enc->stream_enc_inst; 21825fdb7c4cSNicholas Kazlauskas context->stream_status[i].audio_inst = 21835fdb7c4cSNicholas Kazlauskas pipe_ctx->stream_res.audio ? pipe_ctx->stream_res.audio->inst : -1; 21845fdb7c4cSNicholas Kazlauskas 21851dc90497SAndrey Grodzovsky return DC_OK; 21864562236bSHarry Wentland } 21874562236bSHarry Wentland 21881dc90497SAndrey Grodzovsky DC_ERROR("Stream %p not found in new ctx!\n", stream); 21891dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 21904562236bSHarry Wentland } 21914562236bSHarry Wentland 21922119aa17SDavid Francis /** 21932119aa17SDavid Francis * dc_resource_state_copy_construct_current() - Creates a new dc_state from existing state 21942119aa17SDavid Francis * Is a shallow copy. Increments refcounts on existing streams and planes. 21952119aa17SDavid Francis * @dc: copy out of dc->current_state 21962119aa17SDavid Francis * @dst_ctx: copy into this 21972119aa17SDavid Francis */ 2198f36cc577SBhawanpreet Lakha void dc_resource_state_copy_construct_current( 21991dc90497SAndrey Grodzovsky const struct dc *dc, 2200608ac7bbSJerry Zuo struct dc_state *dst_ctx) 22011dc90497SAndrey Grodzovsky { 2202f36cc577SBhawanpreet Lakha dc_resource_state_copy_construct(dc->current_state, dst_ctx); 22031dc90497SAndrey Grodzovsky } 22041dc90497SAndrey Grodzovsky 2205ab8db3e1SAndrey Grodzovsky 2206ab8db3e1SAndrey Grodzovsky void dc_resource_state_construct( 2207ab8db3e1SAndrey Grodzovsky const struct dc *dc, 2208ab8db3e1SAndrey Grodzovsky struct dc_state *dst_ctx) 2209ab8db3e1SAndrey Grodzovsky { 2210dc88b4a6SEric Yang dst_ctx->clk_mgr = dc->clk_mgr; 2211ab8db3e1SAndrey Grodzovsky } 2212ab8db3e1SAndrey Grodzovsky 22136d822156SNikola Cornij 22146d822156SNikola Cornij bool dc_resource_is_dsc_encoding_supported(const struct dc *dc) 22156d822156SNikola Cornij { 22166d822156SNikola Cornij return dc->res_pool->res_cap->num_dsc > 0; 22176d822156SNikola Cornij } 22186d822156SNikola Cornij 22196d822156SNikola Cornij 22202119aa17SDavid Francis /** 22212119aa17SDavid Francis * dc_validate_global_state() - Determine if HW can support a given state 22222119aa17SDavid Francis * Checks HW resource availability and bandwidth requirement. 22232119aa17SDavid Francis * @dc: dc struct for this driver 22242119aa17SDavid Francis * @new_ctx: state to be validated 2225afcd526bSJoshua Aberback * @fast_validate: set to true if only yes/no to support matters 22262119aa17SDavid Francis * 22272119aa17SDavid Francis * Return: DC_OK if the result can be programmed. Otherwise, an error code. 22282119aa17SDavid Francis */ 2229e750d56dSYongqiang Sun enum dc_status dc_validate_global_state( 22301dc90497SAndrey Grodzovsky struct dc *dc, 2231afcd526bSJoshua Aberback struct dc_state *new_ctx, 2232afcd526bSJoshua Aberback bool fast_validate) 22331dc90497SAndrey Grodzovsky { 22341dc90497SAndrey Grodzovsky enum dc_status result = DC_ERROR_UNEXPECTED; 22351dc90497SAndrey Grodzovsky int i, j; 22361dc90497SAndrey Grodzovsky 2237e41ab030SHarry Wentland if (!new_ctx) 2238e41ab030SHarry Wentland return DC_ERROR_UNEXPECTED; 22398fe44c08SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN) 2240cbaf919fSNicholas Kazlauskas 2241cbaf919fSNicholas Kazlauskas /* 2242cbaf919fSNicholas Kazlauskas * Update link encoder to stream assignment. 2243cbaf919fSNicholas Kazlauskas * TODO: Split out reason allocation from validation. 2244cbaf919fSNicholas Kazlauskas */ 2245b3492ed1SJimmy Kizito if (dc->res_pool->funcs->link_encs_assign && fast_validate == false) 2246cbaf919fSNicholas Kazlauskas dc->res_pool->funcs->link_encs_assign( 2247cbaf919fSNicholas Kazlauskas dc, new_ctx, new_ctx->streams, new_ctx->stream_count); 2248cbaf919fSNicholas Kazlauskas #endif 2249e41ab030SHarry Wentland 2250d596e5d0SYongqiang Sun if (dc->res_pool->funcs->validate_global) { 2251d596e5d0SYongqiang Sun result = dc->res_pool->funcs->validate_global(dc, new_ctx); 2252d596e5d0SYongqiang Sun if (result != DC_OK) 2253d596e5d0SYongqiang Sun return result; 2254d596e5d0SYongqiang Sun } 22551dc90497SAndrey Grodzovsky 2256e41ab030SHarry Wentland for (i = 0; i < new_ctx->stream_count; i++) { 22571dc90497SAndrey Grodzovsky struct dc_stream_state *stream = new_ctx->streams[i]; 22581dc90497SAndrey Grodzovsky 22591dc90497SAndrey Grodzovsky for (j = 0; j < dc->res_pool->pipe_count; j++) { 22601dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[j]; 22611dc90497SAndrey Grodzovsky 22621dc90497SAndrey Grodzovsky if (pipe_ctx->stream != stream) 22631dc90497SAndrey Grodzovsky continue; 22641dc90497SAndrey Grodzovsky 22658d8c82b6SJoseph Gravenor if (dc->res_pool->funcs->patch_unknown_plane_state && 226674eac5f3SSu Sung Chung pipe_ctx->plane_state && 226774eac5f3SSu Sung Chung pipe_ctx->plane_state->tiling_info.gfx9.swizzle == DC_SW_UNKNOWN) { 22688d8c82b6SJoseph Gravenor result = dc->res_pool->funcs->patch_unknown_plane_state(pipe_ctx->plane_state); 226974eac5f3SSu Sung Chung if (result != DC_OK) 227074eac5f3SSu Sung Chung return result; 227174eac5f3SSu Sung Chung } 227274eac5f3SSu Sung Chung 22731dc90497SAndrey Grodzovsky /* Switch to dp clock source only if there is 22741dc90497SAndrey Grodzovsky * no non dp stream that shares the same timing 22751dc90497SAndrey Grodzovsky * with the dp stream. 22761dc90497SAndrey Grodzovsky */ 22771dc90497SAndrey Grodzovsky if (dc_is_dp_signal(pipe_ctx->stream->signal) && 22781dc90497SAndrey Grodzovsky !find_pll_sharable_stream(stream, new_ctx)) { 22791dc90497SAndrey Grodzovsky 22809d0dcecdSHarry Wentland resource_unreference_clock_source( 22811dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 22821dc90497SAndrey Grodzovsky dc->res_pool, 22839d0dcecdSHarry Wentland pipe_ctx->clock_source); 22844a629536SHarry Wentland 22851dc90497SAndrey Grodzovsky pipe_ctx->clock_source = dc->res_pool->dp_clock_source; 22861dc90497SAndrey Grodzovsky resource_reference_clock_source( 22871dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 22881dc90497SAndrey Grodzovsky dc->res_pool, 22891dc90497SAndrey Grodzovsky pipe_ctx->clock_source); 22901dc90497SAndrey Grodzovsky } 22911dc90497SAndrey Grodzovsky } 22921dc90497SAndrey Grodzovsky } 22931dc90497SAndrey Grodzovsky 22941dc90497SAndrey Grodzovsky result = resource_build_scaling_params_for_context(dc, new_ctx); 22951dc90497SAndrey Grodzovsky 22961dc90497SAndrey Grodzovsky if (result == DC_OK) 2297afcd526bSJoshua Aberback if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, fast_validate)) 22981dc90497SAndrey Grodzovsky result = DC_FAIL_BANDWIDTH_VALIDATE; 22991dc90497SAndrey Grodzovsky 23001dc90497SAndrey Grodzovsky return result; 23011dc90497SAndrey Grodzovsky } 23021dc90497SAndrey Grodzovsky 23036e4d6beeSTony Cheng static void patch_gamut_packet_checksum( 2304e09b6473SAnthony Koo struct dc_info_packet *gamut_packet) 23054562236bSHarry Wentland { 23064562236bSHarry Wentland /* For gamut we recalc checksum */ 23076e4d6beeSTony Cheng if (gamut_packet->valid) { 23084562236bSHarry Wentland uint8_t chk_sum = 0; 23094562236bSHarry Wentland uint8_t *ptr; 23104562236bSHarry Wentland uint8_t i; 23114562236bSHarry Wentland 23124562236bSHarry Wentland /*start of the Gamut data. */ 23136e4d6beeSTony Cheng ptr = &gamut_packet->sb[3]; 23144562236bSHarry Wentland 23156e4d6beeSTony Cheng for (i = 0; i <= gamut_packet->sb[1]; i++) 23164562236bSHarry Wentland chk_sum += ptr[i]; 23174562236bSHarry Wentland 23186e4d6beeSTony Cheng gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum); 23191646a6feSAndrew Wong } 23204562236bSHarry Wentland } 23214562236bSHarry Wentland 23224562236bSHarry Wentland static void set_avi_info_frame( 2323e09b6473SAnthony Koo struct dc_info_packet *info_packet, 23244562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 23254562236bSHarry Wentland { 23260971c40eSHarry Wentland struct dc_stream_state *stream = pipe_ctx->stream; 23274562236bSHarry Wentland enum dc_color_space color_space = COLOR_SPACE_UNKNOWN; 23284562236bSHarry Wentland uint32_t pixel_encoding = 0; 23294562236bSHarry Wentland enum scanning_type scan_type = SCANNING_TYPE_NODATA; 23304562236bSHarry Wentland enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA; 23314562236bSHarry Wentland bool itc = false; 233250e27654SZeyu Fan uint8_t itc_value = 0; 23334562236bSHarry Wentland uint8_t cn0_cn1 = 0; 233450e27654SZeyu Fan unsigned int cn0_cn1_value = 0; 23354562236bSHarry Wentland uint8_t *check_sum = NULL; 23364562236bSHarry Wentland uint8_t byte_index = 0; 2337754e3673SAnthony Koo union hdmi_info_packet hdmi_info; 233850e27654SZeyu Fan union display_content_support support = {0}; 23394fa086b9SLeo (Sunpeng) Li unsigned int vic = pipe_ctx->stream->timing.vic; 234015e17335SCharlene Liu enum dc_timing_3d_format format; 23414562236bSHarry Wentland 2342754e3673SAnthony Koo memset(&hdmi_info, 0, sizeof(union hdmi_info_packet)); 2343754e3673SAnthony Koo 23444fa086b9SLeo (Sunpeng) Li color_space = pipe_ctx->stream->output_color_space; 2345e5f2038eSCharlene Liu if (color_space == COLOR_SPACE_UNKNOWN) 23464fa086b9SLeo (Sunpeng) Li color_space = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ? 2347e5f2038eSCharlene Liu COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709; 23484562236bSHarry Wentland 23494562236bSHarry Wentland /* Initialize header */ 2350e09b6473SAnthony Koo hdmi_info.bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI; 23514562236bSHarry Wentland /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall 23524562236bSHarry Wentland * not be used in HDMI 2.0 (Section 10.1) */ 2353e09b6473SAnthony Koo hdmi_info.bits.header.version = 2; 2354e09b6473SAnthony Koo hdmi_info.bits.header.length = HDMI_AVI_INFOFRAME_SIZE; 23554562236bSHarry Wentland 23564562236bSHarry Wentland /* 23574562236bSHarry Wentland * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built 23584562236bSHarry Wentland * according to HDMI 2.0 spec (Section 10.1) 23594562236bSHarry Wentland */ 23604562236bSHarry Wentland 23614fa086b9SLeo (Sunpeng) Li switch (stream->timing.pixel_encoding) { 23624562236bSHarry Wentland case PIXEL_ENCODING_YCBCR422: 23634562236bSHarry Wentland pixel_encoding = 1; 23644562236bSHarry Wentland break; 23654562236bSHarry Wentland 23664562236bSHarry Wentland case PIXEL_ENCODING_YCBCR444: 23674562236bSHarry Wentland pixel_encoding = 2; 23684562236bSHarry Wentland break; 23694562236bSHarry Wentland case PIXEL_ENCODING_YCBCR420: 23704562236bSHarry Wentland pixel_encoding = 3; 23714562236bSHarry Wentland break; 23724562236bSHarry Wentland 23734562236bSHarry Wentland case PIXEL_ENCODING_RGB: 23744562236bSHarry Wentland default: 23754562236bSHarry Wentland pixel_encoding = 0; 23764562236bSHarry Wentland } 23774562236bSHarry Wentland 23784562236bSHarry Wentland /* Y0_Y1_Y2 : The pixel encoding */ 23794562236bSHarry Wentland /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */ 2380e09b6473SAnthony Koo hdmi_info.bits.Y0_Y1_Y2 = pixel_encoding; 23814562236bSHarry Wentland 23824562236bSHarry Wentland /* A0 = 1 Active Format Information valid */ 2383e09b6473SAnthony Koo hdmi_info.bits.A0 = ACTIVE_FORMAT_VALID; 23844562236bSHarry Wentland 23854562236bSHarry Wentland /* B0, B1 = 3; Bar info data is valid */ 2386e09b6473SAnthony Koo hdmi_info.bits.B0_B1 = BAR_INFO_BOTH_VALID; 23874562236bSHarry Wentland 2388e09b6473SAnthony Koo hdmi_info.bits.SC0_SC1 = PICTURE_SCALING_UNIFORM; 23894562236bSHarry Wentland 23904562236bSHarry Wentland /* S0, S1 : Underscan / Overscan */ 23914562236bSHarry Wentland /* TODO: un-hardcode scan type */ 23924562236bSHarry Wentland scan_type = SCANNING_TYPE_UNDERSCAN; 2393e09b6473SAnthony Koo hdmi_info.bits.S0_S1 = scan_type; 23944562236bSHarry Wentland 23954562236bSHarry Wentland /* C0, C1 : Colorimetry */ 23968fde5884SCharlene Liu if (color_space == COLOR_SPACE_YCBCR709 || 239715e17335SCharlene Liu color_space == COLOR_SPACE_YCBCR709_LIMITED) 2398e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709; 23998fde5884SCharlene Liu else if (color_space == COLOR_SPACE_YCBCR601 || 24008fde5884SCharlene Liu color_space == COLOR_SPACE_YCBCR601_LIMITED) 2401e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_ITU601; 24028fde5884SCharlene Liu else { 2403e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_NO_DATA; 24048fde5884SCharlene Liu } 2405534db198SAmy Zhang if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE || 2406534db198SAmy Zhang color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE || 2407534db198SAmy Zhang color_space == COLOR_SPACE_2020_YCBCR) { 2408e09b6473SAnthony Koo hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR; 2409e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; 2410534db198SAmy Zhang } else if (color_space == COLOR_SPACE_ADOBERGB) { 2411e09b6473SAnthony Koo hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB; 2412e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; 2413534db198SAmy Zhang } 2414534db198SAmy Zhang 24154562236bSHarry Wentland /* TODO: un-hardcode aspect ratio */ 24164fa086b9SLeo (Sunpeng) Li aspect = stream->timing.aspect_ratio; 24174562236bSHarry Wentland 24184562236bSHarry Wentland switch (aspect) { 24194562236bSHarry Wentland case ASPECT_RATIO_4_3: 24204562236bSHarry Wentland case ASPECT_RATIO_16_9: 2421e09b6473SAnthony Koo hdmi_info.bits.M0_M1 = aspect; 24224562236bSHarry Wentland break; 24234562236bSHarry Wentland 24244562236bSHarry Wentland case ASPECT_RATIO_NO_DATA: 24254562236bSHarry Wentland case ASPECT_RATIO_64_27: 24264562236bSHarry Wentland case ASPECT_RATIO_256_135: 24274562236bSHarry Wentland default: 2428e09b6473SAnthony Koo hdmi_info.bits.M0_M1 = 0; 24294562236bSHarry Wentland } 24304562236bSHarry Wentland 24314562236bSHarry Wentland /* Active Format Aspect ratio - same as Picture Aspect Ratio. */ 2432e09b6473SAnthony Koo hdmi_info.bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; 24334562236bSHarry Wentland 24344562236bSHarry Wentland /* TODO: un-hardcode cn0_cn1 and itc */ 243550e27654SZeyu Fan 24364562236bSHarry Wentland cn0_cn1 = 0; 243750e27654SZeyu Fan cn0_cn1_value = 0; 243850e27654SZeyu Fan 243950e27654SZeyu Fan itc = true; 244050e27654SZeyu Fan itc_value = 1; 244150e27654SZeyu Fan 2442ceb3dbb4SJun Lei support = stream->content_support; 24434562236bSHarry Wentland 24444562236bSHarry Wentland if (itc) { 244550e27654SZeyu Fan if (!support.bits.valid_content_type) { 244650e27654SZeyu Fan cn0_cn1_value = 0; 244750e27654SZeyu Fan } else { 244850e27654SZeyu Fan if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) { 244950e27654SZeyu Fan if (support.bits.graphics_content == 1) { 245050e27654SZeyu Fan cn0_cn1_value = 0; 245150e27654SZeyu Fan } 245250e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) { 245350e27654SZeyu Fan if (support.bits.photo_content == 1) { 245450e27654SZeyu Fan cn0_cn1_value = 1; 245550e27654SZeyu Fan } else { 245650e27654SZeyu Fan cn0_cn1_value = 0; 245750e27654SZeyu Fan itc_value = 0; 245850e27654SZeyu Fan } 245950e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) { 246050e27654SZeyu Fan if (support.bits.cinema_content == 1) { 246150e27654SZeyu Fan cn0_cn1_value = 2; 246250e27654SZeyu Fan } else { 246350e27654SZeyu Fan cn0_cn1_value = 0; 246450e27654SZeyu Fan itc_value = 0; 246550e27654SZeyu Fan } 246650e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) { 246750e27654SZeyu Fan if (support.bits.game_content == 1) { 246850e27654SZeyu Fan cn0_cn1_value = 3; 246950e27654SZeyu Fan } else { 247050e27654SZeyu Fan cn0_cn1_value = 0; 247150e27654SZeyu Fan itc_value = 0; 247250e27654SZeyu Fan } 247350e27654SZeyu Fan } 247450e27654SZeyu Fan } 2475e09b6473SAnthony Koo hdmi_info.bits.CN0_CN1 = cn0_cn1_value; 2476e09b6473SAnthony Koo hdmi_info.bits.ITC = itc_value; 24774562236bSHarry Wentland } 24784562236bSHarry Wentland 2479fdf7d4f5SDillon Varone if (stream->qs_bit == 1) { 2480fdf7d4f5SDillon Varone if (color_space == COLOR_SPACE_SRGB || 2481fdf7d4f5SDillon Varone color_space == COLOR_SPACE_2020_RGB_FULLRANGE) 2482fdf7d4f5SDillon Varone hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; 2483fdf7d4f5SDillon Varone else if (color_space == COLOR_SPACE_SRGB_LIMITED || 2484fdf7d4f5SDillon Varone color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) 2485fdf7d4f5SDillon Varone hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE; 2486fdf7d4f5SDillon Varone else 2487fdf7d4f5SDillon Varone hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 2488fdf7d4f5SDillon Varone } else 2489fdf7d4f5SDillon Varone hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 2490fdf7d4f5SDillon Varone 24914562236bSHarry Wentland /* TODO : We should handle YCC quantization */ 24924562236bSHarry Wentland /* but we do not have matrix calculation */ 2493fdf7d4f5SDillon Varone if (stream->qy_bit == 1) { 249450e27654SZeyu Fan if (color_space == COLOR_SPACE_SRGB || 2495fdf7d4f5SDillon Varone color_space == COLOR_SPACE_2020_RGB_FULLRANGE) 2496993dca3eSQingqing Zhuo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 2497fdf7d4f5SDillon Varone else if (color_space == COLOR_SPACE_SRGB_LIMITED || 2498fdf7d4f5SDillon Varone color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) 2499e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 2500fdf7d4f5SDillon Varone else 2501e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 2502fdf7d4f5SDillon Varone } else 2503e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 250450e27654SZeyu Fan 250515e17335SCharlene Liu ///VIC 25064fa086b9SLeo (Sunpeng) Li format = stream->timing.timing_3d_format; 250715e17335SCharlene Liu /*todo, add 3DStereo support*/ 250815e17335SCharlene Liu if (format != TIMING_3D_FORMAT_NONE) { 250915e17335SCharlene Liu // Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled 25104fa086b9SLeo (Sunpeng) Li switch (pipe_ctx->stream->timing.hdmi_vic) { 251115e17335SCharlene Liu case 1: 251215e17335SCharlene Liu vic = 95; 251315e17335SCharlene Liu break; 251415e17335SCharlene Liu case 2: 251515e17335SCharlene Liu vic = 94; 251615e17335SCharlene Liu break; 251715e17335SCharlene Liu case 3: 251815e17335SCharlene Liu vic = 93; 251915e17335SCharlene Liu break; 252015e17335SCharlene Liu case 4: 252115e17335SCharlene Liu vic = 98; 252215e17335SCharlene Liu break; 252315e17335SCharlene Liu default: 252415e17335SCharlene Liu break; 252515e17335SCharlene Liu } 252615e17335SCharlene Liu } 2527efa02336SChris Park /* If VIC >= 128, the Source shall use AVI InfoFrame Version 3*/ 2528e09b6473SAnthony Koo hdmi_info.bits.VIC0_VIC7 = vic; 2529efa02336SChris Park if (vic >= 128) 2530efa02336SChris Park hdmi_info.bits.header.version = 3; 2531efa02336SChris Park /* If (C1, C0)=(1, 1) and (EC2, EC1, EC0)=(1, 1, 1), 2532efa02336SChris Park * the Source shall use 20 AVI InfoFrame Version 4 2533efa02336SChris Park */ 2534efa02336SChris Park if (hdmi_info.bits.C0_C1 == COLORIMETRY_EXTENDED && 2535efa02336SChris Park hdmi_info.bits.EC0_EC2 == COLORIMETRYEX_RESERVED) { 2536efa02336SChris Park hdmi_info.bits.header.version = 4; 2537efa02336SChris Park hdmi_info.bits.header.length = 14; 2538efa02336SChris Park } 25394562236bSHarry Wentland 25404562236bSHarry Wentland /* pixel repetition 25414562236bSHarry Wentland * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel 25424562236bSHarry Wentland * repetition start from 1 */ 2543e09b6473SAnthony Koo hdmi_info.bits.PR0_PR3 = 0; 25444562236bSHarry Wentland 25454562236bSHarry Wentland /* Bar Info 25464562236bSHarry Wentland * barTop: Line Number of End of Top Bar. 25474562236bSHarry Wentland * barBottom: Line Number of Start of Bottom Bar. 25484562236bSHarry Wentland * barLeft: Pixel Number of End of Left Bar. 25494562236bSHarry Wentland * barRight: Pixel Number of Start of Right Bar. */ 2550e09b6473SAnthony Koo hdmi_info.bits.bar_top = stream->timing.v_border_top; 2551e09b6473SAnthony Koo hdmi_info.bits.bar_bottom = (stream->timing.v_total 25524fa086b9SLeo (Sunpeng) Li - stream->timing.v_border_bottom + 1); 2553e09b6473SAnthony Koo hdmi_info.bits.bar_left = stream->timing.h_border_left; 2554e09b6473SAnthony Koo hdmi_info.bits.bar_right = (stream->timing.h_total 25554fa086b9SLeo (Sunpeng) Li - stream->timing.h_border_right + 1); 25564562236bSHarry Wentland 25572f482c4fSChris Park /* Additional Colorimetry Extension 25582f482c4fSChris Park * Used in conduction with C0-C1 and EC0-EC2 25592f482c4fSChris Park * 0 = DCI-P3 RGB (D65) 25602f482c4fSChris Park * 1 = DCI-P3 RGB (theater) 25612f482c4fSChris Park */ 25622f482c4fSChris Park hdmi_info.bits.ACE0_ACE3 = 0; 25632f482c4fSChris Park 25644562236bSHarry Wentland /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ 2565e09b6473SAnthony Koo check_sum = &hdmi_info.packet_raw_data.sb[0]; 2566e8d726b7SReza Amini 2567efa02336SChris Park *check_sum = HDMI_INFOFRAME_TYPE_AVI + hdmi_info.bits.header.length + hdmi_info.bits.header.version; 25684562236bSHarry Wentland 2569efa02336SChris Park for (byte_index = 1; byte_index <= hdmi_info.bits.header.length; byte_index++) 2570e09b6473SAnthony Koo *check_sum += hdmi_info.packet_raw_data.sb[byte_index]; 25714562236bSHarry Wentland 25724562236bSHarry Wentland /* one byte complement */ 25734562236bSHarry Wentland *check_sum = (uint8_t) (0x100 - *check_sum); 25744562236bSHarry Wentland 25754562236bSHarry Wentland /* Store in hw_path_mode */ 2576e09b6473SAnthony Koo info_packet->hb0 = hdmi_info.packet_raw_data.hb0; 2577e09b6473SAnthony Koo info_packet->hb1 = hdmi_info.packet_raw_data.hb1; 2578e09b6473SAnthony Koo info_packet->hb2 = hdmi_info.packet_raw_data.hb2; 25794562236bSHarry Wentland 2580e09b6473SAnthony Koo for (byte_index = 0; byte_index < sizeof(hdmi_info.packet_raw_data.sb); byte_index++) 2581e09b6473SAnthony Koo info_packet->sb[byte_index] = hdmi_info.packet_raw_data.sb[byte_index]; 25824562236bSHarry Wentland 25834562236bSHarry Wentland info_packet->valid = true; 25844562236bSHarry Wentland } 25854562236bSHarry Wentland 25866e4d6beeSTony Cheng static void set_vendor_info_packet( 2587e09b6473SAnthony Koo struct dc_info_packet *info_packet, 25880971c40eSHarry Wentland struct dc_stream_state *stream) 25894562236bSHarry Wentland { 2590ecd0136bSHarmanprit Tatla /* SPD info packet for FreeSync */ 259115e17335SCharlene Liu 2592ecd0136bSHarmanprit Tatla /* Check if Freesync is supported. Return if false. If true, 2593ecd0136bSHarmanprit Tatla * set the corresponding bit in the info packet 2594ecd0136bSHarmanprit Tatla */ 2595ecd0136bSHarmanprit Tatla if (!stream->vsp_infopacket.valid) 25964562236bSHarry Wentland return; 25974562236bSHarry Wentland 2598ecd0136bSHarmanprit Tatla *info_packet = stream->vsp_infopacket; 25994562236bSHarry Wentland } 26004562236bSHarry Wentland 26016e4d6beeSTony Cheng static void set_spd_info_packet( 2602e09b6473SAnthony Koo struct dc_info_packet *info_packet, 26030971c40eSHarry Wentland struct dc_stream_state *stream) 26044562236bSHarry Wentland { 26054562236bSHarry Wentland /* SPD info packet for FreeSync */ 26064562236bSHarry Wentland 26074562236bSHarry Wentland /* Check if Freesync is supported. Return if false. If true, 26084562236bSHarry Wentland * set the corresponding bit in the info packet 26094562236bSHarry Wentland */ 261098e6436dSAnthony Koo if (!stream->vrr_infopacket.valid) 26114562236bSHarry Wentland return; 26124562236bSHarry Wentland 261398e6436dSAnthony Koo *info_packet = stream->vrr_infopacket; 26144562236bSHarry Wentland } 26154562236bSHarry Wentland 26161646a6feSAndrew Wong static void set_hdr_static_info_packet( 2617e09b6473SAnthony Koo struct dc_info_packet *info_packet, 26180971c40eSHarry Wentland struct dc_stream_state *stream) 26191646a6feSAndrew Wong { 26200eeef690SAnthony Koo /* HDR Static Metadata info packet for HDR10 */ 26211646a6feSAndrew Wong 2622a10dc97aSKrunoslav Kovac if (!stream->hdr_static_metadata.valid || 2623a10dc97aSKrunoslav Kovac stream->use_dynamic_meta) 262410bff005SYongqiang Sun return; 262510bff005SYongqiang Sun 26260eeef690SAnthony Koo *info_packet = stream->hdr_static_metadata; 26271646a6feSAndrew Wong } 26281646a6feSAndrew Wong 26296e4d6beeSTony Cheng static void set_vsc_info_packet( 2630e09b6473SAnthony Koo struct dc_info_packet *info_packet, 26310971c40eSHarry Wentland struct dc_stream_state *stream) 26324562236bSHarry Wentland { 26331336926fSAlvin lee if (!stream->vsc_infopacket.valid) 26344562236bSHarry Wentland return; 26354562236bSHarry Wentland 26361336926fSAlvin lee *info_packet = stream->vsc_infopacket; 26374562236bSHarry Wentland } 26384562236bSHarry Wentland 2639f36cc577SBhawanpreet Lakha void dc_resource_state_destruct(struct dc_state *context) 26404562236bSHarry Wentland { 26414562236bSHarry Wentland int i, j; 26424562236bSHarry Wentland 2643ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 26443be5262eSHarry Wentland for (j = 0; j < context->stream_status[i].plane_count; j++) 26453be5262eSHarry Wentland dc_plane_state_release( 26463be5262eSHarry Wentland context->stream_status[i].plane_states[j]); 26474562236bSHarry Wentland 26483be5262eSHarry Wentland context->stream_status[i].plane_count = 0; 26494fa086b9SLeo (Sunpeng) Li dc_stream_release(context->streams[i]); 2650ab2541b6SAric Cyr context->streams[i] = NULL; 26514562236bSHarry Wentland } 26525728d5e5SPaul Wu context->stream_count = 0; 26534562236bSHarry Wentland } 26544562236bSHarry Wentland 2655f36cc577SBhawanpreet Lakha void dc_resource_state_copy_construct( 2656608ac7bbSJerry Zuo const struct dc_state *src_ctx, 2657608ac7bbSJerry Zuo struct dc_state *dst_ctx) 26584562236bSHarry Wentland { 26594562236bSHarry Wentland int i, j; 26608ee5702aSDave Airlie struct kref refcount = dst_ctx->refcount; 26614562236bSHarry Wentland 26624562236bSHarry Wentland *dst_ctx = *src_ctx; 26634562236bSHarry Wentland 2664a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 26654562236bSHarry Wentland struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i]; 26664562236bSHarry Wentland 26674562236bSHarry Wentland if (cur_pipe->top_pipe) 26684562236bSHarry Wentland cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; 26694562236bSHarry Wentland 26704562236bSHarry Wentland if (cur_pipe->bottom_pipe) 26714562236bSHarry Wentland cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; 2672b1f6d01cSDmytro Laktyushkin 2673b1f6d01cSDmytro Laktyushkin if (cur_pipe->next_odm_pipe) 2674b1f6d01cSDmytro Laktyushkin cur_pipe->next_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx]; 2675b1f6d01cSDmytro Laktyushkin 2676b1f6d01cSDmytro Laktyushkin if (cur_pipe->prev_odm_pipe) 2677b1f6d01cSDmytro Laktyushkin cur_pipe->prev_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx]; 26784562236bSHarry Wentland } 26794562236bSHarry Wentland 2680ab2541b6SAric Cyr for (i = 0; i < dst_ctx->stream_count; i++) { 26814fa086b9SLeo (Sunpeng) Li dc_stream_retain(dst_ctx->streams[i]); 26823be5262eSHarry Wentland for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++) 26833be5262eSHarry Wentland dc_plane_state_retain( 26843be5262eSHarry Wentland dst_ctx->stream_status[i].plane_states[j]); 26854562236bSHarry Wentland } 26869a3afbb3SAndrey Grodzovsky 26879a3afbb3SAndrey Grodzovsky /* context refcount should not be overridden */ 26888ee5702aSDave Airlie dst_ctx->refcount = refcount; 26899a3afbb3SAndrey Grodzovsky 26904562236bSHarry Wentland } 26914562236bSHarry Wentland 26924562236bSHarry Wentland struct clock_source *dc_resource_find_first_free_pll( 2693a2b8659dSTony Cheng struct resource_context *res_ctx, 2694a2b8659dSTony Cheng const struct resource_pool *pool) 26954562236bSHarry Wentland { 26964562236bSHarry Wentland int i; 26974562236bSHarry Wentland 2698a2b8659dSTony Cheng for (i = 0; i < pool->clk_src_count; ++i) { 26994562236bSHarry Wentland if (res_ctx->clock_source_ref_count[i] == 0) 2700a2b8659dSTony Cheng return pool->clock_sources[i]; 27014562236bSHarry Wentland } 27024562236bSHarry Wentland 27034562236bSHarry Wentland return NULL; 27044562236bSHarry Wentland } 27054562236bSHarry Wentland 27064562236bSHarry Wentland void resource_build_info_frame(struct pipe_ctx *pipe_ctx) 27074562236bSHarry Wentland { 27084562236bSHarry Wentland enum signal_type signal = SIGNAL_TYPE_NONE; 270996c50c0dSHarry Wentland struct encoder_info_frame *info = &pipe_ctx->stream_res.encoder_info_frame; 27104562236bSHarry Wentland 27114562236bSHarry Wentland /* default all packets to invalid */ 27126e4d6beeSTony Cheng info->avi.valid = false; 27136e4d6beeSTony Cheng info->gamut.valid = false; 27146e4d6beeSTony Cheng info->vendor.valid = false; 2715630e3573SJeff Smith info->spd.valid = false; 27166e4d6beeSTony Cheng info->hdrsmd.valid = false; 27176e4d6beeSTony Cheng info->vsc.valid = false; 27184562236bSHarry Wentland 27194562236bSHarry Wentland signal = pipe_ctx->stream->signal; 27204562236bSHarry Wentland 27214562236bSHarry Wentland /* HDMi and DP have different info packets*/ 27224562236bSHarry Wentland if (dc_is_hdmi_signal(signal)) { 27236e4d6beeSTony Cheng set_avi_info_frame(&info->avi, pipe_ctx); 27246e4d6beeSTony Cheng 27256e4d6beeSTony Cheng set_vendor_info_packet(&info->vendor, pipe_ctx->stream); 27266e4d6beeSTony Cheng 27276e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 27286e4d6beeSTony Cheng 272956ef6ed9SAnthony Koo set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 27306e4d6beeSTony Cheng 2731a33fa99dSHarry Wentland } else if (dc_is_dp_signal(signal)) { 27326e4d6beeSTony Cheng set_vsc_info_packet(&info->vsc, pipe_ctx->stream); 27336e4d6beeSTony Cheng 27346e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 27356e4d6beeSTony Cheng 273656ef6ed9SAnthony Koo set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 2737a33fa99dSHarry Wentland } 27384562236bSHarry Wentland 27396e4d6beeSTony Cheng patch_gamut_packet_checksum(&info->gamut); 27404562236bSHarry Wentland } 27414562236bSHarry Wentland 27424562236bSHarry Wentland enum dc_status resource_map_clock_resources( 2743fb3466a4SBhawanpreet Lakha const struct dc *dc, 2744608ac7bbSJerry Zuo struct dc_state *context, 27451dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 27464562236bSHarry Wentland { 27474562236bSHarry Wentland /* acquire new resources */ 27481dc90497SAndrey Grodzovsky const struct resource_pool *pool = dc->res_pool; 27491dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream( 27501dc90497SAndrey Grodzovsky &context->res_ctx, stream); 27514562236bSHarry Wentland 27521dc90497SAndrey Grodzovsky if (!pipe_ctx) 27531dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 27544562236bSHarry Wentland 27554562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal) 27564562236bSHarry Wentland || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) 2757a2b8659dSTony Cheng pipe_ctx->clock_source = pool->dp_clock_source; 27584562236bSHarry Wentland else { 27594562236bSHarry Wentland pipe_ctx->clock_source = NULL; 27604562236bSHarry Wentland 2761fb3466a4SBhawanpreet Lakha if (!dc->config.disable_disp_pll_sharing) 27624ed4e51bSMikita Lipski pipe_ctx->clock_source = resource_find_used_clk_src_for_sharing( 27634562236bSHarry Wentland &context->res_ctx, 27644562236bSHarry Wentland pipe_ctx); 27654562236bSHarry Wentland 27664562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 27674562236bSHarry Wentland pipe_ctx->clock_source = 2768a2b8659dSTony Cheng dc_resource_find_first_free_pll( 2769a2b8659dSTony Cheng &context->res_ctx, 2770a2b8659dSTony Cheng pool); 27714562236bSHarry Wentland } 27724562236bSHarry Wentland 27734562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 27744562236bSHarry Wentland return DC_NO_CLOCK_SOURCE_RESOURCE; 27754562236bSHarry Wentland 27764562236bSHarry Wentland resource_reference_clock_source( 2777a2b8659dSTony Cheng &context->res_ctx, pool, 27784562236bSHarry Wentland pipe_ctx->clock_source); 27794562236bSHarry Wentland 27804562236bSHarry Wentland return DC_OK; 27814562236bSHarry Wentland } 27824562236bSHarry Wentland 27834562236bSHarry Wentland /* 27844562236bSHarry Wentland * Note: We need to disable output if clock sources change, 27854562236bSHarry Wentland * since bios does optimization and doesn't apply if changing 27864562236bSHarry Wentland * PHY when not already disabled. 27874562236bSHarry Wentland */ 27884562236bSHarry Wentland bool pipe_need_reprogram( 27894562236bSHarry Wentland struct pipe_ctx *pipe_ctx_old, 27904562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 27914562236bSHarry Wentland { 2792cfe4645eSDmytro Laktyushkin if (!pipe_ctx_old->stream) 2793cfe4645eSDmytro Laktyushkin return false; 2794cfe4645eSDmytro Laktyushkin 27954562236bSHarry Wentland if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink) 27964562236bSHarry Wentland return true; 27974562236bSHarry Wentland 27984562236bSHarry Wentland if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal) 27994562236bSHarry Wentland return true; 28004562236bSHarry Wentland 2801afaacef4SHarry Wentland if (pipe_ctx_old->stream_res.audio != pipe_ctx->stream_res.audio) 28024562236bSHarry Wentland return true; 28034562236bSHarry Wentland 28044562236bSHarry Wentland if (pipe_ctx_old->clock_source != pipe_ctx->clock_source 28054562236bSHarry Wentland && pipe_ctx_old->stream != pipe_ctx->stream) 28064562236bSHarry Wentland return true; 28074562236bSHarry Wentland 28088e9c4c8cSHarry Wentland if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc) 28094562236bSHarry Wentland return true; 28104562236bSHarry Wentland 28114562236bSHarry Wentland if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 28124562236bSHarry Wentland return true; 28134562236bSHarry Wentland 28141e7e86c4SSamson Tam if (pipe_ctx_old->stream->dpms_off != pipe_ctx->stream->dpms_off) 28151e7e86c4SSamson Tam return true; 28161e7e86c4SSamson Tam 2817eed928dcSCharlene Liu if (false == pipe_ctx_old->stream->link->link_state_valid && 2818eed928dcSCharlene Liu false == pipe_ctx_old->stream->dpms_off) 2819eed928dcSCharlene Liu return true; 2820eed928dcSCharlene Liu 282114e49bb3SNikola Cornij if (pipe_ctx_old->stream_res.dsc != pipe_ctx->stream_res.dsc) 282214e49bb3SNikola Cornij return true; 282314e49bb3SNikola Cornij 2824f01ee019SFangzhi Zuo #if defined(CONFIG_DRM_AMD_DC_DCN) 2825f01ee019SFangzhi Zuo if (pipe_ctx_old->stream_res.hpo_dp_stream_enc != pipe_ctx->stream_res.hpo_dp_stream_enc) 2826f01ee019SFangzhi Zuo return true; 2827f01ee019SFangzhi Zuo #endif 2828f01ee019SFangzhi Zuo 2829f42ef862SJimmy Kizito /* DIG link encoder resource assignment for stream changed. */ 2830*0d4b4253SJimmy Kizito if (pipe_ctx_old->stream->ctx->dc->res_pool->funcs->link_encs_assign) { 2831*0d4b4253SJimmy Kizito bool need_reprogram = false; 2832*0d4b4253SJimmy Kizito struct dc *dc = pipe_ctx_old->stream->ctx->dc; 2833*0d4b4253SJimmy Kizito enum link_enc_cfg_mode mode = dc->current_state->res_ctx.link_enc_cfg_ctx.mode; 2834*0d4b4253SJimmy Kizito 2835*0d4b4253SJimmy Kizito dc->current_state->res_ctx.link_enc_cfg_ctx.mode = LINK_ENC_CFG_STEADY; 2836*0d4b4253SJimmy Kizito if (link_enc_cfg_get_link_enc_used_by_stream(dc, pipe_ctx_old->stream) != pipe_ctx->stream->link_enc) 2837*0d4b4253SJimmy Kizito need_reprogram = true; 2838*0d4b4253SJimmy Kizito dc->current_state->res_ctx.link_enc_cfg_ctx.mode = mode; 2839*0d4b4253SJimmy Kizito 2840*0d4b4253SJimmy Kizito return need_reprogram; 2841*0d4b4253SJimmy Kizito } 2842f42ef862SJimmy Kizito 28434562236bSHarry Wentland return false; 28444562236bSHarry Wentland } 2845529cad0fSDing Wang 28460971c40eSHarry Wentland void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, 2847529cad0fSDing Wang struct bit_depth_reduction_params *fmt_bit_depth) 2848529cad0fSDing Wang { 28494fa086b9SLeo (Sunpeng) Li enum dc_dither_option option = stream->dither_option; 2850529cad0fSDing Wang enum dc_pixel_encoding pixel_encoding = 28514fa086b9SLeo (Sunpeng) Li stream->timing.pixel_encoding; 2852529cad0fSDing Wang 2853529cad0fSDing Wang memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); 2854529cad0fSDing Wang 2855603767f9STony Cheng if (option == DITHER_OPTION_DEFAULT) { 2856603767f9STony Cheng switch (stream->timing.display_color_depth) { 2857603767f9STony Cheng case COLOR_DEPTH_666: 2858603767f9STony Cheng option = DITHER_OPTION_SPATIAL6; 2859603767f9STony Cheng break; 2860603767f9STony Cheng case COLOR_DEPTH_888: 2861603767f9STony Cheng option = DITHER_OPTION_SPATIAL8; 2862603767f9STony Cheng break; 2863603767f9STony Cheng case COLOR_DEPTH_101010: 2864603767f9STony Cheng option = DITHER_OPTION_SPATIAL10; 2865603767f9STony Cheng break; 2866603767f9STony Cheng default: 2867603767f9STony Cheng option = DITHER_OPTION_DISABLE; 2868603767f9STony Cheng } 2869603767f9STony Cheng } 2870603767f9STony Cheng 2871529cad0fSDing Wang if (option == DITHER_OPTION_DISABLE) 2872529cad0fSDing Wang return; 2873529cad0fSDing Wang 2874529cad0fSDing Wang if (option == DITHER_OPTION_TRUN6) { 2875529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2876529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 0; 2877529cad0fSDing Wang } else if (option == DITHER_OPTION_TRUN8 || 2878529cad0fSDing Wang option == DITHER_OPTION_TRUN8_SPATIAL6 || 2879529cad0fSDing Wang option == DITHER_OPTION_TRUN8_FM6) { 2880529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2881529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 1; 2882529cad0fSDing Wang } else if (option == DITHER_OPTION_TRUN10 || 2883529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL6 || 2884529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8 || 2885529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM8 || 2886529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM6 || 2887529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2888529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2889529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2890529cad0fSDing Wang } 2891529cad0fSDing Wang 2892529cad0fSDing Wang /* special case - Formatter can only reduce by 4 bits at most. 2893529cad0fSDing Wang * When reducing from 12 to 6 bits, 2894529cad0fSDing Wang * HW recommends we use trunc with round mode 2895529cad0fSDing Wang * (if we did nothing, trunc to 10 bits would be used) 2896529cad0fSDing Wang * note that any 12->10 bit reduction is ignored prior to DCE8, 2897529cad0fSDing Wang * as the input was 10 bits. 2898529cad0fSDing Wang */ 2899529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2900529cad0fSDing Wang option == DITHER_OPTION_SPATIAL6 || 2901529cad0fSDing Wang option == DITHER_OPTION_FM6) { 2902529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2903529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2904529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_MODE = 1; 2905529cad0fSDing Wang } 2906529cad0fSDing Wang 2907529cad0fSDing Wang /* spatial dither 2908529cad0fSDing Wang * note that spatial modes 1-3 are never used 2909529cad0fSDing Wang */ 2910529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2911529cad0fSDing Wang option == DITHER_OPTION_SPATIAL6 || 2912529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL6 || 2913529cad0fSDing Wang option == DITHER_OPTION_TRUN8_SPATIAL6) { 2914529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2915529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0; 2916529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2917529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2918529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2919529cad0fSDing Wang } else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM || 2920529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8 || 2921529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8_FM6 || 2922529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8 || 2923529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2924529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2925529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1; 2926529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2927529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2928529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2929529cad0fSDing Wang } else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM || 2930529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10 || 2931529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM8 || 2932529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM6) { 2933529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2934529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2; 2935529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2936529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2937529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2938529cad0fSDing Wang } 2939529cad0fSDing Wang 2940529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6 || 2941529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8 || 2942529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10) { 2943529cad0fSDing Wang fmt_bit_depth->flags.FRAME_RANDOM = 0; 2944529cad0fSDing Wang } else { 2945529cad0fSDing Wang fmt_bit_depth->flags.FRAME_RANDOM = 1; 2946529cad0fSDing Wang } 2947529cad0fSDing Wang 2948529cad0fSDing Wang ////////////////////// 2949529cad0fSDing Wang //// temporal dither 2950529cad0fSDing Wang ////////////////////// 2951529cad0fSDing Wang if (option == DITHER_OPTION_FM6 || 2952529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8_FM6 || 2953529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM6 || 2954529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM6 || 2955529cad0fSDing Wang option == DITHER_OPTION_TRUN8_FM6 || 2956529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2957529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2958529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0; 2959529cad0fSDing Wang } else if (option == DITHER_OPTION_FM8 || 2960529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM8 || 2961529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM8) { 2962529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2963529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1; 2964529cad0fSDing Wang } else if (option == DITHER_OPTION_FM10) { 2965529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2966529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2; 2967529cad0fSDing Wang } 2968529cad0fSDing Wang 2969529cad0fSDing Wang fmt_bit_depth->pixel_encoding = pixel_encoding; 2970529cad0fSDing Wang } 29719345d987SAndrey Grodzovsky 297262c933f9SYongqiang Sun enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) 29739345d987SAndrey Grodzovsky { 2974ceb3dbb4SJun Lei struct dc_link *link = stream->link; 29752b77dcc5SAnthony Koo struct timing_generator *tg = dc->res_pool->timing_generators[0]; 29769345d987SAndrey Grodzovsky enum dc_status res = DC_OK; 29779345d987SAndrey Grodzovsky 29784fa086b9SLeo (Sunpeng) Li calculate_phy_pix_clks(stream); 29799345d987SAndrey Grodzovsky 29804fa086b9SLeo (Sunpeng) Li if (!tg->funcs->validate_timing(tg, &stream->timing)) 29819345d987SAndrey Grodzovsky res = DC_FAIL_CONTROLLER_VALIDATE; 29829345d987SAndrey Grodzovsky 2983248cbed6SEric Bernstein if (res == DC_OK) { 298464d283cbSJimmy Kizito if (link->ep_type == DISPLAY_ENDPOINT_PHY && 298564d283cbSJimmy Kizito !link->link_enc->funcs->validate_output_with_stream( 29864fa086b9SLeo (Sunpeng) Li link->link_enc, stream)) 29879345d987SAndrey Grodzovsky res = DC_FAIL_ENC_VALIDATE; 2988248cbed6SEric Bernstein } 29899345d987SAndrey Grodzovsky 29909345d987SAndrey Grodzovsky /* TODO: validate audio ASIC caps, encoder */ 29919345d987SAndrey Grodzovsky 29929345d987SAndrey Grodzovsky if (res == DC_OK) 29934fa086b9SLeo (Sunpeng) Li res = dc_link_validate_mode_timing(stream, 29949345d987SAndrey Grodzovsky link, 29954fa086b9SLeo (Sunpeng) Li &stream->timing); 29969345d987SAndrey Grodzovsky 299762c933f9SYongqiang Sun return res; 29989345d987SAndrey Grodzovsky } 2999792671d7SAndrey Grodzovsky 300062c933f9SYongqiang Sun enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) 3001792671d7SAndrey Grodzovsky { 300262c933f9SYongqiang Sun enum dc_status res = DC_OK; 300362c933f9SYongqiang Sun 3004792671d7SAndrey Grodzovsky /* TODO For now validates pixel format only */ 30058e7095b9SDmytro Laktyushkin if (dc->res_pool->funcs->validate_plane) 300662c933f9SYongqiang Sun return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps); 3007792671d7SAndrey Grodzovsky 300862c933f9SYongqiang Sun return res; 3009792671d7SAndrey Grodzovsky } 301074eac5f3SSu Sung Chung 301174eac5f3SSu Sung Chung unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format) 301274eac5f3SSu Sung Chung { 301374eac5f3SSu Sung Chung switch (format) { 301474eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 301574eac5f3SSu Sung Chung return 8; 301674eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 301774eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 301874eac5f3SSu Sung Chung return 12; 301974eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 302074eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 302174eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 302274eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 302374eac5f3SSu Sung Chung return 16; 302474eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 302574eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 302674eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 302774eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 302874eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 302920f2ffe5SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN) 30305dba4991SBhawanpreet Lakha case SURFACE_PIXEL_FORMAT_GRPH_RGBE: 30315dba4991SBhawanpreet Lakha case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA: 30325dba4991SBhawanpreet Lakha #endif 303374eac5f3SSu Sung Chung return 32; 303474eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 3035050cd3d6SMario Kleiner case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: 303674eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 303774eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 303874eac5f3SSu Sung Chung return 64; 303974eac5f3SSu Sung Chung default: 304074eac5f3SSu Sung Chung ASSERT_CRITICAL(false); 304174eac5f3SSu Sung Chung return -1; 304274eac5f3SSu Sung Chung } 304374eac5f3SSu Sung Chung } 30443ab4cc65SCharlene Liu static unsigned int get_max_audio_sample_rate(struct audio_mode *modes) 30453ab4cc65SCharlene Liu { 30463ab4cc65SCharlene Liu if (modes) { 30473ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_192) 30483ab4cc65SCharlene Liu return 192000; 30493ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_176_4) 30503ab4cc65SCharlene Liu return 176400; 30513ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_96) 30523ab4cc65SCharlene Liu return 96000; 30533ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_88_2) 30543ab4cc65SCharlene Liu return 88200; 30553ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_48) 30563ab4cc65SCharlene Liu return 48000; 30573ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_44_1) 30583ab4cc65SCharlene Liu return 44100; 30593ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_32) 30603ab4cc65SCharlene Liu return 32000; 30613ab4cc65SCharlene Liu } 30623ab4cc65SCharlene Liu /*original logic when no audio info*/ 30633ab4cc65SCharlene Liu return 441000; 30643ab4cc65SCharlene Liu } 30653ab4cc65SCharlene Liu 30663ab4cc65SCharlene Liu void get_audio_check(struct audio_info *aud_modes, 30673ab4cc65SCharlene Liu struct audio_check *audio_chk) 30683ab4cc65SCharlene Liu { 30693ab4cc65SCharlene Liu unsigned int i; 30703ab4cc65SCharlene Liu unsigned int max_sample_rate = 0; 30713ab4cc65SCharlene Liu 30723ab4cc65SCharlene Liu if (aud_modes) { 30733ab4cc65SCharlene Liu audio_chk->audio_packet_type = 0x2;/*audio sample packet AP = .25 for layout0, 1 for layout1*/ 30743ab4cc65SCharlene Liu 30753ab4cc65SCharlene Liu audio_chk->max_audiosample_rate = 0; 30763ab4cc65SCharlene Liu for (i = 0; i < aud_modes->mode_count; i++) { 30773ab4cc65SCharlene Liu max_sample_rate = get_max_audio_sample_rate(&aud_modes->modes[i]); 30783ab4cc65SCharlene Liu if (audio_chk->max_audiosample_rate < max_sample_rate) 30793ab4cc65SCharlene Liu audio_chk->max_audiosample_rate = max_sample_rate; 30803ab4cc65SCharlene Liu /*dts takes the same as type 2: AP = 0.25*/ 30813ab4cc65SCharlene Liu } 30823ab4cc65SCharlene Liu /*check which one take more bandwidth*/ 30833ab4cc65SCharlene Liu if (audio_chk->max_audiosample_rate > 192000) 30843ab4cc65SCharlene Liu audio_chk->audio_packet_type = 0x9;/*AP =1*/ 30853ab4cc65SCharlene Liu audio_chk->acat = 0;/*not support*/ 30863ab4cc65SCharlene Liu } 30873ab4cc65SCharlene Liu } 30883ab4cc65SCharlene Liu 3089f01ee019SFangzhi Zuo #if defined(CONFIG_DRM_AMD_DC_DCN) 3090f01ee019SFangzhi Zuo struct hpo_dp_link_encoder *resource_get_unused_hpo_dp_link_encoder( 3091f01ee019SFangzhi Zuo const struct resource_pool *pool) 3092f01ee019SFangzhi Zuo { 3093f01ee019SFangzhi Zuo uint8_t i; 3094f01ee019SFangzhi Zuo struct hpo_dp_link_encoder *enc = NULL; 3095f01ee019SFangzhi Zuo 3096f01ee019SFangzhi Zuo ASSERT(pool->hpo_dp_link_enc_count <= MAX_HPO_DP2_LINK_ENCODERS); 3097f01ee019SFangzhi Zuo 3098f01ee019SFangzhi Zuo for (i = 0; i < pool->hpo_dp_link_enc_count; i++) { 3099f01ee019SFangzhi Zuo if (pool->hpo_dp_link_enc[i]->transmitter == TRANSMITTER_UNKNOWN) { 3100f01ee019SFangzhi Zuo enc = pool->hpo_dp_link_enc[i]; 3101f01ee019SFangzhi Zuo break; 3102f01ee019SFangzhi Zuo } 3103f01ee019SFangzhi Zuo } 3104f01ee019SFangzhi Zuo 3105f01ee019SFangzhi Zuo return enc; 3106f01ee019SFangzhi Zuo } 3107f01ee019SFangzhi Zuo #endif 3108