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 454562236bSHarry Wentland #include "dce80/dce80_resource.h" 464562236bSHarry Wentland #include "dce100/dce100_resource.h" 474562236bSHarry Wentland #include "dce110/dce110_resource.h" 484562236bSHarry Wentland #include "dce112/dce112_resource.h" 49cf2156e2SAlex Deucher #include "dce120/dce120_resource.h" 50b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 51ff5ef992SAlex Deucher #include "dcn10/dcn10_resource.h" 527ed4e635SHarry Wentland #include "dcn20/dcn20_resource.h" 53e22ece54SBhawanpreet Lakha #include "dcn21/dcn21_resource.h" 54cf2156e2SAlex Deucher #endif 555d4b05ddSBhawanpreet Lakha 565d4b05ddSBhawanpreet Lakha #define DC_LOGGER_INIT(logger) 575d4b05ddSBhawanpreet Lakha 584562236bSHarry Wentland enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) 594562236bSHarry Wentland { 604562236bSHarry Wentland enum dce_version dc_version = DCE_VERSION_UNKNOWN; 614562236bSHarry Wentland switch (asic_id.chip_family) { 624562236bSHarry Wentland 634562236bSHarry Wentland case FAMILY_CI: 644562236bSHarry Wentland dc_version = DCE_VERSION_8_0; 654562236bSHarry Wentland break; 66ebfdf0d0SAlex Deucher case FAMILY_KV: 67ebfdf0d0SAlex Deucher if (ASIC_REV_IS_KALINDI(asic_id.hw_internal_rev) || 68ebfdf0d0SAlex Deucher ASIC_REV_IS_BHAVANI(asic_id.hw_internal_rev) || 69ebfdf0d0SAlex Deucher ASIC_REV_IS_GODAVARI(asic_id.hw_internal_rev)) 70ebfdf0d0SAlex Deucher dc_version = DCE_VERSION_8_3; 71ebfdf0d0SAlex Deucher else 72ebfdf0d0SAlex Deucher dc_version = DCE_VERSION_8_1; 73ebfdf0d0SAlex Deucher break; 744562236bSHarry Wentland case FAMILY_CZ: 754562236bSHarry Wentland dc_version = DCE_VERSION_11_0; 764562236bSHarry Wentland break; 774562236bSHarry Wentland 784562236bSHarry Wentland case FAMILY_VI: 794562236bSHarry Wentland if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) || 804562236bSHarry Wentland ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) { 814562236bSHarry Wentland dc_version = DCE_VERSION_10_0; 824562236bSHarry Wentland break; 834562236bSHarry Wentland } 844562236bSHarry Wentland if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) || 85b264d345SJordan Lazare ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || 86b264d345SJordan Lazare ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) { 874562236bSHarry Wentland dc_version = DCE_VERSION_11_2; 884562236bSHarry Wentland } 890c75d5acSJerry (Fangzhi) Zuo if (ASIC_REV_IS_VEGAM(asic_id.hw_internal_rev)) 900c75d5acSJerry (Fangzhi) Zuo dc_version = DCE_VERSION_11_22; 914562236bSHarry Wentland break; 922c8ad2d5SAlex Deucher case FAMILY_AI: 93b8b6ce89SLeo Li if (ASICREV_IS_VEGA20_P(asic_id.hw_internal_rev)) 94b8b6ce89SLeo Li dc_version = DCE_VERSION_12_1; 95b8b6ce89SLeo Li else 962c8ad2d5SAlex Deucher dc_version = DCE_VERSION_12_0; 972c8ad2d5SAlex Deucher break; 98b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 99ff5ef992SAlex Deucher case FAMILY_RV: 100ff5ef992SAlex Deucher dc_version = DCN_VERSION_1_0; 1010e3d73f1SBhawanpreet Lakha if (ASICREV_IS_RAVEN2(asic_id.hw_internal_rev)) 1020e3d73f1SBhawanpreet Lakha dc_version = DCN_VERSION_1_01; 103e22ece54SBhawanpreet Lakha if (ASICREV_IS_RENOIR(asic_id.hw_internal_rev)) 104e22ece54SBhawanpreet Lakha dc_version = DCN_VERSION_2_1; 105ff5ef992SAlex Deucher break; 106ff5ef992SAlex Deucher #endif 1077ed4e635SHarry Wentland 1087ed4e635SHarry Wentland case FAMILY_NV: 1097ed4e635SHarry Wentland dc_version = DCN_VERSION_2_0; 1107ed4e635SHarry Wentland break; 1114562236bSHarry Wentland default: 1124562236bSHarry Wentland dc_version = DCE_VERSION_UNKNOWN; 1134562236bSHarry Wentland break; 1144562236bSHarry Wentland } 1154562236bSHarry Wentland return dc_version; 1164562236bSHarry Wentland } 1174562236bSHarry Wentland 118d9673c92SHarry Wentland struct resource_pool *dc_create_resource_pool(struct dc *dc, 119d9673c92SHarry Wentland const struct dc_init_data *init_data, 120d9673c92SHarry Wentland enum dce_version dc_version) 1214562236bSHarry Wentland { 1225ac3d3c9SCharlene Liu struct resource_pool *res_pool = NULL; 1234562236bSHarry Wentland 1244562236bSHarry Wentland switch (dc_version) { 1254562236bSHarry Wentland case DCE_VERSION_8_0: 1265ac3d3c9SCharlene Liu res_pool = dce80_create_resource_pool( 127d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1285ac3d3c9SCharlene Liu break; 1297992a629SAlex Deucher case DCE_VERSION_8_1: 1307992a629SAlex Deucher res_pool = dce81_create_resource_pool( 131d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1327992a629SAlex Deucher break; 1337992a629SAlex Deucher case DCE_VERSION_8_3: 1347992a629SAlex Deucher res_pool = dce83_create_resource_pool( 135d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1367992a629SAlex Deucher break; 1374562236bSHarry Wentland case DCE_VERSION_10_0: 1385ac3d3c9SCharlene Liu res_pool = dce100_create_resource_pool( 139d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1405ac3d3c9SCharlene Liu break; 1414562236bSHarry Wentland case DCE_VERSION_11_0: 1425ac3d3c9SCharlene Liu res_pool = dce110_create_resource_pool( 143d9673c92SHarry Wentland init_data->num_virtual_links, dc, 144d9673c92SHarry Wentland init_data->asic_id); 1455ac3d3c9SCharlene Liu break; 1464562236bSHarry Wentland case DCE_VERSION_11_2: 1470c75d5acSJerry (Fangzhi) Zuo case DCE_VERSION_11_22: 1485ac3d3c9SCharlene Liu res_pool = dce112_create_resource_pool( 149d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1505ac3d3c9SCharlene Liu break; 1512c8ad2d5SAlex Deucher case DCE_VERSION_12_0: 152b8b6ce89SLeo Li case DCE_VERSION_12_1: 1532c8ad2d5SAlex Deucher res_pool = dce120_create_resource_pool( 154d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1552c8ad2d5SAlex Deucher break; 156ff5ef992SAlex Deucher 157b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 158ff5ef992SAlex Deucher case DCN_VERSION_1_0: 1590e3d73f1SBhawanpreet Lakha case DCN_VERSION_1_01: 160d9673c92SHarry Wentland res_pool = dcn10_create_resource_pool(init_data, dc); 161ff5ef992SAlex Deucher break; 1623639fa68SZeyu Fan 1633639fa68SZeyu Fan 1647ed4e635SHarry Wentland case DCN_VERSION_2_0: 1657ed4e635SHarry Wentland res_pool = dcn20_create_resource_pool(init_data, dc); 1667ed4e635SHarry Wentland break; 167e22ece54SBhawanpreet Lakha case DCN_VERSION_2_1: 168e22ece54SBhawanpreet Lakha res_pool = dcn21_create_resource_pool(init_data, dc); 169e22ece54SBhawanpreet Lakha break; 170e22ece54SBhawanpreet Lakha #endif 1717ed4e635SHarry Wentland 1724562236bSHarry Wentland default: 1734562236bSHarry Wentland break; 1744562236bSHarry Wentland } 175f49cfa27Shersen wu 1765ac3d3c9SCharlene Liu if (res_pool != NULL) { 1779adc8050SDmytro Laktyushkin if (dc->ctx->dc_bios->fw_info_valid) { 17841a5a2a8Shersen wu res_pool->ref_clocks.xtalin_clock_inKhz = 1799adc8050SDmytro Laktyushkin dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency; 18041a5a2a8Shersen wu /* initialize with firmware data first, no all 18141a5a2a8Shersen wu * ASIC have DCCG SW component. FPGA or 18241a5a2a8Shersen wu * simulation need initialization of 18341a5a2a8Shersen wu * dccg_ref_clock_inKhz, dchub_ref_clock_inKhz 18441a5a2a8Shersen wu * with xtalin_clock_inKhz 18541a5a2a8Shersen wu */ 18641a5a2a8Shersen wu res_pool->ref_clocks.dccg_ref_clock_inKhz = 18741a5a2a8Shersen wu res_pool->ref_clocks.xtalin_clock_inKhz; 18841a5a2a8Shersen wu res_pool->ref_clocks.dchub_ref_clock_inKhz = 18941a5a2a8Shersen wu res_pool->ref_clocks.xtalin_clock_inKhz; 1905ac3d3c9SCharlene Liu } else 1915ac3d3c9SCharlene Liu ASSERT_CRITICAL(false); 1925ac3d3c9SCharlene Liu } 1935ac3d3c9SCharlene Liu 1945ac3d3c9SCharlene Liu return res_pool; 1954562236bSHarry Wentland } 1964562236bSHarry Wentland 197fb3466a4SBhawanpreet Lakha void dc_destroy_resource_pool(struct dc *dc) 1984562236bSHarry Wentland { 1994562236bSHarry Wentland if (dc) { 2004562236bSHarry Wentland if (dc->res_pool) 2014562236bSHarry Wentland dc->res_pool->funcs->destroy(&dc->res_pool); 2024562236bSHarry Wentland 2032004f45eSHarry Wentland kfree(dc->hwseq); 2044562236bSHarry Wentland } 2054562236bSHarry Wentland } 2064562236bSHarry Wentland 2074562236bSHarry Wentland static void update_num_audio( 2084562236bSHarry Wentland const struct resource_straps *straps, 2094562236bSHarry Wentland unsigned int *num_audio, 2104562236bSHarry Wentland struct audio_support *aud_support) 2114562236bSHarry Wentland { 2124562236bSHarry Wentland aud_support->dp_audio = true; 213b8e9eb72SCharlene Liu aud_support->hdmi_audio_native = false; 214b8e9eb72SCharlene Liu aud_support->hdmi_audio_on_dongle = false; 215b8e9eb72SCharlene Liu 216b8e9eb72SCharlene Liu if (straps->hdmi_disable == 0) { 2174562236bSHarry Wentland if (straps->dc_pinstraps_audio & 0x2) { 2184562236bSHarry Wentland aud_support->hdmi_audio_on_dongle = true; 219b8e9eb72SCharlene Liu aud_support->hdmi_audio_native = true; 2204562236bSHarry Wentland } 2214562236bSHarry Wentland } 2224562236bSHarry Wentland 2234562236bSHarry Wentland switch (straps->audio_stream_number) { 2244562236bSHarry Wentland case 0: /* multi streams supported */ 2254562236bSHarry Wentland break; 2264562236bSHarry Wentland case 1: /* multi streams not supported */ 2274562236bSHarry Wentland *num_audio = 1; 2284562236bSHarry Wentland break; 2294562236bSHarry Wentland default: 2304562236bSHarry Wentland DC_ERR("DC: unexpected audio fuse!\n"); 23117a96033SJulia Lawall } 2324562236bSHarry Wentland } 2334562236bSHarry Wentland 2344562236bSHarry Wentland bool resource_construct( 2354562236bSHarry Wentland unsigned int num_virtual_links, 236fb3466a4SBhawanpreet Lakha struct dc *dc, 2374562236bSHarry Wentland struct resource_pool *pool, 2384562236bSHarry Wentland const struct resource_create_funcs *create_funcs) 2394562236bSHarry Wentland { 2404562236bSHarry Wentland struct dc_context *ctx = dc->ctx; 2414562236bSHarry Wentland const struct resource_caps *caps = pool->res_cap; 2424562236bSHarry Wentland int i; 2434562236bSHarry Wentland unsigned int num_audio = caps->num_audio; 2444562236bSHarry Wentland struct resource_straps straps = {0}; 2454562236bSHarry Wentland 2464562236bSHarry Wentland if (create_funcs->read_dce_straps) 2474562236bSHarry Wentland create_funcs->read_dce_straps(dc->ctx, &straps); 2484562236bSHarry Wentland 2494562236bSHarry Wentland pool->audio_count = 0; 2504562236bSHarry Wentland if (create_funcs->create_audio) { 2514562236bSHarry Wentland /* find the total number of streams available via the 2524562236bSHarry Wentland * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT 2534562236bSHarry Wentland * registers (one for each pin) starting from pin 1 2544562236bSHarry Wentland * up to the max number of audio pins. 2554562236bSHarry Wentland * We stop on the first pin where 2564562236bSHarry Wentland * PORT_CONNECTIVITY == 1 (as instructed by HW team). 2574562236bSHarry Wentland */ 2584562236bSHarry Wentland update_num_audio(&straps, &num_audio, &pool->audio_support); 2595feb9f07STai Man for (i = 0; i < caps->num_audio; i++) { 2604562236bSHarry Wentland struct audio *aud = create_funcs->create_audio(ctx, i); 2614562236bSHarry Wentland 2624562236bSHarry Wentland if (aud == NULL) { 2634562236bSHarry Wentland DC_ERR("DC: failed to create audio!\n"); 2644562236bSHarry Wentland return false; 2654562236bSHarry Wentland } 2664562236bSHarry Wentland if (!aud->funcs->endpoint_valid(aud)) { 2674562236bSHarry Wentland aud->funcs->destroy(&aud); 2684562236bSHarry Wentland break; 2694562236bSHarry Wentland } 2704562236bSHarry Wentland pool->audios[i] = aud; 2714562236bSHarry Wentland pool->audio_count++; 2724562236bSHarry Wentland } 2734562236bSHarry Wentland } 2744562236bSHarry Wentland 2754562236bSHarry Wentland pool->stream_enc_count = 0; 2764562236bSHarry Wentland if (create_funcs->create_stream_encoder) { 2774562236bSHarry Wentland for (i = 0; i < caps->num_stream_encoder; i++) { 2784562236bSHarry Wentland pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx); 2794562236bSHarry Wentland if (pool->stream_enc[i] == NULL) 2804562236bSHarry Wentland DC_ERR("DC: failed to create stream_encoder!\n"); 2814562236bSHarry Wentland pool->stream_enc_count++; 2824562236bSHarry Wentland } 2834562236bSHarry Wentland } 284929c3aaaSEric Bernstein 2854176664bSCharlene Liu dc->caps.dynamic_audio = false; 2864176664bSCharlene Liu if (pool->audio_count < pool->stream_enc_count) { 2874176664bSCharlene Liu dc->caps.dynamic_audio = true; 2884176664bSCharlene Liu } 2894562236bSHarry Wentland for (i = 0; i < num_virtual_links; i++) { 2904562236bSHarry Wentland pool->stream_enc[pool->stream_enc_count] = 2914562236bSHarry Wentland virtual_stream_encoder_create( 2924562236bSHarry Wentland ctx, ctx->dc_bios); 2934562236bSHarry Wentland if (pool->stream_enc[pool->stream_enc_count] == NULL) { 2944562236bSHarry Wentland DC_ERR("DC: failed to create stream_encoder!\n"); 2954562236bSHarry Wentland return false; 2964562236bSHarry Wentland } 2974562236bSHarry Wentland pool->stream_enc_count++; 2984562236bSHarry Wentland } 2994562236bSHarry Wentland 3004562236bSHarry Wentland dc->hwseq = create_funcs->create_hwseq(ctx); 3014562236bSHarry Wentland 3024562236bSHarry Wentland return true; 3034562236bSHarry Wentland } 304ad8960a6SMikita Lipski static int find_matching_clock_source( 305ad8960a6SMikita Lipski const struct resource_pool *pool, 306ad8960a6SMikita Lipski struct clock_source *clock_source) 307ad8960a6SMikita Lipski { 3084562236bSHarry Wentland 309ad8960a6SMikita Lipski int i; 310ad8960a6SMikita Lipski 311ad8960a6SMikita Lipski for (i = 0; i < pool->clk_src_count; i++) { 312ad8960a6SMikita Lipski if (pool->clock_sources[i] == clock_source) 313ad8960a6SMikita Lipski return i; 314ad8960a6SMikita Lipski } 315ad8960a6SMikita Lipski return -1; 316ad8960a6SMikita Lipski } 3174562236bSHarry Wentland 31821e67d4dSHarry Wentland void resource_unreference_clock_source( 3194562236bSHarry Wentland struct resource_context *res_ctx, 320a2b8659dSTony Cheng const struct resource_pool *pool, 3214a629536SHarry Wentland struct clock_source *clock_source) 3224562236bSHarry Wentland { 323ad8960a6SMikita Lipski int i = find_matching_clock_source(pool, clock_source); 3244a629536SHarry Wentland 325ad8960a6SMikita Lipski if (i > -1) 3264562236bSHarry Wentland res_ctx->clock_source_ref_count[i]--; 3274562236bSHarry Wentland 32821e67d4dSHarry Wentland if (pool->dp_clock_source == clock_source) 3294562236bSHarry Wentland res_ctx->dp_clock_source_ref_count--; 3304562236bSHarry Wentland } 3314562236bSHarry Wentland 3324562236bSHarry Wentland void resource_reference_clock_source( 3334562236bSHarry Wentland struct resource_context *res_ctx, 334a2b8659dSTony Cheng const struct resource_pool *pool, 3354562236bSHarry Wentland struct clock_source *clock_source) 3364562236bSHarry Wentland { 337ad8960a6SMikita Lipski int i = find_matching_clock_source(pool, clock_source); 3384562236bSHarry Wentland 339ad8960a6SMikita Lipski if (i > -1) 3404562236bSHarry Wentland res_ctx->clock_source_ref_count[i]++; 3414562236bSHarry Wentland 342a2b8659dSTony Cheng if (pool->dp_clock_source == clock_source) 3434562236bSHarry Wentland res_ctx->dp_clock_source_ref_count++; 3444562236bSHarry Wentland } 3454562236bSHarry Wentland 346ad8960a6SMikita Lipski int resource_get_clock_source_reference( 347ad8960a6SMikita Lipski struct resource_context *res_ctx, 348ad8960a6SMikita Lipski const struct resource_pool *pool, 349ad8960a6SMikita Lipski struct clock_source *clock_source) 350ad8960a6SMikita Lipski { 351ad8960a6SMikita Lipski int i = find_matching_clock_source(pool, clock_source); 352ad8960a6SMikita Lipski 353ad8960a6SMikita Lipski if (i > -1) 354ad8960a6SMikita Lipski return res_ctx->clock_source_ref_count[i]; 355ad8960a6SMikita Lipski 356ad8960a6SMikita Lipski if (pool->dp_clock_source == clock_source) 357ad8960a6SMikita Lipski return res_ctx->dp_clock_source_ref_count; 358ad8960a6SMikita Lipski 359ad8960a6SMikita Lipski return -1; 360ad8960a6SMikita Lipski } 361ad8960a6SMikita Lipski 3624562236bSHarry Wentland bool resource_are_streams_timing_synchronizable( 3630971c40eSHarry Wentland struct dc_stream_state *stream1, 3640971c40eSHarry Wentland struct dc_stream_state *stream2) 3654562236bSHarry Wentland { 3664fa086b9SLeo (Sunpeng) Li if (stream1->timing.h_total != stream2->timing.h_total) 3674562236bSHarry Wentland return false; 3684562236bSHarry Wentland 3694fa086b9SLeo (Sunpeng) Li if (stream1->timing.v_total != stream2->timing.v_total) 3704562236bSHarry Wentland return false; 3714562236bSHarry Wentland 3724fa086b9SLeo (Sunpeng) Li if (stream1->timing.h_addressable 3734fa086b9SLeo (Sunpeng) Li != stream2->timing.h_addressable) 3744562236bSHarry Wentland return false; 3754562236bSHarry Wentland 3764fa086b9SLeo (Sunpeng) Li if (stream1->timing.v_addressable 3774fa086b9SLeo (Sunpeng) Li != stream2->timing.v_addressable) 3784562236bSHarry Wentland return false; 3794562236bSHarry Wentland 380380604e2SKen Chalmers if (stream1->timing.pix_clk_100hz 381380604e2SKen Chalmers != stream2->timing.pix_clk_100hz) 3824562236bSHarry Wentland return false; 3834562236bSHarry Wentland 3843e27e10eSMikita Lipski if (stream1->clamping.c_depth != stream2->clamping.c_depth) 3853e27e10eSMikita Lipski return false; 3863e27e10eSMikita Lipski 3874562236bSHarry Wentland if (stream1->phy_pix_clk != stream2->phy_pix_clk 3887e2fe319SCharlene Liu && (!dc_is_dp_signal(stream1->signal) 3897e2fe319SCharlene Liu || !dc_is_dp_signal(stream2->signal))) 3904562236bSHarry Wentland return false; 3914562236bSHarry Wentland 392d77f778eSCharlene Liu if (stream1->view_format != stream2->view_format) 393d77f778eSCharlene Liu return false; 394d77f778eSCharlene Liu 3950460f9abSJun Lei if (stream1->ignore_msa_timing_param || stream2->ignore_msa_timing_param) 3960460f9abSJun Lei return false; 3970460f9abSJun Lei 3984562236bSHarry Wentland return true; 3994562236bSHarry Wentland } 4003e27e10eSMikita Lipski static bool is_dp_and_hdmi_sharable( 4013e27e10eSMikita Lipski struct dc_stream_state *stream1, 4023e27e10eSMikita Lipski struct dc_stream_state *stream2) 4033e27e10eSMikita Lipski { 4043e27e10eSMikita Lipski if (stream1->ctx->dc->caps.disable_dp_clk_share) 4053e27e10eSMikita Lipski return false; 4063e27e10eSMikita Lipski 4073e27e10eSMikita Lipski if (stream1->clamping.c_depth != COLOR_DEPTH_888 || 4083e27e10eSMikita Lipski stream2->clamping.c_depth != COLOR_DEPTH_888) 4093e27e10eSMikita Lipski return false; 4103e27e10eSMikita Lipski 4113e27e10eSMikita Lipski return true; 4123e27e10eSMikita Lipski 4133e27e10eSMikita Lipski } 4144562236bSHarry Wentland 4154562236bSHarry Wentland static bool is_sharable_clk_src( 4164562236bSHarry Wentland const struct pipe_ctx *pipe_with_clk_src, 4174562236bSHarry Wentland const struct pipe_ctx *pipe) 4184562236bSHarry Wentland { 4194562236bSHarry Wentland if (pipe_with_clk_src->clock_source == NULL) 4204562236bSHarry Wentland return false; 4214562236bSHarry Wentland 4224562236bSHarry Wentland if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL) 4234562236bSHarry Wentland return false; 4244562236bSHarry Wentland 4253e27e10eSMikita Lipski if (dc_is_dp_signal(pipe_with_clk_src->stream->signal) || 4263e27e10eSMikita Lipski (dc_is_dp_signal(pipe->stream->signal) && 4273e27e10eSMikita Lipski !is_dp_and_hdmi_sharable(pipe_with_clk_src->stream, 4283e27e10eSMikita Lipski pipe->stream))) 4294562236bSHarry Wentland return false; 4304562236bSHarry Wentland 4314562236bSHarry Wentland if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal) 432fc69009eSMikita Lipski && dc_is_dual_link_signal(pipe->stream->signal)) 4334562236bSHarry Wentland return false; 4344562236bSHarry Wentland 4354562236bSHarry Wentland if (dc_is_hdmi_signal(pipe->stream->signal) 436fc69009eSMikita Lipski && dc_is_dual_link_signal(pipe_with_clk_src->stream->signal)) 4374562236bSHarry Wentland return false; 4384562236bSHarry Wentland 4394562236bSHarry Wentland if (!resource_are_streams_timing_synchronizable( 4404562236bSHarry Wentland pipe_with_clk_src->stream, pipe->stream)) 4414562236bSHarry Wentland return false; 4424562236bSHarry Wentland 4434562236bSHarry Wentland return true; 4444562236bSHarry Wentland } 4454562236bSHarry Wentland 4464562236bSHarry Wentland struct clock_source *resource_find_used_clk_src_for_sharing( 4474562236bSHarry Wentland struct resource_context *res_ctx, 4484562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 4494562236bSHarry Wentland { 4504562236bSHarry Wentland int i; 4514562236bSHarry Wentland 4524562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 4534562236bSHarry Wentland if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx)) 4544562236bSHarry Wentland return res_ctx->pipe_ctx[i].clock_source; 4554562236bSHarry Wentland } 4564562236bSHarry Wentland 4574562236bSHarry Wentland return NULL; 4584562236bSHarry Wentland } 4594562236bSHarry Wentland 4604562236bSHarry Wentland static enum pixel_format convert_pixel_format_to_dalsurface( 4614562236bSHarry Wentland enum surface_pixel_format surface_pixel_format) 4624562236bSHarry Wentland { 4634562236bSHarry Wentland enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 4644562236bSHarry Wentland 4654562236bSHarry Wentland switch (surface_pixel_format) { 4664562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 4674562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_INDEX8; 4684562236bSHarry Wentland break; 4694562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 4704562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_RGB565; 4714562236bSHarry Wentland break; 4724562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 4734562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_RGB565; 4744562236bSHarry Wentland break; 4754562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 4764562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB8888; 4774562236bSHarry Wentland break; 4788693049aSTony Cheng case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 4794562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB8888; 4804562236bSHarry Wentland break; 4814562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 4824562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 4834562236bSHarry Wentland break; 4844562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 4854562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 4864562236bSHarry Wentland break; 4874562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 4884562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS; 4894562236bSHarry Wentland break; 4904562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 4914562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 4924562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_FP16; 4934562236bSHarry Wentland break; 4944562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 4954562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 49687449a90SAnthony Koo dal_pixel_format = PIXEL_FORMAT_420BPP8; 4974562236bSHarry Wentland break; 498ffbcd19aSVitaly Prosyak case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 499ffbcd19aSVitaly Prosyak case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 50087449a90SAnthony Koo dal_pixel_format = PIXEL_FORMAT_420BPP10; 501ffbcd19aSVitaly Prosyak break; 5024562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 5034562236bSHarry Wentland default: 5044562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 5054562236bSHarry Wentland break; 5064562236bSHarry Wentland } 5074562236bSHarry Wentland return dal_pixel_format; 5084562236bSHarry Wentland } 5094562236bSHarry Wentland 5109b6067c0SDmytro Laktyushkin static inline void get_vp_scan_direction( 5119b6067c0SDmytro Laktyushkin enum dc_rotation_angle rotation, 5129b6067c0SDmytro Laktyushkin bool horizontal_mirror, 5139b6067c0SDmytro Laktyushkin bool *orthogonal_rotation, 5149b6067c0SDmytro Laktyushkin bool *flip_vert_scan_dir, 5159b6067c0SDmytro Laktyushkin bool *flip_horz_scan_dir) 5164562236bSHarry Wentland { 5179b6067c0SDmytro Laktyushkin *orthogonal_rotation = false; 5189b6067c0SDmytro Laktyushkin *flip_vert_scan_dir = false; 5199b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = false; 5209b6067c0SDmytro Laktyushkin if (rotation == ROTATION_ANGLE_180) { 5219b6067c0SDmytro Laktyushkin *flip_vert_scan_dir = true; 5229b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = true; 5239b6067c0SDmytro Laktyushkin } else if (rotation == ROTATION_ANGLE_90) { 5249b6067c0SDmytro Laktyushkin *orthogonal_rotation = true; 5259b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = true; 5269b6067c0SDmytro Laktyushkin } else if (rotation == ROTATION_ANGLE_270) { 5279b6067c0SDmytro Laktyushkin *orthogonal_rotation = true; 5289b6067c0SDmytro Laktyushkin *flip_vert_scan_dir = true; 5299b6067c0SDmytro Laktyushkin } 5309b6067c0SDmytro Laktyushkin 5319b6067c0SDmytro Laktyushkin if (horizontal_mirror) 5329b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = !*flip_horz_scan_dir; 5334562236bSHarry Wentland } 5344562236bSHarry Wentland 535228a10d4SAlex Deucher int get_num_odm_splits(struct pipe_ctx *pipe) 536228a10d4SAlex Deucher { 537228a10d4SAlex Deucher int odm_split_count = 0; 538228a10d4SAlex Deucher struct pipe_ctx *next_pipe = pipe->next_odm_pipe; 539228a10d4SAlex Deucher while (next_pipe) { 540228a10d4SAlex Deucher odm_split_count++; 541228a10d4SAlex Deucher next_pipe = next_pipe->next_odm_pipe; 542228a10d4SAlex Deucher } 543228a10d4SAlex Deucher pipe = pipe->prev_odm_pipe; 544228a10d4SAlex Deucher while (pipe) { 545228a10d4SAlex Deucher odm_split_count++; 546228a10d4SAlex Deucher pipe = pipe->prev_odm_pipe; 547228a10d4SAlex Deucher } 548228a10d4SAlex Deucher return odm_split_count; 549228a10d4SAlex Deucher } 550228a10d4SAlex Deucher 5515bf24270SDmytro Laktyushkin static void calculate_split_count_and_index(struct pipe_ctx *pipe_ctx, int *split_count, int *split_idx) 5525bf24270SDmytro Laktyushkin { 5535bf24270SDmytro Laktyushkin *split_count = get_num_odm_splits(pipe_ctx); 5545bf24270SDmytro Laktyushkin *split_idx = 0; 5555bf24270SDmytro Laktyushkin if (*split_count == 0) { 5565bf24270SDmytro Laktyushkin /*Check for mpc split*/ 5575bf24270SDmytro Laktyushkin struct pipe_ctx *split_pipe = pipe_ctx->top_pipe; 5585bf24270SDmytro Laktyushkin 5595bf24270SDmytro Laktyushkin while (split_pipe && split_pipe->plane_state == pipe_ctx->plane_state) { 5605bf24270SDmytro Laktyushkin (*split_idx)++; 5615bf24270SDmytro Laktyushkin (*split_count)++; 5625bf24270SDmytro Laktyushkin split_pipe = split_pipe->top_pipe; 5635bf24270SDmytro Laktyushkin } 5645bf24270SDmytro Laktyushkin split_pipe = pipe_ctx->bottom_pipe; 5655bf24270SDmytro Laktyushkin while (split_pipe && split_pipe->plane_state == pipe_ctx->plane_state) { 5665bf24270SDmytro Laktyushkin (*split_count)++; 5675bf24270SDmytro Laktyushkin split_pipe = split_pipe->bottom_pipe; 5685bf24270SDmytro Laktyushkin } 5695bf24270SDmytro Laktyushkin } else { 5705bf24270SDmytro Laktyushkin /*Get odm split index*/ 5715bf24270SDmytro Laktyushkin struct pipe_ctx *split_pipe = pipe_ctx->prev_odm_pipe; 5725bf24270SDmytro Laktyushkin 5735bf24270SDmytro Laktyushkin while (split_pipe) { 5745bf24270SDmytro Laktyushkin (*split_idx)++; 5755bf24270SDmytro Laktyushkin split_pipe = split_pipe->prev_odm_pipe; 5765bf24270SDmytro Laktyushkin } 5775bf24270SDmytro Laktyushkin } 5785bf24270SDmytro Laktyushkin } 5795bf24270SDmytro Laktyushkin 580b2d0a103SDmytro Laktyushkin static void calculate_viewport(struct pipe_ctx *pipe_ctx) 5814562236bSHarry Wentland { 5823be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 5830971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 5846702a9acSHarry Wentland struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 5853be5262eSHarry Wentland struct rect surf_src = plane_state->src_rect; 5869b6067c0SDmytro Laktyushkin struct rect clip, dest; 58787449a90SAnthony Koo int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 58887449a90SAnthony Koo || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 5895bf24270SDmytro Laktyushkin int split_count = 0; 5905bf24270SDmytro Laktyushkin int split_idx = 0; 5919b6067c0SDmytro Laktyushkin bool orthogonal_rotation, flip_y_start, flip_x_start; 59283d40659SDmytro Laktyushkin 5935bf24270SDmytro Laktyushkin calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); 5945bf24270SDmytro Laktyushkin 5957f5c22d1SVitaly Prosyak if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || 5967f5c22d1SVitaly Prosyak stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { 5975bf24270SDmytro Laktyushkin split_count = 0; 5985bf24270SDmytro Laktyushkin split_idx = 0; 5997b779c99SVitaly Prosyak } 60086006a7fSDmytro Laktyushkin 6014562236bSHarry Wentland /* The actual clip is an intersection between stream 6024562236bSHarry Wentland * source and surface clip 6034562236bSHarry Wentland */ 6049b6067c0SDmytro Laktyushkin dest = plane_state->dst_rect; 6053be5262eSHarry Wentland clip.x = stream->src.x > plane_state->clip_rect.x ? 6063be5262eSHarry Wentland stream->src.x : plane_state->clip_rect.x; 6074562236bSHarry Wentland 6081fbd2cfcSDmytro Laktyushkin clip.width = stream->src.x + stream->src.width < 6093be5262eSHarry Wentland plane_state->clip_rect.x + plane_state->clip_rect.width ? 6101fbd2cfcSDmytro Laktyushkin stream->src.x + stream->src.width - clip.x : 6113be5262eSHarry Wentland plane_state->clip_rect.x + plane_state->clip_rect.width - clip.x ; 6124562236bSHarry Wentland 6133be5262eSHarry Wentland clip.y = stream->src.y > plane_state->clip_rect.y ? 6143be5262eSHarry Wentland stream->src.y : plane_state->clip_rect.y; 6154562236bSHarry Wentland 6161fbd2cfcSDmytro Laktyushkin clip.height = stream->src.y + stream->src.height < 6173be5262eSHarry Wentland plane_state->clip_rect.y + plane_state->clip_rect.height ? 6181fbd2cfcSDmytro Laktyushkin stream->src.y + stream->src.height - clip.y : 6193be5262eSHarry Wentland plane_state->clip_rect.y + plane_state->clip_rect.height - clip.y ; 6204562236bSHarry Wentland 6219b6067c0SDmytro Laktyushkin /* 6229b6067c0SDmytro Laktyushkin * Need to calculate how scan origin is shifted in vp space 6239b6067c0SDmytro Laktyushkin * to correctly rotate clip and dst 6249b6067c0SDmytro Laktyushkin */ 6259b6067c0SDmytro Laktyushkin get_vp_scan_direction( 6269b6067c0SDmytro Laktyushkin plane_state->rotation, 6279b6067c0SDmytro Laktyushkin plane_state->horizontal_mirror, 6289b6067c0SDmytro Laktyushkin &orthogonal_rotation, 6299b6067c0SDmytro Laktyushkin &flip_y_start, 6309b6067c0SDmytro Laktyushkin &flip_x_start); 6319b6067c0SDmytro Laktyushkin 6329b6067c0SDmytro Laktyushkin if (orthogonal_rotation) { 6339b6067c0SDmytro Laktyushkin swap(clip.x, clip.y); 6349b6067c0SDmytro Laktyushkin swap(clip.width, clip.height); 6359b6067c0SDmytro Laktyushkin swap(dest.x, dest.y); 6369b6067c0SDmytro Laktyushkin swap(dest.width, dest.height); 6379b6067c0SDmytro Laktyushkin } 6389b6067c0SDmytro Laktyushkin if (flip_x_start) { 6399b6067c0SDmytro Laktyushkin clip.x = dest.x + dest.width - clip.x - clip.width; 6409b6067c0SDmytro Laktyushkin dest.x = 0; 6419b6067c0SDmytro Laktyushkin } 6429b6067c0SDmytro Laktyushkin if (flip_y_start) { 6439b6067c0SDmytro Laktyushkin clip.y = dest.y + dest.height - clip.y - clip.height; 6449b6067c0SDmytro Laktyushkin dest.y = 0; 6459b6067c0SDmytro Laktyushkin } 6469b6067c0SDmytro Laktyushkin 64786006a7fSDmytro Laktyushkin /* offset = surf_src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio 6484562236bSHarry Wentland * num_pixels = clip.num_pix * scl_ratio 6494562236bSHarry Wentland */ 6509b6067c0SDmytro Laktyushkin data->viewport.x = surf_src.x + (clip.x - dest.x) * surf_src.width / dest.width; 6519b6067c0SDmytro Laktyushkin data->viewport.width = clip.width * surf_src.width / dest.width; 6524562236bSHarry Wentland 6539b6067c0SDmytro Laktyushkin data->viewport.y = surf_src.y + (clip.y - dest.y) * surf_src.height / dest.height; 6549b6067c0SDmytro Laktyushkin data->viewport.height = clip.height * surf_src.height / dest.height; 6554562236bSHarry Wentland 6569b6067c0SDmytro Laktyushkin /* Handle split */ 6575bf24270SDmytro Laktyushkin if (split_count) { 6585bf24270SDmytro Laktyushkin /* extra pixels in the division remainder need to go to pipes after 6595bf24270SDmytro Laktyushkin * the extra pixel index minus one(epimo) defined here as: 6605bf24270SDmytro Laktyushkin */ 6615bf24270SDmytro Laktyushkin int epimo = 0; 6625bf24270SDmytro Laktyushkin 6639b6067c0SDmytro Laktyushkin if (orthogonal_rotation) { 6645bf24270SDmytro Laktyushkin if (flip_y_start) 6655bf24270SDmytro Laktyushkin split_idx = split_count - split_idx; 6665bf24270SDmytro Laktyushkin 6675bf24270SDmytro Laktyushkin epimo = split_count - data->viewport.height % (split_count + 1); 6685bf24270SDmytro Laktyushkin 6695bf24270SDmytro Laktyushkin data->viewport.y += (data->viewport.height / (split_count + 1)) * split_idx; 6705bf24270SDmytro Laktyushkin if (split_idx > epimo) 6715bf24270SDmytro Laktyushkin data->viewport.y += split_idx - epimo - 1; 6725bf24270SDmytro Laktyushkin data->viewport.height = data->viewport.height / (split_count + 1) + (split_idx > epimo ? 1 : 0); 6739b6067c0SDmytro Laktyushkin } else { 6745bf24270SDmytro Laktyushkin if (flip_x_start) 6755bf24270SDmytro Laktyushkin split_idx = split_count - split_idx; 6765bf24270SDmytro Laktyushkin 6775bf24270SDmytro Laktyushkin epimo = split_count - data->viewport.width % (split_count + 1); 6785bf24270SDmytro Laktyushkin 6795bf24270SDmytro Laktyushkin data->viewport.x += (data->viewport.width / (split_count + 1)) * split_idx; 6805bf24270SDmytro Laktyushkin if (split_idx > epimo) 6815bf24270SDmytro Laktyushkin data->viewport.x += split_idx - epimo - 1; 6825bf24270SDmytro Laktyushkin data->viewport.width = data->viewport.width / (split_count + 1) + (split_idx > epimo ? 1 : 0); 6839b6067c0SDmytro Laktyushkin } 6849b6067c0SDmytro Laktyushkin } 6859b5349f7SMartin Tsai 686b2d0a103SDmytro Laktyushkin /* Round down, compensate in init */ 687b2d0a103SDmytro Laktyushkin data->viewport_c.x = data->viewport.x / vpc_div; 688b2d0a103SDmytro Laktyushkin data->viewport_c.y = data->viewport.y / vpc_div; 6899b6067c0SDmytro Laktyushkin data->inits.h_c = (data->viewport.x % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero; 6909b6067c0SDmytro Laktyushkin data->inits.v_c = (data->viewport.y % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero; 6919b6067c0SDmytro Laktyushkin 692b2d0a103SDmytro Laktyushkin /* Round up, assume original video size always even dimensions */ 693b2d0a103SDmytro Laktyushkin data->viewport_c.width = (data->viewport.width + vpc_div - 1) / vpc_div; 694b2d0a103SDmytro Laktyushkin data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; 695b2d0a103SDmytro Laktyushkin } 6961fbd2cfcSDmytro Laktyushkin 6979b6067c0SDmytro Laktyushkin static void calculate_recout(struct pipe_ctx *pipe_ctx) 6984562236bSHarry Wentland { 6993be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 7000971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 7015bf24270SDmytro Laktyushkin struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 7023be5262eSHarry Wentland struct rect surf_clip = plane_state->clip_rect; 7035bf24270SDmytro Laktyushkin bool pri_split_tb = pipe_ctx->bottom_pipe && 7045bf24270SDmytro Laktyushkin pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state && 7055bf24270SDmytro Laktyushkin stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; 7065bf24270SDmytro Laktyushkin bool sec_split_tb = pipe_ctx->top_pipe && 7075bf24270SDmytro Laktyushkin pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state && 7085bf24270SDmytro Laktyushkin stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; 7095bf24270SDmytro Laktyushkin int split_count = 0; 7105bf24270SDmytro Laktyushkin int split_idx = 0; 7114562236bSHarry Wentland 7125bf24270SDmytro Laktyushkin calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); 7135bf24270SDmytro Laktyushkin 7145bf24270SDmytro Laktyushkin data->recout.x = stream->dst.x; 7154fa086b9SLeo (Sunpeng) Li if (stream->src.x < surf_clip.x) 7165bf24270SDmytro Laktyushkin data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width 7174fa086b9SLeo (Sunpeng) Li / stream->src.width; 7184562236bSHarry Wentland 7195bf24270SDmytro Laktyushkin data->recout.width = surf_clip.width * stream->dst.width / stream->src.width; 7205bf24270SDmytro Laktyushkin if (data->recout.width + data->recout.x > stream->dst.x + stream->dst.width) 7215bf24270SDmytro Laktyushkin data->recout.width = stream->dst.x + stream->dst.width - data->recout.x; 7224562236bSHarry Wentland 7235bf24270SDmytro Laktyushkin data->recout.y = stream->dst.y; 7244fa086b9SLeo (Sunpeng) Li if (stream->src.y < surf_clip.y) 7255bf24270SDmytro Laktyushkin data->recout.y += (surf_clip.y - stream->src.y) * stream->dst.height 7264fa086b9SLeo (Sunpeng) Li / stream->src.height; 7274562236bSHarry Wentland 7285bf24270SDmytro Laktyushkin data->recout.height = surf_clip.height * stream->dst.height / stream->src.height; 7295bf24270SDmytro Laktyushkin if (data->recout.height + data->recout.y > stream->dst.y + stream->dst.height) 7305bf24270SDmytro Laktyushkin data->recout.height = stream->dst.y + stream->dst.height - data->recout.y; 731b2d0a103SDmytro Laktyushkin 7329b6067c0SDmytro Laktyushkin /* Handle h & v split, handle rotation using viewport */ 7335bf24270SDmytro Laktyushkin if (sec_split_tb) { 7345bf24270SDmytro Laktyushkin data->recout.y += data->recout.height / 2; 7357b779c99SVitaly Prosyak /* Floor primary pipe, ceil 2ndary pipe */ 7365bf24270SDmytro Laktyushkin data->recout.height = (data->recout.height + 1) / 2; 7375bf24270SDmytro Laktyushkin } else if (pri_split_tb) 7385bf24270SDmytro Laktyushkin data->recout.height /= 2; 7395bf24270SDmytro Laktyushkin else if (split_count) { 7405bf24270SDmytro Laktyushkin /* extra pixels in the division remainder need to go to pipes after 7415bf24270SDmytro Laktyushkin * the extra pixel index minus one(epimo) defined here as: 7425bf24270SDmytro Laktyushkin */ 7435bf24270SDmytro Laktyushkin int epimo = split_count - data->recout.width % (split_count + 1); 7445bf24270SDmytro Laktyushkin 7455bf24270SDmytro Laktyushkin /*no recout offset due to odm */ 7465bf24270SDmytro Laktyushkin if (!pipe_ctx->next_odm_pipe && !pipe_ctx->prev_odm_pipe) { 7475bf24270SDmytro Laktyushkin data->recout.x += (data->recout.width / (split_count + 1)) * split_idx; 7485bf24270SDmytro Laktyushkin if (split_idx > epimo) 7495bf24270SDmytro Laktyushkin data->recout.x += split_idx - epimo - 1; 7505bf24270SDmytro Laktyushkin } 7515bf24270SDmytro Laktyushkin data->recout.width = data->recout.width / (split_count + 1) + (split_idx > epimo ? 1 : 0); 7525bf24270SDmytro Laktyushkin } 7534562236bSHarry Wentland } 754b2d0a103SDmytro Laktyushkin 755b2d0a103SDmytro Laktyushkin static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) 7564562236bSHarry Wentland { 7573be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 7580971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 7593be5262eSHarry Wentland struct rect surf_src = plane_state->src_rect; 7604fa086b9SLeo (Sunpeng) Li const int in_w = stream->src.width; 7614fa086b9SLeo (Sunpeng) Li const int in_h = stream->src.height; 7624fa086b9SLeo (Sunpeng) Li const int out_w = stream->dst.width; 7634fa086b9SLeo (Sunpeng) Li const int out_h = stream->dst.height; 7644562236bSHarry Wentland 7659b6067c0SDmytro Laktyushkin /*Swap surf_src height and width since scaling ratios are in recout rotation*/ 7663be5262eSHarry Wentland if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 7673be5262eSHarry Wentland pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 7689b6067c0SDmytro Laktyushkin swap(surf_src.height, surf_src.width); 76986006a7fSDmytro Laktyushkin 770eb0e5154SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_from_fraction( 77186006a7fSDmytro Laktyushkin surf_src.width, 7723be5262eSHarry Wentland plane_state->dst_rect.width); 773eb0e5154SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_from_fraction( 77486006a7fSDmytro Laktyushkin surf_src.height, 7753be5262eSHarry Wentland plane_state->dst_rect.height); 7764562236bSHarry Wentland 7774fa086b9SLeo (Sunpeng) Li if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) 7786702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value *= 2; 7794fa086b9SLeo (Sunpeng) Li else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) 7806702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value *= 2; 7814562236bSHarry Wentland 7826702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value = div64_s64( 7836702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value * in_h, out_h); 7846702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value = div64_s64( 7856702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value * in_w, out_w); 7864562236bSHarry Wentland 7876702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz_c = pipe_ctx->plane_res.scl_data.ratios.horz; 7886702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert_c = pipe_ctx->plane_res.scl_data.ratios.vert; 7894562236bSHarry Wentland 7906702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP8 7916702a9acSHarry Wentland || pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP10) { 7926702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz_c.value /= 2; 7936702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert_c.value /= 2; 7944562236bSHarry Wentland } 7950002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_truncate( 7960002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz, 19); 7970002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_truncate( 7980002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert, 19); 7990002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz_c = dc_fixpt_truncate( 8000002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz_c, 19); 8010002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert_c = dc_fixpt_truncate( 8020002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert_c, 19); 8034562236bSHarry Wentland } 8044562236bSHarry Wentland 8059b6067c0SDmytro Laktyushkin static inline void adjust_vp_and_init_for_seamless_clip( 8069b6067c0SDmytro Laktyushkin bool flip_scan_dir, 8079b6067c0SDmytro Laktyushkin int recout_skip, 8089b6067c0SDmytro Laktyushkin int src_size, 8099b6067c0SDmytro Laktyushkin int taps, 8109b6067c0SDmytro Laktyushkin struct fixed31_32 ratio, 8119b6067c0SDmytro Laktyushkin struct fixed31_32 *init, 8129b6067c0SDmytro Laktyushkin int *vp_offset, 8139b6067c0SDmytro Laktyushkin int *vp_size) 8144562236bSHarry Wentland { 8159b6067c0SDmytro Laktyushkin if (!flip_scan_dir) { 8169b6067c0SDmytro Laktyushkin /* Adjust for viewport end clip-off */ 8179b6067c0SDmytro Laktyushkin if ((*vp_offset + *vp_size) < src_size) { 8189b6067c0SDmytro Laktyushkin int vp_clip = src_size - *vp_size - *vp_offset; 8199b6067c0SDmytro Laktyushkin int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio)); 8209b6067c0SDmytro Laktyushkin 8219b6067c0SDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 8229b6067c0SDmytro Laktyushkin *vp_size += int_part < vp_clip ? int_part : vp_clip; 8239b6067c0SDmytro Laktyushkin } 8249b6067c0SDmytro Laktyushkin 8259b6067c0SDmytro Laktyushkin /* Adjust for non-0 viewport offset */ 8269b6067c0SDmytro Laktyushkin if (*vp_offset) { 8279b6067c0SDmytro Laktyushkin int int_part; 8289b6067c0SDmytro Laktyushkin 8299b6067c0SDmytro Laktyushkin *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip)); 8309b6067c0SDmytro Laktyushkin int_part = dc_fixpt_floor(*init) - *vp_offset; 8319b6067c0SDmytro Laktyushkin if (int_part < taps) { 8329b6067c0SDmytro Laktyushkin int int_adj = *vp_offset >= (taps - int_part) ? 8339b6067c0SDmytro Laktyushkin (taps - int_part) : *vp_offset; 8349b6067c0SDmytro Laktyushkin *vp_offset -= int_adj; 8359b6067c0SDmytro Laktyushkin *vp_size += int_adj; 8369b6067c0SDmytro Laktyushkin int_part += int_adj; 8379b6067c0SDmytro Laktyushkin } else if (int_part > taps) { 8389b6067c0SDmytro Laktyushkin *vp_offset += int_part - taps; 8399b6067c0SDmytro Laktyushkin *vp_size -= int_part - taps; 8409b6067c0SDmytro Laktyushkin int_part = taps; 8419b6067c0SDmytro Laktyushkin } 8429b6067c0SDmytro Laktyushkin init->value &= 0xffffffff; 8439b6067c0SDmytro Laktyushkin *init = dc_fixpt_add_int(*init, int_part); 8449b6067c0SDmytro Laktyushkin } 8459b6067c0SDmytro Laktyushkin } else { 8469b6067c0SDmytro Laktyushkin /* Adjust for non-0 viewport offset */ 8479b6067c0SDmytro Laktyushkin if (*vp_offset) { 8489b6067c0SDmytro Laktyushkin int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio)); 8499b6067c0SDmytro Laktyushkin 8509b6067c0SDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 8519b6067c0SDmytro Laktyushkin *vp_size += int_part < *vp_offset ? int_part : *vp_offset; 8529b6067c0SDmytro Laktyushkin *vp_offset -= int_part < *vp_offset ? int_part : *vp_offset; 8539b6067c0SDmytro Laktyushkin } 8549b6067c0SDmytro Laktyushkin 8559b6067c0SDmytro Laktyushkin /* Adjust for viewport end clip-off */ 8569b6067c0SDmytro Laktyushkin if ((*vp_offset + *vp_size) < src_size) { 8579b6067c0SDmytro Laktyushkin int int_part; 8589b6067c0SDmytro Laktyushkin int end_offset = src_size - *vp_offset - *vp_size; 8599b6067c0SDmytro Laktyushkin 8609b6067c0SDmytro Laktyushkin /* 8619b6067c0SDmytro Laktyushkin * this is init if vp had no offset, keep in mind this is from the 8629b6067c0SDmytro Laktyushkin * right side of vp due to scan direction 8639b6067c0SDmytro Laktyushkin */ 8649b6067c0SDmytro Laktyushkin *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip)); 8659b6067c0SDmytro Laktyushkin /* 8669b6067c0SDmytro Laktyushkin * this is the difference between first pixel of viewport available to read 8679b6067c0SDmytro Laktyushkin * and init position, takning into account scan direction 8689b6067c0SDmytro Laktyushkin */ 8699b6067c0SDmytro Laktyushkin int_part = dc_fixpt_floor(*init) - end_offset; 8709b6067c0SDmytro Laktyushkin if (int_part < taps) { 8719b6067c0SDmytro Laktyushkin int int_adj = end_offset >= (taps - int_part) ? 8729b6067c0SDmytro Laktyushkin (taps - int_part) : end_offset; 8739b6067c0SDmytro Laktyushkin *vp_size += int_adj; 8749b6067c0SDmytro Laktyushkin int_part += int_adj; 8759b6067c0SDmytro Laktyushkin } else if (int_part > taps) { 8769b6067c0SDmytro Laktyushkin *vp_size += int_part - taps; 8779b6067c0SDmytro Laktyushkin int_part = taps; 8789b6067c0SDmytro Laktyushkin } 8799b6067c0SDmytro Laktyushkin init->value &= 0xffffffff; 8809b6067c0SDmytro Laktyushkin *init = dc_fixpt_add_int(*init, int_part); 8819b6067c0SDmytro Laktyushkin } 8829b6067c0SDmytro Laktyushkin } 8839b6067c0SDmytro Laktyushkin } 8849b6067c0SDmytro Laktyushkin 8859b6067c0SDmytro Laktyushkin static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx) 8869b6067c0SDmytro Laktyushkin { 8879b6067c0SDmytro Laktyushkin const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 8889b6067c0SDmytro Laktyushkin const struct dc_stream_state *stream = pipe_ctx->stream; 8895bf24270SDmytro Laktyushkin struct pipe_ctx *odm_pipe = pipe_ctx->prev_odm_pipe; 8906702a9acSHarry Wentland struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 8913be5262eSHarry Wentland struct rect src = pipe_ctx->plane_state->src_rect; 8929b6067c0SDmytro Laktyushkin int recout_skip_h, recout_skip_v, surf_size_h, surf_size_v; 89387449a90SAnthony Koo int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 89487449a90SAnthony Koo || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 8959b6067c0SDmytro Laktyushkin bool orthogonal_rotation, flip_vert_scan_dir, flip_horz_scan_dir; 8967287a675SDmytro Laktyushkin int odm_idx = 0; 897b2d0a103SDmytro Laktyushkin 898b0131391SDmytro Laktyushkin /* 899b0131391SDmytro Laktyushkin * Need to calculate the scan direction for viewport to make adjustments 900b0131391SDmytro Laktyushkin */ 9019b6067c0SDmytro Laktyushkin get_vp_scan_direction( 9029b6067c0SDmytro Laktyushkin plane_state->rotation, 9039b6067c0SDmytro Laktyushkin plane_state->horizontal_mirror, 9049b6067c0SDmytro Laktyushkin &orthogonal_rotation, 9059b6067c0SDmytro Laktyushkin &flip_vert_scan_dir, 9069b6067c0SDmytro Laktyushkin &flip_horz_scan_dir); 907b0131391SDmytro Laktyushkin 9089b6067c0SDmytro Laktyushkin /* Calculate src rect rotation adjusted to recout space */ 9099b6067c0SDmytro Laktyushkin surf_size_h = src.x + src.width; 9109b6067c0SDmytro Laktyushkin surf_size_v = src.y + src.height; 9119b6067c0SDmytro Laktyushkin if (flip_horz_scan_dir) 9129b6067c0SDmytro Laktyushkin src.x = 0; 9139b6067c0SDmytro Laktyushkin if (flip_vert_scan_dir) 9149b6067c0SDmytro Laktyushkin src.y = 0; 9159b6067c0SDmytro Laktyushkin if (orthogonal_rotation) { 9169b6067c0SDmytro Laktyushkin swap(src.x, src.y); 9179b6067c0SDmytro Laktyushkin swap(src.width, src.height); 9189b5349f7SMartin Tsai } 9191fbd2cfcSDmytro Laktyushkin 9209b6067c0SDmytro Laktyushkin /* Recout matching initial vp offset = recout_offset - (stream dst offset + 9219b6067c0SDmytro Laktyushkin * ((surf dst offset - stream src offset) * 1/ stream scaling ratio) 9229b6067c0SDmytro Laktyushkin * - (surf surf_src offset * 1/ full scl ratio)) 9239b6067c0SDmytro Laktyushkin */ 9249b6067c0SDmytro Laktyushkin recout_skip_h = data->recout.x - (stream->dst.x + (plane_state->dst_rect.x - stream->src.x) 9259b6067c0SDmytro Laktyushkin * stream->dst.width / stream->src.width - 9269b6067c0SDmytro Laktyushkin src.x * plane_state->dst_rect.width / src.width 9279b6067c0SDmytro Laktyushkin * stream->dst.width / stream->src.width); 9287287a675SDmytro Laktyushkin /*modified recout_skip_h calculation due to odm having no recout offset*/ 9295bf24270SDmytro Laktyushkin while (odm_pipe) { 9307287a675SDmytro Laktyushkin odm_idx++; 9315bf24270SDmytro Laktyushkin odm_pipe = odm_pipe->prev_odm_pipe; 9325bf24270SDmytro Laktyushkin } 9337287a675SDmytro Laktyushkin if (odm_idx) 9347287a675SDmytro Laktyushkin recout_skip_h += odm_idx * data->recout.width; 9355bf24270SDmytro Laktyushkin 9369b6067c0SDmytro Laktyushkin recout_skip_v = data->recout.y - (stream->dst.y + (plane_state->dst_rect.y - stream->src.y) 9379b6067c0SDmytro Laktyushkin * stream->dst.height / stream->src.height - 9389b6067c0SDmytro Laktyushkin src.y * plane_state->dst_rect.height / src.height 9399b6067c0SDmytro Laktyushkin * stream->dst.height / stream->src.height); 9409b6067c0SDmytro Laktyushkin if (orthogonal_rotation) 9419b6067c0SDmytro Laktyushkin swap(recout_skip_h, recout_skip_v); 942b2d0a103SDmytro Laktyushkin /* 943b2d0a103SDmytro Laktyushkin * Init calculated according to formula: 944b2d0a103SDmytro Laktyushkin * init = (scaling_ratio + number_of_taps + 1) / 2 945b2d0a103SDmytro Laktyushkin * init_bot = init + scaling_ratio 946b2d0a103SDmytro Laktyushkin * init_c = init + truncated_vp_c_offset(from calculate viewport) 947b2d0a103SDmytro Laktyushkin */ 9480002d3acSDmytro Laktyushkin data->inits.h = dc_fixpt_truncate(dc_fixpt_div_int( 9490002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.horz, data->taps.h_taps + 1), 2), 19); 950b2d0a103SDmytro Laktyushkin 9510002d3acSDmytro Laktyushkin data->inits.h_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.h_c, dc_fixpt_div_int( 9520002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.horz_c, data->taps.h_taps_c + 1), 2)), 19); 953b2d0a103SDmytro Laktyushkin 9540002d3acSDmytro Laktyushkin data->inits.v = dc_fixpt_truncate(dc_fixpt_div_int( 9550002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.vert, data->taps.v_taps + 1), 2), 19); 956b2d0a103SDmytro Laktyushkin 9570002d3acSDmytro Laktyushkin data->inits.v_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.v_c, dc_fixpt_div_int( 9580002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2)), 19); 9590002d3acSDmytro Laktyushkin 9609a08f51fSDmytro Laktyushkin /* 9619b6067c0SDmytro Laktyushkin * Taps, inits and scaling ratios are in recout space need to rotate 9629b6067c0SDmytro Laktyushkin * to viewport rotation before adjustment 9639a08f51fSDmytro Laktyushkin */ 9649b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 9659b6067c0SDmytro Laktyushkin flip_horz_scan_dir, 9669b6067c0SDmytro Laktyushkin recout_skip_h, 9679b6067c0SDmytro Laktyushkin surf_size_h, 9689b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.v_taps : data->taps.h_taps, 9699b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.vert : data->ratios.horz, 9709b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.v : &data->inits.h, 9719b6067c0SDmytro Laktyushkin &data->viewport.x, 9729b6067c0SDmytro Laktyushkin &data->viewport.width); 9739b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 9749b6067c0SDmytro Laktyushkin flip_horz_scan_dir, 9759b6067c0SDmytro Laktyushkin recout_skip_h, 9769b6067c0SDmytro Laktyushkin surf_size_h / vpc_div, 9779b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.v_taps_c : data->taps.h_taps_c, 9789b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.vert_c : data->ratios.horz_c, 9799b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.v_c : &data->inits.h_c, 9809b6067c0SDmytro Laktyushkin &data->viewport_c.x, 9819b6067c0SDmytro Laktyushkin &data->viewport_c.width); 9829b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 9839b6067c0SDmytro Laktyushkin flip_vert_scan_dir, 9849b6067c0SDmytro Laktyushkin recout_skip_v, 9859b6067c0SDmytro Laktyushkin surf_size_v, 9869b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.h_taps : data->taps.v_taps, 9879b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.horz : data->ratios.vert, 9889b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.h : &data->inits.v, 9899b6067c0SDmytro Laktyushkin &data->viewport.y, 9909b6067c0SDmytro Laktyushkin &data->viewport.height); 9919b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 9929b6067c0SDmytro Laktyushkin flip_vert_scan_dir, 9939b6067c0SDmytro Laktyushkin recout_skip_v, 9949b6067c0SDmytro Laktyushkin surf_size_v / vpc_div, 9959b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.h_taps_c : data->taps.v_taps_c, 9969b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.horz_c : data->ratios.vert_c, 9979b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.h_c : &data->inits.v_c, 9989b6067c0SDmytro Laktyushkin &data->viewport_c.y, 9999b6067c0SDmytro Laktyushkin &data->viewport_c.height); 1000b2d0a103SDmytro Laktyushkin 1001b2d0a103SDmytro Laktyushkin /* Interlaced inits based on final vert inits */ 1002eb0e5154SDmytro Laktyushkin data->inits.v_bot = dc_fixpt_add(data->inits.v, data->ratios.vert); 1003eb0e5154SDmytro Laktyushkin data->inits.v_c_bot = dc_fixpt_add(data->inits.v_c, data->ratios.vert_c); 10041fbd2cfcSDmytro Laktyushkin 1005b2d0a103SDmytro Laktyushkin } 10063b733278SReza Amini 100789d07b66SSamson Tam /* 100889d07b66SSamson Tam * When handling 270 rotation in mixed SLS mode, we have 100989d07b66SSamson Tam * stream->timing.h_border_left that is non zero. If we are doing 101089d07b66SSamson Tam * pipe-splitting, this h_border_left value gets added to recout.x and when it 101189d07b66SSamson Tam * calls calculate_inits_and_adj_vp() and 101289d07b66SSamson Tam * adjust_vp_and_init_for_seamless_clip(), it can cause viewport.height for a 101389d07b66SSamson Tam * pipe to be incorrect. 101489d07b66SSamson Tam * 101589d07b66SSamson Tam * To fix this, instead of using stream->timing.h_border_left, we can use 101689d07b66SSamson Tam * stream->dst.x to represent the border instead. So we will set h_border_left 101789d07b66SSamson Tam * to 0 and shift the appropriate amount in stream->dst.x. We will then 101889d07b66SSamson Tam * perform all calculations in resource_build_scaling_params() based on this 101989d07b66SSamson Tam * and then restore the h_border_left and stream->dst.x to their original 102089d07b66SSamson Tam * values. 102189d07b66SSamson Tam * 102289d07b66SSamson Tam * shift_border_left_to_dst() will shift the amount of h_border_left to 102389d07b66SSamson Tam * stream->dst.x and set h_border_left to 0. restore_border_left_from_dst() 102489d07b66SSamson Tam * will restore h_border_left and stream->dst.x back to their original values 102589d07b66SSamson Tam * We also need to make sure pipe_ctx->plane_res.scl_data.h_active uses the 102689d07b66SSamson Tam * original h_border_left value in its calculation. 102789d07b66SSamson Tam */ 102889d07b66SSamson Tam int shift_border_left_to_dst(struct pipe_ctx *pipe_ctx) 102989d07b66SSamson Tam { 103089d07b66SSamson Tam int store_h_border_left = pipe_ctx->stream->timing.h_border_left; 103189d07b66SSamson Tam 103289d07b66SSamson Tam if (store_h_border_left) { 103389d07b66SSamson Tam pipe_ctx->stream->timing.h_border_left = 0; 103489d07b66SSamson Tam pipe_ctx->stream->dst.x += store_h_border_left; 103589d07b66SSamson Tam } 103689d07b66SSamson Tam return store_h_border_left; 103789d07b66SSamson Tam } 103889d07b66SSamson Tam 103989d07b66SSamson Tam void restore_border_left_from_dst(struct pipe_ctx *pipe_ctx, 104089d07b66SSamson Tam int store_h_border_left) 104189d07b66SSamson Tam { 104289d07b66SSamson Tam pipe_ctx->stream->dst.x -= store_h_border_left; 104389d07b66SSamson Tam pipe_ctx->stream->timing.h_border_left = store_h_border_left; 104489d07b66SSamson Tam } 104589d07b66SSamson Tam 1046b2d0a103SDmytro Laktyushkin bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) 1047b2d0a103SDmytro Laktyushkin { 10483be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 10494fa086b9SLeo (Sunpeng) Li struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 1050b2d0a103SDmytro Laktyushkin bool res = false; 105189d07b66SSamson Tam int store_h_border_left = shift_border_left_to_dst(pipe_ctx); 10525d4b05ddSBhawanpreet Lakha DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); 10534562236bSHarry Wentland /* Important: scaling ratio calculation requires pixel format, 10544562236bSHarry Wentland * lb depth calculation requires recout and taps require scaling ratios. 1055b2d0a103SDmytro Laktyushkin * Inits require viewport, taps, ratios and recout of split pipe 10564562236bSHarry Wentland */ 10576702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface( 10583be5262eSHarry Wentland pipe_ctx->plane_state->format); 10594562236bSHarry Wentland 1060b2d0a103SDmytro Laktyushkin calculate_scaling_ratios(pipe_ctx); 1061b2d0a103SDmytro Laktyushkin 1062b2d0a103SDmytro Laktyushkin calculate_viewport(pipe_ctx); 10634562236bSHarry Wentland 106489d07b66SSamson Tam if (pipe_ctx->plane_res.scl_data.viewport.height < 16 || 106589d07b66SSamson Tam pipe_ctx->plane_res.scl_data.viewport.width < 16) { 106689d07b66SSamson Tam if (store_h_border_left) { 106789d07b66SSamson Tam restore_border_left_from_dst(pipe_ctx, 106889d07b66SSamson Tam store_h_border_left); 106989d07b66SSamson Tam } 10704562236bSHarry Wentland return false; 107189d07b66SSamson Tam } 10724562236bSHarry Wentland 10739b6067c0SDmytro Laktyushkin calculate_recout(pipe_ctx); 10744562236bSHarry Wentland 10754562236bSHarry Wentland /** 10764562236bSHarry Wentland * Setting line buffer pixel depth to 24bpp yields banding 10774562236bSHarry Wentland * on certain displays, such as the Sharp 4k 10784562236bSHarry Wentland */ 10796702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; 108033eef72fSEric Bernstein pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha; 10814562236bSHarry Wentland 1082199e458aSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left; 108358bb0e63SAndrew Jiang pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top; 1084199e458aSDmytro Laktyushkin 108589d07b66SSamson Tam pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable + 108689d07b66SSamson Tam store_h_border_left + timing->h_border_right; 108789d07b66SSamson Tam pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + 108889d07b66SSamson Tam timing->v_border_top + timing->v_border_bottom; 10895bf24270SDmytro Laktyushkin if (pipe_ctx->next_odm_pipe || pipe_ctx->prev_odm_pipe) 10905bf24270SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.h_active /= get_num_odm_splits(pipe_ctx) + 1; 10911b6c8067SBhawanpreet Lakha 10924562236bSHarry Wentland /* Taps calculations */ 1093d94585a0SYue Hin Lau if (pipe_ctx->plane_res.xfm != NULL) 109486a66c4eSHarry Wentland res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 109586a66c4eSHarry Wentland pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 10964562236bSHarry Wentland 1097d94585a0SYue Hin Lau if (pipe_ctx->plane_res.dpp != NULL) 1098d94585a0SYue Hin Lau res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 1099d94585a0SYue Hin Lau pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 1100f7938bc0SReza Amini 1101f7938bc0SReza Amini 11024562236bSHarry Wentland if (!res) { 11034562236bSHarry Wentland /* Try 24 bpp linebuffer */ 11046702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; 11054562236bSHarry Wentland 11061b6c8067SBhawanpreet Lakha if (pipe_ctx->plane_res.xfm != NULL) 110786a66c4eSHarry Wentland res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 11081b6c8067SBhawanpreet Lakha pipe_ctx->plane_res.xfm, 11091b6c8067SBhawanpreet Lakha &pipe_ctx->plane_res.scl_data, 11101b6c8067SBhawanpreet Lakha &plane_state->scaling_quality); 1111d94585a0SYue Hin Lau 11121b6c8067SBhawanpreet Lakha if (pipe_ctx->plane_res.dpp != NULL) 1113d94585a0SYue Hin Lau res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 11141b6c8067SBhawanpreet Lakha pipe_ctx->plane_res.dpp, 11151b6c8067SBhawanpreet Lakha &pipe_ctx->plane_res.scl_data, 11161b6c8067SBhawanpreet Lakha &plane_state->scaling_quality); 11174562236bSHarry Wentland } 11184562236bSHarry Wentland 1119b2d0a103SDmytro Laktyushkin if (res) 11201fbd2cfcSDmytro Laktyushkin /* May need to re-check lb size after this in some obscure scenario */ 11219b6067c0SDmytro Laktyushkin calculate_inits_and_adj_vp(pipe_ctx); 1122b2d0a103SDmytro Laktyushkin 11231296423bSBhawanpreet Lakha DC_LOG_SCALER( 11244562236bSHarry Wentland "%s: Viewport:\nheight:%d width:%d x:%d " 11254562236bSHarry Wentland "y:%d\n dst_rect:\nheight:%d width:%d x:%d " 11264562236bSHarry Wentland "y:%d\n", 11274562236bSHarry Wentland __func__, 11286702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.height, 11296702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.width, 11306702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.x, 11316702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.y, 11323be5262eSHarry Wentland plane_state->dst_rect.height, 11333be5262eSHarry Wentland plane_state->dst_rect.width, 11343be5262eSHarry Wentland plane_state->dst_rect.x, 11353be5262eSHarry Wentland plane_state->dst_rect.y); 11364562236bSHarry Wentland 113789d07b66SSamson Tam if (store_h_border_left) 113889d07b66SSamson Tam restore_border_left_from_dst(pipe_ctx, store_h_border_left); 113989d07b66SSamson Tam 11404562236bSHarry Wentland return res; 11414562236bSHarry Wentland } 11424562236bSHarry Wentland 11434562236bSHarry Wentland 11444562236bSHarry Wentland enum dc_status resource_build_scaling_params_for_context( 1145fb3466a4SBhawanpreet Lakha const struct dc *dc, 1146608ac7bbSJerry Zuo struct dc_state *context) 11474562236bSHarry Wentland { 11484562236bSHarry Wentland int i; 11494562236bSHarry Wentland 11504562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 11513be5262eSHarry Wentland if (context->res_ctx.pipe_ctx[i].plane_state != NULL && 11524562236bSHarry Wentland context->res_ctx.pipe_ctx[i].stream != NULL) 1153b2d0a103SDmytro Laktyushkin if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i])) 1154f84a8161STony Cheng return DC_FAIL_SCALING; 11554562236bSHarry Wentland } 11564562236bSHarry Wentland 11574562236bSHarry Wentland return DC_OK; 11584562236bSHarry Wentland } 11594562236bSHarry Wentland 1160a2b8659dSTony Cheng struct pipe_ctx *find_idle_secondary_pipe( 1161a2b8659dSTony Cheng struct resource_context *res_ctx, 11625581192dSJun Lei const struct resource_pool *pool, 11635581192dSJun Lei const struct pipe_ctx *primary_pipe) 11644562236bSHarry Wentland { 11654562236bSHarry Wentland int i; 11664562236bSHarry Wentland struct pipe_ctx *secondary_pipe = NULL; 11674562236bSHarry Wentland 11684562236bSHarry Wentland /* 11695581192dSJun Lei * We add a preferred pipe mapping to avoid the chance that 11705581192dSJun Lei * MPCCs already in use will need to be reassigned to other trees. 11715581192dSJun Lei * For example, if we went with the strict, assign backwards logic: 11725581192dSJun Lei * 11735581192dSJun Lei * (State 1) 11745581192dSJun Lei * Display A on, no surface, top pipe = 0 11755581192dSJun Lei * Display B on, no surface, top pipe = 1 11765581192dSJun Lei * 11775581192dSJun Lei * (State 2) 11785581192dSJun Lei * Display A on, no surface, top pipe = 0 11795581192dSJun Lei * Display B on, surface enable, top pipe = 1, bottom pipe = 5 11805581192dSJun Lei * 11815581192dSJun Lei * (State 3) 11825581192dSJun Lei * Display A on, surface enable, top pipe = 0, bottom pipe = 5 11835581192dSJun Lei * Display B on, surface enable, top pipe = 1, bottom pipe = 4 11845581192dSJun Lei * 11855581192dSJun Lei * The state 2->3 transition requires remapping MPCC 5 from display B 11865581192dSJun Lei * to display A. 11875581192dSJun Lei * 11885581192dSJun Lei * However, with the preferred pipe logic, state 2 would look like: 11895581192dSJun Lei * 11905581192dSJun Lei * (State 2) 11915581192dSJun Lei * Display A on, no surface, top pipe = 0 11925581192dSJun Lei * Display B on, surface enable, top pipe = 1, bottom pipe = 4 11935581192dSJun Lei * 11945581192dSJun Lei * This would then cause 2->3 to not require remapping any MPCCs. 11955581192dSJun Lei */ 11965581192dSJun Lei if (primary_pipe) { 11975581192dSJun Lei int preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx; 11985581192dSJun Lei if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) { 11995581192dSJun Lei secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx]; 12005581192dSJun Lei secondary_pipe->pipe_idx = preferred_pipe_idx; 12015581192dSJun Lei } 12025581192dSJun Lei } 12035581192dSJun Lei 12045581192dSJun Lei /* 12054562236bSHarry Wentland * search backwards for the second pipe to keep pipe 12064562236bSHarry Wentland * assignment more consistent 12074562236bSHarry Wentland */ 12085581192dSJun Lei if (!secondary_pipe) 1209a2b8659dSTony Cheng for (i = pool->pipe_count - 1; i >= 0; i--) { 12104562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == NULL) { 12114562236bSHarry Wentland secondary_pipe = &res_ctx->pipe_ctx[i]; 12124562236bSHarry Wentland secondary_pipe->pipe_idx = i; 12134562236bSHarry Wentland break; 12144562236bSHarry Wentland } 12154562236bSHarry Wentland } 12164562236bSHarry Wentland 12174562236bSHarry Wentland return secondary_pipe; 12184562236bSHarry Wentland } 12194562236bSHarry Wentland 12204562236bSHarry Wentland struct pipe_ctx *resource_get_head_pipe_for_stream( 12214562236bSHarry Wentland struct resource_context *res_ctx, 12220971c40eSHarry Wentland struct dc_stream_state *stream) 12234562236bSHarry Wentland { 12244562236bSHarry Wentland int i; 122522498036SDmytro Laktyushkin 1226a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 1227b1f6d01cSDmytro Laktyushkin if (res_ctx->pipe_ctx[i].stream == stream 1228b1f6d01cSDmytro Laktyushkin && !res_ctx->pipe_ctx[i].top_pipe 122922498036SDmytro Laktyushkin && !res_ctx->pipe_ctx[i].prev_odm_pipe) 12304562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 12314562236bSHarry Wentland } 12324562236bSHarry Wentland return NULL; 12334562236bSHarry Wentland } 12344562236bSHarry Wentland 1235b1f6d01cSDmytro Laktyushkin static struct pipe_ctx *resource_get_tail_pipe( 123619f89e23SAndrey Grodzovsky struct resource_context *res_ctx, 1237b1f6d01cSDmytro Laktyushkin struct pipe_ctx *head_pipe) 123819f89e23SAndrey Grodzovsky { 1239b1f6d01cSDmytro Laktyushkin struct pipe_ctx *tail_pipe; 124019f89e23SAndrey Grodzovsky 124119f89e23SAndrey Grodzovsky tail_pipe = head_pipe->bottom_pipe; 124219f89e23SAndrey Grodzovsky 124319f89e23SAndrey Grodzovsky while (tail_pipe) { 124419f89e23SAndrey Grodzovsky head_pipe = tail_pipe; 124519f89e23SAndrey Grodzovsky tail_pipe = tail_pipe->bottom_pipe; 124619f89e23SAndrey Grodzovsky } 124719f89e23SAndrey Grodzovsky 124819f89e23SAndrey Grodzovsky return head_pipe; 124919f89e23SAndrey Grodzovsky } 125019f89e23SAndrey Grodzovsky 12514562236bSHarry Wentland /* 1252ab2541b6SAric Cyr * A free_pipe for a stream is defined here as a pipe 1253ab2541b6SAric Cyr * that has no surface attached yet 12544562236bSHarry Wentland */ 1255b1f6d01cSDmytro Laktyushkin static struct pipe_ctx *acquire_free_pipe_for_head( 1256608ac7bbSJerry Zuo struct dc_state *context, 1257a2b8659dSTony Cheng const struct resource_pool *pool, 1258b1f6d01cSDmytro Laktyushkin struct pipe_ctx *head_pipe) 12594562236bSHarry Wentland { 12604562236bSHarry Wentland int i; 1261745cc746SDmytro Laktyushkin struct resource_context *res_ctx = &context->res_ctx; 12624562236bSHarry Wentland 12633be5262eSHarry Wentland if (!head_pipe->plane_state) 12644562236bSHarry Wentland return head_pipe; 12654562236bSHarry Wentland 12664562236bSHarry Wentland /* Re-use pipe already acquired for this stream if available*/ 1267a2b8659dSTony Cheng for (i = pool->pipe_count - 1; i >= 0; i--) { 1268b1f6d01cSDmytro Laktyushkin if (res_ctx->pipe_ctx[i].stream == head_pipe->stream && 12693be5262eSHarry Wentland !res_ctx->pipe_ctx[i].plane_state) { 12704562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 12714562236bSHarry Wentland } 12724562236bSHarry Wentland } 12734562236bSHarry Wentland 12744562236bSHarry Wentland /* 12754562236bSHarry Wentland * At this point we have no re-useable pipe for this stream and we need 12764562236bSHarry Wentland * to acquire an idle one to satisfy the request 12774562236bSHarry Wentland */ 12784562236bSHarry Wentland 1279a2b8659dSTony Cheng if (!pool->funcs->acquire_idle_pipe_for_layer) 12804562236bSHarry Wentland return NULL; 12814562236bSHarry Wentland 1282b1f6d01cSDmytro Laktyushkin return pool->funcs->acquire_idle_pipe_for_layer(context, pool, head_pipe->stream); 12834562236bSHarry Wentland } 12844562236bSHarry Wentland 1285b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 12860f9a536fSDmytro Laktyushkin static int acquire_first_split_pipe( 12870f9a536fSDmytro Laktyushkin struct resource_context *res_ctx, 12880f9a536fSDmytro Laktyushkin const struct resource_pool *pool, 12890971c40eSHarry Wentland struct dc_stream_state *stream) 12900f9a536fSDmytro Laktyushkin { 12910f9a536fSDmytro Laktyushkin int i; 12920f9a536fSDmytro Laktyushkin 12930f9a536fSDmytro Laktyushkin for (i = 0; i < pool->pipe_count; i++) { 129479592db3SDmytro Laktyushkin struct pipe_ctx *split_pipe = &res_ctx->pipe_ctx[i]; 12950f9a536fSDmytro Laktyushkin 1296b1f6d01cSDmytro Laktyushkin if (split_pipe->top_pipe && 129779592db3SDmytro Laktyushkin split_pipe->top_pipe->plane_state == split_pipe->plane_state) { 129879592db3SDmytro Laktyushkin split_pipe->top_pipe->bottom_pipe = split_pipe->bottom_pipe; 129979592db3SDmytro Laktyushkin if (split_pipe->bottom_pipe) 130079592db3SDmytro Laktyushkin split_pipe->bottom_pipe->top_pipe = split_pipe->top_pipe; 13010f9a536fSDmytro Laktyushkin 130279592db3SDmytro Laktyushkin if (split_pipe->top_pipe->plane_state) 130379592db3SDmytro Laktyushkin resource_build_scaling_params(split_pipe->top_pipe); 13040f9a536fSDmytro Laktyushkin 130579592db3SDmytro Laktyushkin memset(split_pipe, 0, sizeof(*split_pipe)); 130679592db3SDmytro Laktyushkin split_pipe->stream_res.tg = pool->timing_generators[i]; 130779592db3SDmytro Laktyushkin split_pipe->plane_res.hubp = pool->hubps[i]; 130879592db3SDmytro Laktyushkin split_pipe->plane_res.ipp = pool->ipps[i]; 130979592db3SDmytro Laktyushkin split_pipe->plane_res.dpp = pool->dpps[i]; 131079592db3SDmytro Laktyushkin split_pipe->stream_res.opp = pool->opps[i]; 131179592db3SDmytro Laktyushkin split_pipe->plane_res.mpcc_inst = pool->dpps[i]->inst; 131279592db3SDmytro Laktyushkin split_pipe->pipe_idx = i; 131379592db3SDmytro Laktyushkin 131479592db3SDmytro Laktyushkin split_pipe->stream = stream; 13150f9a536fSDmytro Laktyushkin return i; 13160f9a536fSDmytro Laktyushkin } 13170f9a536fSDmytro Laktyushkin } 13180f9a536fSDmytro Laktyushkin return -1; 13190f9a536fSDmytro Laktyushkin } 13200f9a536fSDmytro Laktyushkin #endif 13210f9a536fSDmytro Laktyushkin 132219f89e23SAndrey Grodzovsky bool dc_add_plane_to_context( 132319f89e23SAndrey Grodzovsky const struct dc *dc, 13240971c40eSHarry Wentland struct dc_stream_state *stream, 132519f89e23SAndrey Grodzovsky struct dc_plane_state *plane_state, 1326608ac7bbSJerry Zuo struct dc_state *context) 13274562236bSHarry Wentland { 13284562236bSHarry Wentland int i; 132919f89e23SAndrey Grodzovsky struct resource_pool *pool = dc->res_pool; 133019f89e23SAndrey Grodzovsky struct pipe_ctx *head_pipe, *tail_pipe, *free_pipe; 1331ab2541b6SAric Cyr struct dc_stream_status *stream_status = NULL; 13324562236bSHarry Wentland 1333ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) 13344fa086b9SLeo (Sunpeng) Li if (context->streams[i] == stream) { 1335ab2541b6SAric Cyr stream_status = &context->stream_status[i]; 13364562236bSHarry Wentland break; 13374562236bSHarry Wentland } 1338ab2541b6SAric Cyr if (stream_status == NULL) { 133919f89e23SAndrey Grodzovsky dm_error("Existing stream not found; failed to attach surface!\n"); 134019f89e23SAndrey Grodzovsky return false; 134119f89e23SAndrey Grodzovsky } 134219f89e23SAndrey Grodzovsky 134319f89e23SAndrey Grodzovsky 134419f89e23SAndrey Grodzovsky if (stream_status->plane_count == MAX_SURFACE_NUM) { 134519f89e23SAndrey Grodzovsky dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n", 134619f89e23SAndrey Grodzovsky plane_state, MAX_SURFACE_NUM); 134719f89e23SAndrey Grodzovsky return false; 134819f89e23SAndrey Grodzovsky } 134919f89e23SAndrey Grodzovsky 135019f89e23SAndrey Grodzovsky head_pipe = resource_get_head_pipe_for_stream(&context->res_ctx, stream); 135119f89e23SAndrey Grodzovsky 135219f89e23SAndrey Grodzovsky if (!head_pipe) { 135319f89e23SAndrey Grodzovsky dm_error("Head pipe not found for stream_state %p !\n", stream); 13544562236bSHarry Wentland return false; 13554562236bSHarry Wentland } 13564562236bSHarry Wentland 1357b1f6d01cSDmytro Laktyushkin /* retain new surface, but only once per stream */ 1358b1f6d01cSDmytro Laktyushkin dc_plane_state_retain(plane_state); 1359b1f6d01cSDmytro Laktyushkin 1360b1f6d01cSDmytro Laktyushkin while (head_pipe) { 1361b1f6d01cSDmytro Laktyushkin free_pipe = acquire_free_pipe_for_head(context, pool, head_pipe); 13624562236bSHarry Wentland 1363b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 13640f9a536fSDmytro Laktyushkin if (!free_pipe) { 13650f9a536fSDmytro Laktyushkin int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 13660f9a536fSDmytro Laktyushkin if (pipe_idx >= 0) 13670f9a536fSDmytro Laktyushkin free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; 13680f9a536fSDmytro Laktyushkin } 13690f9a536fSDmytro Laktyushkin #endif 1370b1f6d01cSDmytro Laktyushkin if (!free_pipe) { 1371b1f6d01cSDmytro Laktyushkin dc_plane_state_release(plane_state); 13724562236bSHarry Wentland return false; 1373b1f6d01cSDmytro Laktyushkin } 13744562236bSHarry Wentland 13753be5262eSHarry Wentland free_pipe->plane_state = plane_state; 13764562236bSHarry Wentland 137719f89e23SAndrey Grodzovsky if (head_pipe != free_pipe) { 13785b5c1777SJosip Pavic tail_pipe = resource_get_tail_pipe(&context->res_ctx, head_pipe); 13795b5c1777SJosip Pavic ASSERT(tail_pipe); 13806b670fa9SHarry Wentland free_pipe->stream_res.tg = tail_pipe->stream_res.tg; 13819aef1a31SSivapiriyanKumarasamy free_pipe->stream_res.abm = tail_pipe->stream_res.abm; 1382a6a6cb34SHarry Wentland free_pipe->stream_res.opp = tail_pipe->stream_res.opp; 13838e9c4c8cSHarry Wentland free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; 1384afaacef4SHarry Wentland free_pipe->stream_res.audio = tail_pipe->stream_res.audio; 1385cfe4645eSDmytro Laktyushkin free_pipe->clock_source = tail_pipe->clock_source; 13864562236bSHarry Wentland free_pipe->top_pipe = tail_pipe; 13874562236bSHarry Wentland tail_pipe->bottom_pipe = free_pipe; 13884562236bSHarry Wentland } 1389b1f6d01cSDmytro Laktyushkin head_pipe = head_pipe->next_odm_pipe; 1390b1f6d01cSDmytro Laktyushkin } 13914562236bSHarry Wentland /* assign new surfaces*/ 139219f89e23SAndrey Grodzovsky stream_status->plane_states[stream_status->plane_count] = plane_state; 13934562236bSHarry Wentland 139419f89e23SAndrey Grodzovsky stream_status->plane_count++; 13954562236bSHarry Wentland 13964562236bSHarry Wentland return true; 13974562236bSHarry Wentland } 13984562236bSHarry Wentland 139919f89e23SAndrey Grodzovsky bool dc_remove_plane_from_context( 140019f89e23SAndrey Grodzovsky const struct dc *dc, 140119f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 140219f89e23SAndrey Grodzovsky struct dc_plane_state *plane_state, 1403608ac7bbSJerry Zuo struct dc_state *context) 140419f89e23SAndrey Grodzovsky { 140519f89e23SAndrey Grodzovsky int i; 140619f89e23SAndrey Grodzovsky struct dc_stream_status *stream_status = NULL; 140719f89e23SAndrey Grodzovsky struct resource_pool *pool = dc->res_pool; 140819f89e23SAndrey Grodzovsky 140919f89e23SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 141019f89e23SAndrey Grodzovsky if (context->streams[i] == stream) { 141119f89e23SAndrey Grodzovsky stream_status = &context->stream_status[i]; 141219f89e23SAndrey Grodzovsky break; 141319f89e23SAndrey Grodzovsky } 141419f89e23SAndrey Grodzovsky 141519f89e23SAndrey Grodzovsky if (stream_status == NULL) { 141619f89e23SAndrey Grodzovsky dm_error("Existing stream not found; failed to remove plane.\n"); 141719f89e23SAndrey Grodzovsky return false; 141819f89e23SAndrey Grodzovsky } 141919f89e23SAndrey Grodzovsky 142019f89e23SAndrey Grodzovsky /* release pipe for plane*/ 142119f89e23SAndrey Grodzovsky for (i = pool->pipe_count - 1; i >= 0; i--) { 14226ffaa6fcSDmytro Laktyushkin struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 142319f89e23SAndrey Grodzovsky 14246ffaa6fcSDmytro Laktyushkin if (pipe_ctx->plane_state == plane_state) { 142519f89e23SAndrey Grodzovsky if (pipe_ctx->top_pipe) 142619f89e23SAndrey Grodzovsky pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; 142719f89e23SAndrey Grodzovsky 142819f89e23SAndrey Grodzovsky /* Second condition is to avoid setting NULL to top pipe 142919f89e23SAndrey Grodzovsky * of tail pipe making it look like head pipe in subsequent 143019f89e23SAndrey Grodzovsky * deletes 143119f89e23SAndrey Grodzovsky */ 143219f89e23SAndrey Grodzovsky if (pipe_ctx->bottom_pipe && pipe_ctx->top_pipe) 143319f89e23SAndrey Grodzovsky pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; 143419f89e23SAndrey Grodzovsky 143519f89e23SAndrey Grodzovsky /* 143619f89e23SAndrey Grodzovsky * For head pipe detach surfaces from pipe for tail 143719f89e23SAndrey Grodzovsky * pipe just zero it out 143819f89e23SAndrey Grodzovsky */ 1439b1f6d01cSDmytro Laktyushkin if (!pipe_ctx->top_pipe) 144019f89e23SAndrey Grodzovsky pipe_ctx->plane_state = NULL; 1441b1f6d01cSDmytro Laktyushkin else 144219f89e23SAndrey Grodzovsky memset(pipe_ctx, 0, sizeof(*pipe_ctx)); 144319f89e23SAndrey Grodzovsky } 144419f89e23SAndrey Grodzovsky } 144519f89e23SAndrey Grodzovsky 144619f89e23SAndrey Grodzovsky 144719f89e23SAndrey Grodzovsky for (i = 0; i < stream_status->plane_count; i++) { 144819f89e23SAndrey Grodzovsky if (stream_status->plane_states[i] == plane_state) { 144919f89e23SAndrey Grodzovsky 145019f89e23SAndrey Grodzovsky dc_plane_state_release(stream_status->plane_states[i]); 145119f89e23SAndrey Grodzovsky break; 145219f89e23SAndrey Grodzovsky } 145319f89e23SAndrey Grodzovsky } 145419f89e23SAndrey Grodzovsky 145519f89e23SAndrey Grodzovsky if (i == stream_status->plane_count) { 145619f89e23SAndrey Grodzovsky dm_error("Existing plane_state not found; failed to detach it!\n"); 145719f89e23SAndrey Grodzovsky return false; 145819f89e23SAndrey Grodzovsky } 145919f89e23SAndrey Grodzovsky 146019f89e23SAndrey Grodzovsky stream_status->plane_count--; 146119f89e23SAndrey Grodzovsky 1462abb4986eSAndrew Jiang /* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */ 1463abb4986eSAndrew Jiang for (; i < stream_status->plane_count; i++) 146419f89e23SAndrey Grodzovsky stream_status->plane_states[i] = stream_status->plane_states[i + 1]; 146519f89e23SAndrey Grodzovsky 146619f89e23SAndrey Grodzovsky stream_status->plane_states[stream_status->plane_count] = NULL; 146719f89e23SAndrey Grodzovsky 146819f89e23SAndrey Grodzovsky return true; 146919f89e23SAndrey Grodzovsky } 147019f89e23SAndrey Grodzovsky 147119f89e23SAndrey Grodzovsky bool dc_rem_all_planes_for_stream( 147219f89e23SAndrey Grodzovsky const struct dc *dc, 147319f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 1474608ac7bbSJerry Zuo struct dc_state *context) 147519f89e23SAndrey Grodzovsky { 147619f89e23SAndrey Grodzovsky int i, old_plane_count; 147719f89e23SAndrey Grodzovsky struct dc_stream_status *stream_status = NULL; 147819f89e23SAndrey Grodzovsky struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 }; 147919f89e23SAndrey Grodzovsky 148019f89e23SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 148119f89e23SAndrey Grodzovsky if (context->streams[i] == stream) { 148219f89e23SAndrey Grodzovsky stream_status = &context->stream_status[i]; 148319f89e23SAndrey Grodzovsky break; 148419f89e23SAndrey Grodzovsky } 148519f89e23SAndrey Grodzovsky 148619f89e23SAndrey Grodzovsky if (stream_status == NULL) { 148719f89e23SAndrey Grodzovsky dm_error("Existing stream %p not found!\n", stream); 148819f89e23SAndrey Grodzovsky return false; 148919f89e23SAndrey Grodzovsky } 149019f89e23SAndrey Grodzovsky 149119f89e23SAndrey Grodzovsky old_plane_count = stream_status->plane_count; 149219f89e23SAndrey Grodzovsky 149319f89e23SAndrey Grodzovsky for (i = 0; i < old_plane_count; i++) 149419f89e23SAndrey Grodzovsky del_planes[i] = stream_status->plane_states[i]; 149519f89e23SAndrey Grodzovsky 149619f89e23SAndrey Grodzovsky for (i = 0; i < old_plane_count; i++) 149719f89e23SAndrey Grodzovsky if (!dc_remove_plane_from_context(dc, stream, del_planes[i], context)) 149819f89e23SAndrey Grodzovsky return false; 149919f89e23SAndrey Grodzovsky 150019f89e23SAndrey Grodzovsky return true; 150119f89e23SAndrey Grodzovsky } 150219f89e23SAndrey Grodzovsky 150319f89e23SAndrey Grodzovsky static bool add_all_planes_for_stream( 150419f89e23SAndrey Grodzovsky const struct dc *dc, 150519f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 150619f89e23SAndrey Grodzovsky const struct dc_validation_set set[], 150719f89e23SAndrey Grodzovsky int set_count, 1508608ac7bbSJerry Zuo struct dc_state *context) 150919f89e23SAndrey Grodzovsky { 151019f89e23SAndrey Grodzovsky int i, j; 151119f89e23SAndrey Grodzovsky 151219f89e23SAndrey Grodzovsky for (i = 0; i < set_count; i++) 151319f89e23SAndrey Grodzovsky if (set[i].stream == stream) 151419f89e23SAndrey Grodzovsky break; 151519f89e23SAndrey Grodzovsky 151619f89e23SAndrey Grodzovsky if (i == set_count) { 151719f89e23SAndrey Grodzovsky dm_error("Stream %p not found in set!\n", stream); 151819f89e23SAndrey Grodzovsky return false; 151919f89e23SAndrey Grodzovsky } 152019f89e23SAndrey Grodzovsky 152119f89e23SAndrey Grodzovsky for (j = 0; j < set[i].plane_count; j++) 152219f89e23SAndrey Grodzovsky if (!dc_add_plane_to_context(dc, stream, set[i].plane_states[j], context)) 152319f89e23SAndrey Grodzovsky return false; 152419f89e23SAndrey Grodzovsky 152519f89e23SAndrey Grodzovsky return true; 152619f89e23SAndrey Grodzovsky } 152719f89e23SAndrey Grodzovsky 152819f89e23SAndrey Grodzovsky bool dc_add_all_planes_for_stream( 152919f89e23SAndrey Grodzovsky const struct dc *dc, 153019f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 153119f89e23SAndrey Grodzovsky struct dc_plane_state * const *plane_states, 153219f89e23SAndrey Grodzovsky int plane_count, 1533608ac7bbSJerry Zuo struct dc_state *context) 153419f89e23SAndrey Grodzovsky { 153519f89e23SAndrey Grodzovsky struct dc_validation_set set; 153619f89e23SAndrey Grodzovsky int i; 153719f89e23SAndrey Grodzovsky 153819f89e23SAndrey Grodzovsky set.stream = stream; 153919f89e23SAndrey Grodzovsky set.plane_count = plane_count; 154019f89e23SAndrey Grodzovsky 154119f89e23SAndrey Grodzovsky for (i = 0; i < plane_count; i++) 154219f89e23SAndrey Grodzovsky set.plane_states[i] = plane_states[i]; 154319f89e23SAndrey Grodzovsky 154419f89e23SAndrey Grodzovsky return add_all_planes_for_stream(dc, stream, &set, 1, context); 154519f89e23SAndrey Grodzovsky } 154619f89e23SAndrey Grodzovsky 154719f89e23SAndrey Grodzovsky 15486b622181SJulian Parkin static bool is_hdr_static_meta_changed(struct dc_stream_state *cur_stream, 15496b622181SJulian Parkin struct dc_stream_state *new_stream) 15506b622181SJulian Parkin { 15516b622181SJulian Parkin if (cur_stream == NULL) 15526b622181SJulian Parkin return true; 15536b622181SJulian Parkin 15546b622181SJulian Parkin if (memcmp(&cur_stream->hdr_static_metadata, 15556b622181SJulian Parkin &new_stream->hdr_static_metadata, 15566b622181SJulian Parkin sizeof(struct dc_info_packet)) != 0) 15576b622181SJulian Parkin return true; 15586b622181SJulian Parkin 15596b622181SJulian Parkin return false; 15606b622181SJulian Parkin } 15614562236bSHarry Wentland 15621336926fSAlvin lee static bool is_vsc_info_packet_changed(struct dc_stream_state *cur_stream, 15631336926fSAlvin lee struct dc_stream_state *new_stream) 15641336926fSAlvin lee { 15651336926fSAlvin lee if (cur_stream == NULL) 15661336926fSAlvin lee return true; 15671336926fSAlvin lee 15681336926fSAlvin lee if (memcmp(&cur_stream->vsc_infopacket, 15691336926fSAlvin lee &new_stream->vsc_infopacket, 15701336926fSAlvin lee sizeof(struct dc_info_packet)) != 0) 15711336926fSAlvin lee return true; 15721336926fSAlvin lee 15731336926fSAlvin lee return false; 15741336926fSAlvin lee } 15751336926fSAlvin lee 15760971c40eSHarry Wentland static bool is_timing_changed(struct dc_stream_state *cur_stream, 15770971c40eSHarry Wentland struct dc_stream_state *new_stream) 15784562236bSHarry Wentland { 15794562236bSHarry Wentland if (cur_stream == NULL) 15804562236bSHarry Wentland return true; 15814562236bSHarry Wentland 15824562236bSHarry Wentland /* If sink pointer changed, it means this is a hotplug, we should do 15834562236bSHarry Wentland * full hw setting. 15844562236bSHarry Wentland */ 15854562236bSHarry Wentland if (cur_stream->sink != new_stream->sink) 15864562236bSHarry Wentland return true; 15874562236bSHarry Wentland 15884562236bSHarry Wentland /* If output color space is changed, need to reprogram info frames */ 15894fa086b9SLeo (Sunpeng) Li if (cur_stream->output_color_space != new_stream->output_color_space) 15904562236bSHarry Wentland return true; 15914562236bSHarry Wentland 15924562236bSHarry Wentland return memcmp( 15934fa086b9SLeo (Sunpeng) Li &cur_stream->timing, 15944fa086b9SLeo (Sunpeng) Li &new_stream->timing, 15954562236bSHarry Wentland sizeof(struct dc_crtc_timing)) != 0; 15964562236bSHarry Wentland } 15974562236bSHarry Wentland 15984562236bSHarry Wentland static bool are_stream_backends_same( 15990971c40eSHarry Wentland struct dc_stream_state *stream_a, struct dc_stream_state *stream_b) 16004562236bSHarry Wentland { 16014562236bSHarry Wentland if (stream_a == stream_b) 16024562236bSHarry Wentland return true; 16034562236bSHarry Wentland 16044562236bSHarry Wentland if (stream_a == NULL || stream_b == NULL) 16054562236bSHarry Wentland return false; 16064562236bSHarry Wentland 16074562236bSHarry Wentland if (is_timing_changed(stream_a, stream_b)) 16084562236bSHarry Wentland return false; 16094562236bSHarry Wentland 16106b622181SJulian Parkin if (is_hdr_static_meta_changed(stream_a, stream_b)) 16116b622181SJulian Parkin return false; 16126b622181SJulian Parkin 16131e7e86c4SSamson Tam if (stream_a->dpms_off != stream_b->dpms_off) 16141e7e86c4SSamson Tam return false; 16151e7e86c4SSamson Tam 16161336926fSAlvin lee if (is_vsc_info_packet_changed(stream_a, stream_b)) 16171336926fSAlvin lee return false; 16181336926fSAlvin lee 16194562236bSHarry Wentland return true; 16204562236bSHarry Wentland } 16214562236bSHarry Wentland 16222119aa17SDavid Francis /** 16232119aa17SDavid Francis * dc_is_stream_unchanged() - Compare two stream states for equivalence. 16242119aa17SDavid Francis * 16252119aa17SDavid Francis * Checks if there a difference between the two states 16262119aa17SDavid Francis * that would require a mode change. 16272119aa17SDavid Francis * 16282119aa17SDavid Francis * Does not compare cursor position or attributes. 16292119aa17SDavid Francis */ 1630d54d29dbSBhawanpreet Lakha bool dc_is_stream_unchanged( 16310971c40eSHarry Wentland struct dc_stream_state *old_stream, struct dc_stream_state *stream) 16324562236bSHarry Wentland { 16334562236bSHarry Wentland 16344562236bSHarry Wentland if (!are_stream_backends_same(old_stream, stream)) 16354562236bSHarry Wentland return false; 16364562236bSHarry Wentland 16370460f9abSJun Lei if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param) 16380460f9abSJun Lei return false; 16390460f9abSJun Lei 16404562236bSHarry Wentland return true; 16414562236bSHarry Wentland } 16424562236bSHarry Wentland 16432119aa17SDavid Francis /** 16442119aa17SDavid Francis * dc_is_stream_scaling_unchanged() - Compare scaling rectangles of two streams. 16452119aa17SDavid Francis */ 16469a5d9c48SLeo (Sunpeng) Li bool dc_is_stream_scaling_unchanged( 16479a5d9c48SLeo (Sunpeng) Li struct dc_stream_state *old_stream, struct dc_stream_state *stream) 16489a5d9c48SLeo (Sunpeng) Li { 16499a5d9c48SLeo (Sunpeng) Li if (old_stream == stream) 16509a5d9c48SLeo (Sunpeng) Li return true; 16519a5d9c48SLeo (Sunpeng) Li 16529a5d9c48SLeo (Sunpeng) Li if (old_stream == NULL || stream == NULL) 16539a5d9c48SLeo (Sunpeng) Li return false; 16549a5d9c48SLeo (Sunpeng) Li 16559a5d9c48SLeo (Sunpeng) Li if (memcmp(&old_stream->src, 16569a5d9c48SLeo (Sunpeng) Li &stream->src, 16579a5d9c48SLeo (Sunpeng) Li sizeof(struct rect)) != 0) 16589a5d9c48SLeo (Sunpeng) Li return false; 16599a5d9c48SLeo (Sunpeng) Li 16609a5d9c48SLeo (Sunpeng) Li if (memcmp(&old_stream->dst, 16619a5d9c48SLeo (Sunpeng) Li &stream->dst, 16629a5d9c48SLeo (Sunpeng) Li sizeof(struct rect)) != 0) 16639a5d9c48SLeo (Sunpeng) Li return false; 16649a5d9c48SLeo (Sunpeng) Li 16659a5d9c48SLeo (Sunpeng) Li return true; 16669a5d9c48SLeo (Sunpeng) Li } 16679a5d9c48SLeo (Sunpeng) Li 16681dc90497SAndrey Grodzovsky static void update_stream_engine_usage( 16694562236bSHarry Wentland struct resource_context *res_ctx, 1670a2b8659dSTony Cheng const struct resource_pool *pool, 16711dc90497SAndrey Grodzovsky struct stream_encoder *stream_enc, 16721dc90497SAndrey Grodzovsky bool acquired) 16734562236bSHarry Wentland { 16744562236bSHarry Wentland int i; 16754562236bSHarry Wentland 1676a2b8659dSTony Cheng for (i = 0; i < pool->stream_enc_count; i++) { 1677a2b8659dSTony Cheng if (pool->stream_enc[i] == stream_enc) 16781dc90497SAndrey Grodzovsky res_ctx->is_stream_enc_acquired[i] = acquired; 16794562236bSHarry Wentland } 16804562236bSHarry Wentland } 16814562236bSHarry Wentland 16824562236bSHarry Wentland /* TODO: release audio object */ 16834176664bSCharlene Liu void update_audio_usage( 16844562236bSHarry Wentland struct resource_context *res_ctx, 1685a2b8659dSTony Cheng const struct resource_pool *pool, 16861dc90497SAndrey Grodzovsky struct audio *audio, 16871dc90497SAndrey Grodzovsky bool acquired) 16884562236bSHarry Wentland { 16894562236bSHarry Wentland int i; 1690a2b8659dSTony Cheng for (i = 0; i < pool->audio_count; i++) { 1691a2b8659dSTony Cheng if (pool->audios[i] == audio) 16921dc90497SAndrey Grodzovsky res_ctx->is_audio_acquired[i] = acquired; 16934562236bSHarry Wentland } 16944562236bSHarry Wentland } 16954562236bSHarry Wentland 16964562236bSHarry Wentland static int acquire_first_free_pipe( 16974562236bSHarry Wentland struct resource_context *res_ctx, 1698a2b8659dSTony Cheng const struct resource_pool *pool, 16990971c40eSHarry Wentland struct dc_stream_state *stream) 17004562236bSHarry Wentland { 17014562236bSHarry Wentland int i; 17024562236bSHarry Wentland 1703a2b8659dSTony Cheng for (i = 0; i < pool->pipe_count; i++) { 17044562236bSHarry Wentland if (!res_ctx->pipe_ctx[i].stream) { 17054562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 17064562236bSHarry Wentland 17076b670fa9SHarry Wentland pipe_ctx->stream_res.tg = pool->timing_generators[i]; 170886a66c4eSHarry Wentland pipe_ctx->plane_res.mi = pool->mis[i]; 17098feabd03SYue Hin Lau pipe_ctx->plane_res.hubp = pool->hubps[i]; 171086a66c4eSHarry Wentland pipe_ctx->plane_res.ipp = pool->ipps[i]; 171186a66c4eSHarry Wentland pipe_ctx->plane_res.xfm = pool->transforms[i]; 1712d94585a0SYue Hin Lau pipe_ctx->plane_res.dpp = pool->dpps[i]; 1713a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp = pool->opps[i]; 1714bc373a89SRoman Li if (pool->dpps[i]) 1715e07f541fSYongqiang Sun pipe_ctx->plane_res.mpcc_inst = pool->dpps[i]->inst; 17164562236bSHarry Wentland pipe_ctx->pipe_idx = i; 17174562236bSHarry Wentland 1718ff5ef992SAlex Deucher 17194562236bSHarry Wentland pipe_ctx->stream = stream; 17204562236bSHarry Wentland return i; 17214562236bSHarry Wentland } 17224562236bSHarry Wentland } 17234562236bSHarry Wentland return -1; 17244562236bSHarry Wentland } 17254562236bSHarry Wentland 1726a2b8659dSTony Cheng static struct audio *find_first_free_audio( 1727a2b8659dSTony Cheng struct resource_context *res_ctx, 1728cfb071f7SCharlene Liu const struct resource_pool *pool, 1729f24b0522SPaul Hsieh enum engine_id id, 1730f24b0522SPaul Hsieh enum dce_version dc_version) 17314562236bSHarry Wentland { 1732b5a41620SCharlene Liu int i, available_audio_count; 1733b5a41620SCharlene Liu 1734b5a41620SCharlene Liu available_audio_count = pool->audio_count; 1735b5a41620SCharlene Liu 1736b5a41620SCharlene Liu for (i = 0; i < available_audio_count; i++) { 17374176664bSCharlene Liu if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) { 1738cfb071f7SCharlene Liu /*we have enough audio endpoint, find the matching inst*/ 1739cfb071f7SCharlene Liu if (id != i) 1740cfb071f7SCharlene Liu continue; 1741a2b8659dSTony Cheng return pool->audios[i]; 17424562236bSHarry Wentland } 17434562236bSHarry Wentland } 17445feb9f07STai Man 17455feb9f07STai Man /* use engine id to find free audio */ 1746b5a41620SCharlene Liu if ((id < available_audio_count) && (res_ctx->is_audio_acquired[id] == false)) { 17475feb9f07STai Man return pool->audios[id]; 17485feb9f07STai Man } 174966bfd4fdSCharlene Liu /*not found the matching one, first come first serve*/ 1750b5a41620SCharlene Liu for (i = 0; i < available_audio_count; i++) { 17514176664bSCharlene Liu if (res_ctx->is_audio_acquired[i] == false) { 17524176664bSCharlene Liu return pool->audios[i]; 17534176664bSCharlene Liu } 17544176664bSCharlene Liu } 17554562236bSHarry Wentland return 0; 17564562236bSHarry Wentland } 17574562236bSHarry Wentland 17584562236bSHarry Wentland bool resource_is_stream_unchanged( 1759608ac7bbSJerry Zuo struct dc_state *old_context, struct dc_stream_state *stream) 17604562236bSHarry Wentland { 1761ab2541b6SAric Cyr int i; 17624562236bSHarry Wentland 1763ab2541b6SAric Cyr for (i = 0; i < old_context->stream_count; i++) { 17640971c40eSHarry Wentland struct dc_stream_state *old_stream = old_context->streams[i]; 17654562236bSHarry Wentland 17664562236bSHarry Wentland if (are_stream_backends_same(old_stream, stream)) 17674562236bSHarry Wentland return true; 17684562236bSHarry Wentland } 17694562236bSHarry Wentland 17704562236bSHarry Wentland return false; 17714562236bSHarry Wentland } 17724562236bSHarry Wentland 17732119aa17SDavid Francis /** 17742119aa17SDavid Francis * dc_add_stream_to_ctx() - Add a new dc_stream_state to a dc_state. 17752119aa17SDavid Francis */ 177613ab1b44SYongqiang Sun enum dc_status dc_add_stream_to_ctx( 17771dc90497SAndrey Grodzovsky struct dc *dc, 1778608ac7bbSJerry Zuo struct dc_state *new_ctx, 17791dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 17801dc90497SAndrey Grodzovsky { 17811dc90497SAndrey Grodzovsky enum dc_status res; 1782eb9714a2SWenjing Liu DC_LOGGER_INIT(dc->ctx->logger); 17831dc90497SAndrey Grodzovsky 1784ece4147fSKen Chalmers if (new_ctx->stream_count >= dc->res_pool->timing_generator_count) { 1785eb9714a2SWenjing Liu DC_LOG_WARNING("Max streams reached, can't add stream %p !\n", stream); 17861dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 17871dc90497SAndrey Grodzovsky } 17881dc90497SAndrey Grodzovsky 17891dc90497SAndrey Grodzovsky new_ctx->streams[new_ctx->stream_count] = stream; 17901dc90497SAndrey Grodzovsky dc_stream_retain(stream); 17911dc90497SAndrey Grodzovsky new_ctx->stream_count++; 17921dc90497SAndrey Grodzovsky 17931dc90497SAndrey Grodzovsky res = dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream); 17941dc90497SAndrey Grodzovsky if (res != DC_OK) 1795eb9714a2SWenjing Liu DC_LOG_WARNING("Adding stream %p to context failed with err %d!\n", stream, res); 17961dc90497SAndrey Grodzovsky 179713ab1b44SYongqiang Sun return res; 17981dc90497SAndrey Grodzovsky } 17991dc90497SAndrey Grodzovsky 18002119aa17SDavid Francis /** 18012119aa17SDavid Francis * dc_remove_stream_from_ctx() - Remove a stream from a dc_state. 18022119aa17SDavid Francis */ 180362c933f9SYongqiang Sun enum dc_status dc_remove_stream_from_ctx( 18041dc90497SAndrey Grodzovsky struct dc *dc, 1805608ac7bbSJerry Zuo struct dc_state *new_ctx, 18061dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 18071dc90497SAndrey Grodzovsky { 180819f89e23SAndrey Grodzovsky int i; 18091dc90497SAndrey Grodzovsky struct dc_context *dc_ctx = dc->ctx; 181022498036SDmytro Laktyushkin struct pipe_ctx *del_pipe = resource_get_head_pipe_for_stream(&new_ctx->res_ctx, stream); 181122498036SDmytro Laktyushkin struct pipe_ctx *odm_pipe; 181222498036SDmytro Laktyushkin 181322498036SDmytro Laktyushkin if (!del_pipe) { 181422498036SDmytro Laktyushkin DC_ERROR("Pipe not found for stream %p !\n", stream); 181522498036SDmytro Laktyushkin return DC_ERROR_UNEXPECTED; 181622498036SDmytro Laktyushkin } 181722498036SDmytro Laktyushkin 181822498036SDmytro Laktyushkin odm_pipe = del_pipe->next_odm_pipe; 18191dc90497SAndrey Grodzovsky 182019f89e23SAndrey Grodzovsky /* Release primary pipe */ 182119f89e23SAndrey Grodzovsky ASSERT(del_pipe->stream_res.stream_enc); 18221dc90497SAndrey Grodzovsky update_stream_engine_usage( 18231dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 18241dc90497SAndrey Grodzovsky dc->res_pool, 18251dc90497SAndrey Grodzovsky del_pipe->stream_res.stream_enc, 18261dc90497SAndrey Grodzovsky false); 18271dc90497SAndrey Grodzovsky 18281dc90497SAndrey Grodzovsky if (del_pipe->stream_res.audio) 18291dc90497SAndrey Grodzovsky update_audio_usage( 18301dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 18311dc90497SAndrey Grodzovsky dc->res_pool, 18321dc90497SAndrey Grodzovsky del_pipe->stream_res.audio, 18331dc90497SAndrey Grodzovsky false); 18341dc90497SAndrey Grodzovsky 18359d0dcecdSHarry Wentland resource_unreference_clock_source(&new_ctx->res_ctx, 18369d0dcecdSHarry Wentland dc->res_pool, 18379d0dcecdSHarry Wentland del_pipe->clock_source); 18389d0dcecdSHarry Wentland 1839e56ae556SNikola Cornij if (dc->res_pool->funcs->remove_stream_from_ctx) 1840e56ae556SNikola Cornij dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream); 1841e56ae556SNikola Cornij 184222498036SDmytro Laktyushkin while (odm_pipe) { 184322498036SDmytro Laktyushkin struct pipe_ctx *next_odm_pipe = odm_pipe->next_odm_pipe; 184422498036SDmytro Laktyushkin 184522498036SDmytro Laktyushkin memset(odm_pipe, 0, sizeof(*odm_pipe)); 184622498036SDmytro Laktyushkin odm_pipe = next_odm_pipe; 184722498036SDmytro Laktyushkin } 18481dc90497SAndrey Grodzovsky memset(del_pipe, 0, sizeof(*del_pipe)); 18496ffaa6fcSDmytro Laktyushkin 18501dc90497SAndrey Grodzovsky for (i = 0; i < new_ctx->stream_count; i++) 18511dc90497SAndrey Grodzovsky if (new_ctx->streams[i] == stream) 18521dc90497SAndrey Grodzovsky break; 18531dc90497SAndrey Grodzovsky 18541dc90497SAndrey Grodzovsky if (new_ctx->streams[i] != stream) { 18551dc90497SAndrey Grodzovsky DC_ERROR("Context doesn't have stream %p !\n", stream); 18561dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 18571dc90497SAndrey Grodzovsky } 18581dc90497SAndrey Grodzovsky 18591dc90497SAndrey Grodzovsky dc_stream_release(new_ctx->streams[i]); 18601dc90497SAndrey Grodzovsky new_ctx->stream_count--; 18611dc90497SAndrey Grodzovsky 18621dc90497SAndrey Grodzovsky /* Trim back arrays */ 18631dc90497SAndrey Grodzovsky for (; i < new_ctx->stream_count; i++) { 18641dc90497SAndrey Grodzovsky new_ctx->streams[i] = new_ctx->streams[i + 1]; 18651dc90497SAndrey Grodzovsky new_ctx->stream_status[i] = new_ctx->stream_status[i + 1]; 18661dc90497SAndrey Grodzovsky } 18671dc90497SAndrey Grodzovsky 18681dc90497SAndrey Grodzovsky new_ctx->streams[new_ctx->stream_count] = NULL; 18691dc90497SAndrey Grodzovsky memset( 18701dc90497SAndrey Grodzovsky &new_ctx->stream_status[new_ctx->stream_count], 18711dc90497SAndrey Grodzovsky 0, 18721dc90497SAndrey Grodzovsky sizeof(new_ctx->stream_status[0])); 18731dc90497SAndrey Grodzovsky 18741dc90497SAndrey Grodzovsky return DC_OK; 18751dc90497SAndrey Grodzovsky } 18761dc90497SAndrey Grodzovsky 18770971c40eSHarry Wentland static struct dc_stream_state *find_pll_sharable_stream( 18780971c40eSHarry Wentland struct dc_stream_state *stream_needs_pll, 1879608ac7bbSJerry Zuo struct dc_state *context) 18804562236bSHarry Wentland { 1881ab2541b6SAric Cyr int i; 18824562236bSHarry Wentland 1883ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 18840971c40eSHarry Wentland struct dc_stream_state *stream_has_pll = context->streams[i]; 18854562236bSHarry Wentland 18864562236bSHarry Wentland /* We are looking for non dp, non virtual stream */ 18874562236bSHarry Wentland if (resource_are_streams_timing_synchronizable( 18884562236bSHarry Wentland stream_needs_pll, stream_has_pll) 18894562236bSHarry Wentland && !dc_is_dp_signal(stream_has_pll->signal) 1890ceb3dbb4SJun Lei && stream_has_pll->link->connector_signal 18914562236bSHarry Wentland != SIGNAL_TYPE_VIRTUAL) 18924562236bSHarry Wentland return stream_has_pll; 1893ab2541b6SAric Cyr 18944562236bSHarry Wentland } 18954562236bSHarry Wentland 18964562236bSHarry Wentland return NULL; 18974562236bSHarry Wentland } 18984562236bSHarry Wentland 18994562236bSHarry Wentland static int get_norm_pix_clk(const struct dc_crtc_timing *timing) 19004562236bSHarry Wentland { 1901380604e2SKen Chalmers uint32_t pix_clk = timing->pix_clk_100hz; 19024562236bSHarry Wentland uint32_t normalized_pix_clk = pix_clk; 19034562236bSHarry Wentland 19044562236bSHarry Wentland if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) 19054562236bSHarry Wentland pix_clk /= 2; 1906cc4d99b8SCharlene Liu if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) { 19074562236bSHarry Wentland switch (timing->display_color_depth) { 19088897810aSJulian Parkin case COLOR_DEPTH_666: 19094562236bSHarry Wentland case COLOR_DEPTH_888: 19104562236bSHarry Wentland normalized_pix_clk = pix_clk; 19114562236bSHarry Wentland break; 19124562236bSHarry Wentland case COLOR_DEPTH_101010: 19134562236bSHarry Wentland normalized_pix_clk = (pix_clk * 30) / 24; 19144562236bSHarry Wentland break; 19154562236bSHarry Wentland case COLOR_DEPTH_121212: 19164562236bSHarry Wentland normalized_pix_clk = (pix_clk * 36) / 24; 19174562236bSHarry Wentland break; 19184562236bSHarry Wentland case COLOR_DEPTH_161616: 19194562236bSHarry Wentland normalized_pix_clk = (pix_clk * 48) / 24; 19204562236bSHarry Wentland break; 19214562236bSHarry Wentland default: 19224562236bSHarry Wentland ASSERT(0); 19234562236bSHarry Wentland break; 19244562236bSHarry Wentland } 1925cc4d99b8SCharlene Liu } 19264562236bSHarry Wentland return normalized_pix_clk; 19274562236bSHarry Wentland } 19284562236bSHarry Wentland 19290971c40eSHarry Wentland static void calculate_phy_pix_clks(struct dc_stream_state *stream) 19304562236bSHarry Wentland { 19314562236bSHarry Wentland /* update actual pixel clock on all streams */ 19324562236bSHarry Wentland if (dc_is_hdmi_signal(stream->signal)) 19334562236bSHarry Wentland stream->phy_pix_clk = get_norm_pix_clk( 1934380604e2SKen Chalmers &stream->timing) / 10; 19354562236bSHarry Wentland else 19364562236bSHarry Wentland stream->phy_pix_clk = 1937380604e2SKen Chalmers stream->timing.pix_clk_100hz / 10; 193839c03e00SCharlene Liu 193939c03e00SCharlene Liu if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) 194039c03e00SCharlene Liu stream->phy_pix_clk *= 2; 19414562236bSHarry Wentland } 19424562236bSHarry Wentland 1943d2d7885fSAnthony Koo static int acquire_resource_from_hw_enabled_state( 1944d2d7885fSAnthony Koo struct resource_context *res_ctx, 1945d2d7885fSAnthony Koo const struct resource_pool *pool, 1946d2d7885fSAnthony Koo struct dc_stream_state *stream) 1947d2d7885fSAnthony Koo { 1948d2d7885fSAnthony Koo struct dc_link *link = stream->link; 194908b66279SMartin Leung unsigned int i, inst, tg_inst = 0; 1950d2d7885fSAnthony Koo 1951d2d7885fSAnthony Koo /* Check for enabled DIG to identify enabled display */ 1952d2d7885fSAnthony Koo if (!link->link_enc->funcs->is_dig_enabled(link->link_enc)) 1953d2d7885fSAnthony Koo return -1; 1954d2d7885fSAnthony Koo 19555ec43edaSMartin Leung inst = link->link_enc->funcs->get_dig_frontend(link->link_enc); 1956d2d7885fSAnthony Koo 19577f7652eeSMartin Leung if (inst == ENGINE_ID_UNKNOWN) 195875441d9dSMikita Lipski return -1; 1959d2d7885fSAnthony Koo 19607f7652eeSMartin Leung for (i = 0; i < pool->stream_enc_count; i++) { 19617f7652eeSMartin Leung if (pool->stream_enc[i]->id == inst) { 19627f7652eeSMartin Leung tg_inst = pool->stream_enc[i]->funcs->dig_source_otg( 19637f7652eeSMartin Leung pool->stream_enc[i]); 19647f7652eeSMartin Leung break; 19657f7652eeSMartin Leung } 19667f7652eeSMartin Leung } 1967d2d7885fSAnthony Koo 19687f7652eeSMartin Leung // tg_inst not found 19697f7652eeSMartin Leung if (i == pool->stream_enc_count) 197075441d9dSMikita Lipski return -1; 19715ec43edaSMartin Leung 19725ec43edaSMartin Leung if (tg_inst >= pool->timing_generator_count) 197375441d9dSMikita Lipski return -1; 19745ec43edaSMartin Leung 19755ec43edaSMartin Leung if (!res_ctx->pipe_ctx[tg_inst].stream) { 19765ec43edaSMartin Leung struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[tg_inst]; 19775ec43edaSMartin Leung 19785ec43edaSMartin Leung pipe_ctx->stream_res.tg = pool->timing_generators[tg_inst]; 19795ec43edaSMartin Leung pipe_ctx->plane_res.mi = pool->mis[tg_inst]; 19805ec43edaSMartin Leung pipe_ctx->plane_res.hubp = pool->hubps[tg_inst]; 19815ec43edaSMartin Leung pipe_ctx->plane_res.ipp = pool->ipps[tg_inst]; 19825ec43edaSMartin Leung pipe_ctx->plane_res.xfm = pool->transforms[tg_inst]; 19835ec43edaSMartin Leung pipe_ctx->plane_res.dpp = pool->dpps[tg_inst]; 19845ec43edaSMartin Leung pipe_ctx->stream_res.opp = pool->opps[tg_inst]; 19855ec43edaSMartin Leung 1986ccce745cSMartin Leung if (pool->dpps[tg_inst]) { 19875ec43edaSMartin Leung pipe_ctx->plane_res.mpcc_inst = pool->dpps[tg_inst]->inst; 1988ccce745cSMartin Leung 1989ccce745cSMartin Leung // Read DPP->MPCC->OPP Pipe from HW State 1990ccce745cSMartin Leung if (pool->mpc->funcs->read_mpcc_state) { 1991ccce745cSMartin Leung struct mpcc_state s = {0}; 1992ccce745cSMartin Leung 1993ccce745cSMartin Leung pool->mpc->funcs->read_mpcc_state(pool->mpc, pipe_ctx->plane_res.mpcc_inst, &s); 1994ccce745cSMartin Leung 1995ccce745cSMartin Leung if (s.dpp_id < MAX_MPCC) 1996ccce745cSMartin Leung pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].dpp_id = s.dpp_id; 1997ccce745cSMartin Leung 1998ccce745cSMartin Leung if (s.bot_mpcc_id < MAX_MPCC) 1999ccce745cSMartin Leung pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].mpcc_bot = 2000ccce745cSMartin Leung &pool->mpc->mpcc_array[s.bot_mpcc_id]; 2001ccce745cSMartin Leung 2002ccce745cSMartin Leung if (s.opp_id < MAX_OPP) 2003ccce745cSMartin Leung pipe_ctx->stream_res.opp->mpc_tree_params.opp_id = s.opp_id; 2004ccce745cSMartin Leung } 2005ccce745cSMartin Leung } 20065ec43edaSMartin Leung pipe_ctx->pipe_idx = tg_inst; 2007d2d7885fSAnthony Koo 2008d2d7885fSAnthony Koo pipe_ctx->stream = stream; 20095ec43edaSMartin Leung return tg_inst; 2010d2d7885fSAnthony Koo } 2011d2d7885fSAnthony Koo 2012d2d7885fSAnthony Koo return -1; 2013d2d7885fSAnthony Koo } 2014d2d7885fSAnthony Koo 20154562236bSHarry Wentland enum dc_status resource_map_pool_resources( 2016fb3466a4SBhawanpreet Lakha const struct dc *dc, 2017608ac7bbSJerry Zuo struct dc_state *context, 20181dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 20194562236bSHarry Wentland { 2020a2b8659dSTony Cheng const struct resource_pool *pool = dc->res_pool; 20211dc90497SAndrey Grodzovsky int i; 20221dc90497SAndrey Grodzovsky struct dc_context *dc_ctx = dc->ctx; 20231dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = NULL; 20241dc90497SAndrey Grodzovsky int pipe_idx = -1; 202546570f09SAnthony Koo struct dc_bios *dcb = dc->ctx->dc_bios; 20264562236bSHarry Wentland 20271dc90497SAndrey Grodzovsky /* TODO Check if this is needed */ 20281dc90497SAndrey Grodzovsky /*if (!resource_is_stream_unchanged(old_context, stream)) { 2029430ef426SDmytro Laktyushkin if (stream != NULL && old_context->streams[i] != NULL) { 20304b679bc3SCharlene Liu stream->bit_depth_params = 2031430ef426SDmytro Laktyushkin old_context->streams[i]->bit_depth_params; 2032430ef426SDmytro Laktyushkin stream->clamping = old_context->streams[i]->clamping; 20334562236bSHarry Wentland continue; 20344b679bc3SCharlene Liu } 20354b679bc3SCharlene Liu } 20364562236bSHarry Wentland */ 20374562236bSHarry Wentland 203808e1c28dSYogesh Mohan Marimuthu calculate_phy_pix_clks(stream); 203908e1c28dSYogesh Mohan Marimuthu 204046570f09SAnthony Koo /* TODO: Check Linux */ 204146570f09SAnthony Koo if (dc->config.allow_seamless_boot_optimization && 204246570f09SAnthony Koo !dcb->funcs->is_accelerated_mode(dcb)) { 204346570f09SAnthony Koo if (dc_validate_seamless_boot_timing(dc, stream->sink, &stream->timing)) 204446570f09SAnthony Koo stream->apply_seamless_boot_optimization = true; 204546570f09SAnthony Koo } 204646570f09SAnthony Koo 2047d2d7885fSAnthony Koo if (stream->apply_seamless_boot_optimization) 2048d2d7885fSAnthony Koo pipe_idx = acquire_resource_from_hw_enabled_state( 2049d2d7885fSAnthony Koo &context->res_ctx, 2050d2d7885fSAnthony Koo pool, 2051d2d7885fSAnthony Koo stream); 2052d2d7885fSAnthony Koo 2053d2d7885fSAnthony Koo if (pipe_idx < 0) 20544562236bSHarry Wentland /* acquire new resources */ 20555d11e9fcSDmytro Laktyushkin pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); 20561dc90497SAndrey Grodzovsky 2057b86a1aa3SBhawanpreet Lakha #ifdef CONFIG_DRM_AMD_DC_DCN 20585d11e9fcSDmytro Laktyushkin if (pipe_idx < 0) 205913ab1b44SYongqiang Sun pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 206094c6d735SHarry Wentland #endif 206113ab1b44SYongqiang Sun 2062c5b38aecSDmytro Laktyushkin if (pipe_idx < 0 || context->res_ctx.pipe_ctx[pipe_idx].stream_res.tg == NULL) 20634562236bSHarry Wentland return DC_NO_CONTROLLER_RESOURCE; 20644562236bSHarry Wentland 20654562236bSHarry Wentland pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; 20664562236bSHarry Wentland 20678e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc = 206878cc70b1SWesley Chalmers dc->res_pool->funcs->find_first_free_match_stream_enc_for_link( 2069a2b8659dSTony Cheng &context->res_ctx, pool, stream); 20704562236bSHarry Wentland 20718e9c4c8cSHarry Wentland if (!pipe_ctx->stream_res.stream_enc) 207238684e46SEric Bernstein return DC_NO_STREAM_ENC_RESOURCE; 20734562236bSHarry Wentland 20741dc90497SAndrey Grodzovsky update_stream_engine_usage( 2075a2b8659dSTony Cheng &context->res_ctx, pool, 20761dc90497SAndrey Grodzovsky pipe_ctx->stream_res.stream_enc, 20771dc90497SAndrey Grodzovsky true); 20784562236bSHarry Wentland 20794562236bSHarry Wentland /* TODO: Add check if ASIC support and EDID audio */ 2080ceb3dbb4SJun Lei if (!stream->converter_disable_audio && 20814562236bSHarry Wentland dc_is_audio_capable_signal(pipe_ctx->stream->signal) && 2082ce08aad3SAlvin Lee stream->audio_info.mode_count && stream->audio_info.flags.all) { 2083afaacef4SHarry Wentland pipe_ctx->stream_res.audio = find_first_free_audio( 2084f24b0522SPaul Hsieh &context->res_ctx, pool, pipe_ctx->stream_res.stream_enc->id, dc_ctx->dce_version); 20854562236bSHarry Wentland 20864562236bSHarry Wentland /* 20874562236bSHarry Wentland * Audio assigned in order first come first get. 20884562236bSHarry Wentland * There are asics which has number of audio 20894562236bSHarry Wentland * resources less then number of pipes 20904562236bSHarry Wentland */ 2091afaacef4SHarry Wentland if (pipe_ctx->stream_res.audio) 20921dc90497SAndrey Grodzovsky update_audio_usage(&context->res_ctx, pool, 20931dc90497SAndrey Grodzovsky pipe_ctx->stream_res.audio, true); 20944562236bSHarry Wentland } 20954562236bSHarry Wentland 20969aef1a31SSivapiriyanKumarasamy /* Add ABM to the resource if on EDP */ 20979aef1a31SSivapiriyanKumarasamy if (pipe_ctx->stream && dc_is_embedded_signal(pipe_ctx->stream->signal)) 20989aef1a31SSivapiriyanKumarasamy pipe_ctx->stream_res.abm = pool->abm; 20999aef1a31SSivapiriyanKumarasamy 21001dc90497SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 21011dc90497SAndrey Grodzovsky if (context->streams[i] == stream) { 21026b670fa9SHarry Wentland context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; 21033f0940f8SCharlene Liu context->stream_status[i].stream_enc_inst = pipe_ctx->stream_res.stream_enc->stream_enc_inst; 21045fdb7c4cSNicholas Kazlauskas context->stream_status[i].audio_inst = 21055fdb7c4cSNicholas Kazlauskas pipe_ctx->stream_res.audio ? pipe_ctx->stream_res.audio->inst : -1; 21065fdb7c4cSNicholas Kazlauskas 21071dc90497SAndrey Grodzovsky return DC_OK; 21084562236bSHarry Wentland } 21094562236bSHarry Wentland 21101dc90497SAndrey Grodzovsky DC_ERROR("Stream %p not found in new ctx!\n", stream); 21111dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 21124562236bSHarry Wentland } 21134562236bSHarry Wentland 21142119aa17SDavid Francis /** 21152119aa17SDavid Francis * dc_resource_state_copy_construct_current() - Creates a new dc_state from existing state 21162119aa17SDavid Francis * Is a shallow copy. Increments refcounts on existing streams and planes. 21172119aa17SDavid Francis * @dc: copy out of dc->current_state 21182119aa17SDavid Francis * @dst_ctx: copy into this 21192119aa17SDavid Francis */ 2120f36cc577SBhawanpreet Lakha void dc_resource_state_copy_construct_current( 21211dc90497SAndrey Grodzovsky const struct dc *dc, 2122608ac7bbSJerry Zuo struct dc_state *dst_ctx) 21231dc90497SAndrey Grodzovsky { 2124f36cc577SBhawanpreet Lakha dc_resource_state_copy_construct(dc->current_state, dst_ctx); 21251dc90497SAndrey Grodzovsky } 21261dc90497SAndrey Grodzovsky 2127ab8db3e1SAndrey Grodzovsky 2128ab8db3e1SAndrey Grodzovsky void dc_resource_state_construct( 2129ab8db3e1SAndrey Grodzovsky const struct dc *dc, 2130ab8db3e1SAndrey Grodzovsky struct dc_state *dst_ctx) 2131ab8db3e1SAndrey Grodzovsky { 2132dc88b4a6SEric Yang dst_ctx->clk_mgr = dc->clk_mgr; 2133ab8db3e1SAndrey Grodzovsky } 2134ab8db3e1SAndrey Grodzovsky 21356d822156SNikola Cornij 21366d822156SNikola Cornij bool dc_resource_is_dsc_encoding_supported(const struct dc *dc) 21376d822156SNikola Cornij { 21386d822156SNikola Cornij return dc->res_pool->res_cap->num_dsc > 0; 21396d822156SNikola Cornij } 21406d822156SNikola Cornij 21416d822156SNikola Cornij 21422119aa17SDavid Francis /** 21432119aa17SDavid Francis * dc_validate_global_state() - Determine if HW can support a given state 21442119aa17SDavid Francis * Checks HW resource availability and bandwidth requirement. 21452119aa17SDavid Francis * @dc: dc struct for this driver 21462119aa17SDavid Francis * @new_ctx: state to be validated 2147afcd526bSJoshua Aberback * @fast_validate: set to true if only yes/no to support matters 21482119aa17SDavid Francis * 21492119aa17SDavid Francis * Return: DC_OK if the result can be programmed. Otherwise, an error code. 21502119aa17SDavid Francis */ 2151e750d56dSYongqiang Sun enum dc_status dc_validate_global_state( 21521dc90497SAndrey Grodzovsky struct dc *dc, 2153afcd526bSJoshua Aberback struct dc_state *new_ctx, 2154afcd526bSJoshua Aberback bool fast_validate) 21551dc90497SAndrey Grodzovsky { 21561dc90497SAndrey Grodzovsky enum dc_status result = DC_ERROR_UNEXPECTED; 21571dc90497SAndrey Grodzovsky int i, j; 21581dc90497SAndrey Grodzovsky 2159e41ab030SHarry Wentland if (!new_ctx) 2160e41ab030SHarry Wentland return DC_ERROR_UNEXPECTED; 2161e41ab030SHarry Wentland 2162d596e5d0SYongqiang Sun if (dc->res_pool->funcs->validate_global) { 2163d596e5d0SYongqiang Sun result = dc->res_pool->funcs->validate_global(dc, new_ctx); 2164d596e5d0SYongqiang Sun if (result != DC_OK) 2165d596e5d0SYongqiang Sun return result; 2166d596e5d0SYongqiang Sun } 21671dc90497SAndrey Grodzovsky 2168e41ab030SHarry Wentland for (i = 0; i < new_ctx->stream_count; i++) { 21691dc90497SAndrey Grodzovsky struct dc_stream_state *stream = new_ctx->streams[i]; 21701dc90497SAndrey Grodzovsky 21711dc90497SAndrey Grodzovsky for (j = 0; j < dc->res_pool->pipe_count; j++) { 21721dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[j]; 21731dc90497SAndrey Grodzovsky 21741dc90497SAndrey Grodzovsky if (pipe_ctx->stream != stream) 21751dc90497SAndrey Grodzovsky continue; 21761dc90497SAndrey Grodzovsky 21778d8c82b6SJoseph Gravenor if (dc->res_pool->funcs->patch_unknown_plane_state && 217874eac5f3SSu Sung Chung pipe_ctx->plane_state && 217974eac5f3SSu Sung Chung pipe_ctx->plane_state->tiling_info.gfx9.swizzle == DC_SW_UNKNOWN) { 21808d8c82b6SJoseph Gravenor result = dc->res_pool->funcs->patch_unknown_plane_state(pipe_ctx->plane_state); 218174eac5f3SSu Sung Chung if (result != DC_OK) 218274eac5f3SSu Sung Chung return result; 218374eac5f3SSu Sung Chung } 218474eac5f3SSu Sung Chung 21851dc90497SAndrey Grodzovsky /* Switch to dp clock source only if there is 21861dc90497SAndrey Grodzovsky * no non dp stream that shares the same timing 21871dc90497SAndrey Grodzovsky * with the dp stream. 21881dc90497SAndrey Grodzovsky */ 21891dc90497SAndrey Grodzovsky if (dc_is_dp_signal(pipe_ctx->stream->signal) && 21901dc90497SAndrey Grodzovsky !find_pll_sharable_stream(stream, new_ctx)) { 21911dc90497SAndrey Grodzovsky 21929d0dcecdSHarry Wentland resource_unreference_clock_source( 21931dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 21941dc90497SAndrey Grodzovsky dc->res_pool, 21959d0dcecdSHarry Wentland pipe_ctx->clock_source); 21964a629536SHarry Wentland 21971dc90497SAndrey Grodzovsky pipe_ctx->clock_source = dc->res_pool->dp_clock_source; 21981dc90497SAndrey Grodzovsky resource_reference_clock_source( 21991dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 22001dc90497SAndrey Grodzovsky dc->res_pool, 22011dc90497SAndrey Grodzovsky pipe_ctx->clock_source); 22021dc90497SAndrey Grodzovsky } 22031dc90497SAndrey Grodzovsky } 22041dc90497SAndrey Grodzovsky } 22051dc90497SAndrey Grodzovsky 22061dc90497SAndrey Grodzovsky result = resource_build_scaling_params_for_context(dc, new_ctx); 22071dc90497SAndrey Grodzovsky 22081dc90497SAndrey Grodzovsky if (result == DC_OK) 2209afcd526bSJoshua Aberback if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, fast_validate)) 22101dc90497SAndrey Grodzovsky result = DC_FAIL_BANDWIDTH_VALIDATE; 22111dc90497SAndrey Grodzovsky 22121dc90497SAndrey Grodzovsky return result; 22131dc90497SAndrey Grodzovsky } 22141dc90497SAndrey Grodzovsky 22156e4d6beeSTony Cheng static void patch_gamut_packet_checksum( 2216e09b6473SAnthony Koo struct dc_info_packet *gamut_packet) 22174562236bSHarry Wentland { 22184562236bSHarry Wentland /* For gamut we recalc checksum */ 22196e4d6beeSTony Cheng if (gamut_packet->valid) { 22204562236bSHarry Wentland uint8_t chk_sum = 0; 22214562236bSHarry Wentland uint8_t *ptr; 22224562236bSHarry Wentland uint8_t i; 22234562236bSHarry Wentland 22244562236bSHarry Wentland /*start of the Gamut data. */ 22256e4d6beeSTony Cheng ptr = &gamut_packet->sb[3]; 22264562236bSHarry Wentland 22276e4d6beeSTony Cheng for (i = 0; i <= gamut_packet->sb[1]; i++) 22284562236bSHarry Wentland chk_sum += ptr[i]; 22294562236bSHarry Wentland 22306e4d6beeSTony Cheng gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum); 22311646a6feSAndrew Wong } 22324562236bSHarry Wentland } 22334562236bSHarry Wentland 22344562236bSHarry Wentland static void set_avi_info_frame( 2235e09b6473SAnthony Koo struct dc_info_packet *info_packet, 22364562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 22374562236bSHarry Wentland { 22380971c40eSHarry Wentland struct dc_stream_state *stream = pipe_ctx->stream; 22394562236bSHarry Wentland enum dc_color_space color_space = COLOR_SPACE_UNKNOWN; 22404562236bSHarry Wentland uint32_t pixel_encoding = 0; 22414562236bSHarry Wentland enum scanning_type scan_type = SCANNING_TYPE_NODATA; 22424562236bSHarry Wentland enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA; 22434562236bSHarry Wentland bool itc = false; 224450e27654SZeyu Fan uint8_t itc_value = 0; 22454562236bSHarry Wentland uint8_t cn0_cn1 = 0; 224650e27654SZeyu Fan unsigned int cn0_cn1_value = 0; 22474562236bSHarry Wentland uint8_t *check_sum = NULL; 22484562236bSHarry Wentland uint8_t byte_index = 0; 2249754e3673SAnthony Koo union hdmi_info_packet hdmi_info; 225050e27654SZeyu Fan union display_content_support support = {0}; 22514fa086b9SLeo (Sunpeng) Li unsigned int vic = pipe_ctx->stream->timing.vic; 225215e17335SCharlene Liu enum dc_timing_3d_format format; 22534562236bSHarry Wentland 2254754e3673SAnthony Koo memset(&hdmi_info, 0, sizeof(union hdmi_info_packet)); 2255754e3673SAnthony Koo 22564fa086b9SLeo (Sunpeng) Li color_space = pipe_ctx->stream->output_color_space; 2257e5f2038eSCharlene Liu if (color_space == COLOR_SPACE_UNKNOWN) 22584fa086b9SLeo (Sunpeng) Li color_space = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ? 2259e5f2038eSCharlene Liu COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709; 22604562236bSHarry Wentland 22614562236bSHarry Wentland /* Initialize header */ 2262e09b6473SAnthony Koo hdmi_info.bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI; 22634562236bSHarry Wentland /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall 22644562236bSHarry Wentland * not be used in HDMI 2.0 (Section 10.1) */ 2265e09b6473SAnthony Koo hdmi_info.bits.header.version = 2; 2266e09b6473SAnthony Koo hdmi_info.bits.header.length = HDMI_AVI_INFOFRAME_SIZE; 22674562236bSHarry Wentland 22684562236bSHarry Wentland /* 22694562236bSHarry Wentland * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built 22704562236bSHarry Wentland * according to HDMI 2.0 spec (Section 10.1) 22714562236bSHarry Wentland */ 22724562236bSHarry Wentland 22734fa086b9SLeo (Sunpeng) Li switch (stream->timing.pixel_encoding) { 22744562236bSHarry Wentland case PIXEL_ENCODING_YCBCR422: 22754562236bSHarry Wentland pixel_encoding = 1; 22764562236bSHarry Wentland break; 22774562236bSHarry Wentland 22784562236bSHarry Wentland case PIXEL_ENCODING_YCBCR444: 22794562236bSHarry Wentland pixel_encoding = 2; 22804562236bSHarry Wentland break; 22814562236bSHarry Wentland case PIXEL_ENCODING_YCBCR420: 22824562236bSHarry Wentland pixel_encoding = 3; 22834562236bSHarry Wentland break; 22844562236bSHarry Wentland 22854562236bSHarry Wentland case PIXEL_ENCODING_RGB: 22864562236bSHarry Wentland default: 22874562236bSHarry Wentland pixel_encoding = 0; 22884562236bSHarry Wentland } 22894562236bSHarry Wentland 22904562236bSHarry Wentland /* Y0_Y1_Y2 : The pixel encoding */ 22914562236bSHarry Wentland /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */ 2292e09b6473SAnthony Koo hdmi_info.bits.Y0_Y1_Y2 = pixel_encoding; 22934562236bSHarry Wentland 22944562236bSHarry Wentland /* A0 = 1 Active Format Information valid */ 2295e09b6473SAnthony Koo hdmi_info.bits.A0 = ACTIVE_FORMAT_VALID; 22964562236bSHarry Wentland 22974562236bSHarry Wentland /* B0, B1 = 3; Bar info data is valid */ 2298e09b6473SAnthony Koo hdmi_info.bits.B0_B1 = BAR_INFO_BOTH_VALID; 22994562236bSHarry Wentland 2300e09b6473SAnthony Koo hdmi_info.bits.SC0_SC1 = PICTURE_SCALING_UNIFORM; 23014562236bSHarry Wentland 23024562236bSHarry Wentland /* S0, S1 : Underscan / Overscan */ 23034562236bSHarry Wentland /* TODO: un-hardcode scan type */ 23044562236bSHarry Wentland scan_type = SCANNING_TYPE_UNDERSCAN; 2305e09b6473SAnthony Koo hdmi_info.bits.S0_S1 = scan_type; 23064562236bSHarry Wentland 23074562236bSHarry Wentland /* C0, C1 : Colorimetry */ 23088fde5884SCharlene Liu if (color_space == COLOR_SPACE_YCBCR709 || 230915e17335SCharlene Liu color_space == COLOR_SPACE_YCBCR709_LIMITED) 2310e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709; 23118fde5884SCharlene Liu else if (color_space == COLOR_SPACE_YCBCR601 || 23128fde5884SCharlene Liu color_space == COLOR_SPACE_YCBCR601_LIMITED) 2313e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_ITU601; 23148fde5884SCharlene Liu else { 2315e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_NO_DATA; 23168fde5884SCharlene Liu } 2317534db198SAmy Zhang if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE || 2318534db198SAmy Zhang color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE || 2319534db198SAmy Zhang color_space == COLOR_SPACE_2020_YCBCR) { 2320e09b6473SAnthony Koo hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR; 2321e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; 2322534db198SAmy Zhang } else if (color_space == COLOR_SPACE_ADOBERGB) { 2323e09b6473SAnthony Koo hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB; 2324e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; 2325534db198SAmy Zhang } 2326534db198SAmy Zhang 23274562236bSHarry Wentland /* TODO: un-hardcode aspect ratio */ 23284fa086b9SLeo (Sunpeng) Li aspect = stream->timing.aspect_ratio; 23294562236bSHarry Wentland 23304562236bSHarry Wentland switch (aspect) { 23314562236bSHarry Wentland case ASPECT_RATIO_4_3: 23324562236bSHarry Wentland case ASPECT_RATIO_16_9: 2333e09b6473SAnthony Koo hdmi_info.bits.M0_M1 = aspect; 23344562236bSHarry Wentland break; 23354562236bSHarry Wentland 23364562236bSHarry Wentland case ASPECT_RATIO_NO_DATA: 23374562236bSHarry Wentland case ASPECT_RATIO_64_27: 23384562236bSHarry Wentland case ASPECT_RATIO_256_135: 23394562236bSHarry Wentland default: 2340e09b6473SAnthony Koo hdmi_info.bits.M0_M1 = 0; 23414562236bSHarry Wentland } 23424562236bSHarry Wentland 23434562236bSHarry Wentland /* Active Format Aspect ratio - same as Picture Aspect Ratio. */ 2344e09b6473SAnthony Koo hdmi_info.bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; 23454562236bSHarry Wentland 23464562236bSHarry Wentland /* TODO: un-hardcode cn0_cn1 and itc */ 234750e27654SZeyu Fan 23484562236bSHarry Wentland cn0_cn1 = 0; 234950e27654SZeyu Fan cn0_cn1_value = 0; 235050e27654SZeyu Fan 235150e27654SZeyu Fan itc = true; 235250e27654SZeyu Fan itc_value = 1; 235350e27654SZeyu Fan 2354ceb3dbb4SJun Lei support = stream->content_support; 23554562236bSHarry Wentland 23564562236bSHarry Wentland if (itc) { 235750e27654SZeyu Fan if (!support.bits.valid_content_type) { 235850e27654SZeyu Fan cn0_cn1_value = 0; 235950e27654SZeyu Fan } else { 236050e27654SZeyu Fan if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) { 236150e27654SZeyu Fan if (support.bits.graphics_content == 1) { 236250e27654SZeyu Fan cn0_cn1_value = 0; 236350e27654SZeyu Fan } 236450e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) { 236550e27654SZeyu Fan if (support.bits.photo_content == 1) { 236650e27654SZeyu Fan cn0_cn1_value = 1; 236750e27654SZeyu Fan } else { 236850e27654SZeyu Fan cn0_cn1_value = 0; 236950e27654SZeyu Fan itc_value = 0; 237050e27654SZeyu Fan } 237150e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) { 237250e27654SZeyu Fan if (support.bits.cinema_content == 1) { 237350e27654SZeyu Fan cn0_cn1_value = 2; 237450e27654SZeyu Fan } else { 237550e27654SZeyu Fan cn0_cn1_value = 0; 237650e27654SZeyu Fan itc_value = 0; 237750e27654SZeyu Fan } 237850e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) { 237950e27654SZeyu Fan if (support.bits.game_content == 1) { 238050e27654SZeyu Fan cn0_cn1_value = 3; 238150e27654SZeyu Fan } else { 238250e27654SZeyu Fan cn0_cn1_value = 0; 238350e27654SZeyu Fan itc_value = 0; 238450e27654SZeyu Fan } 238550e27654SZeyu Fan } 238650e27654SZeyu Fan } 2387e09b6473SAnthony Koo hdmi_info.bits.CN0_CN1 = cn0_cn1_value; 2388e09b6473SAnthony Koo hdmi_info.bits.ITC = itc_value; 23894562236bSHarry Wentland } 23904562236bSHarry Wentland 23914562236bSHarry Wentland /* TODO : We should handle YCC quantization */ 23924562236bSHarry Wentland /* but we do not have matrix calculation */ 2393ceb3dbb4SJun Lei if (stream->qs_bit == 1 && 2394ceb3dbb4SJun Lei stream->qy_bit == 1) { 239550e27654SZeyu Fan if (color_space == COLOR_SPACE_SRGB || 239650e27654SZeyu Fan color_space == COLOR_SPACE_2020_RGB_FULLRANGE) { 2397e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; 2398993dca3eSQingqing Zhuo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 239950e27654SZeyu Fan } else if (color_space == COLOR_SPACE_SRGB_LIMITED || 240050e27654SZeyu Fan color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) { 2401e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE; 2402e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 24034562236bSHarry Wentland } else { 2404e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 2405e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 24064562236bSHarry Wentland } 240750e27654SZeyu Fan } else { 2408e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 2409e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 241050e27654SZeyu Fan } 241150e27654SZeyu Fan 241215e17335SCharlene Liu ///VIC 24134fa086b9SLeo (Sunpeng) Li format = stream->timing.timing_3d_format; 241415e17335SCharlene Liu /*todo, add 3DStereo support*/ 241515e17335SCharlene Liu if (format != TIMING_3D_FORMAT_NONE) { 241615e17335SCharlene Liu // Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled 24174fa086b9SLeo (Sunpeng) Li switch (pipe_ctx->stream->timing.hdmi_vic) { 241815e17335SCharlene Liu case 1: 241915e17335SCharlene Liu vic = 95; 242015e17335SCharlene Liu break; 242115e17335SCharlene Liu case 2: 242215e17335SCharlene Liu vic = 94; 242315e17335SCharlene Liu break; 242415e17335SCharlene Liu case 3: 242515e17335SCharlene Liu vic = 93; 242615e17335SCharlene Liu break; 242715e17335SCharlene Liu case 4: 242815e17335SCharlene Liu vic = 98; 242915e17335SCharlene Liu break; 243015e17335SCharlene Liu default: 243115e17335SCharlene Liu break; 243215e17335SCharlene Liu } 243315e17335SCharlene Liu } 2434efa02336SChris Park /* If VIC >= 128, the Source shall use AVI InfoFrame Version 3*/ 2435e09b6473SAnthony Koo hdmi_info.bits.VIC0_VIC7 = vic; 2436efa02336SChris Park if (vic >= 128) 2437efa02336SChris Park hdmi_info.bits.header.version = 3; 2438efa02336SChris Park /* If (C1, C0)=(1, 1) and (EC2, EC1, EC0)=(1, 1, 1), 2439efa02336SChris Park * the Source shall use 20 AVI InfoFrame Version 4 2440efa02336SChris Park */ 2441efa02336SChris Park if (hdmi_info.bits.C0_C1 == COLORIMETRY_EXTENDED && 2442efa02336SChris Park hdmi_info.bits.EC0_EC2 == COLORIMETRYEX_RESERVED) { 2443efa02336SChris Park hdmi_info.bits.header.version = 4; 2444efa02336SChris Park hdmi_info.bits.header.length = 14; 2445efa02336SChris Park } 24464562236bSHarry Wentland 24474562236bSHarry Wentland /* pixel repetition 24484562236bSHarry Wentland * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel 24494562236bSHarry Wentland * repetition start from 1 */ 2450e09b6473SAnthony Koo hdmi_info.bits.PR0_PR3 = 0; 24514562236bSHarry Wentland 24524562236bSHarry Wentland /* Bar Info 24534562236bSHarry Wentland * barTop: Line Number of End of Top Bar. 24544562236bSHarry Wentland * barBottom: Line Number of Start of Bottom Bar. 24554562236bSHarry Wentland * barLeft: Pixel Number of End of Left Bar. 24564562236bSHarry Wentland * barRight: Pixel Number of Start of Right Bar. */ 2457e09b6473SAnthony Koo hdmi_info.bits.bar_top = stream->timing.v_border_top; 2458e09b6473SAnthony Koo hdmi_info.bits.bar_bottom = (stream->timing.v_total 24594fa086b9SLeo (Sunpeng) Li - stream->timing.v_border_bottom + 1); 2460e09b6473SAnthony Koo hdmi_info.bits.bar_left = stream->timing.h_border_left; 2461e09b6473SAnthony Koo hdmi_info.bits.bar_right = (stream->timing.h_total 24624fa086b9SLeo (Sunpeng) Li - stream->timing.h_border_right + 1); 24634562236bSHarry Wentland 24642f482c4fSChris Park /* Additional Colorimetry Extension 24652f482c4fSChris Park * Used in conduction with C0-C1 and EC0-EC2 24662f482c4fSChris Park * 0 = DCI-P3 RGB (D65) 24672f482c4fSChris Park * 1 = DCI-P3 RGB (theater) 24682f482c4fSChris Park */ 24692f482c4fSChris Park hdmi_info.bits.ACE0_ACE3 = 0; 24702f482c4fSChris Park 24714562236bSHarry Wentland /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ 2472e09b6473SAnthony Koo check_sum = &hdmi_info.packet_raw_data.sb[0]; 2473e8d726b7SReza Amini 2474efa02336SChris Park *check_sum = HDMI_INFOFRAME_TYPE_AVI + hdmi_info.bits.header.length + hdmi_info.bits.header.version; 24754562236bSHarry Wentland 2476efa02336SChris Park for (byte_index = 1; byte_index <= hdmi_info.bits.header.length; byte_index++) 2477e09b6473SAnthony Koo *check_sum += hdmi_info.packet_raw_data.sb[byte_index]; 24784562236bSHarry Wentland 24794562236bSHarry Wentland /* one byte complement */ 24804562236bSHarry Wentland *check_sum = (uint8_t) (0x100 - *check_sum); 24814562236bSHarry Wentland 24824562236bSHarry Wentland /* Store in hw_path_mode */ 2483e09b6473SAnthony Koo info_packet->hb0 = hdmi_info.packet_raw_data.hb0; 2484e09b6473SAnthony Koo info_packet->hb1 = hdmi_info.packet_raw_data.hb1; 2485e09b6473SAnthony Koo info_packet->hb2 = hdmi_info.packet_raw_data.hb2; 24864562236bSHarry Wentland 2487e09b6473SAnthony Koo for (byte_index = 0; byte_index < sizeof(hdmi_info.packet_raw_data.sb); byte_index++) 2488e09b6473SAnthony Koo info_packet->sb[byte_index] = hdmi_info.packet_raw_data.sb[byte_index]; 24894562236bSHarry Wentland 24904562236bSHarry Wentland info_packet->valid = true; 24914562236bSHarry Wentland } 24924562236bSHarry Wentland 24936e4d6beeSTony Cheng static void set_vendor_info_packet( 2494e09b6473SAnthony Koo struct dc_info_packet *info_packet, 24950971c40eSHarry Wentland struct dc_stream_state *stream) 24964562236bSHarry Wentland { 2497ecd0136bSHarmanprit Tatla /* SPD info packet for FreeSync */ 249815e17335SCharlene Liu 2499ecd0136bSHarmanprit Tatla /* Check if Freesync is supported. Return if false. If true, 2500ecd0136bSHarmanprit Tatla * set the corresponding bit in the info packet 2501ecd0136bSHarmanprit Tatla */ 2502ecd0136bSHarmanprit Tatla if (!stream->vsp_infopacket.valid) 25034562236bSHarry Wentland return; 25044562236bSHarry Wentland 2505ecd0136bSHarmanprit Tatla *info_packet = stream->vsp_infopacket; 25064562236bSHarry Wentland } 25074562236bSHarry Wentland 25086e4d6beeSTony Cheng static void set_spd_info_packet( 2509e09b6473SAnthony Koo struct dc_info_packet *info_packet, 25100971c40eSHarry Wentland struct dc_stream_state *stream) 25114562236bSHarry Wentland { 25124562236bSHarry Wentland /* SPD info packet for FreeSync */ 25134562236bSHarry Wentland 25144562236bSHarry Wentland /* Check if Freesync is supported. Return if false. If true, 25154562236bSHarry Wentland * set the corresponding bit in the info packet 25164562236bSHarry Wentland */ 251798e6436dSAnthony Koo if (!stream->vrr_infopacket.valid) 25184562236bSHarry Wentland return; 25194562236bSHarry Wentland 252098e6436dSAnthony Koo *info_packet = stream->vrr_infopacket; 25214562236bSHarry Wentland } 25224562236bSHarry Wentland 25231646a6feSAndrew Wong static void set_hdr_static_info_packet( 2524e09b6473SAnthony Koo struct dc_info_packet *info_packet, 25250971c40eSHarry Wentland struct dc_stream_state *stream) 25261646a6feSAndrew Wong { 25270eeef690SAnthony Koo /* HDR Static Metadata info packet for HDR10 */ 25281646a6feSAndrew Wong 2529a10dc97aSKrunoslav Kovac if (!stream->hdr_static_metadata.valid || 2530a10dc97aSKrunoslav Kovac stream->use_dynamic_meta) 253110bff005SYongqiang Sun return; 253210bff005SYongqiang Sun 25330eeef690SAnthony Koo *info_packet = stream->hdr_static_metadata; 25341646a6feSAndrew Wong } 25351646a6feSAndrew Wong 25366e4d6beeSTony Cheng static void set_vsc_info_packet( 2537e09b6473SAnthony Koo struct dc_info_packet *info_packet, 25380971c40eSHarry Wentland struct dc_stream_state *stream) 25394562236bSHarry Wentland { 25401336926fSAlvin lee if (!stream->vsc_infopacket.valid) 25414562236bSHarry Wentland return; 25424562236bSHarry Wentland 25431336926fSAlvin lee *info_packet = stream->vsc_infopacket; 25444562236bSHarry Wentland } 25454562236bSHarry Wentland 2546f36cc577SBhawanpreet Lakha void dc_resource_state_destruct(struct dc_state *context) 25474562236bSHarry Wentland { 25484562236bSHarry Wentland int i, j; 25494562236bSHarry Wentland 2550ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 25513be5262eSHarry Wentland for (j = 0; j < context->stream_status[i].plane_count; j++) 25523be5262eSHarry Wentland dc_plane_state_release( 25533be5262eSHarry Wentland context->stream_status[i].plane_states[j]); 25544562236bSHarry Wentland 25553be5262eSHarry Wentland context->stream_status[i].plane_count = 0; 25564fa086b9SLeo (Sunpeng) Li dc_stream_release(context->streams[i]); 2557ab2541b6SAric Cyr context->streams[i] = NULL; 25584562236bSHarry Wentland } 25594562236bSHarry Wentland } 25604562236bSHarry Wentland 2561f36cc577SBhawanpreet Lakha void dc_resource_state_copy_construct( 2562608ac7bbSJerry Zuo const struct dc_state *src_ctx, 2563608ac7bbSJerry Zuo struct dc_state *dst_ctx) 25644562236bSHarry Wentland { 25654562236bSHarry Wentland int i, j; 25668ee5702aSDave Airlie struct kref refcount = dst_ctx->refcount; 25674562236bSHarry Wentland 25684562236bSHarry Wentland *dst_ctx = *src_ctx; 25694562236bSHarry Wentland 2570a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 25714562236bSHarry Wentland struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i]; 25724562236bSHarry Wentland 25734562236bSHarry Wentland if (cur_pipe->top_pipe) 25744562236bSHarry Wentland cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; 25754562236bSHarry Wentland 25764562236bSHarry Wentland if (cur_pipe->bottom_pipe) 25774562236bSHarry Wentland cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; 2578b1f6d01cSDmytro Laktyushkin 2579b1f6d01cSDmytro Laktyushkin if (cur_pipe->next_odm_pipe) 2580b1f6d01cSDmytro Laktyushkin cur_pipe->next_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx]; 2581b1f6d01cSDmytro Laktyushkin 2582b1f6d01cSDmytro Laktyushkin if (cur_pipe->prev_odm_pipe) 2583b1f6d01cSDmytro Laktyushkin cur_pipe->prev_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx]; 25844562236bSHarry Wentland } 25854562236bSHarry Wentland 2586ab2541b6SAric Cyr for (i = 0; i < dst_ctx->stream_count; i++) { 25874fa086b9SLeo (Sunpeng) Li dc_stream_retain(dst_ctx->streams[i]); 25883be5262eSHarry Wentland for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++) 25893be5262eSHarry Wentland dc_plane_state_retain( 25903be5262eSHarry Wentland dst_ctx->stream_status[i].plane_states[j]); 25914562236bSHarry Wentland } 25929a3afbb3SAndrey Grodzovsky 25939a3afbb3SAndrey Grodzovsky /* context refcount should not be overridden */ 25948ee5702aSDave Airlie dst_ctx->refcount = refcount; 25959a3afbb3SAndrey Grodzovsky 25964562236bSHarry Wentland } 25974562236bSHarry Wentland 25984562236bSHarry Wentland struct clock_source *dc_resource_find_first_free_pll( 2599a2b8659dSTony Cheng struct resource_context *res_ctx, 2600a2b8659dSTony Cheng const struct resource_pool *pool) 26014562236bSHarry Wentland { 26024562236bSHarry Wentland int i; 26034562236bSHarry Wentland 2604a2b8659dSTony Cheng for (i = 0; i < pool->clk_src_count; ++i) { 26054562236bSHarry Wentland if (res_ctx->clock_source_ref_count[i] == 0) 2606a2b8659dSTony Cheng return pool->clock_sources[i]; 26074562236bSHarry Wentland } 26084562236bSHarry Wentland 26094562236bSHarry Wentland return NULL; 26104562236bSHarry Wentland } 26114562236bSHarry Wentland 26124562236bSHarry Wentland void resource_build_info_frame(struct pipe_ctx *pipe_ctx) 26134562236bSHarry Wentland { 26144562236bSHarry Wentland enum signal_type signal = SIGNAL_TYPE_NONE; 261596c50c0dSHarry Wentland struct encoder_info_frame *info = &pipe_ctx->stream_res.encoder_info_frame; 26164562236bSHarry Wentland 26174562236bSHarry Wentland /* default all packets to invalid */ 26186e4d6beeSTony Cheng info->avi.valid = false; 26196e4d6beeSTony Cheng info->gamut.valid = false; 26206e4d6beeSTony Cheng info->vendor.valid = false; 2621630e3573SJeff Smith info->spd.valid = false; 26226e4d6beeSTony Cheng info->hdrsmd.valid = false; 26236e4d6beeSTony Cheng info->vsc.valid = false; 26244562236bSHarry Wentland 26254562236bSHarry Wentland signal = pipe_ctx->stream->signal; 26264562236bSHarry Wentland 26274562236bSHarry Wentland /* HDMi and DP have different info packets*/ 26284562236bSHarry Wentland if (dc_is_hdmi_signal(signal)) { 26296e4d6beeSTony Cheng set_avi_info_frame(&info->avi, pipe_ctx); 26306e4d6beeSTony Cheng 26316e4d6beeSTony Cheng set_vendor_info_packet(&info->vendor, pipe_ctx->stream); 26326e4d6beeSTony Cheng 26336e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 26346e4d6beeSTony Cheng 263556ef6ed9SAnthony Koo set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 26366e4d6beeSTony Cheng 2637a33fa99dSHarry Wentland } else if (dc_is_dp_signal(signal)) { 26386e4d6beeSTony Cheng set_vsc_info_packet(&info->vsc, pipe_ctx->stream); 26396e4d6beeSTony Cheng 26406e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 26416e4d6beeSTony Cheng 264256ef6ed9SAnthony Koo set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 2643a33fa99dSHarry Wentland } 26444562236bSHarry Wentland 26456e4d6beeSTony Cheng patch_gamut_packet_checksum(&info->gamut); 26464562236bSHarry Wentland } 26474562236bSHarry Wentland 26484562236bSHarry Wentland enum dc_status resource_map_clock_resources( 2649fb3466a4SBhawanpreet Lakha const struct dc *dc, 2650608ac7bbSJerry Zuo struct dc_state *context, 26511dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 26524562236bSHarry Wentland { 26534562236bSHarry Wentland /* acquire new resources */ 26541dc90497SAndrey Grodzovsky const struct resource_pool *pool = dc->res_pool; 26551dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream( 26561dc90497SAndrey Grodzovsky &context->res_ctx, stream); 26574562236bSHarry Wentland 26581dc90497SAndrey Grodzovsky if (!pipe_ctx) 26591dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 26604562236bSHarry Wentland 26614562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal) 26624562236bSHarry Wentland || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) 2663a2b8659dSTony Cheng pipe_ctx->clock_source = pool->dp_clock_source; 26644562236bSHarry Wentland else { 26654562236bSHarry Wentland pipe_ctx->clock_source = NULL; 26664562236bSHarry Wentland 2667fb3466a4SBhawanpreet Lakha if (!dc->config.disable_disp_pll_sharing) 26684ed4e51bSMikita Lipski pipe_ctx->clock_source = resource_find_used_clk_src_for_sharing( 26694562236bSHarry Wentland &context->res_ctx, 26704562236bSHarry Wentland pipe_ctx); 26714562236bSHarry Wentland 26724562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 26734562236bSHarry Wentland pipe_ctx->clock_source = 2674a2b8659dSTony Cheng dc_resource_find_first_free_pll( 2675a2b8659dSTony Cheng &context->res_ctx, 2676a2b8659dSTony Cheng pool); 26774562236bSHarry Wentland } 26784562236bSHarry Wentland 26794562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 26804562236bSHarry Wentland return DC_NO_CLOCK_SOURCE_RESOURCE; 26814562236bSHarry Wentland 26824562236bSHarry Wentland resource_reference_clock_source( 2683a2b8659dSTony Cheng &context->res_ctx, pool, 26844562236bSHarry Wentland pipe_ctx->clock_source); 26854562236bSHarry Wentland 26864562236bSHarry Wentland return DC_OK; 26874562236bSHarry Wentland } 26884562236bSHarry Wentland 26894562236bSHarry Wentland /* 26904562236bSHarry Wentland * Note: We need to disable output if clock sources change, 26914562236bSHarry Wentland * since bios does optimization and doesn't apply if changing 26924562236bSHarry Wentland * PHY when not already disabled. 26934562236bSHarry Wentland */ 26944562236bSHarry Wentland bool pipe_need_reprogram( 26954562236bSHarry Wentland struct pipe_ctx *pipe_ctx_old, 26964562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 26974562236bSHarry Wentland { 2698cfe4645eSDmytro Laktyushkin if (!pipe_ctx_old->stream) 2699cfe4645eSDmytro Laktyushkin return false; 2700cfe4645eSDmytro Laktyushkin 27014562236bSHarry Wentland if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink) 27024562236bSHarry Wentland return true; 27034562236bSHarry Wentland 27044562236bSHarry Wentland if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal) 27054562236bSHarry Wentland return true; 27064562236bSHarry Wentland 2707afaacef4SHarry Wentland if (pipe_ctx_old->stream_res.audio != pipe_ctx->stream_res.audio) 27084562236bSHarry Wentland return true; 27094562236bSHarry Wentland 27104562236bSHarry Wentland if (pipe_ctx_old->clock_source != pipe_ctx->clock_source 27114562236bSHarry Wentland && pipe_ctx_old->stream != pipe_ctx->stream) 27124562236bSHarry Wentland return true; 27134562236bSHarry Wentland 27148e9c4c8cSHarry Wentland if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc) 27154562236bSHarry Wentland return true; 27164562236bSHarry Wentland 27174562236bSHarry Wentland if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 27184562236bSHarry Wentland return true; 27194562236bSHarry Wentland 27206b622181SJulian Parkin if (is_hdr_static_meta_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 27216b622181SJulian Parkin return true; 27224562236bSHarry Wentland 27231e7e86c4SSamson Tam if (pipe_ctx_old->stream->dpms_off != pipe_ctx->stream->dpms_off) 27241e7e86c4SSamson Tam return true; 27251e7e86c4SSamson Tam 27261336926fSAlvin lee if (is_vsc_info_packet_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 27271336926fSAlvin lee return true; 27281336926fSAlvin lee 2729eed928dcSCharlene Liu if (false == pipe_ctx_old->stream->link->link_state_valid && 2730eed928dcSCharlene Liu false == pipe_ctx_old->stream->dpms_off) 2731eed928dcSCharlene Liu return true; 2732eed928dcSCharlene Liu 27334562236bSHarry Wentland return false; 27344562236bSHarry Wentland } 2735529cad0fSDing Wang 27360971c40eSHarry Wentland void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, 2737529cad0fSDing Wang struct bit_depth_reduction_params *fmt_bit_depth) 2738529cad0fSDing Wang { 27394fa086b9SLeo (Sunpeng) Li enum dc_dither_option option = stream->dither_option; 2740529cad0fSDing Wang enum dc_pixel_encoding pixel_encoding = 27414fa086b9SLeo (Sunpeng) Li stream->timing.pixel_encoding; 2742529cad0fSDing Wang 2743529cad0fSDing Wang memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); 2744529cad0fSDing Wang 2745603767f9STony Cheng if (option == DITHER_OPTION_DEFAULT) { 2746603767f9STony Cheng switch (stream->timing.display_color_depth) { 2747603767f9STony Cheng case COLOR_DEPTH_666: 2748603767f9STony Cheng option = DITHER_OPTION_SPATIAL6; 2749603767f9STony Cheng break; 2750603767f9STony Cheng case COLOR_DEPTH_888: 2751603767f9STony Cheng option = DITHER_OPTION_SPATIAL8; 2752603767f9STony Cheng break; 2753603767f9STony Cheng case COLOR_DEPTH_101010: 2754603767f9STony Cheng option = DITHER_OPTION_SPATIAL10; 2755603767f9STony Cheng break; 2756603767f9STony Cheng default: 2757603767f9STony Cheng option = DITHER_OPTION_DISABLE; 2758603767f9STony Cheng } 2759603767f9STony Cheng } 2760603767f9STony Cheng 2761529cad0fSDing Wang if (option == DITHER_OPTION_DISABLE) 2762529cad0fSDing Wang return; 2763529cad0fSDing Wang 2764529cad0fSDing Wang if (option == DITHER_OPTION_TRUN6) { 2765529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2766529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 0; 2767529cad0fSDing Wang } else if (option == DITHER_OPTION_TRUN8 || 2768529cad0fSDing Wang option == DITHER_OPTION_TRUN8_SPATIAL6 || 2769529cad0fSDing Wang option == DITHER_OPTION_TRUN8_FM6) { 2770529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2771529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 1; 2772529cad0fSDing Wang } else if (option == DITHER_OPTION_TRUN10 || 2773529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL6 || 2774529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8 || 2775529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM8 || 2776529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM6 || 2777529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2778529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2779529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2780529cad0fSDing Wang } 2781529cad0fSDing Wang 2782529cad0fSDing Wang /* special case - Formatter can only reduce by 4 bits at most. 2783529cad0fSDing Wang * When reducing from 12 to 6 bits, 2784529cad0fSDing Wang * HW recommends we use trunc with round mode 2785529cad0fSDing Wang * (if we did nothing, trunc to 10 bits would be used) 2786529cad0fSDing Wang * note that any 12->10 bit reduction is ignored prior to DCE8, 2787529cad0fSDing Wang * as the input was 10 bits. 2788529cad0fSDing Wang */ 2789529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2790529cad0fSDing Wang option == DITHER_OPTION_SPATIAL6 || 2791529cad0fSDing Wang option == DITHER_OPTION_FM6) { 2792529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2793529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2794529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_MODE = 1; 2795529cad0fSDing Wang } 2796529cad0fSDing Wang 2797529cad0fSDing Wang /* spatial dither 2798529cad0fSDing Wang * note that spatial modes 1-3 are never used 2799529cad0fSDing Wang */ 2800529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2801529cad0fSDing Wang option == DITHER_OPTION_SPATIAL6 || 2802529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL6 || 2803529cad0fSDing Wang option == DITHER_OPTION_TRUN8_SPATIAL6) { 2804529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2805529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0; 2806529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2807529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2808529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2809529cad0fSDing Wang } else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM || 2810529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8 || 2811529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8_FM6 || 2812529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8 || 2813529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2814529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2815529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1; 2816529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2817529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2818529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2819529cad0fSDing Wang } else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM || 2820529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10 || 2821529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM8 || 2822529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM6) { 2823529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2824529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2; 2825529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2826529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2827529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2828529cad0fSDing Wang } 2829529cad0fSDing Wang 2830529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6 || 2831529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8 || 2832529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10) { 2833529cad0fSDing Wang fmt_bit_depth->flags.FRAME_RANDOM = 0; 2834529cad0fSDing Wang } else { 2835529cad0fSDing Wang fmt_bit_depth->flags.FRAME_RANDOM = 1; 2836529cad0fSDing Wang } 2837529cad0fSDing Wang 2838529cad0fSDing Wang ////////////////////// 2839529cad0fSDing Wang //// temporal dither 2840529cad0fSDing Wang ////////////////////// 2841529cad0fSDing Wang if (option == DITHER_OPTION_FM6 || 2842529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8_FM6 || 2843529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM6 || 2844529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM6 || 2845529cad0fSDing Wang option == DITHER_OPTION_TRUN8_FM6 || 2846529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2847529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2848529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0; 2849529cad0fSDing Wang } else if (option == DITHER_OPTION_FM8 || 2850529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM8 || 2851529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM8) { 2852529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2853529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1; 2854529cad0fSDing Wang } else if (option == DITHER_OPTION_FM10) { 2855529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2856529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2; 2857529cad0fSDing Wang } 2858529cad0fSDing Wang 2859529cad0fSDing Wang fmt_bit_depth->pixel_encoding = pixel_encoding; 2860529cad0fSDing Wang } 28619345d987SAndrey Grodzovsky 286262c933f9SYongqiang Sun enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) 28639345d987SAndrey Grodzovsky { 2864ceb3dbb4SJun Lei struct dc_link *link = stream->link; 28652b77dcc5SAnthony Koo struct timing_generator *tg = dc->res_pool->timing_generators[0]; 28669345d987SAndrey Grodzovsky enum dc_status res = DC_OK; 28679345d987SAndrey Grodzovsky 28684fa086b9SLeo (Sunpeng) Li calculate_phy_pix_clks(stream); 28699345d987SAndrey Grodzovsky 28704fa086b9SLeo (Sunpeng) Li if (!tg->funcs->validate_timing(tg, &stream->timing)) 28719345d987SAndrey Grodzovsky res = DC_FAIL_CONTROLLER_VALIDATE; 28729345d987SAndrey Grodzovsky 2873248cbed6SEric Bernstein if (res == DC_OK) { 28749345d987SAndrey Grodzovsky if (!link->link_enc->funcs->validate_output_with_stream( 28754fa086b9SLeo (Sunpeng) Li link->link_enc, stream)) 28769345d987SAndrey Grodzovsky res = DC_FAIL_ENC_VALIDATE; 2877248cbed6SEric Bernstein } 28789345d987SAndrey Grodzovsky 28799345d987SAndrey Grodzovsky /* TODO: validate audio ASIC caps, encoder */ 28809345d987SAndrey Grodzovsky 28819345d987SAndrey Grodzovsky if (res == DC_OK) 28824fa086b9SLeo (Sunpeng) Li res = dc_link_validate_mode_timing(stream, 28839345d987SAndrey Grodzovsky link, 28844fa086b9SLeo (Sunpeng) Li &stream->timing); 28859345d987SAndrey Grodzovsky 288662c933f9SYongqiang Sun return res; 28879345d987SAndrey Grodzovsky } 2888792671d7SAndrey Grodzovsky 288962c933f9SYongqiang Sun enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) 2890792671d7SAndrey Grodzovsky { 289162c933f9SYongqiang Sun enum dc_status res = DC_OK; 289262c933f9SYongqiang Sun 2893792671d7SAndrey Grodzovsky /* TODO For now validates pixel format only */ 28948e7095b9SDmytro Laktyushkin if (dc->res_pool->funcs->validate_plane) 289562c933f9SYongqiang Sun return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps); 2896792671d7SAndrey Grodzovsky 289762c933f9SYongqiang Sun return res; 2898792671d7SAndrey Grodzovsky } 289974eac5f3SSu Sung Chung 290074eac5f3SSu Sung Chung unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format) 290174eac5f3SSu Sung Chung { 290274eac5f3SSu Sung Chung switch (format) { 290374eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 290474eac5f3SSu Sung Chung return 8; 290574eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 290674eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 290774eac5f3SSu Sung Chung return 12; 290874eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 290974eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 291074eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 291174eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 291274eac5f3SSu Sung Chung return 16; 291374eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 291474eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 291574eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 291674eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 291774eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 291874eac5f3SSu Sung Chung return 32; 291974eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 292074eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 292174eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 292274eac5f3SSu Sung Chung return 64; 292374eac5f3SSu Sung Chung default: 292474eac5f3SSu Sung Chung ASSERT_CRITICAL(false); 292574eac5f3SSu Sung Chung return -1; 292674eac5f3SSu Sung Chung } 292774eac5f3SSu Sung Chung } 29283ab4cc65SCharlene Liu static unsigned int get_max_audio_sample_rate(struct audio_mode *modes) 29293ab4cc65SCharlene Liu { 29303ab4cc65SCharlene Liu if (modes) { 29313ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_192) 29323ab4cc65SCharlene Liu return 192000; 29333ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_176_4) 29343ab4cc65SCharlene Liu return 176400; 29353ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_96) 29363ab4cc65SCharlene Liu return 96000; 29373ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_88_2) 29383ab4cc65SCharlene Liu return 88200; 29393ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_48) 29403ab4cc65SCharlene Liu return 48000; 29413ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_44_1) 29423ab4cc65SCharlene Liu return 44100; 29433ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_32) 29443ab4cc65SCharlene Liu return 32000; 29453ab4cc65SCharlene Liu } 29463ab4cc65SCharlene Liu /*original logic when no audio info*/ 29473ab4cc65SCharlene Liu return 441000; 29483ab4cc65SCharlene Liu } 29493ab4cc65SCharlene Liu 29503ab4cc65SCharlene Liu void get_audio_check(struct audio_info *aud_modes, 29513ab4cc65SCharlene Liu struct audio_check *audio_chk) 29523ab4cc65SCharlene Liu { 29533ab4cc65SCharlene Liu unsigned int i; 29543ab4cc65SCharlene Liu unsigned int max_sample_rate = 0; 29553ab4cc65SCharlene Liu 29563ab4cc65SCharlene Liu if (aud_modes) { 29573ab4cc65SCharlene Liu audio_chk->audio_packet_type = 0x2;/*audio sample packet AP = .25 for layout0, 1 for layout1*/ 29583ab4cc65SCharlene Liu 29593ab4cc65SCharlene Liu audio_chk->max_audiosample_rate = 0; 29603ab4cc65SCharlene Liu for (i = 0; i < aud_modes->mode_count; i++) { 29613ab4cc65SCharlene Liu max_sample_rate = get_max_audio_sample_rate(&aud_modes->modes[i]); 29623ab4cc65SCharlene Liu if (audio_chk->max_audiosample_rate < max_sample_rate) 29633ab4cc65SCharlene Liu audio_chk->max_audiosample_rate = max_sample_rate; 29643ab4cc65SCharlene Liu /*dts takes the same as type 2: AP = 0.25*/ 29653ab4cc65SCharlene Liu } 29663ab4cc65SCharlene Liu /*check which one take more bandwidth*/ 29673ab4cc65SCharlene Liu if (audio_chk->max_audiosample_rate > 192000) 29683ab4cc65SCharlene Liu audio_chk->audio_packet_type = 0x9;/*AP =1*/ 29693ab4cc65SCharlene Liu audio_chk->acat = 0;/*not support*/ 29703ab4cc65SCharlene Liu } 29713ab4cc65SCharlene Liu } 29723ab4cc65SCharlene Liu 2973