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; 695fa90219aSDmytro Laktyushkin 696fa90219aSDmytro Laktyushkin data->viewport_unadjusted = data->viewport; 697fa90219aSDmytro Laktyushkin data->viewport_c_unadjusted = data->viewport_c; 698b2d0a103SDmytro Laktyushkin } 6991fbd2cfcSDmytro Laktyushkin 7009b6067c0SDmytro Laktyushkin static void calculate_recout(struct pipe_ctx *pipe_ctx) 7014562236bSHarry Wentland { 7023be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 7030971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 7045bf24270SDmytro Laktyushkin struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 7053be5262eSHarry Wentland struct rect surf_clip = plane_state->clip_rect; 7065bf24270SDmytro Laktyushkin bool pri_split_tb = pipe_ctx->bottom_pipe && 7075bf24270SDmytro Laktyushkin pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state && 7085bf24270SDmytro Laktyushkin stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; 7095bf24270SDmytro Laktyushkin bool sec_split_tb = pipe_ctx->top_pipe && 7105bf24270SDmytro Laktyushkin pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state && 7115bf24270SDmytro Laktyushkin stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; 7125bf24270SDmytro Laktyushkin int split_count = 0; 7135bf24270SDmytro Laktyushkin int split_idx = 0; 7144562236bSHarry Wentland 7155bf24270SDmytro Laktyushkin calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); 7165bf24270SDmytro Laktyushkin 7175bf24270SDmytro Laktyushkin data->recout.x = stream->dst.x; 7184fa086b9SLeo (Sunpeng) Li if (stream->src.x < surf_clip.x) 7195bf24270SDmytro Laktyushkin data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width 7204fa086b9SLeo (Sunpeng) Li / stream->src.width; 7214562236bSHarry Wentland 7225bf24270SDmytro Laktyushkin data->recout.width = surf_clip.width * stream->dst.width / stream->src.width; 7235bf24270SDmytro Laktyushkin if (data->recout.width + data->recout.x > stream->dst.x + stream->dst.width) 7245bf24270SDmytro Laktyushkin data->recout.width = stream->dst.x + stream->dst.width - data->recout.x; 7254562236bSHarry Wentland 7265bf24270SDmytro Laktyushkin data->recout.y = stream->dst.y; 7274fa086b9SLeo (Sunpeng) Li if (stream->src.y < surf_clip.y) 7285bf24270SDmytro Laktyushkin data->recout.y += (surf_clip.y - stream->src.y) * stream->dst.height 7294fa086b9SLeo (Sunpeng) Li / stream->src.height; 7304562236bSHarry Wentland 7315bf24270SDmytro Laktyushkin data->recout.height = surf_clip.height * stream->dst.height / stream->src.height; 7325bf24270SDmytro Laktyushkin if (data->recout.height + data->recout.y > stream->dst.y + stream->dst.height) 7335bf24270SDmytro Laktyushkin data->recout.height = stream->dst.y + stream->dst.height - data->recout.y; 734b2d0a103SDmytro Laktyushkin 7359b6067c0SDmytro Laktyushkin /* Handle h & v split, handle rotation using viewport */ 7365bf24270SDmytro Laktyushkin if (sec_split_tb) { 7375bf24270SDmytro Laktyushkin data->recout.y += data->recout.height / 2; 7387b779c99SVitaly Prosyak /* Floor primary pipe, ceil 2ndary pipe */ 7395bf24270SDmytro Laktyushkin data->recout.height = (data->recout.height + 1) / 2; 7405bf24270SDmytro Laktyushkin } else if (pri_split_tb) 7415bf24270SDmytro Laktyushkin data->recout.height /= 2; 7425bf24270SDmytro Laktyushkin else if (split_count) { 7435bf24270SDmytro Laktyushkin /* extra pixels in the division remainder need to go to pipes after 7445bf24270SDmytro Laktyushkin * the extra pixel index minus one(epimo) defined here as: 7455bf24270SDmytro Laktyushkin */ 7465bf24270SDmytro Laktyushkin int epimo = split_count - data->recout.width % (split_count + 1); 7475bf24270SDmytro Laktyushkin 7485bf24270SDmytro Laktyushkin /*no recout offset due to odm */ 7495bf24270SDmytro Laktyushkin if (!pipe_ctx->next_odm_pipe && !pipe_ctx->prev_odm_pipe) { 7505bf24270SDmytro Laktyushkin data->recout.x += (data->recout.width / (split_count + 1)) * split_idx; 7515bf24270SDmytro Laktyushkin if (split_idx > epimo) 7525bf24270SDmytro Laktyushkin data->recout.x += split_idx - epimo - 1; 7535bf24270SDmytro Laktyushkin } 7545bf24270SDmytro Laktyushkin data->recout.width = data->recout.width / (split_count + 1) + (split_idx > epimo ? 1 : 0); 7555bf24270SDmytro Laktyushkin } 7564562236bSHarry Wentland } 757b2d0a103SDmytro Laktyushkin 758b2d0a103SDmytro Laktyushkin static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) 7594562236bSHarry Wentland { 7603be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 7610971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 7623be5262eSHarry Wentland struct rect surf_src = plane_state->src_rect; 7634fa086b9SLeo (Sunpeng) Li const int in_w = stream->src.width; 7644fa086b9SLeo (Sunpeng) Li const int in_h = stream->src.height; 7654fa086b9SLeo (Sunpeng) Li const int out_w = stream->dst.width; 7664fa086b9SLeo (Sunpeng) Li const int out_h = stream->dst.height; 7674562236bSHarry Wentland 7689b6067c0SDmytro Laktyushkin /*Swap surf_src height and width since scaling ratios are in recout rotation*/ 7693be5262eSHarry Wentland if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 7703be5262eSHarry Wentland pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 7719b6067c0SDmytro Laktyushkin swap(surf_src.height, surf_src.width); 77286006a7fSDmytro Laktyushkin 773eb0e5154SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_from_fraction( 77486006a7fSDmytro Laktyushkin surf_src.width, 7753be5262eSHarry Wentland plane_state->dst_rect.width); 776eb0e5154SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_from_fraction( 77786006a7fSDmytro Laktyushkin surf_src.height, 7783be5262eSHarry Wentland plane_state->dst_rect.height); 7794562236bSHarry Wentland 7804fa086b9SLeo (Sunpeng) Li if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) 7816702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value *= 2; 7824fa086b9SLeo (Sunpeng) Li else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) 7836702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value *= 2; 7844562236bSHarry Wentland 7856702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value = div64_s64( 7866702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value * in_h, out_h); 7876702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value = div64_s64( 7886702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value * in_w, out_w); 7894562236bSHarry Wentland 7906702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz_c = pipe_ctx->plane_res.scl_data.ratios.horz; 7916702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert_c = pipe_ctx->plane_res.scl_data.ratios.vert; 7924562236bSHarry Wentland 7936702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP8 7946702a9acSHarry Wentland || pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP10) { 7956702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz_c.value /= 2; 7966702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert_c.value /= 2; 7974562236bSHarry Wentland } 7980002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_truncate( 7990002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz, 19); 8000002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_truncate( 8010002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert, 19); 8020002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz_c = dc_fixpt_truncate( 8030002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz_c, 19); 8040002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert_c = dc_fixpt_truncate( 8050002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert_c, 19); 8064562236bSHarry Wentland } 8074562236bSHarry Wentland 8089b6067c0SDmytro Laktyushkin static inline void adjust_vp_and_init_for_seamless_clip( 8099b6067c0SDmytro Laktyushkin bool flip_scan_dir, 8109b6067c0SDmytro Laktyushkin int recout_skip, 8119b6067c0SDmytro Laktyushkin int src_size, 8129b6067c0SDmytro Laktyushkin int taps, 8139b6067c0SDmytro Laktyushkin struct fixed31_32 ratio, 8149b6067c0SDmytro Laktyushkin struct fixed31_32 *init, 8159b6067c0SDmytro Laktyushkin int *vp_offset, 8169b6067c0SDmytro Laktyushkin int *vp_size) 8174562236bSHarry Wentland { 8189b6067c0SDmytro Laktyushkin if (!flip_scan_dir) { 8199b6067c0SDmytro Laktyushkin /* Adjust for viewport end clip-off */ 8209b6067c0SDmytro Laktyushkin if ((*vp_offset + *vp_size) < src_size) { 8219b6067c0SDmytro Laktyushkin int vp_clip = src_size - *vp_size - *vp_offset; 8229b6067c0SDmytro Laktyushkin int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio)); 8239b6067c0SDmytro Laktyushkin 8249b6067c0SDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 8259b6067c0SDmytro Laktyushkin *vp_size += int_part < vp_clip ? int_part : vp_clip; 8269b6067c0SDmytro Laktyushkin } 8279b6067c0SDmytro Laktyushkin 8289b6067c0SDmytro Laktyushkin /* Adjust for non-0 viewport offset */ 8299b6067c0SDmytro Laktyushkin if (*vp_offset) { 8309b6067c0SDmytro Laktyushkin int int_part; 8319b6067c0SDmytro Laktyushkin 8329b6067c0SDmytro Laktyushkin *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip)); 8339b6067c0SDmytro Laktyushkin int_part = dc_fixpt_floor(*init) - *vp_offset; 8349b6067c0SDmytro Laktyushkin if (int_part < taps) { 8359b6067c0SDmytro Laktyushkin int int_adj = *vp_offset >= (taps - int_part) ? 8369b6067c0SDmytro Laktyushkin (taps - int_part) : *vp_offset; 8379b6067c0SDmytro Laktyushkin *vp_offset -= int_adj; 8389b6067c0SDmytro Laktyushkin *vp_size += int_adj; 8399b6067c0SDmytro Laktyushkin int_part += int_adj; 8409b6067c0SDmytro Laktyushkin } else if (int_part > taps) { 8419b6067c0SDmytro Laktyushkin *vp_offset += int_part - taps; 8429b6067c0SDmytro Laktyushkin *vp_size -= int_part - taps; 8439b6067c0SDmytro Laktyushkin int_part = taps; 8449b6067c0SDmytro Laktyushkin } 8459b6067c0SDmytro Laktyushkin init->value &= 0xffffffff; 8469b6067c0SDmytro Laktyushkin *init = dc_fixpt_add_int(*init, int_part); 8479b6067c0SDmytro Laktyushkin } 8489b6067c0SDmytro Laktyushkin } else { 8499b6067c0SDmytro Laktyushkin /* Adjust for non-0 viewport offset */ 8509b6067c0SDmytro Laktyushkin if (*vp_offset) { 8519b6067c0SDmytro Laktyushkin int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio)); 8529b6067c0SDmytro Laktyushkin 8539b6067c0SDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 8549b6067c0SDmytro Laktyushkin *vp_size += int_part < *vp_offset ? int_part : *vp_offset; 8559b6067c0SDmytro Laktyushkin *vp_offset -= int_part < *vp_offset ? int_part : *vp_offset; 8569b6067c0SDmytro Laktyushkin } 8579b6067c0SDmytro Laktyushkin 8589b6067c0SDmytro Laktyushkin /* Adjust for viewport end clip-off */ 8599b6067c0SDmytro Laktyushkin if ((*vp_offset + *vp_size) < src_size) { 8609b6067c0SDmytro Laktyushkin int int_part; 8619b6067c0SDmytro Laktyushkin int end_offset = src_size - *vp_offset - *vp_size; 8629b6067c0SDmytro Laktyushkin 8639b6067c0SDmytro Laktyushkin /* 8649b6067c0SDmytro Laktyushkin * this is init if vp had no offset, keep in mind this is from the 8659b6067c0SDmytro Laktyushkin * right side of vp due to scan direction 8669b6067c0SDmytro Laktyushkin */ 8679b6067c0SDmytro Laktyushkin *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip)); 8689b6067c0SDmytro Laktyushkin /* 8699b6067c0SDmytro Laktyushkin * this is the difference between first pixel of viewport available to read 8709b6067c0SDmytro Laktyushkin * and init position, takning into account scan direction 8719b6067c0SDmytro Laktyushkin */ 8729b6067c0SDmytro Laktyushkin int_part = dc_fixpt_floor(*init) - end_offset; 8739b6067c0SDmytro Laktyushkin if (int_part < taps) { 8749b6067c0SDmytro Laktyushkin int int_adj = end_offset >= (taps - int_part) ? 8759b6067c0SDmytro Laktyushkin (taps - int_part) : end_offset; 8769b6067c0SDmytro Laktyushkin *vp_size += int_adj; 8779b6067c0SDmytro Laktyushkin int_part += int_adj; 8789b6067c0SDmytro Laktyushkin } else if (int_part > taps) { 8799b6067c0SDmytro Laktyushkin *vp_size += int_part - taps; 8809b6067c0SDmytro Laktyushkin int_part = taps; 8819b6067c0SDmytro Laktyushkin } 8829b6067c0SDmytro Laktyushkin init->value &= 0xffffffff; 8839b6067c0SDmytro Laktyushkin *init = dc_fixpt_add_int(*init, int_part); 8849b6067c0SDmytro Laktyushkin } 8859b6067c0SDmytro Laktyushkin } 8869b6067c0SDmytro Laktyushkin } 8879b6067c0SDmytro Laktyushkin 8889b6067c0SDmytro Laktyushkin static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx) 8899b6067c0SDmytro Laktyushkin { 8909b6067c0SDmytro Laktyushkin const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 8919b6067c0SDmytro Laktyushkin const struct dc_stream_state *stream = pipe_ctx->stream; 8925bf24270SDmytro Laktyushkin struct pipe_ctx *odm_pipe = pipe_ctx->prev_odm_pipe; 8936702a9acSHarry Wentland struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 8943be5262eSHarry Wentland struct rect src = pipe_ctx->plane_state->src_rect; 8959b6067c0SDmytro Laktyushkin int recout_skip_h, recout_skip_v, surf_size_h, surf_size_v; 89687449a90SAnthony Koo int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 89787449a90SAnthony Koo || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 8989b6067c0SDmytro Laktyushkin bool orthogonal_rotation, flip_vert_scan_dir, flip_horz_scan_dir; 8997287a675SDmytro Laktyushkin int odm_idx = 0; 900b2d0a103SDmytro Laktyushkin 901b0131391SDmytro Laktyushkin /* 902b0131391SDmytro Laktyushkin * Need to calculate the scan direction for viewport to make adjustments 903b0131391SDmytro Laktyushkin */ 9049b6067c0SDmytro Laktyushkin get_vp_scan_direction( 9059b6067c0SDmytro Laktyushkin plane_state->rotation, 9069b6067c0SDmytro Laktyushkin plane_state->horizontal_mirror, 9079b6067c0SDmytro Laktyushkin &orthogonal_rotation, 9089b6067c0SDmytro Laktyushkin &flip_vert_scan_dir, 9099b6067c0SDmytro Laktyushkin &flip_horz_scan_dir); 910b0131391SDmytro Laktyushkin 9119b6067c0SDmytro Laktyushkin /* Calculate src rect rotation adjusted to recout space */ 9129b6067c0SDmytro Laktyushkin surf_size_h = src.x + src.width; 9139b6067c0SDmytro Laktyushkin surf_size_v = src.y + src.height; 9149b6067c0SDmytro Laktyushkin if (flip_horz_scan_dir) 9159b6067c0SDmytro Laktyushkin src.x = 0; 9169b6067c0SDmytro Laktyushkin if (flip_vert_scan_dir) 9179b6067c0SDmytro Laktyushkin src.y = 0; 9189b6067c0SDmytro Laktyushkin if (orthogonal_rotation) { 9199b6067c0SDmytro Laktyushkin swap(src.x, src.y); 9209b6067c0SDmytro Laktyushkin swap(src.width, src.height); 9219b5349f7SMartin Tsai } 9221fbd2cfcSDmytro Laktyushkin 9239b6067c0SDmytro Laktyushkin /* Recout matching initial vp offset = recout_offset - (stream dst offset + 9249b6067c0SDmytro Laktyushkin * ((surf dst offset - stream src offset) * 1/ stream scaling ratio) 9259b6067c0SDmytro Laktyushkin * - (surf surf_src offset * 1/ full scl ratio)) 9269b6067c0SDmytro Laktyushkin */ 9279b6067c0SDmytro Laktyushkin recout_skip_h = data->recout.x - (stream->dst.x + (plane_state->dst_rect.x - stream->src.x) 9289b6067c0SDmytro Laktyushkin * stream->dst.width / stream->src.width - 9299b6067c0SDmytro Laktyushkin src.x * plane_state->dst_rect.width / src.width 9309b6067c0SDmytro Laktyushkin * stream->dst.width / stream->src.width); 9317287a675SDmytro Laktyushkin /*modified recout_skip_h calculation due to odm having no recout offset*/ 9325bf24270SDmytro Laktyushkin while (odm_pipe) { 9337287a675SDmytro Laktyushkin odm_idx++; 9345bf24270SDmytro Laktyushkin odm_pipe = odm_pipe->prev_odm_pipe; 9355bf24270SDmytro Laktyushkin } 9367287a675SDmytro Laktyushkin if (odm_idx) 9377287a675SDmytro Laktyushkin recout_skip_h += odm_idx * data->recout.width; 9385bf24270SDmytro Laktyushkin 9399b6067c0SDmytro Laktyushkin recout_skip_v = data->recout.y - (stream->dst.y + (plane_state->dst_rect.y - stream->src.y) 9409b6067c0SDmytro Laktyushkin * stream->dst.height / stream->src.height - 9419b6067c0SDmytro Laktyushkin src.y * plane_state->dst_rect.height / src.height 9429b6067c0SDmytro Laktyushkin * stream->dst.height / stream->src.height); 9439b6067c0SDmytro Laktyushkin if (orthogonal_rotation) 9449b6067c0SDmytro Laktyushkin swap(recout_skip_h, recout_skip_v); 945b2d0a103SDmytro Laktyushkin /* 946b2d0a103SDmytro Laktyushkin * Init calculated according to formula: 947b2d0a103SDmytro Laktyushkin * init = (scaling_ratio + number_of_taps + 1) / 2 948b2d0a103SDmytro Laktyushkin * init_bot = init + scaling_ratio 949b2d0a103SDmytro Laktyushkin * init_c = init + truncated_vp_c_offset(from calculate viewport) 950b2d0a103SDmytro Laktyushkin */ 9510002d3acSDmytro Laktyushkin data->inits.h = dc_fixpt_truncate(dc_fixpt_div_int( 9520002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.horz, data->taps.h_taps + 1), 2), 19); 953b2d0a103SDmytro Laktyushkin 9540002d3acSDmytro Laktyushkin data->inits.h_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.h_c, dc_fixpt_div_int( 9550002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.horz_c, data->taps.h_taps_c + 1), 2)), 19); 956b2d0a103SDmytro Laktyushkin 9570002d3acSDmytro Laktyushkin data->inits.v = dc_fixpt_truncate(dc_fixpt_div_int( 9580002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.vert, data->taps.v_taps + 1), 2), 19); 959b2d0a103SDmytro Laktyushkin 9600002d3acSDmytro Laktyushkin data->inits.v_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.v_c, dc_fixpt_div_int( 9610002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2)), 19); 9620002d3acSDmytro Laktyushkin 9639a08f51fSDmytro Laktyushkin /* 9649b6067c0SDmytro Laktyushkin * Taps, inits and scaling ratios are in recout space need to rotate 9659b6067c0SDmytro Laktyushkin * to viewport rotation before adjustment 9669a08f51fSDmytro Laktyushkin */ 9679b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 9689b6067c0SDmytro Laktyushkin flip_horz_scan_dir, 9699b6067c0SDmytro Laktyushkin recout_skip_h, 9709b6067c0SDmytro Laktyushkin surf_size_h, 9719b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.v_taps : data->taps.h_taps, 9729b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.vert : data->ratios.horz, 9739b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.v : &data->inits.h, 9749b6067c0SDmytro Laktyushkin &data->viewport.x, 9759b6067c0SDmytro Laktyushkin &data->viewport.width); 9769b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 9779b6067c0SDmytro Laktyushkin flip_horz_scan_dir, 9789b6067c0SDmytro Laktyushkin recout_skip_h, 9799b6067c0SDmytro Laktyushkin surf_size_h / vpc_div, 9809b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.v_taps_c : data->taps.h_taps_c, 9819b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.vert_c : data->ratios.horz_c, 9829b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.v_c : &data->inits.h_c, 9839b6067c0SDmytro Laktyushkin &data->viewport_c.x, 9849b6067c0SDmytro Laktyushkin &data->viewport_c.width); 9859b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 9869b6067c0SDmytro Laktyushkin flip_vert_scan_dir, 9879b6067c0SDmytro Laktyushkin recout_skip_v, 9889b6067c0SDmytro Laktyushkin surf_size_v, 9899b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.h_taps : data->taps.v_taps, 9909b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.horz : data->ratios.vert, 9919b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.h : &data->inits.v, 9929b6067c0SDmytro Laktyushkin &data->viewport.y, 9939b6067c0SDmytro Laktyushkin &data->viewport.height); 9949b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 9959b6067c0SDmytro Laktyushkin flip_vert_scan_dir, 9969b6067c0SDmytro Laktyushkin recout_skip_v, 9979b6067c0SDmytro Laktyushkin surf_size_v / vpc_div, 9989b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.h_taps_c : data->taps.v_taps_c, 9999b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.horz_c : data->ratios.vert_c, 10009b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.h_c : &data->inits.v_c, 10019b6067c0SDmytro Laktyushkin &data->viewport_c.y, 10029b6067c0SDmytro Laktyushkin &data->viewport_c.height); 1003b2d0a103SDmytro Laktyushkin 1004b2d0a103SDmytro Laktyushkin /* Interlaced inits based on final vert inits */ 1005eb0e5154SDmytro Laktyushkin data->inits.v_bot = dc_fixpt_add(data->inits.v, data->ratios.vert); 1006eb0e5154SDmytro Laktyushkin data->inits.v_c_bot = dc_fixpt_add(data->inits.v_c, data->ratios.vert_c); 10071fbd2cfcSDmytro Laktyushkin 1008b2d0a103SDmytro Laktyushkin } 10093b733278SReza Amini 101089d07b66SSamson Tam /* 101189d07b66SSamson Tam * When handling 270 rotation in mixed SLS mode, we have 101289d07b66SSamson Tam * stream->timing.h_border_left that is non zero. If we are doing 101389d07b66SSamson Tam * pipe-splitting, this h_border_left value gets added to recout.x and when it 101489d07b66SSamson Tam * calls calculate_inits_and_adj_vp() and 101589d07b66SSamson Tam * adjust_vp_and_init_for_seamless_clip(), it can cause viewport.height for a 101689d07b66SSamson Tam * pipe to be incorrect. 101789d07b66SSamson Tam * 101889d07b66SSamson Tam * To fix this, instead of using stream->timing.h_border_left, we can use 101989d07b66SSamson Tam * stream->dst.x to represent the border instead. So we will set h_border_left 102089d07b66SSamson Tam * to 0 and shift the appropriate amount in stream->dst.x. We will then 102189d07b66SSamson Tam * perform all calculations in resource_build_scaling_params() based on this 102289d07b66SSamson Tam * and then restore the h_border_left and stream->dst.x to their original 102389d07b66SSamson Tam * values. 102489d07b66SSamson Tam * 102589d07b66SSamson Tam * shift_border_left_to_dst() will shift the amount of h_border_left to 102689d07b66SSamson Tam * stream->dst.x and set h_border_left to 0. restore_border_left_from_dst() 102789d07b66SSamson Tam * will restore h_border_left and stream->dst.x back to their original values 102889d07b66SSamson Tam * We also need to make sure pipe_ctx->plane_res.scl_data.h_active uses the 102989d07b66SSamson Tam * original h_border_left value in its calculation. 103089d07b66SSamson Tam */ 103189d07b66SSamson Tam int shift_border_left_to_dst(struct pipe_ctx *pipe_ctx) 103289d07b66SSamson Tam { 103389d07b66SSamson Tam int store_h_border_left = pipe_ctx->stream->timing.h_border_left; 103489d07b66SSamson Tam 103589d07b66SSamson Tam if (store_h_border_left) { 103689d07b66SSamson Tam pipe_ctx->stream->timing.h_border_left = 0; 103789d07b66SSamson Tam pipe_ctx->stream->dst.x += store_h_border_left; 103889d07b66SSamson Tam } 103989d07b66SSamson Tam return store_h_border_left; 104089d07b66SSamson Tam } 104189d07b66SSamson Tam 104289d07b66SSamson Tam void restore_border_left_from_dst(struct pipe_ctx *pipe_ctx, 104389d07b66SSamson Tam int store_h_border_left) 104489d07b66SSamson Tam { 104589d07b66SSamson Tam pipe_ctx->stream->dst.x -= store_h_border_left; 104689d07b66SSamson Tam pipe_ctx->stream->timing.h_border_left = store_h_border_left; 104789d07b66SSamson Tam } 104889d07b66SSamson Tam 1049b2d0a103SDmytro Laktyushkin bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) 1050b2d0a103SDmytro Laktyushkin { 10513be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 10524fa086b9SLeo (Sunpeng) Li struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 1053b2d0a103SDmytro Laktyushkin bool res = false; 105489d07b66SSamson Tam int store_h_border_left = shift_border_left_to_dst(pipe_ctx); 10555d4b05ddSBhawanpreet Lakha DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); 10564562236bSHarry Wentland /* Important: scaling ratio calculation requires pixel format, 10574562236bSHarry Wentland * lb depth calculation requires recout and taps require scaling ratios. 1058b2d0a103SDmytro Laktyushkin * Inits require viewport, taps, ratios and recout of split pipe 10594562236bSHarry Wentland */ 10606702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface( 10613be5262eSHarry Wentland pipe_ctx->plane_state->format); 10624562236bSHarry Wentland 1063b2d0a103SDmytro Laktyushkin calculate_scaling_ratios(pipe_ctx); 1064b2d0a103SDmytro Laktyushkin 1065b2d0a103SDmytro Laktyushkin calculate_viewport(pipe_ctx); 10664562236bSHarry Wentland 106789d07b66SSamson Tam if (pipe_ctx->plane_res.scl_data.viewport.height < 16 || 106889d07b66SSamson Tam pipe_ctx->plane_res.scl_data.viewport.width < 16) { 106989d07b66SSamson Tam if (store_h_border_left) { 107089d07b66SSamson Tam restore_border_left_from_dst(pipe_ctx, 107189d07b66SSamson Tam store_h_border_left); 107289d07b66SSamson Tam } 10734562236bSHarry Wentland return false; 107489d07b66SSamson Tam } 10754562236bSHarry Wentland 10769b6067c0SDmytro Laktyushkin calculate_recout(pipe_ctx); 10774562236bSHarry Wentland 10784562236bSHarry Wentland /** 10794562236bSHarry Wentland * Setting line buffer pixel depth to 24bpp yields banding 10804562236bSHarry Wentland * on certain displays, such as the Sharp 4k 10814562236bSHarry Wentland */ 10826702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; 108333eef72fSEric Bernstein pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha; 10844562236bSHarry Wentland 1085199e458aSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left; 108658bb0e63SAndrew Jiang pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top; 1087199e458aSDmytro Laktyushkin 108889d07b66SSamson Tam pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable + 108989d07b66SSamson Tam store_h_border_left + timing->h_border_right; 109089d07b66SSamson Tam pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + 109189d07b66SSamson Tam timing->v_border_top + timing->v_border_bottom; 10925bf24270SDmytro Laktyushkin if (pipe_ctx->next_odm_pipe || pipe_ctx->prev_odm_pipe) 10935bf24270SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.h_active /= get_num_odm_splits(pipe_ctx) + 1; 10941b6c8067SBhawanpreet Lakha 10954562236bSHarry Wentland /* Taps calculations */ 1096d94585a0SYue Hin Lau if (pipe_ctx->plane_res.xfm != NULL) 109786a66c4eSHarry Wentland res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 109886a66c4eSHarry Wentland pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 10994562236bSHarry Wentland 1100d94585a0SYue Hin Lau if (pipe_ctx->plane_res.dpp != NULL) 1101d94585a0SYue Hin Lau res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 1102d94585a0SYue Hin Lau pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 1103f7938bc0SReza Amini 1104f7938bc0SReza Amini 11054562236bSHarry Wentland if (!res) { 11064562236bSHarry Wentland /* Try 24 bpp linebuffer */ 11076702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; 11084562236bSHarry Wentland 11091b6c8067SBhawanpreet Lakha if (pipe_ctx->plane_res.xfm != NULL) 111086a66c4eSHarry Wentland res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 11111b6c8067SBhawanpreet Lakha pipe_ctx->plane_res.xfm, 11121b6c8067SBhawanpreet Lakha &pipe_ctx->plane_res.scl_data, 11131b6c8067SBhawanpreet Lakha &plane_state->scaling_quality); 1114d94585a0SYue Hin Lau 11151b6c8067SBhawanpreet Lakha if (pipe_ctx->plane_res.dpp != NULL) 1116d94585a0SYue Hin Lau res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 11171b6c8067SBhawanpreet Lakha pipe_ctx->plane_res.dpp, 11181b6c8067SBhawanpreet Lakha &pipe_ctx->plane_res.scl_data, 11191b6c8067SBhawanpreet Lakha &plane_state->scaling_quality); 11204562236bSHarry Wentland } 11214562236bSHarry Wentland 1122b2d0a103SDmytro Laktyushkin if (res) 11231fbd2cfcSDmytro Laktyushkin /* May need to re-check lb size after this in some obscure scenario */ 11249b6067c0SDmytro Laktyushkin calculate_inits_and_adj_vp(pipe_ctx); 1125b2d0a103SDmytro Laktyushkin 11261296423bSBhawanpreet Lakha DC_LOG_SCALER( 11274562236bSHarry Wentland "%s: Viewport:\nheight:%d width:%d x:%d " 11284562236bSHarry Wentland "y:%d\n dst_rect:\nheight:%d width:%d x:%d " 11294562236bSHarry Wentland "y:%d\n", 11304562236bSHarry Wentland __func__, 11316702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.height, 11326702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.width, 11336702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.x, 11346702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.y, 11353be5262eSHarry Wentland plane_state->dst_rect.height, 11363be5262eSHarry Wentland plane_state->dst_rect.width, 11373be5262eSHarry Wentland plane_state->dst_rect.x, 11383be5262eSHarry Wentland plane_state->dst_rect.y); 11394562236bSHarry Wentland 114089d07b66SSamson Tam if (store_h_border_left) 114189d07b66SSamson Tam restore_border_left_from_dst(pipe_ctx, store_h_border_left); 114289d07b66SSamson Tam 11434562236bSHarry Wentland return res; 11444562236bSHarry Wentland } 11454562236bSHarry Wentland 11464562236bSHarry Wentland 11474562236bSHarry Wentland enum dc_status resource_build_scaling_params_for_context( 1148fb3466a4SBhawanpreet Lakha const struct dc *dc, 1149608ac7bbSJerry Zuo struct dc_state *context) 11504562236bSHarry Wentland { 11514562236bSHarry Wentland int i; 11524562236bSHarry Wentland 11534562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 11543be5262eSHarry Wentland if (context->res_ctx.pipe_ctx[i].plane_state != NULL && 11554562236bSHarry Wentland context->res_ctx.pipe_ctx[i].stream != NULL) 1156b2d0a103SDmytro Laktyushkin if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i])) 1157f84a8161STony Cheng return DC_FAIL_SCALING; 11584562236bSHarry Wentland } 11594562236bSHarry Wentland 11604562236bSHarry Wentland return DC_OK; 11614562236bSHarry Wentland } 11624562236bSHarry Wentland 1163a2b8659dSTony Cheng struct pipe_ctx *find_idle_secondary_pipe( 1164a2b8659dSTony Cheng struct resource_context *res_ctx, 11655581192dSJun Lei const struct resource_pool *pool, 11665581192dSJun Lei const struct pipe_ctx *primary_pipe) 11674562236bSHarry Wentland { 11684562236bSHarry Wentland int i; 11694562236bSHarry Wentland struct pipe_ctx *secondary_pipe = NULL; 11704562236bSHarry Wentland 11714562236bSHarry Wentland /* 11725581192dSJun Lei * We add a preferred pipe mapping to avoid the chance that 11735581192dSJun Lei * MPCCs already in use will need to be reassigned to other trees. 11745581192dSJun Lei * For example, if we went with the strict, assign backwards logic: 11755581192dSJun Lei * 11765581192dSJun Lei * (State 1) 11775581192dSJun Lei * Display A on, no surface, top pipe = 0 11785581192dSJun Lei * Display B on, no surface, top pipe = 1 11795581192dSJun Lei * 11805581192dSJun Lei * (State 2) 11815581192dSJun Lei * Display A on, no surface, top pipe = 0 11825581192dSJun Lei * Display B on, surface enable, top pipe = 1, bottom pipe = 5 11835581192dSJun Lei * 11845581192dSJun Lei * (State 3) 11855581192dSJun Lei * Display A on, surface enable, top pipe = 0, bottom pipe = 5 11865581192dSJun Lei * Display B on, surface enable, top pipe = 1, bottom pipe = 4 11875581192dSJun Lei * 11885581192dSJun Lei * The state 2->3 transition requires remapping MPCC 5 from display B 11895581192dSJun Lei * to display A. 11905581192dSJun Lei * 11915581192dSJun Lei * However, with the preferred pipe logic, state 2 would look like: 11925581192dSJun Lei * 11935581192dSJun Lei * (State 2) 11945581192dSJun Lei * Display A on, no surface, top pipe = 0 11955581192dSJun Lei * Display B on, surface enable, top pipe = 1, bottom pipe = 4 11965581192dSJun Lei * 11975581192dSJun Lei * This would then cause 2->3 to not require remapping any MPCCs. 11985581192dSJun Lei */ 11995581192dSJun Lei if (primary_pipe) { 12005581192dSJun Lei int preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx; 12015581192dSJun Lei if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) { 12025581192dSJun Lei secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx]; 12035581192dSJun Lei secondary_pipe->pipe_idx = preferred_pipe_idx; 12045581192dSJun Lei } 12055581192dSJun Lei } 12065581192dSJun Lei 12075581192dSJun Lei /* 12084562236bSHarry Wentland * search backwards for the second pipe to keep pipe 12094562236bSHarry Wentland * assignment more consistent 12104562236bSHarry Wentland */ 12115581192dSJun Lei if (!secondary_pipe) 1212a2b8659dSTony Cheng for (i = pool->pipe_count - 1; i >= 0; i--) { 12134562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == NULL) { 12144562236bSHarry Wentland secondary_pipe = &res_ctx->pipe_ctx[i]; 12154562236bSHarry Wentland secondary_pipe->pipe_idx = i; 12164562236bSHarry Wentland break; 12174562236bSHarry Wentland } 12184562236bSHarry Wentland } 12194562236bSHarry Wentland 12204562236bSHarry Wentland return secondary_pipe; 12214562236bSHarry Wentland } 12224562236bSHarry Wentland 12234562236bSHarry Wentland struct pipe_ctx *resource_get_head_pipe_for_stream( 12244562236bSHarry Wentland struct resource_context *res_ctx, 12250971c40eSHarry Wentland struct dc_stream_state *stream) 12264562236bSHarry Wentland { 12274562236bSHarry Wentland int i; 122822498036SDmytro Laktyushkin 1229a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 1230b1f6d01cSDmytro Laktyushkin if (res_ctx->pipe_ctx[i].stream == stream 1231b1f6d01cSDmytro Laktyushkin && !res_ctx->pipe_ctx[i].top_pipe 123222498036SDmytro Laktyushkin && !res_ctx->pipe_ctx[i].prev_odm_pipe) 12334562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 12344562236bSHarry Wentland } 12354562236bSHarry Wentland return NULL; 12364562236bSHarry Wentland } 12374562236bSHarry Wentland 1238b1f6d01cSDmytro Laktyushkin static struct pipe_ctx *resource_get_tail_pipe( 123919f89e23SAndrey Grodzovsky struct resource_context *res_ctx, 1240b1f6d01cSDmytro Laktyushkin struct pipe_ctx *head_pipe) 124119f89e23SAndrey Grodzovsky { 1242b1f6d01cSDmytro Laktyushkin struct pipe_ctx *tail_pipe; 124319f89e23SAndrey Grodzovsky 124419f89e23SAndrey Grodzovsky tail_pipe = head_pipe->bottom_pipe; 124519f89e23SAndrey Grodzovsky 124619f89e23SAndrey Grodzovsky while (tail_pipe) { 124719f89e23SAndrey Grodzovsky head_pipe = tail_pipe; 124819f89e23SAndrey Grodzovsky tail_pipe = tail_pipe->bottom_pipe; 124919f89e23SAndrey Grodzovsky } 125019f89e23SAndrey Grodzovsky 125119f89e23SAndrey Grodzovsky return head_pipe; 125219f89e23SAndrey Grodzovsky } 125319f89e23SAndrey Grodzovsky 12544562236bSHarry Wentland /* 1255ab2541b6SAric Cyr * A free_pipe for a stream is defined here as a pipe 1256ab2541b6SAric Cyr * that has no surface attached yet 12574562236bSHarry Wentland */ 1258b1f6d01cSDmytro Laktyushkin static struct pipe_ctx *acquire_free_pipe_for_head( 1259608ac7bbSJerry Zuo struct dc_state *context, 1260a2b8659dSTony Cheng const struct resource_pool *pool, 1261b1f6d01cSDmytro Laktyushkin struct pipe_ctx *head_pipe) 12624562236bSHarry Wentland { 12634562236bSHarry Wentland int i; 1264745cc746SDmytro Laktyushkin struct resource_context *res_ctx = &context->res_ctx; 12654562236bSHarry Wentland 12663be5262eSHarry Wentland if (!head_pipe->plane_state) 12674562236bSHarry Wentland return head_pipe; 12684562236bSHarry Wentland 12694562236bSHarry Wentland /* Re-use pipe already acquired for this stream if available*/ 1270a2b8659dSTony Cheng for (i = pool->pipe_count - 1; i >= 0; i--) { 1271b1f6d01cSDmytro Laktyushkin if (res_ctx->pipe_ctx[i].stream == head_pipe->stream && 12723be5262eSHarry Wentland !res_ctx->pipe_ctx[i].plane_state) { 12734562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 12744562236bSHarry Wentland } 12754562236bSHarry Wentland } 12764562236bSHarry Wentland 12774562236bSHarry Wentland /* 12784562236bSHarry Wentland * At this point we have no re-useable pipe for this stream and we need 12794562236bSHarry Wentland * to acquire an idle one to satisfy the request 12804562236bSHarry Wentland */ 12814562236bSHarry Wentland 1282a2b8659dSTony Cheng if (!pool->funcs->acquire_idle_pipe_for_layer) 12834562236bSHarry Wentland return NULL; 12844562236bSHarry Wentland 1285b1f6d01cSDmytro Laktyushkin return pool->funcs->acquire_idle_pipe_for_layer(context, pool, head_pipe->stream); 12864562236bSHarry Wentland } 12874562236bSHarry Wentland 1288b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 12890f9a536fSDmytro Laktyushkin static int acquire_first_split_pipe( 12900f9a536fSDmytro Laktyushkin struct resource_context *res_ctx, 12910f9a536fSDmytro Laktyushkin const struct resource_pool *pool, 12920971c40eSHarry Wentland struct dc_stream_state *stream) 12930f9a536fSDmytro Laktyushkin { 12940f9a536fSDmytro Laktyushkin int i; 12950f9a536fSDmytro Laktyushkin 12960f9a536fSDmytro Laktyushkin for (i = 0; i < pool->pipe_count; i++) { 129779592db3SDmytro Laktyushkin struct pipe_ctx *split_pipe = &res_ctx->pipe_ctx[i]; 12980f9a536fSDmytro Laktyushkin 1299b1f6d01cSDmytro Laktyushkin if (split_pipe->top_pipe && 130079592db3SDmytro Laktyushkin split_pipe->top_pipe->plane_state == split_pipe->plane_state) { 130179592db3SDmytro Laktyushkin split_pipe->top_pipe->bottom_pipe = split_pipe->bottom_pipe; 130279592db3SDmytro Laktyushkin if (split_pipe->bottom_pipe) 130379592db3SDmytro Laktyushkin split_pipe->bottom_pipe->top_pipe = split_pipe->top_pipe; 13040f9a536fSDmytro Laktyushkin 130579592db3SDmytro Laktyushkin if (split_pipe->top_pipe->plane_state) 130679592db3SDmytro Laktyushkin resource_build_scaling_params(split_pipe->top_pipe); 13070f9a536fSDmytro Laktyushkin 130879592db3SDmytro Laktyushkin memset(split_pipe, 0, sizeof(*split_pipe)); 130979592db3SDmytro Laktyushkin split_pipe->stream_res.tg = pool->timing_generators[i]; 131079592db3SDmytro Laktyushkin split_pipe->plane_res.hubp = pool->hubps[i]; 131179592db3SDmytro Laktyushkin split_pipe->plane_res.ipp = pool->ipps[i]; 131279592db3SDmytro Laktyushkin split_pipe->plane_res.dpp = pool->dpps[i]; 131379592db3SDmytro Laktyushkin split_pipe->stream_res.opp = pool->opps[i]; 131479592db3SDmytro Laktyushkin split_pipe->plane_res.mpcc_inst = pool->dpps[i]->inst; 131579592db3SDmytro Laktyushkin split_pipe->pipe_idx = i; 131679592db3SDmytro Laktyushkin 131779592db3SDmytro Laktyushkin split_pipe->stream = stream; 13180f9a536fSDmytro Laktyushkin return i; 13190f9a536fSDmytro Laktyushkin } 13200f9a536fSDmytro Laktyushkin } 13210f9a536fSDmytro Laktyushkin return -1; 13220f9a536fSDmytro Laktyushkin } 13230f9a536fSDmytro Laktyushkin #endif 13240f9a536fSDmytro Laktyushkin 132519f89e23SAndrey Grodzovsky bool dc_add_plane_to_context( 132619f89e23SAndrey Grodzovsky const struct dc *dc, 13270971c40eSHarry Wentland struct dc_stream_state *stream, 132819f89e23SAndrey Grodzovsky struct dc_plane_state *plane_state, 1329608ac7bbSJerry Zuo struct dc_state *context) 13304562236bSHarry Wentland { 13314562236bSHarry Wentland int i; 133219f89e23SAndrey Grodzovsky struct resource_pool *pool = dc->res_pool; 133319f89e23SAndrey Grodzovsky struct pipe_ctx *head_pipe, *tail_pipe, *free_pipe; 1334ab2541b6SAric Cyr struct dc_stream_status *stream_status = NULL; 13354562236bSHarry Wentland 1336ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) 13374fa086b9SLeo (Sunpeng) Li if (context->streams[i] == stream) { 1338ab2541b6SAric Cyr stream_status = &context->stream_status[i]; 13394562236bSHarry Wentland break; 13404562236bSHarry Wentland } 1341ab2541b6SAric Cyr if (stream_status == NULL) { 134219f89e23SAndrey Grodzovsky dm_error("Existing stream not found; failed to attach surface!\n"); 134319f89e23SAndrey Grodzovsky return false; 134419f89e23SAndrey Grodzovsky } 134519f89e23SAndrey Grodzovsky 134619f89e23SAndrey Grodzovsky 134719f89e23SAndrey Grodzovsky if (stream_status->plane_count == MAX_SURFACE_NUM) { 134819f89e23SAndrey Grodzovsky dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n", 134919f89e23SAndrey Grodzovsky plane_state, MAX_SURFACE_NUM); 135019f89e23SAndrey Grodzovsky return false; 135119f89e23SAndrey Grodzovsky } 135219f89e23SAndrey Grodzovsky 135319f89e23SAndrey Grodzovsky head_pipe = resource_get_head_pipe_for_stream(&context->res_ctx, stream); 135419f89e23SAndrey Grodzovsky 135519f89e23SAndrey Grodzovsky if (!head_pipe) { 135619f89e23SAndrey Grodzovsky dm_error("Head pipe not found for stream_state %p !\n", stream); 13574562236bSHarry Wentland return false; 13584562236bSHarry Wentland } 13594562236bSHarry Wentland 1360b1f6d01cSDmytro Laktyushkin /* retain new surface, but only once per stream */ 1361b1f6d01cSDmytro Laktyushkin dc_plane_state_retain(plane_state); 1362b1f6d01cSDmytro Laktyushkin 1363b1f6d01cSDmytro Laktyushkin while (head_pipe) { 1364b1f6d01cSDmytro Laktyushkin free_pipe = acquire_free_pipe_for_head(context, pool, head_pipe); 13654562236bSHarry Wentland 1366b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 13670f9a536fSDmytro Laktyushkin if (!free_pipe) { 13680f9a536fSDmytro Laktyushkin int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 13690f9a536fSDmytro Laktyushkin if (pipe_idx >= 0) 13700f9a536fSDmytro Laktyushkin free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; 13710f9a536fSDmytro Laktyushkin } 13720f9a536fSDmytro Laktyushkin #endif 1373b1f6d01cSDmytro Laktyushkin if (!free_pipe) { 1374b1f6d01cSDmytro Laktyushkin dc_plane_state_release(plane_state); 13754562236bSHarry Wentland return false; 1376b1f6d01cSDmytro Laktyushkin } 13774562236bSHarry Wentland 13783be5262eSHarry Wentland free_pipe->plane_state = plane_state; 13794562236bSHarry Wentland 138019f89e23SAndrey Grodzovsky if (head_pipe != free_pipe) { 13815b5c1777SJosip Pavic tail_pipe = resource_get_tail_pipe(&context->res_ctx, head_pipe); 13825b5c1777SJosip Pavic ASSERT(tail_pipe); 13836b670fa9SHarry Wentland free_pipe->stream_res.tg = tail_pipe->stream_res.tg; 13849aef1a31SSivapiriyanKumarasamy free_pipe->stream_res.abm = tail_pipe->stream_res.abm; 1385a6a6cb34SHarry Wentland free_pipe->stream_res.opp = tail_pipe->stream_res.opp; 13868e9c4c8cSHarry Wentland free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; 1387afaacef4SHarry Wentland free_pipe->stream_res.audio = tail_pipe->stream_res.audio; 1388cfe4645eSDmytro Laktyushkin free_pipe->clock_source = tail_pipe->clock_source; 13894562236bSHarry Wentland free_pipe->top_pipe = tail_pipe; 13904562236bSHarry Wentland tail_pipe->bottom_pipe = free_pipe; 13914562236bSHarry Wentland } 1392b1f6d01cSDmytro Laktyushkin head_pipe = head_pipe->next_odm_pipe; 1393b1f6d01cSDmytro Laktyushkin } 13944562236bSHarry Wentland /* assign new surfaces*/ 139519f89e23SAndrey Grodzovsky stream_status->plane_states[stream_status->plane_count] = plane_state; 13964562236bSHarry Wentland 139719f89e23SAndrey Grodzovsky stream_status->plane_count++; 13984562236bSHarry Wentland 13994562236bSHarry Wentland return true; 14004562236bSHarry Wentland } 14014562236bSHarry Wentland 140219f89e23SAndrey Grodzovsky bool dc_remove_plane_from_context( 140319f89e23SAndrey Grodzovsky const struct dc *dc, 140419f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 140519f89e23SAndrey Grodzovsky struct dc_plane_state *plane_state, 1406608ac7bbSJerry Zuo struct dc_state *context) 140719f89e23SAndrey Grodzovsky { 140819f89e23SAndrey Grodzovsky int i; 140919f89e23SAndrey Grodzovsky struct dc_stream_status *stream_status = NULL; 141019f89e23SAndrey Grodzovsky struct resource_pool *pool = dc->res_pool; 141119f89e23SAndrey Grodzovsky 141219f89e23SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 141319f89e23SAndrey Grodzovsky if (context->streams[i] == stream) { 141419f89e23SAndrey Grodzovsky stream_status = &context->stream_status[i]; 141519f89e23SAndrey Grodzovsky break; 141619f89e23SAndrey Grodzovsky } 141719f89e23SAndrey Grodzovsky 141819f89e23SAndrey Grodzovsky if (stream_status == NULL) { 141919f89e23SAndrey Grodzovsky dm_error("Existing stream not found; failed to remove plane.\n"); 142019f89e23SAndrey Grodzovsky return false; 142119f89e23SAndrey Grodzovsky } 142219f89e23SAndrey Grodzovsky 142319f89e23SAndrey Grodzovsky /* release pipe for plane*/ 142419f89e23SAndrey Grodzovsky for (i = pool->pipe_count - 1; i >= 0; i--) { 14256ffaa6fcSDmytro Laktyushkin struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 142619f89e23SAndrey Grodzovsky 14276ffaa6fcSDmytro Laktyushkin if (pipe_ctx->plane_state == plane_state) { 142819f89e23SAndrey Grodzovsky if (pipe_ctx->top_pipe) 142919f89e23SAndrey Grodzovsky pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; 143019f89e23SAndrey Grodzovsky 143119f89e23SAndrey Grodzovsky /* Second condition is to avoid setting NULL to top pipe 143219f89e23SAndrey Grodzovsky * of tail pipe making it look like head pipe in subsequent 143319f89e23SAndrey Grodzovsky * deletes 143419f89e23SAndrey Grodzovsky */ 143519f89e23SAndrey Grodzovsky if (pipe_ctx->bottom_pipe && pipe_ctx->top_pipe) 143619f89e23SAndrey Grodzovsky pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; 143719f89e23SAndrey Grodzovsky 143819f89e23SAndrey Grodzovsky /* 143919f89e23SAndrey Grodzovsky * For head pipe detach surfaces from pipe for tail 144019f89e23SAndrey Grodzovsky * pipe just zero it out 144119f89e23SAndrey Grodzovsky */ 1442b1f6d01cSDmytro Laktyushkin if (!pipe_ctx->top_pipe) 144319f89e23SAndrey Grodzovsky pipe_ctx->plane_state = NULL; 1444b1f6d01cSDmytro Laktyushkin else 144519f89e23SAndrey Grodzovsky memset(pipe_ctx, 0, sizeof(*pipe_ctx)); 144619f89e23SAndrey Grodzovsky } 144719f89e23SAndrey Grodzovsky } 144819f89e23SAndrey Grodzovsky 144919f89e23SAndrey Grodzovsky 145019f89e23SAndrey Grodzovsky for (i = 0; i < stream_status->plane_count; i++) { 145119f89e23SAndrey Grodzovsky if (stream_status->plane_states[i] == plane_state) { 145219f89e23SAndrey Grodzovsky 145319f89e23SAndrey Grodzovsky dc_plane_state_release(stream_status->plane_states[i]); 145419f89e23SAndrey Grodzovsky break; 145519f89e23SAndrey Grodzovsky } 145619f89e23SAndrey Grodzovsky } 145719f89e23SAndrey Grodzovsky 145819f89e23SAndrey Grodzovsky if (i == stream_status->plane_count) { 145919f89e23SAndrey Grodzovsky dm_error("Existing plane_state not found; failed to detach it!\n"); 146019f89e23SAndrey Grodzovsky return false; 146119f89e23SAndrey Grodzovsky } 146219f89e23SAndrey Grodzovsky 146319f89e23SAndrey Grodzovsky stream_status->plane_count--; 146419f89e23SAndrey Grodzovsky 1465abb4986eSAndrew Jiang /* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */ 1466abb4986eSAndrew Jiang for (; i < stream_status->plane_count; i++) 146719f89e23SAndrey Grodzovsky stream_status->plane_states[i] = stream_status->plane_states[i + 1]; 146819f89e23SAndrey Grodzovsky 146919f89e23SAndrey Grodzovsky stream_status->plane_states[stream_status->plane_count] = NULL; 147019f89e23SAndrey Grodzovsky 147119f89e23SAndrey Grodzovsky return true; 147219f89e23SAndrey Grodzovsky } 147319f89e23SAndrey Grodzovsky 147419f89e23SAndrey Grodzovsky bool dc_rem_all_planes_for_stream( 147519f89e23SAndrey Grodzovsky const struct dc *dc, 147619f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 1477608ac7bbSJerry Zuo struct dc_state *context) 147819f89e23SAndrey Grodzovsky { 147919f89e23SAndrey Grodzovsky int i, old_plane_count; 148019f89e23SAndrey Grodzovsky struct dc_stream_status *stream_status = NULL; 148119f89e23SAndrey Grodzovsky struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 }; 148219f89e23SAndrey Grodzovsky 148319f89e23SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 148419f89e23SAndrey Grodzovsky if (context->streams[i] == stream) { 148519f89e23SAndrey Grodzovsky stream_status = &context->stream_status[i]; 148619f89e23SAndrey Grodzovsky break; 148719f89e23SAndrey Grodzovsky } 148819f89e23SAndrey Grodzovsky 148919f89e23SAndrey Grodzovsky if (stream_status == NULL) { 149019f89e23SAndrey Grodzovsky dm_error("Existing stream %p not found!\n", stream); 149119f89e23SAndrey Grodzovsky return false; 149219f89e23SAndrey Grodzovsky } 149319f89e23SAndrey Grodzovsky 149419f89e23SAndrey Grodzovsky old_plane_count = stream_status->plane_count; 149519f89e23SAndrey Grodzovsky 149619f89e23SAndrey Grodzovsky for (i = 0; i < old_plane_count; i++) 149719f89e23SAndrey Grodzovsky del_planes[i] = stream_status->plane_states[i]; 149819f89e23SAndrey Grodzovsky 149919f89e23SAndrey Grodzovsky for (i = 0; i < old_plane_count; i++) 150019f89e23SAndrey Grodzovsky if (!dc_remove_plane_from_context(dc, stream, del_planes[i], context)) 150119f89e23SAndrey Grodzovsky return false; 150219f89e23SAndrey Grodzovsky 150319f89e23SAndrey Grodzovsky return true; 150419f89e23SAndrey Grodzovsky } 150519f89e23SAndrey Grodzovsky 150619f89e23SAndrey Grodzovsky static bool add_all_planes_for_stream( 150719f89e23SAndrey Grodzovsky const struct dc *dc, 150819f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 150919f89e23SAndrey Grodzovsky const struct dc_validation_set set[], 151019f89e23SAndrey Grodzovsky int set_count, 1511608ac7bbSJerry Zuo struct dc_state *context) 151219f89e23SAndrey Grodzovsky { 151319f89e23SAndrey Grodzovsky int i, j; 151419f89e23SAndrey Grodzovsky 151519f89e23SAndrey Grodzovsky for (i = 0; i < set_count; i++) 151619f89e23SAndrey Grodzovsky if (set[i].stream == stream) 151719f89e23SAndrey Grodzovsky break; 151819f89e23SAndrey Grodzovsky 151919f89e23SAndrey Grodzovsky if (i == set_count) { 152019f89e23SAndrey Grodzovsky dm_error("Stream %p not found in set!\n", stream); 152119f89e23SAndrey Grodzovsky return false; 152219f89e23SAndrey Grodzovsky } 152319f89e23SAndrey Grodzovsky 152419f89e23SAndrey Grodzovsky for (j = 0; j < set[i].plane_count; j++) 152519f89e23SAndrey Grodzovsky if (!dc_add_plane_to_context(dc, stream, set[i].plane_states[j], context)) 152619f89e23SAndrey Grodzovsky return false; 152719f89e23SAndrey Grodzovsky 152819f89e23SAndrey Grodzovsky return true; 152919f89e23SAndrey Grodzovsky } 153019f89e23SAndrey Grodzovsky 153119f89e23SAndrey Grodzovsky bool dc_add_all_planes_for_stream( 153219f89e23SAndrey Grodzovsky const struct dc *dc, 153319f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 153419f89e23SAndrey Grodzovsky struct dc_plane_state * const *plane_states, 153519f89e23SAndrey Grodzovsky int plane_count, 1536608ac7bbSJerry Zuo struct dc_state *context) 153719f89e23SAndrey Grodzovsky { 153819f89e23SAndrey Grodzovsky struct dc_validation_set set; 153919f89e23SAndrey Grodzovsky int i; 154019f89e23SAndrey Grodzovsky 154119f89e23SAndrey Grodzovsky set.stream = stream; 154219f89e23SAndrey Grodzovsky set.plane_count = plane_count; 154319f89e23SAndrey Grodzovsky 154419f89e23SAndrey Grodzovsky for (i = 0; i < plane_count; i++) 154519f89e23SAndrey Grodzovsky set.plane_states[i] = plane_states[i]; 154619f89e23SAndrey Grodzovsky 154719f89e23SAndrey Grodzovsky return add_all_planes_for_stream(dc, stream, &set, 1, context); 154819f89e23SAndrey Grodzovsky } 154919f89e23SAndrey Grodzovsky 155019f89e23SAndrey Grodzovsky 15516b622181SJulian Parkin static bool is_hdr_static_meta_changed(struct dc_stream_state *cur_stream, 15526b622181SJulian Parkin struct dc_stream_state *new_stream) 15536b622181SJulian Parkin { 15546b622181SJulian Parkin if (cur_stream == NULL) 15556b622181SJulian Parkin return true; 15566b622181SJulian Parkin 15576b622181SJulian Parkin if (memcmp(&cur_stream->hdr_static_metadata, 15586b622181SJulian Parkin &new_stream->hdr_static_metadata, 15596b622181SJulian Parkin sizeof(struct dc_info_packet)) != 0) 15606b622181SJulian Parkin return true; 15616b622181SJulian Parkin 15626b622181SJulian Parkin return false; 15636b622181SJulian Parkin } 15644562236bSHarry Wentland 15651336926fSAlvin lee static bool is_vsc_info_packet_changed(struct dc_stream_state *cur_stream, 15661336926fSAlvin lee struct dc_stream_state *new_stream) 15671336926fSAlvin lee { 15681336926fSAlvin lee if (cur_stream == NULL) 15691336926fSAlvin lee return true; 15701336926fSAlvin lee 15711336926fSAlvin lee if (memcmp(&cur_stream->vsc_infopacket, 15721336926fSAlvin lee &new_stream->vsc_infopacket, 15731336926fSAlvin lee sizeof(struct dc_info_packet)) != 0) 15741336926fSAlvin lee return true; 15751336926fSAlvin lee 15761336926fSAlvin lee return false; 15771336926fSAlvin lee } 15781336926fSAlvin lee 15790971c40eSHarry Wentland static bool is_timing_changed(struct dc_stream_state *cur_stream, 15800971c40eSHarry Wentland struct dc_stream_state *new_stream) 15814562236bSHarry Wentland { 15824562236bSHarry Wentland if (cur_stream == NULL) 15834562236bSHarry Wentland return true; 15844562236bSHarry Wentland 15854562236bSHarry Wentland /* If sink pointer changed, it means this is a hotplug, we should do 15864562236bSHarry Wentland * full hw setting. 15874562236bSHarry Wentland */ 15884562236bSHarry Wentland if (cur_stream->sink != new_stream->sink) 15894562236bSHarry Wentland return true; 15904562236bSHarry Wentland 15914562236bSHarry Wentland /* If output color space is changed, need to reprogram info frames */ 15924fa086b9SLeo (Sunpeng) Li if (cur_stream->output_color_space != new_stream->output_color_space) 15934562236bSHarry Wentland return true; 15944562236bSHarry Wentland 15954562236bSHarry Wentland return memcmp( 15964fa086b9SLeo (Sunpeng) Li &cur_stream->timing, 15974fa086b9SLeo (Sunpeng) Li &new_stream->timing, 15984562236bSHarry Wentland sizeof(struct dc_crtc_timing)) != 0; 15994562236bSHarry Wentland } 16004562236bSHarry Wentland 16014562236bSHarry Wentland static bool are_stream_backends_same( 16020971c40eSHarry Wentland struct dc_stream_state *stream_a, struct dc_stream_state *stream_b) 16034562236bSHarry Wentland { 16044562236bSHarry Wentland if (stream_a == stream_b) 16054562236bSHarry Wentland return true; 16064562236bSHarry Wentland 16074562236bSHarry Wentland if (stream_a == NULL || stream_b == NULL) 16084562236bSHarry Wentland return false; 16094562236bSHarry Wentland 16104562236bSHarry Wentland if (is_timing_changed(stream_a, stream_b)) 16114562236bSHarry Wentland return false; 16124562236bSHarry Wentland 16136b622181SJulian Parkin if (is_hdr_static_meta_changed(stream_a, stream_b)) 16146b622181SJulian Parkin return false; 16156b622181SJulian Parkin 16161e7e86c4SSamson Tam if (stream_a->dpms_off != stream_b->dpms_off) 16171e7e86c4SSamson Tam return false; 16181e7e86c4SSamson Tam 16191336926fSAlvin lee if (is_vsc_info_packet_changed(stream_a, stream_b)) 16201336926fSAlvin lee return false; 16211336926fSAlvin lee 16224562236bSHarry Wentland return true; 16234562236bSHarry Wentland } 16244562236bSHarry Wentland 16252119aa17SDavid Francis /** 16262119aa17SDavid Francis * dc_is_stream_unchanged() - Compare two stream states for equivalence. 16272119aa17SDavid Francis * 16282119aa17SDavid Francis * Checks if there a difference between the two states 16292119aa17SDavid Francis * that would require a mode change. 16302119aa17SDavid Francis * 16312119aa17SDavid Francis * Does not compare cursor position or attributes. 16322119aa17SDavid Francis */ 1633d54d29dbSBhawanpreet Lakha bool dc_is_stream_unchanged( 16340971c40eSHarry Wentland struct dc_stream_state *old_stream, struct dc_stream_state *stream) 16354562236bSHarry Wentland { 16364562236bSHarry Wentland 16374562236bSHarry Wentland if (!are_stream_backends_same(old_stream, stream)) 16384562236bSHarry Wentland return false; 16394562236bSHarry Wentland 16400460f9abSJun Lei if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param) 16410460f9abSJun Lei return false; 16420460f9abSJun Lei 16434562236bSHarry Wentland return true; 16444562236bSHarry Wentland } 16454562236bSHarry Wentland 16462119aa17SDavid Francis /** 16472119aa17SDavid Francis * dc_is_stream_scaling_unchanged() - Compare scaling rectangles of two streams. 16482119aa17SDavid Francis */ 16499a5d9c48SLeo (Sunpeng) Li bool dc_is_stream_scaling_unchanged( 16509a5d9c48SLeo (Sunpeng) Li struct dc_stream_state *old_stream, struct dc_stream_state *stream) 16519a5d9c48SLeo (Sunpeng) Li { 16529a5d9c48SLeo (Sunpeng) Li if (old_stream == stream) 16539a5d9c48SLeo (Sunpeng) Li return true; 16549a5d9c48SLeo (Sunpeng) Li 16559a5d9c48SLeo (Sunpeng) Li if (old_stream == NULL || stream == NULL) 16569a5d9c48SLeo (Sunpeng) Li return false; 16579a5d9c48SLeo (Sunpeng) Li 16589a5d9c48SLeo (Sunpeng) Li if (memcmp(&old_stream->src, 16599a5d9c48SLeo (Sunpeng) Li &stream->src, 16609a5d9c48SLeo (Sunpeng) Li sizeof(struct rect)) != 0) 16619a5d9c48SLeo (Sunpeng) Li return false; 16629a5d9c48SLeo (Sunpeng) Li 16639a5d9c48SLeo (Sunpeng) Li if (memcmp(&old_stream->dst, 16649a5d9c48SLeo (Sunpeng) Li &stream->dst, 16659a5d9c48SLeo (Sunpeng) Li sizeof(struct rect)) != 0) 16669a5d9c48SLeo (Sunpeng) Li return false; 16679a5d9c48SLeo (Sunpeng) Li 16689a5d9c48SLeo (Sunpeng) Li return true; 16699a5d9c48SLeo (Sunpeng) Li } 16709a5d9c48SLeo (Sunpeng) Li 16711dc90497SAndrey Grodzovsky static void update_stream_engine_usage( 16724562236bSHarry Wentland struct resource_context *res_ctx, 1673a2b8659dSTony Cheng const struct resource_pool *pool, 16741dc90497SAndrey Grodzovsky struct stream_encoder *stream_enc, 16751dc90497SAndrey Grodzovsky bool acquired) 16764562236bSHarry Wentland { 16774562236bSHarry Wentland int i; 16784562236bSHarry Wentland 1679a2b8659dSTony Cheng for (i = 0; i < pool->stream_enc_count; i++) { 1680a2b8659dSTony Cheng if (pool->stream_enc[i] == stream_enc) 16811dc90497SAndrey Grodzovsky res_ctx->is_stream_enc_acquired[i] = acquired; 16824562236bSHarry Wentland } 16834562236bSHarry Wentland } 16844562236bSHarry Wentland 16854562236bSHarry Wentland /* TODO: release audio object */ 16864176664bSCharlene Liu void update_audio_usage( 16874562236bSHarry Wentland struct resource_context *res_ctx, 1688a2b8659dSTony Cheng const struct resource_pool *pool, 16891dc90497SAndrey Grodzovsky struct audio *audio, 16901dc90497SAndrey Grodzovsky bool acquired) 16914562236bSHarry Wentland { 16924562236bSHarry Wentland int i; 1693a2b8659dSTony Cheng for (i = 0; i < pool->audio_count; i++) { 1694a2b8659dSTony Cheng if (pool->audios[i] == audio) 16951dc90497SAndrey Grodzovsky res_ctx->is_audio_acquired[i] = acquired; 16964562236bSHarry Wentland } 16974562236bSHarry Wentland } 16984562236bSHarry Wentland 16994562236bSHarry Wentland static int acquire_first_free_pipe( 17004562236bSHarry Wentland struct resource_context *res_ctx, 1701a2b8659dSTony Cheng const struct resource_pool *pool, 17020971c40eSHarry Wentland struct dc_stream_state *stream) 17034562236bSHarry Wentland { 17044562236bSHarry Wentland int i; 17054562236bSHarry Wentland 1706a2b8659dSTony Cheng for (i = 0; i < pool->pipe_count; i++) { 17074562236bSHarry Wentland if (!res_ctx->pipe_ctx[i].stream) { 17084562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 17094562236bSHarry Wentland 17106b670fa9SHarry Wentland pipe_ctx->stream_res.tg = pool->timing_generators[i]; 171186a66c4eSHarry Wentland pipe_ctx->plane_res.mi = pool->mis[i]; 17128feabd03SYue Hin Lau pipe_ctx->plane_res.hubp = pool->hubps[i]; 171386a66c4eSHarry Wentland pipe_ctx->plane_res.ipp = pool->ipps[i]; 171486a66c4eSHarry Wentland pipe_ctx->plane_res.xfm = pool->transforms[i]; 1715d94585a0SYue Hin Lau pipe_ctx->plane_res.dpp = pool->dpps[i]; 1716a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp = pool->opps[i]; 1717bc373a89SRoman Li if (pool->dpps[i]) 1718e07f541fSYongqiang Sun pipe_ctx->plane_res.mpcc_inst = pool->dpps[i]->inst; 17194562236bSHarry Wentland pipe_ctx->pipe_idx = i; 17204562236bSHarry Wentland 1721ff5ef992SAlex Deucher 17224562236bSHarry Wentland pipe_ctx->stream = stream; 17234562236bSHarry Wentland return i; 17244562236bSHarry Wentland } 17254562236bSHarry Wentland } 17264562236bSHarry Wentland return -1; 17274562236bSHarry Wentland } 17284562236bSHarry Wentland 1729a2b8659dSTony Cheng static struct audio *find_first_free_audio( 1730a2b8659dSTony Cheng struct resource_context *res_ctx, 1731cfb071f7SCharlene Liu const struct resource_pool *pool, 1732f24b0522SPaul Hsieh enum engine_id id, 1733f24b0522SPaul Hsieh enum dce_version dc_version) 17344562236bSHarry Wentland { 1735b5a41620SCharlene Liu int i, available_audio_count; 1736b5a41620SCharlene Liu 1737b5a41620SCharlene Liu available_audio_count = pool->audio_count; 1738b5a41620SCharlene Liu 1739b5a41620SCharlene Liu for (i = 0; i < available_audio_count; i++) { 17404176664bSCharlene Liu if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) { 1741cfb071f7SCharlene Liu /*we have enough audio endpoint, find the matching inst*/ 1742cfb071f7SCharlene Liu if (id != i) 1743cfb071f7SCharlene Liu continue; 1744a2b8659dSTony Cheng return pool->audios[i]; 17454562236bSHarry Wentland } 17464562236bSHarry Wentland } 17475feb9f07STai Man 17485feb9f07STai Man /* use engine id to find free audio */ 1749b5a41620SCharlene Liu if ((id < available_audio_count) && (res_ctx->is_audio_acquired[id] == false)) { 17505feb9f07STai Man return pool->audios[id]; 17515feb9f07STai Man } 175266bfd4fdSCharlene Liu /*not found the matching one, first come first serve*/ 1753b5a41620SCharlene Liu for (i = 0; i < available_audio_count; i++) { 17544176664bSCharlene Liu if (res_ctx->is_audio_acquired[i] == false) { 17554176664bSCharlene Liu return pool->audios[i]; 17564176664bSCharlene Liu } 17574176664bSCharlene Liu } 17584562236bSHarry Wentland return 0; 17594562236bSHarry Wentland } 17604562236bSHarry Wentland 17614562236bSHarry Wentland bool resource_is_stream_unchanged( 1762608ac7bbSJerry Zuo struct dc_state *old_context, struct dc_stream_state *stream) 17634562236bSHarry Wentland { 1764ab2541b6SAric Cyr int i; 17654562236bSHarry Wentland 1766ab2541b6SAric Cyr for (i = 0; i < old_context->stream_count; i++) { 17670971c40eSHarry Wentland struct dc_stream_state *old_stream = old_context->streams[i]; 17684562236bSHarry Wentland 17694562236bSHarry Wentland if (are_stream_backends_same(old_stream, stream)) 17704562236bSHarry Wentland return true; 17714562236bSHarry Wentland } 17724562236bSHarry Wentland 17734562236bSHarry Wentland return false; 17744562236bSHarry Wentland } 17754562236bSHarry Wentland 17762119aa17SDavid Francis /** 17772119aa17SDavid Francis * dc_add_stream_to_ctx() - Add a new dc_stream_state to a dc_state. 17782119aa17SDavid Francis */ 177913ab1b44SYongqiang Sun enum dc_status dc_add_stream_to_ctx( 17801dc90497SAndrey Grodzovsky struct dc *dc, 1781608ac7bbSJerry Zuo struct dc_state *new_ctx, 17821dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 17831dc90497SAndrey Grodzovsky { 17841dc90497SAndrey Grodzovsky enum dc_status res; 1785eb9714a2SWenjing Liu DC_LOGGER_INIT(dc->ctx->logger); 17861dc90497SAndrey Grodzovsky 1787ece4147fSKen Chalmers if (new_ctx->stream_count >= dc->res_pool->timing_generator_count) { 1788eb9714a2SWenjing Liu DC_LOG_WARNING("Max streams reached, can't add stream %p !\n", stream); 17891dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 17901dc90497SAndrey Grodzovsky } 17911dc90497SAndrey Grodzovsky 17921dc90497SAndrey Grodzovsky new_ctx->streams[new_ctx->stream_count] = stream; 17931dc90497SAndrey Grodzovsky dc_stream_retain(stream); 17941dc90497SAndrey Grodzovsky new_ctx->stream_count++; 17951dc90497SAndrey Grodzovsky 17961dc90497SAndrey Grodzovsky res = dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream); 17971dc90497SAndrey Grodzovsky if (res != DC_OK) 1798eb9714a2SWenjing Liu DC_LOG_WARNING("Adding stream %p to context failed with err %d!\n", stream, res); 17991dc90497SAndrey Grodzovsky 180013ab1b44SYongqiang Sun return res; 18011dc90497SAndrey Grodzovsky } 18021dc90497SAndrey Grodzovsky 18032119aa17SDavid Francis /** 18042119aa17SDavid Francis * dc_remove_stream_from_ctx() - Remove a stream from a dc_state. 18052119aa17SDavid Francis */ 180662c933f9SYongqiang Sun enum dc_status dc_remove_stream_from_ctx( 18071dc90497SAndrey Grodzovsky struct dc *dc, 1808608ac7bbSJerry Zuo struct dc_state *new_ctx, 18091dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 18101dc90497SAndrey Grodzovsky { 181119f89e23SAndrey Grodzovsky int i; 18121dc90497SAndrey Grodzovsky struct dc_context *dc_ctx = dc->ctx; 181322498036SDmytro Laktyushkin struct pipe_ctx *del_pipe = resource_get_head_pipe_for_stream(&new_ctx->res_ctx, stream); 181422498036SDmytro Laktyushkin struct pipe_ctx *odm_pipe; 181522498036SDmytro Laktyushkin 181622498036SDmytro Laktyushkin if (!del_pipe) { 181722498036SDmytro Laktyushkin DC_ERROR("Pipe not found for stream %p !\n", stream); 181822498036SDmytro Laktyushkin return DC_ERROR_UNEXPECTED; 181922498036SDmytro Laktyushkin } 182022498036SDmytro Laktyushkin 182122498036SDmytro Laktyushkin odm_pipe = del_pipe->next_odm_pipe; 18221dc90497SAndrey Grodzovsky 182319f89e23SAndrey Grodzovsky /* Release primary pipe */ 182419f89e23SAndrey Grodzovsky ASSERT(del_pipe->stream_res.stream_enc); 18251dc90497SAndrey Grodzovsky update_stream_engine_usage( 18261dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 18271dc90497SAndrey Grodzovsky dc->res_pool, 18281dc90497SAndrey Grodzovsky del_pipe->stream_res.stream_enc, 18291dc90497SAndrey Grodzovsky false); 18301dc90497SAndrey Grodzovsky 18311dc90497SAndrey Grodzovsky if (del_pipe->stream_res.audio) 18321dc90497SAndrey Grodzovsky update_audio_usage( 18331dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 18341dc90497SAndrey Grodzovsky dc->res_pool, 18351dc90497SAndrey Grodzovsky del_pipe->stream_res.audio, 18361dc90497SAndrey Grodzovsky false); 18371dc90497SAndrey Grodzovsky 18389d0dcecdSHarry Wentland resource_unreference_clock_source(&new_ctx->res_ctx, 18399d0dcecdSHarry Wentland dc->res_pool, 18409d0dcecdSHarry Wentland del_pipe->clock_source); 18419d0dcecdSHarry Wentland 1842e56ae556SNikola Cornij if (dc->res_pool->funcs->remove_stream_from_ctx) 1843e56ae556SNikola Cornij dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream); 1844e56ae556SNikola Cornij 184522498036SDmytro Laktyushkin while (odm_pipe) { 184622498036SDmytro Laktyushkin struct pipe_ctx *next_odm_pipe = odm_pipe->next_odm_pipe; 184722498036SDmytro Laktyushkin 184822498036SDmytro Laktyushkin memset(odm_pipe, 0, sizeof(*odm_pipe)); 184922498036SDmytro Laktyushkin odm_pipe = next_odm_pipe; 185022498036SDmytro Laktyushkin } 18511dc90497SAndrey Grodzovsky memset(del_pipe, 0, sizeof(*del_pipe)); 18526ffaa6fcSDmytro Laktyushkin 18531dc90497SAndrey Grodzovsky for (i = 0; i < new_ctx->stream_count; i++) 18541dc90497SAndrey Grodzovsky if (new_ctx->streams[i] == stream) 18551dc90497SAndrey Grodzovsky break; 18561dc90497SAndrey Grodzovsky 18571dc90497SAndrey Grodzovsky if (new_ctx->streams[i] != stream) { 18581dc90497SAndrey Grodzovsky DC_ERROR("Context doesn't have stream %p !\n", stream); 18591dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 18601dc90497SAndrey Grodzovsky } 18611dc90497SAndrey Grodzovsky 18621dc90497SAndrey Grodzovsky dc_stream_release(new_ctx->streams[i]); 18631dc90497SAndrey Grodzovsky new_ctx->stream_count--; 18641dc90497SAndrey Grodzovsky 18651dc90497SAndrey Grodzovsky /* Trim back arrays */ 18661dc90497SAndrey Grodzovsky for (; i < new_ctx->stream_count; i++) { 18671dc90497SAndrey Grodzovsky new_ctx->streams[i] = new_ctx->streams[i + 1]; 18681dc90497SAndrey Grodzovsky new_ctx->stream_status[i] = new_ctx->stream_status[i + 1]; 18691dc90497SAndrey Grodzovsky } 18701dc90497SAndrey Grodzovsky 18711dc90497SAndrey Grodzovsky new_ctx->streams[new_ctx->stream_count] = NULL; 18721dc90497SAndrey Grodzovsky memset( 18731dc90497SAndrey Grodzovsky &new_ctx->stream_status[new_ctx->stream_count], 18741dc90497SAndrey Grodzovsky 0, 18751dc90497SAndrey Grodzovsky sizeof(new_ctx->stream_status[0])); 18761dc90497SAndrey Grodzovsky 18771dc90497SAndrey Grodzovsky return DC_OK; 18781dc90497SAndrey Grodzovsky } 18791dc90497SAndrey Grodzovsky 18800971c40eSHarry Wentland static struct dc_stream_state *find_pll_sharable_stream( 18810971c40eSHarry Wentland struct dc_stream_state *stream_needs_pll, 1882608ac7bbSJerry Zuo struct dc_state *context) 18834562236bSHarry Wentland { 1884ab2541b6SAric Cyr int i; 18854562236bSHarry Wentland 1886ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 18870971c40eSHarry Wentland struct dc_stream_state *stream_has_pll = context->streams[i]; 18884562236bSHarry Wentland 18894562236bSHarry Wentland /* We are looking for non dp, non virtual stream */ 18904562236bSHarry Wentland if (resource_are_streams_timing_synchronizable( 18914562236bSHarry Wentland stream_needs_pll, stream_has_pll) 18924562236bSHarry Wentland && !dc_is_dp_signal(stream_has_pll->signal) 1893ceb3dbb4SJun Lei && stream_has_pll->link->connector_signal 18944562236bSHarry Wentland != SIGNAL_TYPE_VIRTUAL) 18954562236bSHarry Wentland return stream_has_pll; 1896ab2541b6SAric Cyr 18974562236bSHarry Wentland } 18984562236bSHarry Wentland 18994562236bSHarry Wentland return NULL; 19004562236bSHarry Wentland } 19014562236bSHarry Wentland 19024562236bSHarry Wentland static int get_norm_pix_clk(const struct dc_crtc_timing *timing) 19034562236bSHarry Wentland { 1904380604e2SKen Chalmers uint32_t pix_clk = timing->pix_clk_100hz; 19054562236bSHarry Wentland uint32_t normalized_pix_clk = pix_clk; 19064562236bSHarry Wentland 19074562236bSHarry Wentland if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) 19084562236bSHarry Wentland pix_clk /= 2; 1909cc4d99b8SCharlene Liu if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) { 19104562236bSHarry Wentland switch (timing->display_color_depth) { 19118897810aSJulian Parkin case COLOR_DEPTH_666: 19124562236bSHarry Wentland case COLOR_DEPTH_888: 19134562236bSHarry Wentland normalized_pix_clk = pix_clk; 19144562236bSHarry Wentland break; 19154562236bSHarry Wentland case COLOR_DEPTH_101010: 19164562236bSHarry Wentland normalized_pix_clk = (pix_clk * 30) / 24; 19174562236bSHarry Wentland break; 19184562236bSHarry Wentland case COLOR_DEPTH_121212: 19194562236bSHarry Wentland normalized_pix_clk = (pix_clk * 36) / 24; 19204562236bSHarry Wentland break; 19214562236bSHarry Wentland case COLOR_DEPTH_161616: 19224562236bSHarry Wentland normalized_pix_clk = (pix_clk * 48) / 24; 19234562236bSHarry Wentland break; 19244562236bSHarry Wentland default: 19254562236bSHarry Wentland ASSERT(0); 19264562236bSHarry Wentland break; 19274562236bSHarry Wentland } 1928cc4d99b8SCharlene Liu } 19294562236bSHarry Wentland return normalized_pix_clk; 19304562236bSHarry Wentland } 19314562236bSHarry Wentland 19320971c40eSHarry Wentland static void calculate_phy_pix_clks(struct dc_stream_state *stream) 19334562236bSHarry Wentland { 19344562236bSHarry Wentland /* update actual pixel clock on all streams */ 19354562236bSHarry Wentland if (dc_is_hdmi_signal(stream->signal)) 19364562236bSHarry Wentland stream->phy_pix_clk = get_norm_pix_clk( 1937380604e2SKen Chalmers &stream->timing) / 10; 19384562236bSHarry Wentland else 19394562236bSHarry Wentland stream->phy_pix_clk = 1940380604e2SKen Chalmers stream->timing.pix_clk_100hz / 10; 194139c03e00SCharlene Liu 194239c03e00SCharlene Liu if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) 194339c03e00SCharlene Liu stream->phy_pix_clk *= 2; 19444562236bSHarry Wentland } 19454562236bSHarry Wentland 1946d2d7885fSAnthony Koo static int acquire_resource_from_hw_enabled_state( 1947d2d7885fSAnthony Koo struct resource_context *res_ctx, 1948d2d7885fSAnthony Koo const struct resource_pool *pool, 1949d2d7885fSAnthony Koo struct dc_stream_state *stream) 1950d2d7885fSAnthony Koo { 1951d2d7885fSAnthony Koo struct dc_link *link = stream->link; 195208b66279SMartin Leung unsigned int i, inst, tg_inst = 0; 1953d2d7885fSAnthony Koo 1954d2d7885fSAnthony Koo /* Check for enabled DIG to identify enabled display */ 1955d2d7885fSAnthony Koo if (!link->link_enc->funcs->is_dig_enabled(link->link_enc)) 1956d2d7885fSAnthony Koo return -1; 1957d2d7885fSAnthony Koo 19585ec43edaSMartin Leung inst = link->link_enc->funcs->get_dig_frontend(link->link_enc); 1959d2d7885fSAnthony Koo 19607f7652eeSMartin Leung if (inst == ENGINE_ID_UNKNOWN) 196175441d9dSMikita Lipski return -1; 1962d2d7885fSAnthony Koo 19637f7652eeSMartin Leung for (i = 0; i < pool->stream_enc_count; i++) { 19647f7652eeSMartin Leung if (pool->stream_enc[i]->id == inst) { 19657f7652eeSMartin Leung tg_inst = pool->stream_enc[i]->funcs->dig_source_otg( 19667f7652eeSMartin Leung pool->stream_enc[i]); 19677f7652eeSMartin Leung break; 19687f7652eeSMartin Leung } 19697f7652eeSMartin Leung } 1970d2d7885fSAnthony Koo 19717f7652eeSMartin Leung // tg_inst not found 19727f7652eeSMartin Leung if (i == pool->stream_enc_count) 197375441d9dSMikita Lipski return -1; 19745ec43edaSMartin Leung 19755ec43edaSMartin Leung if (tg_inst >= pool->timing_generator_count) 197675441d9dSMikita Lipski return -1; 19775ec43edaSMartin Leung 19785ec43edaSMartin Leung if (!res_ctx->pipe_ctx[tg_inst].stream) { 19795ec43edaSMartin Leung struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[tg_inst]; 19805ec43edaSMartin Leung 19815ec43edaSMartin Leung pipe_ctx->stream_res.tg = pool->timing_generators[tg_inst]; 19825ec43edaSMartin Leung pipe_ctx->plane_res.mi = pool->mis[tg_inst]; 19835ec43edaSMartin Leung pipe_ctx->plane_res.hubp = pool->hubps[tg_inst]; 19845ec43edaSMartin Leung pipe_ctx->plane_res.ipp = pool->ipps[tg_inst]; 19855ec43edaSMartin Leung pipe_ctx->plane_res.xfm = pool->transforms[tg_inst]; 19865ec43edaSMartin Leung pipe_ctx->plane_res.dpp = pool->dpps[tg_inst]; 19875ec43edaSMartin Leung pipe_ctx->stream_res.opp = pool->opps[tg_inst]; 19885ec43edaSMartin Leung 1989ccce745cSMartin Leung if (pool->dpps[tg_inst]) { 19905ec43edaSMartin Leung pipe_ctx->plane_res.mpcc_inst = pool->dpps[tg_inst]->inst; 1991ccce745cSMartin Leung 1992ccce745cSMartin Leung // Read DPP->MPCC->OPP Pipe from HW State 1993ccce745cSMartin Leung if (pool->mpc->funcs->read_mpcc_state) { 1994ccce745cSMartin Leung struct mpcc_state s = {0}; 1995ccce745cSMartin Leung 1996ccce745cSMartin Leung pool->mpc->funcs->read_mpcc_state(pool->mpc, pipe_ctx->plane_res.mpcc_inst, &s); 1997ccce745cSMartin Leung 1998ccce745cSMartin Leung if (s.dpp_id < MAX_MPCC) 1999ccce745cSMartin Leung pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].dpp_id = s.dpp_id; 2000ccce745cSMartin Leung 2001ccce745cSMartin Leung if (s.bot_mpcc_id < MAX_MPCC) 2002ccce745cSMartin Leung pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].mpcc_bot = 2003ccce745cSMartin Leung &pool->mpc->mpcc_array[s.bot_mpcc_id]; 2004ccce745cSMartin Leung 2005ccce745cSMartin Leung if (s.opp_id < MAX_OPP) 2006ccce745cSMartin Leung pipe_ctx->stream_res.opp->mpc_tree_params.opp_id = s.opp_id; 2007ccce745cSMartin Leung } 2008ccce745cSMartin Leung } 20095ec43edaSMartin Leung pipe_ctx->pipe_idx = tg_inst; 2010d2d7885fSAnthony Koo 2011d2d7885fSAnthony Koo pipe_ctx->stream = stream; 20125ec43edaSMartin Leung return tg_inst; 2013d2d7885fSAnthony Koo } 2014d2d7885fSAnthony Koo 2015d2d7885fSAnthony Koo return -1; 2016d2d7885fSAnthony Koo } 2017d2d7885fSAnthony Koo 20184562236bSHarry Wentland enum dc_status resource_map_pool_resources( 2019fb3466a4SBhawanpreet Lakha const struct dc *dc, 2020608ac7bbSJerry Zuo struct dc_state *context, 20211dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 20224562236bSHarry Wentland { 2023a2b8659dSTony Cheng const struct resource_pool *pool = dc->res_pool; 20241dc90497SAndrey Grodzovsky int i; 20251dc90497SAndrey Grodzovsky struct dc_context *dc_ctx = dc->ctx; 20261dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = NULL; 20271dc90497SAndrey Grodzovsky int pipe_idx = -1; 202846570f09SAnthony Koo struct dc_bios *dcb = dc->ctx->dc_bios; 20294562236bSHarry Wentland 20301dc90497SAndrey Grodzovsky /* TODO Check if this is needed */ 20311dc90497SAndrey Grodzovsky /*if (!resource_is_stream_unchanged(old_context, stream)) { 2032430ef426SDmytro Laktyushkin if (stream != NULL && old_context->streams[i] != NULL) { 20334b679bc3SCharlene Liu stream->bit_depth_params = 2034430ef426SDmytro Laktyushkin old_context->streams[i]->bit_depth_params; 2035430ef426SDmytro Laktyushkin stream->clamping = old_context->streams[i]->clamping; 20364562236bSHarry Wentland continue; 20374b679bc3SCharlene Liu } 20384b679bc3SCharlene Liu } 20394562236bSHarry Wentland */ 20404562236bSHarry Wentland 204108e1c28dSYogesh Mohan Marimuthu calculate_phy_pix_clks(stream); 204208e1c28dSYogesh Mohan Marimuthu 204346570f09SAnthony Koo /* TODO: Check Linux */ 204446570f09SAnthony Koo if (dc->config.allow_seamless_boot_optimization && 204546570f09SAnthony Koo !dcb->funcs->is_accelerated_mode(dcb)) { 204646570f09SAnthony Koo if (dc_validate_seamless_boot_timing(dc, stream->sink, &stream->timing)) 204746570f09SAnthony Koo stream->apply_seamless_boot_optimization = true; 204846570f09SAnthony Koo } 204946570f09SAnthony Koo 2050d2d7885fSAnthony Koo if (stream->apply_seamless_boot_optimization) 2051d2d7885fSAnthony Koo pipe_idx = acquire_resource_from_hw_enabled_state( 2052d2d7885fSAnthony Koo &context->res_ctx, 2053d2d7885fSAnthony Koo pool, 2054d2d7885fSAnthony Koo stream); 2055d2d7885fSAnthony Koo 2056d2d7885fSAnthony Koo if (pipe_idx < 0) 20574562236bSHarry Wentland /* acquire new resources */ 20585d11e9fcSDmytro Laktyushkin pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); 20591dc90497SAndrey Grodzovsky 2060b86a1aa3SBhawanpreet Lakha #ifdef CONFIG_DRM_AMD_DC_DCN 20615d11e9fcSDmytro Laktyushkin if (pipe_idx < 0) 206213ab1b44SYongqiang Sun pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 206394c6d735SHarry Wentland #endif 206413ab1b44SYongqiang Sun 2065c5b38aecSDmytro Laktyushkin if (pipe_idx < 0 || context->res_ctx.pipe_ctx[pipe_idx].stream_res.tg == NULL) 20664562236bSHarry Wentland return DC_NO_CONTROLLER_RESOURCE; 20674562236bSHarry Wentland 20684562236bSHarry Wentland pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; 20694562236bSHarry Wentland 20708e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc = 207178cc70b1SWesley Chalmers dc->res_pool->funcs->find_first_free_match_stream_enc_for_link( 2072a2b8659dSTony Cheng &context->res_ctx, pool, stream); 20734562236bSHarry Wentland 20748e9c4c8cSHarry Wentland if (!pipe_ctx->stream_res.stream_enc) 207538684e46SEric Bernstein return DC_NO_STREAM_ENC_RESOURCE; 20764562236bSHarry Wentland 20771dc90497SAndrey Grodzovsky update_stream_engine_usage( 2078a2b8659dSTony Cheng &context->res_ctx, pool, 20791dc90497SAndrey Grodzovsky pipe_ctx->stream_res.stream_enc, 20801dc90497SAndrey Grodzovsky true); 20814562236bSHarry Wentland 20824562236bSHarry Wentland /* TODO: Add check if ASIC support and EDID audio */ 2083ceb3dbb4SJun Lei if (!stream->converter_disable_audio && 20844562236bSHarry Wentland dc_is_audio_capable_signal(pipe_ctx->stream->signal) && 2085ce08aad3SAlvin Lee stream->audio_info.mode_count && stream->audio_info.flags.all) { 2086afaacef4SHarry Wentland pipe_ctx->stream_res.audio = find_first_free_audio( 2087f24b0522SPaul Hsieh &context->res_ctx, pool, pipe_ctx->stream_res.stream_enc->id, dc_ctx->dce_version); 20884562236bSHarry Wentland 20894562236bSHarry Wentland /* 20904562236bSHarry Wentland * Audio assigned in order first come first get. 20914562236bSHarry Wentland * There are asics which has number of audio 20924562236bSHarry Wentland * resources less then number of pipes 20934562236bSHarry Wentland */ 2094afaacef4SHarry Wentland if (pipe_ctx->stream_res.audio) 20951dc90497SAndrey Grodzovsky update_audio_usage(&context->res_ctx, pool, 20961dc90497SAndrey Grodzovsky pipe_ctx->stream_res.audio, true); 20974562236bSHarry Wentland } 20984562236bSHarry Wentland 20999aef1a31SSivapiriyanKumarasamy /* Add ABM to the resource if on EDP */ 21009aef1a31SSivapiriyanKumarasamy if (pipe_ctx->stream && dc_is_embedded_signal(pipe_ctx->stream->signal)) 21019aef1a31SSivapiriyanKumarasamy pipe_ctx->stream_res.abm = pool->abm; 21029aef1a31SSivapiriyanKumarasamy 21031dc90497SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 21041dc90497SAndrey Grodzovsky if (context->streams[i] == stream) { 21056b670fa9SHarry Wentland context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; 21063f0940f8SCharlene Liu context->stream_status[i].stream_enc_inst = pipe_ctx->stream_res.stream_enc->stream_enc_inst; 21075fdb7c4cSNicholas Kazlauskas context->stream_status[i].audio_inst = 21085fdb7c4cSNicholas Kazlauskas pipe_ctx->stream_res.audio ? pipe_ctx->stream_res.audio->inst : -1; 21095fdb7c4cSNicholas Kazlauskas 21101dc90497SAndrey Grodzovsky return DC_OK; 21114562236bSHarry Wentland } 21124562236bSHarry Wentland 21131dc90497SAndrey Grodzovsky DC_ERROR("Stream %p not found in new ctx!\n", stream); 21141dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 21154562236bSHarry Wentland } 21164562236bSHarry Wentland 21172119aa17SDavid Francis /** 21182119aa17SDavid Francis * dc_resource_state_copy_construct_current() - Creates a new dc_state from existing state 21192119aa17SDavid Francis * Is a shallow copy. Increments refcounts on existing streams and planes. 21202119aa17SDavid Francis * @dc: copy out of dc->current_state 21212119aa17SDavid Francis * @dst_ctx: copy into this 21222119aa17SDavid Francis */ 2123f36cc577SBhawanpreet Lakha void dc_resource_state_copy_construct_current( 21241dc90497SAndrey Grodzovsky const struct dc *dc, 2125608ac7bbSJerry Zuo struct dc_state *dst_ctx) 21261dc90497SAndrey Grodzovsky { 2127f36cc577SBhawanpreet Lakha dc_resource_state_copy_construct(dc->current_state, dst_ctx); 21281dc90497SAndrey Grodzovsky } 21291dc90497SAndrey Grodzovsky 2130ab8db3e1SAndrey Grodzovsky 2131ab8db3e1SAndrey Grodzovsky void dc_resource_state_construct( 2132ab8db3e1SAndrey Grodzovsky const struct dc *dc, 2133ab8db3e1SAndrey Grodzovsky struct dc_state *dst_ctx) 2134ab8db3e1SAndrey Grodzovsky { 2135dc88b4a6SEric Yang dst_ctx->clk_mgr = dc->clk_mgr; 2136ab8db3e1SAndrey Grodzovsky } 2137ab8db3e1SAndrey Grodzovsky 21386d822156SNikola Cornij 21396d822156SNikola Cornij bool dc_resource_is_dsc_encoding_supported(const struct dc *dc) 21406d822156SNikola Cornij { 21416d822156SNikola Cornij return dc->res_pool->res_cap->num_dsc > 0; 21426d822156SNikola Cornij } 21436d822156SNikola Cornij 21446d822156SNikola Cornij 21452119aa17SDavid Francis /** 21462119aa17SDavid Francis * dc_validate_global_state() - Determine if HW can support a given state 21472119aa17SDavid Francis * Checks HW resource availability and bandwidth requirement. 21482119aa17SDavid Francis * @dc: dc struct for this driver 21492119aa17SDavid Francis * @new_ctx: state to be validated 2150afcd526bSJoshua Aberback * @fast_validate: set to true if only yes/no to support matters 21512119aa17SDavid Francis * 21522119aa17SDavid Francis * Return: DC_OK if the result can be programmed. Otherwise, an error code. 21532119aa17SDavid Francis */ 2154e750d56dSYongqiang Sun enum dc_status dc_validate_global_state( 21551dc90497SAndrey Grodzovsky struct dc *dc, 2156afcd526bSJoshua Aberback struct dc_state *new_ctx, 2157afcd526bSJoshua Aberback bool fast_validate) 21581dc90497SAndrey Grodzovsky { 21591dc90497SAndrey Grodzovsky enum dc_status result = DC_ERROR_UNEXPECTED; 21601dc90497SAndrey Grodzovsky int i, j; 21611dc90497SAndrey Grodzovsky 2162e41ab030SHarry Wentland if (!new_ctx) 2163e41ab030SHarry Wentland return DC_ERROR_UNEXPECTED; 2164e41ab030SHarry Wentland 2165d596e5d0SYongqiang Sun if (dc->res_pool->funcs->validate_global) { 2166d596e5d0SYongqiang Sun result = dc->res_pool->funcs->validate_global(dc, new_ctx); 2167d596e5d0SYongqiang Sun if (result != DC_OK) 2168d596e5d0SYongqiang Sun return result; 2169d596e5d0SYongqiang Sun } 21701dc90497SAndrey Grodzovsky 2171e41ab030SHarry Wentland for (i = 0; i < new_ctx->stream_count; i++) { 21721dc90497SAndrey Grodzovsky struct dc_stream_state *stream = new_ctx->streams[i]; 21731dc90497SAndrey Grodzovsky 21741dc90497SAndrey Grodzovsky for (j = 0; j < dc->res_pool->pipe_count; j++) { 21751dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[j]; 21761dc90497SAndrey Grodzovsky 21771dc90497SAndrey Grodzovsky if (pipe_ctx->stream != stream) 21781dc90497SAndrey Grodzovsky continue; 21791dc90497SAndrey Grodzovsky 21808d8c82b6SJoseph Gravenor if (dc->res_pool->funcs->patch_unknown_plane_state && 218174eac5f3SSu Sung Chung pipe_ctx->plane_state && 218274eac5f3SSu Sung Chung pipe_ctx->plane_state->tiling_info.gfx9.swizzle == DC_SW_UNKNOWN) { 21838d8c82b6SJoseph Gravenor result = dc->res_pool->funcs->patch_unknown_plane_state(pipe_ctx->plane_state); 218474eac5f3SSu Sung Chung if (result != DC_OK) 218574eac5f3SSu Sung Chung return result; 218674eac5f3SSu Sung Chung } 218774eac5f3SSu Sung Chung 21881dc90497SAndrey Grodzovsky /* Switch to dp clock source only if there is 21891dc90497SAndrey Grodzovsky * no non dp stream that shares the same timing 21901dc90497SAndrey Grodzovsky * with the dp stream. 21911dc90497SAndrey Grodzovsky */ 21921dc90497SAndrey Grodzovsky if (dc_is_dp_signal(pipe_ctx->stream->signal) && 21931dc90497SAndrey Grodzovsky !find_pll_sharable_stream(stream, new_ctx)) { 21941dc90497SAndrey Grodzovsky 21959d0dcecdSHarry Wentland resource_unreference_clock_source( 21961dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 21971dc90497SAndrey Grodzovsky dc->res_pool, 21989d0dcecdSHarry Wentland pipe_ctx->clock_source); 21994a629536SHarry Wentland 22001dc90497SAndrey Grodzovsky pipe_ctx->clock_source = dc->res_pool->dp_clock_source; 22011dc90497SAndrey Grodzovsky resource_reference_clock_source( 22021dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 22031dc90497SAndrey Grodzovsky dc->res_pool, 22041dc90497SAndrey Grodzovsky pipe_ctx->clock_source); 22051dc90497SAndrey Grodzovsky } 22061dc90497SAndrey Grodzovsky } 22071dc90497SAndrey Grodzovsky } 22081dc90497SAndrey Grodzovsky 22091dc90497SAndrey Grodzovsky result = resource_build_scaling_params_for_context(dc, new_ctx); 22101dc90497SAndrey Grodzovsky 22111dc90497SAndrey Grodzovsky if (result == DC_OK) 2212afcd526bSJoshua Aberback if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, fast_validate)) 22131dc90497SAndrey Grodzovsky result = DC_FAIL_BANDWIDTH_VALIDATE; 22141dc90497SAndrey Grodzovsky 22151dc90497SAndrey Grodzovsky return result; 22161dc90497SAndrey Grodzovsky } 22171dc90497SAndrey Grodzovsky 22186e4d6beeSTony Cheng static void patch_gamut_packet_checksum( 2219e09b6473SAnthony Koo struct dc_info_packet *gamut_packet) 22204562236bSHarry Wentland { 22214562236bSHarry Wentland /* For gamut we recalc checksum */ 22226e4d6beeSTony Cheng if (gamut_packet->valid) { 22234562236bSHarry Wentland uint8_t chk_sum = 0; 22244562236bSHarry Wentland uint8_t *ptr; 22254562236bSHarry Wentland uint8_t i; 22264562236bSHarry Wentland 22274562236bSHarry Wentland /*start of the Gamut data. */ 22286e4d6beeSTony Cheng ptr = &gamut_packet->sb[3]; 22294562236bSHarry Wentland 22306e4d6beeSTony Cheng for (i = 0; i <= gamut_packet->sb[1]; i++) 22314562236bSHarry Wentland chk_sum += ptr[i]; 22324562236bSHarry Wentland 22336e4d6beeSTony Cheng gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum); 22341646a6feSAndrew Wong } 22354562236bSHarry Wentland } 22364562236bSHarry Wentland 22374562236bSHarry Wentland static void set_avi_info_frame( 2238e09b6473SAnthony Koo struct dc_info_packet *info_packet, 22394562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 22404562236bSHarry Wentland { 22410971c40eSHarry Wentland struct dc_stream_state *stream = pipe_ctx->stream; 22424562236bSHarry Wentland enum dc_color_space color_space = COLOR_SPACE_UNKNOWN; 22434562236bSHarry Wentland uint32_t pixel_encoding = 0; 22444562236bSHarry Wentland enum scanning_type scan_type = SCANNING_TYPE_NODATA; 22454562236bSHarry Wentland enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA; 22464562236bSHarry Wentland bool itc = false; 224750e27654SZeyu Fan uint8_t itc_value = 0; 22484562236bSHarry Wentland uint8_t cn0_cn1 = 0; 224950e27654SZeyu Fan unsigned int cn0_cn1_value = 0; 22504562236bSHarry Wentland uint8_t *check_sum = NULL; 22514562236bSHarry Wentland uint8_t byte_index = 0; 2252754e3673SAnthony Koo union hdmi_info_packet hdmi_info; 225350e27654SZeyu Fan union display_content_support support = {0}; 22544fa086b9SLeo (Sunpeng) Li unsigned int vic = pipe_ctx->stream->timing.vic; 225515e17335SCharlene Liu enum dc_timing_3d_format format; 22564562236bSHarry Wentland 2257754e3673SAnthony Koo memset(&hdmi_info, 0, sizeof(union hdmi_info_packet)); 2258754e3673SAnthony Koo 22594fa086b9SLeo (Sunpeng) Li color_space = pipe_ctx->stream->output_color_space; 2260e5f2038eSCharlene Liu if (color_space == COLOR_SPACE_UNKNOWN) 22614fa086b9SLeo (Sunpeng) Li color_space = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ? 2262e5f2038eSCharlene Liu COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709; 22634562236bSHarry Wentland 22644562236bSHarry Wentland /* Initialize header */ 2265e09b6473SAnthony Koo hdmi_info.bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI; 22664562236bSHarry Wentland /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall 22674562236bSHarry Wentland * not be used in HDMI 2.0 (Section 10.1) */ 2268e09b6473SAnthony Koo hdmi_info.bits.header.version = 2; 2269e09b6473SAnthony Koo hdmi_info.bits.header.length = HDMI_AVI_INFOFRAME_SIZE; 22704562236bSHarry Wentland 22714562236bSHarry Wentland /* 22724562236bSHarry Wentland * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built 22734562236bSHarry Wentland * according to HDMI 2.0 spec (Section 10.1) 22744562236bSHarry Wentland */ 22754562236bSHarry Wentland 22764fa086b9SLeo (Sunpeng) Li switch (stream->timing.pixel_encoding) { 22774562236bSHarry Wentland case PIXEL_ENCODING_YCBCR422: 22784562236bSHarry Wentland pixel_encoding = 1; 22794562236bSHarry Wentland break; 22804562236bSHarry Wentland 22814562236bSHarry Wentland case PIXEL_ENCODING_YCBCR444: 22824562236bSHarry Wentland pixel_encoding = 2; 22834562236bSHarry Wentland break; 22844562236bSHarry Wentland case PIXEL_ENCODING_YCBCR420: 22854562236bSHarry Wentland pixel_encoding = 3; 22864562236bSHarry Wentland break; 22874562236bSHarry Wentland 22884562236bSHarry Wentland case PIXEL_ENCODING_RGB: 22894562236bSHarry Wentland default: 22904562236bSHarry Wentland pixel_encoding = 0; 22914562236bSHarry Wentland } 22924562236bSHarry Wentland 22934562236bSHarry Wentland /* Y0_Y1_Y2 : The pixel encoding */ 22944562236bSHarry Wentland /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */ 2295e09b6473SAnthony Koo hdmi_info.bits.Y0_Y1_Y2 = pixel_encoding; 22964562236bSHarry Wentland 22974562236bSHarry Wentland /* A0 = 1 Active Format Information valid */ 2298e09b6473SAnthony Koo hdmi_info.bits.A0 = ACTIVE_FORMAT_VALID; 22994562236bSHarry Wentland 23004562236bSHarry Wentland /* B0, B1 = 3; Bar info data is valid */ 2301e09b6473SAnthony Koo hdmi_info.bits.B0_B1 = BAR_INFO_BOTH_VALID; 23024562236bSHarry Wentland 2303e09b6473SAnthony Koo hdmi_info.bits.SC0_SC1 = PICTURE_SCALING_UNIFORM; 23044562236bSHarry Wentland 23054562236bSHarry Wentland /* S0, S1 : Underscan / Overscan */ 23064562236bSHarry Wentland /* TODO: un-hardcode scan type */ 23074562236bSHarry Wentland scan_type = SCANNING_TYPE_UNDERSCAN; 2308e09b6473SAnthony Koo hdmi_info.bits.S0_S1 = scan_type; 23094562236bSHarry Wentland 23104562236bSHarry Wentland /* C0, C1 : Colorimetry */ 23118fde5884SCharlene Liu if (color_space == COLOR_SPACE_YCBCR709 || 231215e17335SCharlene Liu color_space == COLOR_SPACE_YCBCR709_LIMITED) 2313e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709; 23148fde5884SCharlene Liu else if (color_space == COLOR_SPACE_YCBCR601 || 23158fde5884SCharlene Liu color_space == COLOR_SPACE_YCBCR601_LIMITED) 2316e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_ITU601; 23178fde5884SCharlene Liu else { 2318e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_NO_DATA; 23198fde5884SCharlene Liu } 2320534db198SAmy Zhang if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE || 2321534db198SAmy Zhang color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE || 2322534db198SAmy Zhang color_space == COLOR_SPACE_2020_YCBCR) { 2323e09b6473SAnthony Koo hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR; 2324e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; 2325534db198SAmy Zhang } else if (color_space == COLOR_SPACE_ADOBERGB) { 2326e09b6473SAnthony Koo hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB; 2327e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; 2328534db198SAmy Zhang } 2329534db198SAmy Zhang 23304562236bSHarry Wentland /* TODO: un-hardcode aspect ratio */ 23314fa086b9SLeo (Sunpeng) Li aspect = stream->timing.aspect_ratio; 23324562236bSHarry Wentland 23334562236bSHarry Wentland switch (aspect) { 23344562236bSHarry Wentland case ASPECT_RATIO_4_3: 23354562236bSHarry Wentland case ASPECT_RATIO_16_9: 2336e09b6473SAnthony Koo hdmi_info.bits.M0_M1 = aspect; 23374562236bSHarry Wentland break; 23384562236bSHarry Wentland 23394562236bSHarry Wentland case ASPECT_RATIO_NO_DATA: 23404562236bSHarry Wentland case ASPECT_RATIO_64_27: 23414562236bSHarry Wentland case ASPECT_RATIO_256_135: 23424562236bSHarry Wentland default: 2343e09b6473SAnthony Koo hdmi_info.bits.M0_M1 = 0; 23444562236bSHarry Wentland } 23454562236bSHarry Wentland 23464562236bSHarry Wentland /* Active Format Aspect ratio - same as Picture Aspect Ratio. */ 2347e09b6473SAnthony Koo hdmi_info.bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; 23484562236bSHarry Wentland 23494562236bSHarry Wentland /* TODO: un-hardcode cn0_cn1 and itc */ 235050e27654SZeyu Fan 23514562236bSHarry Wentland cn0_cn1 = 0; 235250e27654SZeyu Fan cn0_cn1_value = 0; 235350e27654SZeyu Fan 235450e27654SZeyu Fan itc = true; 235550e27654SZeyu Fan itc_value = 1; 235650e27654SZeyu Fan 2357ceb3dbb4SJun Lei support = stream->content_support; 23584562236bSHarry Wentland 23594562236bSHarry Wentland if (itc) { 236050e27654SZeyu Fan if (!support.bits.valid_content_type) { 236150e27654SZeyu Fan cn0_cn1_value = 0; 236250e27654SZeyu Fan } else { 236350e27654SZeyu Fan if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) { 236450e27654SZeyu Fan if (support.bits.graphics_content == 1) { 236550e27654SZeyu Fan cn0_cn1_value = 0; 236650e27654SZeyu Fan } 236750e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) { 236850e27654SZeyu Fan if (support.bits.photo_content == 1) { 236950e27654SZeyu Fan cn0_cn1_value = 1; 237050e27654SZeyu Fan } else { 237150e27654SZeyu Fan cn0_cn1_value = 0; 237250e27654SZeyu Fan itc_value = 0; 237350e27654SZeyu Fan } 237450e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) { 237550e27654SZeyu Fan if (support.bits.cinema_content == 1) { 237650e27654SZeyu Fan cn0_cn1_value = 2; 237750e27654SZeyu Fan } else { 237850e27654SZeyu Fan cn0_cn1_value = 0; 237950e27654SZeyu Fan itc_value = 0; 238050e27654SZeyu Fan } 238150e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) { 238250e27654SZeyu Fan if (support.bits.game_content == 1) { 238350e27654SZeyu Fan cn0_cn1_value = 3; 238450e27654SZeyu Fan } else { 238550e27654SZeyu Fan cn0_cn1_value = 0; 238650e27654SZeyu Fan itc_value = 0; 238750e27654SZeyu Fan } 238850e27654SZeyu Fan } 238950e27654SZeyu Fan } 2390e09b6473SAnthony Koo hdmi_info.bits.CN0_CN1 = cn0_cn1_value; 2391e09b6473SAnthony Koo hdmi_info.bits.ITC = itc_value; 23924562236bSHarry Wentland } 23934562236bSHarry Wentland 23944562236bSHarry Wentland /* TODO : We should handle YCC quantization */ 23954562236bSHarry Wentland /* but we do not have matrix calculation */ 2396ceb3dbb4SJun Lei if (stream->qs_bit == 1 && 2397ceb3dbb4SJun Lei stream->qy_bit == 1) { 239850e27654SZeyu Fan if (color_space == COLOR_SPACE_SRGB || 239950e27654SZeyu Fan color_space == COLOR_SPACE_2020_RGB_FULLRANGE) { 2400e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; 2401993dca3eSQingqing Zhuo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 240250e27654SZeyu Fan } else if (color_space == COLOR_SPACE_SRGB_LIMITED || 240350e27654SZeyu Fan color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) { 2404e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE; 2405e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 24064562236bSHarry Wentland } else { 2407e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 2408e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 24094562236bSHarry Wentland } 241050e27654SZeyu Fan } else { 2411e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 2412e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 241350e27654SZeyu Fan } 241450e27654SZeyu Fan 241515e17335SCharlene Liu ///VIC 24164fa086b9SLeo (Sunpeng) Li format = stream->timing.timing_3d_format; 241715e17335SCharlene Liu /*todo, add 3DStereo support*/ 241815e17335SCharlene Liu if (format != TIMING_3D_FORMAT_NONE) { 241915e17335SCharlene Liu // Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled 24204fa086b9SLeo (Sunpeng) Li switch (pipe_ctx->stream->timing.hdmi_vic) { 242115e17335SCharlene Liu case 1: 242215e17335SCharlene Liu vic = 95; 242315e17335SCharlene Liu break; 242415e17335SCharlene Liu case 2: 242515e17335SCharlene Liu vic = 94; 242615e17335SCharlene Liu break; 242715e17335SCharlene Liu case 3: 242815e17335SCharlene Liu vic = 93; 242915e17335SCharlene Liu break; 243015e17335SCharlene Liu case 4: 243115e17335SCharlene Liu vic = 98; 243215e17335SCharlene Liu break; 243315e17335SCharlene Liu default: 243415e17335SCharlene Liu break; 243515e17335SCharlene Liu } 243615e17335SCharlene Liu } 2437efa02336SChris Park /* If VIC >= 128, the Source shall use AVI InfoFrame Version 3*/ 2438e09b6473SAnthony Koo hdmi_info.bits.VIC0_VIC7 = vic; 2439efa02336SChris Park if (vic >= 128) 2440efa02336SChris Park hdmi_info.bits.header.version = 3; 2441efa02336SChris Park /* If (C1, C0)=(1, 1) and (EC2, EC1, EC0)=(1, 1, 1), 2442efa02336SChris Park * the Source shall use 20 AVI InfoFrame Version 4 2443efa02336SChris Park */ 2444efa02336SChris Park if (hdmi_info.bits.C0_C1 == COLORIMETRY_EXTENDED && 2445efa02336SChris Park hdmi_info.bits.EC0_EC2 == COLORIMETRYEX_RESERVED) { 2446efa02336SChris Park hdmi_info.bits.header.version = 4; 2447efa02336SChris Park hdmi_info.bits.header.length = 14; 2448efa02336SChris Park } 24494562236bSHarry Wentland 24504562236bSHarry Wentland /* pixel repetition 24514562236bSHarry Wentland * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel 24524562236bSHarry Wentland * repetition start from 1 */ 2453e09b6473SAnthony Koo hdmi_info.bits.PR0_PR3 = 0; 24544562236bSHarry Wentland 24554562236bSHarry Wentland /* Bar Info 24564562236bSHarry Wentland * barTop: Line Number of End of Top Bar. 24574562236bSHarry Wentland * barBottom: Line Number of Start of Bottom Bar. 24584562236bSHarry Wentland * barLeft: Pixel Number of End of Left Bar. 24594562236bSHarry Wentland * barRight: Pixel Number of Start of Right Bar. */ 2460e09b6473SAnthony Koo hdmi_info.bits.bar_top = stream->timing.v_border_top; 2461e09b6473SAnthony Koo hdmi_info.bits.bar_bottom = (stream->timing.v_total 24624fa086b9SLeo (Sunpeng) Li - stream->timing.v_border_bottom + 1); 2463e09b6473SAnthony Koo hdmi_info.bits.bar_left = stream->timing.h_border_left; 2464e09b6473SAnthony Koo hdmi_info.bits.bar_right = (stream->timing.h_total 24654fa086b9SLeo (Sunpeng) Li - stream->timing.h_border_right + 1); 24664562236bSHarry Wentland 24672f482c4fSChris Park /* Additional Colorimetry Extension 24682f482c4fSChris Park * Used in conduction with C0-C1 and EC0-EC2 24692f482c4fSChris Park * 0 = DCI-P3 RGB (D65) 24702f482c4fSChris Park * 1 = DCI-P3 RGB (theater) 24712f482c4fSChris Park */ 24722f482c4fSChris Park hdmi_info.bits.ACE0_ACE3 = 0; 24732f482c4fSChris Park 24744562236bSHarry Wentland /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ 2475e09b6473SAnthony Koo check_sum = &hdmi_info.packet_raw_data.sb[0]; 2476e8d726b7SReza Amini 2477efa02336SChris Park *check_sum = HDMI_INFOFRAME_TYPE_AVI + hdmi_info.bits.header.length + hdmi_info.bits.header.version; 24784562236bSHarry Wentland 2479efa02336SChris Park for (byte_index = 1; byte_index <= hdmi_info.bits.header.length; byte_index++) 2480e09b6473SAnthony Koo *check_sum += hdmi_info.packet_raw_data.sb[byte_index]; 24814562236bSHarry Wentland 24824562236bSHarry Wentland /* one byte complement */ 24834562236bSHarry Wentland *check_sum = (uint8_t) (0x100 - *check_sum); 24844562236bSHarry Wentland 24854562236bSHarry Wentland /* Store in hw_path_mode */ 2486e09b6473SAnthony Koo info_packet->hb0 = hdmi_info.packet_raw_data.hb0; 2487e09b6473SAnthony Koo info_packet->hb1 = hdmi_info.packet_raw_data.hb1; 2488e09b6473SAnthony Koo info_packet->hb2 = hdmi_info.packet_raw_data.hb2; 24894562236bSHarry Wentland 2490e09b6473SAnthony Koo for (byte_index = 0; byte_index < sizeof(hdmi_info.packet_raw_data.sb); byte_index++) 2491e09b6473SAnthony Koo info_packet->sb[byte_index] = hdmi_info.packet_raw_data.sb[byte_index]; 24924562236bSHarry Wentland 24934562236bSHarry Wentland info_packet->valid = true; 24944562236bSHarry Wentland } 24954562236bSHarry Wentland 24966e4d6beeSTony Cheng static void set_vendor_info_packet( 2497e09b6473SAnthony Koo struct dc_info_packet *info_packet, 24980971c40eSHarry Wentland struct dc_stream_state *stream) 24994562236bSHarry Wentland { 2500ecd0136bSHarmanprit Tatla /* SPD info packet for FreeSync */ 250115e17335SCharlene Liu 2502ecd0136bSHarmanprit Tatla /* Check if Freesync is supported. Return if false. If true, 2503ecd0136bSHarmanprit Tatla * set the corresponding bit in the info packet 2504ecd0136bSHarmanprit Tatla */ 2505ecd0136bSHarmanprit Tatla if (!stream->vsp_infopacket.valid) 25064562236bSHarry Wentland return; 25074562236bSHarry Wentland 2508ecd0136bSHarmanprit Tatla *info_packet = stream->vsp_infopacket; 25094562236bSHarry Wentland } 25104562236bSHarry Wentland 25116e4d6beeSTony Cheng static void set_spd_info_packet( 2512e09b6473SAnthony Koo struct dc_info_packet *info_packet, 25130971c40eSHarry Wentland struct dc_stream_state *stream) 25144562236bSHarry Wentland { 25154562236bSHarry Wentland /* SPD info packet for FreeSync */ 25164562236bSHarry Wentland 25174562236bSHarry Wentland /* Check if Freesync is supported. Return if false. If true, 25184562236bSHarry Wentland * set the corresponding bit in the info packet 25194562236bSHarry Wentland */ 252098e6436dSAnthony Koo if (!stream->vrr_infopacket.valid) 25214562236bSHarry Wentland return; 25224562236bSHarry Wentland 252398e6436dSAnthony Koo *info_packet = stream->vrr_infopacket; 25244562236bSHarry Wentland } 25254562236bSHarry Wentland 25261646a6feSAndrew Wong static void set_hdr_static_info_packet( 2527e09b6473SAnthony Koo struct dc_info_packet *info_packet, 25280971c40eSHarry Wentland struct dc_stream_state *stream) 25291646a6feSAndrew Wong { 25300eeef690SAnthony Koo /* HDR Static Metadata info packet for HDR10 */ 25311646a6feSAndrew Wong 2532a10dc97aSKrunoslav Kovac if (!stream->hdr_static_metadata.valid || 2533a10dc97aSKrunoslav Kovac stream->use_dynamic_meta) 253410bff005SYongqiang Sun return; 253510bff005SYongqiang Sun 25360eeef690SAnthony Koo *info_packet = stream->hdr_static_metadata; 25371646a6feSAndrew Wong } 25381646a6feSAndrew Wong 25396e4d6beeSTony Cheng static void set_vsc_info_packet( 2540e09b6473SAnthony Koo struct dc_info_packet *info_packet, 25410971c40eSHarry Wentland struct dc_stream_state *stream) 25424562236bSHarry Wentland { 25431336926fSAlvin lee if (!stream->vsc_infopacket.valid) 25444562236bSHarry Wentland return; 25454562236bSHarry Wentland 25461336926fSAlvin lee *info_packet = stream->vsc_infopacket; 25474562236bSHarry Wentland } 25484562236bSHarry Wentland 2549f36cc577SBhawanpreet Lakha void dc_resource_state_destruct(struct dc_state *context) 25504562236bSHarry Wentland { 25514562236bSHarry Wentland int i, j; 25524562236bSHarry Wentland 2553ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 25543be5262eSHarry Wentland for (j = 0; j < context->stream_status[i].plane_count; j++) 25553be5262eSHarry Wentland dc_plane_state_release( 25563be5262eSHarry Wentland context->stream_status[i].plane_states[j]); 25574562236bSHarry Wentland 25583be5262eSHarry Wentland context->stream_status[i].plane_count = 0; 25594fa086b9SLeo (Sunpeng) Li dc_stream_release(context->streams[i]); 2560ab2541b6SAric Cyr context->streams[i] = NULL; 25614562236bSHarry Wentland } 25624562236bSHarry Wentland } 25634562236bSHarry Wentland 2564f36cc577SBhawanpreet Lakha void dc_resource_state_copy_construct( 2565608ac7bbSJerry Zuo const struct dc_state *src_ctx, 2566608ac7bbSJerry Zuo struct dc_state *dst_ctx) 25674562236bSHarry Wentland { 25684562236bSHarry Wentland int i, j; 25698ee5702aSDave Airlie struct kref refcount = dst_ctx->refcount; 25704562236bSHarry Wentland 25714562236bSHarry Wentland *dst_ctx = *src_ctx; 25724562236bSHarry Wentland 2573a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 25744562236bSHarry Wentland struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i]; 25754562236bSHarry Wentland 25764562236bSHarry Wentland if (cur_pipe->top_pipe) 25774562236bSHarry Wentland cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; 25784562236bSHarry Wentland 25794562236bSHarry Wentland if (cur_pipe->bottom_pipe) 25804562236bSHarry Wentland cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; 2581b1f6d01cSDmytro Laktyushkin 2582b1f6d01cSDmytro Laktyushkin if (cur_pipe->next_odm_pipe) 2583b1f6d01cSDmytro Laktyushkin cur_pipe->next_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx]; 2584b1f6d01cSDmytro Laktyushkin 2585b1f6d01cSDmytro Laktyushkin if (cur_pipe->prev_odm_pipe) 2586b1f6d01cSDmytro Laktyushkin cur_pipe->prev_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx]; 25874562236bSHarry Wentland } 25884562236bSHarry Wentland 2589ab2541b6SAric Cyr for (i = 0; i < dst_ctx->stream_count; i++) { 25904fa086b9SLeo (Sunpeng) Li dc_stream_retain(dst_ctx->streams[i]); 25913be5262eSHarry Wentland for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++) 25923be5262eSHarry Wentland dc_plane_state_retain( 25933be5262eSHarry Wentland dst_ctx->stream_status[i].plane_states[j]); 25944562236bSHarry Wentland } 25959a3afbb3SAndrey Grodzovsky 25969a3afbb3SAndrey Grodzovsky /* context refcount should not be overridden */ 25978ee5702aSDave Airlie dst_ctx->refcount = refcount; 25989a3afbb3SAndrey Grodzovsky 25994562236bSHarry Wentland } 26004562236bSHarry Wentland 26014562236bSHarry Wentland struct clock_source *dc_resource_find_first_free_pll( 2602a2b8659dSTony Cheng struct resource_context *res_ctx, 2603a2b8659dSTony Cheng const struct resource_pool *pool) 26044562236bSHarry Wentland { 26054562236bSHarry Wentland int i; 26064562236bSHarry Wentland 2607a2b8659dSTony Cheng for (i = 0; i < pool->clk_src_count; ++i) { 26084562236bSHarry Wentland if (res_ctx->clock_source_ref_count[i] == 0) 2609a2b8659dSTony Cheng return pool->clock_sources[i]; 26104562236bSHarry Wentland } 26114562236bSHarry Wentland 26124562236bSHarry Wentland return NULL; 26134562236bSHarry Wentland } 26144562236bSHarry Wentland 26154562236bSHarry Wentland void resource_build_info_frame(struct pipe_ctx *pipe_ctx) 26164562236bSHarry Wentland { 26174562236bSHarry Wentland enum signal_type signal = SIGNAL_TYPE_NONE; 261896c50c0dSHarry Wentland struct encoder_info_frame *info = &pipe_ctx->stream_res.encoder_info_frame; 26194562236bSHarry Wentland 26204562236bSHarry Wentland /* default all packets to invalid */ 26216e4d6beeSTony Cheng info->avi.valid = false; 26226e4d6beeSTony Cheng info->gamut.valid = false; 26236e4d6beeSTony Cheng info->vendor.valid = false; 2624630e3573SJeff Smith info->spd.valid = false; 26256e4d6beeSTony Cheng info->hdrsmd.valid = false; 26266e4d6beeSTony Cheng info->vsc.valid = false; 26274562236bSHarry Wentland 26284562236bSHarry Wentland signal = pipe_ctx->stream->signal; 26294562236bSHarry Wentland 26304562236bSHarry Wentland /* HDMi and DP have different info packets*/ 26314562236bSHarry Wentland if (dc_is_hdmi_signal(signal)) { 26326e4d6beeSTony Cheng set_avi_info_frame(&info->avi, pipe_ctx); 26336e4d6beeSTony Cheng 26346e4d6beeSTony Cheng set_vendor_info_packet(&info->vendor, pipe_ctx->stream); 26356e4d6beeSTony Cheng 26366e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 26376e4d6beeSTony Cheng 263856ef6ed9SAnthony Koo set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 26396e4d6beeSTony Cheng 2640a33fa99dSHarry Wentland } else if (dc_is_dp_signal(signal)) { 26416e4d6beeSTony Cheng set_vsc_info_packet(&info->vsc, pipe_ctx->stream); 26426e4d6beeSTony Cheng 26436e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 26446e4d6beeSTony Cheng 264556ef6ed9SAnthony Koo set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 2646a33fa99dSHarry Wentland } 26474562236bSHarry Wentland 26486e4d6beeSTony Cheng patch_gamut_packet_checksum(&info->gamut); 26494562236bSHarry Wentland } 26504562236bSHarry Wentland 26514562236bSHarry Wentland enum dc_status resource_map_clock_resources( 2652fb3466a4SBhawanpreet Lakha const struct dc *dc, 2653608ac7bbSJerry Zuo struct dc_state *context, 26541dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 26554562236bSHarry Wentland { 26564562236bSHarry Wentland /* acquire new resources */ 26571dc90497SAndrey Grodzovsky const struct resource_pool *pool = dc->res_pool; 26581dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream( 26591dc90497SAndrey Grodzovsky &context->res_ctx, stream); 26604562236bSHarry Wentland 26611dc90497SAndrey Grodzovsky if (!pipe_ctx) 26621dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 26634562236bSHarry Wentland 26644562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal) 26654562236bSHarry Wentland || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) 2666a2b8659dSTony Cheng pipe_ctx->clock_source = pool->dp_clock_source; 26674562236bSHarry Wentland else { 26684562236bSHarry Wentland pipe_ctx->clock_source = NULL; 26694562236bSHarry Wentland 2670fb3466a4SBhawanpreet Lakha if (!dc->config.disable_disp_pll_sharing) 26714ed4e51bSMikita Lipski pipe_ctx->clock_source = resource_find_used_clk_src_for_sharing( 26724562236bSHarry Wentland &context->res_ctx, 26734562236bSHarry Wentland pipe_ctx); 26744562236bSHarry Wentland 26754562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 26764562236bSHarry Wentland pipe_ctx->clock_source = 2677a2b8659dSTony Cheng dc_resource_find_first_free_pll( 2678a2b8659dSTony Cheng &context->res_ctx, 2679a2b8659dSTony Cheng pool); 26804562236bSHarry Wentland } 26814562236bSHarry Wentland 26824562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 26834562236bSHarry Wentland return DC_NO_CLOCK_SOURCE_RESOURCE; 26844562236bSHarry Wentland 26854562236bSHarry Wentland resource_reference_clock_source( 2686a2b8659dSTony Cheng &context->res_ctx, pool, 26874562236bSHarry Wentland pipe_ctx->clock_source); 26884562236bSHarry Wentland 26894562236bSHarry Wentland return DC_OK; 26904562236bSHarry Wentland } 26914562236bSHarry Wentland 26924562236bSHarry Wentland /* 26934562236bSHarry Wentland * Note: We need to disable output if clock sources change, 26944562236bSHarry Wentland * since bios does optimization and doesn't apply if changing 26954562236bSHarry Wentland * PHY when not already disabled. 26964562236bSHarry Wentland */ 26974562236bSHarry Wentland bool pipe_need_reprogram( 26984562236bSHarry Wentland struct pipe_ctx *pipe_ctx_old, 26994562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 27004562236bSHarry Wentland { 2701cfe4645eSDmytro Laktyushkin if (!pipe_ctx_old->stream) 2702cfe4645eSDmytro Laktyushkin return false; 2703cfe4645eSDmytro Laktyushkin 27044562236bSHarry Wentland if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink) 27054562236bSHarry Wentland return true; 27064562236bSHarry Wentland 27074562236bSHarry Wentland if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal) 27084562236bSHarry Wentland return true; 27094562236bSHarry Wentland 2710afaacef4SHarry Wentland if (pipe_ctx_old->stream_res.audio != pipe_ctx->stream_res.audio) 27114562236bSHarry Wentland return true; 27124562236bSHarry Wentland 27134562236bSHarry Wentland if (pipe_ctx_old->clock_source != pipe_ctx->clock_source 27144562236bSHarry Wentland && pipe_ctx_old->stream != pipe_ctx->stream) 27154562236bSHarry Wentland return true; 27164562236bSHarry Wentland 27178e9c4c8cSHarry Wentland if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc) 27184562236bSHarry Wentland return true; 27194562236bSHarry Wentland 27204562236bSHarry Wentland if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 27214562236bSHarry Wentland return true; 27224562236bSHarry Wentland 27236b622181SJulian Parkin if (is_hdr_static_meta_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 27246b622181SJulian Parkin return true; 27254562236bSHarry Wentland 27261e7e86c4SSamson Tam if (pipe_ctx_old->stream->dpms_off != pipe_ctx->stream->dpms_off) 27271e7e86c4SSamson Tam return true; 27281e7e86c4SSamson Tam 27291336926fSAlvin lee if (is_vsc_info_packet_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 27301336926fSAlvin lee return true; 27311336926fSAlvin lee 2732eed928dcSCharlene Liu if (false == pipe_ctx_old->stream->link->link_state_valid && 2733eed928dcSCharlene Liu false == pipe_ctx_old->stream->dpms_off) 2734eed928dcSCharlene Liu return true; 2735eed928dcSCharlene Liu 27364562236bSHarry Wentland return false; 27374562236bSHarry Wentland } 2738529cad0fSDing Wang 27390971c40eSHarry Wentland void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, 2740529cad0fSDing Wang struct bit_depth_reduction_params *fmt_bit_depth) 2741529cad0fSDing Wang { 27424fa086b9SLeo (Sunpeng) Li enum dc_dither_option option = stream->dither_option; 2743529cad0fSDing Wang enum dc_pixel_encoding pixel_encoding = 27444fa086b9SLeo (Sunpeng) Li stream->timing.pixel_encoding; 2745529cad0fSDing Wang 2746529cad0fSDing Wang memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); 2747529cad0fSDing Wang 2748603767f9STony Cheng if (option == DITHER_OPTION_DEFAULT) { 2749603767f9STony Cheng switch (stream->timing.display_color_depth) { 2750603767f9STony Cheng case COLOR_DEPTH_666: 2751603767f9STony Cheng option = DITHER_OPTION_SPATIAL6; 2752603767f9STony Cheng break; 2753603767f9STony Cheng case COLOR_DEPTH_888: 2754603767f9STony Cheng option = DITHER_OPTION_SPATIAL8; 2755603767f9STony Cheng break; 2756603767f9STony Cheng case COLOR_DEPTH_101010: 2757603767f9STony Cheng option = DITHER_OPTION_SPATIAL10; 2758603767f9STony Cheng break; 2759603767f9STony Cheng default: 2760603767f9STony Cheng option = DITHER_OPTION_DISABLE; 2761603767f9STony Cheng } 2762603767f9STony Cheng } 2763603767f9STony Cheng 2764529cad0fSDing Wang if (option == DITHER_OPTION_DISABLE) 2765529cad0fSDing Wang return; 2766529cad0fSDing Wang 2767529cad0fSDing Wang if (option == DITHER_OPTION_TRUN6) { 2768529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2769529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 0; 2770529cad0fSDing Wang } else if (option == DITHER_OPTION_TRUN8 || 2771529cad0fSDing Wang option == DITHER_OPTION_TRUN8_SPATIAL6 || 2772529cad0fSDing Wang option == DITHER_OPTION_TRUN8_FM6) { 2773529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2774529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 1; 2775529cad0fSDing Wang } else if (option == DITHER_OPTION_TRUN10 || 2776529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL6 || 2777529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8 || 2778529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM8 || 2779529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM6 || 2780529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2781529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2782529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2783529cad0fSDing Wang } 2784529cad0fSDing Wang 2785529cad0fSDing Wang /* special case - Formatter can only reduce by 4 bits at most. 2786529cad0fSDing Wang * When reducing from 12 to 6 bits, 2787529cad0fSDing Wang * HW recommends we use trunc with round mode 2788529cad0fSDing Wang * (if we did nothing, trunc to 10 bits would be used) 2789529cad0fSDing Wang * note that any 12->10 bit reduction is ignored prior to DCE8, 2790529cad0fSDing Wang * as the input was 10 bits. 2791529cad0fSDing Wang */ 2792529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2793529cad0fSDing Wang option == DITHER_OPTION_SPATIAL6 || 2794529cad0fSDing Wang option == DITHER_OPTION_FM6) { 2795529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2796529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2797529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_MODE = 1; 2798529cad0fSDing Wang } 2799529cad0fSDing Wang 2800529cad0fSDing Wang /* spatial dither 2801529cad0fSDing Wang * note that spatial modes 1-3 are never used 2802529cad0fSDing Wang */ 2803529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2804529cad0fSDing Wang option == DITHER_OPTION_SPATIAL6 || 2805529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL6 || 2806529cad0fSDing Wang option == DITHER_OPTION_TRUN8_SPATIAL6) { 2807529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2808529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0; 2809529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2810529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2811529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2812529cad0fSDing Wang } else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM || 2813529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8 || 2814529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8_FM6 || 2815529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8 || 2816529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2817529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2818529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1; 2819529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2820529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2821529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2822529cad0fSDing Wang } else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM || 2823529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10 || 2824529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM8 || 2825529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM6) { 2826529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2827529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2; 2828529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2829529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2830529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2831529cad0fSDing Wang } 2832529cad0fSDing Wang 2833529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6 || 2834529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8 || 2835529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10) { 2836529cad0fSDing Wang fmt_bit_depth->flags.FRAME_RANDOM = 0; 2837529cad0fSDing Wang } else { 2838529cad0fSDing Wang fmt_bit_depth->flags.FRAME_RANDOM = 1; 2839529cad0fSDing Wang } 2840529cad0fSDing Wang 2841529cad0fSDing Wang ////////////////////// 2842529cad0fSDing Wang //// temporal dither 2843529cad0fSDing Wang ////////////////////// 2844529cad0fSDing Wang if (option == DITHER_OPTION_FM6 || 2845529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8_FM6 || 2846529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM6 || 2847529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM6 || 2848529cad0fSDing Wang option == DITHER_OPTION_TRUN8_FM6 || 2849529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2850529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2851529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0; 2852529cad0fSDing Wang } else if (option == DITHER_OPTION_FM8 || 2853529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM8 || 2854529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM8) { 2855529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2856529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1; 2857529cad0fSDing Wang } else if (option == DITHER_OPTION_FM10) { 2858529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2859529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2; 2860529cad0fSDing Wang } 2861529cad0fSDing Wang 2862529cad0fSDing Wang fmt_bit_depth->pixel_encoding = pixel_encoding; 2863529cad0fSDing Wang } 28649345d987SAndrey Grodzovsky 286562c933f9SYongqiang Sun enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) 28669345d987SAndrey Grodzovsky { 2867ceb3dbb4SJun Lei struct dc_link *link = stream->link; 28682b77dcc5SAnthony Koo struct timing_generator *tg = dc->res_pool->timing_generators[0]; 28699345d987SAndrey Grodzovsky enum dc_status res = DC_OK; 28709345d987SAndrey Grodzovsky 28714fa086b9SLeo (Sunpeng) Li calculate_phy_pix_clks(stream); 28729345d987SAndrey Grodzovsky 28734fa086b9SLeo (Sunpeng) Li if (!tg->funcs->validate_timing(tg, &stream->timing)) 28749345d987SAndrey Grodzovsky res = DC_FAIL_CONTROLLER_VALIDATE; 28759345d987SAndrey Grodzovsky 2876248cbed6SEric Bernstein if (res == DC_OK) { 28779345d987SAndrey Grodzovsky if (!link->link_enc->funcs->validate_output_with_stream( 28784fa086b9SLeo (Sunpeng) Li link->link_enc, stream)) 28799345d987SAndrey Grodzovsky res = DC_FAIL_ENC_VALIDATE; 2880248cbed6SEric Bernstein } 28819345d987SAndrey Grodzovsky 28829345d987SAndrey Grodzovsky /* TODO: validate audio ASIC caps, encoder */ 28839345d987SAndrey Grodzovsky 28849345d987SAndrey Grodzovsky if (res == DC_OK) 28854fa086b9SLeo (Sunpeng) Li res = dc_link_validate_mode_timing(stream, 28869345d987SAndrey Grodzovsky link, 28874fa086b9SLeo (Sunpeng) Li &stream->timing); 28889345d987SAndrey Grodzovsky 288962c933f9SYongqiang Sun return res; 28909345d987SAndrey Grodzovsky } 2891792671d7SAndrey Grodzovsky 289262c933f9SYongqiang Sun enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) 2893792671d7SAndrey Grodzovsky { 289462c933f9SYongqiang Sun enum dc_status res = DC_OK; 289562c933f9SYongqiang Sun 2896792671d7SAndrey Grodzovsky /* TODO For now validates pixel format only */ 28978e7095b9SDmytro Laktyushkin if (dc->res_pool->funcs->validate_plane) 289862c933f9SYongqiang Sun return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps); 2899792671d7SAndrey Grodzovsky 290062c933f9SYongqiang Sun return res; 2901792671d7SAndrey Grodzovsky } 290274eac5f3SSu Sung Chung 290374eac5f3SSu Sung Chung unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format) 290474eac5f3SSu Sung Chung { 290574eac5f3SSu Sung Chung switch (format) { 290674eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 290774eac5f3SSu Sung Chung return 8; 290874eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 290974eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 291074eac5f3SSu Sung Chung return 12; 291174eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 291274eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 291374eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 291474eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 291574eac5f3SSu Sung Chung return 16; 291674eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 291774eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 291874eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 291974eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 292074eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 292174eac5f3SSu Sung Chung return 32; 292274eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 292374eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 292474eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 292574eac5f3SSu Sung Chung return 64; 292674eac5f3SSu Sung Chung default: 292774eac5f3SSu Sung Chung ASSERT_CRITICAL(false); 292874eac5f3SSu Sung Chung return -1; 292974eac5f3SSu Sung Chung } 293074eac5f3SSu Sung Chung } 29313ab4cc65SCharlene Liu static unsigned int get_max_audio_sample_rate(struct audio_mode *modes) 29323ab4cc65SCharlene Liu { 29333ab4cc65SCharlene Liu if (modes) { 29343ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_192) 29353ab4cc65SCharlene Liu return 192000; 29363ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_176_4) 29373ab4cc65SCharlene Liu return 176400; 29383ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_96) 29393ab4cc65SCharlene Liu return 96000; 29403ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_88_2) 29413ab4cc65SCharlene Liu return 88200; 29423ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_48) 29433ab4cc65SCharlene Liu return 48000; 29443ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_44_1) 29453ab4cc65SCharlene Liu return 44100; 29463ab4cc65SCharlene Liu if (modes->sample_rates.rate.RATE_32) 29473ab4cc65SCharlene Liu return 32000; 29483ab4cc65SCharlene Liu } 29493ab4cc65SCharlene Liu /*original logic when no audio info*/ 29503ab4cc65SCharlene Liu return 441000; 29513ab4cc65SCharlene Liu } 29523ab4cc65SCharlene Liu 29533ab4cc65SCharlene Liu void get_audio_check(struct audio_info *aud_modes, 29543ab4cc65SCharlene Liu struct audio_check *audio_chk) 29553ab4cc65SCharlene Liu { 29563ab4cc65SCharlene Liu unsigned int i; 29573ab4cc65SCharlene Liu unsigned int max_sample_rate = 0; 29583ab4cc65SCharlene Liu 29593ab4cc65SCharlene Liu if (aud_modes) { 29603ab4cc65SCharlene Liu audio_chk->audio_packet_type = 0x2;/*audio sample packet AP = .25 for layout0, 1 for layout1*/ 29613ab4cc65SCharlene Liu 29623ab4cc65SCharlene Liu audio_chk->max_audiosample_rate = 0; 29633ab4cc65SCharlene Liu for (i = 0; i < aud_modes->mode_count; i++) { 29643ab4cc65SCharlene Liu max_sample_rate = get_max_audio_sample_rate(&aud_modes->modes[i]); 29653ab4cc65SCharlene Liu if (audio_chk->max_audiosample_rate < max_sample_rate) 29663ab4cc65SCharlene Liu audio_chk->max_audiosample_rate = max_sample_rate; 29673ab4cc65SCharlene Liu /*dts takes the same as type 2: AP = 0.25*/ 29683ab4cc65SCharlene Liu } 29693ab4cc65SCharlene Liu /*check which one take more bandwidth*/ 29703ab4cc65SCharlene Liu if (audio_chk->max_audiosample_rate > 192000) 29713ab4cc65SCharlene Liu audio_chk->audio_packet_type = 0x9;/*AP =1*/ 29723ab4cc65SCharlene Liu audio_chk->acat = 0;/*not support*/ 29733ab4cc65SCharlene Liu } 29743ab4cc65SCharlene Liu } 29753ab4cc65SCharlene Liu 2976