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" 57cf2156e2SAlex Deucher #endif 585dba4991SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN3_0) 595dba4991SBhawanpreet Lakha #include "../dcn30/dcn30_resource.h" 605dba4991SBhawanpreet Lakha #endif 613a83e4e6SRoman Li #if defined(CONFIG_DRM_AMD_DC_DCN3_01) 623a83e4e6SRoman Li #include "../dcn301/dcn301_resource.h" 633a83e4e6SRoman Li #endif 6436d26912SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN3_02) 6536d26912SBhawanpreet Lakha #include "../dcn302/dcn302_resource.h" 6636d26912SBhawanpreet Lakha #endif 675d4b05ddSBhawanpreet Lakha 685d4b05ddSBhawanpreet Lakha #define DC_LOGGER_INIT(logger) 695d4b05ddSBhawanpreet Lakha 704562236bSHarry Wentland enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) 714562236bSHarry Wentland { 724562236bSHarry Wentland enum dce_version dc_version = DCE_VERSION_UNKNOWN; 734562236bSHarry Wentland switch (asic_id.chip_family) { 744562236bSHarry Wentland 75683b5950SMauro Rossi #if defined(CONFIG_DRM_AMD_DC_SI) 76683b5950SMauro Rossi case FAMILY_SI: 77683b5950SMauro Rossi if (ASIC_REV_IS_TAHITI_P(asic_id.hw_internal_rev) || 78683b5950SMauro Rossi ASIC_REV_IS_PITCAIRN_PM(asic_id.hw_internal_rev) || 79683b5950SMauro Rossi ASIC_REV_IS_CAPEVERDE_M(asic_id.hw_internal_rev)) 80683b5950SMauro Rossi dc_version = DCE_VERSION_6_0; 81683b5950SMauro Rossi else if (ASIC_REV_IS_OLAND_M(asic_id.hw_internal_rev)) 82683b5950SMauro Rossi dc_version = DCE_VERSION_6_4; 83683b5950SMauro Rossi else 84683b5950SMauro Rossi dc_version = DCE_VERSION_6_1; 85683b5950SMauro Rossi break; 86683b5950SMauro Rossi #endif 874562236bSHarry Wentland case FAMILY_CI: 884562236bSHarry Wentland dc_version = DCE_VERSION_8_0; 894562236bSHarry Wentland break; 90ebfdf0d0SAlex Deucher case FAMILY_KV: 91ebfdf0d0SAlex Deucher if (ASIC_REV_IS_KALINDI(asic_id.hw_internal_rev) || 92ebfdf0d0SAlex Deucher ASIC_REV_IS_BHAVANI(asic_id.hw_internal_rev) || 93ebfdf0d0SAlex Deucher ASIC_REV_IS_GODAVARI(asic_id.hw_internal_rev)) 94ebfdf0d0SAlex Deucher dc_version = DCE_VERSION_8_3; 95ebfdf0d0SAlex Deucher else 96ebfdf0d0SAlex Deucher dc_version = DCE_VERSION_8_1; 97ebfdf0d0SAlex Deucher break; 984562236bSHarry Wentland case FAMILY_CZ: 994562236bSHarry Wentland dc_version = DCE_VERSION_11_0; 1004562236bSHarry Wentland break; 1014562236bSHarry Wentland 1024562236bSHarry Wentland case FAMILY_VI: 1034562236bSHarry Wentland if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) || 1044562236bSHarry Wentland ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) { 1054562236bSHarry Wentland dc_version = DCE_VERSION_10_0; 1064562236bSHarry Wentland break; 1074562236bSHarry Wentland } 1084562236bSHarry Wentland if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) || 109b264d345SJordan Lazare ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || 110b264d345SJordan Lazare ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) { 1114562236bSHarry Wentland dc_version = DCE_VERSION_11_2; 1124562236bSHarry Wentland } 1130c75d5acSJerry (Fangzhi) Zuo if (ASIC_REV_IS_VEGAM(asic_id.hw_internal_rev)) 1140c75d5acSJerry (Fangzhi) Zuo dc_version = DCE_VERSION_11_22; 1154562236bSHarry Wentland break; 1162c8ad2d5SAlex Deucher case FAMILY_AI: 117b8b6ce89SLeo Li if (ASICREV_IS_VEGA20_P(asic_id.hw_internal_rev)) 118b8b6ce89SLeo Li dc_version = DCE_VERSION_12_1; 119b8b6ce89SLeo Li else 1202c8ad2d5SAlex Deucher dc_version = DCE_VERSION_12_0; 1212c8ad2d5SAlex Deucher break; 122b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 123ff5ef992SAlex Deucher case FAMILY_RV: 124ff5ef992SAlex Deucher dc_version = DCN_VERSION_1_0; 1250e3d73f1SBhawanpreet Lakha if (ASICREV_IS_RAVEN2(asic_id.hw_internal_rev)) 1260e3d73f1SBhawanpreet Lakha dc_version = DCN_VERSION_1_01; 127e22ece54SBhawanpreet Lakha if (ASICREV_IS_RENOIR(asic_id.hw_internal_rev)) 128e22ece54SBhawanpreet Lakha dc_version = DCN_VERSION_2_1; 1299ba93114SRoman Li if (ASICREV_IS_GREEN_SARDINE(asic_id.hw_internal_rev)) 1309ba93114SRoman Li dc_version = DCN_VERSION_2_1; 131ff5ef992SAlex Deucher break; 132ff5ef992SAlex Deucher #endif 1337ed4e635SHarry Wentland 1347ed4e635SHarry Wentland case FAMILY_NV: 1357ed4e635SHarry Wentland dc_version = DCN_VERSION_2_0; 1365dba4991SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN3_0) 1375dba4991SBhawanpreet Lakha if (ASICREV_IS_SIENNA_CICHLID_P(asic_id.hw_internal_rev)) 1385dba4991SBhawanpreet Lakha dc_version = DCN_VERSION_3_0; 1395dba4991SBhawanpreet Lakha #endif 14036d26912SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN3_02) 14136d26912SBhawanpreet Lakha if (ASICREV_IS_DIMGREY_CAVEFISH_P(asic_id.hw_internal_rev)) 14236d26912SBhawanpreet Lakha dc_version = DCN_VERSION_3_02; 14336d26912SBhawanpreet Lakha #endif 1447ed4e635SHarry Wentland break; 1453a83e4e6SRoman Li 1463a83e4e6SRoman Li #if defined(CONFIG_DRM_AMD_DC_DCN3_01) 1473a83e4e6SRoman Li case FAMILY_VGH: 1483a83e4e6SRoman Li dc_version = DCN_VERSION_3_01; 1493a83e4e6SRoman Li break; 1503a83e4e6SRoman Li #endif 1514562236bSHarry Wentland default: 1524562236bSHarry Wentland dc_version = DCE_VERSION_UNKNOWN; 1534562236bSHarry Wentland break; 1544562236bSHarry Wentland } 1554562236bSHarry Wentland return dc_version; 1564562236bSHarry Wentland } 1574562236bSHarry Wentland 158d9673c92SHarry Wentland struct resource_pool *dc_create_resource_pool(struct dc *dc, 159d9673c92SHarry Wentland const struct dc_init_data *init_data, 160d9673c92SHarry Wentland enum dce_version dc_version) 1614562236bSHarry Wentland { 1625ac3d3c9SCharlene Liu struct resource_pool *res_pool = NULL; 1634562236bSHarry Wentland 1644562236bSHarry Wentland switch (dc_version) { 165683b5950SMauro Rossi #if defined(CONFIG_DRM_AMD_DC_SI) 166683b5950SMauro Rossi case DCE_VERSION_6_0: 167683b5950SMauro Rossi res_pool = dce60_create_resource_pool( 168683b5950SMauro Rossi init_data->num_virtual_links, dc); 169683b5950SMauro Rossi break; 170683b5950SMauro Rossi case DCE_VERSION_6_1: 171683b5950SMauro Rossi res_pool = dce61_create_resource_pool( 172683b5950SMauro Rossi init_data->num_virtual_links, dc); 173683b5950SMauro Rossi break; 174683b5950SMauro Rossi case DCE_VERSION_6_4: 175683b5950SMauro Rossi res_pool = dce64_create_resource_pool( 176683b5950SMauro Rossi init_data->num_virtual_links, dc); 177683b5950SMauro Rossi break; 178683b5950SMauro Rossi #endif 1794562236bSHarry Wentland case DCE_VERSION_8_0: 1805ac3d3c9SCharlene Liu res_pool = dce80_create_resource_pool( 181d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1825ac3d3c9SCharlene Liu break; 1837992a629SAlex Deucher case DCE_VERSION_8_1: 1847992a629SAlex Deucher res_pool = dce81_create_resource_pool( 185d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1867992a629SAlex Deucher break; 1877992a629SAlex Deucher case DCE_VERSION_8_3: 1887992a629SAlex Deucher res_pool = dce83_create_resource_pool( 189d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1907992a629SAlex Deucher break; 1914562236bSHarry Wentland case DCE_VERSION_10_0: 1925ac3d3c9SCharlene Liu res_pool = dce100_create_resource_pool( 193d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1945ac3d3c9SCharlene Liu break; 1954562236bSHarry Wentland case DCE_VERSION_11_0: 1965ac3d3c9SCharlene Liu res_pool = dce110_create_resource_pool( 197d9673c92SHarry Wentland init_data->num_virtual_links, dc, 198d9673c92SHarry Wentland init_data->asic_id); 1995ac3d3c9SCharlene Liu break; 2004562236bSHarry Wentland case DCE_VERSION_11_2: 2010c75d5acSJerry (Fangzhi) Zuo case DCE_VERSION_11_22: 2025ac3d3c9SCharlene Liu res_pool = dce112_create_resource_pool( 203d9673c92SHarry Wentland init_data->num_virtual_links, dc); 2045ac3d3c9SCharlene Liu break; 2052c8ad2d5SAlex Deucher case DCE_VERSION_12_0: 206b8b6ce89SLeo Li case DCE_VERSION_12_1: 2072c8ad2d5SAlex Deucher res_pool = dce120_create_resource_pool( 208d9673c92SHarry Wentland init_data->num_virtual_links, dc); 2092c8ad2d5SAlex Deucher break; 210ff5ef992SAlex Deucher 211b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 212ff5ef992SAlex Deucher case DCN_VERSION_1_0: 2130e3d73f1SBhawanpreet Lakha case DCN_VERSION_1_01: 214d9673c92SHarry Wentland res_pool = dcn10_create_resource_pool(init_data, dc); 215ff5ef992SAlex Deucher break; 2163639fa68SZeyu Fan 2173639fa68SZeyu Fan 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; 224e22ece54SBhawanpreet Lakha #endif 2255dba4991SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN3_0) 2265dba4991SBhawanpreet Lakha case DCN_VERSION_3_0: 2275dba4991SBhawanpreet Lakha res_pool = dcn30_create_resource_pool(init_data, dc); 2285dba4991SBhawanpreet Lakha break; 2295dba4991SBhawanpreet Lakha #endif 2307ed4e635SHarry Wentland 2313a83e4e6SRoman Li #if defined(CONFIG_DRM_AMD_DC_DCN3_01) 2323a83e4e6SRoman Li case DCN_VERSION_3_01: 2333a83e4e6SRoman Li res_pool = dcn301_create_resource_pool(init_data, dc); 2343a83e4e6SRoman Li break; 2353a83e4e6SRoman Li #endif 23636d26912SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN3_02) 23736d26912SBhawanpreet Lakha case DCN_VERSION_3_02: 23836d26912SBhawanpreet Lakha res_pool = dcn302_create_resource_pool(init_data, dc); 23936d26912SBhawanpreet Lakha break; 24036d26912SBhawanpreet Lakha 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 3555dba4991SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN3_0) 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 4424562236bSHarry Wentland bool resource_are_streams_timing_synchronizable( 4430971c40eSHarry Wentland struct dc_stream_state *stream1, 4440971c40eSHarry Wentland struct dc_stream_state *stream2) 4454562236bSHarry Wentland { 4464fa086b9SLeo (Sunpeng) Li if (stream1->timing.h_total != stream2->timing.h_total) 4474562236bSHarry Wentland return false; 4484562236bSHarry Wentland 4494fa086b9SLeo (Sunpeng) Li if (stream1->timing.v_total != stream2->timing.v_total) 4504562236bSHarry Wentland return false; 4514562236bSHarry Wentland 4524fa086b9SLeo (Sunpeng) Li if (stream1->timing.h_addressable 4534fa086b9SLeo (Sunpeng) Li != stream2->timing.h_addressable) 4544562236bSHarry Wentland return false; 4554562236bSHarry Wentland 4564fa086b9SLeo (Sunpeng) Li if (stream1->timing.v_addressable 4574fa086b9SLeo (Sunpeng) Li != stream2->timing.v_addressable) 4584562236bSHarry Wentland return false; 4594562236bSHarry Wentland 4608582aea2SDavid Galiffi if (stream1->timing.v_front_porch 4618582aea2SDavid Galiffi != stream2->timing.v_front_porch) 4628582aea2SDavid Galiffi return false; 4638582aea2SDavid Galiffi 464380604e2SKen Chalmers if (stream1->timing.pix_clk_100hz 465380604e2SKen Chalmers != stream2->timing.pix_clk_100hz) 4664562236bSHarry Wentland return false; 4674562236bSHarry Wentland 4683e27e10eSMikita Lipski if (stream1->clamping.c_depth != stream2->clamping.c_depth) 4693e27e10eSMikita Lipski return false; 4703e27e10eSMikita Lipski 4714562236bSHarry Wentland if (stream1->phy_pix_clk != stream2->phy_pix_clk 4727e2fe319SCharlene Liu && (!dc_is_dp_signal(stream1->signal) 4737e2fe319SCharlene Liu || !dc_is_dp_signal(stream2->signal))) 4744562236bSHarry Wentland return false; 4754562236bSHarry Wentland 476d77f778eSCharlene Liu if (stream1->view_format != stream2->view_format) 477d77f778eSCharlene Liu return false; 478d77f778eSCharlene Liu 4790460f9abSJun Lei if (stream1->ignore_msa_timing_param || stream2->ignore_msa_timing_param) 4800460f9abSJun Lei return false; 4810460f9abSJun Lei 4824562236bSHarry Wentland return true; 4834562236bSHarry Wentland } 4843e27e10eSMikita Lipski static bool is_dp_and_hdmi_sharable( 4853e27e10eSMikita Lipski struct dc_stream_state *stream1, 4863e27e10eSMikita Lipski struct dc_stream_state *stream2) 4873e27e10eSMikita Lipski { 4883e27e10eSMikita Lipski if (stream1->ctx->dc->caps.disable_dp_clk_share) 4893e27e10eSMikita Lipski return false; 4903e27e10eSMikita Lipski 4913e27e10eSMikita Lipski if (stream1->clamping.c_depth != COLOR_DEPTH_888 || 4923e27e10eSMikita Lipski stream2->clamping.c_depth != COLOR_DEPTH_888) 4933e27e10eSMikita Lipski return false; 4943e27e10eSMikita Lipski 4953e27e10eSMikita Lipski return true; 4963e27e10eSMikita Lipski 4973e27e10eSMikita Lipski } 4984562236bSHarry Wentland 4994562236bSHarry Wentland static bool is_sharable_clk_src( 5004562236bSHarry Wentland const struct pipe_ctx *pipe_with_clk_src, 5014562236bSHarry Wentland const struct pipe_ctx *pipe) 5024562236bSHarry Wentland { 5034562236bSHarry Wentland if (pipe_with_clk_src->clock_source == NULL) 5044562236bSHarry Wentland return false; 5054562236bSHarry Wentland 5064562236bSHarry Wentland if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL) 5074562236bSHarry Wentland return false; 5084562236bSHarry Wentland 5093e27e10eSMikita Lipski if (dc_is_dp_signal(pipe_with_clk_src->stream->signal) || 5103e27e10eSMikita Lipski (dc_is_dp_signal(pipe->stream->signal) && 5113e27e10eSMikita Lipski !is_dp_and_hdmi_sharable(pipe_with_clk_src->stream, 5123e27e10eSMikita Lipski pipe->stream))) 5134562236bSHarry Wentland return false; 5144562236bSHarry Wentland 5154562236bSHarry Wentland if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal) 516fc69009eSMikita Lipski && dc_is_dual_link_signal(pipe->stream->signal)) 5174562236bSHarry Wentland return false; 5184562236bSHarry Wentland 5194562236bSHarry Wentland if (dc_is_hdmi_signal(pipe->stream->signal) 520fc69009eSMikita Lipski && dc_is_dual_link_signal(pipe_with_clk_src->stream->signal)) 5214562236bSHarry Wentland return false; 5224562236bSHarry Wentland 5234562236bSHarry Wentland if (!resource_are_streams_timing_synchronizable( 5244562236bSHarry Wentland pipe_with_clk_src->stream, pipe->stream)) 5254562236bSHarry Wentland return false; 5264562236bSHarry Wentland 5274562236bSHarry Wentland return true; 5284562236bSHarry Wentland } 5294562236bSHarry Wentland 5304562236bSHarry Wentland struct clock_source *resource_find_used_clk_src_for_sharing( 5314562236bSHarry Wentland struct resource_context *res_ctx, 5324562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 5334562236bSHarry Wentland { 5344562236bSHarry Wentland int i; 5354562236bSHarry Wentland 5364562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 5374562236bSHarry Wentland if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx)) 5384562236bSHarry Wentland return res_ctx->pipe_ctx[i].clock_source; 5394562236bSHarry Wentland } 5404562236bSHarry Wentland 5414562236bSHarry Wentland return NULL; 5424562236bSHarry Wentland } 5434562236bSHarry Wentland 5444562236bSHarry Wentland static enum pixel_format convert_pixel_format_to_dalsurface( 5454562236bSHarry Wentland enum surface_pixel_format surface_pixel_format) 5464562236bSHarry Wentland { 5474562236bSHarry Wentland enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 5484562236bSHarry Wentland 5494562236bSHarry Wentland switch (surface_pixel_format) { 5504562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 5514562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_INDEX8; 5524562236bSHarry Wentland break; 5534562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 5544562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_RGB565; 5554562236bSHarry Wentland break; 5564562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 5574562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_RGB565; 5584562236bSHarry Wentland break; 5594562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 5604562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB8888; 5614562236bSHarry Wentland break; 5628693049aSTony Cheng case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 5634562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB8888; 5644562236bSHarry Wentland break; 5654562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 5664562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 5674562236bSHarry Wentland break; 5684562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 5694562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 5704562236bSHarry Wentland break; 5714562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 5724562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS; 5734562236bSHarry Wentland break; 5744562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 5754562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 5764562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_FP16; 5774562236bSHarry Wentland break; 5784562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 5794562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 58087449a90SAnthony Koo dal_pixel_format = PIXEL_FORMAT_420BPP8; 5814562236bSHarry Wentland break; 582ffbcd19aSVitaly Prosyak case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 583ffbcd19aSVitaly Prosyak case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 58487449a90SAnthony Koo dal_pixel_format = PIXEL_FORMAT_420BPP10; 585ffbcd19aSVitaly Prosyak break; 5864562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 5874562236bSHarry Wentland default: 5884562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 5894562236bSHarry Wentland break; 5904562236bSHarry Wentland } 5914562236bSHarry Wentland return dal_pixel_format; 5924562236bSHarry Wentland } 5934562236bSHarry Wentland 5949b6067c0SDmytro Laktyushkin static inline void get_vp_scan_direction( 5959b6067c0SDmytro Laktyushkin enum dc_rotation_angle rotation, 5969b6067c0SDmytro Laktyushkin bool horizontal_mirror, 5979b6067c0SDmytro Laktyushkin bool *orthogonal_rotation, 5989b6067c0SDmytro Laktyushkin bool *flip_vert_scan_dir, 5999b6067c0SDmytro Laktyushkin bool *flip_horz_scan_dir) 6004562236bSHarry Wentland { 6019b6067c0SDmytro Laktyushkin *orthogonal_rotation = false; 6029b6067c0SDmytro Laktyushkin *flip_vert_scan_dir = false; 6039b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = false; 6049b6067c0SDmytro Laktyushkin if (rotation == ROTATION_ANGLE_180) { 6059b6067c0SDmytro Laktyushkin *flip_vert_scan_dir = true; 6069b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = true; 6079b6067c0SDmytro Laktyushkin } else if (rotation == ROTATION_ANGLE_90) { 6089b6067c0SDmytro Laktyushkin *orthogonal_rotation = true; 6099b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = true; 6109b6067c0SDmytro Laktyushkin } else if (rotation == ROTATION_ANGLE_270) { 6119b6067c0SDmytro Laktyushkin *orthogonal_rotation = true; 6129b6067c0SDmytro Laktyushkin *flip_vert_scan_dir = true; 6139b6067c0SDmytro Laktyushkin } 6149b6067c0SDmytro Laktyushkin 6159b6067c0SDmytro Laktyushkin if (horizontal_mirror) 6169b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = !*flip_horz_scan_dir; 6174562236bSHarry Wentland } 6184562236bSHarry Wentland 619570bc18cSDmytro Laktyushkin int get_num_mpc_splits(struct pipe_ctx *pipe) 620570bc18cSDmytro Laktyushkin { 621570bc18cSDmytro Laktyushkin int mpc_split_count = 0; 622570bc18cSDmytro Laktyushkin struct pipe_ctx *other_pipe = pipe->bottom_pipe; 623570bc18cSDmytro Laktyushkin 624570bc18cSDmytro Laktyushkin while (other_pipe && other_pipe->plane_state == pipe->plane_state) { 625570bc18cSDmytro Laktyushkin mpc_split_count++; 626570bc18cSDmytro Laktyushkin other_pipe = other_pipe->bottom_pipe; 627570bc18cSDmytro Laktyushkin } 628570bc18cSDmytro Laktyushkin other_pipe = pipe->top_pipe; 629570bc18cSDmytro Laktyushkin while (other_pipe && other_pipe->plane_state == pipe->plane_state) { 630570bc18cSDmytro Laktyushkin mpc_split_count++; 631570bc18cSDmytro Laktyushkin other_pipe = other_pipe->top_pipe; 632570bc18cSDmytro Laktyushkin } 633570bc18cSDmytro Laktyushkin 634570bc18cSDmytro Laktyushkin return mpc_split_count; 635570bc18cSDmytro Laktyushkin } 636570bc18cSDmytro Laktyushkin 637228a10d4SAlex Deucher int get_num_odm_splits(struct pipe_ctx *pipe) 638228a10d4SAlex Deucher { 639228a10d4SAlex Deucher int odm_split_count = 0; 640228a10d4SAlex Deucher struct pipe_ctx *next_pipe = pipe->next_odm_pipe; 641228a10d4SAlex Deucher while (next_pipe) { 642228a10d4SAlex Deucher odm_split_count++; 643228a10d4SAlex Deucher next_pipe = next_pipe->next_odm_pipe; 644228a10d4SAlex Deucher } 645228a10d4SAlex Deucher pipe = pipe->prev_odm_pipe; 646228a10d4SAlex Deucher while (pipe) { 647228a10d4SAlex Deucher odm_split_count++; 648228a10d4SAlex Deucher pipe = pipe->prev_odm_pipe; 649228a10d4SAlex Deucher } 650228a10d4SAlex Deucher return odm_split_count; 651228a10d4SAlex Deucher } 652228a10d4SAlex Deucher 6535bf24270SDmytro Laktyushkin static void calculate_split_count_and_index(struct pipe_ctx *pipe_ctx, int *split_count, int *split_idx) 6545bf24270SDmytro Laktyushkin { 6555bf24270SDmytro Laktyushkin *split_count = get_num_odm_splits(pipe_ctx); 6565bf24270SDmytro Laktyushkin *split_idx = 0; 6575bf24270SDmytro Laktyushkin if (*split_count == 0) { 6585bf24270SDmytro Laktyushkin /*Check for mpc split*/ 6595bf24270SDmytro Laktyushkin struct pipe_ctx *split_pipe = pipe_ctx->top_pipe; 6605bf24270SDmytro Laktyushkin 661570bc18cSDmytro Laktyushkin *split_count = get_num_mpc_splits(pipe_ctx); 6625bf24270SDmytro Laktyushkin while (split_pipe && split_pipe->plane_state == pipe_ctx->plane_state) { 6635bf24270SDmytro Laktyushkin (*split_idx)++; 6645bf24270SDmytro Laktyushkin split_pipe = split_pipe->top_pipe; 6655bf24270SDmytro Laktyushkin } 6665bf24270SDmytro Laktyushkin } else { 6675bf24270SDmytro Laktyushkin /*Get odm split index*/ 6685bf24270SDmytro Laktyushkin struct pipe_ctx *split_pipe = pipe_ctx->prev_odm_pipe; 6695bf24270SDmytro Laktyushkin 6705bf24270SDmytro Laktyushkin while (split_pipe) { 6715bf24270SDmytro Laktyushkin (*split_idx)++; 6725bf24270SDmytro Laktyushkin split_pipe = split_pipe->prev_odm_pipe; 6735bf24270SDmytro Laktyushkin } 6745bf24270SDmytro Laktyushkin } 6755bf24270SDmytro Laktyushkin } 6765bf24270SDmytro Laktyushkin 677b2d0a103SDmytro Laktyushkin static void calculate_viewport(struct pipe_ctx *pipe_ctx) 6784562236bSHarry Wentland { 6793be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 6800971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 6816702a9acSHarry Wentland struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 6823be5262eSHarry Wentland struct rect surf_src = plane_state->src_rect; 6839b6067c0SDmytro Laktyushkin struct rect clip, dest; 68487449a90SAnthony Koo int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 68587449a90SAnthony Koo || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 6865bf24270SDmytro Laktyushkin int split_count = 0; 6875bf24270SDmytro Laktyushkin int split_idx = 0; 6889b6067c0SDmytro Laktyushkin bool orthogonal_rotation, flip_y_start, flip_x_start; 68983d40659SDmytro Laktyushkin 6905bf24270SDmytro Laktyushkin calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); 6915bf24270SDmytro Laktyushkin 6927f5c22d1SVitaly Prosyak if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || 6937f5c22d1SVitaly Prosyak stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { 6945bf24270SDmytro Laktyushkin split_count = 0; 6955bf24270SDmytro Laktyushkin split_idx = 0; 6967b779c99SVitaly Prosyak } 69786006a7fSDmytro Laktyushkin 6984562236bSHarry Wentland /* The actual clip is an intersection between stream 6994562236bSHarry Wentland * source and surface clip 7004562236bSHarry Wentland */ 7019b6067c0SDmytro Laktyushkin dest = plane_state->dst_rect; 7023be5262eSHarry Wentland clip.x = stream->src.x > plane_state->clip_rect.x ? 7033be5262eSHarry Wentland stream->src.x : plane_state->clip_rect.x; 7044562236bSHarry Wentland 7051fbd2cfcSDmytro Laktyushkin clip.width = stream->src.x + stream->src.width < 7063be5262eSHarry Wentland plane_state->clip_rect.x + plane_state->clip_rect.width ? 7071fbd2cfcSDmytro Laktyushkin stream->src.x + stream->src.width - clip.x : 7083be5262eSHarry Wentland plane_state->clip_rect.x + plane_state->clip_rect.width - clip.x ; 7094562236bSHarry Wentland 7103be5262eSHarry Wentland clip.y = stream->src.y > plane_state->clip_rect.y ? 7113be5262eSHarry Wentland stream->src.y : plane_state->clip_rect.y; 7124562236bSHarry Wentland 7131fbd2cfcSDmytro Laktyushkin clip.height = stream->src.y + stream->src.height < 7143be5262eSHarry Wentland plane_state->clip_rect.y + plane_state->clip_rect.height ? 7151fbd2cfcSDmytro Laktyushkin stream->src.y + stream->src.height - clip.y : 7163be5262eSHarry Wentland plane_state->clip_rect.y + plane_state->clip_rect.height - clip.y ; 7174562236bSHarry Wentland 7189b6067c0SDmytro Laktyushkin /* 7199b6067c0SDmytro Laktyushkin * Need to calculate how scan origin is shifted in vp space 7209b6067c0SDmytro Laktyushkin * to correctly rotate clip and dst 7219b6067c0SDmytro Laktyushkin */ 7229b6067c0SDmytro Laktyushkin get_vp_scan_direction( 7239b6067c0SDmytro Laktyushkin plane_state->rotation, 7249b6067c0SDmytro Laktyushkin plane_state->horizontal_mirror, 7259b6067c0SDmytro Laktyushkin &orthogonal_rotation, 7269b6067c0SDmytro Laktyushkin &flip_y_start, 7279b6067c0SDmytro Laktyushkin &flip_x_start); 7289b6067c0SDmytro Laktyushkin 7299b6067c0SDmytro Laktyushkin if (orthogonal_rotation) { 7309b6067c0SDmytro Laktyushkin swap(clip.x, clip.y); 7319b6067c0SDmytro Laktyushkin swap(clip.width, clip.height); 7329b6067c0SDmytro Laktyushkin swap(dest.x, dest.y); 7339b6067c0SDmytro Laktyushkin swap(dest.width, dest.height); 7349b6067c0SDmytro Laktyushkin } 7359b6067c0SDmytro Laktyushkin if (flip_x_start) { 7369b6067c0SDmytro Laktyushkin clip.x = dest.x + dest.width - clip.x - clip.width; 7379b6067c0SDmytro Laktyushkin dest.x = 0; 7389b6067c0SDmytro Laktyushkin } 7399b6067c0SDmytro Laktyushkin if (flip_y_start) { 7409b6067c0SDmytro Laktyushkin clip.y = dest.y + dest.height - clip.y - clip.height; 7419b6067c0SDmytro Laktyushkin dest.y = 0; 7429b6067c0SDmytro Laktyushkin } 7439b6067c0SDmytro Laktyushkin 74486006a7fSDmytro Laktyushkin /* offset = surf_src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio 7454562236bSHarry Wentland * num_pixels = clip.num_pix * scl_ratio 7464562236bSHarry Wentland */ 7479b6067c0SDmytro Laktyushkin data->viewport.x = surf_src.x + (clip.x - dest.x) * surf_src.width / dest.width; 7489b6067c0SDmytro Laktyushkin data->viewport.width = clip.width * surf_src.width / dest.width; 7494562236bSHarry Wentland 7509b6067c0SDmytro Laktyushkin data->viewport.y = surf_src.y + (clip.y - dest.y) * surf_src.height / dest.height; 7519b6067c0SDmytro Laktyushkin data->viewport.height = clip.height * surf_src.height / dest.height; 7524562236bSHarry Wentland 7539b6067c0SDmytro Laktyushkin /* Handle split */ 7545bf24270SDmytro Laktyushkin if (split_count) { 7555bf24270SDmytro Laktyushkin /* extra pixels in the division remainder need to go to pipes after 7565bf24270SDmytro Laktyushkin * the extra pixel index minus one(epimo) defined here as: 7575bf24270SDmytro Laktyushkin */ 7585bf24270SDmytro Laktyushkin int epimo = 0; 7595bf24270SDmytro Laktyushkin 7609b6067c0SDmytro Laktyushkin if (orthogonal_rotation) { 7615bf24270SDmytro Laktyushkin if (flip_y_start) 7625bf24270SDmytro Laktyushkin split_idx = split_count - split_idx; 7635bf24270SDmytro Laktyushkin 7645bf24270SDmytro Laktyushkin epimo = split_count - data->viewport.height % (split_count + 1); 7655bf24270SDmytro Laktyushkin 7665bf24270SDmytro Laktyushkin data->viewport.y += (data->viewport.height / (split_count + 1)) * split_idx; 7675bf24270SDmytro Laktyushkin if (split_idx > epimo) 7685bf24270SDmytro Laktyushkin data->viewport.y += split_idx - epimo - 1; 7695bf24270SDmytro Laktyushkin data->viewport.height = data->viewport.height / (split_count + 1) + (split_idx > epimo ? 1 : 0); 7709b6067c0SDmytro Laktyushkin } else { 7715bf24270SDmytro Laktyushkin if (flip_x_start) 7725bf24270SDmytro Laktyushkin split_idx = split_count - split_idx; 7735bf24270SDmytro Laktyushkin 7745bf24270SDmytro Laktyushkin epimo = split_count - data->viewport.width % (split_count + 1); 7755bf24270SDmytro Laktyushkin 7765bf24270SDmytro Laktyushkin data->viewport.x += (data->viewport.width / (split_count + 1)) * split_idx; 7775bf24270SDmytro Laktyushkin if (split_idx > epimo) 7785bf24270SDmytro Laktyushkin data->viewport.x += split_idx - epimo - 1; 7795bf24270SDmytro Laktyushkin data->viewport.width = data->viewport.width / (split_count + 1) + (split_idx > epimo ? 1 : 0); 7809b6067c0SDmytro Laktyushkin } 7819b6067c0SDmytro Laktyushkin } 7829b5349f7SMartin Tsai 783b2d0a103SDmytro Laktyushkin /* Round down, compensate in init */ 784b2d0a103SDmytro Laktyushkin data->viewport_c.x = data->viewport.x / vpc_div; 785b2d0a103SDmytro Laktyushkin data->viewport_c.y = data->viewport.y / vpc_div; 7869b6067c0SDmytro Laktyushkin data->inits.h_c = (data->viewport.x % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero; 7879b6067c0SDmytro Laktyushkin data->inits.v_c = (data->viewport.y % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero; 7889b6067c0SDmytro Laktyushkin 789b2d0a103SDmytro Laktyushkin /* Round up, assume original video size always even dimensions */ 790b2d0a103SDmytro Laktyushkin data->viewport_c.width = (data->viewport.width + vpc_div - 1) / vpc_div; 791b2d0a103SDmytro Laktyushkin data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; 792fa90219aSDmytro Laktyushkin 793fa90219aSDmytro Laktyushkin data->viewport_unadjusted = data->viewport; 794fa90219aSDmytro Laktyushkin data->viewport_c_unadjusted = data->viewport_c; 795b2d0a103SDmytro Laktyushkin } 7961fbd2cfcSDmytro Laktyushkin 7979b6067c0SDmytro Laktyushkin static void calculate_recout(struct pipe_ctx *pipe_ctx) 7984562236bSHarry Wentland { 7993be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 8000971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 8015bf24270SDmytro Laktyushkin struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 8023be5262eSHarry Wentland struct rect surf_clip = plane_state->clip_rect; 8035bf24270SDmytro Laktyushkin bool pri_split_tb = pipe_ctx->bottom_pipe && 8045bf24270SDmytro Laktyushkin pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state && 8055bf24270SDmytro Laktyushkin stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; 8065bf24270SDmytro Laktyushkin bool sec_split_tb = pipe_ctx->top_pipe && 8075bf24270SDmytro Laktyushkin pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state && 8085bf24270SDmytro Laktyushkin stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; 8095bf24270SDmytro Laktyushkin int split_count = 0; 8105bf24270SDmytro Laktyushkin int split_idx = 0; 8114562236bSHarry Wentland 8125bf24270SDmytro Laktyushkin calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); 8135bf24270SDmytro Laktyushkin 81405e3d830SWesley Chalmers /* 81505e3d830SWesley Chalmers * Only the leftmost ODM pipe should be offset by a nonzero distance 81605e3d830SWesley Chalmers */ 81725b31581SWesley Chalmers if (!pipe_ctx->prev_odm_pipe) { 8185bf24270SDmytro Laktyushkin data->recout.x = stream->dst.x; 8194fa086b9SLeo (Sunpeng) Li if (stream->src.x < surf_clip.x) 8205bf24270SDmytro Laktyushkin data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width 8214fa086b9SLeo (Sunpeng) Li / stream->src.width; 8224562236bSHarry Wentland 82325b31581SWesley Chalmers } else 82425b31581SWesley Chalmers data->recout.x = 0; 82525b31581SWesley Chalmers 826*84aef2abSDmytro Laktyushkin if (stream->src.x > surf_clip.x) 827*84aef2abSDmytro Laktyushkin surf_clip.width -= stream->src.x - surf_clip.x; 8285bf24270SDmytro Laktyushkin data->recout.width = surf_clip.width * stream->dst.width / stream->src.width; 8295bf24270SDmytro Laktyushkin if (data->recout.width + data->recout.x > stream->dst.x + stream->dst.width) 8305bf24270SDmytro Laktyushkin data->recout.width = stream->dst.x + stream->dst.width - data->recout.x; 8314562236bSHarry Wentland 8325bf24270SDmytro Laktyushkin data->recout.y = stream->dst.y; 8334fa086b9SLeo (Sunpeng) Li if (stream->src.y < surf_clip.y) 8345bf24270SDmytro Laktyushkin data->recout.y += (surf_clip.y - stream->src.y) * stream->dst.height 8354fa086b9SLeo (Sunpeng) Li / stream->src.height; 836*84aef2abSDmytro Laktyushkin else if (stream->src.y > surf_clip.y) 837*84aef2abSDmytro Laktyushkin surf_clip.height -= stream->src.y - surf_clip.y; 8384562236bSHarry Wentland 8395bf24270SDmytro Laktyushkin data->recout.height = surf_clip.height * stream->dst.height / stream->src.height; 8405bf24270SDmytro Laktyushkin if (data->recout.height + data->recout.y > stream->dst.y + stream->dst.height) 8415bf24270SDmytro Laktyushkin data->recout.height = stream->dst.y + stream->dst.height - data->recout.y; 842b2d0a103SDmytro Laktyushkin 8439b6067c0SDmytro Laktyushkin /* Handle h & v split, handle rotation using viewport */ 8445bf24270SDmytro Laktyushkin if (sec_split_tb) { 8455bf24270SDmytro Laktyushkin data->recout.y += data->recout.height / 2; 8467b779c99SVitaly Prosyak /* Floor primary pipe, ceil 2ndary pipe */ 8475bf24270SDmytro Laktyushkin data->recout.height = (data->recout.height + 1) / 2; 8485bf24270SDmytro Laktyushkin } else if (pri_split_tb) 8495bf24270SDmytro Laktyushkin data->recout.height /= 2; 8505bf24270SDmytro Laktyushkin else if (split_count) { 8515bf24270SDmytro Laktyushkin /* extra pixels in the division remainder need to go to pipes after 8525bf24270SDmytro Laktyushkin * the extra pixel index minus one(epimo) defined here as: 8535bf24270SDmytro Laktyushkin */ 8545bf24270SDmytro Laktyushkin int epimo = split_count - data->recout.width % (split_count + 1); 8555bf24270SDmytro Laktyushkin 8565bf24270SDmytro Laktyushkin /*no recout offset due to odm */ 8575bf24270SDmytro Laktyushkin if (!pipe_ctx->next_odm_pipe && !pipe_ctx->prev_odm_pipe) { 8585bf24270SDmytro Laktyushkin data->recout.x += (data->recout.width / (split_count + 1)) * split_idx; 8595bf24270SDmytro Laktyushkin if (split_idx > epimo) 8605bf24270SDmytro Laktyushkin data->recout.x += split_idx - epimo - 1; 8615bf24270SDmytro Laktyushkin } 8625bf24270SDmytro Laktyushkin data->recout.width = data->recout.width / (split_count + 1) + (split_idx > epimo ? 1 : 0); 8635bf24270SDmytro Laktyushkin } 8644562236bSHarry Wentland } 865b2d0a103SDmytro Laktyushkin 866b2d0a103SDmytro Laktyushkin static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) 8674562236bSHarry Wentland { 8683be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 8690971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 8703be5262eSHarry Wentland struct rect surf_src = plane_state->src_rect; 8714fa086b9SLeo (Sunpeng) Li const int in_w = stream->src.width; 8724fa086b9SLeo (Sunpeng) Li const int in_h = stream->src.height; 8734fa086b9SLeo (Sunpeng) Li const int out_w = stream->dst.width; 8744fa086b9SLeo (Sunpeng) Li const int out_h = stream->dst.height; 8754562236bSHarry Wentland 8769b6067c0SDmytro Laktyushkin /*Swap surf_src height and width since scaling ratios are in recout rotation*/ 8773be5262eSHarry Wentland if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 8783be5262eSHarry Wentland pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 8799b6067c0SDmytro Laktyushkin swap(surf_src.height, surf_src.width); 88086006a7fSDmytro Laktyushkin 881eb0e5154SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_from_fraction( 88286006a7fSDmytro Laktyushkin surf_src.width, 8833be5262eSHarry Wentland plane_state->dst_rect.width); 884eb0e5154SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_from_fraction( 88586006a7fSDmytro Laktyushkin surf_src.height, 8863be5262eSHarry Wentland plane_state->dst_rect.height); 8874562236bSHarry Wentland 8884fa086b9SLeo (Sunpeng) Li if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) 8896702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value *= 2; 8904fa086b9SLeo (Sunpeng) Li else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) 8916702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value *= 2; 8924562236bSHarry Wentland 8936702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value = div64_s64( 8946702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value * in_h, out_h); 8956702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value = div64_s64( 8966702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value * in_w, out_w); 8974562236bSHarry Wentland 8986702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz_c = pipe_ctx->plane_res.scl_data.ratios.horz; 8996702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert_c = pipe_ctx->plane_res.scl_data.ratios.vert; 9004562236bSHarry Wentland 9016702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP8 9026702a9acSHarry Wentland || pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP10) { 9036702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz_c.value /= 2; 9046702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert_c.value /= 2; 9054562236bSHarry Wentland } 9060002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_truncate( 9070002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz, 19); 9080002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_truncate( 9090002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert, 19); 9100002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz_c = dc_fixpt_truncate( 9110002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz_c, 19); 9120002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert_c = dc_fixpt_truncate( 9130002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert_c, 19); 9144562236bSHarry Wentland } 9154562236bSHarry Wentland 9169b6067c0SDmytro Laktyushkin static inline void adjust_vp_and_init_for_seamless_clip( 9179b6067c0SDmytro Laktyushkin bool flip_scan_dir, 9189b6067c0SDmytro Laktyushkin int recout_skip, 9199b6067c0SDmytro Laktyushkin int src_size, 9209b6067c0SDmytro Laktyushkin int taps, 9219b6067c0SDmytro Laktyushkin struct fixed31_32 ratio, 9229b6067c0SDmytro Laktyushkin struct fixed31_32 *init, 9239b6067c0SDmytro Laktyushkin int *vp_offset, 9249b6067c0SDmytro Laktyushkin int *vp_size) 9254562236bSHarry Wentland { 9269b6067c0SDmytro Laktyushkin if (!flip_scan_dir) { 9279b6067c0SDmytro Laktyushkin /* Adjust for viewport end clip-off */ 9289b6067c0SDmytro Laktyushkin if ((*vp_offset + *vp_size) < src_size) { 9299b6067c0SDmytro Laktyushkin int vp_clip = src_size - *vp_size - *vp_offset; 9309b6067c0SDmytro Laktyushkin int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio)); 9319b6067c0SDmytro Laktyushkin 9329b6067c0SDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 9339b6067c0SDmytro Laktyushkin *vp_size += int_part < vp_clip ? int_part : vp_clip; 9349b6067c0SDmytro Laktyushkin } 9359b6067c0SDmytro Laktyushkin 9369b6067c0SDmytro Laktyushkin /* Adjust for non-0 viewport offset */ 9379b6067c0SDmytro Laktyushkin if (*vp_offset) { 9389b6067c0SDmytro Laktyushkin int int_part; 9399b6067c0SDmytro Laktyushkin 9409b6067c0SDmytro Laktyushkin *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip)); 9419b6067c0SDmytro Laktyushkin int_part = dc_fixpt_floor(*init) - *vp_offset; 9429b6067c0SDmytro Laktyushkin if (int_part < taps) { 9439b6067c0SDmytro Laktyushkin int int_adj = *vp_offset >= (taps - int_part) ? 9449b6067c0SDmytro Laktyushkin (taps - int_part) : *vp_offset; 9459b6067c0SDmytro Laktyushkin *vp_offset -= int_adj; 9469b6067c0SDmytro Laktyushkin *vp_size += int_adj; 9479b6067c0SDmytro Laktyushkin int_part += int_adj; 9489b6067c0SDmytro Laktyushkin } else if (int_part > taps) { 9499b6067c0SDmytro Laktyushkin *vp_offset += int_part - taps; 9509b6067c0SDmytro Laktyushkin *vp_size -= int_part - taps; 9519b6067c0SDmytro Laktyushkin int_part = taps; 9529b6067c0SDmytro Laktyushkin } 9539b6067c0SDmytro Laktyushkin init->value &= 0xffffffff; 9549b6067c0SDmytro Laktyushkin *init = dc_fixpt_add_int(*init, int_part); 9559b6067c0SDmytro Laktyushkin } 9569b6067c0SDmytro Laktyushkin } else { 9579b6067c0SDmytro Laktyushkin /* Adjust for non-0 viewport offset */ 9589b6067c0SDmytro Laktyushkin if (*vp_offset) { 9599b6067c0SDmytro Laktyushkin int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio)); 9609b6067c0SDmytro Laktyushkin 9619b6067c0SDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 9629b6067c0SDmytro Laktyushkin *vp_size += int_part < *vp_offset ? int_part : *vp_offset; 9639b6067c0SDmytro Laktyushkin *vp_offset -= int_part < *vp_offset ? int_part : *vp_offset; 9649b6067c0SDmytro Laktyushkin } 9659b6067c0SDmytro Laktyushkin 9669b6067c0SDmytro Laktyushkin /* Adjust for viewport end clip-off */ 9679b6067c0SDmytro Laktyushkin if ((*vp_offset + *vp_size) < src_size) { 9689b6067c0SDmytro Laktyushkin int int_part; 9699b6067c0SDmytro Laktyushkin int end_offset = src_size - *vp_offset - *vp_size; 9709b6067c0SDmytro Laktyushkin 9719b6067c0SDmytro Laktyushkin /* 9729b6067c0SDmytro Laktyushkin * this is init if vp had no offset, keep in mind this is from the 9739b6067c0SDmytro Laktyushkin * right side of vp due to scan direction 9749b6067c0SDmytro Laktyushkin */ 9759b6067c0SDmytro Laktyushkin *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip)); 9769b6067c0SDmytro Laktyushkin /* 9779b6067c0SDmytro Laktyushkin * this is the difference between first pixel of viewport available to read 9789b6067c0SDmytro Laktyushkin * and init position, takning into account scan direction 9799b6067c0SDmytro Laktyushkin */ 9809b6067c0SDmytro Laktyushkin int_part = dc_fixpt_floor(*init) - end_offset; 9819b6067c0SDmytro Laktyushkin if (int_part < taps) { 9829b6067c0SDmytro Laktyushkin int int_adj = end_offset >= (taps - int_part) ? 9839b6067c0SDmytro Laktyushkin (taps - int_part) : end_offset; 9849b6067c0SDmytro Laktyushkin *vp_size += int_adj; 9859b6067c0SDmytro Laktyushkin int_part += int_adj; 9869b6067c0SDmytro Laktyushkin } else if (int_part > taps) { 9879b6067c0SDmytro Laktyushkin *vp_size += int_part - taps; 9889b6067c0SDmytro Laktyushkin int_part = taps; 9899b6067c0SDmytro Laktyushkin } 9909b6067c0SDmytro Laktyushkin init->value &= 0xffffffff; 9919b6067c0SDmytro Laktyushkin *init = dc_fixpt_add_int(*init, int_part); 9929b6067c0SDmytro Laktyushkin } 9939b6067c0SDmytro Laktyushkin } 9949b6067c0SDmytro Laktyushkin } 9959b6067c0SDmytro Laktyushkin 9969b6067c0SDmytro Laktyushkin static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx) 9979b6067c0SDmytro Laktyushkin { 9989b6067c0SDmytro Laktyushkin const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 9999b6067c0SDmytro Laktyushkin const struct dc_stream_state *stream = pipe_ctx->stream; 100005e3d830SWesley Chalmers struct pipe_ctx *odm_pipe = pipe_ctx; 10016702a9acSHarry Wentland struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 10023be5262eSHarry Wentland struct rect src = pipe_ctx->plane_state->src_rect; 10039b6067c0SDmytro Laktyushkin int recout_skip_h, recout_skip_v, surf_size_h, surf_size_v; 100487449a90SAnthony Koo int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 100587449a90SAnthony Koo || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 10069b6067c0SDmytro Laktyushkin bool orthogonal_rotation, flip_vert_scan_dir, flip_horz_scan_dir; 10077287a675SDmytro Laktyushkin int odm_idx = 0; 1008b2d0a103SDmytro Laktyushkin 1009b0131391SDmytro Laktyushkin /* 1010b0131391SDmytro Laktyushkin * Need to calculate the scan direction for viewport to make adjustments 1011b0131391SDmytro Laktyushkin */ 10129b6067c0SDmytro Laktyushkin get_vp_scan_direction( 10139b6067c0SDmytro Laktyushkin plane_state->rotation, 10149b6067c0SDmytro Laktyushkin plane_state->horizontal_mirror, 10159b6067c0SDmytro Laktyushkin &orthogonal_rotation, 10169b6067c0SDmytro Laktyushkin &flip_vert_scan_dir, 10179b6067c0SDmytro Laktyushkin &flip_horz_scan_dir); 1018b0131391SDmytro Laktyushkin 10199b6067c0SDmytro Laktyushkin /* Calculate src rect rotation adjusted to recout space */ 10209b6067c0SDmytro Laktyushkin surf_size_h = src.x + src.width; 10219b6067c0SDmytro Laktyushkin surf_size_v = src.y + src.height; 10229b6067c0SDmytro Laktyushkin if (flip_horz_scan_dir) 10239b6067c0SDmytro Laktyushkin src.x = 0; 10249b6067c0SDmytro Laktyushkin if (flip_vert_scan_dir) 10259b6067c0SDmytro Laktyushkin src.y = 0; 10269b6067c0SDmytro Laktyushkin if (orthogonal_rotation) { 10279b6067c0SDmytro Laktyushkin swap(src.x, src.y); 10289b6067c0SDmytro Laktyushkin swap(src.width, src.height); 10299b5349f7SMartin Tsai } 10301fbd2cfcSDmytro Laktyushkin 103105e3d830SWesley Chalmers /*modified recout_skip_h calculation due to odm having no recout offset*/ 103205e3d830SWesley Chalmers while (odm_pipe->prev_odm_pipe) { 103305e3d830SWesley Chalmers odm_idx++; 103405e3d830SWesley Chalmers odm_pipe = odm_pipe->prev_odm_pipe; 103505e3d830SWesley Chalmers } 103605e3d830SWesley Chalmers /*odm_pipe is the leftmost pipe in the ODM group*/ 103705e3d830SWesley Chalmers recout_skip_h = odm_idx * data->recout.width; 103805e3d830SWesley Chalmers 10399b6067c0SDmytro Laktyushkin /* Recout matching initial vp offset = recout_offset - (stream dst offset + 10409b6067c0SDmytro Laktyushkin * ((surf dst offset - stream src offset) * 1/ stream scaling ratio) 10419b6067c0SDmytro Laktyushkin * - (surf surf_src offset * 1/ full scl ratio)) 10429b6067c0SDmytro Laktyushkin */ 104305e3d830SWesley Chalmers recout_skip_h += odm_pipe->plane_res.scl_data.recout.x 104405e3d830SWesley Chalmers - (stream->dst.x + (plane_state->dst_rect.x - stream->src.x) 10459b6067c0SDmytro Laktyushkin * stream->dst.width / stream->src.width - 10469b6067c0SDmytro Laktyushkin src.x * plane_state->dst_rect.width / src.width 10479b6067c0SDmytro Laktyushkin * stream->dst.width / stream->src.width); 104805e3d830SWesley Chalmers 10495bf24270SDmytro Laktyushkin 10509b6067c0SDmytro Laktyushkin recout_skip_v = data->recout.y - (stream->dst.y + (plane_state->dst_rect.y - stream->src.y) 10519b6067c0SDmytro Laktyushkin * stream->dst.height / stream->src.height - 10529b6067c0SDmytro Laktyushkin src.y * plane_state->dst_rect.height / src.height 10539b6067c0SDmytro Laktyushkin * stream->dst.height / stream->src.height); 10549b6067c0SDmytro Laktyushkin if (orthogonal_rotation) 10559b6067c0SDmytro Laktyushkin swap(recout_skip_h, recout_skip_v); 1056b2d0a103SDmytro Laktyushkin /* 1057b2d0a103SDmytro Laktyushkin * Init calculated according to formula: 1058b2d0a103SDmytro Laktyushkin * init = (scaling_ratio + number_of_taps + 1) / 2 1059b2d0a103SDmytro Laktyushkin * init_bot = init + scaling_ratio 1060b2d0a103SDmytro Laktyushkin * init_c = init + truncated_vp_c_offset(from calculate viewport) 1061b2d0a103SDmytro Laktyushkin */ 10620002d3acSDmytro Laktyushkin data->inits.h = dc_fixpt_truncate(dc_fixpt_div_int( 10630002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.horz, data->taps.h_taps + 1), 2), 19); 1064b2d0a103SDmytro Laktyushkin 10650002d3acSDmytro Laktyushkin data->inits.h_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.h_c, dc_fixpt_div_int( 10660002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.horz_c, data->taps.h_taps_c + 1), 2)), 19); 1067b2d0a103SDmytro Laktyushkin 10680002d3acSDmytro Laktyushkin data->inits.v = dc_fixpt_truncate(dc_fixpt_div_int( 10690002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.vert, data->taps.v_taps + 1), 2), 19); 1070b2d0a103SDmytro Laktyushkin 10710002d3acSDmytro Laktyushkin data->inits.v_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.v_c, dc_fixpt_div_int( 10720002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2)), 19); 10730002d3acSDmytro Laktyushkin 10749a08f51fSDmytro Laktyushkin /* 10759b6067c0SDmytro Laktyushkin * Taps, inits and scaling ratios are in recout space need to rotate 10769b6067c0SDmytro Laktyushkin * to viewport rotation before adjustment 10779a08f51fSDmytro Laktyushkin */ 10789b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 10799b6067c0SDmytro Laktyushkin flip_horz_scan_dir, 10809b6067c0SDmytro Laktyushkin recout_skip_h, 10819b6067c0SDmytro Laktyushkin surf_size_h, 10829b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.v_taps : data->taps.h_taps, 10839b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.vert : data->ratios.horz, 10849b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.v : &data->inits.h, 10859b6067c0SDmytro Laktyushkin &data->viewport.x, 10869b6067c0SDmytro Laktyushkin &data->viewport.width); 10879b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 10889b6067c0SDmytro Laktyushkin flip_horz_scan_dir, 10899b6067c0SDmytro Laktyushkin recout_skip_h, 10909b6067c0SDmytro Laktyushkin surf_size_h / vpc_div, 10919b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.v_taps_c : data->taps.h_taps_c, 10929b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.vert_c : data->ratios.horz_c, 10939b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.v_c : &data->inits.h_c, 10949b6067c0SDmytro Laktyushkin &data->viewport_c.x, 10959b6067c0SDmytro Laktyushkin &data->viewport_c.width); 10969b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 10979b6067c0SDmytro Laktyushkin flip_vert_scan_dir, 10989b6067c0SDmytro Laktyushkin recout_skip_v, 10999b6067c0SDmytro Laktyushkin surf_size_v, 11009b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.h_taps : data->taps.v_taps, 11019b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.horz : data->ratios.vert, 11029b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.h : &data->inits.v, 11039b6067c0SDmytro Laktyushkin &data->viewport.y, 11049b6067c0SDmytro Laktyushkin &data->viewport.height); 11059b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 11069b6067c0SDmytro Laktyushkin flip_vert_scan_dir, 11079b6067c0SDmytro Laktyushkin recout_skip_v, 11089b6067c0SDmytro Laktyushkin surf_size_v / vpc_div, 11099b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.h_taps_c : data->taps.v_taps_c, 11109b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.horz_c : data->ratios.vert_c, 11119b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.h_c : &data->inits.v_c, 11129b6067c0SDmytro Laktyushkin &data->viewport_c.y, 11139b6067c0SDmytro Laktyushkin &data->viewport_c.height); 1114b2d0a103SDmytro Laktyushkin 1115b2d0a103SDmytro Laktyushkin /* Interlaced inits based on final vert inits */ 1116eb0e5154SDmytro Laktyushkin data->inits.v_bot = dc_fixpt_add(data->inits.v, data->ratios.vert); 1117eb0e5154SDmytro Laktyushkin data->inits.v_c_bot = dc_fixpt_add(data->inits.v_c, data->ratios.vert_c); 11181fbd2cfcSDmytro Laktyushkin 1119b2d0a103SDmytro Laktyushkin } 11203b733278SReza Amini 112189d07b66SSamson Tam /* 112289d07b66SSamson Tam * When handling 270 rotation in mixed SLS mode, we have 112389d07b66SSamson Tam * stream->timing.h_border_left that is non zero. If we are doing 112489d07b66SSamson Tam * pipe-splitting, this h_border_left value gets added to recout.x and when it 112589d07b66SSamson Tam * calls calculate_inits_and_adj_vp() and 112689d07b66SSamson Tam * adjust_vp_and_init_for_seamless_clip(), it can cause viewport.height for a 112789d07b66SSamson Tam * pipe to be incorrect. 112889d07b66SSamson Tam * 112989d07b66SSamson Tam * To fix this, instead of using stream->timing.h_border_left, we can use 113089d07b66SSamson Tam * stream->dst.x to represent the border instead. So we will set h_border_left 113189d07b66SSamson Tam * to 0 and shift the appropriate amount in stream->dst.x. We will then 113289d07b66SSamson Tam * perform all calculations in resource_build_scaling_params() based on this 113389d07b66SSamson Tam * and then restore the h_border_left and stream->dst.x to their original 113489d07b66SSamson Tam * values. 113589d07b66SSamson Tam * 113689d07b66SSamson Tam * shift_border_left_to_dst() will shift the amount of h_border_left to 113789d07b66SSamson Tam * stream->dst.x and set h_border_left to 0. restore_border_left_from_dst() 113889d07b66SSamson Tam * will restore h_border_left and stream->dst.x back to their original values 113989d07b66SSamson Tam * We also need to make sure pipe_ctx->plane_res.scl_data.h_active uses the 114089d07b66SSamson Tam * original h_border_left value in its calculation. 114189d07b66SSamson Tam */ 114289d07b66SSamson Tam int shift_border_left_to_dst(struct pipe_ctx *pipe_ctx) 114389d07b66SSamson Tam { 114489d07b66SSamson Tam int store_h_border_left = pipe_ctx->stream->timing.h_border_left; 114589d07b66SSamson Tam 114689d07b66SSamson Tam if (store_h_border_left) { 114789d07b66SSamson Tam pipe_ctx->stream->timing.h_border_left = 0; 114889d07b66SSamson Tam pipe_ctx->stream->dst.x += store_h_border_left; 114989d07b66SSamson Tam } 115089d07b66SSamson Tam return store_h_border_left; 115189d07b66SSamson Tam } 115289d07b66SSamson Tam 115389d07b66SSamson Tam void restore_border_left_from_dst(struct pipe_ctx *pipe_ctx, 115489d07b66SSamson Tam int store_h_border_left) 115589d07b66SSamson Tam { 115689d07b66SSamson Tam pipe_ctx->stream->dst.x -= store_h_border_left; 115789d07b66SSamson Tam pipe_ctx->stream->timing.h_border_left = store_h_border_left; 115889d07b66SSamson Tam } 115989d07b66SSamson Tam 1160b2d0a103SDmytro Laktyushkin bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) 1161b2d0a103SDmytro Laktyushkin { 11623be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 11634fa086b9SLeo (Sunpeng) Li struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 1164b2d0a103SDmytro Laktyushkin bool res = false; 116589d07b66SSamson Tam int store_h_border_left = shift_border_left_to_dst(pipe_ctx); 11665d4b05ddSBhawanpreet Lakha DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); 11674562236bSHarry Wentland /* Important: scaling ratio calculation requires pixel format, 11684562236bSHarry Wentland * lb depth calculation requires recout and taps require scaling ratios. 1169b2d0a103SDmytro Laktyushkin * Inits require viewport, taps, ratios and recout of split pipe 11704562236bSHarry Wentland */ 11716702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface( 11723be5262eSHarry Wentland pipe_ctx->plane_state->format); 11734562236bSHarry Wentland 1174b2d0a103SDmytro Laktyushkin calculate_scaling_ratios(pipe_ctx); 1175b2d0a103SDmytro Laktyushkin 1176b2d0a103SDmytro Laktyushkin calculate_viewport(pipe_ctx); 11774562236bSHarry Wentland 11783a4837fbSSung Lee if (pipe_ctx->plane_res.scl_data.viewport.height < 12 || 11793a4837fbSSung Lee pipe_ctx->plane_res.scl_data.viewport.width < 12) { 118089d07b66SSamson Tam if (store_h_border_left) { 118189d07b66SSamson Tam restore_border_left_from_dst(pipe_ctx, 118289d07b66SSamson Tam store_h_border_left); 118389d07b66SSamson Tam } 11844562236bSHarry Wentland return false; 118589d07b66SSamson Tam } 11864562236bSHarry Wentland 11879b6067c0SDmytro Laktyushkin calculate_recout(pipe_ctx); 11884562236bSHarry Wentland 11894562236bSHarry Wentland /** 11904562236bSHarry Wentland * Setting line buffer pixel depth to 24bpp yields banding 11914562236bSHarry Wentland * on certain displays, such as the Sharp 4k 11924562236bSHarry Wentland */ 11936702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; 119433eef72fSEric Bernstein pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha; 11954562236bSHarry Wentland 1196199e458aSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left; 119758bb0e63SAndrew Jiang pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top; 1198199e458aSDmytro Laktyushkin 119989d07b66SSamson Tam pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable + 120089d07b66SSamson Tam store_h_border_left + timing->h_border_right; 120189d07b66SSamson Tam pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + 120289d07b66SSamson Tam timing->v_border_top + timing->v_border_bottom; 12035bf24270SDmytro Laktyushkin if (pipe_ctx->next_odm_pipe || pipe_ctx->prev_odm_pipe) 12045bf24270SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.h_active /= get_num_odm_splits(pipe_ctx) + 1; 12051b6c8067SBhawanpreet Lakha 12064562236bSHarry Wentland /* Taps calculations */ 1207d94585a0SYue Hin Lau if (pipe_ctx->plane_res.xfm != NULL) 120886a66c4eSHarry Wentland res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 120986a66c4eSHarry Wentland pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 12104562236bSHarry Wentland 1211d94585a0SYue Hin Lau if (pipe_ctx->plane_res.dpp != NULL) 1212d94585a0SYue Hin Lau res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 1213d94585a0SYue Hin Lau pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 1214f7938bc0SReza Amini 1215f7938bc0SReza Amini 12164562236bSHarry Wentland if (!res) { 12174562236bSHarry Wentland /* Try 24 bpp linebuffer */ 12186702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; 12194562236bSHarry Wentland 12201b6c8067SBhawanpreet Lakha if (pipe_ctx->plane_res.xfm != NULL) 122186a66c4eSHarry Wentland res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 12221b6c8067SBhawanpreet Lakha pipe_ctx->plane_res.xfm, 12231b6c8067SBhawanpreet Lakha &pipe_ctx->plane_res.scl_data, 12241b6c8067SBhawanpreet Lakha &plane_state->scaling_quality); 1225d94585a0SYue Hin Lau 12261b6c8067SBhawanpreet Lakha if (pipe_ctx->plane_res.dpp != NULL) 1227d94585a0SYue Hin Lau res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 12281b6c8067SBhawanpreet Lakha pipe_ctx->plane_res.dpp, 12291b6c8067SBhawanpreet Lakha &pipe_ctx->plane_res.scl_data, 12301b6c8067SBhawanpreet Lakha &plane_state->scaling_quality); 12314562236bSHarry Wentland } 12324562236bSHarry Wentland 1233b2d0a103SDmytro Laktyushkin if (res) 12341fbd2cfcSDmytro Laktyushkin /* May need to re-check lb size after this in some obscure scenario */ 12359b6067c0SDmytro Laktyushkin calculate_inits_and_adj_vp(pipe_ctx); 1236b2d0a103SDmytro Laktyushkin 12373c0dcf9fSDmytro 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" 12383c0dcf9fSDmytro 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", 12394562236bSHarry Wentland __func__, 12403c0dcf9fSDmytro Laktyushkin pipe_ctx->pipe_idx, 12416702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.height, 12426702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.width, 12436702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.x, 12446702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.y, 12453c0dcf9fSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.height, 12463c0dcf9fSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.width, 12473c0dcf9fSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.x, 12483c0dcf9fSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.y, 12493c0dcf9fSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.h_active, 12503c0dcf9fSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.v_active, 12513c0dcf9fSDmytro Laktyushkin plane_state->src_rect.height, 12523c0dcf9fSDmytro Laktyushkin plane_state->src_rect.width, 12533c0dcf9fSDmytro Laktyushkin plane_state->src_rect.x, 12543c0dcf9fSDmytro Laktyushkin plane_state->src_rect.y, 12553be5262eSHarry Wentland plane_state->dst_rect.height, 12563be5262eSHarry Wentland plane_state->dst_rect.width, 12573be5262eSHarry Wentland plane_state->dst_rect.x, 12583c0dcf9fSDmytro Laktyushkin plane_state->dst_rect.y, 12593c0dcf9fSDmytro Laktyushkin plane_state->clip_rect.height, 12603c0dcf9fSDmytro Laktyushkin plane_state->clip_rect.width, 12613c0dcf9fSDmytro Laktyushkin plane_state->clip_rect.x, 12623c0dcf9fSDmytro Laktyushkin plane_state->clip_rect.y); 12634562236bSHarry Wentland 126489d07b66SSamson Tam if (store_h_border_left) 126589d07b66SSamson Tam restore_border_left_from_dst(pipe_ctx, store_h_border_left); 126689d07b66SSamson Tam 12674562236bSHarry Wentland return res; 12684562236bSHarry Wentland } 12694562236bSHarry Wentland 12704562236bSHarry Wentland 12714562236bSHarry Wentland enum dc_status resource_build_scaling_params_for_context( 1272fb3466a4SBhawanpreet Lakha const struct dc *dc, 1273608ac7bbSJerry Zuo struct dc_state *context) 12744562236bSHarry Wentland { 12754562236bSHarry Wentland int i; 12764562236bSHarry Wentland 12774562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 12783be5262eSHarry Wentland if (context->res_ctx.pipe_ctx[i].plane_state != NULL && 12794562236bSHarry Wentland context->res_ctx.pipe_ctx[i].stream != NULL) 1280b2d0a103SDmytro Laktyushkin if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i])) 1281f84a8161STony Cheng return DC_FAIL_SCALING; 12824562236bSHarry Wentland } 12834562236bSHarry Wentland 12844562236bSHarry Wentland return DC_OK; 12854562236bSHarry Wentland } 12864562236bSHarry Wentland 1287a2b8659dSTony Cheng struct pipe_ctx *find_idle_secondary_pipe( 1288a2b8659dSTony Cheng struct resource_context *res_ctx, 12895581192dSJun Lei const struct resource_pool *pool, 12905581192dSJun Lei const struct pipe_ctx *primary_pipe) 12914562236bSHarry Wentland { 12924562236bSHarry Wentland int i; 12934562236bSHarry Wentland struct pipe_ctx *secondary_pipe = NULL; 12944562236bSHarry Wentland 12954562236bSHarry Wentland /* 12965581192dSJun Lei * We add a preferred pipe mapping to avoid the chance that 12975581192dSJun Lei * MPCCs already in use will need to be reassigned to other trees. 12985581192dSJun Lei * For example, if we went with the strict, assign backwards logic: 12995581192dSJun Lei * 13005581192dSJun Lei * (State 1) 13015581192dSJun Lei * Display A on, no surface, top pipe = 0 13025581192dSJun Lei * Display B on, no surface, top pipe = 1 13035581192dSJun Lei * 13045581192dSJun Lei * (State 2) 13055581192dSJun Lei * Display A on, no surface, top pipe = 0 13065581192dSJun Lei * Display B on, surface enable, top pipe = 1, bottom pipe = 5 13075581192dSJun Lei * 13085581192dSJun Lei * (State 3) 13095581192dSJun Lei * Display A on, surface enable, top pipe = 0, bottom pipe = 5 13105581192dSJun Lei * Display B on, surface enable, top pipe = 1, bottom pipe = 4 13115581192dSJun Lei * 13125581192dSJun Lei * The state 2->3 transition requires remapping MPCC 5 from display B 13135581192dSJun Lei * to display A. 13145581192dSJun Lei * 13155581192dSJun Lei * However, with the preferred pipe logic, state 2 would look like: 13165581192dSJun Lei * 13175581192dSJun Lei * (State 2) 13185581192dSJun Lei * Display A on, no surface, top pipe = 0 13195581192dSJun Lei * Display B on, surface enable, top pipe = 1, bottom pipe = 4 13205581192dSJun Lei * 13215581192dSJun Lei * This would then cause 2->3 to not require remapping any MPCCs. 13225581192dSJun Lei */ 13235581192dSJun Lei if (primary_pipe) { 13245581192dSJun Lei int preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx; 13255581192dSJun Lei if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) { 13265581192dSJun Lei secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx]; 13275581192dSJun Lei secondary_pipe->pipe_idx = preferred_pipe_idx; 13285581192dSJun Lei } 13295581192dSJun Lei } 13305581192dSJun Lei 13315581192dSJun Lei /* 13324562236bSHarry Wentland * search backwards for the second pipe to keep pipe 13334562236bSHarry Wentland * assignment more consistent 13344562236bSHarry Wentland */ 13355581192dSJun Lei if (!secondary_pipe) 1336a2b8659dSTony Cheng for (i = pool->pipe_count - 1; i >= 0; i--) { 13374562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == NULL) { 13384562236bSHarry Wentland secondary_pipe = &res_ctx->pipe_ctx[i]; 13394562236bSHarry Wentland secondary_pipe->pipe_idx = i; 13404562236bSHarry Wentland break; 13414562236bSHarry Wentland } 13424562236bSHarry Wentland } 13434562236bSHarry Wentland 13444562236bSHarry Wentland return secondary_pipe; 13454562236bSHarry Wentland } 13464562236bSHarry Wentland 13474562236bSHarry Wentland struct pipe_ctx *resource_get_head_pipe_for_stream( 13484562236bSHarry Wentland struct resource_context *res_ctx, 13490971c40eSHarry Wentland struct dc_stream_state *stream) 13504562236bSHarry Wentland { 13514562236bSHarry Wentland int i; 135222498036SDmytro Laktyushkin 1353a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 1354b1f6d01cSDmytro Laktyushkin if (res_ctx->pipe_ctx[i].stream == stream 1355b1f6d01cSDmytro Laktyushkin && !res_ctx->pipe_ctx[i].top_pipe 135622498036SDmytro Laktyushkin && !res_ctx->pipe_ctx[i].prev_odm_pipe) 13574562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 13584562236bSHarry Wentland } 13594562236bSHarry Wentland return NULL; 13604562236bSHarry Wentland } 13614562236bSHarry Wentland 1362b1f6d01cSDmytro Laktyushkin static struct pipe_ctx *resource_get_tail_pipe( 136319f89e23SAndrey Grodzovsky struct resource_context *res_ctx, 1364b1f6d01cSDmytro Laktyushkin struct pipe_ctx *head_pipe) 136519f89e23SAndrey Grodzovsky { 1366b1f6d01cSDmytro Laktyushkin struct pipe_ctx *tail_pipe; 136719f89e23SAndrey Grodzovsky 136819f89e23SAndrey Grodzovsky tail_pipe = head_pipe->bottom_pipe; 136919f89e23SAndrey Grodzovsky 137019f89e23SAndrey Grodzovsky while (tail_pipe) { 137119f89e23SAndrey Grodzovsky head_pipe = tail_pipe; 137219f89e23SAndrey Grodzovsky tail_pipe = tail_pipe->bottom_pipe; 137319f89e23SAndrey Grodzovsky } 137419f89e23SAndrey Grodzovsky 137519f89e23SAndrey Grodzovsky return head_pipe; 137619f89e23SAndrey Grodzovsky } 137719f89e23SAndrey Grodzovsky 13784562236bSHarry Wentland /* 1379ab2541b6SAric Cyr * A free_pipe for a stream is defined here as a pipe 1380ab2541b6SAric Cyr * that has no surface attached yet 13814562236bSHarry Wentland */ 1382b1f6d01cSDmytro Laktyushkin static struct pipe_ctx *acquire_free_pipe_for_head( 1383608ac7bbSJerry Zuo struct dc_state *context, 1384a2b8659dSTony Cheng const struct resource_pool *pool, 1385b1f6d01cSDmytro Laktyushkin struct pipe_ctx *head_pipe) 13864562236bSHarry Wentland { 13874562236bSHarry Wentland int i; 1388745cc746SDmytro Laktyushkin struct resource_context *res_ctx = &context->res_ctx; 13894562236bSHarry Wentland 13903be5262eSHarry Wentland if (!head_pipe->plane_state) 13914562236bSHarry Wentland return head_pipe; 13924562236bSHarry Wentland 13934562236bSHarry Wentland /* Re-use pipe already acquired for this stream if available*/ 1394a2b8659dSTony Cheng for (i = pool->pipe_count - 1; i >= 0; i--) { 1395b1f6d01cSDmytro Laktyushkin if (res_ctx->pipe_ctx[i].stream == head_pipe->stream && 13963be5262eSHarry Wentland !res_ctx->pipe_ctx[i].plane_state) { 13974562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 13984562236bSHarry Wentland } 13994562236bSHarry Wentland } 14004562236bSHarry Wentland 14014562236bSHarry Wentland /* 14024562236bSHarry Wentland * At this point we have no re-useable pipe for this stream and we need 14034562236bSHarry Wentland * to acquire an idle one to satisfy the request 14044562236bSHarry Wentland */ 14054562236bSHarry Wentland 1406a2b8659dSTony Cheng if (!pool->funcs->acquire_idle_pipe_for_layer) 14074562236bSHarry Wentland return NULL; 14084562236bSHarry Wentland 1409b1f6d01cSDmytro Laktyushkin return pool->funcs->acquire_idle_pipe_for_layer(context, pool, head_pipe->stream); 14104562236bSHarry Wentland } 14114562236bSHarry Wentland 1412b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 14130f9a536fSDmytro Laktyushkin static int acquire_first_split_pipe( 14140f9a536fSDmytro Laktyushkin struct resource_context *res_ctx, 14150f9a536fSDmytro Laktyushkin const struct resource_pool *pool, 14160971c40eSHarry Wentland struct dc_stream_state *stream) 14170f9a536fSDmytro Laktyushkin { 14180f9a536fSDmytro Laktyushkin int i; 14190f9a536fSDmytro Laktyushkin 14200f9a536fSDmytro Laktyushkin for (i = 0; i < pool->pipe_count; i++) { 142179592db3SDmytro Laktyushkin struct pipe_ctx *split_pipe = &res_ctx->pipe_ctx[i]; 14220f9a536fSDmytro Laktyushkin 1423b1f6d01cSDmytro Laktyushkin if (split_pipe->top_pipe && 142479592db3SDmytro Laktyushkin split_pipe->top_pipe->plane_state == split_pipe->plane_state) { 142579592db3SDmytro Laktyushkin split_pipe->top_pipe->bottom_pipe = split_pipe->bottom_pipe; 142679592db3SDmytro Laktyushkin if (split_pipe->bottom_pipe) 142779592db3SDmytro Laktyushkin split_pipe->bottom_pipe->top_pipe = split_pipe->top_pipe; 14280f9a536fSDmytro Laktyushkin 142979592db3SDmytro Laktyushkin if (split_pipe->top_pipe->plane_state) 143079592db3SDmytro Laktyushkin resource_build_scaling_params(split_pipe->top_pipe); 14310f9a536fSDmytro Laktyushkin 143279592db3SDmytro Laktyushkin memset(split_pipe, 0, sizeof(*split_pipe)); 143379592db3SDmytro Laktyushkin split_pipe->stream_res.tg = pool->timing_generators[i]; 143479592db3SDmytro Laktyushkin split_pipe->plane_res.hubp = pool->hubps[i]; 143579592db3SDmytro Laktyushkin split_pipe->plane_res.ipp = pool->ipps[i]; 143679592db3SDmytro Laktyushkin split_pipe->plane_res.dpp = pool->dpps[i]; 143779592db3SDmytro Laktyushkin split_pipe->stream_res.opp = pool->opps[i]; 143879592db3SDmytro Laktyushkin split_pipe->plane_res.mpcc_inst = pool->dpps[i]->inst; 143979592db3SDmytro Laktyushkin split_pipe->pipe_idx = i; 144079592db3SDmytro Laktyushkin 144179592db3SDmytro Laktyushkin split_pipe->stream = stream; 14420f9a536fSDmytro Laktyushkin return i; 14430f9a536fSDmytro Laktyushkin } 14440f9a536fSDmytro Laktyushkin } 14450f9a536fSDmytro Laktyushkin return -1; 14460f9a536fSDmytro Laktyushkin } 14470f9a536fSDmytro Laktyushkin #endif 14480f9a536fSDmytro Laktyushkin 144919f89e23SAndrey Grodzovsky bool dc_add_plane_to_context( 145019f89e23SAndrey Grodzovsky const struct dc *dc, 14510971c40eSHarry Wentland struct dc_stream_state *stream, 145219f89e23SAndrey Grodzovsky struct dc_plane_state *plane_state, 1453608ac7bbSJerry Zuo struct dc_state *context) 14544562236bSHarry Wentland { 14554562236bSHarry Wentland int i; 145619f89e23SAndrey Grodzovsky struct resource_pool *pool = dc->res_pool; 145719f89e23SAndrey Grodzovsky struct pipe_ctx *head_pipe, *tail_pipe, *free_pipe; 1458ab2541b6SAric Cyr struct dc_stream_status *stream_status = NULL; 14594562236bSHarry Wentland 1460ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) 14614fa086b9SLeo (Sunpeng) Li if (context->streams[i] == stream) { 1462ab2541b6SAric Cyr stream_status = &context->stream_status[i]; 14634562236bSHarry Wentland break; 14644562236bSHarry Wentland } 1465ab2541b6SAric Cyr if (stream_status == NULL) { 146619f89e23SAndrey Grodzovsky dm_error("Existing stream not found; failed to attach surface!\n"); 146719f89e23SAndrey Grodzovsky return false; 146819f89e23SAndrey Grodzovsky } 146919f89e23SAndrey Grodzovsky 147019f89e23SAndrey Grodzovsky 147119f89e23SAndrey Grodzovsky if (stream_status->plane_count == MAX_SURFACE_NUM) { 147219f89e23SAndrey Grodzovsky dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n", 147319f89e23SAndrey Grodzovsky plane_state, MAX_SURFACE_NUM); 147419f89e23SAndrey Grodzovsky return false; 147519f89e23SAndrey Grodzovsky } 147619f89e23SAndrey Grodzovsky 147719f89e23SAndrey Grodzovsky head_pipe = resource_get_head_pipe_for_stream(&context->res_ctx, stream); 147819f89e23SAndrey Grodzovsky 147919f89e23SAndrey Grodzovsky if (!head_pipe) { 148019f89e23SAndrey Grodzovsky dm_error("Head pipe not found for stream_state %p !\n", stream); 14814562236bSHarry Wentland return false; 14824562236bSHarry Wentland } 14834562236bSHarry Wentland 1484b1f6d01cSDmytro Laktyushkin /* retain new surface, but only once per stream */ 1485b1f6d01cSDmytro Laktyushkin dc_plane_state_retain(plane_state); 1486b1f6d01cSDmytro Laktyushkin 1487b1f6d01cSDmytro Laktyushkin while (head_pipe) { 1488b1f6d01cSDmytro Laktyushkin free_pipe = acquire_free_pipe_for_head(context, pool, head_pipe); 14894562236bSHarry Wentland 1490b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 14910f9a536fSDmytro Laktyushkin if (!free_pipe) { 14920f9a536fSDmytro Laktyushkin int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 14930f9a536fSDmytro Laktyushkin if (pipe_idx >= 0) 14940f9a536fSDmytro Laktyushkin free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; 14950f9a536fSDmytro Laktyushkin } 14960f9a536fSDmytro Laktyushkin #endif 1497b1f6d01cSDmytro Laktyushkin if (!free_pipe) { 1498b1f6d01cSDmytro Laktyushkin dc_plane_state_release(plane_state); 14994562236bSHarry Wentland return false; 1500b1f6d01cSDmytro Laktyushkin } 15014562236bSHarry Wentland 15023be5262eSHarry Wentland free_pipe->plane_state = plane_state; 15034562236bSHarry Wentland 150419f89e23SAndrey Grodzovsky if (head_pipe != free_pipe) { 15055b5c1777SJosip Pavic tail_pipe = resource_get_tail_pipe(&context->res_ctx, head_pipe); 15065b5c1777SJosip Pavic ASSERT(tail_pipe); 15076b670fa9SHarry Wentland free_pipe->stream_res.tg = tail_pipe->stream_res.tg; 15089aef1a31SSivapiriyanKumarasamy free_pipe->stream_res.abm = tail_pipe->stream_res.abm; 1509a6a6cb34SHarry Wentland free_pipe->stream_res.opp = tail_pipe->stream_res.opp; 15108e9c4c8cSHarry Wentland free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; 1511afaacef4SHarry Wentland free_pipe->stream_res.audio = tail_pipe->stream_res.audio; 1512cfe4645eSDmytro Laktyushkin free_pipe->clock_source = tail_pipe->clock_source; 15134562236bSHarry Wentland free_pipe->top_pipe = tail_pipe; 15144562236bSHarry Wentland tail_pipe->bottom_pipe = free_pipe; 15152e7b43e6SDmytro Laktyushkin if (!free_pipe->next_odm_pipe && tail_pipe->next_odm_pipe && tail_pipe->next_odm_pipe->bottom_pipe) { 15162e7b43e6SDmytro Laktyushkin free_pipe->next_odm_pipe = tail_pipe->next_odm_pipe->bottom_pipe; 15172e7b43e6SDmytro Laktyushkin tail_pipe->next_odm_pipe->bottom_pipe->prev_odm_pipe = free_pipe; 15182e7b43e6SDmytro Laktyushkin } 15192e7b43e6SDmytro Laktyushkin if (!free_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe->bottom_pipe) { 15202e7b43e6SDmytro Laktyushkin free_pipe->prev_odm_pipe = tail_pipe->prev_odm_pipe->bottom_pipe; 15212e7b43e6SDmytro Laktyushkin tail_pipe->prev_odm_pipe->bottom_pipe->next_odm_pipe = free_pipe; 15222e7b43e6SDmytro Laktyushkin } 15234562236bSHarry Wentland } 1524b1f6d01cSDmytro Laktyushkin head_pipe = head_pipe->next_odm_pipe; 1525b1f6d01cSDmytro Laktyushkin } 15264562236bSHarry Wentland /* assign new surfaces*/ 152719f89e23SAndrey Grodzovsky stream_status->plane_states[stream_status->plane_count] = plane_state; 15284562236bSHarry Wentland 152919f89e23SAndrey Grodzovsky stream_status->plane_count++; 15304562236bSHarry Wentland 15314562236bSHarry Wentland return true; 15324562236bSHarry Wentland } 15334562236bSHarry Wentland 153419f89e23SAndrey Grodzovsky bool dc_remove_plane_from_context( 153519f89e23SAndrey Grodzovsky const struct dc *dc, 153619f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 153719f89e23SAndrey Grodzovsky struct dc_plane_state *plane_state, 1538608ac7bbSJerry Zuo struct dc_state *context) 153919f89e23SAndrey Grodzovsky { 154019f89e23SAndrey Grodzovsky int i; 154119f89e23SAndrey Grodzovsky struct dc_stream_status *stream_status = NULL; 154219f89e23SAndrey Grodzovsky struct resource_pool *pool = dc->res_pool; 154319f89e23SAndrey Grodzovsky 154419f89e23SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 154519f89e23SAndrey Grodzovsky if (context->streams[i] == stream) { 154619f89e23SAndrey Grodzovsky stream_status = &context->stream_status[i]; 154719f89e23SAndrey Grodzovsky break; 154819f89e23SAndrey Grodzovsky } 154919f89e23SAndrey Grodzovsky 155019f89e23SAndrey Grodzovsky if (stream_status == NULL) { 155119f89e23SAndrey Grodzovsky dm_error("Existing stream not found; failed to remove plane.\n"); 155219f89e23SAndrey Grodzovsky return false; 155319f89e23SAndrey Grodzovsky } 155419f89e23SAndrey Grodzovsky 155519f89e23SAndrey Grodzovsky /* release pipe for plane*/ 155619f89e23SAndrey Grodzovsky for (i = pool->pipe_count - 1; i >= 0; i--) { 15576ffaa6fcSDmytro Laktyushkin struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 155819f89e23SAndrey Grodzovsky 15596ffaa6fcSDmytro Laktyushkin if (pipe_ctx->plane_state == plane_state) { 156019f89e23SAndrey Grodzovsky if (pipe_ctx->top_pipe) 156119f89e23SAndrey Grodzovsky pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; 156219f89e23SAndrey Grodzovsky 156319f89e23SAndrey Grodzovsky /* Second condition is to avoid setting NULL to top pipe 156419f89e23SAndrey Grodzovsky * of tail pipe making it look like head pipe in subsequent 156519f89e23SAndrey Grodzovsky * deletes 156619f89e23SAndrey Grodzovsky */ 156719f89e23SAndrey Grodzovsky if (pipe_ctx->bottom_pipe && pipe_ctx->top_pipe) 156819f89e23SAndrey Grodzovsky pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; 156919f89e23SAndrey Grodzovsky 157019f89e23SAndrey Grodzovsky /* 157119f89e23SAndrey Grodzovsky * For head pipe detach surfaces from pipe for tail 157219f89e23SAndrey Grodzovsky * pipe just zero it out 157319f89e23SAndrey Grodzovsky */ 1574b1f6d01cSDmytro Laktyushkin if (!pipe_ctx->top_pipe) 157519f89e23SAndrey Grodzovsky pipe_ctx->plane_state = NULL; 1576b1f6d01cSDmytro Laktyushkin else 157719f89e23SAndrey Grodzovsky memset(pipe_ctx, 0, sizeof(*pipe_ctx)); 157819f89e23SAndrey Grodzovsky } 157919f89e23SAndrey Grodzovsky } 158019f89e23SAndrey Grodzovsky 158119f89e23SAndrey Grodzovsky 158219f89e23SAndrey Grodzovsky for (i = 0; i < stream_status->plane_count; i++) { 158319f89e23SAndrey Grodzovsky if (stream_status->plane_states[i] == plane_state) { 158419f89e23SAndrey Grodzovsky 158519f89e23SAndrey Grodzovsky dc_plane_state_release(stream_status->plane_states[i]); 158619f89e23SAndrey Grodzovsky break; 158719f89e23SAndrey Grodzovsky } 158819f89e23SAndrey Grodzovsky } 158919f89e23SAndrey Grodzovsky 159019f89e23SAndrey Grodzovsky if (i == stream_status->plane_count) { 159119f89e23SAndrey Grodzovsky dm_error("Existing plane_state not found; failed to detach it!\n"); 159219f89e23SAndrey Grodzovsky return false; 159319f89e23SAndrey Grodzovsky } 159419f89e23SAndrey Grodzovsky 159519f89e23SAndrey Grodzovsky stream_status->plane_count--; 159619f89e23SAndrey Grodzovsky 1597abb4986eSAndrew Jiang /* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */ 1598abb4986eSAndrew Jiang for (; i < stream_status->plane_count; i++) 159919f89e23SAndrey Grodzovsky stream_status->plane_states[i] = stream_status->plane_states[i + 1]; 160019f89e23SAndrey Grodzovsky 160119f89e23SAndrey Grodzovsky stream_status->plane_states[stream_status->plane_count] = NULL; 160219f89e23SAndrey Grodzovsky 160319f89e23SAndrey Grodzovsky return true; 160419f89e23SAndrey Grodzovsky } 160519f89e23SAndrey Grodzovsky 160619f89e23SAndrey Grodzovsky bool dc_rem_all_planes_for_stream( 160719f89e23SAndrey Grodzovsky const struct dc *dc, 160819f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 1609608ac7bbSJerry Zuo struct dc_state *context) 161019f89e23SAndrey Grodzovsky { 161119f89e23SAndrey Grodzovsky int i, old_plane_count; 161219f89e23SAndrey Grodzovsky struct dc_stream_status *stream_status = NULL; 161319f89e23SAndrey Grodzovsky struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 }; 161419f89e23SAndrey Grodzovsky 161519f89e23SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 161619f89e23SAndrey Grodzovsky if (context->streams[i] == stream) { 161719f89e23SAndrey Grodzovsky stream_status = &context->stream_status[i]; 161819f89e23SAndrey Grodzovsky break; 161919f89e23SAndrey Grodzovsky } 162019f89e23SAndrey Grodzovsky 162119f89e23SAndrey Grodzovsky if (stream_status == NULL) { 162219f89e23SAndrey Grodzovsky dm_error("Existing stream %p not found!\n", stream); 162319f89e23SAndrey Grodzovsky return false; 162419f89e23SAndrey Grodzovsky } 162519f89e23SAndrey Grodzovsky 162619f89e23SAndrey Grodzovsky old_plane_count = stream_status->plane_count; 162719f89e23SAndrey Grodzovsky 162819f89e23SAndrey Grodzovsky for (i = 0; i < old_plane_count; i++) 162919f89e23SAndrey Grodzovsky del_planes[i] = stream_status->plane_states[i]; 163019f89e23SAndrey Grodzovsky 163119f89e23SAndrey Grodzovsky for (i = 0; i < old_plane_count; i++) 163219f89e23SAndrey Grodzovsky if (!dc_remove_plane_from_context(dc, stream, del_planes[i], context)) 163319f89e23SAndrey Grodzovsky return false; 163419f89e23SAndrey Grodzovsky 163519f89e23SAndrey Grodzovsky return true; 163619f89e23SAndrey Grodzovsky } 163719f89e23SAndrey Grodzovsky 163819f89e23SAndrey Grodzovsky static bool add_all_planes_for_stream( 163919f89e23SAndrey Grodzovsky const struct dc *dc, 164019f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 164119f89e23SAndrey Grodzovsky const struct dc_validation_set set[], 164219f89e23SAndrey Grodzovsky int set_count, 1643608ac7bbSJerry Zuo struct dc_state *context) 164419f89e23SAndrey Grodzovsky { 164519f89e23SAndrey Grodzovsky int i, j; 164619f89e23SAndrey Grodzovsky 164719f89e23SAndrey Grodzovsky for (i = 0; i < set_count; i++) 164819f89e23SAndrey Grodzovsky if (set[i].stream == stream) 164919f89e23SAndrey Grodzovsky break; 165019f89e23SAndrey Grodzovsky 165119f89e23SAndrey Grodzovsky if (i == set_count) { 165219f89e23SAndrey Grodzovsky dm_error("Stream %p not found in set!\n", stream); 165319f89e23SAndrey Grodzovsky return false; 165419f89e23SAndrey Grodzovsky } 165519f89e23SAndrey Grodzovsky 165619f89e23SAndrey Grodzovsky for (j = 0; j < set[i].plane_count; j++) 165719f89e23SAndrey Grodzovsky if (!dc_add_plane_to_context(dc, stream, set[i].plane_states[j], context)) 165819f89e23SAndrey Grodzovsky return false; 165919f89e23SAndrey Grodzovsky 166019f89e23SAndrey Grodzovsky return true; 166119f89e23SAndrey Grodzovsky } 166219f89e23SAndrey Grodzovsky 166319f89e23SAndrey Grodzovsky bool dc_add_all_planes_for_stream( 166419f89e23SAndrey Grodzovsky const struct dc *dc, 166519f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 166619f89e23SAndrey Grodzovsky struct dc_plane_state * const *plane_states, 166719f89e23SAndrey Grodzovsky int plane_count, 1668608ac7bbSJerry Zuo struct dc_state *context) 166919f89e23SAndrey Grodzovsky { 167019f89e23SAndrey Grodzovsky struct dc_validation_set set; 167119f89e23SAndrey Grodzovsky int i; 167219f89e23SAndrey Grodzovsky 167319f89e23SAndrey Grodzovsky set.stream = stream; 167419f89e23SAndrey Grodzovsky set.plane_count = plane_count; 167519f89e23SAndrey Grodzovsky 167619f89e23SAndrey Grodzovsky for (i = 0; i < plane_count; i++) 167719f89e23SAndrey Grodzovsky set.plane_states[i] = plane_states[i]; 167819f89e23SAndrey Grodzovsky 167919f89e23SAndrey Grodzovsky return add_all_planes_for_stream(dc, stream, &set, 1, context); 168019f89e23SAndrey Grodzovsky } 168119f89e23SAndrey Grodzovsky 16820971c40eSHarry Wentland static bool is_timing_changed(struct dc_stream_state *cur_stream, 16830971c40eSHarry Wentland struct dc_stream_state *new_stream) 16844562236bSHarry Wentland { 16854562236bSHarry Wentland if (cur_stream == NULL) 16864562236bSHarry Wentland return true; 16874562236bSHarry Wentland 16884562236bSHarry Wentland /* If sink pointer changed, it means this is a hotplug, we should do 16894562236bSHarry Wentland * full hw setting. 16904562236bSHarry Wentland */ 16914562236bSHarry Wentland if (cur_stream->sink != new_stream->sink) 16924562236bSHarry Wentland return true; 16934562236bSHarry Wentland 16944562236bSHarry Wentland /* If output color space is changed, need to reprogram info frames */ 16954fa086b9SLeo (Sunpeng) Li if (cur_stream->output_color_space != new_stream->output_color_space) 16964562236bSHarry Wentland return true; 16974562236bSHarry Wentland 16984562236bSHarry Wentland return memcmp( 16994fa086b9SLeo (Sunpeng) Li &cur_stream->timing, 17004fa086b9SLeo (Sunpeng) Li &new_stream->timing, 17014562236bSHarry Wentland sizeof(struct dc_crtc_timing)) != 0; 17024562236bSHarry Wentland } 17034562236bSHarry Wentland 17044562236bSHarry Wentland static bool are_stream_backends_same( 17050971c40eSHarry Wentland struct dc_stream_state *stream_a, struct dc_stream_state *stream_b) 17064562236bSHarry Wentland { 17074562236bSHarry Wentland if (stream_a == stream_b) 17084562236bSHarry Wentland return true; 17094562236bSHarry Wentland 17104562236bSHarry Wentland if (stream_a == NULL || stream_b == NULL) 17114562236bSHarry Wentland return false; 17124562236bSHarry Wentland 17134562236bSHarry Wentland if (is_timing_changed(stream_a, stream_b)) 17144562236bSHarry Wentland return false; 17154562236bSHarry Wentland 17161e7e86c4SSamson Tam if (stream_a->dpms_off != stream_b->dpms_off) 17171e7e86c4SSamson Tam return false; 17181e7e86c4SSamson Tam 17194562236bSHarry Wentland return true; 17204562236bSHarry Wentland } 17214562236bSHarry Wentland 17222119aa17SDavid Francis /** 17232119aa17SDavid Francis * dc_is_stream_unchanged() - Compare two stream states for equivalence. 17242119aa17SDavid Francis * 17252119aa17SDavid Francis * Checks if there a difference between the two states 17262119aa17SDavid Francis * that would require a mode change. 17272119aa17SDavid Francis * 17282119aa17SDavid Francis * Does not compare cursor position or attributes. 17292119aa17SDavid Francis */ 1730d54d29dbSBhawanpreet Lakha bool dc_is_stream_unchanged( 17310971c40eSHarry Wentland struct dc_stream_state *old_stream, struct dc_stream_state *stream) 17324562236bSHarry Wentland { 17334562236bSHarry Wentland 17344562236bSHarry Wentland if (!are_stream_backends_same(old_stream, stream)) 17354562236bSHarry Wentland return false; 17364562236bSHarry Wentland 17370460f9abSJun Lei if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param) 17380460f9abSJun Lei return false; 17390460f9abSJun Lei 17404562236bSHarry Wentland return true; 17414562236bSHarry Wentland } 17424562236bSHarry Wentland 17432119aa17SDavid Francis /** 17442119aa17SDavid Francis * dc_is_stream_scaling_unchanged() - Compare scaling rectangles of two streams. 17452119aa17SDavid Francis */ 17469a5d9c48SLeo (Sunpeng) Li bool dc_is_stream_scaling_unchanged( 17479a5d9c48SLeo (Sunpeng) Li struct dc_stream_state *old_stream, struct dc_stream_state *stream) 17489a5d9c48SLeo (Sunpeng) Li { 17499a5d9c48SLeo (Sunpeng) Li if (old_stream == stream) 17509a5d9c48SLeo (Sunpeng) Li return true; 17519a5d9c48SLeo (Sunpeng) Li 17529a5d9c48SLeo (Sunpeng) Li if (old_stream == NULL || stream == NULL) 17539a5d9c48SLeo (Sunpeng) Li return false; 17549a5d9c48SLeo (Sunpeng) Li 17559a5d9c48SLeo (Sunpeng) Li if (memcmp(&old_stream->src, 17569a5d9c48SLeo (Sunpeng) Li &stream->src, 17579a5d9c48SLeo (Sunpeng) Li sizeof(struct rect)) != 0) 17589a5d9c48SLeo (Sunpeng) Li return false; 17599a5d9c48SLeo (Sunpeng) Li 17609a5d9c48SLeo (Sunpeng) Li if (memcmp(&old_stream->dst, 17619a5d9c48SLeo (Sunpeng) Li &stream->dst, 17629a5d9c48SLeo (Sunpeng) Li sizeof(struct rect)) != 0) 17639a5d9c48SLeo (Sunpeng) Li return false; 17649a5d9c48SLeo (Sunpeng) Li 17659a5d9c48SLeo (Sunpeng) Li return true; 17669a5d9c48SLeo (Sunpeng) Li } 17679a5d9c48SLeo (Sunpeng) Li 17681dc90497SAndrey Grodzovsky static void update_stream_engine_usage( 17694562236bSHarry Wentland struct resource_context *res_ctx, 1770a2b8659dSTony Cheng const struct resource_pool *pool, 17711dc90497SAndrey Grodzovsky struct stream_encoder *stream_enc, 17721dc90497SAndrey Grodzovsky bool acquired) 17734562236bSHarry Wentland { 17744562236bSHarry Wentland int i; 17754562236bSHarry Wentland 1776a2b8659dSTony Cheng for (i = 0; i < pool->stream_enc_count; i++) { 1777a2b8659dSTony Cheng if (pool->stream_enc[i] == stream_enc) 17781dc90497SAndrey Grodzovsky res_ctx->is_stream_enc_acquired[i] = acquired; 17794562236bSHarry Wentland } 17804562236bSHarry Wentland } 17814562236bSHarry Wentland 17824562236bSHarry Wentland /* TODO: release audio object */ 17834176664bSCharlene Liu void update_audio_usage( 17844562236bSHarry Wentland struct resource_context *res_ctx, 1785a2b8659dSTony Cheng const struct resource_pool *pool, 17861dc90497SAndrey Grodzovsky struct audio *audio, 17871dc90497SAndrey Grodzovsky bool acquired) 17884562236bSHarry Wentland { 17894562236bSHarry Wentland int i; 1790a2b8659dSTony Cheng for (i = 0; i < pool->audio_count; i++) { 1791a2b8659dSTony Cheng if (pool->audios[i] == audio) 17921dc90497SAndrey Grodzovsky res_ctx->is_audio_acquired[i] = acquired; 17934562236bSHarry Wentland } 17944562236bSHarry Wentland } 17954562236bSHarry Wentland 17964562236bSHarry Wentland static int acquire_first_free_pipe( 17974562236bSHarry Wentland struct resource_context *res_ctx, 1798a2b8659dSTony Cheng const struct resource_pool *pool, 17990971c40eSHarry Wentland struct dc_stream_state *stream) 18004562236bSHarry Wentland { 18014562236bSHarry Wentland int i; 18024562236bSHarry Wentland 1803a2b8659dSTony Cheng for (i = 0; i < pool->pipe_count; i++) { 18044562236bSHarry Wentland if (!res_ctx->pipe_ctx[i].stream) { 18054562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 18064562236bSHarry Wentland 18076b670fa9SHarry Wentland pipe_ctx->stream_res.tg = pool->timing_generators[i]; 180886a66c4eSHarry Wentland pipe_ctx->plane_res.mi = pool->mis[i]; 18098feabd03SYue Hin Lau pipe_ctx->plane_res.hubp = pool->hubps[i]; 181086a66c4eSHarry Wentland pipe_ctx->plane_res.ipp = pool->ipps[i]; 181186a66c4eSHarry Wentland pipe_ctx->plane_res.xfm = pool->transforms[i]; 1812d94585a0SYue Hin Lau pipe_ctx->plane_res.dpp = pool->dpps[i]; 1813a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp = pool->opps[i]; 1814bc373a89SRoman Li if (pool->dpps[i]) 1815e07f541fSYongqiang Sun pipe_ctx->plane_res.mpcc_inst = pool->dpps[i]->inst; 18164562236bSHarry Wentland pipe_ctx->pipe_idx = i; 18174562236bSHarry Wentland 1818ff5ef992SAlex Deucher 18194562236bSHarry Wentland pipe_ctx->stream = stream; 18204562236bSHarry Wentland return i; 18214562236bSHarry Wentland } 18224562236bSHarry Wentland } 18234562236bSHarry Wentland return -1; 18244562236bSHarry Wentland } 18254562236bSHarry Wentland 1826a2b8659dSTony Cheng static struct audio *find_first_free_audio( 1827a2b8659dSTony Cheng struct resource_context *res_ctx, 1828cfb071f7SCharlene Liu const struct resource_pool *pool, 1829f24b0522SPaul Hsieh enum engine_id id, 1830f24b0522SPaul Hsieh enum dce_version dc_version) 18314562236bSHarry Wentland { 1832b5a41620SCharlene Liu int i, available_audio_count; 1833b5a41620SCharlene Liu 1834b5a41620SCharlene Liu available_audio_count = pool->audio_count; 1835b5a41620SCharlene Liu 1836b5a41620SCharlene Liu for (i = 0; i < available_audio_count; i++) { 18374176664bSCharlene Liu if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) { 1838cfb071f7SCharlene Liu /*we have enough audio endpoint, find the matching inst*/ 1839cfb071f7SCharlene Liu if (id != i) 1840cfb071f7SCharlene Liu continue; 1841a2b8659dSTony Cheng return pool->audios[i]; 18424562236bSHarry Wentland } 18434562236bSHarry Wentland } 18445feb9f07STai Man 18455feb9f07STai Man /* use engine id to find free audio */ 1846b5a41620SCharlene Liu if ((id < available_audio_count) && (res_ctx->is_audio_acquired[id] == false)) { 18475feb9f07STai Man return pool->audios[id]; 18485feb9f07STai Man } 184966bfd4fdSCharlene Liu /*not found the matching one, first come first serve*/ 1850b5a41620SCharlene Liu for (i = 0; i < available_audio_count; i++) { 18514176664bSCharlene Liu if (res_ctx->is_audio_acquired[i] == false) { 18524176664bSCharlene Liu return pool->audios[i]; 18534176664bSCharlene Liu } 18544176664bSCharlene Liu } 18554562236bSHarry Wentland return 0; 18564562236bSHarry Wentland } 18574562236bSHarry Wentland 18582119aa17SDavid Francis /** 18592119aa17SDavid Francis * dc_add_stream_to_ctx() - Add a new dc_stream_state to a dc_state. 18602119aa17SDavid Francis */ 186113ab1b44SYongqiang Sun enum dc_status dc_add_stream_to_ctx( 18621dc90497SAndrey Grodzovsky struct dc *dc, 1863608ac7bbSJerry Zuo struct dc_state *new_ctx, 18641dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 18651dc90497SAndrey Grodzovsky { 18661dc90497SAndrey Grodzovsky enum dc_status res; 1867eb9714a2SWenjing Liu DC_LOGGER_INIT(dc->ctx->logger); 18681dc90497SAndrey Grodzovsky 1869ece4147fSKen Chalmers if (new_ctx->stream_count >= dc->res_pool->timing_generator_count) { 1870eb9714a2SWenjing Liu DC_LOG_WARNING("Max streams reached, can't add stream %p !\n", stream); 18711dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 18721dc90497SAndrey Grodzovsky } 18731dc90497SAndrey Grodzovsky 18741dc90497SAndrey Grodzovsky new_ctx->streams[new_ctx->stream_count] = stream; 18751dc90497SAndrey Grodzovsky dc_stream_retain(stream); 18761dc90497SAndrey Grodzovsky new_ctx->stream_count++; 18771dc90497SAndrey Grodzovsky 18781dc90497SAndrey Grodzovsky res = dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream); 18791dc90497SAndrey Grodzovsky if (res != DC_OK) 1880eb9714a2SWenjing Liu DC_LOG_WARNING("Adding stream %p to context failed with err %d!\n", stream, res); 18811dc90497SAndrey Grodzovsky 188213ab1b44SYongqiang Sun return res; 18831dc90497SAndrey Grodzovsky } 18841dc90497SAndrey Grodzovsky 18852119aa17SDavid Francis /** 18862119aa17SDavid Francis * dc_remove_stream_from_ctx() - Remove a stream from a dc_state. 18872119aa17SDavid Francis */ 188862c933f9SYongqiang Sun enum dc_status dc_remove_stream_from_ctx( 18891dc90497SAndrey Grodzovsky struct dc *dc, 1890608ac7bbSJerry Zuo struct dc_state *new_ctx, 18911dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 18921dc90497SAndrey Grodzovsky { 189319f89e23SAndrey Grodzovsky int i; 18941dc90497SAndrey Grodzovsky struct dc_context *dc_ctx = dc->ctx; 189522498036SDmytro Laktyushkin struct pipe_ctx *del_pipe = resource_get_head_pipe_for_stream(&new_ctx->res_ctx, stream); 189622498036SDmytro Laktyushkin struct pipe_ctx *odm_pipe; 189722498036SDmytro Laktyushkin 189822498036SDmytro Laktyushkin if (!del_pipe) { 189922498036SDmytro Laktyushkin DC_ERROR("Pipe not found for stream %p !\n", stream); 190022498036SDmytro Laktyushkin return DC_ERROR_UNEXPECTED; 190122498036SDmytro Laktyushkin } 190222498036SDmytro Laktyushkin 190322498036SDmytro Laktyushkin odm_pipe = del_pipe->next_odm_pipe; 19041dc90497SAndrey Grodzovsky 190519f89e23SAndrey Grodzovsky /* Release primary pipe */ 190619f89e23SAndrey Grodzovsky ASSERT(del_pipe->stream_res.stream_enc); 19071dc90497SAndrey Grodzovsky update_stream_engine_usage( 19081dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 19091dc90497SAndrey Grodzovsky dc->res_pool, 19101dc90497SAndrey Grodzovsky del_pipe->stream_res.stream_enc, 19111dc90497SAndrey Grodzovsky false); 19121dc90497SAndrey Grodzovsky 19131dc90497SAndrey Grodzovsky if (del_pipe->stream_res.audio) 19141dc90497SAndrey Grodzovsky update_audio_usage( 19151dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 19161dc90497SAndrey Grodzovsky dc->res_pool, 19171dc90497SAndrey Grodzovsky del_pipe->stream_res.audio, 19181dc90497SAndrey Grodzovsky false); 19191dc90497SAndrey Grodzovsky 19209d0dcecdSHarry Wentland resource_unreference_clock_source(&new_ctx->res_ctx, 19219d0dcecdSHarry Wentland dc->res_pool, 19229d0dcecdSHarry Wentland del_pipe->clock_source); 19239d0dcecdSHarry Wentland 1924e56ae556SNikola Cornij if (dc->res_pool->funcs->remove_stream_from_ctx) 1925e56ae556SNikola Cornij dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream); 1926e56ae556SNikola Cornij 192722498036SDmytro Laktyushkin while (odm_pipe) { 192822498036SDmytro Laktyushkin struct pipe_ctx *next_odm_pipe = odm_pipe->next_odm_pipe; 192922498036SDmytro Laktyushkin 193022498036SDmytro Laktyushkin memset(odm_pipe, 0, sizeof(*odm_pipe)); 193122498036SDmytro Laktyushkin odm_pipe = next_odm_pipe; 193222498036SDmytro Laktyushkin } 19331dc90497SAndrey Grodzovsky memset(del_pipe, 0, sizeof(*del_pipe)); 19346ffaa6fcSDmytro Laktyushkin 19351dc90497SAndrey Grodzovsky for (i = 0; i < new_ctx->stream_count; i++) 19361dc90497SAndrey Grodzovsky if (new_ctx->streams[i] == stream) 19371dc90497SAndrey Grodzovsky break; 19381dc90497SAndrey Grodzovsky 19391dc90497SAndrey Grodzovsky if (new_ctx->streams[i] != stream) { 19401dc90497SAndrey Grodzovsky DC_ERROR("Context doesn't have stream %p !\n", stream); 19411dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 19421dc90497SAndrey Grodzovsky } 19431dc90497SAndrey Grodzovsky 19441dc90497SAndrey Grodzovsky dc_stream_release(new_ctx->streams[i]); 19451dc90497SAndrey Grodzovsky new_ctx->stream_count--; 19461dc90497SAndrey Grodzovsky 19471dc90497SAndrey Grodzovsky /* Trim back arrays */ 19481dc90497SAndrey Grodzovsky for (; i < new_ctx->stream_count; i++) { 19491dc90497SAndrey Grodzovsky new_ctx->streams[i] = new_ctx->streams[i + 1]; 19501dc90497SAndrey Grodzovsky new_ctx->stream_status[i] = new_ctx->stream_status[i + 1]; 19511dc90497SAndrey Grodzovsky } 19521dc90497SAndrey Grodzovsky 19531dc90497SAndrey Grodzovsky new_ctx->streams[new_ctx->stream_count] = NULL; 19541dc90497SAndrey Grodzovsky memset( 19551dc90497SAndrey Grodzovsky &new_ctx->stream_status[new_ctx->stream_count], 19561dc90497SAndrey Grodzovsky 0, 19571dc90497SAndrey Grodzovsky sizeof(new_ctx->stream_status[0])); 19581dc90497SAndrey Grodzovsky 19591dc90497SAndrey Grodzovsky return DC_OK; 19601dc90497SAndrey Grodzovsky } 19611dc90497SAndrey Grodzovsky 19620971c40eSHarry Wentland static struct dc_stream_state *find_pll_sharable_stream( 19630971c40eSHarry Wentland struct dc_stream_state *stream_needs_pll, 1964608ac7bbSJerry Zuo struct dc_state *context) 19654562236bSHarry Wentland { 1966ab2541b6SAric Cyr int i; 19674562236bSHarry Wentland 1968ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 19690971c40eSHarry Wentland struct dc_stream_state *stream_has_pll = context->streams[i]; 19704562236bSHarry Wentland 19714562236bSHarry Wentland /* We are looking for non dp, non virtual stream */ 19724562236bSHarry Wentland if (resource_are_streams_timing_synchronizable( 19734562236bSHarry Wentland stream_needs_pll, stream_has_pll) 19744562236bSHarry Wentland && !dc_is_dp_signal(stream_has_pll->signal) 1975ceb3dbb4SJun Lei && stream_has_pll->link->connector_signal 19764562236bSHarry Wentland != SIGNAL_TYPE_VIRTUAL) 19774562236bSHarry Wentland return stream_has_pll; 1978ab2541b6SAric Cyr 19794562236bSHarry Wentland } 19804562236bSHarry Wentland 19814562236bSHarry Wentland return NULL; 19824562236bSHarry Wentland } 19834562236bSHarry Wentland 19844562236bSHarry Wentland static int get_norm_pix_clk(const struct dc_crtc_timing *timing) 19854562236bSHarry Wentland { 1986380604e2SKen Chalmers uint32_t pix_clk = timing->pix_clk_100hz; 19874562236bSHarry Wentland uint32_t normalized_pix_clk = pix_clk; 19884562236bSHarry Wentland 19894562236bSHarry Wentland if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) 19904562236bSHarry Wentland pix_clk /= 2; 1991cc4d99b8SCharlene Liu if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) { 19924562236bSHarry Wentland switch (timing->display_color_depth) { 19938897810aSJulian Parkin case COLOR_DEPTH_666: 19944562236bSHarry Wentland case COLOR_DEPTH_888: 19954562236bSHarry Wentland normalized_pix_clk = pix_clk; 19964562236bSHarry Wentland break; 19974562236bSHarry Wentland case COLOR_DEPTH_101010: 19984562236bSHarry Wentland normalized_pix_clk = (pix_clk * 30) / 24; 19994562236bSHarry Wentland break; 20004562236bSHarry Wentland case COLOR_DEPTH_121212: 20014562236bSHarry Wentland normalized_pix_clk = (pix_clk * 36) / 24; 20024562236bSHarry Wentland break; 20034562236bSHarry Wentland case COLOR_DEPTH_161616: 20044562236bSHarry Wentland normalized_pix_clk = (pix_clk * 48) / 24; 20054562236bSHarry Wentland break; 20064562236bSHarry Wentland default: 20074562236bSHarry Wentland ASSERT(0); 20084562236bSHarry Wentland break; 20094562236bSHarry Wentland } 2010cc4d99b8SCharlene Liu } 20114562236bSHarry Wentland return normalized_pix_clk; 20124562236bSHarry Wentland } 20134562236bSHarry Wentland 20140971c40eSHarry Wentland static void calculate_phy_pix_clks(struct dc_stream_state *stream) 20154562236bSHarry Wentland { 20164562236bSHarry Wentland /* update actual pixel clock on all streams */ 20174562236bSHarry Wentland if (dc_is_hdmi_signal(stream->signal)) 20184562236bSHarry Wentland stream->phy_pix_clk = get_norm_pix_clk( 2019380604e2SKen Chalmers &stream->timing) / 10; 20204562236bSHarry Wentland else 20214562236bSHarry Wentland stream->phy_pix_clk = 2022380604e2SKen Chalmers stream->timing.pix_clk_100hz / 10; 202339c03e00SCharlene Liu 202439c03e00SCharlene Liu if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) 202539c03e00SCharlene Liu stream->phy_pix_clk *= 2; 20264562236bSHarry Wentland } 20274562236bSHarry Wentland 2028d2d7885fSAnthony Koo static int acquire_resource_from_hw_enabled_state( 2029d2d7885fSAnthony Koo struct resource_context *res_ctx, 2030d2d7885fSAnthony Koo const struct resource_pool *pool, 2031d2d7885fSAnthony Koo struct dc_stream_state *stream) 2032d2d7885fSAnthony Koo { 2033d2d7885fSAnthony Koo struct dc_link *link = stream->link; 203408b66279SMartin Leung unsigned int i, inst, tg_inst = 0; 2035d2d7885fSAnthony Koo 2036d2d7885fSAnthony Koo /* Check for enabled DIG to identify enabled display */ 2037d2d7885fSAnthony Koo if (!link->link_enc->funcs->is_dig_enabled(link->link_enc)) 2038d2d7885fSAnthony Koo return -1; 2039d2d7885fSAnthony Koo 20405ec43edaSMartin Leung inst = link->link_enc->funcs->get_dig_frontend(link->link_enc); 2041d2d7885fSAnthony Koo 20427f7652eeSMartin Leung if (inst == ENGINE_ID_UNKNOWN) 204375441d9dSMikita Lipski return -1; 2044d2d7885fSAnthony Koo 20457f7652eeSMartin Leung for (i = 0; i < pool->stream_enc_count; i++) { 20467f7652eeSMartin Leung if (pool->stream_enc[i]->id == inst) { 20477f7652eeSMartin Leung tg_inst = pool->stream_enc[i]->funcs->dig_source_otg( 20487f7652eeSMartin Leung pool->stream_enc[i]); 20497f7652eeSMartin Leung break; 20507f7652eeSMartin Leung } 20517f7652eeSMartin Leung } 2052d2d7885fSAnthony Koo 20537f7652eeSMartin Leung // tg_inst not found 20547f7652eeSMartin Leung if (i == pool->stream_enc_count) 205575441d9dSMikita Lipski return -1; 20565ec43edaSMartin Leung 20575ec43edaSMartin Leung if (tg_inst >= pool->timing_generator_count) 205875441d9dSMikita Lipski return -1; 20595ec43edaSMartin Leung 20605ec43edaSMartin Leung if (!res_ctx->pipe_ctx[tg_inst].stream) { 20615ec43edaSMartin Leung struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[tg_inst]; 20625ec43edaSMartin Leung 20635ec43edaSMartin Leung pipe_ctx->stream_res.tg = pool->timing_generators[tg_inst]; 20645ec43edaSMartin Leung pipe_ctx->plane_res.mi = pool->mis[tg_inst]; 20655ec43edaSMartin Leung pipe_ctx->plane_res.hubp = pool->hubps[tg_inst]; 20665ec43edaSMartin Leung pipe_ctx->plane_res.ipp = pool->ipps[tg_inst]; 20675ec43edaSMartin Leung pipe_ctx->plane_res.xfm = pool->transforms[tg_inst]; 20685ec43edaSMartin Leung pipe_ctx->plane_res.dpp = pool->dpps[tg_inst]; 20695ec43edaSMartin Leung pipe_ctx->stream_res.opp = pool->opps[tg_inst]; 20705ec43edaSMartin Leung 2071ccce745cSMartin Leung if (pool->dpps[tg_inst]) { 20725ec43edaSMartin Leung pipe_ctx->plane_res.mpcc_inst = pool->dpps[tg_inst]->inst; 2073ccce745cSMartin Leung 2074ccce745cSMartin Leung // Read DPP->MPCC->OPP Pipe from HW State 2075ccce745cSMartin Leung if (pool->mpc->funcs->read_mpcc_state) { 2076ccce745cSMartin Leung struct mpcc_state s = {0}; 2077ccce745cSMartin Leung 2078ccce745cSMartin Leung pool->mpc->funcs->read_mpcc_state(pool->mpc, pipe_ctx->plane_res.mpcc_inst, &s); 2079ccce745cSMartin Leung 2080ccce745cSMartin Leung if (s.dpp_id < MAX_MPCC) 2081ccce745cSMartin Leung pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].dpp_id = s.dpp_id; 2082ccce745cSMartin Leung 2083ccce745cSMartin Leung if (s.bot_mpcc_id < MAX_MPCC) 2084ccce745cSMartin Leung pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].mpcc_bot = 2085ccce745cSMartin Leung &pool->mpc->mpcc_array[s.bot_mpcc_id]; 2086ccce745cSMartin Leung 2087ccce745cSMartin Leung if (s.opp_id < MAX_OPP) 2088ccce745cSMartin Leung pipe_ctx->stream_res.opp->mpc_tree_params.opp_id = s.opp_id; 2089ccce745cSMartin Leung } 2090ccce745cSMartin Leung } 20915ec43edaSMartin Leung pipe_ctx->pipe_idx = tg_inst; 2092d2d7885fSAnthony Koo 2093d2d7885fSAnthony Koo pipe_ctx->stream = stream; 20945ec43edaSMartin Leung return tg_inst; 2095d2d7885fSAnthony Koo } 2096d2d7885fSAnthony Koo 2097d2d7885fSAnthony Koo return -1; 2098d2d7885fSAnthony Koo } 2099d2d7885fSAnthony Koo 21004562236bSHarry Wentland enum dc_status resource_map_pool_resources( 2101fb3466a4SBhawanpreet Lakha const struct dc *dc, 2102608ac7bbSJerry Zuo struct dc_state *context, 21031dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 21044562236bSHarry Wentland { 2105a2b8659dSTony Cheng const struct resource_pool *pool = dc->res_pool; 21061dc90497SAndrey Grodzovsky int i; 21071dc90497SAndrey Grodzovsky struct dc_context *dc_ctx = dc->ctx; 21081dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = NULL; 21091dc90497SAndrey Grodzovsky int pipe_idx = -1; 211046570f09SAnthony Koo struct dc_bios *dcb = dc->ctx->dc_bios; 21114562236bSHarry Wentland 211208e1c28dSYogesh Mohan Marimuthu calculate_phy_pix_clks(stream); 211308e1c28dSYogesh Mohan Marimuthu 211446570f09SAnthony Koo /* TODO: Check Linux */ 211546570f09SAnthony Koo if (dc->config.allow_seamless_boot_optimization && 211646570f09SAnthony Koo !dcb->funcs->is_accelerated_mode(dcb)) { 211746570f09SAnthony Koo if (dc_validate_seamless_boot_timing(dc, stream->sink, &stream->timing)) 211846570f09SAnthony Koo stream->apply_seamless_boot_optimization = true; 211946570f09SAnthony Koo } 212046570f09SAnthony Koo 2121d2d7885fSAnthony Koo if (stream->apply_seamless_boot_optimization) 2122d2d7885fSAnthony Koo pipe_idx = acquire_resource_from_hw_enabled_state( 2123d2d7885fSAnthony Koo &context->res_ctx, 2124d2d7885fSAnthony Koo pool, 2125d2d7885fSAnthony Koo stream); 2126d2d7885fSAnthony Koo 2127d2d7885fSAnthony Koo if (pipe_idx < 0) 21284562236bSHarry Wentland /* acquire new resources */ 21295d11e9fcSDmytro Laktyushkin pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); 21301dc90497SAndrey Grodzovsky 2131b86a1aa3SBhawanpreet Lakha #ifdef CONFIG_DRM_AMD_DC_DCN 21325d11e9fcSDmytro Laktyushkin if (pipe_idx < 0) 213313ab1b44SYongqiang Sun pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 213494c6d735SHarry Wentland #endif 213513ab1b44SYongqiang Sun 2136c5b38aecSDmytro Laktyushkin if (pipe_idx < 0 || context->res_ctx.pipe_ctx[pipe_idx].stream_res.tg == NULL) 21374562236bSHarry Wentland return DC_NO_CONTROLLER_RESOURCE; 21384562236bSHarry Wentland 21394562236bSHarry Wentland pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; 21404562236bSHarry Wentland 21418e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc = 214278cc70b1SWesley Chalmers dc->res_pool->funcs->find_first_free_match_stream_enc_for_link( 2143a2b8659dSTony Cheng &context->res_ctx, pool, stream); 21444562236bSHarry Wentland 21458e9c4c8cSHarry Wentland if (!pipe_ctx->stream_res.stream_enc) 214638684e46SEric Bernstein return DC_NO_STREAM_ENC_RESOURCE; 21474562236bSHarry Wentland 21481dc90497SAndrey Grodzovsky update_stream_engine_usage( 2149a2b8659dSTony Cheng &context->res_ctx, pool, 21501dc90497SAndrey Grodzovsky pipe_ctx->stream_res.stream_enc, 21511dc90497SAndrey Grodzovsky true); 21524562236bSHarry Wentland 21534562236bSHarry Wentland /* TODO: Add check if ASIC support and EDID audio */ 2154ceb3dbb4SJun Lei if (!stream->converter_disable_audio && 21554562236bSHarry Wentland dc_is_audio_capable_signal(pipe_ctx->stream->signal) && 2156ce08aad3SAlvin Lee stream->audio_info.mode_count && stream->audio_info.flags.all) { 2157afaacef4SHarry Wentland pipe_ctx->stream_res.audio = find_first_free_audio( 2158f24b0522SPaul Hsieh &context->res_ctx, pool, pipe_ctx->stream_res.stream_enc->id, dc_ctx->dce_version); 21594562236bSHarry Wentland 21604562236bSHarry Wentland /* 21614562236bSHarry Wentland * Audio assigned in order first come first get. 21624562236bSHarry Wentland * There are asics which has number of audio 21634562236bSHarry Wentland * resources less then number of pipes 21644562236bSHarry Wentland */ 2165afaacef4SHarry Wentland if (pipe_ctx->stream_res.audio) 21661dc90497SAndrey Grodzovsky update_audio_usage(&context->res_ctx, pool, 21671dc90497SAndrey Grodzovsky pipe_ctx->stream_res.audio, true); 21684562236bSHarry Wentland } 21694562236bSHarry Wentland 21709aef1a31SSivapiriyanKumarasamy /* Add ABM to the resource if on EDP */ 21715dba4991SBhawanpreet Lakha if (pipe_ctx->stream && dc_is_embedded_signal(pipe_ctx->stream->signal)) { 21725dba4991SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN3_0) 21735dba4991SBhawanpreet Lakha if (pool->abm) 21749aef1a31SSivapiriyanKumarasamy pipe_ctx->stream_res.abm = pool->abm; 21755dba4991SBhawanpreet Lakha else 21765dba4991SBhawanpreet Lakha pipe_ctx->stream_res.abm = pool->multiple_abms[pipe_ctx->stream_res.tg->inst]; 21775dba4991SBhawanpreet Lakha #else 21785dba4991SBhawanpreet Lakha pipe_ctx->stream_res.abm = pool->abm; 21795dba4991SBhawanpreet Lakha #endif 21805dba4991SBhawanpreet Lakha } 21819aef1a31SSivapiriyanKumarasamy 21821dc90497SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 21831dc90497SAndrey Grodzovsky if (context->streams[i] == stream) { 21846b670fa9SHarry Wentland context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; 21853f0940f8SCharlene Liu context->stream_status[i].stream_enc_inst = pipe_ctx->stream_res.stream_enc->stream_enc_inst; 21865fdb7c4cSNicholas Kazlauskas context->stream_status[i].audio_inst = 21875fdb7c4cSNicholas Kazlauskas pipe_ctx->stream_res.audio ? pipe_ctx->stream_res.audio->inst : -1; 21885fdb7c4cSNicholas Kazlauskas 21891dc90497SAndrey Grodzovsky return DC_OK; 21904562236bSHarry Wentland } 21914562236bSHarry Wentland 21921dc90497SAndrey Grodzovsky DC_ERROR("Stream %p not found in new ctx!\n", stream); 21931dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 21944562236bSHarry Wentland } 21954562236bSHarry Wentland 21962119aa17SDavid Francis /** 21972119aa17SDavid Francis * dc_resource_state_copy_construct_current() - Creates a new dc_state from existing state 21982119aa17SDavid Francis * Is a shallow copy. Increments refcounts on existing streams and planes. 21992119aa17SDavid Francis * @dc: copy out of dc->current_state 22002119aa17SDavid Francis * @dst_ctx: copy into this 22012119aa17SDavid Francis */ 2202f36cc577SBhawanpreet Lakha void dc_resource_state_copy_construct_current( 22031dc90497SAndrey Grodzovsky const struct dc *dc, 2204608ac7bbSJerry Zuo struct dc_state *dst_ctx) 22051dc90497SAndrey Grodzovsky { 2206f36cc577SBhawanpreet Lakha dc_resource_state_copy_construct(dc->current_state, dst_ctx); 22071dc90497SAndrey Grodzovsky } 22081dc90497SAndrey Grodzovsky 2209ab8db3e1SAndrey Grodzovsky 2210ab8db3e1SAndrey Grodzovsky void dc_resource_state_construct( 2211ab8db3e1SAndrey Grodzovsky const struct dc *dc, 2212ab8db3e1SAndrey Grodzovsky struct dc_state *dst_ctx) 2213ab8db3e1SAndrey Grodzovsky { 2214dc88b4a6SEric Yang dst_ctx->clk_mgr = dc->clk_mgr; 2215ab8db3e1SAndrey Grodzovsky } 2216ab8db3e1SAndrey Grodzovsky 22176d822156SNikola Cornij 22186d822156SNikola Cornij bool dc_resource_is_dsc_encoding_supported(const struct dc *dc) 22196d822156SNikola Cornij { 22206d822156SNikola Cornij return dc->res_pool->res_cap->num_dsc > 0; 22216d822156SNikola Cornij } 22226d822156SNikola Cornij 22236d822156SNikola Cornij 22242119aa17SDavid Francis /** 22252119aa17SDavid Francis * dc_validate_global_state() - Determine if HW can support a given state 22262119aa17SDavid Francis * Checks HW resource availability and bandwidth requirement. 22272119aa17SDavid Francis * @dc: dc struct for this driver 22282119aa17SDavid Francis * @new_ctx: state to be validated 2229afcd526bSJoshua Aberback * @fast_validate: set to true if only yes/no to support matters 22302119aa17SDavid Francis * 22312119aa17SDavid Francis * Return: DC_OK if the result can be programmed. Otherwise, an error code. 22322119aa17SDavid Francis */ 2233e750d56dSYongqiang Sun enum dc_status dc_validate_global_state( 22341dc90497SAndrey Grodzovsky struct dc *dc, 2235afcd526bSJoshua Aberback struct dc_state *new_ctx, 2236afcd526bSJoshua Aberback bool fast_validate) 22371dc90497SAndrey Grodzovsky { 22381dc90497SAndrey Grodzovsky enum dc_status result = DC_ERROR_UNEXPECTED; 22391dc90497SAndrey Grodzovsky int i, j; 22401dc90497SAndrey Grodzovsky 2241e41ab030SHarry Wentland if (!new_ctx) 2242e41ab030SHarry Wentland return DC_ERROR_UNEXPECTED; 2243e41ab030SHarry Wentland 2244d596e5d0SYongqiang Sun if (dc->res_pool->funcs->validate_global) { 2245d596e5d0SYongqiang Sun result = dc->res_pool->funcs->validate_global(dc, new_ctx); 2246d596e5d0SYongqiang Sun if (result != DC_OK) 2247d596e5d0SYongqiang Sun return result; 2248d596e5d0SYongqiang Sun } 22491dc90497SAndrey Grodzovsky 2250e41ab030SHarry Wentland for (i = 0; i < new_ctx->stream_count; i++) { 22511dc90497SAndrey Grodzovsky struct dc_stream_state *stream = new_ctx->streams[i]; 22521dc90497SAndrey Grodzovsky 22531dc90497SAndrey Grodzovsky for (j = 0; j < dc->res_pool->pipe_count; j++) { 22541dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[j]; 22551dc90497SAndrey Grodzovsky 22561dc90497SAndrey Grodzovsky if (pipe_ctx->stream != stream) 22571dc90497SAndrey Grodzovsky continue; 22581dc90497SAndrey Grodzovsky 22598d8c82b6SJoseph Gravenor if (dc->res_pool->funcs->patch_unknown_plane_state && 226074eac5f3SSu Sung Chung pipe_ctx->plane_state && 226174eac5f3SSu Sung Chung pipe_ctx->plane_state->tiling_info.gfx9.swizzle == DC_SW_UNKNOWN) { 22628d8c82b6SJoseph Gravenor result = dc->res_pool->funcs->patch_unknown_plane_state(pipe_ctx->plane_state); 226374eac5f3SSu Sung Chung if (result != DC_OK) 226474eac5f3SSu Sung Chung return result; 226574eac5f3SSu Sung Chung } 226674eac5f3SSu Sung Chung 22671dc90497SAndrey Grodzovsky /* Switch to dp clock source only if there is 22681dc90497SAndrey Grodzovsky * no non dp stream that shares the same timing 22691dc90497SAndrey Grodzovsky * with the dp stream. 22701dc90497SAndrey Grodzovsky */ 22711dc90497SAndrey Grodzovsky if (dc_is_dp_signal(pipe_ctx->stream->signal) && 22721dc90497SAndrey Grodzovsky !find_pll_sharable_stream(stream, new_ctx)) { 22731dc90497SAndrey Grodzovsky 22749d0dcecdSHarry Wentland resource_unreference_clock_source( 22751dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 22761dc90497SAndrey Grodzovsky dc->res_pool, 22779d0dcecdSHarry Wentland pipe_ctx->clock_source); 22784a629536SHarry Wentland 22791dc90497SAndrey Grodzovsky pipe_ctx->clock_source = dc->res_pool->dp_clock_source; 22801dc90497SAndrey Grodzovsky resource_reference_clock_source( 22811dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 22821dc90497SAndrey Grodzovsky dc->res_pool, 22831dc90497SAndrey Grodzovsky pipe_ctx->clock_source); 22841dc90497SAndrey Grodzovsky } 22851dc90497SAndrey Grodzovsky } 22861dc90497SAndrey Grodzovsky } 22871dc90497SAndrey Grodzovsky 22881dc90497SAndrey Grodzovsky result = resource_build_scaling_params_for_context(dc, new_ctx); 22891dc90497SAndrey Grodzovsky 22901dc90497SAndrey Grodzovsky if (result == DC_OK) 2291afcd526bSJoshua Aberback if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, fast_validate)) 22921dc90497SAndrey Grodzovsky result = DC_FAIL_BANDWIDTH_VALIDATE; 22931dc90497SAndrey Grodzovsky 22941dc90497SAndrey Grodzovsky return result; 22951dc90497SAndrey Grodzovsky } 22961dc90497SAndrey Grodzovsky 22976e4d6beeSTony Cheng static void patch_gamut_packet_checksum( 2298e09b6473SAnthony Koo struct dc_info_packet *gamut_packet) 22994562236bSHarry Wentland { 23004562236bSHarry Wentland /* For gamut we recalc checksum */ 23016e4d6beeSTony Cheng if (gamut_packet->valid) { 23024562236bSHarry Wentland uint8_t chk_sum = 0; 23034562236bSHarry Wentland uint8_t *ptr; 23044562236bSHarry Wentland uint8_t i; 23054562236bSHarry Wentland 23064562236bSHarry Wentland /*start of the Gamut data. */ 23076e4d6beeSTony Cheng ptr = &gamut_packet->sb[3]; 23084562236bSHarry Wentland 23096e4d6beeSTony Cheng for (i = 0; i <= gamut_packet->sb[1]; i++) 23104562236bSHarry Wentland chk_sum += ptr[i]; 23114562236bSHarry Wentland 23126e4d6beeSTony Cheng gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum); 23131646a6feSAndrew Wong } 23144562236bSHarry Wentland } 23154562236bSHarry Wentland 23164562236bSHarry Wentland static void set_avi_info_frame( 2317e09b6473SAnthony Koo struct dc_info_packet *info_packet, 23184562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 23194562236bSHarry Wentland { 23200971c40eSHarry Wentland struct dc_stream_state *stream = pipe_ctx->stream; 23214562236bSHarry Wentland enum dc_color_space color_space = COLOR_SPACE_UNKNOWN; 23224562236bSHarry Wentland uint32_t pixel_encoding = 0; 23234562236bSHarry Wentland enum scanning_type scan_type = SCANNING_TYPE_NODATA; 23244562236bSHarry Wentland enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA; 23254562236bSHarry Wentland bool itc = false; 232650e27654SZeyu Fan uint8_t itc_value = 0; 23274562236bSHarry Wentland uint8_t cn0_cn1 = 0; 232850e27654SZeyu Fan unsigned int cn0_cn1_value = 0; 23294562236bSHarry Wentland uint8_t *check_sum = NULL; 23304562236bSHarry Wentland uint8_t byte_index = 0; 2331754e3673SAnthony Koo union hdmi_info_packet hdmi_info; 233250e27654SZeyu Fan union display_content_support support = {0}; 23334fa086b9SLeo (Sunpeng) Li unsigned int vic = pipe_ctx->stream->timing.vic; 233415e17335SCharlene Liu enum dc_timing_3d_format format; 23354562236bSHarry Wentland 2336754e3673SAnthony Koo memset(&hdmi_info, 0, sizeof(union hdmi_info_packet)); 2337754e3673SAnthony Koo 23384fa086b9SLeo (Sunpeng) Li color_space = pipe_ctx->stream->output_color_space; 2339e5f2038eSCharlene Liu if (color_space == COLOR_SPACE_UNKNOWN) 23404fa086b9SLeo (Sunpeng) Li color_space = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ? 2341e5f2038eSCharlene Liu COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709; 23424562236bSHarry Wentland 23434562236bSHarry Wentland /* Initialize header */ 2344e09b6473SAnthony Koo hdmi_info.bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI; 23454562236bSHarry Wentland /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall 23464562236bSHarry Wentland * not be used in HDMI 2.0 (Section 10.1) */ 2347e09b6473SAnthony Koo hdmi_info.bits.header.version = 2; 2348e09b6473SAnthony Koo hdmi_info.bits.header.length = HDMI_AVI_INFOFRAME_SIZE; 23494562236bSHarry Wentland 23504562236bSHarry Wentland /* 23514562236bSHarry Wentland * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built 23524562236bSHarry Wentland * according to HDMI 2.0 spec (Section 10.1) 23534562236bSHarry Wentland */ 23544562236bSHarry Wentland 23554fa086b9SLeo (Sunpeng) Li switch (stream->timing.pixel_encoding) { 23564562236bSHarry Wentland case PIXEL_ENCODING_YCBCR422: 23574562236bSHarry Wentland pixel_encoding = 1; 23584562236bSHarry Wentland break; 23594562236bSHarry Wentland 23604562236bSHarry Wentland case PIXEL_ENCODING_YCBCR444: 23614562236bSHarry Wentland pixel_encoding = 2; 23624562236bSHarry Wentland break; 23634562236bSHarry Wentland case PIXEL_ENCODING_YCBCR420: 23644562236bSHarry Wentland pixel_encoding = 3; 23654562236bSHarry Wentland break; 23664562236bSHarry Wentland 23674562236bSHarry Wentland case PIXEL_ENCODING_RGB: 23684562236bSHarry Wentland default: 23694562236bSHarry Wentland pixel_encoding = 0; 23704562236bSHarry Wentland } 23714562236bSHarry Wentland 23724562236bSHarry Wentland /* Y0_Y1_Y2 : The pixel encoding */ 23734562236bSHarry Wentland /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */ 2374e09b6473SAnthony Koo hdmi_info.bits.Y0_Y1_Y2 = pixel_encoding; 23754562236bSHarry Wentland 23764562236bSHarry Wentland /* A0 = 1 Active Format Information valid */ 2377e09b6473SAnthony Koo hdmi_info.bits.A0 = ACTIVE_FORMAT_VALID; 23784562236bSHarry Wentland 23794562236bSHarry Wentland /* B0, B1 = 3; Bar info data is valid */ 2380e09b6473SAnthony Koo hdmi_info.bits.B0_B1 = BAR_INFO_BOTH_VALID; 23814562236bSHarry Wentland 2382e09b6473SAnthony Koo hdmi_info.bits.SC0_SC1 = PICTURE_SCALING_UNIFORM; 23834562236bSHarry Wentland 23844562236bSHarry Wentland /* S0, S1 : Underscan / Overscan */ 23854562236bSHarry Wentland /* TODO: un-hardcode scan type */ 23864562236bSHarry Wentland scan_type = SCANNING_TYPE_UNDERSCAN; 2387e09b6473SAnthony Koo hdmi_info.bits.S0_S1 = scan_type; 23884562236bSHarry Wentland 23894562236bSHarry Wentland /* C0, C1 : Colorimetry */ 23908fde5884SCharlene Liu if (color_space == COLOR_SPACE_YCBCR709 || 239115e17335SCharlene Liu color_space == COLOR_SPACE_YCBCR709_LIMITED) 2392e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709; 23938fde5884SCharlene Liu else if (color_space == COLOR_SPACE_YCBCR601 || 23948fde5884SCharlene Liu color_space == COLOR_SPACE_YCBCR601_LIMITED) 2395e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_ITU601; 23968fde5884SCharlene Liu else { 2397e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_NO_DATA; 23988fde5884SCharlene Liu } 2399534db198SAmy Zhang if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE || 2400534db198SAmy Zhang color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE || 2401534db198SAmy Zhang color_space == COLOR_SPACE_2020_YCBCR) { 2402e09b6473SAnthony Koo hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR; 2403e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; 2404534db198SAmy Zhang } else if (color_space == COLOR_SPACE_ADOBERGB) { 2405e09b6473SAnthony Koo hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB; 2406e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; 2407534db198SAmy Zhang } 2408534db198SAmy Zhang 24094562236bSHarry Wentland /* TODO: un-hardcode aspect ratio */ 24104fa086b9SLeo (Sunpeng) Li aspect = stream->timing.aspect_ratio; 24114562236bSHarry Wentland 24124562236bSHarry Wentland switch (aspect) { 24134562236bSHarry Wentland case ASPECT_RATIO_4_3: 24144562236bSHarry Wentland case ASPECT_RATIO_16_9: 2415e09b6473SAnthony Koo hdmi_info.bits.M0_M1 = aspect; 24164562236bSHarry Wentland break; 24174562236bSHarry Wentland 24184562236bSHarry Wentland case ASPECT_RATIO_NO_DATA: 24194562236bSHarry Wentland case ASPECT_RATIO_64_27: 24204562236bSHarry Wentland case ASPECT_RATIO_256_135: 24214562236bSHarry Wentland default: 2422e09b6473SAnthony Koo hdmi_info.bits.M0_M1 = 0; 24234562236bSHarry Wentland } 24244562236bSHarry Wentland 24254562236bSHarry Wentland /* Active Format Aspect ratio - same as Picture Aspect Ratio. */ 2426e09b6473SAnthony Koo hdmi_info.bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; 24274562236bSHarry Wentland 24284562236bSHarry Wentland /* TODO: un-hardcode cn0_cn1 and itc */ 242950e27654SZeyu Fan 24304562236bSHarry Wentland cn0_cn1 = 0; 243150e27654SZeyu Fan cn0_cn1_value = 0; 243250e27654SZeyu Fan 243350e27654SZeyu Fan itc = true; 243450e27654SZeyu Fan itc_value = 1; 243550e27654SZeyu Fan 2436ceb3dbb4SJun Lei support = stream->content_support; 24374562236bSHarry Wentland 24384562236bSHarry Wentland if (itc) { 243950e27654SZeyu Fan if (!support.bits.valid_content_type) { 244050e27654SZeyu Fan cn0_cn1_value = 0; 244150e27654SZeyu Fan } else { 244250e27654SZeyu Fan if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) { 244350e27654SZeyu Fan if (support.bits.graphics_content == 1) { 244450e27654SZeyu Fan cn0_cn1_value = 0; 244550e27654SZeyu Fan } 244650e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) { 244750e27654SZeyu Fan if (support.bits.photo_content == 1) { 244850e27654SZeyu Fan cn0_cn1_value = 1; 244950e27654SZeyu Fan } else { 245050e27654SZeyu Fan cn0_cn1_value = 0; 245150e27654SZeyu Fan itc_value = 0; 245250e27654SZeyu Fan } 245350e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) { 245450e27654SZeyu Fan if (support.bits.cinema_content == 1) { 245550e27654SZeyu Fan cn0_cn1_value = 2; 245650e27654SZeyu Fan } else { 245750e27654SZeyu Fan cn0_cn1_value = 0; 245850e27654SZeyu Fan itc_value = 0; 245950e27654SZeyu Fan } 246050e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) { 246150e27654SZeyu Fan if (support.bits.game_content == 1) { 246250e27654SZeyu Fan cn0_cn1_value = 3; 246350e27654SZeyu Fan } else { 246450e27654SZeyu Fan cn0_cn1_value = 0; 246550e27654SZeyu Fan itc_value = 0; 246650e27654SZeyu Fan } 246750e27654SZeyu Fan } 246850e27654SZeyu Fan } 2469e09b6473SAnthony Koo hdmi_info.bits.CN0_CN1 = cn0_cn1_value; 2470e09b6473SAnthony Koo hdmi_info.bits.ITC = itc_value; 24714562236bSHarry Wentland } 24724562236bSHarry Wentland 24734562236bSHarry Wentland /* TODO : We should handle YCC quantization */ 24744562236bSHarry Wentland /* but we do not have matrix calculation */ 2475ceb3dbb4SJun Lei if (stream->qs_bit == 1 && 2476ceb3dbb4SJun Lei stream->qy_bit == 1) { 247750e27654SZeyu Fan if (color_space == COLOR_SPACE_SRGB || 247850e27654SZeyu Fan color_space == COLOR_SPACE_2020_RGB_FULLRANGE) { 2479e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; 2480993dca3eSQingqing Zhuo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 248150e27654SZeyu Fan } else if (color_space == COLOR_SPACE_SRGB_LIMITED || 248250e27654SZeyu Fan color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) { 2483e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE; 2484e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 24854562236bSHarry Wentland } else { 2486e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 2487e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 24884562236bSHarry Wentland } 248950e27654SZeyu Fan } else { 2490e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 2491e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 249250e27654SZeyu Fan } 249350e27654SZeyu Fan 249415e17335SCharlene Liu ///VIC 24954fa086b9SLeo (Sunpeng) Li format = stream->timing.timing_3d_format; 249615e17335SCharlene Liu /*todo, add 3DStereo support*/ 249715e17335SCharlene Liu if (format != TIMING_3D_FORMAT_NONE) { 249815e17335SCharlene Liu // Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled 24994fa086b9SLeo (Sunpeng) Li switch (pipe_ctx->stream->timing.hdmi_vic) { 250015e17335SCharlene Liu case 1: 250115e17335SCharlene Liu vic = 95; 250215e17335SCharlene Liu break; 250315e17335SCharlene Liu case 2: 250415e17335SCharlene Liu vic = 94; 250515e17335SCharlene Liu break; 250615e17335SCharlene Liu case 3: 250715e17335SCharlene Liu vic = 93; 250815e17335SCharlene Liu break; 250915e17335SCharlene Liu case 4: 251015e17335SCharlene Liu vic = 98; 251115e17335SCharlene Liu break; 251215e17335SCharlene Liu default: 251315e17335SCharlene Liu break; 251415e17335SCharlene Liu } 251515e17335SCharlene Liu } 2516efa02336SChris Park /* If VIC >= 128, the Source shall use AVI InfoFrame Version 3*/ 2517e09b6473SAnthony Koo hdmi_info.bits.VIC0_VIC7 = vic; 2518efa02336SChris Park if (vic >= 128) 2519efa02336SChris Park hdmi_info.bits.header.version = 3; 2520efa02336SChris Park /* If (C1, C0)=(1, 1) and (EC2, EC1, EC0)=(1, 1, 1), 2521efa02336SChris Park * the Source shall use 20 AVI InfoFrame Version 4 2522efa02336SChris Park */ 2523efa02336SChris Park if (hdmi_info.bits.C0_C1 == COLORIMETRY_EXTENDED && 2524efa02336SChris Park hdmi_info.bits.EC0_EC2 == COLORIMETRYEX_RESERVED) { 2525efa02336SChris Park hdmi_info.bits.header.version = 4; 2526efa02336SChris Park hdmi_info.bits.header.length = 14; 2527efa02336SChris Park } 25284562236bSHarry Wentland 25294562236bSHarry Wentland /* pixel repetition 25304562236bSHarry Wentland * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel 25314562236bSHarry Wentland * repetition start from 1 */ 2532e09b6473SAnthony Koo hdmi_info.bits.PR0_PR3 = 0; 25334562236bSHarry Wentland 25344562236bSHarry Wentland /* Bar Info 25354562236bSHarry Wentland * barTop: Line Number of End of Top Bar. 25364562236bSHarry Wentland * barBottom: Line Number of Start of Bottom Bar. 25374562236bSHarry Wentland * barLeft: Pixel Number of End of Left Bar. 25384562236bSHarry Wentland * barRight: Pixel Number of Start of Right Bar. */ 2539e09b6473SAnthony Koo hdmi_info.bits.bar_top = stream->timing.v_border_top; 2540e09b6473SAnthony Koo hdmi_info.bits.bar_bottom = (stream->timing.v_total 25414fa086b9SLeo (Sunpeng) Li - stream->timing.v_border_bottom + 1); 2542e09b6473SAnthony Koo hdmi_info.bits.bar_left = stream->timing.h_border_left; 2543e09b6473SAnthony Koo hdmi_info.bits.bar_right = (stream->timing.h_total 25444fa086b9SLeo (Sunpeng) Li - stream->timing.h_border_right + 1); 25454562236bSHarry Wentland 25462f482c4fSChris Park /* Additional Colorimetry Extension 25472f482c4fSChris Park * Used in conduction with C0-C1 and EC0-EC2 25482f482c4fSChris Park * 0 = DCI-P3 RGB (D65) 25492f482c4fSChris Park * 1 = DCI-P3 RGB (theater) 25502f482c4fSChris Park */ 25512f482c4fSChris Park hdmi_info.bits.ACE0_ACE3 = 0; 25522f482c4fSChris Park 25534562236bSHarry Wentland /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ 2554e09b6473SAnthony Koo check_sum = &hdmi_info.packet_raw_data.sb[0]; 2555e8d726b7SReza Amini 2556efa02336SChris Park *check_sum = HDMI_INFOFRAME_TYPE_AVI + hdmi_info.bits.header.length + hdmi_info.bits.header.version; 25574562236bSHarry Wentland 2558efa02336SChris Park for (byte_index = 1; byte_index <= hdmi_info.bits.header.length; byte_index++) 2559e09b6473SAnthony Koo *check_sum += hdmi_info.packet_raw_data.sb[byte_index]; 25604562236bSHarry Wentland 25614562236bSHarry Wentland /* one byte complement */ 25624562236bSHarry Wentland *check_sum = (uint8_t) (0x100 - *check_sum); 25634562236bSHarry Wentland 25644562236bSHarry Wentland /* Store in hw_path_mode */ 2565e09b6473SAnthony Koo info_packet->hb0 = hdmi_info.packet_raw_data.hb0; 2566e09b6473SAnthony Koo info_packet->hb1 = hdmi_info.packet_raw_data.hb1; 2567e09b6473SAnthony Koo info_packet->hb2 = hdmi_info.packet_raw_data.hb2; 25684562236bSHarry Wentland 2569e09b6473SAnthony Koo for (byte_index = 0; byte_index < sizeof(hdmi_info.packet_raw_data.sb); byte_index++) 2570e09b6473SAnthony Koo info_packet->sb[byte_index] = hdmi_info.packet_raw_data.sb[byte_index]; 25714562236bSHarry Wentland 25724562236bSHarry Wentland info_packet->valid = true; 25734562236bSHarry Wentland } 25744562236bSHarry Wentland 25756e4d6beeSTony Cheng static void set_vendor_info_packet( 2576e09b6473SAnthony Koo struct dc_info_packet *info_packet, 25770971c40eSHarry Wentland struct dc_stream_state *stream) 25784562236bSHarry Wentland { 2579ecd0136bSHarmanprit Tatla /* SPD info packet for FreeSync */ 258015e17335SCharlene Liu 2581ecd0136bSHarmanprit Tatla /* Check if Freesync is supported. Return if false. If true, 2582ecd0136bSHarmanprit Tatla * set the corresponding bit in the info packet 2583ecd0136bSHarmanprit Tatla */ 2584ecd0136bSHarmanprit Tatla if (!stream->vsp_infopacket.valid) 25854562236bSHarry Wentland return; 25864562236bSHarry Wentland 2587ecd0136bSHarmanprit Tatla *info_packet = stream->vsp_infopacket; 25884562236bSHarry Wentland } 25894562236bSHarry Wentland 25906e4d6beeSTony Cheng static void set_spd_info_packet( 2591e09b6473SAnthony Koo struct dc_info_packet *info_packet, 25920971c40eSHarry Wentland struct dc_stream_state *stream) 25934562236bSHarry Wentland { 25944562236bSHarry Wentland /* SPD info packet for FreeSync */ 25954562236bSHarry Wentland 25964562236bSHarry Wentland /* Check if Freesync is supported. Return if false. If true, 25974562236bSHarry Wentland * set the corresponding bit in the info packet 25984562236bSHarry Wentland */ 259998e6436dSAnthony Koo if (!stream->vrr_infopacket.valid) 26004562236bSHarry Wentland return; 26014562236bSHarry Wentland 260298e6436dSAnthony Koo *info_packet = stream->vrr_infopacket; 26034562236bSHarry Wentland } 26044562236bSHarry Wentland 26051646a6feSAndrew Wong static void set_hdr_static_info_packet( 2606e09b6473SAnthony Koo struct dc_info_packet *info_packet, 26070971c40eSHarry Wentland struct dc_stream_state *stream) 26081646a6feSAndrew Wong { 26090eeef690SAnthony Koo /* HDR Static Metadata info packet for HDR10 */ 26101646a6feSAndrew Wong 2611a10dc97aSKrunoslav Kovac if (!stream->hdr_static_metadata.valid || 2612a10dc97aSKrunoslav Kovac stream->use_dynamic_meta) 261310bff005SYongqiang Sun return; 261410bff005SYongqiang Sun 26150eeef690SAnthony Koo *info_packet = stream->hdr_static_metadata; 26161646a6feSAndrew Wong } 26171646a6feSAndrew Wong 26186e4d6beeSTony Cheng static void set_vsc_info_packet( 2619e09b6473SAnthony Koo struct dc_info_packet *info_packet, 26200971c40eSHarry Wentland struct dc_stream_state *stream) 26214562236bSHarry Wentland { 26221336926fSAlvin lee if (!stream->vsc_infopacket.valid) 26234562236bSHarry Wentland return; 26244562236bSHarry Wentland 26251336926fSAlvin lee *info_packet = stream->vsc_infopacket; 26264562236bSHarry Wentland } 26274562236bSHarry Wentland 2628f36cc577SBhawanpreet Lakha void dc_resource_state_destruct(struct dc_state *context) 26294562236bSHarry Wentland { 26304562236bSHarry Wentland int i, j; 26314562236bSHarry Wentland 2632ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 26333be5262eSHarry Wentland for (j = 0; j < context->stream_status[i].plane_count; j++) 26343be5262eSHarry Wentland dc_plane_state_release( 26353be5262eSHarry Wentland context->stream_status[i].plane_states[j]); 26364562236bSHarry Wentland 26373be5262eSHarry Wentland context->stream_status[i].plane_count = 0; 26384fa086b9SLeo (Sunpeng) Li dc_stream_release(context->streams[i]); 2639ab2541b6SAric Cyr context->streams[i] = NULL; 26404562236bSHarry Wentland } 26414562236bSHarry Wentland } 26424562236bSHarry Wentland 2643f36cc577SBhawanpreet Lakha void dc_resource_state_copy_construct( 2644608ac7bbSJerry Zuo const struct dc_state *src_ctx, 2645608ac7bbSJerry Zuo struct dc_state *dst_ctx) 26464562236bSHarry Wentland { 26474562236bSHarry Wentland int i, j; 26488ee5702aSDave Airlie struct kref refcount = dst_ctx->refcount; 26494562236bSHarry Wentland 26504562236bSHarry Wentland *dst_ctx = *src_ctx; 26514562236bSHarry Wentland 2652a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 26534562236bSHarry Wentland struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i]; 26544562236bSHarry Wentland 26554562236bSHarry Wentland if (cur_pipe->top_pipe) 26564562236bSHarry Wentland cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; 26574562236bSHarry Wentland 26584562236bSHarry Wentland if (cur_pipe->bottom_pipe) 26594562236bSHarry Wentland cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; 2660b1f6d01cSDmytro Laktyushkin 2661b1f6d01cSDmytro Laktyushkin if (cur_pipe->next_odm_pipe) 2662b1f6d01cSDmytro Laktyushkin cur_pipe->next_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx]; 2663b1f6d01cSDmytro Laktyushkin 2664b1f6d01cSDmytro Laktyushkin if (cur_pipe->prev_odm_pipe) 2665b1f6d01cSDmytro Laktyushkin cur_pipe->prev_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx]; 26664562236bSHarry Wentland } 26674562236bSHarry Wentland 2668ab2541b6SAric Cyr for (i = 0; i < dst_ctx->stream_count; i++) { 26694fa086b9SLeo (Sunpeng) Li dc_stream_retain(dst_ctx->streams[i]); 26703be5262eSHarry Wentland for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++) 26713be5262eSHarry Wentland dc_plane_state_retain( 26723be5262eSHarry Wentland dst_ctx->stream_status[i].plane_states[j]); 26734562236bSHarry Wentland } 26749a3afbb3SAndrey Grodzovsky 26759a3afbb3SAndrey Grodzovsky /* context refcount should not be overridden */ 26768ee5702aSDave Airlie dst_ctx->refcount = refcount; 26779a3afbb3SAndrey Grodzovsky 26784562236bSHarry Wentland } 26794562236bSHarry Wentland 26804562236bSHarry Wentland struct clock_source *dc_resource_find_first_free_pll( 2681a2b8659dSTony Cheng struct resource_context *res_ctx, 2682a2b8659dSTony Cheng const struct resource_pool *pool) 26834562236bSHarry Wentland { 26844562236bSHarry Wentland int i; 26854562236bSHarry Wentland 2686a2b8659dSTony Cheng for (i = 0; i < pool->clk_src_count; ++i) { 26874562236bSHarry Wentland if (res_ctx->clock_source_ref_count[i] == 0) 2688a2b8659dSTony Cheng return pool->clock_sources[i]; 26894562236bSHarry Wentland } 26904562236bSHarry Wentland 26914562236bSHarry Wentland return NULL; 26924562236bSHarry Wentland } 26934562236bSHarry Wentland 26944562236bSHarry Wentland void resource_build_info_frame(struct pipe_ctx *pipe_ctx) 26954562236bSHarry Wentland { 26964562236bSHarry Wentland enum signal_type signal = SIGNAL_TYPE_NONE; 269796c50c0dSHarry Wentland struct encoder_info_frame *info = &pipe_ctx->stream_res.encoder_info_frame; 26984562236bSHarry Wentland 26994562236bSHarry Wentland /* default all packets to invalid */ 27006e4d6beeSTony Cheng info->avi.valid = false; 27016e4d6beeSTony Cheng info->gamut.valid = false; 27026e4d6beeSTony Cheng info->vendor.valid = false; 2703630e3573SJeff Smith info->spd.valid = false; 27046e4d6beeSTony Cheng info->hdrsmd.valid = false; 27056e4d6beeSTony Cheng info->vsc.valid = false; 27064562236bSHarry Wentland 27074562236bSHarry Wentland signal = pipe_ctx->stream->signal; 27084562236bSHarry Wentland 27094562236bSHarry Wentland /* HDMi and DP have different info packets*/ 27104562236bSHarry Wentland if (dc_is_hdmi_signal(signal)) { 27116e4d6beeSTony Cheng set_avi_info_frame(&info->avi, pipe_ctx); 27126e4d6beeSTony Cheng 27136e4d6beeSTony Cheng set_vendor_info_packet(&info->vendor, pipe_ctx->stream); 27146e4d6beeSTony Cheng 27156e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 27166e4d6beeSTony Cheng 271756ef6ed9SAnthony Koo set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 27186e4d6beeSTony Cheng 2719a33fa99dSHarry Wentland } else if (dc_is_dp_signal(signal)) { 27206e4d6beeSTony Cheng set_vsc_info_packet(&info->vsc, pipe_ctx->stream); 27216e4d6beeSTony Cheng 27226e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 27236e4d6beeSTony Cheng 272456ef6ed9SAnthony Koo set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 2725a33fa99dSHarry Wentland } 27264562236bSHarry Wentland 27276e4d6beeSTony Cheng patch_gamut_packet_checksum(&info->gamut); 27284562236bSHarry Wentland } 27294562236bSHarry Wentland 27304562236bSHarry Wentland enum dc_status resource_map_clock_resources( 2731fb3466a4SBhawanpreet Lakha const struct dc *dc, 2732608ac7bbSJerry Zuo struct dc_state *context, 27331dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 27344562236bSHarry Wentland { 27354562236bSHarry Wentland /* acquire new resources */ 27361dc90497SAndrey Grodzovsky const struct resource_pool *pool = dc->res_pool; 27371dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream( 27381dc90497SAndrey Grodzovsky &context->res_ctx, stream); 27394562236bSHarry Wentland 27401dc90497SAndrey Grodzovsky if (!pipe_ctx) 27411dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 27424562236bSHarry Wentland 27434562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal) 27444562236bSHarry Wentland || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) 2745a2b8659dSTony Cheng pipe_ctx->clock_source = pool->dp_clock_source; 27464562236bSHarry Wentland else { 27474562236bSHarry Wentland pipe_ctx->clock_source = NULL; 27484562236bSHarry Wentland 2749fb3466a4SBhawanpreet Lakha if (!dc->config.disable_disp_pll_sharing) 27504ed4e51bSMikita Lipski pipe_ctx->clock_source = resource_find_used_clk_src_for_sharing( 27514562236bSHarry Wentland &context->res_ctx, 27524562236bSHarry Wentland pipe_ctx); 27534562236bSHarry Wentland 27544562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 27554562236bSHarry Wentland pipe_ctx->clock_source = 2756a2b8659dSTony Cheng dc_resource_find_first_free_pll( 2757a2b8659dSTony Cheng &context->res_ctx, 2758a2b8659dSTony Cheng pool); 27594562236bSHarry Wentland } 27604562236bSHarry Wentland 27614562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 27624562236bSHarry Wentland return DC_NO_CLOCK_SOURCE_RESOURCE; 27634562236bSHarry Wentland 27644562236bSHarry Wentland resource_reference_clock_source( 2765a2b8659dSTony Cheng &context->res_ctx, pool, 27664562236bSHarry Wentland pipe_ctx->clock_source); 27674562236bSHarry Wentland 27684562236bSHarry Wentland return DC_OK; 27694562236bSHarry Wentland } 27704562236bSHarry Wentland 27714562236bSHarry Wentland /* 27724562236bSHarry Wentland * Note: We need to disable output if clock sources change, 27734562236bSHarry Wentland * since bios does optimization and doesn't apply if changing 27744562236bSHarry Wentland * PHY when not already disabled. 27754562236bSHarry Wentland */ 27764562236bSHarry Wentland bool pipe_need_reprogram( 27774562236bSHarry Wentland struct pipe_ctx *pipe_ctx_old, 27784562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 27794562236bSHarry Wentland { 2780cfe4645eSDmytro Laktyushkin if (!pipe_ctx_old->stream) 2781cfe4645eSDmytro Laktyushkin return false; 2782cfe4645eSDmytro Laktyushkin 27834562236bSHarry Wentland if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink) 27844562236bSHarry Wentland return true; 27854562236bSHarry Wentland 27864562236bSHarry Wentland if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal) 27874562236bSHarry Wentland return true; 27884562236bSHarry Wentland 2789afaacef4SHarry Wentland if (pipe_ctx_old->stream_res.audio != pipe_ctx->stream_res.audio) 27904562236bSHarry Wentland return true; 27914562236bSHarry Wentland 27924562236bSHarry Wentland if (pipe_ctx_old->clock_source != pipe_ctx->clock_source 27934562236bSHarry Wentland && pipe_ctx_old->stream != pipe_ctx->stream) 27944562236bSHarry Wentland return true; 27954562236bSHarry Wentland 27968e9c4c8cSHarry Wentland if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc) 27974562236bSHarry Wentland return true; 27984562236bSHarry Wentland 27994562236bSHarry Wentland if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 28004562236bSHarry Wentland return true; 28014562236bSHarry Wentland 28021e7e86c4SSamson Tam if (pipe_ctx_old->stream->dpms_off != pipe_ctx->stream->dpms_off) 28031e7e86c4SSamson Tam return true; 28041e7e86c4SSamson Tam 2805eed928dcSCharlene Liu if (false == pipe_ctx_old->stream->link->link_state_valid && 2806eed928dcSCharlene Liu false == pipe_ctx_old->stream->dpms_off) 2807eed928dcSCharlene Liu return true; 2808eed928dcSCharlene Liu 280914e49bb3SNikola Cornij if (pipe_ctx_old->stream_res.dsc != pipe_ctx->stream_res.dsc) 281014e49bb3SNikola Cornij return true; 281114e49bb3SNikola Cornij 28124562236bSHarry Wentland return false; 28134562236bSHarry Wentland } 2814529cad0fSDing Wang 28150971c40eSHarry Wentland void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, 2816529cad0fSDing Wang struct bit_depth_reduction_params *fmt_bit_depth) 2817529cad0fSDing Wang { 28184fa086b9SLeo (Sunpeng) Li enum dc_dither_option option = stream->dither_option; 2819529cad0fSDing Wang enum dc_pixel_encoding pixel_encoding = 28204fa086b9SLeo (Sunpeng) Li stream->timing.pixel_encoding; 2821529cad0fSDing Wang 2822529cad0fSDing Wang memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); 2823529cad0fSDing Wang 2824603767f9STony Cheng if (option == DITHER_OPTION_DEFAULT) { 2825603767f9STony Cheng switch (stream->timing.display_color_depth) { 2826603767f9STony Cheng case COLOR_DEPTH_666: 2827603767f9STony Cheng option = DITHER_OPTION_SPATIAL6; 2828603767f9STony Cheng break; 2829603767f9STony Cheng case COLOR_DEPTH_888: 2830603767f9STony Cheng option = DITHER_OPTION_SPATIAL8; 2831603767f9STony Cheng break; 2832603767f9STony Cheng case COLOR_DEPTH_101010: 2833603767f9STony Cheng option = DITHER_OPTION_SPATIAL10; 2834603767f9STony Cheng break; 2835603767f9STony Cheng default: 2836603767f9STony Cheng option = DITHER_OPTION_DISABLE; 2837603767f9STony Cheng } 2838603767f9STony Cheng } 2839603767f9STony Cheng 2840529cad0fSDing Wang if (option == DITHER_OPTION_DISABLE) 2841529cad0fSDing Wang return; 2842529cad0fSDing Wang 2843529cad0fSDing Wang if (option == DITHER_OPTION_TRUN6) { 2844529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2845529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 0; 2846529cad0fSDing Wang } else if (option == DITHER_OPTION_TRUN8 || 2847529cad0fSDing Wang option == DITHER_OPTION_TRUN8_SPATIAL6 || 2848529cad0fSDing Wang option == DITHER_OPTION_TRUN8_FM6) { 2849529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2850529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 1; 2851529cad0fSDing Wang } else if (option == DITHER_OPTION_TRUN10 || 2852529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL6 || 2853529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8 || 2854529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM8 || 2855529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM6 || 2856529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2857529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2858529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2859529cad0fSDing Wang } 2860529cad0fSDing Wang 2861529cad0fSDing Wang /* special case - Formatter can only reduce by 4 bits at most. 2862529cad0fSDing Wang * When reducing from 12 to 6 bits, 2863529cad0fSDing Wang * HW recommends we use trunc with round mode 2864529cad0fSDing Wang * (if we did nothing, trunc to 10 bits would be used) 2865529cad0fSDing Wang * note that any 12->10 bit reduction is ignored prior to DCE8, 2866529cad0fSDing Wang * as the input was 10 bits. 2867529cad0fSDing Wang */ 2868529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2869529cad0fSDing Wang option == DITHER_OPTION_SPATIAL6 || 2870529cad0fSDing Wang option == DITHER_OPTION_FM6) { 2871529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2872529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2873529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_MODE = 1; 2874529cad0fSDing Wang } 2875529cad0fSDing Wang 2876529cad0fSDing Wang /* spatial dither 2877529cad0fSDing Wang * note that spatial modes 1-3 are never used 2878529cad0fSDing Wang */ 2879529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2880529cad0fSDing Wang option == DITHER_OPTION_SPATIAL6 || 2881529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL6 || 2882529cad0fSDing Wang option == DITHER_OPTION_TRUN8_SPATIAL6) { 2883529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2884529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0; 2885529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2886529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2887529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2888529cad0fSDing Wang } else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM || 2889529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8 || 2890529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8_FM6 || 2891529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8 || 2892529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2893529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2894529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1; 2895529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2896529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2897529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2898529cad0fSDing Wang } else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM || 2899529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10 || 2900529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM8 || 2901529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM6) { 2902529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2903529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2; 2904529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2905529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2906529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2907529cad0fSDing Wang } 2908529cad0fSDing Wang 2909529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6 || 2910529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8 || 2911529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10) { 2912529cad0fSDing Wang fmt_bit_depth->flags.FRAME_RANDOM = 0; 2913529cad0fSDing Wang } else { 2914529cad0fSDing Wang fmt_bit_depth->flags.FRAME_RANDOM = 1; 2915529cad0fSDing Wang } 2916529cad0fSDing Wang 2917529cad0fSDing Wang ////////////////////// 2918529cad0fSDing Wang //// temporal dither 2919529cad0fSDing Wang ////////////////////// 2920529cad0fSDing Wang if (option == DITHER_OPTION_FM6 || 2921529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8_FM6 || 2922529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM6 || 2923529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM6 || 2924529cad0fSDing Wang option == DITHER_OPTION_TRUN8_FM6 || 2925529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2926529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2927529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0; 2928529cad0fSDing Wang } else if (option == DITHER_OPTION_FM8 || 2929529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM8 || 2930529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM8) { 2931529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2932529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1; 2933529cad0fSDing Wang } else if (option == DITHER_OPTION_FM10) { 2934529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2935529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2; 2936529cad0fSDing Wang } 2937529cad0fSDing Wang 2938529cad0fSDing Wang fmt_bit_depth->pixel_encoding = pixel_encoding; 2939529cad0fSDing Wang } 29409345d987SAndrey Grodzovsky 294162c933f9SYongqiang Sun enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) 29429345d987SAndrey Grodzovsky { 2943ceb3dbb4SJun Lei struct dc_link *link = stream->link; 29442b77dcc5SAnthony Koo struct timing_generator *tg = dc->res_pool->timing_generators[0]; 29459345d987SAndrey Grodzovsky enum dc_status res = DC_OK; 29469345d987SAndrey Grodzovsky 29474fa086b9SLeo (Sunpeng) Li calculate_phy_pix_clks(stream); 29489345d987SAndrey Grodzovsky 29494fa086b9SLeo (Sunpeng) Li if (!tg->funcs->validate_timing(tg, &stream->timing)) 29509345d987SAndrey Grodzovsky res = DC_FAIL_CONTROLLER_VALIDATE; 29519345d987SAndrey Grodzovsky 2952248cbed6SEric Bernstein if (res == DC_OK) { 29539345d987SAndrey Grodzovsky if (!link->link_enc->funcs->validate_output_with_stream( 29544fa086b9SLeo (Sunpeng) Li link->link_enc, stream)) 29559345d987SAndrey Grodzovsky res = DC_FAIL_ENC_VALIDATE; 2956248cbed6SEric Bernstein } 29579345d987SAndrey Grodzovsky 29589345d987SAndrey Grodzovsky /* TODO: validate audio ASIC caps, encoder */ 29599345d987SAndrey Grodzovsky 29609345d987SAndrey Grodzovsky if (res == DC_OK) 29614fa086b9SLeo (Sunpeng) Li res = dc_link_validate_mode_timing(stream, 29629345d987SAndrey Grodzovsky link, 29634fa086b9SLeo (Sunpeng) Li &stream->timing); 29649345d987SAndrey Grodzovsky 296562c933f9SYongqiang Sun return res; 29669345d987SAndrey Grodzovsky } 2967792671d7SAndrey Grodzovsky 296862c933f9SYongqiang Sun enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) 2969792671d7SAndrey Grodzovsky { 297062c933f9SYongqiang Sun enum dc_status res = DC_OK; 297162c933f9SYongqiang Sun 2972792671d7SAndrey Grodzovsky /* TODO For now validates pixel format only */ 29738e7095b9SDmytro Laktyushkin if (dc->res_pool->funcs->validate_plane) 297462c933f9SYongqiang Sun return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps); 2975792671d7SAndrey Grodzovsky 297662c933f9SYongqiang Sun return res; 2977792671d7SAndrey Grodzovsky } 297874eac5f3SSu Sung Chung 297974eac5f3SSu Sung Chung unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format) 298074eac5f3SSu Sung Chung { 298174eac5f3SSu Sung Chung switch (format) { 298274eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 298374eac5f3SSu Sung Chung return 8; 298474eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 298574eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 298674eac5f3SSu Sung Chung return 12; 298774eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 298874eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 298974eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 299074eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 299174eac5f3SSu Sung Chung return 16; 299274eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 299374eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 299474eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 299574eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 299674eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 29975dba4991SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN3_0) 29985dba4991SBhawanpreet Lakha case SURFACE_PIXEL_FORMAT_GRPH_RGBE: 29995dba4991SBhawanpreet Lakha case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA: 30005dba4991SBhawanpreet Lakha #endif 300174eac5f3SSu Sung Chung return 32; 300274eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 300374eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 300474eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 300574eac5f3SSu Sung Chung return 64; 300674eac5f3SSu Sung Chung default: 300774eac5f3SSu Sung Chung ASSERT_CRITICAL(false); 300874eac5f3SSu Sung Chung return -1; 300974eac5f3SSu Sung Chung } 301074eac5f3SSu Sung Chung } 30113ab4cc65SCharlene Liu static unsigned int get_max_audio_sample_rate(struct audio_mode *modes) 30123ab4cc65SCharlene Liu { 30133ab4cc65SCharlene Liu if (modes) { 30143ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_192) 30153ab4cc65SCharlene Liu return 192000; 30163ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_176_4) 30173ab4cc65SCharlene Liu return 176400; 30183ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_96) 30193ab4cc65SCharlene Liu return 96000; 30203ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_88_2) 30213ab4cc65SCharlene Liu return 88200; 30223ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_48) 30233ab4cc65SCharlene Liu return 48000; 30243ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_44_1) 30253ab4cc65SCharlene Liu return 44100; 30263ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_32) 30273ab4cc65SCharlene Liu return 32000; 30283ab4cc65SCharlene Liu } 30293ab4cc65SCharlene Liu /*original logic when no audio info*/ 30303ab4cc65SCharlene Liu return 441000; 30313ab4cc65SCharlene Liu } 30323ab4cc65SCharlene Liu 30333ab4cc65SCharlene Liu void get_audio_check(struct audio_info *aud_modes, 30343ab4cc65SCharlene Liu struct audio_check *audio_chk) 30353ab4cc65SCharlene Liu { 30363ab4cc65SCharlene Liu unsigned int i; 30373ab4cc65SCharlene Liu unsigned int max_sample_rate = 0; 30383ab4cc65SCharlene Liu 30393ab4cc65SCharlene Liu if (aud_modes) { 30403ab4cc65SCharlene Liu audio_chk->audio_packet_type = 0x2;/*audio sample packet AP = .25 for layout0, 1 for layout1*/ 30413ab4cc65SCharlene Liu 30423ab4cc65SCharlene Liu audio_chk->max_audiosample_rate = 0; 30433ab4cc65SCharlene Liu for (i = 0; i < aud_modes->mode_count; i++) { 30443ab4cc65SCharlene Liu max_sample_rate = get_max_audio_sample_rate(&aud_modes->modes[i]); 30453ab4cc65SCharlene Liu if (audio_chk->max_audiosample_rate < max_sample_rate) 30463ab4cc65SCharlene Liu audio_chk->max_audiosample_rate = max_sample_rate; 30473ab4cc65SCharlene Liu /*dts takes the same as type 2: AP = 0.25*/ 30483ab4cc65SCharlene Liu } 30493ab4cc65SCharlene Liu /*check which one take more bandwidth*/ 30503ab4cc65SCharlene Liu if (audio_chk->max_audiosample_rate > 192000) 30513ab4cc65SCharlene Liu audio_chk->audio_packet_type = 0x9;/*AP =1*/ 30523ab4cc65SCharlene Liu audio_chk->acat = 0;/*not support*/ 30533ab4cc65SCharlene Liu } 30543ab4cc65SCharlene Liu } 30553ab4cc65SCharlene Liu 3056