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" 444562236bSHarry Wentland 45683b5950SMauro Rossi #if defined(CONFIG_DRM_AMD_DC_SI) 46683b5950SMauro Rossi #include "dce60/dce60_resource.h" 47683b5950SMauro Rossi #endif 484562236bSHarry Wentland #include "dce80/dce80_resource.h" 494562236bSHarry Wentland #include "dce100/dce100_resource.h" 504562236bSHarry Wentland #include "dce110/dce110_resource.h" 514562236bSHarry Wentland #include "dce112/dce112_resource.h" 52cf2156e2SAlex Deucher #include "dce120/dce120_resource.h" 53b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 54ff5ef992SAlex Deucher #include "dcn10/dcn10_resource.h" 557ed4e635SHarry Wentland #include "dcn20/dcn20_resource.h" 56e22ece54SBhawanpreet Lakha #include "dcn21/dcn21_resource.h" 5720f2ffe5SAlex Deucher #include "dcn30/dcn30_resource.h" 5820f2ffe5SAlex Deucher #include "dcn301/dcn301_resource.h" 5920f2ffe5SAlex Deucher #include "dcn302/dcn302_resource.h" 60cd6d421eSAurabindo Pillai #include "dcn303/dcn303_resource.h" 612083640fSNicholas Kazlauskas #if defined(CONFIG_DRM_AMD_DC_DCN3_1) 622083640fSNicholas Kazlauskas #include "../dcn31/dcn31_resource.h" 632083640fSNicholas Kazlauskas #endif 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; 1443a83e4e6SRoman Li #endif 1452083640fSNicholas Kazlauskas 1462083640fSNicholas Kazlauskas #if defined(CONFIG_DRM_AMD_DC_DCN3_1) 1472083640fSNicholas Kazlauskas case FAMILY_YELLOW_CARP: 1482083640fSNicholas Kazlauskas if (ASICREV_IS_YELLOW_CARP(asic_id.hw_internal_rev)) 1492083640fSNicholas Kazlauskas dc_version = DCN_VERSION_3_1; 1502083640fSNicholas Kazlauskas break; 1512083640fSNicholas Kazlauskas #endif 1522083640fSNicholas Kazlauskas 1534562236bSHarry Wentland default: 1544562236bSHarry Wentland dc_version = DCE_VERSION_UNKNOWN; 1554562236bSHarry Wentland break; 1564562236bSHarry Wentland } 1574562236bSHarry Wentland return dc_version; 1584562236bSHarry Wentland } 1594562236bSHarry Wentland 160d9673c92SHarry Wentland struct resource_pool *dc_create_resource_pool(struct dc *dc, 161d9673c92SHarry Wentland const struct dc_init_data *init_data, 162d9673c92SHarry Wentland enum dce_version dc_version) 1634562236bSHarry Wentland { 1645ac3d3c9SCharlene Liu struct resource_pool *res_pool = NULL; 1654562236bSHarry Wentland 1664562236bSHarry Wentland switch (dc_version) { 167683b5950SMauro Rossi #if defined(CONFIG_DRM_AMD_DC_SI) 168683b5950SMauro Rossi case DCE_VERSION_6_0: 169683b5950SMauro Rossi res_pool = dce60_create_resource_pool( 170683b5950SMauro Rossi init_data->num_virtual_links, dc); 171683b5950SMauro Rossi break; 172683b5950SMauro Rossi case DCE_VERSION_6_1: 173683b5950SMauro Rossi res_pool = dce61_create_resource_pool( 174683b5950SMauro Rossi init_data->num_virtual_links, dc); 175683b5950SMauro Rossi break; 176683b5950SMauro Rossi case DCE_VERSION_6_4: 177683b5950SMauro Rossi res_pool = dce64_create_resource_pool( 178683b5950SMauro Rossi init_data->num_virtual_links, dc); 179683b5950SMauro Rossi break; 180683b5950SMauro Rossi #endif 1814562236bSHarry Wentland case DCE_VERSION_8_0: 1825ac3d3c9SCharlene Liu res_pool = dce80_create_resource_pool( 183d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1845ac3d3c9SCharlene Liu break; 1857992a629SAlex Deucher case DCE_VERSION_8_1: 1867992a629SAlex Deucher res_pool = dce81_create_resource_pool( 187d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1887992a629SAlex Deucher break; 1897992a629SAlex Deucher case DCE_VERSION_8_3: 1907992a629SAlex Deucher res_pool = dce83_create_resource_pool( 191d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1927992a629SAlex Deucher break; 1934562236bSHarry Wentland case DCE_VERSION_10_0: 1945ac3d3c9SCharlene Liu res_pool = dce100_create_resource_pool( 195d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1965ac3d3c9SCharlene Liu break; 1974562236bSHarry Wentland case DCE_VERSION_11_0: 1985ac3d3c9SCharlene Liu res_pool = dce110_create_resource_pool( 199d9673c92SHarry Wentland init_data->num_virtual_links, dc, 200d9673c92SHarry Wentland init_data->asic_id); 2015ac3d3c9SCharlene Liu break; 2024562236bSHarry Wentland case DCE_VERSION_11_2: 2030c75d5acSJerry (Fangzhi) Zuo case DCE_VERSION_11_22: 2045ac3d3c9SCharlene Liu res_pool = dce112_create_resource_pool( 205d9673c92SHarry Wentland init_data->num_virtual_links, dc); 2065ac3d3c9SCharlene Liu break; 2072c8ad2d5SAlex Deucher case DCE_VERSION_12_0: 208b8b6ce89SLeo Li case DCE_VERSION_12_1: 2092c8ad2d5SAlex Deucher res_pool = dce120_create_resource_pool( 210d9673c92SHarry Wentland init_data->num_virtual_links, dc); 2112c8ad2d5SAlex Deucher break; 212ff5ef992SAlex Deucher 213b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 214ff5ef992SAlex Deucher case DCN_VERSION_1_0: 2150e3d73f1SBhawanpreet Lakha case DCN_VERSION_1_01: 216d9673c92SHarry Wentland res_pool = dcn10_create_resource_pool(init_data, dc); 217ff5ef992SAlex Deucher break; 2187ed4e635SHarry Wentland case DCN_VERSION_2_0: 2197ed4e635SHarry Wentland res_pool = dcn20_create_resource_pool(init_data, dc); 2207ed4e635SHarry Wentland break; 221e22ece54SBhawanpreet Lakha case DCN_VERSION_2_1: 222e22ece54SBhawanpreet Lakha res_pool = dcn21_create_resource_pool(init_data, dc); 223e22ece54SBhawanpreet Lakha break; 2245dba4991SBhawanpreet Lakha case DCN_VERSION_3_0: 2255dba4991SBhawanpreet Lakha res_pool = dcn30_create_resource_pool(init_data, dc); 2265dba4991SBhawanpreet Lakha break; 2273a83e4e6SRoman Li case DCN_VERSION_3_01: 2283a83e4e6SRoman Li res_pool = dcn301_create_resource_pool(init_data, dc); 2293a83e4e6SRoman Li break; 23036d26912SBhawanpreet Lakha case DCN_VERSION_3_02: 23136d26912SBhawanpreet Lakha res_pool = dcn302_create_resource_pool(init_data, dc); 23236d26912SBhawanpreet Lakha break; 233cd6d421eSAurabindo Pillai case DCN_VERSION_3_03: 234cd6d421eSAurabindo Pillai res_pool = dcn303_create_resource_pool(init_data, dc); 235cd6d421eSAurabindo Pillai break; 2362083640fSNicholas Kazlauskas #if defined(CONFIG_DRM_AMD_DC_DCN3_1) 2372083640fSNicholas Kazlauskas case DCN_VERSION_3_1: 2382083640fSNicholas Kazlauskas res_pool = dcn31_create_resource_pool(init_data, dc); 2392083640fSNicholas Kazlauskas break; 2402083640fSNicholas Kazlauskas #endif 24136d26912SBhawanpreet Lakha #endif 2424562236bSHarry Wentland default: 2434562236bSHarry Wentland break; 2444562236bSHarry Wentland } 245f49cfa27Shersen wu 2465ac3d3c9SCharlene Liu if (res_pool != NULL) { 2479adc8050SDmytro Laktyushkin if (dc->ctx->dc_bios->fw_info_valid) { 24841a5a2a8Shersen wu res_pool->ref_clocks.xtalin_clock_inKhz = 2499adc8050SDmytro Laktyushkin dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency; 25041a5a2a8Shersen wu /* initialize with firmware data first, no all 25141a5a2a8Shersen wu * ASIC have DCCG SW component. FPGA or 25241a5a2a8Shersen wu * simulation need initialization of 25341a5a2a8Shersen wu * dccg_ref_clock_inKhz, dchub_ref_clock_inKhz 25441a5a2a8Shersen wu * with xtalin_clock_inKhz 25541a5a2a8Shersen wu */ 25641a5a2a8Shersen wu res_pool->ref_clocks.dccg_ref_clock_inKhz = 25741a5a2a8Shersen wu res_pool->ref_clocks.xtalin_clock_inKhz; 25841a5a2a8Shersen wu res_pool->ref_clocks.dchub_ref_clock_inKhz = 25941a5a2a8Shersen wu res_pool->ref_clocks.xtalin_clock_inKhz; 2605ac3d3c9SCharlene Liu } else 2615ac3d3c9SCharlene Liu ASSERT_CRITICAL(false); 2625ac3d3c9SCharlene Liu } 2635ac3d3c9SCharlene Liu 2645ac3d3c9SCharlene Liu return res_pool; 2654562236bSHarry Wentland } 2664562236bSHarry Wentland 267fb3466a4SBhawanpreet Lakha void dc_destroy_resource_pool(struct dc *dc) 2684562236bSHarry Wentland { 2694562236bSHarry Wentland if (dc) { 2704562236bSHarry Wentland if (dc->res_pool) 2714562236bSHarry Wentland dc->res_pool->funcs->destroy(&dc->res_pool); 2724562236bSHarry Wentland 2732004f45eSHarry Wentland kfree(dc->hwseq); 2744562236bSHarry Wentland } 2754562236bSHarry Wentland } 2764562236bSHarry Wentland 2774562236bSHarry Wentland static void update_num_audio( 2784562236bSHarry Wentland const struct resource_straps *straps, 2794562236bSHarry Wentland unsigned int *num_audio, 2804562236bSHarry Wentland struct audio_support *aud_support) 2814562236bSHarry Wentland { 2824562236bSHarry Wentland aud_support->dp_audio = true; 283b8e9eb72SCharlene Liu aud_support->hdmi_audio_native = false; 284b8e9eb72SCharlene Liu aud_support->hdmi_audio_on_dongle = false; 285b8e9eb72SCharlene Liu 286b8e9eb72SCharlene Liu if (straps->hdmi_disable == 0) { 2874562236bSHarry Wentland if (straps->dc_pinstraps_audio & 0x2) { 2884562236bSHarry Wentland aud_support->hdmi_audio_on_dongle = true; 289b8e9eb72SCharlene Liu aud_support->hdmi_audio_native = true; 2904562236bSHarry Wentland } 2914562236bSHarry Wentland } 2924562236bSHarry Wentland 2934562236bSHarry Wentland switch (straps->audio_stream_number) { 2944562236bSHarry Wentland case 0: /* multi streams supported */ 2954562236bSHarry Wentland break; 2964562236bSHarry Wentland case 1: /* multi streams not supported */ 2974562236bSHarry Wentland *num_audio = 1; 2984562236bSHarry Wentland break; 2994562236bSHarry Wentland default: 3004562236bSHarry Wentland DC_ERR("DC: unexpected audio fuse!\n"); 30117a96033SJulia Lawall } 3024562236bSHarry Wentland } 3034562236bSHarry Wentland 3044562236bSHarry Wentland bool resource_construct( 3054562236bSHarry Wentland unsigned int num_virtual_links, 306fb3466a4SBhawanpreet Lakha struct dc *dc, 3074562236bSHarry Wentland struct resource_pool *pool, 3084562236bSHarry Wentland const struct resource_create_funcs *create_funcs) 3094562236bSHarry Wentland { 3104562236bSHarry Wentland struct dc_context *ctx = dc->ctx; 3114562236bSHarry Wentland const struct resource_caps *caps = pool->res_cap; 3124562236bSHarry Wentland int i; 3134562236bSHarry Wentland unsigned int num_audio = caps->num_audio; 3144562236bSHarry Wentland struct resource_straps straps = {0}; 3154562236bSHarry Wentland 3164562236bSHarry Wentland if (create_funcs->read_dce_straps) 3174562236bSHarry Wentland create_funcs->read_dce_straps(dc->ctx, &straps); 3184562236bSHarry Wentland 3194562236bSHarry Wentland pool->audio_count = 0; 3204562236bSHarry Wentland if (create_funcs->create_audio) { 3214562236bSHarry Wentland /* find the total number of streams available via the 3224562236bSHarry Wentland * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT 3234562236bSHarry Wentland * registers (one for each pin) starting from pin 1 3244562236bSHarry Wentland * up to the max number of audio pins. 3254562236bSHarry Wentland * We stop on the first pin where 3264562236bSHarry Wentland * PORT_CONNECTIVITY == 1 (as instructed by HW team). 3274562236bSHarry Wentland */ 3284562236bSHarry Wentland update_num_audio(&straps, &num_audio, &pool->audio_support); 3295feb9f07STai Man for (i = 0; i < caps->num_audio; i++) { 3304562236bSHarry Wentland struct audio *aud = create_funcs->create_audio(ctx, i); 3314562236bSHarry Wentland 3324562236bSHarry Wentland if (aud == NULL) { 3334562236bSHarry Wentland DC_ERR("DC: failed to create audio!\n"); 3344562236bSHarry Wentland return false; 3354562236bSHarry Wentland } 3364562236bSHarry Wentland if (!aud->funcs->endpoint_valid(aud)) { 3374562236bSHarry Wentland aud->funcs->destroy(&aud); 3384562236bSHarry Wentland break; 3394562236bSHarry Wentland } 3404562236bSHarry Wentland pool->audios[i] = aud; 3414562236bSHarry Wentland pool->audio_count++; 3424562236bSHarry Wentland } 3434562236bSHarry Wentland } 3444562236bSHarry Wentland 3454562236bSHarry Wentland pool->stream_enc_count = 0; 3464562236bSHarry Wentland if (create_funcs->create_stream_encoder) { 3474562236bSHarry Wentland for (i = 0; i < caps->num_stream_encoder; i++) { 3484562236bSHarry Wentland pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx); 3494562236bSHarry Wentland if (pool->stream_enc[i] == NULL) 3504562236bSHarry Wentland DC_ERR("DC: failed to create stream_encoder!\n"); 3514562236bSHarry Wentland pool->stream_enc_count++; 3524562236bSHarry Wentland } 3534562236bSHarry Wentland } 354929c3aaaSEric Bernstein 35520f2ffe5SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN) 3565dba4991SBhawanpreet Lakha for (i = 0; i < caps->num_mpc_3dlut; i++) { 3575dba4991SBhawanpreet Lakha pool->mpc_lut[i] = dc_create_3dlut_func(); 3585dba4991SBhawanpreet Lakha if (pool->mpc_lut[i] == NULL) 3595dba4991SBhawanpreet Lakha DC_ERR("DC: failed to create MPC 3dlut!\n"); 3605dba4991SBhawanpreet Lakha pool->mpc_shaper[i] = dc_create_transfer_func(); 3615dba4991SBhawanpreet Lakha if (pool->mpc_shaper[i] == NULL) 3625dba4991SBhawanpreet Lakha DC_ERR("DC: failed to create MPC shaper!\n"); 3635dba4991SBhawanpreet Lakha } 3645dba4991SBhawanpreet Lakha #endif 3654176664bSCharlene Liu dc->caps.dynamic_audio = false; 3664176664bSCharlene Liu if (pool->audio_count < pool->stream_enc_count) { 3674176664bSCharlene Liu dc->caps.dynamic_audio = true; 3684176664bSCharlene Liu } 3694562236bSHarry Wentland for (i = 0; i < num_virtual_links; i++) { 3704562236bSHarry Wentland pool->stream_enc[pool->stream_enc_count] = 3714562236bSHarry Wentland virtual_stream_encoder_create( 3724562236bSHarry Wentland ctx, ctx->dc_bios); 3734562236bSHarry Wentland if (pool->stream_enc[pool->stream_enc_count] == NULL) { 3744562236bSHarry Wentland DC_ERR("DC: failed to create stream_encoder!\n"); 3754562236bSHarry Wentland return false; 3764562236bSHarry Wentland } 3774562236bSHarry Wentland pool->stream_enc_count++; 3784562236bSHarry Wentland } 3794562236bSHarry Wentland 3804562236bSHarry Wentland dc->hwseq = create_funcs->create_hwseq(ctx); 3814562236bSHarry Wentland 3824562236bSHarry Wentland return true; 3834562236bSHarry Wentland } 384ad8960a6SMikita Lipski static int find_matching_clock_source( 385ad8960a6SMikita Lipski const struct resource_pool *pool, 386ad8960a6SMikita Lipski struct clock_source *clock_source) 387ad8960a6SMikita Lipski { 3884562236bSHarry Wentland 389ad8960a6SMikita Lipski int i; 390ad8960a6SMikita Lipski 391ad8960a6SMikita Lipski for (i = 0; i < pool->clk_src_count; i++) { 392ad8960a6SMikita Lipski if (pool->clock_sources[i] == clock_source) 393ad8960a6SMikita Lipski return i; 394ad8960a6SMikita Lipski } 395ad8960a6SMikita Lipski return -1; 396ad8960a6SMikita Lipski } 3974562236bSHarry Wentland 39821e67d4dSHarry Wentland void resource_unreference_clock_source( 3994562236bSHarry Wentland struct resource_context *res_ctx, 400a2b8659dSTony Cheng const struct resource_pool *pool, 4014a629536SHarry Wentland struct clock_source *clock_source) 4024562236bSHarry Wentland { 403ad8960a6SMikita Lipski int i = find_matching_clock_source(pool, clock_source); 4044a629536SHarry Wentland 405ad8960a6SMikita Lipski if (i > -1) 4064562236bSHarry Wentland res_ctx->clock_source_ref_count[i]--; 4074562236bSHarry Wentland 40821e67d4dSHarry Wentland if (pool->dp_clock_source == clock_source) 4094562236bSHarry Wentland res_ctx->dp_clock_source_ref_count--; 4104562236bSHarry Wentland } 4114562236bSHarry Wentland 4124562236bSHarry Wentland void resource_reference_clock_source( 4134562236bSHarry Wentland struct resource_context *res_ctx, 414a2b8659dSTony Cheng const struct resource_pool *pool, 4154562236bSHarry Wentland struct clock_source *clock_source) 4164562236bSHarry Wentland { 417ad8960a6SMikita Lipski int i = find_matching_clock_source(pool, clock_source); 4184562236bSHarry Wentland 419ad8960a6SMikita Lipski if (i > -1) 4204562236bSHarry Wentland res_ctx->clock_source_ref_count[i]++; 4214562236bSHarry Wentland 422a2b8659dSTony Cheng if (pool->dp_clock_source == clock_source) 4234562236bSHarry Wentland res_ctx->dp_clock_source_ref_count++; 4244562236bSHarry Wentland } 4254562236bSHarry Wentland 426ad8960a6SMikita Lipski int resource_get_clock_source_reference( 427ad8960a6SMikita Lipski struct resource_context *res_ctx, 428ad8960a6SMikita Lipski const struct resource_pool *pool, 429ad8960a6SMikita Lipski struct clock_source *clock_source) 430ad8960a6SMikita Lipski { 431ad8960a6SMikita Lipski int i = find_matching_clock_source(pool, clock_source); 432ad8960a6SMikita Lipski 433ad8960a6SMikita Lipski if (i > -1) 434ad8960a6SMikita Lipski return res_ctx->clock_source_ref_count[i]; 435ad8960a6SMikita Lipski 436ad8960a6SMikita Lipski if (pool->dp_clock_source == clock_source) 437ad8960a6SMikita Lipski return res_ctx->dp_clock_source_ref_count; 438ad8960a6SMikita Lipski 439ad8960a6SMikita Lipski return -1; 440ad8960a6SMikita Lipski } 441ad8960a6SMikita Lipski 44277a2b726SVladimir Stempen bool resource_are_vblanks_synchronizable( 44377a2b726SVladimir Stempen struct dc_stream_state *stream1, 44477a2b726SVladimir Stempen struct dc_stream_state *stream2) 44577a2b726SVladimir Stempen { 44677a2b726SVladimir Stempen uint32_t base60_refresh_rates[] = {10, 20, 5}; 44777a2b726SVladimir Stempen uint8_t i; 44877a2b726SVladimir Stempen uint8_t rr_count = sizeof(base60_refresh_rates)/sizeof(base60_refresh_rates[0]); 449783bf403SVladimir Stempen uint64_t frame_time_diff; 45077a2b726SVladimir Stempen 45177a2b726SVladimir Stempen if (stream1->ctx->dc->config.vblank_alignment_dto_params && 45277a2b726SVladimir Stempen stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0 && 45377a2b726SVladimir Stempen dc_is_dp_signal(stream1->signal) && 45477a2b726SVladimir Stempen dc_is_dp_signal(stream2->signal) && 45577a2b726SVladimir Stempen false == stream1->has_non_synchronizable_pclk && 45677a2b726SVladimir Stempen false == stream2->has_non_synchronizable_pclk && 45777a2b726SVladimir Stempen stream1->timing.flags.VBLANK_SYNCHRONIZABLE && 45877a2b726SVladimir Stempen stream2->timing.flags.VBLANK_SYNCHRONIZABLE) { 45977a2b726SVladimir Stempen /* disable refresh rates higher than 60Hz for now */ 46077a2b726SVladimir Stempen if (stream1->timing.pix_clk_100hz*100/stream1->timing.h_total/ 46177a2b726SVladimir Stempen stream1->timing.v_total > 60) 46277a2b726SVladimir Stempen return false; 46377a2b726SVladimir Stempen if (stream2->timing.pix_clk_100hz*100/stream2->timing.h_total/ 46477a2b726SVladimir Stempen stream2->timing.v_total > 60) 46577a2b726SVladimir Stempen return false; 466783bf403SVladimir Stempen frame_time_diff = (uint64_t)10000 * 46777a2b726SVladimir Stempen stream1->timing.h_total * 46877a2b726SVladimir Stempen stream1->timing.v_total * 469783bf403SVladimir Stempen stream2->timing.pix_clk_100hz; 470783bf403SVladimir Stempen frame_time_diff = div_u64(frame_time_diff, stream1->timing.pix_clk_100hz); 471783bf403SVladimir Stempen frame_time_diff = div_u64(frame_time_diff, stream2->timing.h_total); 472783bf403SVladimir Stempen frame_time_diff = div_u64(frame_time_diff, stream2->timing.v_total); 47377a2b726SVladimir Stempen for (i = 0; i < rr_count; i++) { 474783bf403SVladimir Stempen int64_t diff = (int64_t)div_u64(frame_time_diff * base60_refresh_rates[i], 10) - 10000; 47577a2b726SVladimir Stempen 47677a2b726SVladimir Stempen if (diff < 0) 47777a2b726SVladimir Stempen diff = -diff; 47877a2b726SVladimir Stempen if (diff < stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff) 47977a2b726SVladimir Stempen return true; 48077a2b726SVladimir Stempen } 48177a2b726SVladimir Stempen } 48277a2b726SVladimir Stempen return false; 48377a2b726SVladimir Stempen } 48477a2b726SVladimir Stempen 4854562236bSHarry Wentland bool resource_are_streams_timing_synchronizable( 4860971c40eSHarry Wentland struct dc_stream_state *stream1, 4870971c40eSHarry Wentland struct dc_stream_state *stream2) 4884562236bSHarry Wentland { 4894fa086b9SLeo (Sunpeng) Li if (stream1->timing.h_total != stream2->timing.h_total) 4904562236bSHarry Wentland return false; 4914562236bSHarry Wentland 4924fa086b9SLeo (Sunpeng) Li if (stream1->timing.v_total != stream2->timing.v_total) 4934562236bSHarry Wentland return false; 4944562236bSHarry Wentland 4954fa086b9SLeo (Sunpeng) Li if (stream1->timing.h_addressable 4964fa086b9SLeo (Sunpeng) Li != stream2->timing.h_addressable) 4974562236bSHarry Wentland return false; 4984562236bSHarry Wentland 4994fa086b9SLeo (Sunpeng) Li if (stream1->timing.v_addressable 5004fa086b9SLeo (Sunpeng) Li != stream2->timing.v_addressable) 5014562236bSHarry Wentland return false; 5024562236bSHarry Wentland 5038582aea2SDavid Galiffi if (stream1->timing.v_front_porch 5048582aea2SDavid Galiffi != stream2->timing.v_front_porch) 5058582aea2SDavid Galiffi return false; 5068582aea2SDavid Galiffi 507380604e2SKen Chalmers if (stream1->timing.pix_clk_100hz 508380604e2SKen Chalmers != stream2->timing.pix_clk_100hz) 5094562236bSHarry Wentland return false; 5104562236bSHarry Wentland 5113e27e10eSMikita Lipski if (stream1->clamping.c_depth != stream2->clamping.c_depth) 5123e27e10eSMikita Lipski return false; 5133e27e10eSMikita Lipski 5144562236bSHarry Wentland if (stream1->phy_pix_clk != stream2->phy_pix_clk 5157e2fe319SCharlene Liu && (!dc_is_dp_signal(stream1->signal) 5167e2fe319SCharlene Liu || !dc_is_dp_signal(stream2->signal))) 5174562236bSHarry Wentland return false; 5184562236bSHarry Wentland 519d77f778eSCharlene Liu if (stream1->view_format != stream2->view_format) 520d77f778eSCharlene Liu return false; 521d77f778eSCharlene Liu 5220460f9abSJun Lei if (stream1->ignore_msa_timing_param || stream2->ignore_msa_timing_param) 5230460f9abSJun Lei return false; 5240460f9abSJun Lei 5254562236bSHarry Wentland return true; 5264562236bSHarry Wentland } 5273e27e10eSMikita Lipski static bool is_dp_and_hdmi_sharable( 5283e27e10eSMikita Lipski struct dc_stream_state *stream1, 5293e27e10eSMikita Lipski struct dc_stream_state *stream2) 5303e27e10eSMikita Lipski { 5313e27e10eSMikita Lipski if (stream1->ctx->dc->caps.disable_dp_clk_share) 5323e27e10eSMikita Lipski return false; 5333e27e10eSMikita Lipski 5343e27e10eSMikita Lipski if (stream1->clamping.c_depth != COLOR_DEPTH_888 || 5353e27e10eSMikita Lipski stream2->clamping.c_depth != COLOR_DEPTH_888) 5363e27e10eSMikita Lipski return false; 5373e27e10eSMikita Lipski 5383e27e10eSMikita Lipski return true; 5393e27e10eSMikita Lipski 5403e27e10eSMikita Lipski } 5414562236bSHarry Wentland 5424562236bSHarry Wentland static bool is_sharable_clk_src( 5434562236bSHarry Wentland const struct pipe_ctx *pipe_with_clk_src, 5444562236bSHarry Wentland const struct pipe_ctx *pipe) 5454562236bSHarry Wentland { 5464562236bSHarry Wentland if (pipe_with_clk_src->clock_source == NULL) 5474562236bSHarry Wentland return false; 5484562236bSHarry Wentland 5494562236bSHarry Wentland if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL) 5504562236bSHarry Wentland return false; 5514562236bSHarry Wentland 5523e27e10eSMikita Lipski if (dc_is_dp_signal(pipe_with_clk_src->stream->signal) || 5533e27e10eSMikita Lipski (dc_is_dp_signal(pipe->stream->signal) && 5543e27e10eSMikita Lipski !is_dp_and_hdmi_sharable(pipe_with_clk_src->stream, 5553e27e10eSMikita Lipski pipe->stream))) 5564562236bSHarry Wentland return false; 5574562236bSHarry Wentland 5584562236bSHarry Wentland if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal) 559fc69009eSMikita Lipski && dc_is_dual_link_signal(pipe->stream->signal)) 5604562236bSHarry Wentland return false; 5614562236bSHarry Wentland 5624562236bSHarry Wentland if (dc_is_hdmi_signal(pipe->stream->signal) 563fc69009eSMikita Lipski && dc_is_dual_link_signal(pipe_with_clk_src->stream->signal)) 5644562236bSHarry Wentland return false; 5654562236bSHarry Wentland 5664562236bSHarry Wentland if (!resource_are_streams_timing_synchronizable( 5674562236bSHarry Wentland pipe_with_clk_src->stream, pipe->stream)) 5684562236bSHarry Wentland return false; 5694562236bSHarry Wentland 5704562236bSHarry Wentland return true; 5714562236bSHarry Wentland } 5724562236bSHarry Wentland 5734562236bSHarry Wentland struct clock_source *resource_find_used_clk_src_for_sharing( 5744562236bSHarry Wentland struct resource_context *res_ctx, 5754562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 5764562236bSHarry Wentland { 5774562236bSHarry Wentland int i; 5784562236bSHarry Wentland 5794562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 5804562236bSHarry Wentland if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx)) 5814562236bSHarry Wentland return res_ctx->pipe_ctx[i].clock_source; 5824562236bSHarry Wentland } 5834562236bSHarry Wentland 5844562236bSHarry Wentland return NULL; 5854562236bSHarry Wentland } 5864562236bSHarry Wentland 5874562236bSHarry Wentland static enum pixel_format convert_pixel_format_to_dalsurface( 5884562236bSHarry Wentland enum surface_pixel_format surface_pixel_format) 5894562236bSHarry Wentland { 5904562236bSHarry Wentland enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 5914562236bSHarry Wentland 5924562236bSHarry Wentland switch (surface_pixel_format) { 5934562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 5944562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_INDEX8; 5954562236bSHarry Wentland break; 5964562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 5974562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_RGB565; 5984562236bSHarry Wentland break; 5994562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 6004562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_RGB565; 6014562236bSHarry Wentland break; 6024562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 6034562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB8888; 6044562236bSHarry Wentland break; 6058693049aSTony Cheng case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 6064562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB8888; 6074562236bSHarry Wentland break; 6084562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 6094562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 6104562236bSHarry Wentland break; 6114562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 6124562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 6134562236bSHarry Wentland break; 6144562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 6154562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS; 6164562236bSHarry Wentland break; 6174562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 6184562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 6194562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_FP16; 6204562236bSHarry Wentland break; 6214562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 6224562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 62387449a90SAnthony Koo dal_pixel_format = PIXEL_FORMAT_420BPP8; 6244562236bSHarry Wentland break; 625ffbcd19aSVitaly Prosyak case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 626ffbcd19aSVitaly Prosyak case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 62787449a90SAnthony Koo dal_pixel_format = PIXEL_FORMAT_420BPP10; 628ffbcd19aSVitaly Prosyak break; 6294562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 630050cd3d6SMario Kleiner case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: 6314562236bSHarry Wentland default: 6324562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 6334562236bSHarry Wentland break; 6344562236bSHarry Wentland } 6354562236bSHarry Wentland return dal_pixel_format; 6364562236bSHarry Wentland } 6374562236bSHarry Wentland 6389b6067c0SDmytro Laktyushkin static inline void get_vp_scan_direction( 6399b6067c0SDmytro Laktyushkin enum dc_rotation_angle rotation, 6409b6067c0SDmytro Laktyushkin bool horizontal_mirror, 6419b6067c0SDmytro Laktyushkin bool *orthogonal_rotation, 6429b6067c0SDmytro Laktyushkin bool *flip_vert_scan_dir, 6439b6067c0SDmytro Laktyushkin bool *flip_horz_scan_dir) 6444562236bSHarry Wentland { 6459b6067c0SDmytro Laktyushkin *orthogonal_rotation = false; 6469b6067c0SDmytro Laktyushkin *flip_vert_scan_dir = false; 6479b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = false; 6489b6067c0SDmytro Laktyushkin if (rotation == ROTATION_ANGLE_180) { 6499b6067c0SDmytro Laktyushkin *flip_vert_scan_dir = true; 6509b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = true; 6519b6067c0SDmytro Laktyushkin } else if (rotation == ROTATION_ANGLE_90) { 6529b6067c0SDmytro Laktyushkin *orthogonal_rotation = true; 6539b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = true; 6549b6067c0SDmytro Laktyushkin } else if (rotation == ROTATION_ANGLE_270) { 6559b6067c0SDmytro Laktyushkin *orthogonal_rotation = true; 6569b6067c0SDmytro Laktyushkin *flip_vert_scan_dir = true; 6579b6067c0SDmytro Laktyushkin } 6589b6067c0SDmytro Laktyushkin 6599b6067c0SDmytro Laktyushkin if (horizontal_mirror) 6609b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = !*flip_horz_scan_dir; 6614562236bSHarry Wentland } 6624562236bSHarry Wentland 663570bc18cSDmytro Laktyushkin int get_num_mpc_splits(struct pipe_ctx *pipe) 664570bc18cSDmytro Laktyushkin { 665570bc18cSDmytro Laktyushkin int mpc_split_count = 0; 666570bc18cSDmytro Laktyushkin struct pipe_ctx *other_pipe = pipe->bottom_pipe; 667570bc18cSDmytro Laktyushkin 668570bc18cSDmytro Laktyushkin while (other_pipe && other_pipe->plane_state == pipe->plane_state) { 669570bc18cSDmytro Laktyushkin mpc_split_count++; 670570bc18cSDmytro Laktyushkin other_pipe = other_pipe->bottom_pipe; 671570bc18cSDmytro Laktyushkin } 672570bc18cSDmytro Laktyushkin other_pipe = pipe->top_pipe; 673570bc18cSDmytro Laktyushkin while (other_pipe && other_pipe->plane_state == pipe->plane_state) { 674570bc18cSDmytro Laktyushkin mpc_split_count++; 675570bc18cSDmytro Laktyushkin other_pipe = other_pipe->top_pipe; 676570bc18cSDmytro Laktyushkin } 677570bc18cSDmytro Laktyushkin 678570bc18cSDmytro Laktyushkin return mpc_split_count; 679570bc18cSDmytro Laktyushkin } 680570bc18cSDmytro Laktyushkin 681228a10d4SAlex Deucher int get_num_odm_splits(struct pipe_ctx *pipe) 682228a10d4SAlex Deucher { 683228a10d4SAlex Deucher int odm_split_count = 0; 684228a10d4SAlex Deucher struct pipe_ctx *next_pipe = pipe->next_odm_pipe; 685228a10d4SAlex Deucher while (next_pipe) { 686228a10d4SAlex Deucher odm_split_count++; 687228a10d4SAlex Deucher next_pipe = next_pipe->next_odm_pipe; 688228a10d4SAlex Deucher } 689228a10d4SAlex Deucher pipe = pipe->prev_odm_pipe; 690228a10d4SAlex Deucher while (pipe) { 691228a10d4SAlex Deucher odm_split_count++; 692228a10d4SAlex Deucher pipe = pipe->prev_odm_pipe; 693228a10d4SAlex Deucher } 694228a10d4SAlex Deucher return odm_split_count; 695228a10d4SAlex Deucher } 696228a10d4SAlex Deucher 6975bf24270SDmytro Laktyushkin static void calculate_split_count_and_index(struct pipe_ctx *pipe_ctx, int *split_count, int *split_idx) 6985bf24270SDmytro Laktyushkin { 6995bf24270SDmytro Laktyushkin *split_count = get_num_odm_splits(pipe_ctx); 7005bf24270SDmytro Laktyushkin *split_idx = 0; 7015bf24270SDmytro Laktyushkin if (*split_count == 0) { 7025bf24270SDmytro Laktyushkin /*Check for mpc split*/ 7035bf24270SDmytro Laktyushkin struct pipe_ctx *split_pipe = pipe_ctx->top_pipe; 7045bf24270SDmytro Laktyushkin 705570bc18cSDmytro Laktyushkin *split_count = get_num_mpc_splits(pipe_ctx); 7065bf24270SDmytro Laktyushkin while (split_pipe && split_pipe->plane_state == pipe_ctx->plane_state) { 7075bf24270SDmytro Laktyushkin (*split_idx)++; 7085bf24270SDmytro Laktyushkin split_pipe = split_pipe->top_pipe; 7095bf24270SDmytro Laktyushkin } 7105bf24270SDmytro Laktyushkin } else { 7115bf24270SDmytro Laktyushkin /*Get odm split index*/ 7125bf24270SDmytro Laktyushkin struct pipe_ctx *split_pipe = pipe_ctx->prev_odm_pipe; 7135bf24270SDmytro Laktyushkin 7145bf24270SDmytro Laktyushkin while (split_pipe) { 7155bf24270SDmytro Laktyushkin (*split_idx)++; 7165bf24270SDmytro Laktyushkin split_pipe = split_pipe->prev_odm_pipe; 7175bf24270SDmytro Laktyushkin } 7185bf24270SDmytro Laktyushkin } 7195bf24270SDmytro Laktyushkin } 7205bf24270SDmytro Laktyushkin 7219b6067c0SDmytro Laktyushkin /* 7226566cae7SDmytro Laktyushkin * This is a preliminary vp size calculation to allow us to check taps support. 7236566cae7SDmytro Laktyushkin * The result is completely overridden afterwards. 7249b6067c0SDmytro Laktyushkin */ 7256566cae7SDmytro Laktyushkin static void calculate_viewport_size(struct pipe_ctx *pipe_ctx) 7266566cae7SDmytro Laktyushkin { 7276566cae7SDmytro Laktyushkin struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 7289b6067c0SDmytro Laktyushkin 7296566cae7SDmytro Laktyushkin data->viewport.width = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.horz, data->recout.width)); 7306566cae7SDmytro Laktyushkin data->viewport.height = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.vert, data->recout.height)); 7316566cae7SDmytro Laktyushkin data->viewport_c.width = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.horz_c, data->recout.width)); 7326566cae7SDmytro Laktyushkin data->viewport_c.height = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.vert_c, data->recout.height)); 7336566cae7SDmytro Laktyushkin if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 7346566cae7SDmytro Laktyushkin pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) { 7356566cae7SDmytro Laktyushkin swap(data->viewport.width, data->viewport.height); 7366566cae7SDmytro Laktyushkin swap(data->viewport_c.width, data->viewport_c.height); 7379b6067c0SDmytro Laktyushkin } 738b2d0a103SDmytro Laktyushkin } 7391fbd2cfcSDmytro Laktyushkin 7409b6067c0SDmytro Laktyushkin static void calculate_recout(struct pipe_ctx *pipe_ctx) 7414562236bSHarry Wentland { 7423be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 7430971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 7445bf24270SDmytro Laktyushkin struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 7453be5262eSHarry Wentland struct rect surf_clip = plane_state->clip_rect; 7466566cae7SDmytro Laktyushkin bool split_tb = stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; 7476566cae7SDmytro Laktyushkin int split_count, split_idx; 7484562236bSHarry Wentland 7495bf24270SDmytro Laktyushkin calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); 7506566cae7SDmytro Laktyushkin if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) 7516566cae7SDmytro Laktyushkin split_idx = 0; 7525bf24270SDmytro Laktyushkin 75305e3d830SWesley Chalmers /* 75405e3d830SWesley Chalmers * Only the leftmost ODM pipe should be offset by a nonzero distance 75505e3d830SWesley Chalmers */ 7566566cae7SDmytro Laktyushkin if (!pipe_ctx->prev_odm_pipe || split_idx == split_count) { 7575bf24270SDmytro Laktyushkin data->recout.x = stream->dst.x; 7584fa086b9SLeo (Sunpeng) Li if (stream->src.x < surf_clip.x) 7595bf24270SDmytro Laktyushkin data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width 7604fa086b9SLeo (Sunpeng) Li / stream->src.width; 76125b31581SWesley Chalmers } else 76225b31581SWesley Chalmers data->recout.x = 0; 76325b31581SWesley Chalmers 76484aef2abSDmytro Laktyushkin if (stream->src.x > surf_clip.x) 76584aef2abSDmytro Laktyushkin surf_clip.width -= stream->src.x - surf_clip.x; 7665bf24270SDmytro Laktyushkin data->recout.width = surf_clip.width * stream->dst.width / stream->src.width; 7675bf24270SDmytro Laktyushkin if (data->recout.width + data->recout.x > stream->dst.x + stream->dst.width) 7685bf24270SDmytro Laktyushkin data->recout.width = stream->dst.x + stream->dst.width - data->recout.x; 7694562236bSHarry Wentland 7705bf24270SDmytro Laktyushkin data->recout.y = stream->dst.y; 7714fa086b9SLeo (Sunpeng) Li if (stream->src.y < surf_clip.y) 7725bf24270SDmytro Laktyushkin data->recout.y += (surf_clip.y - stream->src.y) * stream->dst.height 7734fa086b9SLeo (Sunpeng) Li / stream->src.height; 77484aef2abSDmytro Laktyushkin else if (stream->src.y > surf_clip.y) 77584aef2abSDmytro Laktyushkin surf_clip.height -= stream->src.y - surf_clip.y; 7764562236bSHarry Wentland 7775bf24270SDmytro Laktyushkin data->recout.height = surf_clip.height * stream->dst.height / stream->src.height; 7785bf24270SDmytro Laktyushkin if (data->recout.height + data->recout.y > stream->dst.y + stream->dst.height) 7795bf24270SDmytro Laktyushkin data->recout.height = stream->dst.y + stream->dst.height - data->recout.y; 780b2d0a103SDmytro Laktyushkin 7816566cae7SDmytro Laktyushkin /* Handle h & v split */ 7826566cae7SDmytro Laktyushkin if (split_tb) { 7836566cae7SDmytro Laktyushkin ASSERT(data->recout.height % 2 == 0); 7845bf24270SDmytro Laktyushkin data->recout.height /= 2; 7856566cae7SDmytro Laktyushkin } else if (split_count) { 7866566cae7SDmytro Laktyushkin if (!pipe_ctx->next_odm_pipe && !pipe_ctx->prev_odm_pipe) { 7875bf24270SDmytro Laktyushkin /* extra pixels in the division remainder need to go to pipes after 7885bf24270SDmytro Laktyushkin * the extra pixel index minus one(epimo) defined here as: 7895bf24270SDmytro Laktyushkin */ 7905bf24270SDmytro Laktyushkin int epimo = split_count - data->recout.width % (split_count + 1); 7915bf24270SDmytro Laktyushkin 7925bf24270SDmytro Laktyushkin data->recout.x += (data->recout.width / (split_count + 1)) * split_idx; 7935bf24270SDmytro Laktyushkin if (split_idx > epimo) 7945bf24270SDmytro Laktyushkin data->recout.x += split_idx - epimo - 1; 7956566cae7SDmytro Laktyushkin ASSERT(stream->view_format != VIEW_3D_FORMAT_SIDE_BY_SIDE || data->recout.width % 2 == 0); 7965bf24270SDmytro Laktyushkin data->recout.width = data->recout.width / (split_count + 1) + (split_idx > epimo ? 1 : 0); 7976566cae7SDmytro Laktyushkin } else { 7986566cae7SDmytro Laktyushkin /* odm */ 7996566cae7SDmytro Laktyushkin if (split_idx == split_count) { 8006566cae7SDmytro Laktyushkin /* rightmost pipe is the remainder recout */ 8016566cae7SDmytro Laktyushkin data->recout.width -= data->h_active * split_count - data->recout.x; 802*665f2850SAric Cyr 803*665f2850SAric Cyr /* ODM combine cases with MPO we can get negative widths */ 804*665f2850SAric Cyr if (data->recout.width < 0) 805*665f2850SAric Cyr data->recout.width = 0; 806*665f2850SAric Cyr 8076566cae7SDmytro Laktyushkin data->recout.x = 0; 8086566cae7SDmytro Laktyushkin } else 8096566cae7SDmytro Laktyushkin data->recout.width = data->h_active - data->recout.x; 8106566cae7SDmytro Laktyushkin } 8115bf24270SDmytro Laktyushkin } 8124562236bSHarry Wentland } 813b2d0a103SDmytro Laktyushkin 814b2d0a103SDmytro Laktyushkin static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) 8154562236bSHarry Wentland { 8163be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 8170971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 8183be5262eSHarry Wentland struct rect surf_src = plane_state->src_rect; 8194fa086b9SLeo (Sunpeng) Li const int in_w = stream->src.width; 8204fa086b9SLeo (Sunpeng) Li const int in_h = stream->src.height; 8214fa086b9SLeo (Sunpeng) Li const int out_w = stream->dst.width; 8224fa086b9SLeo (Sunpeng) Li const int out_h = stream->dst.height; 8234562236bSHarry Wentland 8249b6067c0SDmytro Laktyushkin /*Swap surf_src height and width since scaling ratios are in recout rotation*/ 8253be5262eSHarry Wentland if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 8263be5262eSHarry Wentland pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 8279b6067c0SDmytro Laktyushkin swap(surf_src.height, surf_src.width); 82886006a7fSDmytro Laktyushkin 829eb0e5154SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_from_fraction( 83086006a7fSDmytro Laktyushkin surf_src.width, 8313be5262eSHarry Wentland plane_state->dst_rect.width); 832eb0e5154SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_from_fraction( 83386006a7fSDmytro Laktyushkin surf_src.height, 8343be5262eSHarry Wentland plane_state->dst_rect.height); 8354562236bSHarry Wentland 8364fa086b9SLeo (Sunpeng) Li if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) 8376702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value *= 2; 8384fa086b9SLeo (Sunpeng) Li else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) 8396702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value *= 2; 8404562236bSHarry Wentland 8416702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value = div64_s64( 8426702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value * in_h, out_h); 8436702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value = div64_s64( 8446702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value * in_w, out_w); 8454562236bSHarry Wentland 8466702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz_c = pipe_ctx->plane_res.scl_data.ratios.horz; 8476702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert_c = pipe_ctx->plane_res.scl_data.ratios.vert; 8484562236bSHarry Wentland 8496702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP8 8506702a9acSHarry Wentland || pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP10) { 8516702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz_c.value /= 2; 8526702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert_c.value /= 2; 8534562236bSHarry Wentland } 8540002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_truncate( 8550002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz, 19); 8560002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_truncate( 8570002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert, 19); 8580002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz_c = dc_fixpt_truncate( 8590002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz_c, 19); 8600002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert_c = dc_fixpt_truncate( 8610002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert_c, 19); 8624562236bSHarry Wentland } 8634562236bSHarry Wentland 8646566cae7SDmytro Laktyushkin 8656566cae7SDmytro Laktyushkin /* 8666566cae7SDmytro Laktyushkin * We completely calculate vp offset, size and inits here based entirely on scaling 8676566cae7SDmytro Laktyushkin * ratios and recout for pixel perfect pipe combine. 8686566cae7SDmytro Laktyushkin */ 8696566cae7SDmytro Laktyushkin static void calculate_init_and_vp( 8709b6067c0SDmytro Laktyushkin bool flip_scan_dir, 8716566cae7SDmytro Laktyushkin int recout_offset_within_recout_full, 8726566cae7SDmytro Laktyushkin int recout_size, 8739b6067c0SDmytro Laktyushkin int src_size, 8749b6067c0SDmytro Laktyushkin int taps, 8759b6067c0SDmytro Laktyushkin struct fixed31_32 ratio, 8769b6067c0SDmytro Laktyushkin struct fixed31_32 *init, 8779b6067c0SDmytro Laktyushkin int *vp_offset, 8789b6067c0SDmytro Laktyushkin int *vp_size) 8794562236bSHarry Wentland { 8806566cae7SDmytro Laktyushkin struct fixed31_32 temp; 8819b6067c0SDmytro Laktyushkin int int_part; 8829b6067c0SDmytro Laktyushkin 8836566cae7SDmytro Laktyushkin /* 8846566cae7SDmytro Laktyushkin * First of the taps starts sampling pixel number <init_int_part> corresponding to recout 8856566cae7SDmytro Laktyushkin * pixel 1. Next recout pixel samples int part of <init + scaling ratio> and so on. 8866566cae7SDmytro Laktyushkin * All following calculations are based on this logic. 8876566cae7SDmytro Laktyushkin * 8886566cae7SDmytro Laktyushkin * Init calculated according to formula: 8896566cae7SDmytro Laktyushkin * init = (scaling_ratio + number_of_taps + 1) / 2 8906566cae7SDmytro Laktyushkin * init_bot = init + scaling_ratio 8916566cae7SDmytro Laktyushkin * to get pixel perfect combine add the fraction from calculating vp offset 8926566cae7SDmytro Laktyushkin */ 8936566cae7SDmytro Laktyushkin temp = dc_fixpt_mul_int(ratio, recout_offset_within_recout_full); 8946566cae7SDmytro Laktyushkin *vp_offset = dc_fixpt_floor(temp); 8956566cae7SDmytro Laktyushkin temp.value &= 0xffffffff; 8966566cae7SDmytro Laktyushkin *init = dc_fixpt_truncate(dc_fixpt_add(dc_fixpt_div_int( 8976566cae7SDmytro Laktyushkin dc_fixpt_add_int(ratio, taps + 1), 2), temp), 19); 8986566cae7SDmytro Laktyushkin /* 8996566cae7SDmytro Laktyushkin * If viewport has non 0 offset and there are more taps than covered by init then 9006566cae7SDmytro Laktyushkin * we should decrease the offset and increase init so we are never sampling 9016566cae7SDmytro Laktyushkin * outside of viewport. 9026566cae7SDmytro Laktyushkin */ 9036566cae7SDmytro Laktyushkin int_part = dc_fixpt_floor(*init); 9049b6067c0SDmytro Laktyushkin if (int_part < taps) { 9056566cae7SDmytro Laktyushkin int_part = taps - int_part; 9066566cae7SDmytro Laktyushkin if (int_part > *vp_offset) 9076566cae7SDmytro Laktyushkin int_part = *vp_offset; 9086566cae7SDmytro Laktyushkin *vp_offset -= int_part; 9099b6067c0SDmytro Laktyushkin *init = dc_fixpt_add_int(*init, int_part); 9109b6067c0SDmytro Laktyushkin } 9119b6067c0SDmytro Laktyushkin /* 9126566cae7SDmytro Laktyushkin * If taps are sampling outside of viewport at end of recout and there are more pixels 9136566cae7SDmytro Laktyushkin * available in the surface we should increase the viewport size, regardless set vp to 9146566cae7SDmytro Laktyushkin * only what is used. 9159b6067c0SDmytro Laktyushkin */ 9166566cae7SDmytro Laktyushkin temp = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_size - 1)); 9176566cae7SDmytro Laktyushkin *vp_size = dc_fixpt_floor(temp); 9186566cae7SDmytro Laktyushkin if (*vp_size + *vp_offset > src_size) 9196566cae7SDmytro Laktyushkin *vp_size = src_size - *vp_offset; 9206566cae7SDmytro Laktyushkin 9216566cae7SDmytro Laktyushkin /* We did all the math assuming we are scanning same direction as display does, 9226566cae7SDmytro Laktyushkin * however mirror/rotation changes how vp scans vs how it is offset. If scan direction 9236566cae7SDmytro Laktyushkin * is flipped we simply need to calculate offset from the other side of plane. 9246566cae7SDmytro Laktyushkin * Note that outside of viewport all scaling hardware works in recout space. 9259b6067c0SDmytro Laktyushkin */ 9266566cae7SDmytro Laktyushkin if (flip_scan_dir) 9276566cae7SDmytro Laktyushkin *vp_offset = src_size - *vp_offset - *vp_size; 9289b6067c0SDmytro Laktyushkin } 9299b6067c0SDmytro Laktyushkin 9306566cae7SDmytro Laktyushkin static void calculate_inits_and_viewports(struct pipe_ctx *pipe_ctx) 9319b6067c0SDmytro Laktyushkin { 9329b6067c0SDmytro Laktyushkin const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 9339b6067c0SDmytro Laktyushkin const struct dc_stream_state *stream = pipe_ctx->stream; 9346702a9acSHarry Wentland struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 9356566cae7SDmytro Laktyushkin struct rect src = plane_state->src_rect; 93687449a90SAnthony Koo int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 93787449a90SAnthony Koo || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 9386566cae7SDmytro Laktyushkin int split_count, split_idx, ro_lb, ro_tb, recout_full_x, recout_full_y; 9399b6067c0SDmytro Laktyushkin bool orthogonal_rotation, flip_vert_scan_dir, flip_horz_scan_dir; 9406566cae7SDmytro Laktyushkin 9416566cae7SDmytro Laktyushkin calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); 9426566cae7SDmytro Laktyushkin /* 9436566cae7SDmytro Laktyushkin * recout full is what the recout would have been if we didnt clip 9446566cae7SDmytro Laktyushkin * the source plane at all. We only care about left(ro_lb) and top(ro_tb) 9456566cae7SDmytro Laktyushkin * offsets of recout within recout full because those are the directions 9466566cae7SDmytro Laktyushkin * we scan from and therefore the only ones that affect inits. 9476566cae7SDmytro Laktyushkin */ 9486566cae7SDmytro Laktyushkin recout_full_x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x) 9496566cae7SDmytro Laktyushkin * stream->dst.width / stream->src.width; 9506566cae7SDmytro Laktyushkin recout_full_y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y) 9516566cae7SDmytro Laktyushkin * stream->dst.height / stream->src.height; 9526566cae7SDmytro Laktyushkin if (pipe_ctx->prev_odm_pipe && split_idx) 9536566cae7SDmytro Laktyushkin ro_lb = data->h_active * split_idx - recout_full_x; 9546566cae7SDmytro Laktyushkin else 9556566cae7SDmytro Laktyushkin ro_lb = data->recout.x - recout_full_x; 9566566cae7SDmytro Laktyushkin ro_tb = data->recout.y - recout_full_y; 9576566cae7SDmytro Laktyushkin ASSERT(ro_lb >= 0 && ro_tb >= 0); 958b2d0a103SDmytro Laktyushkin 959b0131391SDmytro Laktyushkin /* 9606566cae7SDmytro Laktyushkin * Work in recout rotation since that requires less transformations 961b0131391SDmytro Laktyushkin */ 9629b6067c0SDmytro Laktyushkin get_vp_scan_direction( 9639b6067c0SDmytro Laktyushkin plane_state->rotation, 9649b6067c0SDmytro Laktyushkin plane_state->horizontal_mirror, 9659b6067c0SDmytro Laktyushkin &orthogonal_rotation, 9669b6067c0SDmytro Laktyushkin &flip_vert_scan_dir, 9679b6067c0SDmytro Laktyushkin &flip_horz_scan_dir); 968b0131391SDmytro Laktyushkin 9699b6067c0SDmytro Laktyushkin if (orthogonal_rotation) { 9709b6067c0SDmytro Laktyushkin swap(src.width, src.height); 9716566cae7SDmytro Laktyushkin swap(flip_vert_scan_dir, flip_horz_scan_dir); 9729b5349f7SMartin Tsai } 9731fbd2cfcSDmytro Laktyushkin 9746566cae7SDmytro Laktyushkin calculate_init_and_vp( 9759b6067c0SDmytro Laktyushkin flip_horz_scan_dir, 9766566cae7SDmytro Laktyushkin ro_lb, 9776566cae7SDmytro Laktyushkin data->recout.width, 9786566cae7SDmytro Laktyushkin src.width, 9796566cae7SDmytro Laktyushkin data->taps.h_taps, 9806566cae7SDmytro Laktyushkin data->ratios.horz, 9816566cae7SDmytro Laktyushkin &data->inits.h, 9829b6067c0SDmytro Laktyushkin &data->viewport.x, 9839b6067c0SDmytro Laktyushkin &data->viewport.width); 9846566cae7SDmytro Laktyushkin calculate_init_and_vp( 9859b6067c0SDmytro Laktyushkin flip_horz_scan_dir, 9866566cae7SDmytro Laktyushkin ro_lb, 9876566cae7SDmytro Laktyushkin data->recout.width, 9886566cae7SDmytro Laktyushkin src.width / vpc_div, 9896566cae7SDmytro Laktyushkin data->taps.h_taps_c, 9906566cae7SDmytro Laktyushkin data->ratios.horz_c, 9916566cae7SDmytro Laktyushkin &data->inits.h_c, 9929b6067c0SDmytro Laktyushkin &data->viewport_c.x, 9939b6067c0SDmytro Laktyushkin &data->viewport_c.width); 9946566cae7SDmytro Laktyushkin calculate_init_and_vp( 9959b6067c0SDmytro Laktyushkin flip_vert_scan_dir, 9966566cae7SDmytro Laktyushkin ro_tb, 9976566cae7SDmytro Laktyushkin data->recout.height, 9986566cae7SDmytro Laktyushkin src.height, 9996566cae7SDmytro Laktyushkin data->taps.v_taps, 10006566cae7SDmytro Laktyushkin data->ratios.vert, 10016566cae7SDmytro Laktyushkin &data->inits.v, 10029b6067c0SDmytro Laktyushkin &data->viewport.y, 10039b6067c0SDmytro Laktyushkin &data->viewport.height); 10046566cae7SDmytro Laktyushkin calculate_init_and_vp( 10059b6067c0SDmytro Laktyushkin flip_vert_scan_dir, 10066566cae7SDmytro Laktyushkin ro_tb, 10076566cae7SDmytro Laktyushkin data->recout.height, 10086566cae7SDmytro Laktyushkin src.height / vpc_div, 10096566cae7SDmytro Laktyushkin data->taps.v_taps_c, 10106566cae7SDmytro Laktyushkin data->ratios.vert_c, 10116566cae7SDmytro Laktyushkin &data->inits.v_c, 10129b6067c0SDmytro Laktyushkin &data->viewport_c.y, 10139b6067c0SDmytro Laktyushkin &data->viewport_c.height); 10146566cae7SDmytro Laktyushkin if (orthogonal_rotation) { 10156566cae7SDmytro Laktyushkin swap(data->viewport.x, data->viewport.y); 10166566cae7SDmytro Laktyushkin swap(data->viewport.width, data->viewport.height); 10176566cae7SDmytro Laktyushkin swap(data->viewport_c.x, data->viewport_c.y); 10186566cae7SDmytro Laktyushkin swap(data->viewport_c.width, data->viewport_c.height); 1019b2d0a103SDmytro Laktyushkin } 10206566cae7SDmytro Laktyushkin data->viewport.x += src.x; 10216566cae7SDmytro Laktyushkin data->viewport.y += src.y; 10226566cae7SDmytro Laktyushkin ASSERT(src.x % vpc_div == 0 && src.y % vpc_div == 0); 10236566cae7SDmytro Laktyushkin data->viewport_c.x += src.x / vpc_div; 10246566cae7SDmytro Laktyushkin data->viewport_c.y += src.y / vpc_div; 102589d07b66SSamson Tam } 102689d07b66SSamson Tam 1027b2d0a103SDmytro Laktyushkin bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) 1028b2d0a103SDmytro Laktyushkin { 10293be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 10304fa086b9SLeo (Sunpeng) Li struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 1031b2d0a103SDmytro Laktyushkin bool res = false; 10325d4b05ddSBhawanpreet Lakha DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); 10336566cae7SDmytro Laktyushkin 10346702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface( 10353be5262eSHarry Wentland pipe_ctx->plane_state->format); 10364562236bSHarry Wentland 10376566cae7SDmytro Laktyushkin /* Timing borders are part of vactive that we are also supposed to skip in addition 10386566cae7SDmytro Laktyushkin * to any stream dst offset. Since dm logic assumes dst is in addressable 10396566cae7SDmytro Laktyushkin * space we need to add the the left and top borders to dst offsets temporarily. 10406566cae7SDmytro Laktyushkin * TODO: fix in DM, stream dst is supposed to be in vactive 10416566cae7SDmytro Laktyushkin */ 10426566cae7SDmytro Laktyushkin pipe_ctx->stream->dst.x += timing->h_border_left; 10436566cae7SDmytro Laktyushkin pipe_ctx->stream->dst.y += timing->v_border_top; 1044b2d0a103SDmytro Laktyushkin 10456566cae7SDmytro Laktyushkin /* Calculate H and V active size */ 10466566cae7SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable + 10476566cae7SDmytro Laktyushkin timing->h_border_left + timing->h_border_right; 10486566cae7SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + 10496566cae7SDmytro Laktyushkin timing->v_border_top + timing->v_border_bottom; 10506566cae7SDmytro Laktyushkin if (pipe_ctx->next_odm_pipe || pipe_ctx->prev_odm_pipe) 10516566cae7SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.h_active /= get_num_odm_splits(pipe_ctx) + 1; 10524562236bSHarry Wentland 10536566cae7SDmytro Laktyushkin /* depends on h_active */ 10549b6067c0SDmytro Laktyushkin calculate_recout(pipe_ctx); 10556566cae7SDmytro Laktyushkin /* depends on pixel format */ 10566566cae7SDmytro Laktyushkin calculate_scaling_ratios(pipe_ctx); 10576566cae7SDmytro Laktyushkin /* depends on scaling ratios and recout, does not calculate offset yet */ 10586566cae7SDmytro Laktyushkin calculate_viewport_size(pipe_ctx); 10594562236bSHarry Wentland 10606566cae7SDmytro Laktyushkin /* 10616566cae7SDmytro Laktyushkin * LB calculations depend on vp size, h/v_active and scaling ratios 10624562236bSHarry Wentland * Setting line buffer pixel depth to 24bpp yields banding 1063a316db72SMario Kleiner * on certain displays, such as the Sharp 4k. 36bpp is needed 1064a316db72SMario Kleiner * to support SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 and 1065a316db72SMario Kleiner * SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616 with actual > 10 bpc 106672a7cf0aSMario Kleiner * precision on at least DCN display engines. However, at least 106772a7cf0aSMario Kleiner * Carrizo with DCE_VERSION_11_0 does not like 36 bpp lb depth, 106872a7cf0aSMario Kleiner * so use only 30 bpp on DCE_VERSION_11_0. Testing with DCE 11.2 and 8.3 106972a7cf0aSMario Kleiner * did not show such problems, so this seems to be the exception. 10704562236bSHarry Wentland */ 107172a7cf0aSMario Kleiner if (plane_state->ctx->dce_version != DCE_VERSION_11_0) 1072a316db72SMario Kleiner pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_36BPP; 107372a7cf0aSMario Kleiner else 107472a7cf0aSMario Kleiner pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; 107572a7cf0aSMario Kleiner 107633eef72fSEric Bernstein pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha; 10774562236bSHarry Wentland 1078d94585a0SYue Hin Lau if (pipe_ctx->plane_res.xfm != NULL) 107986a66c4eSHarry Wentland res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 108086a66c4eSHarry Wentland pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 10814562236bSHarry Wentland 1082d94585a0SYue Hin Lau if (pipe_ctx->plane_res.dpp != NULL) 1083d94585a0SYue Hin Lau res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 1084d94585a0SYue Hin Lau pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 1085f7938bc0SReza Amini 1086f7938bc0SReza Amini 10874562236bSHarry Wentland if (!res) { 10884562236bSHarry Wentland /* Try 24 bpp linebuffer */ 10896702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; 10904562236bSHarry Wentland 10911b6c8067SBhawanpreet Lakha if (pipe_ctx->plane_res.xfm != NULL) 109286a66c4eSHarry Wentland res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 10931b6c8067SBhawanpreet Lakha pipe_ctx->plane_res.xfm, 10941b6c8067SBhawanpreet Lakha &pipe_ctx->plane_res.scl_data, 10951b6c8067SBhawanpreet Lakha &plane_state->scaling_quality); 1096d94585a0SYue Hin Lau 10971b6c8067SBhawanpreet Lakha if (pipe_ctx->plane_res.dpp != NULL) 1098d94585a0SYue Hin Lau res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 10991b6c8067SBhawanpreet Lakha pipe_ctx->plane_res.dpp, 11001b6c8067SBhawanpreet Lakha &pipe_ctx->plane_res.scl_data, 11011b6c8067SBhawanpreet Lakha &plane_state->scaling_quality); 11024562236bSHarry Wentland } 11034562236bSHarry Wentland 11046566cae7SDmytro Laktyushkin /* 11056566cae7SDmytro Laktyushkin * Depends on recout, scaling ratios, h_active and taps 11066566cae7SDmytro Laktyushkin * May need to re-check lb size after this in some obscure scenario 11076566cae7SDmytro Laktyushkin */ 1108b2d0a103SDmytro Laktyushkin if (res) 11096566cae7SDmytro Laktyushkin calculate_inits_and_viewports(pipe_ctx); 11106566cae7SDmytro Laktyushkin 11116566cae7SDmytro Laktyushkin /* 11126566cae7SDmytro Laktyushkin * Handle side by side and top bottom 3d recout offsets after vp calculation 11136566cae7SDmytro Laktyushkin * since 3d is special and needs to calculate vp as if there is no recout offset 11146566cae7SDmytro Laktyushkin * This may break with rotation, good thing we aren't mixing hw rotation and 3d 11156566cae7SDmytro Laktyushkin */ 11166566cae7SDmytro Laktyushkin if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->plane_state == plane_state) { 11176566cae7SDmytro Laktyushkin ASSERT(plane_state->rotation == ROTATION_ANGLE_0 || 11186566cae7SDmytro Laktyushkin (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_TOP_AND_BOTTOM && 11196566cae7SDmytro Laktyushkin pipe_ctx->stream->view_format != VIEW_3D_FORMAT_SIDE_BY_SIDE)); 11206566cae7SDmytro Laktyushkin if (pipe_ctx->stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) 11216566cae7SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.y += pipe_ctx->plane_res.scl_data.recout.height; 11226566cae7SDmytro Laktyushkin else if (pipe_ctx->stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) 11236566cae7SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.x += pipe_ctx->plane_res.scl_data.recout.width; 11246566cae7SDmytro Laktyushkin } 11256566cae7SDmytro Laktyushkin 11266566cae7SDmytro Laktyushkin if (pipe_ctx->plane_res.scl_data.viewport.height < MIN_VIEWPORT_SIZE || 11276566cae7SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE) 11286566cae7SDmytro Laktyushkin res = false; 1129b2d0a103SDmytro Laktyushkin 11303c0dcf9fSDmytro 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" 11313c0dcf9fSDmytro 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", 11324562236bSHarry Wentland __func__, 11333c0dcf9fSDmytro Laktyushkin pipe_ctx->pipe_idx, 11346702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.height, 11356702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.width, 11366702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.x, 11376702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.y, 11383c0dcf9fSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.height, 11393c0dcf9fSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.width, 11403c0dcf9fSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.x, 11413c0dcf9fSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.y, 11423c0dcf9fSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.h_active, 11433c0dcf9fSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.v_active, 11443c0dcf9fSDmytro Laktyushkin plane_state->src_rect.height, 11453c0dcf9fSDmytro Laktyushkin plane_state->src_rect.width, 11463c0dcf9fSDmytro Laktyushkin plane_state->src_rect.x, 11473c0dcf9fSDmytro Laktyushkin plane_state->src_rect.y, 11483be5262eSHarry Wentland plane_state->dst_rect.height, 11493be5262eSHarry Wentland plane_state->dst_rect.width, 11503be5262eSHarry Wentland plane_state->dst_rect.x, 11513c0dcf9fSDmytro Laktyushkin plane_state->dst_rect.y, 11523c0dcf9fSDmytro Laktyushkin plane_state->clip_rect.height, 11533c0dcf9fSDmytro Laktyushkin plane_state->clip_rect.width, 11543c0dcf9fSDmytro Laktyushkin plane_state->clip_rect.x, 11553c0dcf9fSDmytro Laktyushkin plane_state->clip_rect.y); 11564562236bSHarry Wentland 11576566cae7SDmytro Laktyushkin pipe_ctx->stream->dst.x -= timing->h_border_left; 11586566cae7SDmytro Laktyushkin pipe_ctx->stream->dst.y -= timing->v_border_top; 115989d07b66SSamson Tam 11604562236bSHarry Wentland return res; 11614562236bSHarry Wentland } 11624562236bSHarry Wentland 11634562236bSHarry Wentland 11644562236bSHarry Wentland enum dc_status resource_build_scaling_params_for_context( 1165fb3466a4SBhawanpreet Lakha const struct dc *dc, 1166608ac7bbSJerry Zuo struct dc_state *context) 11674562236bSHarry Wentland { 11684562236bSHarry Wentland int i; 11694562236bSHarry Wentland 11704562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 11713be5262eSHarry Wentland if (context->res_ctx.pipe_ctx[i].plane_state != NULL && 11724562236bSHarry Wentland context->res_ctx.pipe_ctx[i].stream != NULL) 1173b2d0a103SDmytro Laktyushkin if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i])) 1174f84a8161STony Cheng return DC_FAIL_SCALING; 11754562236bSHarry Wentland } 11764562236bSHarry Wentland 11774562236bSHarry Wentland return DC_OK; 11784562236bSHarry Wentland } 11794562236bSHarry Wentland 1180a2b8659dSTony Cheng struct pipe_ctx *find_idle_secondary_pipe( 1181a2b8659dSTony Cheng struct resource_context *res_ctx, 11825581192dSJun Lei const struct resource_pool *pool, 11835581192dSJun Lei const struct pipe_ctx *primary_pipe) 11844562236bSHarry Wentland { 11854562236bSHarry Wentland int i; 11864562236bSHarry Wentland struct pipe_ctx *secondary_pipe = NULL; 11874562236bSHarry Wentland 11884562236bSHarry Wentland /* 11895581192dSJun Lei * We add a preferred pipe mapping to avoid the chance that 11905581192dSJun Lei * MPCCs already in use will need to be reassigned to other trees. 11915581192dSJun Lei * For example, if we went with the strict, assign backwards logic: 11925581192dSJun Lei * 11935581192dSJun Lei * (State 1) 11945581192dSJun Lei * Display A on, no surface, top pipe = 0 11955581192dSJun Lei * Display B on, no surface, top pipe = 1 11965581192dSJun Lei * 11975581192dSJun Lei * (State 2) 11985581192dSJun Lei * Display A on, no surface, top pipe = 0 11995581192dSJun Lei * Display B on, surface enable, top pipe = 1, bottom pipe = 5 12005581192dSJun Lei * 12015581192dSJun Lei * (State 3) 12025581192dSJun Lei * Display A on, surface enable, top pipe = 0, bottom pipe = 5 12035581192dSJun Lei * Display B on, surface enable, top pipe = 1, bottom pipe = 4 12045581192dSJun Lei * 12055581192dSJun Lei * The state 2->3 transition requires remapping MPCC 5 from display B 12065581192dSJun Lei * to display A. 12075581192dSJun Lei * 12085581192dSJun Lei * However, with the preferred pipe logic, state 2 would look like: 12095581192dSJun Lei * 12105581192dSJun Lei * (State 2) 12115581192dSJun Lei * Display A on, no surface, top pipe = 0 12125581192dSJun Lei * Display B on, surface enable, top pipe = 1, bottom pipe = 4 12135581192dSJun Lei * 12145581192dSJun Lei * This would then cause 2->3 to not require remapping any MPCCs. 12155581192dSJun Lei */ 12165581192dSJun Lei if (primary_pipe) { 12175581192dSJun Lei int preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx; 12185581192dSJun Lei if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) { 12195581192dSJun Lei secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx]; 12205581192dSJun Lei secondary_pipe->pipe_idx = preferred_pipe_idx; 12215581192dSJun Lei } 12225581192dSJun Lei } 12235581192dSJun Lei 12245581192dSJun Lei /* 12254562236bSHarry Wentland * search backwards for the second pipe to keep pipe 12264562236bSHarry Wentland * assignment more consistent 12274562236bSHarry Wentland */ 12285581192dSJun Lei if (!secondary_pipe) 1229a2b8659dSTony Cheng for (i = pool->pipe_count - 1; i >= 0; i--) { 12304562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == NULL) { 12314562236bSHarry Wentland secondary_pipe = &res_ctx->pipe_ctx[i]; 12324562236bSHarry Wentland secondary_pipe->pipe_idx = i; 12334562236bSHarry Wentland break; 12344562236bSHarry Wentland } 12354562236bSHarry Wentland } 12364562236bSHarry Wentland 12374562236bSHarry Wentland return secondary_pipe; 12384562236bSHarry Wentland } 12394562236bSHarry Wentland 12404562236bSHarry Wentland struct pipe_ctx *resource_get_head_pipe_for_stream( 12414562236bSHarry Wentland struct resource_context *res_ctx, 12420971c40eSHarry Wentland struct dc_stream_state *stream) 12434562236bSHarry Wentland { 12444562236bSHarry Wentland int i; 124522498036SDmytro Laktyushkin 1246a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 1247b1f6d01cSDmytro Laktyushkin if (res_ctx->pipe_ctx[i].stream == stream 1248b1f6d01cSDmytro Laktyushkin && !res_ctx->pipe_ctx[i].top_pipe 124922498036SDmytro Laktyushkin && !res_ctx->pipe_ctx[i].prev_odm_pipe) 12504562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 12514562236bSHarry Wentland } 12524562236bSHarry Wentland return NULL; 12534562236bSHarry Wentland } 12544562236bSHarry Wentland 1255b1f6d01cSDmytro Laktyushkin static struct pipe_ctx *resource_get_tail_pipe( 125619f89e23SAndrey Grodzovsky struct resource_context *res_ctx, 1257b1f6d01cSDmytro Laktyushkin struct pipe_ctx *head_pipe) 125819f89e23SAndrey Grodzovsky { 1259b1f6d01cSDmytro Laktyushkin struct pipe_ctx *tail_pipe; 126019f89e23SAndrey Grodzovsky 126119f89e23SAndrey Grodzovsky tail_pipe = head_pipe->bottom_pipe; 126219f89e23SAndrey Grodzovsky 126319f89e23SAndrey Grodzovsky while (tail_pipe) { 126419f89e23SAndrey Grodzovsky head_pipe = tail_pipe; 126519f89e23SAndrey Grodzovsky tail_pipe = tail_pipe->bottom_pipe; 126619f89e23SAndrey Grodzovsky } 126719f89e23SAndrey Grodzovsky 126819f89e23SAndrey Grodzovsky return head_pipe; 126919f89e23SAndrey Grodzovsky } 127019f89e23SAndrey Grodzovsky 12714562236bSHarry Wentland /* 1272ab2541b6SAric Cyr * A free_pipe for a stream is defined here as a pipe 1273ab2541b6SAric Cyr * that has no surface attached yet 12744562236bSHarry Wentland */ 1275b1f6d01cSDmytro Laktyushkin static struct pipe_ctx *acquire_free_pipe_for_head( 1276608ac7bbSJerry Zuo struct dc_state *context, 1277a2b8659dSTony Cheng const struct resource_pool *pool, 1278b1f6d01cSDmytro Laktyushkin struct pipe_ctx *head_pipe) 12794562236bSHarry Wentland { 12804562236bSHarry Wentland int i; 1281745cc746SDmytro Laktyushkin struct resource_context *res_ctx = &context->res_ctx; 12824562236bSHarry Wentland 12833be5262eSHarry Wentland if (!head_pipe->plane_state) 12844562236bSHarry Wentland return head_pipe; 12854562236bSHarry Wentland 12864562236bSHarry Wentland /* Re-use pipe already acquired for this stream if available*/ 1287a2b8659dSTony Cheng for (i = pool->pipe_count - 1; i >= 0; i--) { 1288b1f6d01cSDmytro Laktyushkin if (res_ctx->pipe_ctx[i].stream == head_pipe->stream && 12893be5262eSHarry Wentland !res_ctx->pipe_ctx[i].plane_state) { 12904562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 12914562236bSHarry Wentland } 12924562236bSHarry Wentland } 12934562236bSHarry Wentland 12944562236bSHarry Wentland /* 12954562236bSHarry Wentland * At this point we have no re-useable pipe for this stream and we need 12964562236bSHarry Wentland * to acquire an idle one to satisfy the request 12974562236bSHarry Wentland */ 12984562236bSHarry Wentland 1299a2b8659dSTony Cheng if (!pool->funcs->acquire_idle_pipe_for_layer) 13004562236bSHarry Wentland return NULL; 13014562236bSHarry Wentland 1302b1f6d01cSDmytro Laktyushkin return pool->funcs->acquire_idle_pipe_for_layer(context, pool, head_pipe->stream); 13034562236bSHarry Wentland } 13044562236bSHarry Wentland 1305b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 13060f9a536fSDmytro Laktyushkin static int acquire_first_split_pipe( 13070f9a536fSDmytro Laktyushkin struct resource_context *res_ctx, 13080f9a536fSDmytro Laktyushkin const struct resource_pool *pool, 13090971c40eSHarry Wentland struct dc_stream_state *stream) 13100f9a536fSDmytro Laktyushkin { 13110f9a536fSDmytro Laktyushkin int i; 13120f9a536fSDmytro Laktyushkin 13130f9a536fSDmytro Laktyushkin for (i = 0; i < pool->pipe_count; i++) { 131479592db3SDmytro Laktyushkin struct pipe_ctx *split_pipe = &res_ctx->pipe_ctx[i]; 13150f9a536fSDmytro Laktyushkin 1316b1f6d01cSDmytro Laktyushkin if (split_pipe->top_pipe && 131779592db3SDmytro Laktyushkin split_pipe->top_pipe->plane_state == split_pipe->plane_state) { 131879592db3SDmytro Laktyushkin split_pipe->top_pipe->bottom_pipe = split_pipe->bottom_pipe; 131979592db3SDmytro Laktyushkin if (split_pipe->bottom_pipe) 132079592db3SDmytro Laktyushkin split_pipe->bottom_pipe->top_pipe = split_pipe->top_pipe; 13210f9a536fSDmytro Laktyushkin 132279592db3SDmytro Laktyushkin if (split_pipe->top_pipe->plane_state) 132379592db3SDmytro Laktyushkin resource_build_scaling_params(split_pipe->top_pipe); 13240f9a536fSDmytro Laktyushkin 132579592db3SDmytro Laktyushkin memset(split_pipe, 0, sizeof(*split_pipe)); 132679592db3SDmytro Laktyushkin split_pipe->stream_res.tg = pool->timing_generators[i]; 132779592db3SDmytro Laktyushkin split_pipe->plane_res.hubp = pool->hubps[i]; 132879592db3SDmytro Laktyushkin split_pipe->plane_res.ipp = pool->ipps[i]; 132979592db3SDmytro Laktyushkin split_pipe->plane_res.dpp = pool->dpps[i]; 133079592db3SDmytro Laktyushkin split_pipe->stream_res.opp = pool->opps[i]; 133179592db3SDmytro Laktyushkin split_pipe->plane_res.mpcc_inst = pool->dpps[i]->inst; 133279592db3SDmytro Laktyushkin split_pipe->pipe_idx = i; 133379592db3SDmytro Laktyushkin 133479592db3SDmytro Laktyushkin split_pipe->stream = stream; 13350f9a536fSDmytro Laktyushkin return i; 13360f9a536fSDmytro Laktyushkin } 13370f9a536fSDmytro Laktyushkin } 13380f9a536fSDmytro Laktyushkin return -1; 13390f9a536fSDmytro Laktyushkin } 13400f9a536fSDmytro Laktyushkin #endif 13410f9a536fSDmytro Laktyushkin 134219f89e23SAndrey Grodzovsky bool dc_add_plane_to_context( 134319f89e23SAndrey Grodzovsky const struct dc *dc, 13440971c40eSHarry Wentland struct dc_stream_state *stream, 134519f89e23SAndrey Grodzovsky struct dc_plane_state *plane_state, 1346608ac7bbSJerry Zuo struct dc_state *context) 13474562236bSHarry Wentland { 13484562236bSHarry Wentland int i; 134919f89e23SAndrey Grodzovsky struct resource_pool *pool = dc->res_pool; 135019f89e23SAndrey Grodzovsky struct pipe_ctx *head_pipe, *tail_pipe, *free_pipe; 1351ab2541b6SAric Cyr struct dc_stream_status *stream_status = NULL; 13524562236bSHarry Wentland 1353ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) 13544fa086b9SLeo (Sunpeng) Li if (context->streams[i] == stream) { 1355ab2541b6SAric Cyr stream_status = &context->stream_status[i]; 13564562236bSHarry Wentland break; 13574562236bSHarry Wentland } 1358ab2541b6SAric Cyr if (stream_status == NULL) { 135919f89e23SAndrey Grodzovsky dm_error("Existing stream not found; failed to attach surface!\n"); 136019f89e23SAndrey Grodzovsky return false; 136119f89e23SAndrey Grodzovsky } 136219f89e23SAndrey Grodzovsky 136319f89e23SAndrey Grodzovsky 136419f89e23SAndrey Grodzovsky if (stream_status->plane_count == MAX_SURFACE_NUM) { 136519f89e23SAndrey Grodzovsky dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n", 136619f89e23SAndrey Grodzovsky plane_state, MAX_SURFACE_NUM); 136719f89e23SAndrey Grodzovsky return false; 136819f89e23SAndrey Grodzovsky } 136919f89e23SAndrey Grodzovsky 137019f89e23SAndrey Grodzovsky head_pipe = resource_get_head_pipe_for_stream(&context->res_ctx, stream); 137119f89e23SAndrey Grodzovsky 137219f89e23SAndrey Grodzovsky if (!head_pipe) { 137319f89e23SAndrey Grodzovsky dm_error("Head pipe not found for stream_state %p !\n", stream); 13744562236bSHarry Wentland return false; 13754562236bSHarry Wentland } 13764562236bSHarry Wentland 1377b1f6d01cSDmytro Laktyushkin /* retain new surface, but only once per stream */ 1378b1f6d01cSDmytro Laktyushkin dc_plane_state_retain(plane_state); 1379b1f6d01cSDmytro Laktyushkin 1380b1f6d01cSDmytro Laktyushkin while (head_pipe) { 1381b1f6d01cSDmytro Laktyushkin free_pipe = acquire_free_pipe_for_head(context, pool, head_pipe); 13824562236bSHarry Wentland 1383b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 13840f9a536fSDmytro Laktyushkin if (!free_pipe) { 13850f9a536fSDmytro Laktyushkin int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 13860f9a536fSDmytro Laktyushkin if (pipe_idx >= 0) 13870f9a536fSDmytro Laktyushkin free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; 13880f9a536fSDmytro Laktyushkin } 13890f9a536fSDmytro Laktyushkin #endif 1390b1f6d01cSDmytro Laktyushkin if (!free_pipe) { 1391b1f6d01cSDmytro Laktyushkin dc_plane_state_release(plane_state); 13924562236bSHarry Wentland return false; 1393b1f6d01cSDmytro Laktyushkin } 13944562236bSHarry Wentland 13953be5262eSHarry Wentland free_pipe->plane_state = plane_state; 13964562236bSHarry Wentland 139719f89e23SAndrey Grodzovsky if (head_pipe != free_pipe) { 13985b5c1777SJosip Pavic tail_pipe = resource_get_tail_pipe(&context->res_ctx, head_pipe); 13995b5c1777SJosip Pavic ASSERT(tail_pipe); 14006b670fa9SHarry Wentland free_pipe->stream_res.tg = tail_pipe->stream_res.tg; 14019aef1a31SSivapiriyanKumarasamy free_pipe->stream_res.abm = tail_pipe->stream_res.abm; 1402a6a6cb34SHarry Wentland free_pipe->stream_res.opp = tail_pipe->stream_res.opp; 14038e9c4c8cSHarry Wentland free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; 1404afaacef4SHarry Wentland free_pipe->stream_res.audio = tail_pipe->stream_res.audio; 1405cfe4645eSDmytro Laktyushkin free_pipe->clock_source = tail_pipe->clock_source; 14064562236bSHarry Wentland free_pipe->top_pipe = tail_pipe; 14074562236bSHarry Wentland tail_pipe->bottom_pipe = free_pipe; 14082e7b43e6SDmytro Laktyushkin if (!free_pipe->next_odm_pipe && tail_pipe->next_odm_pipe && tail_pipe->next_odm_pipe->bottom_pipe) { 14092e7b43e6SDmytro Laktyushkin free_pipe->next_odm_pipe = tail_pipe->next_odm_pipe->bottom_pipe; 14102e7b43e6SDmytro Laktyushkin tail_pipe->next_odm_pipe->bottom_pipe->prev_odm_pipe = free_pipe; 14112e7b43e6SDmytro Laktyushkin } 14122e7b43e6SDmytro Laktyushkin if (!free_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe->bottom_pipe) { 14132e7b43e6SDmytro Laktyushkin free_pipe->prev_odm_pipe = tail_pipe->prev_odm_pipe->bottom_pipe; 14142e7b43e6SDmytro Laktyushkin tail_pipe->prev_odm_pipe->bottom_pipe->next_odm_pipe = free_pipe; 14152e7b43e6SDmytro Laktyushkin } 14164562236bSHarry Wentland } 1417b1f6d01cSDmytro Laktyushkin head_pipe = head_pipe->next_odm_pipe; 1418b1f6d01cSDmytro Laktyushkin } 14194562236bSHarry Wentland /* assign new surfaces*/ 142019f89e23SAndrey Grodzovsky stream_status->plane_states[stream_status->plane_count] = plane_state; 14214562236bSHarry Wentland 142219f89e23SAndrey Grodzovsky stream_status->plane_count++; 14234562236bSHarry Wentland 14244562236bSHarry Wentland return true; 14254562236bSHarry Wentland } 14264562236bSHarry Wentland 142719f89e23SAndrey Grodzovsky bool dc_remove_plane_from_context( 142819f89e23SAndrey Grodzovsky const struct dc *dc, 142919f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 143019f89e23SAndrey Grodzovsky struct dc_plane_state *plane_state, 1431608ac7bbSJerry Zuo struct dc_state *context) 143219f89e23SAndrey Grodzovsky { 143319f89e23SAndrey Grodzovsky int i; 143419f89e23SAndrey Grodzovsky struct dc_stream_status *stream_status = NULL; 143519f89e23SAndrey Grodzovsky struct resource_pool *pool = dc->res_pool; 143619f89e23SAndrey Grodzovsky 143719f89e23SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 143819f89e23SAndrey Grodzovsky if (context->streams[i] == stream) { 143919f89e23SAndrey Grodzovsky stream_status = &context->stream_status[i]; 144019f89e23SAndrey Grodzovsky break; 144119f89e23SAndrey Grodzovsky } 144219f89e23SAndrey Grodzovsky 144319f89e23SAndrey Grodzovsky if (stream_status == NULL) { 144419f89e23SAndrey Grodzovsky dm_error("Existing stream not found; failed to remove plane.\n"); 144519f89e23SAndrey Grodzovsky return false; 144619f89e23SAndrey Grodzovsky } 144719f89e23SAndrey Grodzovsky 144819f89e23SAndrey Grodzovsky /* release pipe for plane*/ 144919f89e23SAndrey Grodzovsky for (i = pool->pipe_count - 1; i >= 0; i--) { 14506ffaa6fcSDmytro Laktyushkin struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 145119f89e23SAndrey Grodzovsky 14526ffaa6fcSDmytro Laktyushkin if (pipe_ctx->plane_state == plane_state) { 145319f89e23SAndrey Grodzovsky if (pipe_ctx->top_pipe) 145419f89e23SAndrey Grodzovsky pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; 145519f89e23SAndrey Grodzovsky 145619f89e23SAndrey Grodzovsky /* Second condition is to avoid setting NULL to top pipe 145719f89e23SAndrey Grodzovsky * of tail pipe making it look like head pipe in subsequent 145819f89e23SAndrey Grodzovsky * deletes 145919f89e23SAndrey Grodzovsky */ 146019f89e23SAndrey Grodzovsky if (pipe_ctx->bottom_pipe && pipe_ctx->top_pipe) 146119f89e23SAndrey Grodzovsky pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; 146219f89e23SAndrey Grodzovsky 146319f89e23SAndrey Grodzovsky /* 146419f89e23SAndrey Grodzovsky * For head pipe detach surfaces from pipe for tail 146519f89e23SAndrey Grodzovsky * pipe just zero it out 146619f89e23SAndrey Grodzovsky */ 1467b1f6d01cSDmytro Laktyushkin if (!pipe_ctx->top_pipe) 146819f89e23SAndrey Grodzovsky pipe_ctx->plane_state = NULL; 1469b1f6d01cSDmytro Laktyushkin else 147019f89e23SAndrey Grodzovsky memset(pipe_ctx, 0, sizeof(*pipe_ctx)); 147119f89e23SAndrey Grodzovsky } 147219f89e23SAndrey Grodzovsky } 147319f89e23SAndrey Grodzovsky 147419f89e23SAndrey Grodzovsky 147519f89e23SAndrey Grodzovsky for (i = 0; i < stream_status->plane_count; i++) { 147619f89e23SAndrey Grodzovsky if (stream_status->plane_states[i] == plane_state) { 147719f89e23SAndrey Grodzovsky 147819f89e23SAndrey Grodzovsky dc_plane_state_release(stream_status->plane_states[i]); 147919f89e23SAndrey Grodzovsky break; 148019f89e23SAndrey Grodzovsky } 148119f89e23SAndrey Grodzovsky } 148219f89e23SAndrey Grodzovsky 148319f89e23SAndrey Grodzovsky if (i == stream_status->plane_count) { 148419f89e23SAndrey Grodzovsky dm_error("Existing plane_state not found; failed to detach it!\n"); 148519f89e23SAndrey Grodzovsky return false; 148619f89e23SAndrey Grodzovsky } 148719f89e23SAndrey Grodzovsky 148819f89e23SAndrey Grodzovsky stream_status->plane_count--; 148919f89e23SAndrey Grodzovsky 1490abb4986eSAndrew Jiang /* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */ 1491abb4986eSAndrew Jiang for (; i < stream_status->plane_count; i++) 149219f89e23SAndrey Grodzovsky stream_status->plane_states[i] = stream_status->plane_states[i + 1]; 149319f89e23SAndrey Grodzovsky 149419f89e23SAndrey Grodzovsky stream_status->plane_states[stream_status->plane_count] = NULL; 149519f89e23SAndrey Grodzovsky 149619f89e23SAndrey Grodzovsky return true; 149719f89e23SAndrey Grodzovsky } 149819f89e23SAndrey Grodzovsky 149919f89e23SAndrey Grodzovsky bool dc_rem_all_planes_for_stream( 150019f89e23SAndrey Grodzovsky const struct dc *dc, 150119f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 1502608ac7bbSJerry Zuo struct dc_state *context) 150319f89e23SAndrey Grodzovsky { 150419f89e23SAndrey Grodzovsky int i, old_plane_count; 150519f89e23SAndrey Grodzovsky struct dc_stream_status *stream_status = NULL; 150619f89e23SAndrey Grodzovsky struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 }; 150719f89e23SAndrey Grodzovsky 150819f89e23SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 150919f89e23SAndrey Grodzovsky if (context->streams[i] == stream) { 151019f89e23SAndrey Grodzovsky stream_status = &context->stream_status[i]; 151119f89e23SAndrey Grodzovsky break; 151219f89e23SAndrey Grodzovsky } 151319f89e23SAndrey Grodzovsky 151419f89e23SAndrey Grodzovsky if (stream_status == NULL) { 151519f89e23SAndrey Grodzovsky dm_error("Existing stream %p not found!\n", stream); 151619f89e23SAndrey Grodzovsky return false; 151719f89e23SAndrey Grodzovsky } 151819f89e23SAndrey Grodzovsky 151919f89e23SAndrey Grodzovsky old_plane_count = stream_status->plane_count; 152019f89e23SAndrey Grodzovsky 152119f89e23SAndrey Grodzovsky for (i = 0; i < old_plane_count; i++) 152219f89e23SAndrey Grodzovsky del_planes[i] = stream_status->plane_states[i]; 152319f89e23SAndrey Grodzovsky 152419f89e23SAndrey Grodzovsky for (i = 0; i < old_plane_count; i++) 152519f89e23SAndrey Grodzovsky if (!dc_remove_plane_from_context(dc, stream, del_planes[i], context)) 152619f89e23SAndrey Grodzovsky return false; 152719f89e23SAndrey Grodzovsky 152819f89e23SAndrey Grodzovsky return true; 152919f89e23SAndrey Grodzovsky } 153019f89e23SAndrey Grodzovsky 153119f89e23SAndrey Grodzovsky static bool add_all_planes_for_stream( 153219f89e23SAndrey Grodzovsky const struct dc *dc, 153319f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 153419f89e23SAndrey Grodzovsky const struct dc_validation_set set[], 153519f89e23SAndrey Grodzovsky int set_count, 1536608ac7bbSJerry Zuo struct dc_state *context) 153719f89e23SAndrey Grodzovsky { 153819f89e23SAndrey Grodzovsky int i, j; 153919f89e23SAndrey Grodzovsky 154019f89e23SAndrey Grodzovsky for (i = 0; i < set_count; i++) 154119f89e23SAndrey Grodzovsky if (set[i].stream == stream) 154219f89e23SAndrey Grodzovsky break; 154319f89e23SAndrey Grodzovsky 154419f89e23SAndrey Grodzovsky if (i == set_count) { 154519f89e23SAndrey Grodzovsky dm_error("Stream %p not found in set!\n", stream); 154619f89e23SAndrey Grodzovsky return false; 154719f89e23SAndrey Grodzovsky } 154819f89e23SAndrey Grodzovsky 154919f89e23SAndrey Grodzovsky for (j = 0; j < set[i].plane_count; j++) 155019f89e23SAndrey Grodzovsky if (!dc_add_plane_to_context(dc, stream, set[i].plane_states[j], context)) 155119f89e23SAndrey Grodzovsky return false; 155219f89e23SAndrey Grodzovsky 155319f89e23SAndrey Grodzovsky return true; 155419f89e23SAndrey Grodzovsky } 155519f89e23SAndrey Grodzovsky 155619f89e23SAndrey Grodzovsky bool dc_add_all_planes_for_stream( 155719f89e23SAndrey Grodzovsky const struct dc *dc, 155819f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 155919f89e23SAndrey Grodzovsky struct dc_plane_state * const *plane_states, 156019f89e23SAndrey Grodzovsky int plane_count, 1561608ac7bbSJerry Zuo struct dc_state *context) 156219f89e23SAndrey Grodzovsky { 156319f89e23SAndrey Grodzovsky struct dc_validation_set set; 156419f89e23SAndrey Grodzovsky int i; 156519f89e23SAndrey Grodzovsky 156619f89e23SAndrey Grodzovsky set.stream = stream; 156719f89e23SAndrey Grodzovsky set.plane_count = plane_count; 156819f89e23SAndrey Grodzovsky 156919f89e23SAndrey Grodzovsky for (i = 0; i < plane_count; i++) 157019f89e23SAndrey Grodzovsky set.plane_states[i] = plane_states[i]; 157119f89e23SAndrey Grodzovsky 157219f89e23SAndrey Grodzovsky return add_all_planes_for_stream(dc, stream, &set, 1, context); 157319f89e23SAndrey Grodzovsky } 157419f89e23SAndrey Grodzovsky 15750971c40eSHarry Wentland static bool is_timing_changed(struct dc_stream_state *cur_stream, 15760971c40eSHarry Wentland struct dc_stream_state *new_stream) 15774562236bSHarry Wentland { 15784562236bSHarry Wentland if (cur_stream == NULL) 15794562236bSHarry Wentland return true; 15804562236bSHarry Wentland 15814562236bSHarry Wentland /* If output color space is changed, need to reprogram info frames */ 15824fa086b9SLeo (Sunpeng) Li if (cur_stream->output_color_space != new_stream->output_color_space) 15834562236bSHarry Wentland return true; 15844562236bSHarry Wentland 15854562236bSHarry Wentland return memcmp( 15864fa086b9SLeo (Sunpeng) Li &cur_stream->timing, 15874fa086b9SLeo (Sunpeng) Li &new_stream->timing, 15884562236bSHarry Wentland sizeof(struct dc_crtc_timing)) != 0; 15894562236bSHarry Wentland } 15904562236bSHarry Wentland 15914562236bSHarry Wentland static bool are_stream_backends_same( 15920971c40eSHarry Wentland struct dc_stream_state *stream_a, struct dc_stream_state *stream_b) 15934562236bSHarry Wentland { 15944562236bSHarry Wentland if (stream_a == stream_b) 15954562236bSHarry Wentland return true; 15964562236bSHarry Wentland 15974562236bSHarry Wentland if (stream_a == NULL || stream_b == NULL) 15984562236bSHarry Wentland return false; 15994562236bSHarry Wentland 16004562236bSHarry Wentland if (is_timing_changed(stream_a, stream_b)) 16014562236bSHarry Wentland return false; 16024562236bSHarry Wentland 16031e7e86c4SSamson Tam if (stream_a->dpms_off != stream_b->dpms_off) 16041e7e86c4SSamson Tam return false; 16051e7e86c4SSamson Tam 16064562236bSHarry Wentland return true; 16074562236bSHarry Wentland } 16084562236bSHarry Wentland 1609625a15bfSLee Jones /* 16102119aa17SDavid Francis * dc_is_stream_unchanged() - Compare two stream states for equivalence. 16112119aa17SDavid Francis * 16122119aa17SDavid Francis * Checks if there a difference between the two states 16132119aa17SDavid Francis * that would require a mode change. 16142119aa17SDavid Francis * 16152119aa17SDavid Francis * Does not compare cursor position or attributes. 16162119aa17SDavid Francis */ 1617d54d29dbSBhawanpreet Lakha bool dc_is_stream_unchanged( 16180971c40eSHarry Wentland struct dc_stream_state *old_stream, struct dc_stream_state *stream) 16194562236bSHarry Wentland { 16204562236bSHarry Wentland 16214562236bSHarry Wentland if (!are_stream_backends_same(old_stream, stream)) 16224562236bSHarry Wentland return false; 16234562236bSHarry Wentland 16240460f9abSJun Lei if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param) 16250460f9abSJun Lei return false; 16260460f9abSJun Lei 16274562236bSHarry Wentland return true; 16284562236bSHarry Wentland } 16294562236bSHarry Wentland 1630625a15bfSLee Jones /* 16312119aa17SDavid Francis * dc_is_stream_scaling_unchanged() - Compare scaling rectangles of two streams. 16322119aa17SDavid Francis */ 16339a5d9c48SLeo (Sunpeng) Li bool dc_is_stream_scaling_unchanged( 16349a5d9c48SLeo (Sunpeng) Li struct dc_stream_state *old_stream, struct dc_stream_state *stream) 16359a5d9c48SLeo (Sunpeng) Li { 16369a5d9c48SLeo (Sunpeng) Li if (old_stream == stream) 16379a5d9c48SLeo (Sunpeng) Li return true; 16389a5d9c48SLeo (Sunpeng) Li 16399a5d9c48SLeo (Sunpeng) Li if (old_stream == NULL || stream == NULL) 16409a5d9c48SLeo (Sunpeng) Li return false; 16419a5d9c48SLeo (Sunpeng) Li 16429a5d9c48SLeo (Sunpeng) Li if (memcmp(&old_stream->src, 16439a5d9c48SLeo (Sunpeng) Li &stream->src, 16449a5d9c48SLeo (Sunpeng) Li sizeof(struct rect)) != 0) 16459a5d9c48SLeo (Sunpeng) Li return false; 16469a5d9c48SLeo (Sunpeng) Li 16479a5d9c48SLeo (Sunpeng) Li if (memcmp(&old_stream->dst, 16489a5d9c48SLeo (Sunpeng) Li &stream->dst, 16499a5d9c48SLeo (Sunpeng) Li sizeof(struct rect)) != 0) 16509a5d9c48SLeo (Sunpeng) Li return false; 16519a5d9c48SLeo (Sunpeng) Li 16529a5d9c48SLeo (Sunpeng) Li return true; 16539a5d9c48SLeo (Sunpeng) Li } 16549a5d9c48SLeo (Sunpeng) Li 16551dc90497SAndrey Grodzovsky static void update_stream_engine_usage( 16564562236bSHarry Wentland struct resource_context *res_ctx, 1657a2b8659dSTony Cheng const struct resource_pool *pool, 16581dc90497SAndrey Grodzovsky struct stream_encoder *stream_enc, 16591dc90497SAndrey Grodzovsky bool acquired) 16604562236bSHarry Wentland { 16614562236bSHarry Wentland int i; 16624562236bSHarry Wentland 1663a2b8659dSTony Cheng for (i = 0; i < pool->stream_enc_count; i++) { 1664a2b8659dSTony Cheng if (pool->stream_enc[i] == stream_enc) 16651dc90497SAndrey Grodzovsky res_ctx->is_stream_enc_acquired[i] = acquired; 16664562236bSHarry Wentland } 16674562236bSHarry Wentland } 16684562236bSHarry Wentland 16694562236bSHarry Wentland /* TODO: release audio object */ 16704176664bSCharlene Liu void update_audio_usage( 16714562236bSHarry Wentland struct resource_context *res_ctx, 1672a2b8659dSTony Cheng const struct resource_pool *pool, 16731dc90497SAndrey Grodzovsky struct audio *audio, 16741dc90497SAndrey Grodzovsky bool acquired) 16754562236bSHarry Wentland { 16764562236bSHarry Wentland int i; 1677a2b8659dSTony Cheng for (i = 0; i < pool->audio_count; i++) { 1678a2b8659dSTony Cheng if (pool->audios[i] == audio) 16791dc90497SAndrey Grodzovsky res_ctx->is_audio_acquired[i] = acquired; 16804562236bSHarry Wentland } 16814562236bSHarry Wentland } 16824562236bSHarry Wentland 16834562236bSHarry Wentland static int acquire_first_free_pipe( 16844562236bSHarry Wentland struct resource_context *res_ctx, 1685a2b8659dSTony Cheng const struct resource_pool *pool, 16860971c40eSHarry Wentland struct dc_stream_state *stream) 16874562236bSHarry Wentland { 16884562236bSHarry Wentland int i; 16894562236bSHarry Wentland 1690a2b8659dSTony Cheng for (i = 0; i < pool->pipe_count; i++) { 16914562236bSHarry Wentland if (!res_ctx->pipe_ctx[i].stream) { 16924562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 16934562236bSHarry Wentland 16946b670fa9SHarry Wentland pipe_ctx->stream_res.tg = pool->timing_generators[i]; 169586a66c4eSHarry Wentland pipe_ctx->plane_res.mi = pool->mis[i]; 16968feabd03SYue Hin Lau pipe_ctx->plane_res.hubp = pool->hubps[i]; 169786a66c4eSHarry Wentland pipe_ctx->plane_res.ipp = pool->ipps[i]; 169886a66c4eSHarry Wentland pipe_ctx->plane_res.xfm = pool->transforms[i]; 1699d94585a0SYue Hin Lau pipe_ctx->plane_res.dpp = pool->dpps[i]; 1700a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp = pool->opps[i]; 1701bc373a89SRoman Li if (pool->dpps[i]) 1702e07f541fSYongqiang Sun pipe_ctx->plane_res.mpcc_inst = pool->dpps[i]->inst; 17034562236bSHarry Wentland pipe_ctx->pipe_idx = i; 17044562236bSHarry Wentland 1705ff5ef992SAlex Deucher 17064562236bSHarry Wentland pipe_ctx->stream = stream; 17074562236bSHarry Wentland return i; 17084562236bSHarry Wentland } 17094562236bSHarry Wentland } 17104562236bSHarry Wentland return -1; 17114562236bSHarry Wentland } 17124562236bSHarry Wentland 1713a2b8659dSTony Cheng static struct audio *find_first_free_audio( 1714a2b8659dSTony Cheng struct resource_context *res_ctx, 1715cfb071f7SCharlene Liu const struct resource_pool *pool, 1716f24b0522SPaul Hsieh enum engine_id id, 1717f24b0522SPaul Hsieh enum dce_version dc_version) 17184562236bSHarry Wentland { 1719b5a41620SCharlene Liu int i, available_audio_count; 1720b5a41620SCharlene Liu 1721b5a41620SCharlene Liu available_audio_count = pool->audio_count; 1722b5a41620SCharlene Liu 1723b5a41620SCharlene Liu for (i = 0; i < available_audio_count; i++) { 17244176664bSCharlene Liu if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) { 1725cfb071f7SCharlene Liu /*we have enough audio endpoint, find the matching inst*/ 1726cfb071f7SCharlene Liu if (id != i) 1727cfb071f7SCharlene Liu continue; 1728a2b8659dSTony Cheng return pool->audios[i]; 17294562236bSHarry Wentland } 17304562236bSHarry Wentland } 17315feb9f07STai Man 17325feb9f07STai Man /* use engine id to find free audio */ 1733b5a41620SCharlene Liu if ((id < available_audio_count) && (res_ctx->is_audio_acquired[id] == false)) { 17345feb9f07STai Man return pool->audios[id]; 17355feb9f07STai Man } 173666bfd4fdSCharlene Liu /*not found the matching one, first come first serve*/ 1737b5a41620SCharlene Liu for (i = 0; i < available_audio_count; i++) { 17384176664bSCharlene Liu if (res_ctx->is_audio_acquired[i] == false) { 17394176664bSCharlene Liu return pool->audios[i]; 17404176664bSCharlene Liu } 17414176664bSCharlene Liu } 17424562236bSHarry Wentland return 0; 17434562236bSHarry Wentland } 17444562236bSHarry Wentland 1745625a15bfSLee Jones /* 17462119aa17SDavid Francis * dc_add_stream_to_ctx() - Add a new dc_stream_state to a dc_state. 17472119aa17SDavid Francis */ 174813ab1b44SYongqiang Sun enum dc_status dc_add_stream_to_ctx( 17491dc90497SAndrey Grodzovsky struct dc *dc, 1750608ac7bbSJerry Zuo struct dc_state *new_ctx, 17511dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 17521dc90497SAndrey Grodzovsky { 17531dc90497SAndrey Grodzovsky enum dc_status res; 1754eb9714a2SWenjing Liu DC_LOGGER_INIT(dc->ctx->logger); 17551dc90497SAndrey Grodzovsky 1756ece4147fSKen Chalmers if (new_ctx->stream_count >= dc->res_pool->timing_generator_count) { 1757eb9714a2SWenjing Liu DC_LOG_WARNING("Max streams reached, can't add stream %p !\n", stream); 17581dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 17591dc90497SAndrey Grodzovsky } 17601dc90497SAndrey Grodzovsky 17611dc90497SAndrey Grodzovsky new_ctx->streams[new_ctx->stream_count] = stream; 17621dc90497SAndrey Grodzovsky dc_stream_retain(stream); 17631dc90497SAndrey Grodzovsky new_ctx->stream_count++; 17641dc90497SAndrey Grodzovsky 17651dc90497SAndrey Grodzovsky res = dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream); 17661dc90497SAndrey Grodzovsky if (res != DC_OK) 1767eb9714a2SWenjing Liu DC_LOG_WARNING("Adding stream %p to context failed with err %d!\n", stream, res); 17681dc90497SAndrey Grodzovsky 176913ab1b44SYongqiang Sun return res; 17701dc90497SAndrey Grodzovsky } 17711dc90497SAndrey Grodzovsky 1772625a15bfSLee Jones /* 17732119aa17SDavid Francis * dc_remove_stream_from_ctx() - Remove a stream from a dc_state. 17742119aa17SDavid Francis */ 177562c933f9SYongqiang Sun enum dc_status dc_remove_stream_from_ctx( 17761dc90497SAndrey Grodzovsky struct dc *dc, 1777608ac7bbSJerry Zuo struct dc_state *new_ctx, 17781dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 17791dc90497SAndrey Grodzovsky { 178019f89e23SAndrey Grodzovsky int i; 17811dc90497SAndrey Grodzovsky struct dc_context *dc_ctx = dc->ctx; 178222498036SDmytro Laktyushkin struct pipe_ctx *del_pipe = resource_get_head_pipe_for_stream(&new_ctx->res_ctx, stream); 178322498036SDmytro Laktyushkin struct pipe_ctx *odm_pipe; 178422498036SDmytro Laktyushkin 178522498036SDmytro Laktyushkin if (!del_pipe) { 178622498036SDmytro Laktyushkin DC_ERROR("Pipe not found for stream %p !\n", stream); 178722498036SDmytro Laktyushkin return DC_ERROR_UNEXPECTED; 178822498036SDmytro Laktyushkin } 178922498036SDmytro Laktyushkin 179022498036SDmytro Laktyushkin odm_pipe = del_pipe->next_odm_pipe; 17911dc90497SAndrey Grodzovsky 179219f89e23SAndrey Grodzovsky /* Release primary pipe */ 179319f89e23SAndrey Grodzovsky ASSERT(del_pipe->stream_res.stream_enc); 17941dc90497SAndrey Grodzovsky update_stream_engine_usage( 17951dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 17961dc90497SAndrey Grodzovsky dc->res_pool, 17971dc90497SAndrey Grodzovsky del_pipe->stream_res.stream_enc, 17981dc90497SAndrey Grodzovsky false); 1799f42ef862SJimmy Kizito /* Release link encoder from stream in new dc_state. */ 1800f42ef862SJimmy Kizito if (dc->res_pool->funcs->link_enc_unassign) 1801f42ef862SJimmy Kizito dc->res_pool->funcs->link_enc_unassign(new_ctx, del_pipe->stream); 18021dc90497SAndrey Grodzovsky 18031dc90497SAndrey Grodzovsky if (del_pipe->stream_res.audio) 18041dc90497SAndrey Grodzovsky update_audio_usage( 18051dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 18061dc90497SAndrey Grodzovsky dc->res_pool, 18071dc90497SAndrey Grodzovsky del_pipe->stream_res.audio, 18081dc90497SAndrey Grodzovsky false); 18091dc90497SAndrey Grodzovsky 18109d0dcecdSHarry Wentland resource_unreference_clock_source(&new_ctx->res_ctx, 18119d0dcecdSHarry Wentland dc->res_pool, 18129d0dcecdSHarry Wentland del_pipe->clock_source); 18139d0dcecdSHarry Wentland 1814e56ae556SNikola Cornij if (dc->res_pool->funcs->remove_stream_from_ctx) 1815e56ae556SNikola Cornij dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream); 1816e56ae556SNikola Cornij 181722498036SDmytro Laktyushkin while (odm_pipe) { 181822498036SDmytro Laktyushkin struct pipe_ctx *next_odm_pipe = odm_pipe->next_odm_pipe; 181922498036SDmytro Laktyushkin 182022498036SDmytro Laktyushkin memset(odm_pipe, 0, sizeof(*odm_pipe)); 182122498036SDmytro Laktyushkin odm_pipe = next_odm_pipe; 182222498036SDmytro Laktyushkin } 18231dc90497SAndrey Grodzovsky memset(del_pipe, 0, sizeof(*del_pipe)); 18246ffaa6fcSDmytro Laktyushkin 18251dc90497SAndrey Grodzovsky for (i = 0; i < new_ctx->stream_count; i++) 18261dc90497SAndrey Grodzovsky if (new_ctx->streams[i] == stream) 18271dc90497SAndrey Grodzovsky break; 18281dc90497SAndrey Grodzovsky 18291dc90497SAndrey Grodzovsky if (new_ctx->streams[i] != stream) { 18301dc90497SAndrey Grodzovsky DC_ERROR("Context doesn't have stream %p !\n", stream); 18311dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 18321dc90497SAndrey Grodzovsky } 18331dc90497SAndrey Grodzovsky 18341dc90497SAndrey Grodzovsky dc_stream_release(new_ctx->streams[i]); 18351dc90497SAndrey Grodzovsky new_ctx->stream_count--; 18361dc90497SAndrey Grodzovsky 18371dc90497SAndrey Grodzovsky /* Trim back arrays */ 18381dc90497SAndrey Grodzovsky for (; i < new_ctx->stream_count; i++) { 18391dc90497SAndrey Grodzovsky new_ctx->streams[i] = new_ctx->streams[i + 1]; 18401dc90497SAndrey Grodzovsky new_ctx->stream_status[i] = new_ctx->stream_status[i + 1]; 18411dc90497SAndrey Grodzovsky } 18421dc90497SAndrey Grodzovsky 18431dc90497SAndrey Grodzovsky new_ctx->streams[new_ctx->stream_count] = NULL; 18441dc90497SAndrey Grodzovsky memset( 18451dc90497SAndrey Grodzovsky &new_ctx->stream_status[new_ctx->stream_count], 18461dc90497SAndrey Grodzovsky 0, 18471dc90497SAndrey Grodzovsky sizeof(new_ctx->stream_status[0])); 18481dc90497SAndrey Grodzovsky 18491dc90497SAndrey Grodzovsky return DC_OK; 18501dc90497SAndrey Grodzovsky } 18511dc90497SAndrey Grodzovsky 18520971c40eSHarry Wentland static struct dc_stream_state *find_pll_sharable_stream( 18530971c40eSHarry Wentland struct dc_stream_state *stream_needs_pll, 1854608ac7bbSJerry Zuo struct dc_state *context) 18554562236bSHarry Wentland { 1856ab2541b6SAric Cyr int i; 18574562236bSHarry Wentland 1858ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 18590971c40eSHarry Wentland struct dc_stream_state *stream_has_pll = context->streams[i]; 18604562236bSHarry Wentland 18614562236bSHarry Wentland /* We are looking for non dp, non virtual stream */ 18624562236bSHarry Wentland if (resource_are_streams_timing_synchronizable( 18634562236bSHarry Wentland stream_needs_pll, stream_has_pll) 18644562236bSHarry Wentland && !dc_is_dp_signal(stream_has_pll->signal) 1865ceb3dbb4SJun Lei && stream_has_pll->link->connector_signal 18664562236bSHarry Wentland != SIGNAL_TYPE_VIRTUAL) 18674562236bSHarry Wentland return stream_has_pll; 1868ab2541b6SAric Cyr 18694562236bSHarry Wentland } 18704562236bSHarry Wentland 18714562236bSHarry Wentland return NULL; 18724562236bSHarry Wentland } 18734562236bSHarry Wentland 18744562236bSHarry Wentland static int get_norm_pix_clk(const struct dc_crtc_timing *timing) 18754562236bSHarry Wentland { 1876380604e2SKen Chalmers uint32_t pix_clk = timing->pix_clk_100hz; 18774562236bSHarry Wentland uint32_t normalized_pix_clk = pix_clk; 18784562236bSHarry Wentland 18794562236bSHarry Wentland if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) 18804562236bSHarry Wentland pix_clk /= 2; 1881cc4d99b8SCharlene Liu if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) { 18824562236bSHarry Wentland switch (timing->display_color_depth) { 18838897810aSJulian Parkin case COLOR_DEPTH_666: 18844562236bSHarry Wentland case COLOR_DEPTH_888: 18854562236bSHarry Wentland normalized_pix_clk = pix_clk; 18864562236bSHarry Wentland break; 18874562236bSHarry Wentland case COLOR_DEPTH_101010: 18884562236bSHarry Wentland normalized_pix_clk = (pix_clk * 30) / 24; 18894562236bSHarry Wentland break; 18904562236bSHarry Wentland case COLOR_DEPTH_121212: 18914562236bSHarry Wentland normalized_pix_clk = (pix_clk * 36) / 24; 18924562236bSHarry Wentland break; 18934562236bSHarry Wentland case COLOR_DEPTH_161616: 18944562236bSHarry Wentland normalized_pix_clk = (pix_clk * 48) / 24; 18954562236bSHarry Wentland break; 18964562236bSHarry Wentland default: 18974562236bSHarry Wentland ASSERT(0); 18984562236bSHarry Wentland break; 18994562236bSHarry Wentland } 1900cc4d99b8SCharlene Liu } 19014562236bSHarry Wentland return normalized_pix_clk; 19024562236bSHarry Wentland } 19034562236bSHarry Wentland 19040971c40eSHarry Wentland static void calculate_phy_pix_clks(struct dc_stream_state *stream) 19054562236bSHarry Wentland { 19064562236bSHarry Wentland /* update actual pixel clock on all streams */ 19074562236bSHarry Wentland if (dc_is_hdmi_signal(stream->signal)) 19084562236bSHarry Wentland stream->phy_pix_clk = get_norm_pix_clk( 1909380604e2SKen Chalmers &stream->timing) / 10; 19104562236bSHarry Wentland else 19114562236bSHarry Wentland stream->phy_pix_clk = 1912380604e2SKen Chalmers stream->timing.pix_clk_100hz / 10; 191339c03e00SCharlene Liu 191439c03e00SCharlene Liu if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) 191539c03e00SCharlene Liu stream->phy_pix_clk *= 2; 19164562236bSHarry Wentland } 19174562236bSHarry Wentland 1918d2d7885fSAnthony Koo static int acquire_resource_from_hw_enabled_state( 1919d2d7885fSAnthony Koo struct resource_context *res_ctx, 1920d2d7885fSAnthony Koo const struct resource_pool *pool, 1921d2d7885fSAnthony Koo struct dc_stream_state *stream) 1922d2d7885fSAnthony Koo { 1923d2d7885fSAnthony Koo struct dc_link *link = stream->link; 192408b66279SMartin Leung unsigned int i, inst, tg_inst = 0; 1925d2d7885fSAnthony Koo 1926d2d7885fSAnthony Koo /* Check for enabled DIG to identify enabled display */ 1927d2d7885fSAnthony Koo if (!link->link_enc->funcs->is_dig_enabled(link->link_enc)) 1928d2d7885fSAnthony Koo return -1; 1929d2d7885fSAnthony Koo 19305ec43edaSMartin Leung inst = link->link_enc->funcs->get_dig_frontend(link->link_enc); 1931d2d7885fSAnthony Koo 19327f7652eeSMartin Leung if (inst == ENGINE_ID_UNKNOWN) 193375441d9dSMikita Lipski return -1; 1934d2d7885fSAnthony Koo 19357f7652eeSMartin Leung for (i = 0; i < pool->stream_enc_count; i++) { 19367f7652eeSMartin Leung if (pool->stream_enc[i]->id == inst) { 19377f7652eeSMartin Leung tg_inst = pool->stream_enc[i]->funcs->dig_source_otg( 19387f7652eeSMartin Leung pool->stream_enc[i]); 19397f7652eeSMartin Leung break; 19407f7652eeSMartin Leung } 19417f7652eeSMartin Leung } 1942d2d7885fSAnthony Koo 19437f7652eeSMartin Leung // tg_inst not found 19447f7652eeSMartin Leung if (i == pool->stream_enc_count) 194575441d9dSMikita Lipski return -1; 19465ec43edaSMartin Leung 19475ec43edaSMartin Leung if (tg_inst >= pool->timing_generator_count) 194875441d9dSMikita Lipski return -1; 19495ec43edaSMartin Leung 19505ec43edaSMartin Leung if (!res_ctx->pipe_ctx[tg_inst].stream) { 19515ec43edaSMartin Leung struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[tg_inst]; 19525ec43edaSMartin Leung 19535ec43edaSMartin Leung pipe_ctx->stream_res.tg = pool->timing_generators[tg_inst]; 19545ec43edaSMartin Leung pipe_ctx->plane_res.mi = pool->mis[tg_inst]; 19555ec43edaSMartin Leung pipe_ctx->plane_res.hubp = pool->hubps[tg_inst]; 19565ec43edaSMartin Leung pipe_ctx->plane_res.ipp = pool->ipps[tg_inst]; 19575ec43edaSMartin Leung pipe_ctx->plane_res.xfm = pool->transforms[tg_inst]; 19585ec43edaSMartin Leung pipe_ctx->plane_res.dpp = pool->dpps[tg_inst]; 19595ec43edaSMartin Leung pipe_ctx->stream_res.opp = pool->opps[tg_inst]; 19605ec43edaSMartin Leung 1961ccce745cSMartin Leung if (pool->dpps[tg_inst]) { 19625ec43edaSMartin Leung pipe_ctx->plane_res.mpcc_inst = pool->dpps[tg_inst]->inst; 1963ccce745cSMartin Leung 1964ccce745cSMartin Leung // Read DPP->MPCC->OPP Pipe from HW State 1965ccce745cSMartin Leung if (pool->mpc->funcs->read_mpcc_state) { 1966ccce745cSMartin Leung struct mpcc_state s = {0}; 1967ccce745cSMartin Leung 1968ccce745cSMartin Leung pool->mpc->funcs->read_mpcc_state(pool->mpc, pipe_ctx->plane_res.mpcc_inst, &s); 1969ccce745cSMartin Leung 1970ccce745cSMartin Leung if (s.dpp_id < MAX_MPCC) 1971ccce745cSMartin Leung pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].dpp_id = s.dpp_id; 1972ccce745cSMartin Leung 1973ccce745cSMartin Leung if (s.bot_mpcc_id < MAX_MPCC) 1974ccce745cSMartin Leung pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].mpcc_bot = 1975ccce745cSMartin Leung &pool->mpc->mpcc_array[s.bot_mpcc_id]; 1976ccce745cSMartin Leung 1977ccce745cSMartin Leung if (s.opp_id < MAX_OPP) 1978ccce745cSMartin Leung pipe_ctx->stream_res.opp->mpc_tree_params.opp_id = s.opp_id; 1979ccce745cSMartin Leung } 1980ccce745cSMartin Leung } 19815ec43edaSMartin Leung pipe_ctx->pipe_idx = tg_inst; 1982d2d7885fSAnthony Koo 1983d2d7885fSAnthony Koo pipe_ctx->stream = stream; 19845ec43edaSMartin Leung return tg_inst; 1985d2d7885fSAnthony Koo } 1986d2d7885fSAnthony Koo 1987d2d7885fSAnthony Koo return -1; 1988d2d7885fSAnthony Koo } 1989d2d7885fSAnthony Koo 199096b5e3e1SRaymond Yang static void mark_seamless_boot_stream( 199196b5e3e1SRaymond Yang const struct dc *dc, 199296b5e3e1SRaymond Yang struct dc_stream_state *stream) 199396b5e3e1SRaymond Yang { 199496b5e3e1SRaymond Yang struct dc_bios *dcb = dc->ctx->dc_bios; 199596b5e3e1SRaymond Yang 199696b5e3e1SRaymond Yang /* TODO: Check Linux */ 199796b5e3e1SRaymond Yang if (dc->config.allow_seamless_boot_optimization && 199896b5e3e1SRaymond Yang !dcb->funcs->is_accelerated_mode(dcb)) { 199996b5e3e1SRaymond Yang if (dc_validate_seamless_boot_timing(dc, stream->sink, &stream->timing)) 200096b5e3e1SRaymond Yang stream->apply_seamless_boot_optimization = true; 200196b5e3e1SRaymond Yang } 200296b5e3e1SRaymond Yang } 200396b5e3e1SRaymond Yang 20044562236bSHarry Wentland enum dc_status resource_map_pool_resources( 2005fb3466a4SBhawanpreet Lakha const struct dc *dc, 2006608ac7bbSJerry Zuo struct dc_state *context, 20071dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 20084562236bSHarry Wentland { 2009a2b8659dSTony Cheng const struct resource_pool *pool = dc->res_pool; 20101dc90497SAndrey Grodzovsky int i; 20111dc90497SAndrey Grodzovsky struct dc_context *dc_ctx = dc->ctx; 20121dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = NULL; 20131dc90497SAndrey Grodzovsky int pipe_idx = -1; 20144562236bSHarry Wentland 201508e1c28dSYogesh Mohan Marimuthu calculate_phy_pix_clks(stream); 201608e1c28dSYogesh Mohan Marimuthu 201796b5e3e1SRaymond Yang mark_seamless_boot_stream(dc, stream); 201846570f09SAnthony Koo 201996b5e3e1SRaymond Yang if (stream->apply_seamless_boot_optimization) { 2020d2d7885fSAnthony Koo pipe_idx = acquire_resource_from_hw_enabled_state( 2021d2d7885fSAnthony Koo &context->res_ctx, 2022d2d7885fSAnthony Koo pool, 2023d2d7885fSAnthony Koo stream); 202496b5e3e1SRaymond Yang if (pipe_idx < 0) 202596b5e3e1SRaymond Yang /* hw resource was assigned to other stream */ 202696b5e3e1SRaymond Yang stream->apply_seamless_boot_optimization = false; 202796b5e3e1SRaymond Yang } 2028d2d7885fSAnthony Koo 2029d2d7885fSAnthony Koo if (pipe_idx < 0) 20304562236bSHarry Wentland /* acquire new resources */ 20315d11e9fcSDmytro Laktyushkin pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); 20321dc90497SAndrey Grodzovsky 2033b86a1aa3SBhawanpreet Lakha #ifdef CONFIG_DRM_AMD_DC_DCN 20345d11e9fcSDmytro Laktyushkin if (pipe_idx < 0) 203513ab1b44SYongqiang Sun pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 203694c6d735SHarry Wentland #endif 203713ab1b44SYongqiang Sun 2038c5b38aecSDmytro Laktyushkin if (pipe_idx < 0 || context->res_ctx.pipe_ctx[pipe_idx].stream_res.tg == NULL) 20394562236bSHarry Wentland return DC_NO_CONTROLLER_RESOURCE; 20404562236bSHarry Wentland 20414562236bSHarry Wentland pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; 20424562236bSHarry Wentland 20438e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc = 204478cc70b1SWesley Chalmers dc->res_pool->funcs->find_first_free_match_stream_enc_for_link( 2045a2b8659dSTony Cheng &context->res_ctx, pool, stream); 20464562236bSHarry Wentland 20478e9c4c8cSHarry Wentland if (!pipe_ctx->stream_res.stream_enc) 204838684e46SEric Bernstein return DC_NO_STREAM_ENC_RESOURCE; 20494562236bSHarry Wentland 20501dc90497SAndrey Grodzovsky update_stream_engine_usage( 2051a2b8659dSTony Cheng &context->res_ctx, pool, 20521dc90497SAndrey Grodzovsky pipe_ctx->stream_res.stream_enc, 20531dc90497SAndrey Grodzovsky true); 20544562236bSHarry Wentland 20554562236bSHarry Wentland /* TODO: Add check if ASIC support and EDID audio */ 2056ceb3dbb4SJun Lei if (!stream->converter_disable_audio && 20574562236bSHarry Wentland dc_is_audio_capable_signal(pipe_ctx->stream->signal) && 2058ce08aad3SAlvin Lee stream->audio_info.mode_count && stream->audio_info.flags.all) { 2059afaacef4SHarry Wentland pipe_ctx->stream_res.audio = find_first_free_audio( 2060f24b0522SPaul Hsieh &context->res_ctx, pool, pipe_ctx->stream_res.stream_enc->id, dc_ctx->dce_version); 20614562236bSHarry Wentland 20624562236bSHarry Wentland /* 20634562236bSHarry Wentland * Audio assigned in order first come first get. 20644562236bSHarry Wentland * There are asics which has number of audio 20654562236bSHarry Wentland * resources less then number of pipes 20664562236bSHarry Wentland */ 2067afaacef4SHarry Wentland if (pipe_ctx->stream_res.audio) 20681dc90497SAndrey Grodzovsky update_audio_usage(&context->res_ctx, pool, 20691dc90497SAndrey Grodzovsky pipe_ctx->stream_res.audio, true); 20704562236bSHarry Wentland } 20714562236bSHarry Wentland 20729aef1a31SSivapiriyanKumarasamy /* Add ABM to the resource if on EDP */ 20735dba4991SBhawanpreet Lakha if (pipe_ctx->stream && dc_is_embedded_signal(pipe_ctx->stream->signal)) { 207420f2ffe5SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN) 20755dba4991SBhawanpreet Lakha if (pool->abm) 20769aef1a31SSivapiriyanKumarasamy pipe_ctx->stream_res.abm = pool->abm; 20775dba4991SBhawanpreet Lakha else 20785dba4991SBhawanpreet Lakha pipe_ctx->stream_res.abm = pool->multiple_abms[pipe_ctx->stream_res.tg->inst]; 20795dba4991SBhawanpreet Lakha #else 20805dba4991SBhawanpreet Lakha pipe_ctx->stream_res.abm = pool->abm; 20815dba4991SBhawanpreet Lakha #endif 20825dba4991SBhawanpreet Lakha } 20839aef1a31SSivapiriyanKumarasamy 20841dc90497SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 20851dc90497SAndrey Grodzovsky if (context->streams[i] == stream) { 20866b670fa9SHarry Wentland context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; 20873f0940f8SCharlene Liu context->stream_status[i].stream_enc_inst = pipe_ctx->stream_res.stream_enc->stream_enc_inst; 20885fdb7c4cSNicholas Kazlauskas context->stream_status[i].audio_inst = 20895fdb7c4cSNicholas Kazlauskas pipe_ctx->stream_res.audio ? pipe_ctx->stream_res.audio->inst : -1; 20905fdb7c4cSNicholas Kazlauskas 20911dc90497SAndrey Grodzovsky return DC_OK; 20924562236bSHarry Wentland } 20934562236bSHarry Wentland 20941dc90497SAndrey Grodzovsky DC_ERROR("Stream %p not found in new ctx!\n", stream); 20951dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 20964562236bSHarry Wentland } 20974562236bSHarry Wentland 20982119aa17SDavid Francis /** 20992119aa17SDavid Francis * dc_resource_state_copy_construct_current() - Creates a new dc_state from existing state 21002119aa17SDavid Francis * Is a shallow copy. Increments refcounts on existing streams and planes. 21012119aa17SDavid Francis * @dc: copy out of dc->current_state 21022119aa17SDavid Francis * @dst_ctx: copy into this 21032119aa17SDavid Francis */ 2104f36cc577SBhawanpreet Lakha void dc_resource_state_copy_construct_current( 21051dc90497SAndrey Grodzovsky const struct dc *dc, 2106608ac7bbSJerry Zuo struct dc_state *dst_ctx) 21071dc90497SAndrey Grodzovsky { 2108f36cc577SBhawanpreet Lakha dc_resource_state_copy_construct(dc->current_state, dst_ctx); 21091dc90497SAndrey Grodzovsky } 21101dc90497SAndrey Grodzovsky 2111ab8db3e1SAndrey Grodzovsky 2112ab8db3e1SAndrey Grodzovsky void dc_resource_state_construct( 2113ab8db3e1SAndrey Grodzovsky const struct dc *dc, 2114ab8db3e1SAndrey Grodzovsky struct dc_state *dst_ctx) 2115ab8db3e1SAndrey Grodzovsky { 2116dc88b4a6SEric Yang dst_ctx->clk_mgr = dc->clk_mgr; 2117ab8db3e1SAndrey Grodzovsky } 2118ab8db3e1SAndrey Grodzovsky 21196d822156SNikola Cornij 21206d822156SNikola Cornij bool dc_resource_is_dsc_encoding_supported(const struct dc *dc) 21216d822156SNikola Cornij { 21226d822156SNikola Cornij return dc->res_pool->res_cap->num_dsc > 0; 21236d822156SNikola Cornij } 21246d822156SNikola Cornij 21256d822156SNikola Cornij 21262119aa17SDavid Francis /** 21272119aa17SDavid Francis * dc_validate_global_state() - Determine if HW can support a given state 21282119aa17SDavid Francis * Checks HW resource availability and bandwidth requirement. 21292119aa17SDavid Francis * @dc: dc struct for this driver 21302119aa17SDavid Francis * @new_ctx: state to be validated 2131afcd526bSJoshua Aberback * @fast_validate: set to true if only yes/no to support matters 21322119aa17SDavid Francis * 21332119aa17SDavid Francis * Return: DC_OK if the result can be programmed. Otherwise, an error code. 21342119aa17SDavid Francis */ 2135e750d56dSYongqiang Sun enum dc_status dc_validate_global_state( 21361dc90497SAndrey Grodzovsky struct dc *dc, 2137afcd526bSJoshua Aberback struct dc_state *new_ctx, 2138afcd526bSJoshua Aberback bool fast_validate) 21391dc90497SAndrey Grodzovsky { 21401dc90497SAndrey Grodzovsky enum dc_status result = DC_ERROR_UNEXPECTED; 21411dc90497SAndrey Grodzovsky int i, j; 21421dc90497SAndrey Grodzovsky 2143e41ab030SHarry Wentland if (!new_ctx) 2144e41ab030SHarry Wentland return DC_ERROR_UNEXPECTED; 2145cbaf919fSNicholas Kazlauskas #if defined(CONFIG_DRM_AMD_DC_DCN3_1) 2146cbaf919fSNicholas Kazlauskas 2147cbaf919fSNicholas Kazlauskas /* 2148cbaf919fSNicholas Kazlauskas * Update link encoder to stream assignment. 2149cbaf919fSNicholas Kazlauskas * TODO: Split out reason allocation from validation. 2150cbaf919fSNicholas Kazlauskas */ 2151cbaf919fSNicholas Kazlauskas if (dc->res_pool->funcs->link_encs_assign) 2152cbaf919fSNicholas Kazlauskas dc->res_pool->funcs->link_encs_assign( 2153cbaf919fSNicholas Kazlauskas dc, new_ctx, new_ctx->streams, new_ctx->stream_count); 2154cbaf919fSNicholas Kazlauskas #endif 2155e41ab030SHarry Wentland 2156d596e5d0SYongqiang Sun if (dc->res_pool->funcs->validate_global) { 2157d596e5d0SYongqiang Sun result = dc->res_pool->funcs->validate_global(dc, new_ctx); 2158d596e5d0SYongqiang Sun if (result != DC_OK) 2159d596e5d0SYongqiang Sun return result; 2160d596e5d0SYongqiang Sun } 21611dc90497SAndrey Grodzovsky 2162e41ab030SHarry Wentland for (i = 0; i < new_ctx->stream_count; i++) { 21631dc90497SAndrey Grodzovsky struct dc_stream_state *stream = new_ctx->streams[i]; 21641dc90497SAndrey Grodzovsky 21651dc90497SAndrey Grodzovsky for (j = 0; j < dc->res_pool->pipe_count; j++) { 21661dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[j]; 21671dc90497SAndrey Grodzovsky 21681dc90497SAndrey Grodzovsky if (pipe_ctx->stream != stream) 21691dc90497SAndrey Grodzovsky continue; 21701dc90497SAndrey Grodzovsky 21718d8c82b6SJoseph Gravenor if (dc->res_pool->funcs->patch_unknown_plane_state && 217274eac5f3SSu Sung Chung pipe_ctx->plane_state && 217374eac5f3SSu Sung Chung pipe_ctx->plane_state->tiling_info.gfx9.swizzle == DC_SW_UNKNOWN) { 21748d8c82b6SJoseph Gravenor result = dc->res_pool->funcs->patch_unknown_plane_state(pipe_ctx->plane_state); 217574eac5f3SSu Sung Chung if (result != DC_OK) 217674eac5f3SSu Sung Chung return result; 217774eac5f3SSu Sung Chung } 217874eac5f3SSu Sung Chung 21791dc90497SAndrey Grodzovsky /* Switch to dp clock source only if there is 21801dc90497SAndrey Grodzovsky * no non dp stream that shares the same timing 21811dc90497SAndrey Grodzovsky * with the dp stream. 21821dc90497SAndrey Grodzovsky */ 21831dc90497SAndrey Grodzovsky if (dc_is_dp_signal(pipe_ctx->stream->signal) && 21841dc90497SAndrey Grodzovsky !find_pll_sharable_stream(stream, new_ctx)) { 21851dc90497SAndrey Grodzovsky 21869d0dcecdSHarry Wentland resource_unreference_clock_source( 21871dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 21881dc90497SAndrey Grodzovsky dc->res_pool, 21899d0dcecdSHarry Wentland pipe_ctx->clock_source); 21904a629536SHarry Wentland 21911dc90497SAndrey Grodzovsky pipe_ctx->clock_source = dc->res_pool->dp_clock_source; 21921dc90497SAndrey Grodzovsky resource_reference_clock_source( 21931dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 21941dc90497SAndrey Grodzovsky dc->res_pool, 21951dc90497SAndrey Grodzovsky pipe_ctx->clock_source); 21961dc90497SAndrey Grodzovsky } 21971dc90497SAndrey Grodzovsky } 21981dc90497SAndrey Grodzovsky } 21991dc90497SAndrey Grodzovsky 22001dc90497SAndrey Grodzovsky result = resource_build_scaling_params_for_context(dc, new_ctx); 22011dc90497SAndrey Grodzovsky 22021dc90497SAndrey Grodzovsky if (result == DC_OK) 2203afcd526bSJoshua Aberback if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, fast_validate)) 22041dc90497SAndrey Grodzovsky result = DC_FAIL_BANDWIDTH_VALIDATE; 22051dc90497SAndrey Grodzovsky 22061dc90497SAndrey Grodzovsky return result; 22071dc90497SAndrey Grodzovsky } 22081dc90497SAndrey Grodzovsky 22096e4d6beeSTony Cheng static void patch_gamut_packet_checksum( 2210e09b6473SAnthony Koo struct dc_info_packet *gamut_packet) 22114562236bSHarry Wentland { 22124562236bSHarry Wentland /* For gamut we recalc checksum */ 22136e4d6beeSTony Cheng if (gamut_packet->valid) { 22144562236bSHarry Wentland uint8_t chk_sum = 0; 22154562236bSHarry Wentland uint8_t *ptr; 22164562236bSHarry Wentland uint8_t i; 22174562236bSHarry Wentland 22184562236bSHarry Wentland /*start of the Gamut data. */ 22196e4d6beeSTony Cheng ptr = &gamut_packet->sb[3]; 22204562236bSHarry Wentland 22216e4d6beeSTony Cheng for (i = 0; i <= gamut_packet->sb[1]; i++) 22224562236bSHarry Wentland chk_sum += ptr[i]; 22234562236bSHarry Wentland 22246e4d6beeSTony Cheng gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum); 22251646a6feSAndrew Wong } 22264562236bSHarry Wentland } 22274562236bSHarry Wentland 22284562236bSHarry Wentland static void set_avi_info_frame( 2229e09b6473SAnthony Koo struct dc_info_packet *info_packet, 22304562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 22314562236bSHarry Wentland { 22320971c40eSHarry Wentland struct dc_stream_state *stream = pipe_ctx->stream; 22334562236bSHarry Wentland enum dc_color_space color_space = COLOR_SPACE_UNKNOWN; 22344562236bSHarry Wentland uint32_t pixel_encoding = 0; 22354562236bSHarry Wentland enum scanning_type scan_type = SCANNING_TYPE_NODATA; 22364562236bSHarry Wentland enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA; 22374562236bSHarry Wentland bool itc = false; 223850e27654SZeyu Fan uint8_t itc_value = 0; 22394562236bSHarry Wentland uint8_t cn0_cn1 = 0; 224050e27654SZeyu Fan unsigned int cn0_cn1_value = 0; 22414562236bSHarry Wentland uint8_t *check_sum = NULL; 22424562236bSHarry Wentland uint8_t byte_index = 0; 2243754e3673SAnthony Koo union hdmi_info_packet hdmi_info; 224450e27654SZeyu Fan union display_content_support support = {0}; 22454fa086b9SLeo (Sunpeng) Li unsigned int vic = pipe_ctx->stream->timing.vic; 224615e17335SCharlene Liu enum dc_timing_3d_format format; 22474562236bSHarry Wentland 2248754e3673SAnthony Koo memset(&hdmi_info, 0, sizeof(union hdmi_info_packet)); 2249754e3673SAnthony Koo 22504fa086b9SLeo (Sunpeng) Li color_space = pipe_ctx->stream->output_color_space; 2251e5f2038eSCharlene Liu if (color_space == COLOR_SPACE_UNKNOWN) 22524fa086b9SLeo (Sunpeng) Li color_space = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ? 2253e5f2038eSCharlene Liu COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709; 22544562236bSHarry Wentland 22554562236bSHarry Wentland /* Initialize header */ 2256e09b6473SAnthony Koo hdmi_info.bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI; 22574562236bSHarry Wentland /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall 22584562236bSHarry Wentland * not be used in HDMI 2.0 (Section 10.1) */ 2259e09b6473SAnthony Koo hdmi_info.bits.header.version = 2; 2260e09b6473SAnthony Koo hdmi_info.bits.header.length = HDMI_AVI_INFOFRAME_SIZE; 22614562236bSHarry Wentland 22624562236bSHarry Wentland /* 22634562236bSHarry Wentland * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built 22644562236bSHarry Wentland * according to HDMI 2.0 spec (Section 10.1) 22654562236bSHarry Wentland */ 22664562236bSHarry Wentland 22674fa086b9SLeo (Sunpeng) Li switch (stream->timing.pixel_encoding) { 22684562236bSHarry Wentland case PIXEL_ENCODING_YCBCR422: 22694562236bSHarry Wentland pixel_encoding = 1; 22704562236bSHarry Wentland break; 22714562236bSHarry Wentland 22724562236bSHarry Wentland case PIXEL_ENCODING_YCBCR444: 22734562236bSHarry Wentland pixel_encoding = 2; 22744562236bSHarry Wentland break; 22754562236bSHarry Wentland case PIXEL_ENCODING_YCBCR420: 22764562236bSHarry Wentland pixel_encoding = 3; 22774562236bSHarry Wentland break; 22784562236bSHarry Wentland 22794562236bSHarry Wentland case PIXEL_ENCODING_RGB: 22804562236bSHarry Wentland default: 22814562236bSHarry Wentland pixel_encoding = 0; 22824562236bSHarry Wentland } 22834562236bSHarry Wentland 22844562236bSHarry Wentland /* Y0_Y1_Y2 : The pixel encoding */ 22854562236bSHarry Wentland /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */ 2286e09b6473SAnthony Koo hdmi_info.bits.Y0_Y1_Y2 = pixel_encoding; 22874562236bSHarry Wentland 22884562236bSHarry Wentland /* A0 = 1 Active Format Information valid */ 2289e09b6473SAnthony Koo hdmi_info.bits.A0 = ACTIVE_FORMAT_VALID; 22904562236bSHarry Wentland 22914562236bSHarry Wentland /* B0, B1 = 3; Bar info data is valid */ 2292e09b6473SAnthony Koo hdmi_info.bits.B0_B1 = BAR_INFO_BOTH_VALID; 22934562236bSHarry Wentland 2294e09b6473SAnthony Koo hdmi_info.bits.SC0_SC1 = PICTURE_SCALING_UNIFORM; 22954562236bSHarry Wentland 22964562236bSHarry Wentland /* S0, S1 : Underscan / Overscan */ 22974562236bSHarry Wentland /* TODO: un-hardcode scan type */ 22984562236bSHarry Wentland scan_type = SCANNING_TYPE_UNDERSCAN; 2299e09b6473SAnthony Koo hdmi_info.bits.S0_S1 = scan_type; 23004562236bSHarry Wentland 23014562236bSHarry Wentland /* C0, C1 : Colorimetry */ 23028fde5884SCharlene Liu if (color_space == COLOR_SPACE_YCBCR709 || 230315e17335SCharlene Liu color_space == COLOR_SPACE_YCBCR709_LIMITED) 2304e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709; 23058fde5884SCharlene Liu else if (color_space == COLOR_SPACE_YCBCR601 || 23068fde5884SCharlene Liu color_space == COLOR_SPACE_YCBCR601_LIMITED) 2307e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_ITU601; 23088fde5884SCharlene Liu else { 2309e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_NO_DATA; 23108fde5884SCharlene Liu } 2311534db198SAmy Zhang if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE || 2312534db198SAmy Zhang color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE || 2313534db198SAmy Zhang color_space == COLOR_SPACE_2020_YCBCR) { 2314e09b6473SAnthony Koo hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR; 2315e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; 2316534db198SAmy Zhang } else if (color_space == COLOR_SPACE_ADOBERGB) { 2317e09b6473SAnthony Koo hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB; 2318e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; 2319534db198SAmy Zhang } 2320534db198SAmy Zhang 23214562236bSHarry Wentland /* TODO: un-hardcode aspect ratio */ 23224fa086b9SLeo (Sunpeng) Li aspect = stream->timing.aspect_ratio; 23234562236bSHarry Wentland 23244562236bSHarry Wentland switch (aspect) { 23254562236bSHarry Wentland case ASPECT_RATIO_4_3: 23264562236bSHarry Wentland case ASPECT_RATIO_16_9: 2327e09b6473SAnthony Koo hdmi_info.bits.M0_M1 = aspect; 23284562236bSHarry Wentland break; 23294562236bSHarry Wentland 23304562236bSHarry Wentland case ASPECT_RATIO_NO_DATA: 23314562236bSHarry Wentland case ASPECT_RATIO_64_27: 23324562236bSHarry Wentland case ASPECT_RATIO_256_135: 23334562236bSHarry Wentland default: 2334e09b6473SAnthony Koo hdmi_info.bits.M0_M1 = 0; 23354562236bSHarry Wentland } 23364562236bSHarry Wentland 23374562236bSHarry Wentland /* Active Format Aspect ratio - same as Picture Aspect Ratio. */ 2338e09b6473SAnthony Koo hdmi_info.bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; 23394562236bSHarry Wentland 23404562236bSHarry Wentland /* TODO: un-hardcode cn0_cn1 and itc */ 234150e27654SZeyu Fan 23424562236bSHarry Wentland cn0_cn1 = 0; 234350e27654SZeyu Fan cn0_cn1_value = 0; 234450e27654SZeyu Fan 234550e27654SZeyu Fan itc = true; 234650e27654SZeyu Fan itc_value = 1; 234750e27654SZeyu Fan 2348ceb3dbb4SJun Lei support = stream->content_support; 23494562236bSHarry Wentland 23504562236bSHarry Wentland if (itc) { 235150e27654SZeyu Fan if (!support.bits.valid_content_type) { 235250e27654SZeyu Fan cn0_cn1_value = 0; 235350e27654SZeyu Fan } else { 235450e27654SZeyu Fan if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) { 235550e27654SZeyu Fan if (support.bits.graphics_content == 1) { 235650e27654SZeyu Fan cn0_cn1_value = 0; 235750e27654SZeyu Fan } 235850e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) { 235950e27654SZeyu Fan if (support.bits.photo_content == 1) { 236050e27654SZeyu Fan cn0_cn1_value = 1; 236150e27654SZeyu Fan } else { 236250e27654SZeyu Fan cn0_cn1_value = 0; 236350e27654SZeyu Fan itc_value = 0; 236450e27654SZeyu Fan } 236550e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) { 236650e27654SZeyu Fan if (support.bits.cinema_content == 1) { 236750e27654SZeyu Fan cn0_cn1_value = 2; 236850e27654SZeyu Fan } else { 236950e27654SZeyu Fan cn0_cn1_value = 0; 237050e27654SZeyu Fan itc_value = 0; 237150e27654SZeyu Fan } 237250e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) { 237350e27654SZeyu Fan if (support.bits.game_content == 1) { 237450e27654SZeyu Fan cn0_cn1_value = 3; 237550e27654SZeyu Fan } else { 237650e27654SZeyu Fan cn0_cn1_value = 0; 237750e27654SZeyu Fan itc_value = 0; 237850e27654SZeyu Fan } 237950e27654SZeyu Fan } 238050e27654SZeyu Fan } 2381e09b6473SAnthony Koo hdmi_info.bits.CN0_CN1 = cn0_cn1_value; 2382e09b6473SAnthony Koo hdmi_info.bits.ITC = itc_value; 23834562236bSHarry Wentland } 23844562236bSHarry Wentland 2385fdf7d4f5SDillon Varone if (stream->qs_bit == 1) { 2386fdf7d4f5SDillon Varone if (color_space == COLOR_SPACE_SRGB || 2387fdf7d4f5SDillon Varone color_space == COLOR_SPACE_2020_RGB_FULLRANGE) 2388fdf7d4f5SDillon Varone hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; 2389fdf7d4f5SDillon Varone else if (color_space == COLOR_SPACE_SRGB_LIMITED || 2390fdf7d4f5SDillon Varone color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) 2391fdf7d4f5SDillon Varone hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE; 2392fdf7d4f5SDillon Varone else 2393fdf7d4f5SDillon Varone hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 2394fdf7d4f5SDillon Varone } else 2395fdf7d4f5SDillon Varone hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 2396fdf7d4f5SDillon Varone 23974562236bSHarry Wentland /* TODO : We should handle YCC quantization */ 23984562236bSHarry Wentland /* but we do not have matrix calculation */ 2399fdf7d4f5SDillon Varone if (stream->qy_bit == 1) { 240050e27654SZeyu Fan if (color_space == COLOR_SPACE_SRGB || 2401fdf7d4f5SDillon Varone color_space == COLOR_SPACE_2020_RGB_FULLRANGE) 2402993dca3eSQingqing Zhuo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 2403fdf7d4f5SDillon Varone else if (color_space == COLOR_SPACE_SRGB_LIMITED || 2404fdf7d4f5SDillon Varone color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) 2405e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 2406fdf7d4f5SDillon Varone else 2407e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 2408fdf7d4f5SDillon Varone } else 2409e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 241050e27654SZeyu Fan 241115e17335SCharlene Liu ///VIC 24124fa086b9SLeo (Sunpeng) Li format = stream->timing.timing_3d_format; 241315e17335SCharlene Liu /*todo, add 3DStereo support*/ 241415e17335SCharlene Liu if (format != TIMING_3D_FORMAT_NONE) { 241515e17335SCharlene Liu // Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled 24164fa086b9SLeo (Sunpeng) Li switch (pipe_ctx->stream->timing.hdmi_vic) { 241715e17335SCharlene Liu case 1: 241815e17335SCharlene Liu vic = 95; 241915e17335SCharlene Liu break; 242015e17335SCharlene Liu case 2: 242115e17335SCharlene Liu vic = 94; 242215e17335SCharlene Liu break; 242315e17335SCharlene Liu case 3: 242415e17335SCharlene Liu vic = 93; 242515e17335SCharlene Liu break; 242615e17335SCharlene Liu case 4: 242715e17335SCharlene Liu vic = 98; 242815e17335SCharlene Liu break; 242915e17335SCharlene Liu default: 243015e17335SCharlene Liu break; 243115e17335SCharlene Liu } 243215e17335SCharlene Liu } 2433efa02336SChris Park /* If VIC >= 128, the Source shall use AVI InfoFrame Version 3*/ 2434e09b6473SAnthony Koo hdmi_info.bits.VIC0_VIC7 = vic; 2435efa02336SChris Park if (vic >= 128) 2436efa02336SChris Park hdmi_info.bits.header.version = 3; 2437efa02336SChris Park /* If (C1, C0)=(1, 1) and (EC2, EC1, EC0)=(1, 1, 1), 2438efa02336SChris Park * the Source shall use 20 AVI InfoFrame Version 4 2439efa02336SChris Park */ 2440efa02336SChris Park if (hdmi_info.bits.C0_C1 == COLORIMETRY_EXTENDED && 2441efa02336SChris Park hdmi_info.bits.EC0_EC2 == COLORIMETRYEX_RESERVED) { 2442efa02336SChris Park hdmi_info.bits.header.version = 4; 2443efa02336SChris Park hdmi_info.bits.header.length = 14; 2444efa02336SChris Park } 24454562236bSHarry Wentland 24464562236bSHarry Wentland /* pixel repetition 24474562236bSHarry Wentland * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel 24484562236bSHarry Wentland * repetition start from 1 */ 2449e09b6473SAnthony Koo hdmi_info.bits.PR0_PR3 = 0; 24504562236bSHarry Wentland 24514562236bSHarry Wentland /* Bar Info 24524562236bSHarry Wentland * barTop: Line Number of End of Top Bar. 24534562236bSHarry Wentland * barBottom: Line Number of Start of Bottom Bar. 24544562236bSHarry Wentland * barLeft: Pixel Number of End of Left Bar. 24554562236bSHarry Wentland * barRight: Pixel Number of Start of Right Bar. */ 2456e09b6473SAnthony Koo hdmi_info.bits.bar_top = stream->timing.v_border_top; 2457e09b6473SAnthony Koo hdmi_info.bits.bar_bottom = (stream->timing.v_total 24584fa086b9SLeo (Sunpeng) Li - stream->timing.v_border_bottom + 1); 2459e09b6473SAnthony Koo hdmi_info.bits.bar_left = stream->timing.h_border_left; 2460e09b6473SAnthony Koo hdmi_info.bits.bar_right = (stream->timing.h_total 24614fa086b9SLeo (Sunpeng) Li - stream->timing.h_border_right + 1); 24624562236bSHarry Wentland 24632f482c4fSChris Park /* Additional Colorimetry Extension 24642f482c4fSChris Park * Used in conduction with C0-C1 and EC0-EC2 24652f482c4fSChris Park * 0 = DCI-P3 RGB (D65) 24662f482c4fSChris Park * 1 = DCI-P3 RGB (theater) 24672f482c4fSChris Park */ 24682f482c4fSChris Park hdmi_info.bits.ACE0_ACE3 = 0; 24692f482c4fSChris Park 24704562236bSHarry Wentland /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ 2471e09b6473SAnthony Koo check_sum = &hdmi_info.packet_raw_data.sb[0]; 2472e8d726b7SReza Amini 2473efa02336SChris Park *check_sum = HDMI_INFOFRAME_TYPE_AVI + hdmi_info.bits.header.length + hdmi_info.bits.header.version; 24744562236bSHarry Wentland 2475efa02336SChris Park for (byte_index = 1; byte_index <= hdmi_info.bits.header.length; byte_index++) 2476e09b6473SAnthony Koo *check_sum += hdmi_info.packet_raw_data.sb[byte_index]; 24774562236bSHarry Wentland 24784562236bSHarry Wentland /* one byte complement */ 24794562236bSHarry Wentland *check_sum = (uint8_t) (0x100 - *check_sum); 24804562236bSHarry Wentland 24814562236bSHarry Wentland /* Store in hw_path_mode */ 2482e09b6473SAnthony Koo info_packet->hb0 = hdmi_info.packet_raw_data.hb0; 2483e09b6473SAnthony Koo info_packet->hb1 = hdmi_info.packet_raw_data.hb1; 2484e09b6473SAnthony Koo info_packet->hb2 = hdmi_info.packet_raw_data.hb2; 24854562236bSHarry Wentland 2486e09b6473SAnthony Koo for (byte_index = 0; byte_index < sizeof(hdmi_info.packet_raw_data.sb); byte_index++) 2487e09b6473SAnthony Koo info_packet->sb[byte_index] = hdmi_info.packet_raw_data.sb[byte_index]; 24884562236bSHarry Wentland 24894562236bSHarry Wentland info_packet->valid = true; 24904562236bSHarry Wentland } 24914562236bSHarry Wentland 24926e4d6beeSTony Cheng static void set_vendor_info_packet( 2493e09b6473SAnthony Koo struct dc_info_packet *info_packet, 24940971c40eSHarry Wentland struct dc_stream_state *stream) 24954562236bSHarry Wentland { 2496ecd0136bSHarmanprit Tatla /* SPD info packet for FreeSync */ 249715e17335SCharlene Liu 2498ecd0136bSHarmanprit Tatla /* Check if Freesync is supported. Return if false. If true, 2499ecd0136bSHarmanprit Tatla * set the corresponding bit in the info packet 2500ecd0136bSHarmanprit Tatla */ 2501ecd0136bSHarmanprit Tatla if (!stream->vsp_infopacket.valid) 25024562236bSHarry Wentland return; 25034562236bSHarry Wentland 2504ecd0136bSHarmanprit Tatla *info_packet = stream->vsp_infopacket; 25054562236bSHarry Wentland } 25064562236bSHarry Wentland 25076e4d6beeSTony Cheng static void set_spd_info_packet( 2508e09b6473SAnthony Koo struct dc_info_packet *info_packet, 25090971c40eSHarry Wentland struct dc_stream_state *stream) 25104562236bSHarry Wentland { 25114562236bSHarry Wentland /* SPD info packet for FreeSync */ 25124562236bSHarry Wentland 25134562236bSHarry Wentland /* Check if Freesync is supported. Return if false. If true, 25144562236bSHarry Wentland * set the corresponding bit in the info packet 25154562236bSHarry Wentland */ 251698e6436dSAnthony Koo if (!stream->vrr_infopacket.valid) 25174562236bSHarry Wentland return; 25184562236bSHarry Wentland 251998e6436dSAnthony Koo *info_packet = stream->vrr_infopacket; 25204562236bSHarry Wentland } 25214562236bSHarry Wentland 25221646a6feSAndrew Wong static void set_hdr_static_info_packet( 2523e09b6473SAnthony Koo struct dc_info_packet *info_packet, 25240971c40eSHarry Wentland struct dc_stream_state *stream) 25251646a6feSAndrew Wong { 25260eeef690SAnthony Koo /* HDR Static Metadata info packet for HDR10 */ 25271646a6feSAndrew Wong 2528a10dc97aSKrunoslav Kovac if (!stream->hdr_static_metadata.valid || 2529a10dc97aSKrunoslav Kovac stream->use_dynamic_meta) 253010bff005SYongqiang Sun return; 253110bff005SYongqiang Sun 25320eeef690SAnthony Koo *info_packet = stream->hdr_static_metadata; 25331646a6feSAndrew Wong } 25341646a6feSAndrew Wong 25356e4d6beeSTony Cheng static void set_vsc_info_packet( 2536e09b6473SAnthony Koo struct dc_info_packet *info_packet, 25370971c40eSHarry Wentland struct dc_stream_state *stream) 25384562236bSHarry Wentland { 25391336926fSAlvin lee if (!stream->vsc_infopacket.valid) 25404562236bSHarry Wentland return; 25414562236bSHarry Wentland 25421336926fSAlvin lee *info_packet = stream->vsc_infopacket; 25434562236bSHarry Wentland } 25444562236bSHarry Wentland 2545f36cc577SBhawanpreet Lakha void dc_resource_state_destruct(struct dc_state *context) 25464562236bSHarry Wentland { 25474562236bSHarry Wentland int i, j; 25484562236bSHarry Wentland 2549ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 25503be5262eSHarry Wentland for (j = 0; j < context->stream_status[i].plane_count; j++) 25513be5262eSHarry Wentland dc_plane_state_release( 25523be5262eSHarry Wentland context->stream_status[i].plane_states[j]); 25534562236bSHarry Wentland 25543be5262eSHarry Wentland context->stream_status[i].plane_count = 0; 25554fa086b9SLeo (Sunpeng) Li dc_stream_release(context->streams[i]); 2556ab2541b6SAric Cyr context->streams[i] = NULL; 25574562236bSHarry Wentland } 25585728d5e5SPaul Wu context->stream_count = 0; 25594562236bSHarry Wentland } 25604562236bSHarry Wentland 2561f36cc577SBhawanpreet Lakha void dc_resource_state_copy_construct( 2562608ac7bbSJerry Zuo const struct dc_state *src_ctx, 2563608ac7bbSJerry Zuo struct dc_state *dst_ctx) 25644562236bSHarry Wentland { 25654562236bSHarry Wentland int i, j; 25668ee5702aSDave Airlie struct kref refcount = dst_ctx->refcount; 25674562236bSHarry Wentland 25684562236bSHarry Wentland *dst_ctx = *src_ctx; 25694562236bSHarry Wentland 2570a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 25714562236bSHarry Wentland struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i]; 25724562236bSHarry Wentland 25734562236bSHarry Wentland if (cur_pipe->top_pipe) 25744562236bSHarry Wentland cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; 25754562236bSHarry Wentland 25764562236bSHarry Wentland if (cur_pipe->bottom_pipe) 25774562236bSHarry Wentland cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; 2578b1f6d01cSDmytro Laktyushkin 2579b1f6d01cSDmytro Laktyushkin if (cur_pipe->next_odm_pipe) 2580b1f6d01cSDmytro Laktyushkin cur_pipe->next_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx]; 2581b1f6d01cSDmytro Laktyushkin 2582b1f6d01cSDmytro Laktyushkin if (cur_pipe->prev_odm_pipe) 2583b1f6d01cSDmytro Laktyushkin cur_pipe->prev_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx]; 25844562236bSHarry Wentland } 25854562236bSHarry Wentland 2586ab2541b6SAric Cyr for (i = 0; i < dst_ctx->stream_count; i++) { 25874fa086b9SLeo (Sunpeng) Li dc_stream_retain(dst_ctx->streams[i]); 25883be5262eSHarry Wentland for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++) 25893be5262eSHarry Wentland dc_plane_state_retain( 25903be5262eSHarry Wentland dst_ctx->stream_status[i].plane_states[j]); 25914562236bSHarry Wentland } 25929a3afbb3SAndrey Grodzovsky 25939a3afbb3SAndrey Grodzovsky /* context refcount should not be overridden */ 25948ee5702aSDave Airlie dst_ctx->refcount = refcount; 25959a3afbb3SAndrey Grodzovsky 25964562236bSHarry Wentland } 25974562236bSHarry Wentland 25984562236bSHarry Wentland struct clock_source *dc_resource_find_first_free_pll( 2599a2b8659dSTony Cheng struct resource_context *res_ctx, 2600a2b8659dSTony Cheng const struct resource_pool *pool) 26014562236bSHarry Wentland { 26024562236bSHarry Wentland int i; 26034562236bSHarry Wentland 2604a2b8659dSTony Cheng for (i = 0; i < pool->clk_src_count; ++i) { 26054562236bSHarry Wentland if (res_ctx->clock_source_ref_count[i] == 0) 2606a2b8659dSTony Cheng return pool->clock_sources[i]; 26074562236bSHarry Wentland } 26084562236bSHarry Wentland 26094562236bSHarry Wentland return NULL; 26104562236bSHarry Wentland } 26114562236bSHarry Wentland 26124562236bSHarry Wentland void resource_build_info_frame(struct pipe_ctx *pipe_ctx) 26134562236bSHarry Wentland { 26144562236bSHarry Wentland enum signal_type signal = SIGNAL_TYPE_NONE; 261596c50c0dSHarry Wentland struct encoder_info_frame *info = &pipe_ctx->stream_res.encoder_info_frame; 26164562236bSHarry Wentland 26174562236bSHarry Wentland /* default all packets to invalid */ 26186e4d6beeSTony Cheng info->avi.valid = false; 26196e4d6beeSTony Cheng info->gamut.valid = false; 26206e4d6beeSTony Cheng info->vendor.valid = false; 2621630e3573SJeff Smith info->spd.valid = false; 26226e4d6beeSTony Cheng info->hdrsmd.valid = false; 26236e4d6beeSTony Cheng info->vsc.valid = false; 26244562236bSHarry Wentland 26254562236bSHarry Wentland signal = pipe_ctx->stream->signal; 26264562236bSHarry Wentland 26274562236bSHarry Wentland /* HDMi and DP have different info packets*/ 26284562236bSHarry Wentland if (dc_is_hdmi_signal(signal)) { 26296e4d6beeSTony Cheng set_avi_info_frame(&info->avi, pipe_ctx); 26306e4d6beeSTony Cheng 26316e4d6beeSTony Cheng set_vendor_info_packet(&info->vendor, pipe_ctx->stream); 26326e4d6beeSTony Cheng 26336e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 26346e4d6beeSTony Cheng 263556ef6ed9SAnthony Koo set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 26366e4d6beeSTony Cheng 2637a33fa99dSHarry Wentland } else if (dc_is_dp_signal(signal)) { 26386e4d6beeSTony Cheng set_vsc_info_packet(&info->vsc, pipe_ctx->stream); 26396e4d6beeSTony Cheng 26406e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 26416e4d6beeSTony Cheng 264256ef6ed9SAnthony Koo set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 2643a33fa99dSHarry Wentland } 26444562236bSHarry Wentland 26456e4d6beeSTony Cheng patch_gamut_packet_checksum(&info->gamut); 26464562236bSHarry Wentland } 26474562236bSHarry Wentland 26484562236bSHarry Wentland enum dc_status resource_map_clock_resources( 2649fb3466a4SBhawanpreet Lakha const struct dc *dc, 2650608ac7bbSJerry Zuo struct dc_state *context, 26511dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 26524562236bSHarry Wentland { 26534562236bSHarry Wentland /* acquire new resources */ 26541dc90497SAndrey Grodzovsky const struct resource_pool *pool = dc->res_pool; 26551dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream( 26561dc90497SAndrey Grodzovsky &context->res_ctx, stream); 26574562236bSHarry Wentland 26581dc90497SAndrey Grodzovsky if (!pipe_ctx) 26591dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 26604562236bSHarry Wentland 26614562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal) 26624562236bSHarry Wentland || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) 2663a2b8659dSTony Cheng pipe_ctx->clock_source = pool->dp_clock_source; 26644562236bSHarry Wentland else { 26654562236bSHarry Wentland pipe_ctx->clock_source = NULL; 26664562236bSHarry Wentland 2667fb3466a4SBhawanpreet Lakha if (!dc->config.disable_disp_pll_sharing) 26684ed4e51bSMikita Lipski pipe_ctx->clock_source = resource_find_used_clk_src_for_sharing( 26694562236bSHarry Wentland &context->res_ctx, 26704562236bSHarry Wentland pipe_ctx); 26714562236bSHarry Wentland 26724562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 26734562236bSHarry Wentland pipe_ctx->clock_source = 2674a2b8659dSTony Cheng dc_resource_find_first_free_pll( 2675a2b8659dSTony Cheng &context->res_ctx, 2676a2b8659dSTony Cheng pool); 26774562236bSHarry Wentland } 26784562236bSHarry Wentland 26794562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 26804562236bSHarry Wentland return DC_NO_CLOCK_SOURCE_RESOURCE; 26814562236bSHarry Wentland 26824562236bSHarry Wentland resource_reference_clock_source( 2683a2b8659dSTony Cheng &context->res_ctx, pool, 26844562236bSHarry Wentland pipe_ctx->clock_source); 26854562236bSHarry Wentland 26864562236bSHarry Wentland return DC_OK; 26874562236bSHarry Wentland } 26884562236bSHarry Wentland 26894562236bSHarry Wentland /* 26904562236bSHarry Wentland * Note: We need to disable output if clock sources change, 26914562236bSHarry Wentland * since bios does optimization and doesn't apply if changing 26924562236bSHarry Wentland * PHY when not already disabled. 26934562236bSHarry Wentland */ 26944562236bSHarry Wentland bool pipe_need_reprogram( 26954562236bSHarry Wentland struct pipe_ctx *pipe_ctx_old, 26964562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 26974562236bSHarry Wentland { 2698cfe4645eSDmytro Laktyushkin if (!pipe_ctx_old->stream) 2699cfe4645eSDmytro Laktyushkin return false; 2700cfe4645eSDmytro Laktyushkin 27014562236bSHarry Wentland if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink) 27024562236bSHarry Wentland return true; 27034562236bSHarry Wentland 27044562236bSHarry Wentland if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal) 27054562236bSHarry Wentland return true; 27064562236bSHarry Wentland 2707afaacef4SHarry Wentland if (pipe_ctx_old->stream_res.audio != pipe_ctx->stream_res.audio) 27084562236bSHarry Wentland return true; 27094562236bSHarry Wentland 27104562236bSHarry Wentland if (pipe_ctx_old->clock_source != pipe_ctx->clock_source 27114562236bSHarry Wentland && pipe_ctx_old->stream != pipe_ctx->stream) 27124562236bSHarry Wentland return true; 27134562236bSHarry Wentland 27148e9c4c8cSHarry Wentland if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc) 27154562236bSHarry Wentland return true; 27164562236bSHarry Wentland 27174562236bSHarry Wentland if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 27184562236bSHarry Wentland return true; 27194562236bSHarry Wentland 27201e7e86c4SSamson Tam if (pipe_ctx_old->stream->dpms_off != pipe_ctx->stream->dpms_off) 27211e7e86c4SSamson Tam return true; 27221e7e86c4SSamson Tam 2723eed928dcSCharlene Liu if (false == pipe_ctx_old->stream->link->link_state_valid && 2724eed928dcSCharlene Liu false == pipe_ctx_old->stream->dpms_off) 2725eed928dcSCharlene Liu return true; 2726eed928dcSCharlene Liu 272714e49bb3SNikola Cornij if (pipe_ctx_old->stream_res.dsc != pipe_ctx->stream_res.dsc) 272814e49bb3SNikola Cornij return true; 272914e49bb3SNikola Cornij 2730f42ef862SJimmy Kizito /* DIG link encoder resource assignment for stream changed. */ 2731f42ef862SJimmy Kizito if (pipe_ctx_old->stream->link_enc != pipe_ctx->stream->link_enc) 2732f42ef862SJimmy Kizito return true; 2733f42ef862SJimmy Kizito 27344562236bSHarry Wentland return false; 27354562236bSHarry Wentland } 2736529cad0fSDing Wang 27370971c40eSHarry Wentland void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, 2738529cad0fSDing Wang struct bit_depth_reduction_params *fmt_bit_depth) 2739529cad0fSDing Wang { 27404fa086b9SLeo (Sunpeng) Li enum dc_dither_option option = stream->dither_option; 2741529cad0fSDing Wang enum dc_pixel_encoding pixel_encoding = 27424fa086b9SLeo (Sunpeng) Li stream->timing.pixel_encoding; 2743529cad0fSDing Wang 2744529cad0fSDing Wang memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); 2745529cad0fSDing Wang 2746603767f9STony Cheng if (option == DITHER_OPTION_DEFAULT) { 2747603767f9STony Cheng switch (stream->timing.display_color_depth) { 2748603767f9STony Cheng case COLOR_DEPTH_666: 2749603767f9STony Cheng option = DITHER_OPTION_SPATIAL6; 2750603767f9STony Cheng break; 2751603767f9STony Cheng case COLOR_DEPTH_888: 2752603767f9STony Cheng option = DITHER_OPTION_SPATIAL8; 2753603767f9STony Cheng break; 2754603767f9STony Cheng case COLOR_DEPTH_101010: 2755603767f9STony Cheng option = DITHER_OPTION_SPATIAL10; 2756603767f9STony Cheng break; 2757603767f9STony Cheng default: 2758603767f9STony Cheng option = DITHER_OPTION_DISABLE; 2759603767f9STony Cheng } 2760603767f9STony Cheng } 2761603767f9STony Cheng 2762529cad0fSDing Wang if (option == DITHER_OPTION_DISABLE) 2763529cad0fSDing Wang return; 2764529cad0fSDing Wang 2765529cad0fSDing Wang if (option == DITHER_OPTION_TRUN6) { 2766529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2767529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 0; 2768529cad0fSDing Wang } else if (option == DITHER_OPTION_TRUN8 || 2769529cad0fSDing Wang option == DITHER_OPTION_TRUN8_SPATIAL6 || 2770529cad0fSDing Wang option == DITHER_OPTION_TRUN8_FM6) { 2771529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2772529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 1; 2773529cad0fSDing Wang } else if (option == DITHER_OPTION_TRUN10 || 2774529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL6 || 2775529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8 || 2776529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM8 || 2777529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM6 || 2778529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2779529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2780529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2781529cad0fSDing Wang } 2782529cad0fSDing Wang 2783529cad0fSDing Wang /* special case - Formatter can only reduce by 4 bits at most. 2784529cad0fSDing Wang * When reducing from 12 to 6 bits, 2785529cad0fSDing Wang * HW recommends we use trunc with round mode 2786529cad0fSDing Wang * (if we did nothing, trunc to 10 bits would be used) 2787529cad0fSDing Wang * note that any 12->10 bit reduction is ignored prior to DCE8, 2788529cad0fSDing Wang * as the input was 10 bits. 2789529cad0fSDing Wang */ 2790529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2791529cad0fSDing Wang option == DITHER_OPTION_SPATIAL6 || 2792529cad0fSDing Wang option == DITHER_OPTION_FM6) { 2793529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2794529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2795529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_MODE = 1; 2796529cad0fSDing Wang } 2797529cad0fSDing Wang 2798529cad0fSDing Wang /* spatial dither 2799529cad0fSDing Wang * note that spatial modes 1-3 are never used 2800529cad0fSDing Wang */ 2801529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2802529cad0fSDing Wang option == DITHER_OPTION_SPATIAL6 || 2803529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL6 || 2804529cad0fSDing Wang option == DITHER_OPTION_TRUN8_SPATIAL6) { 2805529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2806529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0; 2807529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2808529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2809529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2810529cad0fSDing Wang } else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM || 2811529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8 || 2812529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8_FM6 || 2813529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8 || 2814529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2815529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2816529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1; 2817529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2818529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2819529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2820529cad0fSDing Wang } else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM || 2821529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10 || 2822529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM8 || 2823529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM6) { 2824529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2825529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2; 2826529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2827529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2828529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2829529cad0fSDing Wang } 2830529cad0fSDing Wang 2831529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6 || 2832529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8 || 2833529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10) { 2834529cad0fSDing Wang fmt_bit_depth->flags.FRAME_RANDOM = 0; 2835529cad0fSDing Wang } else { 2836529cad0fSDing Wang fmt_bit_depth->flags.FRAME_RANDOM = 1; 2837529cad0fSDing Wang } 2838529cad0fSDing Wang 2839529cad0fSDing Wang ////////////////////// 2840529cad0fSDing Wang //// temporal dither 2841529cad0fSDing Wang ////////////////////// 2842529cad0fSDing Wang if (option == DITHER_OPTION_FM6 || 2843529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8_FM6 || 2844529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM6 || 2845529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM6 || 2846529cad0fSDing Wang option == DITHER_OPTION_TRUN8_FM6 || 2847529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2848529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2849529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0; 2850529cad0fSDing Wang } else if (option == DITHER_OPTION_FM8 || 2851529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM8 || 2852529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM8) { 2853529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2854529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1; 2855529cad0fSDing Wang } else if (option == DITHER_OPTION_FM10) { 2856529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2857529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2; 2858529cad0fSDing Wang } 2859529cad0fSDing Wang 2860529cad0fSDing Wang fmt_bit_depth->pixel_encoding = pixel_encoding; 2861529cad0fSDing Wang } 28629345d987SAndrey Grodzovsky 286362c933f9SYongqiang Sun enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) 28649345d987SAndrey Grodzovsky { 2865ceb3dbb4SJun Lei struct dc_link *link = stream->link; 28662b77dcc5SAnthony Koo struct timing_generator *tg = dc->res_pool->timing_generators[0]; 28679345d987SAndrey Grodzovsky enum dc_status res = DC_OK; 28689345d987SAndrey Grodzovsky 28694fa086b9SLeo (Sunpeng) Li calculate_phy_pix_clks(stream); 28709345d987SAndrey Grodzovsky 28714fa086b9SLeo (Sunpeng) Li if (!tg->funcs->validate_timing(tg, &stream->timing)) 28729345d987SAndrey Grodzovsky res = DC_FAIL_CONTROLLER_VALIDATE; 28739345d987SAndrey Grodzovsky 2874248cbed6SEric Bernstein if (res == DC_OK) { 28759345d987SAndrey Grodzovsky if (!link->link_enc->funcs->validate_output_with_stream( 28764fa086b9SLeo (Sunpeng) Li link->link_enc, stream)) 28779345d987SAndrey Grodzovsky res = DC_FAIL_ENC_VALIDATE; 2878248cbed6SEric Bernstein } 28799345d987SAndrey Grodzovsky 28809345d987SAndrey Grodzovsky /* TODO: validate audio ASIC caps, encoder */ 28819345d987SAndrey Grodzovsky 28829345d987SAndrey Grodzovsky if (res == DC_OK) 28834fa086b9SLeo (Sunpeng) Li res = dc_link_validate_mode_timing(stream, 28849345d987SAndrey Grodzovsky link, 28854fa086b9SLeo (Sunpeng) Li &stream->timing); 28869345d987SAndrey Grodzovsky 288762c933f9SYongqiang Sun return res; 28889345d987SAndrey Grodzovsky } 2889792671d7SAndrey Grodzovsky 289062c933f9SYongqiang Sun enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) 2891792671d7SAndrey Grodzovsky { 289262c933f9SYongqiang Sun enum dc_status res = DC_OK; 289362c933f9SYongqiang Sun 2894792671d7SAndrey Grodzovsky /* TODO For now validates pixel format only */ 28958e7095b9SDmytro Laktyushkin if (dc->res_pool->funcs->validate_plane) 289662c933f9SYongqiang Sun return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps); 2897792671d7SAndrey Grodzovsky 289862c933f9SYongqiang Sun return res; 2899792671d7SAndrey Grodzovsky } 290074eac5f3SSu Sung Chung 290174eac5f3SSu Sung Chung unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format) 290274eac5f3SSu Sung Chung { 290374eac5f3SSu Sung Chung switch (format) { 290474eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 290574eac5f3SSu Sung Chung return 8; 290674eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 290774eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 290874eac5f3SSu Sung Chung return 12; 290974eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 291074eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 291174eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 291274eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 291374eac5f3SSu Sung Chung return 16; 291474eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 291574eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 291674eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 291774eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 291874eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 291920f2ffe5SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN) 29205dba4991SBhawanpreet Lakha case SURFACE_PIXEL_FORMAT_GRPH_RGBE: 29215dba4991SBhawanpreet Lakha case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA: 29225dba4991SBhawanpreet Lakha #endif 292374eac5f3SSu Sung Chung return 32; 292474eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 2925050cd3d6SMario Kleiner case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: 292674eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 292774eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 292874eac5f3SSu Sung Chung return 64; 292974eac5f3SSu Sung Chung default: 293074eac5f3SSu Sung Chung ASSERT_CRITICAL(false); 293174eac5f3SSu Sung Chung return -1; 293274eac5f3SSu Sung Chung } 293374eac5f3SSu Sung Chung } 29343ab4cc65SCharlene Liu static unsigned int get_max_audio_sample_rate(struct audio_mode *modes) 29353ab4cc65SCharlene Liu { 29363ab4cc65SCharlene Liu if (modes) { 29373ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_192) 29383ab4cc65SCharlene Liu return 192000; 29393ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_176_4) 29403ab4cc65SCharlene Liu return 176400; 29413ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_96) 29423ab4cc65SCharlene Liu return 96000; 29433ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_88_2) 29443ab4cc65SCharlene Liu return 88200; 29453ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_48) 29463ab4cc65SCharlene Liu return 48000; 29473ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_44_1) 29483ab4cc65SCharlene Liu return 44100; 29493ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_32) 29503ab4cc65SCharlene Liu return 32000; 29513ab4cc65SCharlene Liu } 29523ab4cc65SCharlene Liu /*original logic when no audio info*/ 29533ab4cc65SCharlene Liu return 441000; 29543ab4cc65SCharlene Liu } 29553ab4cc65SCharlene Liu 29563ab4cc65SCharlene Liu void get_audio_check(struct audio_info *aud_modes, 29573ab4cc65SCharlene Liu struct audio_check *audio_chk) 29583ab4cc65SCharlene Liu { 29593ab4cc65SCharlene Liu unsigned int i; 29603ab4cc65SCharlene Liu unsigned int max_sample_rate = 0; 29613ab4cc65SCharlene Liu 29623ab4cc65SCharlene Liu if (aud_modes) { 29633ab4cc65SCharlene Liu audio_chk->audio_packet_type = 0x2;/*audio sample packet AP = .25 for layout0, 1 for layout1*/ 29643ab4cc65SCharlene Liu 29653ab4cc65SCharlene Liu audio_chk->max_audiosample_rate = 0; 29663ab4cc65SCharlene Liu for (i = 0; i < aud_modes->mode_count; i++) { 29673ab4cc65SCharlene Liu max_sample_rate = get_max_audio_sample_rate(&aud_modes->modes[i]); 29683ab4cc65SCharlene Liu if (audio_chk->max_audiosample_rate < max_sample_rate) 29693ab4cc65SCharlene Liu audio_chk->max_audiosample_rate = max_sample_rate; 29703ab4cc65SCharlene Liu /*dts takes the same as type 2: AP = 0.25*/ 29713ab4cc65SCharlene Liu } 29723ab4cc65SCharlene Liu /*check which one take more bandwidth*/ 29733ab4cc65SCharlene Liu if (audio_chk->max_audiosample_rate > 192000) 29743ab4cc65SCharlene Liu audio_chk->audio_packet_type = 0x9;/*AP =1*/ 29753ab4cc65SCharlene Liu audio_chk->acat = 0;/*not support*/ 29763ab4cc65SCharlene Liu } 29773ab4cc65SCharlene Liu } 29783ab4cc65SCharlene Liu 2979