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" 49dc37a9a0SLeo (Sunpeng) Li #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 50ff5ef992SAlex Deucher #include "dcn10/dcn10_resource.h" 51ff5ef992SAlex Deucher #endif 527ed4e635SHarry Wentland #if defined(CONFIG_DRM_AMD_DC_DCN2_0) 537ed4e635SHarry Wentland #include "dcn20/dcn20_resource.h" 547ed4e635SHarry Wentland #endif 55e22ece54SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN2_1) 56e22ece54SBhawanpreet Lakha #include "dcn21/dcn21_resource.h" 57e22ece54SBhawanpreet Lakha #endif 582c8ad2d5SAlex Deucher #include "dce120/dce120_resource.h" 595d4b05ddSBhawanpreet Lakha 605d4b05ddSBhawanpreet Lakha #define DC_LOGGER_INIT(logger) 615d4b05ddSBhawanpreet Lakha 624562236bSHarry Wentland enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) 634562236bSHarry Wentland { 644562236bSHarry Wentland enum dce_version dc_version = DCE_VERSION_UNKNOWN; 654562236bSHarry Wentland switch (asic_id.chip_family) { 664562236bSHarry Wentland 674562236bSHarry Wentland case FAMILY_CI: 684562236bSHarry Wentland dc_version = DCE_VERSION_8_0; 694562236bSHarry Wentland break; 70ebfdf0d0SAlex Deucher case FAMILY_KV: 71ebfdf0d0SAlex Deucher if (ASIC_REV_IS_KALINDI(asic_id.hw_internal_rev) || 72ebfdf0d0SAlex Deucher ASIC_REV_IS_BHAVANI(asic_id.hw_internal_rev) || 73ebfdf0d0SAlex Deucher ASIC_REV_IS_GODAVARI(asic_id.hw_internal_rev)) 74ebfdf0d0SAlex Deucher dc_version = DCE_VERSION_8_3; 75ebfdf0d0SAlex Deucher else 76ebfdf0d0SAlex Deucher dc_version = DCE_VERSION_8_1; 77ebfdf0d0SAlex Deucher break; 784562236bSHarry Wentland case FAMILY_CZ: 794562236bSHarry Wentland dc_version = DCE_VERSION_11_0; 804562236bSHarry Wentland break; 814562236bSHarry Wentland 824562236bSHarry Wentland case FAMILY_VI: 834562236bSHarry Wentland if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) || 844562236bSHarry Wentland ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) { 854562236bSHarry Wentland dc_version = DCE_VERSION_10_0; 864562236bSHarry Wentland break; 874562236bSHarry Wentland } 884562236bSHarry Wentland if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) || 89b264d345SJordan Lazare ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || 90b264d345SJordan Lazare ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) { 914562236bSHarry Wentland dc_version = DCE_VERSION_11_2; 924562236bSHarry Wentland } 930c75d5acSJerry (Fangzhi) Zuo if (ASIC_REV_IS_VEGAM(asic_id.hw_internal_rev)) 940c75d5acSJerry (Fangzhi) Zuo dc_version = DCE_VERSION_11_22; 954562236bSHarry Wentland break; 962c8ad2d5SAlex Deucher case FAMILY_AI: 97b8b6ce89SLeo Li if (ASICREV_IS_VEGA20_P(asic_id.hw_internal_rev)) 98b8b6ce89SLeo Li dc_version = DCE_VERSION_12_1; 99b8b6ce89SLeo Li else 1002c8ad2d5SAlex Deucher dc_version = DCE_VERSION_12_0; 1012c8ad2d5SAlex Deucher break; 102dc37a9a0SLeo (Sunpeng) Li #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 103ff5ef992SAlex Deucher case FAMILY_RV: 104ff5ef992SAlex Deucher dc_version = DCN_VERSION_1_0; 1050e3d73f1SBhawanpreet Lakha if (ASICREV_IS_RAVEN2(asic_id.hw_internal_rev)) 1060e3d73f1SBhawanpreet Lakha dc_version = DCN_VERSION_1_01; 107e22ece54SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN2_1) 108e22ece54SBhawanpreet Lakha if (ASICREV_IS_RENOIR(asic_id.hw_internal_rev)) 109e22ece54SBhawanpreet Lakha dc_version = DCN_VERSION_2_1; 110e22ece54SBhawanpreet Lakha #endif 111ff5ef992SAlex Deucher break; 112ff5ef992SAlex Deucher #endif 1137ed4e635SHarry Wentland 1147ed4e635SHarry Wentland #if defined(CONFIG_DRM_AMD_DC_DCN2_0) 1157ed4e635SHarry Wentland case FAMILY_NV: 1167ed4e635SHarry Wentland dc_version = DCN_VERSION_2_0; 1177ed4e635SHarry Wentland break; 1187ed4e635SHarry Wentland #endif 1194562236bSHarry Wentland default: 1204562236bSHarry Wentland dc_version = DCE_VERSION_UNKNOWN; 1214562236bSHarry Wentland break; 1224562236bSHarry Wentland } 1234562236bSHarry Wentland return dc_version; 1244562236bSHarry Wentland } 1254562236bSHarry Wentland 126d9673c92SHarry Wentland struct resource_pool *dc_create_resource_pool(struct dc *dc, 127d9673c92SHarry Wentland const struct dc_init_data *init_data, 128d9673c92SHarry Wentland enum dce_version dc_version) 1294562236bSHarry Wentland { 1305ac3d3c9SCharlene Liu struct resource_pool *res_pool = NULL; 1314562236bSHarry Wentland 1324562236bSHarry Wentland switch (dc_version) { 1334562236bSHarry Wentland case DCE_VERSION_8_0: 1345ac3d3c9SCharlene Liu res_pool = dce80_create_resource_pool( 135d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1365ac3d3c9SCharlene Liu break; 1377992a629SAlex Deucher case DCE_VERSION_8_1: 1387992a629SAlex Deucher res_pool = dce81_create_resource_pool( 139d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1407992a629SAlex Deucher break; 1417992a629SAlex Deucher case DCE_VERSION_8_3: 1427992a629SAlex Deucher res_pool = dce83_create_resource_pool( 143d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1447992a629SAlex Deucher break; 1454562236bSHarry Wentland case DCE_VERSION_10_0: 1465ac3d3c9SCharlene Liu res_pool = dce100_create_resource_pool( 147d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1485ac3d3c9SCharlene Liu break; 1494562236bSHarry Wentland case DCE_VERSION_11_0: 1505ac3d3c9SCharlene Liu res_pool = dce110_create_resource_pool( 151d9673c92SHarry Wentland init_data->num_virtual_links, dc, 152d9673c92SHarry Wentland init_data->asic_id); 1535ac3d3c9SCharlene Liu break; 1544562236bSHarry Wentland case DCE_VERSION_11_2: 1550c75d5acSJerry (Fangzhi) Zuo case DCE_VERSION_11_22: 1565ac3d3c9SCharlene Liu res_pool = dce112_create_resource_pool( 157d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1585ac3d3c9SCharlene Liu break; 1592c8ad2d5SAlex Deucher case DCE_VERSION_12_0: 160b8b6ce89SLeo Li case DCE_VERSION_12_1: 1612c8ad2d5SAlex Deucher res_pool = dce120_create_resource_pool( 162d9673c92SHarry Wentland init_data->num_virtual_links, dc); 1632c8ad2d5SAlex Deucher break; 164ff5ef992SAlex Deucher 165dc37a9a0SLeo (Sunpeng) Li #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 166ff5ef992SAlex Deucher case DCN_VERSION_1_0: 1670e3d73f1SBhawanpreet Lakha case DCN_VERSION_1_01: 168d9673c92SHarry Wentland res_pool = dcn10_create_resource_pool(init_data, dc); 169ff5ef992SAlex Deucher break; 170ff5ef992SAlex Deucher #endif 1713639fa68SZeyu Fan 1723639fa68SZeyu Fan 1737ed4e635SHarry Wentland #if defined(CONFIG_DRM_AMD_DC_DCN2_0) 1747ed4e635SHarry Wentland case DCN_VERSION_2_0: 1757ed4e635SHarry Wentland res_pool = dcn20_create_resource_pool(init_data, dc); 1767ed4e635SHarry Wentland break; 1777ed4e635SHarry Wentland #endif 178e22ece54SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN2_1) 179e22ece54SBhawanpreet Lakha case DCN_VERSION_2_1: 180e22ece54SBhawanpreet Lakha res_pool = dcn21_create_resource_pool(init_data, dc); 181e22ece54SBhawanpreet Lakha break; 182e22ece54SBhawanpreet Lakha #endif 1837ed4e635SHarry Wentland 1844562236bSHarry Wentland default: 1854562236bSHarry Wentland break; 1864562236bSHarry Wentland } 187f49cfa27Shersen wu 1885ac3d3c9SCharlene Liu if (res_pool != NULL) { 1899adc8050SDmytro Laktyushkin if (dc->ctx->dc_bios->fw_info_valid) { 19041a5a2a8Shersen wu res_pool->ref_clocks.xtalin_clock_inKhz = 1919adc8050SDmytro Laktyushkin dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency; 19241a5a2a8Shersen wu /* initialize with firmware data first, no all 19341a5a2a8Shersen wu * ASIC have DCCG SW component. FPGA or 19441a5a2a8Shersen wu * simulation need initialization of 19541a5a2a8Shersen wu * dccg_ref_clock_inKhz, dchub_ref_clock_inKhz 19641a5a2a8Shersen wu * with xtalin_clock_inKhz 19741a5a2a8Shersen wu */ 19841a5a2a8Shersen wu res_pool->ref_clocks.dccg_ref_clock_inKhz = 19941a5a2a8Shersen wu res_pool->ref_clocks.xtalin_clock_inKhz; 20041a5a2a8Shersen wu res_pool->ref_clocks.dchub_ref_clock_inKhz = 20141a5a2a8Shersen wu res_pool->ref_clocks.xtalin_clock_inKhz; 2025ac3d3c9SCharlene Liu } else 2035ac3d3c9SCharlene Liu ASSERT_CRITICAL(false); 2045ac3d3c9SCharlene Liu } 2055ac3d3c9SCharlene Liu 2065ac3d3c9SCharlene Liu return res_pool; 2074562236bSHarry Wentland } 2084562236bSHarry Wentland 209fb3466a4SBhawanpreet Lakha void dc_destroy_resource_pool(struct dc *dc) 2104562236bSHarry Wentland { 2114562236bSHarry Wentland if (dc) { 2124562236bSHarry Wentland if (dc->res_pool) 2134562236bSHarry Wentland dc->res_pool->funcs->destroy(&dc->res_pool); 2144562236bSHarry Wentland 2152004f45eSHarry Wentland kfree(dc->hwseq); 2164562236bSHarry Wentland } 2174562236bSHarry Wentland } 2184562236bSHarry Wentland 2194562236bSHarry Wentland static void update_num_audio( 2204562236bSHarry Wentland const struct resource_straps *straps, 2214562236bSHarry Wentland unsigned int *num_audio, 2224562236bSHarry Wentland struct audio_support *aud_support) 2234562236bSHarry Wentland { 2244562236bSHarry Wentland aud_support->dp_audio = true; 225b8e9eb72SCharlene Liu aud_support->hdmi_audio_native = false; 226b8e9eb72SCharlene Liu aud_support->hdmi_audio_on_dongle = false; 227b8e9eb72SCharlene Liu 228b8e9eb72SCharlene Liu if (straps->hdmi_disable == 0) { 2294562236bSHarry Wentland if (straps->dc_pinstraps_audio & 0x2) { 2304562236bSHarry Wentland aud_support->hdmi_audio_on_dongle = true; 231b8e9eb72SCharlene Liu aud_support->hdmi_audio_native = true; 2324562236bSHarry Wentland } 2334562236bSHarry Wentland } 2344562236bSHarry Wentland 2354562236bSHarry Wentland switch (straps->audio_stream_number) { 2364562236bSHarry Wentland case 0: /* multi streams supported */ 2374562236bSHarry Wentland break; 2384562236bSHarry Wentland case 1: /* multi streams not supported */ 2394562236bSHarry Wentland *num_audio = 1; 2404562236bSHarry Wentland break; 2414562236bSHarry Wentland default: 2424562236bSHarry Wentland DC_ERR("DC: unexpected audio fuse!\n"); 24317a96033SJulia Lawall } 2444562236bSHarry Wentland } 2454562236bSHarry Wentland 2464562236bSHarry Wentland bool resource_construct( 2474562236bSHarry Wentland unsigned int num_virtual_links, 248fb3466a4SBhawanpreet Lakha struct dc *dc, 2494562236bSHarry Wentland struct resource_pool *pool, 2504562236bSHarry Wentland const struct resource_create_funcs *create_funcs) 2514562236bSHarry Wentland { 2524562236bSHarry Wentland struct dc_context *ctx = dc->ctx; 2534562236bSHarry Wentland const struct resource_caps *caps = pool->res_cap; 2544562236bSHarry Wentland int i; 2554562236bSHarry Wentland unsigned int num_audio = caps->num_audio; 2564562236bSHarry Wentland struct resource_straps straps = {0}; 2574562236bSHarry Wentland 2584562236bSHarry Wentland if (create_funcs->read_dce_straps) 2594562236bSHarry Wentland create_funcs->read_dce_straps(dc->ctx, &straps); 2604562236bSHarry Wentland 2614562236bSHarry Wentland pool->audio_count = 0; 2624562236bSHarry Wentland if (create_funcs->create_audio) { 2634562236bSHarry Wentland /* find the total number of streams available via the 2644562236bSHarry Wentland * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT 2654562236bSHarry Wentland * registers (one for each pin) starting from pin 1 2664562236bSHarry Wentland * up to the max number of audio pins. 2674562236bSHarry Wentland * We stop on the first pin where 2684562236bSHarry Wentland * PORT_CONNECTIVITY == 1 (as instructed by HW team). 2694562236bSHarry Wentland */ 2704562236bSHarry Wentland update_num_audio(&straps, &num_audio, &pool->audio_support); 2715feb9f07STai Man for (i = 0; i < caps->num_audio; i++) { 2724562236bSHarry Wentland struct audio *aud = create_funcs->create_audio(ctx, i); 2734562236bSHarry Wentland 2744562236bSHarry Wentland if (aud == NULL) { 2754562236bSHarry Wentland DC_ERR("DC: failed to create audio!\n"); 2764562236bSHarry Wentland return false; 2774562236bSHarry Wentland } 2784562236bSHarry Wentland if (!aud->funcs->endpoint_valid(aud)) { 2794562236bSHarry Wentland aud->funcs->destroy(&aud); 2804562236bSHarry Wentland break; 2814562236bSHarry Wentland } 2824562236bSHarry Wentland pool->audios[i] = aud; 2834562236bSHarry Wentland pool->audio_count++; 2844562236bSHarry Wentland } 2854562236bSHarry Wentland } 2864562236bSHarry Wentland 2874562236bSHarry Wentland pool->stream_enc_count = 0; 2884562236bSHarry Wentland if (create_funcs->create_stream_encoder) { 2894562236bSHarry Wentland for (i = 0; i < caps->num_stream_encoder; i++) { 2904562236bSHarry Wentland pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx); 2914562236bSHarry Wentland if (pool->stream_enc[i] == NULL) 2924562236bSHarry Wentland DC_ERR("DC: failed to create stream_encoder!\n"); 2934562236bSHarry Wentland pool->stream_enc_count++; 2944562236bSHarry Wentland } 2954562236bSHarry Wentland } 296929c3aaaSEric Bernstein 2974176664bSCharlene Liu dc->caps.dynamic_audio = false; 2984176664bSCharlene Liu if (pool->audio_count < pool->stream_enc_count) { 2994176664bSCharlene Liu dc->caps.dynamic_audio = true; 3004176664bSCharlene Liu } 3014562236bSHarry Wentland for (i = 0; i < num_virtual_links; i++) { 3024562236bSHarry Wentland pool->stream_enc[pool->stream_enc_count] = 3034562236bSHarry Wentland virtual_stream_encoder_create( 3044562236bSHarry Wentland ctx, ctx->dc_bios); 3054562236bSHarry Wentland if (pool->stream_enc[pool->stream_enc_count] == NULL) { 3064562236bSHarry Wentland DC_ERR("DC: failed to create stream_encoder!\n"); 3074562236bSHarry Wentland return false; 3084562236bSHarry Wentland } 3094562236bSHarry Wentland pool->stream_enc_count++; 3104562236bSHarry Wentland } 3114562236bSHarry Wentland 3124562236bSHarry Wentland dc->hwseq = create_funcs->create_hwseq(ctx); 3134562236bSHarry Wentland 3144562236bSHarry Wentland return true; 3154562236bSHarry Wentland } 316ad8960a6SMikita Lipski static int find_matching_clock_source( 317ad8960a6SMikita Lipski const struct resource_pool *pool, 318ad8960a6SMikita Lipski struct clock_source *clock_source) 319ad8960a6SMikita Lipski { 3204562236bSHarry Wentland 321ad8960a6SMikita Lipski int i; 322ad8960a6SMikita Lipski 323ad8960a6SMikita Lipski for (i = 0; i < pool->clk_src_count; i++) { 324ad8960a6SMikita Lipski if (pool->clock_sources[i] == clock_source) 325ad8960a6SMikita Lipski return i; 326ad8960a6SMikita Lipski } 327ad8960a6SMikita Lipski return -1; 328ad8960a6SMikita Lipski } 3294562236bSHarry Wentland 33021e67d4dSHarry Wentland void resource_unreference_clock_source( 3314562236bSHarry Wentland struct resource_context *res_ctx, 332a2b8659dSTony Cheng const struct resource_pool *pool, 3334a629536SHarry Wentland struct clock_source *clock_source) 3344562236bSHarry Wentland { 335ad8960a6SMikita Lipski int i = find_matching_clock_source(pool, clock_source); 3364a629536SHarry Wentland 337ad8960a6SMikita Lipski if (i > -1) 3384562236bSHarry Wentland res_ctx->clock_source_ref_count[i]--; 3394562236bSHarry Wentland 34021e67d4dSHarry Wentland if (pool->dp_clock_source == clock_source) 3414562236bSHarry Wentland res_ctx->dp_clock_source_ref_count--; 3424562236bSHarry Wentland } 3434562236bSHarry Wentland 3444562236bSHarry Wentland void resource_reference_clock_source( 3454562236bSHarry Wentland struct resource_context *res_ctx, 346a2b8659dSTony Cheng const struct resource_pool *pool, 3474562236bSHarry Wentland struct clock_source *clock_source) 3484562236bSHarry Wentland { 349ad8960a6SMikita Lipski int i = find_matching_clock_source(pool, clock_source); 3504562236bSHarry Wentland 351ad8960a6SMikita Lipski if (i > -1) 3524562236bSHarry Wentland res_ctx->clock_source_ref_count[i]++; 3534562236bSHarry Wentland 354a2b8659dSTony Cheng if (pool->dp_clock_source == clock_source) 3554562236bSHarry Wentland res_ctx->dp_clock_source_ref_count++; 3564562236bSHarry Wentland } 3574562236bSHarry Wentland 358ad8960a6SMikita Lipski int resource_get_clock_source_reference( 359ad8960a6SMikita Lipski struct resource_context *res_ctx, 360ad8960a6SMikita Lipski const struct resource_pool *pool, 361ad8960a6SMikita Lipski struct clock_source *clock_source) 362ad8960a6SMikita Lipski { 363ad8960a6SMikita Lipski int i = find_matching_clock_source(pool, clock_source); 364ad8960a6SMikita Lipski 365ad8960a6SMikita Lipski if (i > -1) 366ad8960a6SMikita Lipski return res_ctx->clock_source_ref_count[i]; 367ad8960a6SMikita Lipski 368ad8960a6SMikita Lipski if (pool->dp_clock_source == clock_source) 369ad8960a6SMikita Lipski return res_ctx->dp_clock_source_ref_count; 370ad8960a6SMikita Lipski 371ad8960a6SMikita Lipski return -1; 372ad8960a6SMikita Lipski } 373ad8960a6SMikita Lipski 3744562236bSHarry Wentland bool resource_are_streams_timing_synchronizable( 3750971c40eSHarry Wentland struct dc_stream_state *stream1, 3760971c40eSHarry Wentland struct dc_stream_state *stream2) 3774562236bSHarry Wentland { 3784fa086b9SLeo (Sunpeng) Li if (stream1->timing.h_total != stream2->timing.h_total) 3794562236bSHarry Wentland return false; 3804562236bSHarry Wentland 3814fa086b9SLeo (Sunpeng) Li if (stream1->timing.v_total != stream2->timing.v_total) 3824562236bSHarry Wentland return false; 3834562236bSHarry Wentland 3844fa086b9SLeo (Sunpeng) Li if (stream1->timing.h_addressable 3854fa086b9SLeo (Sunpeng) Li != stream2->timing.h_addressable) 3864562236bSHarry Wentland return false; 3874562236bSHarry Wentland 3884fa086b9SLeo (Sunpeng) Li if (stream1->timing.v_addressable 3894fa086b9SLeo (Sunpeng) Li != stream2->timing.v_addressable) 3904562236bSHarry Wentland return false; 3914562236bSHarry Wentland 392380604e2SKen Chalmers if (stream1->timing.pix_clk_100hz 393380604e2SKen Chalmers != stream2->timing.pix_clk_100hz) 3944562236bSHarry Wentland return false; 3954562236bSHarry Wentland 3963e27e10eSMikita Lipski if (stream1->clamping.c_depth != stream2->clamping.c_depth) 3973e27e10eSMikita Lipski return false; 3983e27e10eSMikita Lipski 3994562236bSHarry Wentland if (stream1->phy_pix_clk != stream2->phy_pix_clk 4007e2fe319SCharlene Liu && (!dc_is_dp_signal(stream1->signal) 4017e2fe319SCharlene Liu || !dc_is_dp_signal(stream2->signal))) 4024562236bSHarry Wentland return false; 4034562236bSHarry Wentland 404d77f778eSCharlene Liu if (stream1->view_format != stream2->view_format) 405d77f778eSCharlene Liu return false; 406d77f778eSCharlene Liu 4070460f9abSJun Lei if (stream1->ignore_msa_timing_param || stream2->ignore_msa_timing_param) 4080460f9abSJun Lei return false; 4090460f9abSJun Lei 4104562236bSHarry Wentland return true; 4114562236bSHarry Wentland } 4123e27e10eSMikita Lipski static bool is_dp_and_hdmi_sharable( 4133e27e10eSMikita Lipski struct dc_stream_state *stream1, 4143e27e10eSMikita Lipski struct dc_stream_state *stream2) 4153e27e10eSMikita Lipski { 4163e27e10eSMikita Lipski if (stream1->ctx->dc->caps.disable_dp_clk_share) 4173e27e10eSMikita Lipski return false; 4183e27e10eSMikita Lipski 4193e27e10eSMikita Lipski if (stream1->clamping.c_depth != COLOR_DEPTH_888 || 4203e27e10eSMikita Lipski stream2->clamping.c_depth != COLOR_DEPTH_888) 4213e27e10eSMikita Lipski return false; 4223e27e10eSMikita Lipski 4233e27e10eSMikita Lipski return true; 4243e27e10eSMikita Lipski 4253e27e10eSMikita Lipski } 4264562236bSHarry Wentland 4274562236bSHarry Wentland static bool is_sharable_clk_src( 4284562236bSHarry Wentland const struct pipe_ctx *pipe_with_clk_src, 4294562236bSHarry Wentland const struct pipe_ctx *pipe) 4304562236bSHarry Wentland { 4314562236bSHarry Wentland if (pipe_with_clk_src->clock_source == NULL) 4324562236bSHarry Wentland return false; 4334562236bSHarry Wentland 4344562236bSHarry Wentland if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL) 4354562236bSHarry Wentland return false; 4364562236bSHarry Wentland 4373e27e10eSMikita Lipski if (dc_is_dp_signal(pipe_with_clk_src->stream->signal) || 4383e27e10eSMikita Lipski (dc_is_dp_signal(pipe->stream->signal) && 4393e27e10eSMikita Lipski !is_dp_and_hdmi_sharable(pipe_with_clk_src->stream, 4403e27e10eSMikita Lipski pipe->stream))) 4414562236bSHarry Wentland return false; 4424562236bSHarry Wentland 4434562236bSHarry Wentland if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal) 444fc69009eSMikita Lipski && dc_is_dual_link_signal(pipe->stream->signal)) 4454562236bSHarry Wentland return false; 4464562236bSHarry Wentland 4474562236bSHarry Wentland if (dc_is_hdmi_signal(pipe->stream->signal) 448fc69009eSMikita Lipski && dc_is_dual_link_signal(pipe_with_clk_src->stream->signal)) 4494562236bSHarry Wentland return false; 4504562236bSHarry Wentland 4514562236bSHarry Wentland if (!resource_are_streams_timing_synchronizable( 4524562236bSHarry Wentland pipe_with_clk_src->stream, pipe->stream)) 4534562236bSHarry Wentland return false; 4544562236bSHarry Wentland 4554562236bSHarry Wentland return true; 4564562236bSHarry Wentland } 4574562236bSHarry Wentland 4584562236bSHarry Wentland struct clock_source *resource_find_used_clk_src_for_sharing( 4594562236bSHarry Wentland struct resource_context *res_ctx, 4604562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 4614562236bSHarry Wentland { 4624562236bSHarry Wentland int i; 4634562236bSHarry Wentland 4644562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 4654562236bSHarry Wentland if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx)) 4664562236bSHarry Wentland return res_ctx->pipe_ctx[i].clock_source; 4674562236bSHarry Wentland } 4684562236bSHarry Wentland 4694562236bSHarry Wentland return NULL; 4704562236bSHarry Wentland } 4714562236bSHarry Wentland 4724562236bSHarry Wentland static enum pixel_format convert_pixel_format_to_dalsurface( 4734562236bSHarry Wentland enum surface_pixel_format surface_pixel_format) 4744562236bSHarry Wentland { 4754562236bSHarry Wentland enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 4764562236bSHarry Wentland 4774562236bSHarry Wentland switch (surface_pixel_format) { 4784562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 4794562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_INDEX8; 4804562236bSHarry Wentland break; 4814562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 4824562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_RGB565; 4834562236bSHarry Wentland break; 4844562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 4854562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_RGB565; 4864562236bSHarry Wentland break; 4874562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 4884562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB8888; 4894562236bSHarry Wentland break; 4908693049aSTony Cheng case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 4914562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB8888; 4924562236bSHarry Wentland break; 4934562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 4944562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 4954562236bSHarry Wentland break; 4964562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 4974562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 4984562236bSHarry Wentland break; 4994562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 5004562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS; 5014562236bSHarry Wentland break; 5024562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 5034562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 5044562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_FP16; 5054562236bSHarry Wentland break; 5064562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 5074562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 50887449a90SAnthony Koo dal_pixel_format = PIXEL_FORMAT_420BPP8; 5094562236bSHarry Wentland break; 510ffbcd19aSVitaly Prosyak case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 511ffbcd19aSVitaly Prosyak case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 51287449a90SAnthony Koo dal_pixel_format = PIXEL_FORMAT_420BPP10; 513ffbcd19aSVitaly Prosyak break; 5144562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 5154562236bSHarry Wentland default: 5164562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 5174562236bSHarry Wentland break; 5184562236bSHarry Wentland } 5194562236bSHarry Wentland return dal_pixel_format; 5204562236bSHarry Wentland } 5214562236bSHarry Wentland 5229b6067c0SDmytro Laktyushkin static inline void get_vp_scan_direction( 5239b6067c0SDmytro Laktyushkin enum dc_rotation_angle rotation, 5249b6067c0SDmytro Laktyushkin bool horizontal_mirror, 5259b6067c0SDmytro Laktyushkin bool *orthogonal_rotation, 5269b6067c0SDmytro Laktyushkin bool *flip_vert_scan_dir, 5279b6067c0SDmytro Laktyushkin bool *flip_horz_scan_dir) 5284562236bSHarry Wentland { 5299b6067c0SDmytro Laktyushkin *orthogonal_rotation = false; 5309b6067c0SDmytro Laktyushkin *flip_vert_scan_dir = false; 5319b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = false; 5329b6067c0SDmytro Laktyushkin if (rotation == ROTATION_ANGLE_180) { 5339b6067c0SDmytro Laktyushkin *flip_vert_scan_dir = true; 5349b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = true; 5359b6067c0SDmytro Laktyushkin } else if (rotation == ROTATION_ANGLE_90) { 5369b6067c0SDmytro Laktyushkin *orthogonal_rotation = true; 5379b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = true; 5389b6067c0SDmytro Laktyushkin } else if (rotation == ROTATION_ANGLE_270) { 5399b6067c0SDmytro Laktyushkin *orthogonal_rotation = true; 5409b6067c0SDmytro Laktyushkin *flip_vert_scan_dir = true; 5419b6067c0SDmytro Laktyushkin } 5429b6067c0SDmytro Laktyushkin 5439b6067c0SDmytro Laktyushkin if (horizontal_mirror) 5449b6067c0SDmytro Laktyushkin *flip_horz_scan_dir = !*flip_horz_scan_dir; 5454562236bSHarry Wentland } 5464562236bSHarry Wentland 547b2d0a103SDmytro Laktyushkin static void calculate_viewport(struct pipe_ctx *pipe_ctx) 5484562236bSHarry Wentland { 5493be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 5500971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 5516702a9acSHarry Wentland struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 5523be5262eSHarry Wentland struct rect surf_src = plane_state->src_rect; 5539b6067c0SDmytro Laktyushkin struct rect clip, dest; 55487449a90SAnthony Koo int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 55587449a90SAnthony Koo || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 5561fbd2cfcSDmytro Laktyushkin bool pri_split = pipe_ctx->bottom_pipe && 5573be5262eSHarry Wentland pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; 5581fbd2cfcSDmytro Laktyushkin bool sec_split = pipe_ctx->top_pipe && 5593be5262eSHarry Wentland pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; 5609b6067c0SDmytro Laktyushkin bool orthogonal_rotation, flip_y_start, flip_x_start; 56183d40659SDmytro Laktyushkin 5627f5c22d1SVitaly Prosyak if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || 5637f5c22d1SVitaly Prosyak stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { 5647b779c99SVitaly Prosyak pri_split = false; 5657b779c99SVitaly Prosyak sec_split = false; 5667b779c99SVitaly Prosyak } 56786006a7fSDmytro Laktyushkin 5684562236bSHarry Wentland /* The actual clip is an intersection between stream 5694562236bSHarry Wentland * source and surface clip 5704562236bSHarry Wentland */ 5719b6067c0SDmytro Laktyushkin dest = plane_state->dst_rect; 5723be5262eSHarry Wentland clip.x = stream->src.x > plane_state->clip_rect.x ? 5733be5262eSHarry Wentland stream->src.x : plane_state->clip_rect.x; 5744562236bSHarry Wentland 5751fbd2cfcSDmytro Laktyushkin clip.width = stream->src.x + stream->src.width < 5763be5262eSHarry Wentland plane_state->clip_rect.x + plane_state->clip_rect.width ? 5771fbd2cfcSDmytro Laktyushkin stream->src.x + stream->src.width - clip.x : 5783be5262eSHarry Wentland plane_state->clip_rect.x + plane_state->clip_rect.width - clip.x ; 5794562236bSHarry Wentland 5803be5262eSHarry Wentland clip.y = stream->src.y > plane_state->clip_rect.y ? 5813be5262eSHarry Wentland stream->src.y : plane_state->clip_rect.y; 5824562236bSHarry Wentland 5831fbd2cfcSDmytro Laktyushkin clip.height = stream->src.y + stream->src.height < 5843be5262eSHarry Wentland plane_state->clip_rect.y + plane_state->clip_rect.height ? 5851fbd2cfcSDmytro Laktyushkin stream->src.y + stream->src.height - clip.y : 5863be5262eSHarry Wentland plane_state->clip_rect.y + plane_state->clip_rect.height - clip.y ; 5874562236bSHarry Wentland 5889b6067c0SDmytro Laktyushkin /* 5899b6067c0SDmytro Laktyushkin * Need to calculate how scan origin is shifted in vp space 5909b6067c0SDmytro Laktyushkin * to correctly rotate clip and dst 5919b6067c0SDmytro Laktyushkin */ 5929b6067c0SDmytro Laktyushkin get_vp_scan_direction( 5939b6067c0SDmytro Laktyushkin plane_state->rotation, 5949b6067c0SDmytro Laktyushkin plane_state->horizontal_mirror, 5959b6067c0SDmytro Laktyushkin &orthogonal_rotation, 5969b6067c0SDmytro Laktyushkin &flip_y_start, 5979b6067c0SDmytro Laktyushkin &flip_x_start); 5989b6067c0SDmytro Laktyushkin 5999b6067c0SDmytro Laktyushkin if (orthogonal_rotation) { 6009b6067c0SDmytro Laktyushkin swap(clip.x, clip.y); 6019b6067c0SDmytro Laktyushkin swap(clip.width, clip.height); 6029b6067c0SDmytro Laktyushkin swap(dest.x, dest.y); 6039b6067c0SDmytro Laktyushkin swap(dest.width, dest.height); 6049b6067c0SDmytro Laktyushkin } 6059b6067c0SDmytro Laktyushkin if (flip_x_start) { 6069b6067c0SDmytro Laktyushkin clip.x = dest.x + dest.width - clip.x - clip.width; 6079b6067c0SDmytro Laktyushkin dest.x = 0; 6089b6067c0SDmytro Laktyushkin } 6099b6067c0SDmytro Laktyushkin if (flip_y_start) { 6109b6067c0SDmytro Laktyushkin clip.y = dest.y + dest.height - clip.y - clip.height; 6119b6067c0SDmytro Laktyushkin dest.y = 0; 6129b6067c0SDmytro Laktyushkin } 6139b6067c0SDmytro Laktyushkin 61486006a7fSDmytro Laktyushkin /* offset = surf_src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio 6154562236bSHarry Wentland * num_pixels = clip.num_pix * scl_ratio 6164562236bSHarry Wentland */ 6179b6067c0SDmytro Laktyushkin data->viewport.x = surf_src.x + (clip.x - dest.x) * surf_src.width / dest.width; 6189b6067c0SDmytro Laktyushkin data->viewport.width = clip.width * surf_src.width / dest.width; 6194562236bSHarry Wentland 6209b6067c0SDmytro Laktyushkin data->viewport.y = surf_src.y + (clip.y - dest.y) * surf_src.height / dest.height; 6219b6067c0SDmytro Laktyushkin data->viewport.height = clip.height * surf_src.height / dest.height; 6224562236bSHarry Wentland 6239b6067c0SDmytro Laktyushkin /* Handle split */ 6249b6067c0SDmytro Laktyushkin if (pri_split || sec_split) { 6259b6067c0SDmytro Laktyushkin if (orthogonal_rotation) { 6269b6067c0SDmytro Laktyushkin if (flip_y_start != pri_split) 6279b6067c0SDmytro Laktyushkin data->viewport.height /= 2; 6289b6067c0SDmytro Laktyushkin else { 6299b6067c0SDmytro Laktyushkin data->viewport.y += data->viewport.height / 2; 6309b6067c0SDmytro Laktyushkin /* Ceil offset pipe */ 6319b6067c0SDmytro Laktyushkin data->viewport.height = (data->viewport.height + 1) / 2; 6329b6067c0SDmytro Laktyushkin } 6339b6067c0SDmytro Laktyushkin } else { 6349b6067c0SDmytro Laktyushkin if (flip_x_start != pri_split) 6359b6067c0SDmytro Laktyushkin data->viewport.width /= 2; 6369b6067c0SDmytro Laktyushkin else { 6379b6067c0SDmytro Laktyushkin data->viewport.x += data->viewport.width / 2; 6389b6067c0SDmytro Laktyushkin /* Ceil offset pipe */ 6399b6067c0SDmytro Laktyushkin data->viewport.width = (data->viewport.width + 1) / 2; 6409b6067c0SDmytro Laktyushkin } 6419b6067c0SDmytro Laktyushkin } 6429b6067c0SDmytro Laktyushkin } 6439b5349f7SMartin Tsai 644b2d0a103SDmytro Laktyushkin /* Round down, compensate in init */ 645b2d0a103SDmytro Laktyushkin data->viewport_c.x = data->viewport.x / vpc_div; 646b2d0a103SDmytro Laktyushkin data->viewport_c.y = data->viewport.y / vpc_div; 6479b6067c0SDmytro Laktyushkin data->inits.h_c = (data->viewport.x % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero; 6489b6067c0SDmytro Laktyushkin data->inits.v_c = (data->viewport.y % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero; 6499b6067c0SDmytro Laktyushkin 650b2d0a103SDmytro Laktyushkin /* Round up, assume original video size always even dimensions */ 651b2d0a103SDmytro Laktyushkin data->viewport_c.width = (data->viewport.width + vpc_div - 1) / vpc_div; 652b2d0a103SDmytro Laktyushkin data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; 653b2d0a103SDmytro Laktyushkin } 6541fbd2cfcSDmytro Laktyushkin 6559b6067c0SDmytro Laktyushkin static void calculate_recout(struct pipe_ctx *pipe_ctx) 6564562236bSHarry Wentland { 6573be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 6580971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 6593be5262eSHarry Wentland struct rect surf_clip = plane_state->clip_rect; 6600c31a821SYongqiang Sun bool pri_split = pipe_ctx->bottom_pipe && 6610c31a821SYongqiang Sun pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; 6620c31a821SYongqiang Sun bool sec_split = pipe_ctx->top_pipe && 6630c31a821SYongqiang Sun pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; 664b0131391SDmytro Laktyushkin bool top_bottom_split = stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; 6654562236bSHarry Wentland 6666702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.x = stream->dst.x; 6674fa086b9SLeo (Sunpeng) Li if (stream->src.x < surf_clip.x) 6686702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.x += (surf_clip.x 6694fa086b9SLeo (Sunpeng) Li - stream->src.x) * stream->dst.width 6704fa086b9SLeo (Sunpeng) Li / stream->src.width; 6714562236bSHarry Wentland 6726702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.width = surf_clip.width * 6734fa086b9SLeo (Sunpeng) Li stream->dst.width / stream->src.width; 6746702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.recout.width + pipe_ctx->plane_res.scl_data.recout.x > 6754fa086b9SLeo (Sunpeng) Li stream->dst.x + stream->dst.width) 6766702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.width = 6774fa086b9SLeo (Sunpeng) Li stream->dst.x + stream->dst.width 6786702a9acSHarry Wentland - pipe_ctx->plane_res.scl_data.recout.x; 6794562236bSHarry Wentland 6806702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.y = stream->dst.y; 6814fa086b9SLeo (Sunpeng) Li if (stream->src.y < surf_clip.y) 6826702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.y += (surf_clip.y 6834fa086b9SLeo (Sunpeng) Li - stream->src.y) * stream->dst.height 6844fa086b9SLeo (Sunpeng) Li / stream->src.height; 6854562236bSHarry Wentland 6866702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.height = surf_clip.height * 6874fa086b9SLeo (Sunpeng) Li stream->dst.height / stream->src.height; 6886702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.recout.height + pipe_ctx->plane_res.scl_data.recout.y > 6894fa086b9SLeo (Sunpeng) Li stream->dst.y + stream->dst.height) 6906702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.height = 6914fa086b9SLeo (Sunpeng) Li stream->dst.y + stream->dst.height 6926702a9acSHarry Wentland - pipe_ctx->plane_res.scl_data.recout.y; 693b2d0a103SDmytro Laktyushkin 6949b6067c0SDmytro Laktyushkin /* Handle h & v split, handle rotation using viewport */ 695b0131391SDmytro Laktyushkin if (sec_split && top_bottom_split) { 696b0131391SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.y += 697b0131391SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.height / 2; 6987b779c99SVitaly Prosyak /* Floor primary pipe, ceil 2ndary pipe */ 699b0131391SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.height = 700b0131391SDmytro Laktyushkin (pipe_ctx->plane_res.scl_data.recout.height + 1) / 2; 701b0131391SDmytro Laktyushkin } else if (pri_split && top_bottom_split) 7026702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.height /= 2; 7039b6067c0SDmytro Laktyushkin else if (sec_split) { 7040c31a821SYongqiang Sun pipe_ctx->plane_res.scl_data.recout.x += 7050c31a821SYongqiang Sun pipe_ctx->plane_res.scl_data.recout.width / 2; 7060c31a821SYongqiang Sun /* Ceil offset pipe */ 7070c31a821SYongqiang Sun pipe_ctx->plane_res.scl_data.recout.width = 7080c31a821SYongqiang Sun (pipe_ctx->plane_res.scl_data.recout.width + 1) / 2; 7099b6067c0SDmytro Laktyushkin } else if (pri_split) 7106702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.width /= 2; 7114562236bSHarry Wentland } 712b2d0a103SDmytro Laktyushkin 713b2d0a103SDmytro Laktyushkin static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) 7144562236bSHarry Wentland { 7153be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 7160971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 7173be5262eSHarry Wentland struct rect surf_src = plane_state->src_rect; 7184fa086b9SLeo (Sunpeng) Li const int in_w = stream->src.width; 7194fa086b9SLeo (Sunpeng) Li const int in_h = stream->src.height; 7204fa086b9SLeo (Sunpeng) Li const int out_w = stream->dst.width; 7214fa086b9SLeo (Sunpeng) Li const int out_h = stream->dst.height; 7224562236bSHarry Wentland 7239b6067c0SDmytro Laktyushkin /*Swap surf_src height and width since scaling ratios are in recout rotation*/ 7243be5262eSHarry Wentland if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 7253be5262eSHarry Wentland pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 7269b6067c0SDmytro Laktyushkin swap(surf_src.height, surf_src.width); 72786006a7fSDmytro Laktyushkin 728eb0e5154SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_from_fraction( 72986006a7fSDmytro Laktyushkin surf_src.width, 7303be5262eSHarry Wentland plane_state->dst_rect.width); 731eb0e5154SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_from_fraction( 73286006a7fSDmytro Laktyushkin surf_src.height, 7333be5262eSHarry Wentland plane_state->dst_rect.height); 7344562236bSHarry Wentland 7354fa086b9SLeo (Sunpeng) Li if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) 7366702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value *= 2; 7374fa086b9SLeo (Sunpeng) Li else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) 7386702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value *= 2; 7394562236bSHarry Wentland 7406702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value = div64_s64( 7416702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value * in_h, out_h); 7426702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value = div64_s64( 7436702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value * in_w, out_w); 7444562236bSHarry Wentland 7456702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz_c = pipe_ctx->plane_res.scl_data.ratios.horz; 7466702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert_c = pipe_ctx->plane_res.scl_data.ratios.vert; 7474562236bSHarry Wentland 7486702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP8 7496702a9acSHarry Wentland || pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP10) { 7506702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz_c.value /= 2; 7516702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert_c.value /= 2; 7524562236bSHarry Wentland } 7530002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_truncate( 7540002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz, 19); 7550002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_truncate( 7560002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert, 19); 7570002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz_c = dc_fixpt_truncate( 7580002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.horz_c, 19); 7590002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert_c = dc_fixpt_truncate( 7600002d3acSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.ratios.vert_c, 19); 7614562236bSHarry Wentland } 7624562236bSHarry Wentland 7639b6067c0SDmytro Laktyushkin static inline void adjust_vp_and_init_for_seamless_clip( 7649b6067c0SDmytro Laktyushkin bool flip_scan_dir, 7659b6067c0SDmytro Laktyushkin int recout_skip, 7669b6067c0SDmytro Laktyushkin int src_size, 7679b6067c0SDmytro Laktyushkin int taps, 7689b6067c0SDmytro Laktyushkin struct fixed31_32 ratio, 7699b6067c0SDmytro Laktyushkin struct fixed31_32 *init, 7709b6067c0SDmytro Laktyushkin int *vp_offset, 7719b6067c0SDmytro Laktyushkin int *vp_size) 7724562236bSHarry Wentland { 7739b6067c0SDmytro Laktyushkin if (!flip_scan_dir) { 7749b6067c0SDmytro Laktyushkin /* Adjust for viewport end clip-off */ 7759b6067c0SDmytro Laktyushkin if ((*vp_offset + *vp_size) < src_size) { 7769b6067c0SDmytro Laktyushkin int vp_clip = src_size - *vp_size - *vp_offset; 7779b6067c0SDmytro Laktyushkin int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio)); 7789b6067c0SDmytro Laktyushkin 7799b6067c0SDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 7809b6067c0SDmytro Laktyushkin *vp_size += int_part < vp_clip ? int_part : vp_clip; 7819b6067c0SDmytro Laktyushkin } 7829b6067c0SDmytro Laktyushkin 7839b6067c0SDmytro Laktyushkin /* Adjust for non-0 viewport offset */ 7849b6067c0SDmytro Laktyushkin if (*vp_offset) { 7859b6067c0SDmytro Laktyushkin int int_part; 7869b6067c0SDmytro Laktyushkin 7879b6067c0SDmytro Laktyushkin *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip)); 7889b6067c0SDmytro Laktyushkin int_part = dc_fixpt_floor(*init) - *vp_offset; 7899b6067c0SDmytro Laktyushkin if (int_part < taps) { 7909b6067c0SDmytro Laktyushkin int int_adj = *vp_offset >= (taps - int_part) ? 7919b6067c0SDmytro Laktyushkin (taps - int_part) : *vp_offset; 7929b6067c0SDmytro Laktyushkin *vp_offset -= int_adj; 7939b6067c0SDmytro Laktyushkin *vp_size += int_adj; 7949b6067c0SDmytro Laktyushkin int_part += int_adj; 7959b6067c0SDmytro Laktyushkin } else if (int_part > taps) { 7969b6067c0SDmytro Laktyushkin *vp_offset += int_part - taps; 7979b6067c0SDmytro Laktyushkin *vp_size -= int_part - taps; 7989b6067c0SDmytro Laktyushkin int_part = taps; 7999b6067c0SDmytro Laktyushkin } 8009b6067c0SDmytro Laktyushkin init->value &= 0xffffffff; 8019b6067c0SDmytro Laktyushkin *init = dc_fixpt_add_int(*init, int_part); 8029b6067c0SDmytro Laktyushkin } 8039b6067c0SDmytro Laktyushkin } else { 8049b6067c0SDmytro Laktyushkin /* Adjust for non-0 viewport offset */ 8059b6067c0SDmytro Laktyushkin if (*vp_offset) { 8069b6067c0SDmytro Laktyushkin int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio)); 8079b6067c0SDmytro Laktyushkin 8089b6067c0SDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 8099b6067c0SDmytro Laktyushkin *vp_size += int_part < *vp_offset ? int_part : *vp_offset; 8109b6067c0SDmytro Laktyushkin *vp_offset -= int_part < *vp_offset ? int_part : *vp_offset; 8119b6067c0SDmytro Laktyushkin } 8129b6067c0SDmytro Laktyushkin 8139b6067c0SDmytro Laktyushkin /* Adjust for viewport end clip-off */ 8149b6067c0SDmytro Laktyushkin if ((*vp_offset + *vp_size) < src_size) { 8159b6067c0SDmytro Laktyushkin int int_part; 8169b6067c0SDmytro Laktyushkin int end_offset = src_size - *vp_offset - *vp_size; 8179b6067c0SDmytro Laktyushkin 8189b6067c0SDmytro Laktyushkin /* 8199b6067c0SDmytro Laktyushkin * this is init if vp had no offset, keep in mind this is from the 8209b6067c0SDmytro Laktyushkin * right side of vp due to scan direction 8219b6067c0SDmytro Laktyushkin */ 8229b6067c0SDmytro Laktyushkin *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip)); 8239b6067c0SDmytro Laktyushkin /* 8249b6067c0SDmytro Laktyushkin * this is the difference between first pixel of viewport available to read 8259b6067c0SDmytro Laktyushkin * and init position, takning into account scan direction 8269b6067c0SDmytro Laktyushkin */ 8279b6067c0SDmytro Laktyushkin int_part = dc_fixpt_floor(*init) - end_offset; 8289b6067c0SDmytro Laktyushkin if (int_part < taps) { 8299b6067c0SDmytro Laktyushkin int int_adj = end_offset >= (taps - int_part) ? 8309b6067c0SDmytro Laktyushkin (taps - int_part) : end_offset; 8319b6067c0SDmytro Laktyushkin *vp_size += int_adj; 8329b6067c0SDmytro Laktyushkin int_part += int_adj; 8339b6067c0SDmytro Laktyushkin } else if (int_part > taps) { 8349b6067c0SDmytro Laktyushkin *vp_size += int_part - taps; 8359b6067c0SDmytro Laktyushkin int_part = taps; 8369b6067c0SDmytro Laktyushkin } 8379b6067c0SDmytro Laktyushkin init->value &= 0xffffffff; 8389b6067c0SDmytro Laktyushkin *init = dc_fixpt_add_int(*init, int_part); 8399b6067c0SDmytro Laktyushkin } 8409b6067c0SDmytro Laktyushkin } 8419b6067c0SDmytro Laktyushkin } 8429b6067c0SDmytro Laktyushkin 8439b6067c0SDmytro Laktyushkin static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx) 8449b6067c0SDmytro Laktyushkin { 8459b6067c0SDmytro Laktyushkin const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 8469b6067c0SDmytro Laktyushkin const struct dc_stream_state *stream = pipe_ctx->stream; 8476702a9acSHarry Wentland struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 8483be5262eSHarry Wentland struct rect src = pipe_ctx->plane_state->src_rect; 8499b6067c0SDmytro Laktyushkin int recout_skip_h, recout_skip_v, surf_size_h, surf_size_v; 85087449a90SAnthony Koo int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 85187449a90SAnthony Koo || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 8529b6067c0SDmytro Laktyushkin bool orthogonal_rotation, flip_vert_scan_dir, flip_horz_scan_dir; 853b2d0a103SDmytro Laktyushkin 854b0131391SDmytro Laktyushkin /* 855b0131391SDmytro Laktyushkin * Need to calculate the scan direction for viewport to make adjustments 856b0131391SDmytro Laktyushkin */ 8579b6067c0SDmytro Laktyushkin get_vp_scan_direction( 8589b6067c0SDmytro Laktyushkin plane_state->rotation, 8599b6067c0SDmytro Laktyushkin plane_state->horizontal_mirror, 8609b6067c0SDmytro Laktyushkin &orthogonal_rotation, 8619b6067c0SDmytro Laktyushkin &flip_vert_scan_dir, 8629b6067c0SDmytro Laktyushkin &flip_horz_scan_dir); 863b0131391SDmytro Laktyushkin 8649b6067c0SDmytro Laktyushkin /* Calculate src rect rotation adjusted to recout space */ 8659b6067c0SDmytro Laktyushkin surf_size_h = src.x + src.width; 8669b6067c0SDmytro Laktyushkin surf_size_v = src.y + src.height; 8679b6067c0SDmytro Laktyushkin if (flip_horz_scan_dir) 8689b6067c0SDmytro Laktyushkin src.x = 0; 8699b6067c0SDmytro Laktyushkin if (flip_vert_scan_dir) 8709b6067c0SDmytro Laktyushkin src.y = 0; 8719b6067c0SDmytro Laktyushkin if (orthogonal_rotation) { 8729b6067c0SDmytro Laktyushkin swap(src.x, src.y); 8739b6067c0SDmytro Laktyushkin swap(src.width, src.height); 8749b5349f7SMartin Tsai } 8751fbd2cfcSDmytro Laktyushkin 8769b6067c0SDmytro Laktyushkin /* Recout matching initial vp offset = recout_offset - (stream dst offset + 8779b6067c0SDmytro Laktyushkin * ((surf dst offset - stream src offset) * 1/ stream scaling ratio) 8789b6067c0SDmytro Laktyushkin * - (surf surf_src offset * 1/ full scl ratio)) 8799b6067c0SDmytro Laktyushkin */ 8809b6067c0SDmytro Laktyushkin recout_skip_h = data->recout.x - (stream->dst.x + (plane_state->dst_rect.x - stream->src.x) 8819b6067c0SDmytro Laktyushkin * stream->dst.width / stream->src.width - 8829b6067c0SDmytro Laktyushkin src.x * plane_state->dst_rect.width / src.width 8839b6067c0SDmytro Laktyushkin * stream->dst.width / stream->src.width); 8849b6067c0SDmytro Laktyushkin recout_skip_v = data->recout.y - (stream->dst.y + (plane_state->dst_rect.y - stream->src.y) 8859b6067c0SDmytro Laktyushkin * stream->dst.height / stream->src.height - 8869b6067c0SDmytro Laktyushkin src.y * plane_state->dst_rect.height / src.height 8879b6067c0SDmytro Laktyushkin * stream->dst.height / stream->src.height); 8889b6067c0SDmytro Laktyushkin if (orthogonal_rotation) 8899b6067c0SDmytro Laktyushkin swap(recout_skip_h, recout_skip_v); 890b2d0a103SDmytro Laktyushkin /* 891b2d0a103SDmytro Laktyushkin * Init calculated according to formula: 892b2d0a103SDmytro Laktyushkin * init = (scaling_ratio + number_of_taps + 1) / 2 893b2d0a103SDmytro Laktyushkin * init_bot = init + scaling_ratio 894b2d0a103SDmytro Laktyushkin * init_c = init + truncated_vp_c_offset(from calculate viewport) 895b2d0a103SDmytro Laktyushkin */ 8960002d3acSDmytro Laktyushkin data->inits.h = dc_fixpt_truncate(dc_fixpt_div_int( 8970002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.horz, data->taps.h_taps + 1), 2), 19); 898b2d0a103SDmytro Laktyushkin 8990002d3acSDmytro Laktyushkin data->inits.h_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.h_c, dc_fixpt_div_int( 9000002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.horz_c, data->taps.h_taps_c + 1), 2)), 19); 901b2d0a103SDmytro Laktyushkin 9020002d3acSDmytro Laktyushkin data->inits.v = dc_fixpt_truncate(dc_fixpt_div_int( 9030002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.vert, data->taps.v_taps + 1), 2), 19); 904b2d0a103SDmytro Laktyushkin 9050002d3acSDmytro Laktyushkin data->inits.v_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.v_c, dc_fixpt_div_int( 9060002d3acSDmytro Laktyushkin dc_fixpt_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2)), 19); 9070002d3acSDmytro Laktyushkin 9089a08f51fSDmytro Laktyushkin /* 9099b6067c0SDmytro Laktyushkin * Taps, inits and scaling ratios are in recout space need to rotate 9109b6067c0SDmytro Laktyushkin * to viewport rotation before adjustment 9119a08f51fSDmytro Laktyushkin */ 9129b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 9139b6067c0SDmytro Laktyushkin flip_horz_scan_dir, 9149b6067c0SDmytro Laktyushkin recout_skip_h, 9159b6067c0SDmytro Laktyushkin surf_size_h, 9169b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.v_taps : data->taps.h_taps, 9179b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.vert : data->ratios.horz, 9189b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.v : &data->inits.h, 9199b6067c0SDmytro Laktyushkin &data->viewport.x, 9209b6067c0SDmytro Laktyushkin &data->viewport.width); 9219b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 9229b6067c0SDmytro Laktyushkin flip_horz_scan_dir, 9239b6067c0SDmytro Laktyushkin recout_skip_h, 9249b6067c0SDmytro Laktyushkin surf_size_h / vpc_div, 9259b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.v_taps_c : data->taps.h_taps_c, 9269b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.vert_c : data->ratios.horz_c, 9279b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.v_c : &data->inits.h_c, 9289b6067c0SDmytro Laktyushkin &data->viewport_c.x, 9299b6067c0SDmytro Laktyushkin &data->viewport_c.width); 9309b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 9319b6067c0SDmytro Laktyushkin flip_vert_scan_dir, 9329b6067c0SDmytro Laktyushkin recout_skip_v, 9339b6067c0SDmytro Laktyushkin surf_size_v, 9349b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.h_taps : data->taps.v_taps, 9359b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.horz : data->ratios.vert, 9369b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.h : &data->inits.v, 9379b6067c0SDmytro Laktyushkin &data->viewport.y, 9389b6067c0SDmytro Laktyushkin &data->viewport.height); 9399b6067c0SDmytro Laktyushkin adjust_vp_and_init_for_seamless_clip( 9409b6067c0SDmytro Laktyushkin flip_vert_scan_dir, 9419b6067c0SDmytro Laktyushkin recout_skip_v, 9429b6067c0SDmytro Laktyushkin surf_size_v / vpc_div, 9439b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->taps.h_taps_c : data->taps.v_taps_c, 9449b6067c0SDmytro Laktyushkin orthogonal_rotation ? data->ratios.horz_c : data->ratios.vert_c, 9459b6067c0SDmytro Laktyushkin orthogonal_rotation ? &data->inits.h_c : &data->inits.v_c, 9469b6067c0SDmytro Laktyushkin &data->viewport_c.y, 9479b6067c0SDmytro Laktyushkin &data->viewport_c.height); 948b2d0a103SDmytro Laktyushkin 949b2d0a103SDmytro Laktyushkin /* Interlaced inits based on final vert inits */ 950eb0e5154SDmytro Laktyushkin data->inits.v_bot = dc_fixpt_add(data->inits.v, data->ratios.vert); 951eb0e5154SDmytro Laktyushkin data->inits.v_c_bot = dc_fixpt_add(data->inits.v_c, data->ratios.vert_c); 9521fbd2cfcSDmytro Laktyushkin 953b2d0a103SDmytro Laktyushkin } 9543b733278SReza Amini static bool are_rects_integer_multiples(struct rect src, struct rect dest) 955f7938bc0SReza Amini { 956f7938bc0SReza Amini if (dest.width >= src.width && dest.width % src.width == 0 && 957f7938bc0SReza Amini dest.height >= src.height && dest.height % src.height == 0) 958f7938bc0SReza Amini return true; 959b2d0a103SDmytro Laktyushkin 960f7938bc0SReza Amini return false; 961f7938bc0SReza Amini } 9623b733278SReza Amini 9634ef0b9d0SYueHaibing static void calculate_integer_scaling(struct pipe_ctx *pipe_ctx) 9643b733278SReza Amini { 9653b733278SReza Amini if (!pipe_ctx->plane_state->scaling_quality.integer_scaling) 9663b733278SReza Amini return; 9673b733278SReza Amini 9683b733278SReza Amini //for Centered Mode 9693b733278SReza Amini if (pipe_ctx->stream->dst.width == pipe_ctx->stream->src.width && 9703b733278SReza Amini pipe_ctx->stream->dst.height == pipe_ctx->stream->src.height) { 9713b733278SReza Amini // calculate maximum # of replication of src onto addressable 9723b733278SReza Amini unsigned int integer_multiple = min( 9733b733278SReza Amini pipe_ctx->stream->timing.h_addressable / pipe_ctx->stream->src.width, 9743b733278SReza Amini pipe_ctx->stream->timing.v_addressable / pipe_ctx->stream->src.height); 9753b733278SReza Amini 9763b733278SReza Amini //scale dst 9773b733278SReza Amini pipe_ctx->stream->dst.width = integer_multiple * pipe_ctx->stream->src.width; 9783b733278SReza Amini pipe_ctx->stream->dst.height = integer_multiple * pipe_ctx->stream->src.height; 9793b733278SReza Amini 9803b733278SReza Amini //center dst onto addressable 9813b733278SReza Amini pipe_ctx->stream->dst.x = (pipe_ctx->stream->timing.h_addressable - pipe_ctx->stream->dst.width)/2; 9823b733278SReza Amini pipe_ctx->stream->dst.y = (pipe_ctx->stream->timing.v_addressable - pipe_ctx->stream->dst.height)/2; 9833b733278SReza Amini } 9843b733278SReza Amini 9853b733278SReza Amini //disable taps if src & dst are integer ratio 9863b733278SReza Amini if (are_rects_integer_multiples(pipe_ctx->stream->src, pipe_ctx->stream->dst)) { 9873b733278SReza Amini pipe_ctx->plane_state->scaling_quality.v_taps = 1; 9883b733278SReza Amini pipe_ctx->plane_state->scaling_quality.h_taps = 1; 9893b733278SReza Amini pipe_ctx->plane_state->scaling_quality.v_taps_c = 1; 9903b733278SReza Amini pipe_ctx->plane_state->scaling_quality.h_taps_c = 1; 9913b733278SReza Amini } 9923b733278SReza Amini } 9933b733278SReza Amini 994b2d0a103SDmytro Laktyushkin bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) 995b2d0a103SDmytro Laktyushkin { 9963be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 9974fa086b9SLeo (Sunpeng) Li struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 998b2d0a103SDmytro Laktyushkin bool res = false; 9995d4b05ddSBhawanpreet Lakha DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); 10004562236bSHarry Wentland /* Important: scaling ratio calculation requires pixel format, 10014562236bSHarry Wentland * lb depth calculation requires recout and taps require scaling ratios. 1002b2d0a103SDmytro Laktyushkin * Inits require viewport, taps, ratios and recout of split pipe 10034562236bSHarry Wentland */ 10046702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface( 10053be5262eSHarry Wentland pipe_ctx->plane_state->format); 10064562236bSHarry Wentland 10073b733278SReza Amini calculate_integer_scaling(pipe_ctx); 10083b733278SReza Amini 1009b2d0a103SDmytro Laktyushkin calculate_scaling_ratios(pipe_ctx); 1010b2d0a103SDmytro Laktyushkin 1011b2d0a103SDmytro Laktyushkin calculate_viewport(pipe_ctx); 10124562236bSHarry Wentland 10136702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.viewport.height < 16 || pipe_ctx->plane_res.scl_data.viewport.width < 16) 10144562236bSHarry Wentland return false; 10154562236bSHarry Wentland 10169b6067c0SDmytro Laktyushkin calculate_recout(pipe_ctx); 10174562236bSHarry Wentland 10184562236bSHarry Wentland /** 10194562236bSHarry Wentland * Setting line buffer pixel depth to 24bpp yields banding 10204562236bSHarry Wentland * on certain displays, such as the Sharp 4k 10214562236bSHarry Wentland */ 10226702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; 10234562236bSHarry Wentland 1024199e458aSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left; 102558bb0e63SAndrew Jiang pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top; 1026199e458aSDmytro Laktyushkin 102758bb0e63SAndrew Jiang pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right; 102858bb0e63SAndrew Jiang pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + timing->v_border_top + timing->v_border_bottom; 10291b6c8067SBhawanpreet Lakha 10304562236bSHarry Wentland /* Taps calculations */ 1031d94585a0SYue Hin Lau if (pipe_ctx->plane_res.xfm != NULL) 103286a66c4eSHarry Wentland res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 103386a66c4eSHarry Wentland pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 10344562236bSHarry Wentland 1035d94585a0SYue Hin Lau if (pipe_ctx->plane_res.dpp != NULL) 1036d94585a0SYue Hin Lau res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 1037d94585a0SYue Hin Lau pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 1038f7938bc0SReza Amini 1039f7938bc0SReza Amini 10404562236bSHarry Wentland if (!res) { 10414562236bSHarry Wentland /* Try 24 bpp linebuffer */ 10426702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; 10434562236bSHarry Wentland 10441b6c8067SBhawanpreet Lakha if (pipe_ctx->plane_res.xfm != NULL) 104586a66c4eSHarry Wentland res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 10461b6c8067SBhawanpreet Lakha pipe_ctx->plane_res.xfm, 10471b6c8067SBhawanpreet Lakha &pipe_ctx->plane_res.scl_data, 10481b6c8067SBhawanpreet Lakha &plane_state->scaling_quality); 1049d94585a0SYue Hin Lau 10501b6c8067SBhawanpreet Lakha if (pipe_ctx->plane_res.dpp != NULL) 1051d94585a0SYue Hin Lau res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 10521b6c8067SBhawanpreet Lakha pipe_ctx->plane_res.dpp, 10531b6c8067SBhawanpreet Lakha &pipe_ctx->plane_res.scl_data, 10541b6c8067SBhawanpreet Lakha &plane_state->scaling_quality); 10554562236bSHarry Wentland } 10564562236bSHarry Wentland 1057b2d0a103SDmytro Laktyushkin if (res) 10581fbd2cfcSDmytro Laktyushkin /* May need to re-check lb size after this in some obscure scenario */ 10599b6067c0SDmytro Laktyushkin calculate_inits_and_adj_vp(pipe_ctx); 1060b2d0a103SDmytro Laktyushkin 10611296423bSBhawanpreet Lakha DC_LOG_SCALER( 10624562236bSHarry Wentland "%s: Viewport:\nheight:%d width:%d x:%d " 10634562236bSHarry Wentland "y:%d\n dst_rect:\nheight:%d width:%d x:%d " 10644562236bSHarry Wentland "y:%d\n", 10654562236bSHarry Wentland __func__, 10666702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.height, 10676702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.width, 10686702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.x, 10696702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.y, 10703be5262eSHarry Wentland plane_state->dst_rect.height, 10713be5262eSHarry Wentland plane_state->dst_rect.width, 10723be5262eSHarry Wentland plane_state->dst_rect.x, 10733be5262eSHarry Wentland plane_state->dst_rect.y); 10744562236bSHarry Wentland 10754562236bSHarry Wentland return res; 10764562236bSHarry Wentland } 10774562236bSHarry Wentland 10784562236bSHarry Wentland 10794562236bSHarry Wentland enum dc_status resource_build_scaling_params_for_context( 1080fb3466a4SBhawanpreet Lakha const struct dc *dc, 1081608ac7bbSJerry Zuo struct dc_state *context) 10824562236bSHarry Wentland { 10834562236bSHarry Wentland int i; 10844562236bSHarry Wentland 10854562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 10863be5262eSHarry Wentland if (context->res_ctx.pipe_ctx[i].plane_state != NULL && 10874562236bSHarry Wentland context->res_ctx.pipe_ctx[i].stream != NULL) 1088b2d0a103SDmytro Laktyushkin if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i])) 1089f84a8161STony Cheng return DC_FAIL_SCALING; 10904562236bSHarry Wentland } 10914562236bSHarry Wentland 10924562236bSHarry Wentland return DC_OK; 10934562236bSHarry Wentland } 10944562236bSHarry Wentland 1095a2b8659dSTony Cheng struct pipe_ctx *find_idle_secondary_pipe( 1096a2b8659dSTony Cheng struct resource_context *res_ctx, 10975581192dSJun Lei const struct resource_pool *pool, 10985581192dSJun Lei const struct pipe_ctx *primary_pipe) 10994562236bSHarry Wentland { 11004562236bSHarry Wentland int i; 11014562236bSHarry Wentland struct pipe_ctx *secondary_pipe = NULL; 11024562236bSHarry Wentland 11034562236bSHarry Wentland /* 11045581192dSJun Lei * We add a preferred pipe mapping to avoid the chance that 11055581192dSJun Lei * MPCCs already in use will need to be reassigned to other trees. 11065581192dSJun Lei * For example, if we went with the strict, assign backwards logic: 11075581192dSJun Lei * 11085581192dSJun Lei * (State 1) 11095581192dSJun Lei * Display A on, no surface, top pipe = 0 11105581192dSJun Lei * Display B on, no surface, top pipe = 1 11115581192dSJun Lei * 11125581192dSJun Lei * (State 2) 11135581192dSJun Lei * Display A on, no surface, top pipe = 0 11145581192dSJun Lei * Display B on, surface enable, top pipe = 1, bottom pipe = 5 11155581192dSJun Lei * 11165581192dSJun Lei * (State 3) 11175581192dSJun Lei * Display A on, surface enable, top pipe = 0, bottom pipe = 5 11185581192dSJun Lei * Display B on, surface enable, top pipe = 1, bottom pipe = 4 11195581192dSJun Lei * 11205581192dSJun Lei * The state 2->3 transition requires remapping MPCC 5 from display B 11215581192dSJun Lei * to display A. 11225581192dSJun Lei * 11235581192dSJun Lei * However, with the preferred pipe logic, state 2 would look like: 11245581192dSJun Lei * 11255581192dSJun Lei * (State 2) 11265581192dSJun Lei * Display A on, no surface, top pipe = 0 11275581192dSJun Lei * Display B on, surface enable, top pipe = 1, bottom pipe = 4 11285581192dSJun Lei * 11295581192dSJun Lei * This would then cause 2->3 to not require remapping any MPCCs. 11305581192dSJun Lei */ 11315581192dSJun Lei if (primary_pipe) { 11325581192dSJun Lei int preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx; 11335581192dSJun Lei if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) { 11345581192dSJun Lei secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx]; 11355581192dSJun Lei secondary_pipe->pipe_idx = preferred_pipe_idx; 11365581192dSJun Lei } 11375581192dSJun Lei } 11385581192dSJun Lei 11395581192dSJun Lei /* 11404562236bSHarry Wentland * search backwards for the second pipe to keep pipe 11414562236bSHarry Wentland * assignment more consistent 11424562236bSHarry Wentland */ 11435581192dSJun Lei if (!secondary_pipe) 1144a2b8659dSTony Cheng for (i = pool->pipe_count - 1; i >= 0; i--) { 11454562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == NULL) { 11464562236bSHarry Wentland secondary_pipe = &res_ctx->pipe_ctx[i]; 11474562236bSHarry Wentland secondary_pipe->pipe_idx = i; 11484562236bSHarry Wentland break; 11494562236bSHarry Wentland } 11504562236bSHarry Wentland } 11514562236bSHarry Wentland 11524562236bSHarry Wentland return secondary_pipe; 11534562236bSHarry Wentland } 11544562236bSHarry Wentland 11554562236bSHarry Wentland struct pipe_ctx *resource_get_head_pipe_for_stream( 11564562236bSHarry Wentland struct resource_context *res_ctx, 11570971c40eSHarry Wentland struct dc_stream_state *stream) 11584562236bSHarry Wentland { 11594562236bSHarry Wentland int i; 116022498036SDmytro Laktyushkin 1161a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 1162b1f6d01cSDmytro Laktyushkin if (res_ctx->pipe_ctx[i].stream == stream 1163b1f6d01cSDmytro Laktyushkin && !res_ctx->pipe_ctx[i].top_pipe 116422498036SDmytro Laktyushkin && !res_ctx->pipe_ctx[i].prev_odm_pipe) 11654562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 11664562236bSHarry Wentland } 11674562236bSHarry Wentland return NULL; 11684562236bSHarry Wentland } 11694562236bSHarry Wentland 1170b1f6d01cSDmytro Laktyushkin static struct pipe_ctx *resource_get_tail_pipe( 117119f89e23SAndrey Grodzovsky struct resource_context *res_ctx, 1172b1f6d01cSDmytro Laktyushkin struct pipe_ctx *head_pipe) 117319f89e23SAndrey Grodzovsky { 1174b1f6d01cSDmytro Laktyushkin struct pipe_ctx *tail_pipe; 117519f89e23SAndrey Grodzovsky 117619f89e23SAndrey Grodzovsky tail_pipe = head_pipe->bottom_pipe; 117719f89e23SAndrey Grodzovsky 117819f89e23SAndrey Grodzovsky while (tail_pipe) { 117919f89e23SAndrey Grodzovsky head_pipe = tail_pipe; 118019f89e23SAndrey Grodzovsky tail_pipe = tail_pipe->bottom_pipe; 118119f89e23SAndrey Grodzovsky } 118219f89e23SAndrey Grodzovsky 118319f89e23SAndrey Grodzovsky return head_pipe; 118419f89e23SAndrey Grodzovsky } 118519f89e23SAndrey Grodzovsky 11864562236bSHarry Wentland /* 1187ab2541b6SAric Cyr * A free_pipe for a stream is defined here as a pipe 1188ab2541b6SAric Cyr * that has no surface attached yet 11894562236bSHarry Wentland */ 1190b1f6d01cSDmytro Laktyushkin static struct pipe_ctx *acquire_free_pipe_for_head( 1191608ac7bbSJerry Zuo struct dc_state *context, 1192a2b8659dSTony Cheng const struct resource_pool *pool, 1193b1f6d01cSDmytro Laktyushkin struct pipe_ctx *head_pipe) 11944562236bSHarry Wentland { 11954562236bSHarry Wentland int i; 1196745cc746SDmytro Laktyushkin struct resource_context *res_ctx = &context->res_ctx; 11974562236bSHarry Wentland 11983be5262eSHarry Wentland if (!head_pipe->plane_state) 11994562236bSHarry Wentland return head_pipe; 12004562236bSHarry Wentland 12014562236bSHarry Wentland /* Re-use pipe already acquired for this stream if available*/ 1202a2b8659dSTony Cheng for (i = pool->pipe_count - 1; i >= 0; i--) { 1203b1f6d01cSDmytro Laktyushkin if (res_ctx->pipe_ctx[i].stream == head_pipe->stream && 12043be5262eSHarry Wentland !res_ctx->pipe_ctx[i].plane_state) { 12054562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 12064562236bSHarry Wentland } 12074562236bSHarry Wentland } 12084562236bSHarry Wentland 12094562236bSHarry Wentland /* 12104562236bSHarry Wentland * At this point we have no re-useable pipe for this stream and we need 12114562236bSHarry Wentland * to acquire an idle one to satisfy the request 12124562236bSHarry Wentland */ 12134562236bSHarry Wentland 1214a2b8659dSTony Cheng if (!pool->funcs->acquire_idle_pipe_for_layer) 12154562236bSHarry Wentland return NULL; 12164562236bSHarry Wentland 1217b1f6d01cSDmytro Laktyushkin return pool->funcs->acquire_idle_pipe_for_layer(context, pool, head_pipe->stream); 12184562236bSHarry Wentland } 12194562236bSHarry Wentland 1220dc37a9a0SLeo (Sunpeng) Li #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 12210f9a536fSDmytro Laktyushkin static int acquire_first_split_pipe( 12220f9a536fSDmytro Laktyushkin struct resource_context *res_ctx, 12230f9a536fSDmytro Laktyushkin const struct resource_pool *pool, 12240971c40eSHarry Wentland struct dc_stream_state *stream) 12250f9a536fSDmytro Laktyushkin { 12260f9a536fSDmytro Laktyushkin int i; 12270f9a536fSDmytro Laktyushkin 12280f9a536fSDmytro Laktyushkin for (i = 0; i < pool->pipe_count; i++) { 122979592db3SDmytro Laktyushkin struct pipe_ctx *split_pipe = &res_ctx->pipe_ctx[i]; 12300f9a536fSDmytro Laktyushkin 1231b1f6d01cSDmytro Laktyushkin if (split_pipe->top_pipe && 123279592db3SDmytro Laktyushkin split_pipe->top_pipe->plane_state == split_pipe->plane_state) { 123379592db3SDmytro Laktyushkin split_pipe->top_pipe->bottom_pipe = split_pipe->bottom_pipe; 123479592db3SDmytro Laktyushkin if (split_pipe->bottom_pipe) 123579592db3SDmytro Laktyushkin split_pipe->bottom_pipe->top_pipe = split_pipe->top_pipe; 12360f9a536fSDmytro Laktyushkin 123779592db3SDmytro Laktyushkin if (split_pipe->top_pipe->plane_state) 123879592db3SDmytro Laktyushkin resource_build_scaling_params(split_pipe->top_pipe); 12390f9a536fSDmytro Laktyushkin 124079592db3SDmytro Laktyushkin memset(split_pipe, 0, sizeof(*split_pipe)); 124179592db3SDmytro Laktyushkin split_pipe->stream_res.tg = pool->timing_generators[i]; 124279592db3SDmytro Laktyushkin split_pipe->plane_res.hubp = pool->hubps[i]; 124379592db3SDmytro Laktyushkin split_pipe->plane_res.ipp = pool->ipps[i]; 124479592db3SDmytro Laktyushkin split_pipe->plane_res.dpp = pool->dpps[i]; 124579592db3SDmytro Laktyushkin split_pipe->stream_res.opp = pool->opps[i]; 124679592db3SDmytro Laktyushkin split_pipe->plane_res.mpcc_inst = pool->dpps[i]->inst; 124779592db3SDmytro Laktyushkin split_pipe->pipe_idx = i; 124879592db3SDmytro Laktyushkin 124979592db3SDmytro Laktyushkin split_pipe->stream = stream; 12500f9a536fSDmytro Laktyushkin return i; 12510f9a536fSDmytro Laktyushkin } 12520f9a536fSDmytro Laktyushkin } 12530f9a536fSDmytro Laktyushkin return -1; 12540f9a536fSDmytro Laktyushkin } 12550f9a536fSDmytro Laktyushkin #endif 12560f9a536fSDmytro Laktyushkin 125719f89e23SAndrey Grodzovsky bool dc_add_plane_to_context( 125819f89e23SAndrey Grodzovsky const struct dc *dc, 12590971c40eSHarry Wentland struct dc_stream_state *stream, 126019f89e23SAndrey Grodzovsky struct dc_plane_state *plane_state, 1261608ac7bbSJerry Zuo struct dc_state *context) 12624562236bSHarry Wentland { 12634562236bSHarry Wentland int i; 126419f89e23SAndrey Grodzovsky struct resource_pool *pool = dc->res_pool; 126519f89e23SAndrey Grodzovsky struct pipe_ctx *head_pipe, *tail_pipe, *free_pipe; 1266ab2541b6SAric Cyr struct dc_stream_status *stream_status = NULL; 12674562236bSHarry Wentland 1268ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) 12694fa086b9SLeo (Sunpeng) Li if (context->streams[i] == stream) { 1270ab2541b6SAric Cyr stream_status = &context->stream_status[i]; 12714562236bSHarry Wentland break; 12724562236bSHarry Wentland } 1273ab2541b6SAric Cyr if (stream_status == NULL) { 127419f89e23SAndrey Grodzovsky dm_error("Existing stream not found; failed to attach surface!\n"); 127519f89e23SAndrey Grodzovsky return false; 127619f89e23SAndrey Grodzovsky } 127719f89e23SAndrey Grodzovsky 127819f89e23SAndrey Grodzovsky 127919f89e23SAndrey Grodzovsky if (stream_status->plane_count == MAX_SURFACE_NUM) { 128019f89e23SAndrey Grodzovsky dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n", 128119f89e23SAndrey Grodzovsky plane_state, MAX_SURFACE_NUM); 128219f89e23SAndrey Grodzovsky return false; 128319f89e23SAndrey Grodzovsky } 128419f89e23SAndrey Grodzovsky 128519f89e23SAndrey Grodzovsky head_pipe = resource_get_head_pipe_for_stream(&context->res_ctx, stream); 128619f89e23SAndrey Grodzovsky 128719f89e23SAndrey Grodzovsky if (!head_pipe) { 128819f89e23SAndrey Grodzovsky dm_error("Head pipe not found for stream_state %p !\n", stream); 12894562236bSHarry Wentland return false; 12904562236bSHarry Wentland } 12914562236bSHarry Wentland 1292b1f6d01cSDmytro Laktyushkin /* retain new surface, but only once per stream */ 1293b1f6d01cSDmytro Laktyushkin dc_plane_state_retain(plane_state); 1294b1f6d01cSDmytro Laktyushkin 1295b1f6d01cSDmytro Laktyushkin while (head_pipe) { 1296b1f6d01cSDmytro Laktyushkin tail_pipe = resource_get_tail_pipe(&context->res_ctx, head_pipe); 129700737c59SEric Bernstein ASSERT(tail_pipe); 129800737c59SEric Bernstein 1299b1f6d01cSDmytro Laktyushkin free_pipe = acquire_free_pipe_for_head(context, pool, head_pipe); 13004562236bSHarry Wentland 1301dc37a9a0SLeo (Sunpeng) Li #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 13020f9a536fSDmytro Laktyushkin if (!free_pipe) { 13030f9a536fSDmytro Laktyushkin int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 13040f9a536fSDmytro Laktyushkin if (pipe_idx >= 0) 13050f9a536fSDmytro Laktyushkin free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; 13060f9a536fSDmytro Laktyushkin } 13070f9a536fSDmytro Laktyushkin #endif 1308b1f6d01cSDmytro Laktyushkin if (!free_pipe) { 1309b1f6d01cSDmytro Laktyushkin dc_plane_state_release(plane_state); 13104562236bSHarry Wentland return false; 1311b1f6d01cSDmytro Laktyushkin } 13124562236bSHarry Wentland 13133be5262eSHarry Wentland free_pipe->plane_state = plane_state; 13144562236bSHarry Wentland 131519f89e23SAndrey Grodzovsky if (head_pipe != free_pipe) { 13166b670fa9SHarry Wentland free_pipe->stream_res.tg = tail_pipe->stream_res.tg; 13179aef1a31SSivapiriyanKumarasamy free_pipe->stream_res.abm = tail_pipe->stream_res.abm; 1318a6a6cb34SHarry Wentland free_pipe->stream_res.opp = tail_pipe->stream_res.opp; 13198e9c4c8cSHarry Wentland free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; 1320afaacef4SHarry Wentland free_pipe->stream_res.audio = tail_pipe->stream_res.audio; 1321cfe4645eSDmytro Laktyushkin free_pipe->clock_source = tail_pipe->clock_source; 13224562236bSHarry Wentland free_pipe->top_pipe = tail_pipe; 13234562236bSHarry Wentland tail_pipe->bottom_pipe = free_pipe; 13244562236bSHarry Wentland } 1325b1f6d01cSDmytro Laktyushkin head_pipe = head_pipe->next_odm_pipe; 1326b1f6d01cSDmytro Laktyushkin } 13274562236bSHarry Wentland /* assign new surfaces*/ 132819f89e23SAndrey Grodzovsky stream_status->plane_states[stream_status->plane_count] = plane_state; 13294562236bSHarry Wentland 133019f89e23SAndrey Grodzovsky stream_status->plane_count++; 13314562236bSHarry Wentland 13324562236bSHarry Wentland return true; 13334562236bSHarry Wentland } 13344562236bSHarry Wentland 133519f89e23SAndrey Grodzovsky bool dc_remove_plane_from_context( 133619f89e23SAndrey Grodzovsky const struct dc *dc, 133719f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 133819f89e23SAndrey Grodzovsky struct dc_plane_state *plane_state, 1339608ac7bbSJerry Zuo struct dc_state *context) 134019f89e23SAndrey Grodzovsky { 134119f89e23SAndrey Grodzovsky int i; 134219f89e23SAndrey Grodzovsky struct dc_stream_status *stream_status = NULL; 134319f89e23SAndrey Grodzovsky struct resource_pool *pool = dc->res_pool; 134419f89e23SAndrey Grodzovsky 134519f89e23SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 134619f89e23SAndrey Grodzovsky if (context->streams[i] == stream) { 134719f89e23SAndrey Grodzovsky stream_status = &context->stream_status[i]; 134819f89e23SAndrey Grodzovsky break; 134919f89e23SAndrey Grodzovsky } 135019f89e23SAndrey Grodzovsky 135119f89e23SAndrey Grodzovsky if (stream_status == NULL) { 135219f89e23SAndrey Grodzovsky dm_error("Existing stream not found; failed to remove plane.\n"); 135319f89e23SAndrey Grodzovsky return false; 135419f89e23SAndrey Grodzovsky } 135519f89e23SAndrey Grodzovsky 135619f89e23SAndrey Grodzovsky /* release pipe for plane*/ 135719f89e23SAndrey Grodzovsky for (i = pool->pipe_count - 1; i >= 0; i--) { 13586ffaa6fcSDmytro Laktyushkin struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 135919f89e23SAndrey Grodzovsky 13606ffaa6fcSDmytro Laktyushkin if (pipe_ctx->plane_state == plane_state) { 136119f89e23SAndrey Grodzovsky if (pipe_ctx->top_pipe) 136219f89e23SAndrey Grodzovsky pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; 136319f89e23SAndrey Grodzovsky 136419f89e23SAndrey Grodzovsky /* Second condition is to avoid setting NULL to top pipe 136519f89e23SAndrey Grodzovsky * of tail pipe making it look like head pipe in subsequent 136619f89e23SAndrey Grodzovsky * deletes 136719f89e23SAndrey Grodzovsky */ 136819f89e23SAndrey Grodzovsky if (pipe_ctx->bottom_pipe && pipe_ctx->top_pipe) 136919f89e23SAndrey Grodzovsky pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; 137019f89e23SAndrey Grodzovsky 137119f89e23SAndrey Grodzovsky /* 137219f89e23SAndrey Grodzovsky * For head pipe detach surfaces from pipe for tail 137319f89e23SAndrey Grodzovsky * pipe just zero it out 137419f89e23SAndrey Grodzovsky */ 1375b1f6d01cSDmytro Laktyushkin if (!pipe_ctx->top_pipe) 137619f89e23SAndrey Grodzovsky pipe_ctx->plane_state = NULL; 1377b1f6d01cSDmytro Laktyushkin else 137819f89e23SAndrey Grodzovsky memset(pipe_ctx, 0, sizeof(*pipe_ctx)); 137919f89e23SAndrey Grodzovsky } 138019f89e23SAndrey Grodzovsky } 138119f89e23SAndrey Grodzovsky 138219f89e23SAndrey Grodzovsky 138319f89e23SAndrey Grodzovsky for (i = 0; i < stream_status->plane_count; i++) { 138419f89e23SAndrey Grodzovsky if (stream_status->plane_states[i] == plane_state) { 138519f89e23SAndrey Grodzovsky 138619f89e23SAndrey Grodzovsky dc_plane_state_release(stream_status->plane_states[i]); 138719f89e23SAndrey Grodzovsky break; 138819f89e23SAndrey Grodzovsky } 138919f89e23SAndrey Grodzovsky } 139019f89e23SAndrey Grodzovsky 139119f89e23SAndrey Grodzovsky if (i == stream_status->plane_count) { 139219f89e23SAndrey Grodzovsky dm_error("Existing plane_state not found; failed to detach it!\n"); 139319f89e23SAndrey Grodzovsky return false; 139419f89e23SAndrey Grodzovsky } 139519f89e23SAndrey Grodzovsky 139619f89e23SAndrey Grodzovsky stream_status->plane_count--; 139719f89e23SAndrey Grodzovsky 1398abb4986eSAndrew Jiang /* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */ 1399abb4986eSAndrew Jiang for (; i < stream_status->plane_count; i++) 140019f89e23SAndrey Grodzovsky stream_status->plane_states[i] = stream_status->plane_states[i + 1]; 140119f89e23SAndrey Grodzovsky 140219f89e23SAndrey Grodzovsky stream_status->plane_states[stream_status->plane_count] = NULL; 140319f89e23SAndrey Grodzovsky 140419f89e23SAndrey Grodzovsky return true; 140519f89e23SAndrey Grodzovsky } 140619f89e23SAndrey Grodzovsky 140719f89e23SAndrey Grodzovsky bool dc_rem_all_planes_for_stream( 140819f89e23SAndrey Grodzovsky const struct dc *dc, 140919f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 1410608ac7bbSJerry Zuo struct dc_state *context) 141119f89e23SAndrey Grodzovsky { 141219f89e23SAndrey Grodzovsky int i, old_plane_count; 141319f89e23SAndrey Grodzovsky struct dc_stream_status *stream_status = NULL; 141419f89e23SAndrey Grodzovsky struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 }; 141519f89e23SAndrey Grodzovsky 141619f89e23SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 141719f89e23SAndrey Grodzovsky if (context->streams[i] == stream) { 141819f89e23SAndrey Grodzovsky stream_status = &context->stream_status[i]; 141919f89e23SAndrey Grodzovsky break; 142019f89e23SAndrey Grodzovsky } 142119f89e23SAndrey Grodzovsky 142219f89e23SAndrey Grodzovsky if (stream_status == NULL) { 142319f89e23SAndrey Grodzovsky dm_error("Existing stream %p not found!\n", stream); 142419f89e23SAndrey Grodzovsky return false; 142519f89e23SAndrey Grodzovsky } 142619f89e23SAndrey Grodzovsky 142719f89e23SAndrey Grodzovsky old_plane_count = stream_status->plane_count; 142819f89e23SAndrey Grodzovsky 142919f89e23SAndrey Grodzovsky for (i = 0; i < old_plane_count; i++) 143019f89e23SAndrey Grodzovsky del_planes[i] = stream_status->plane_states[i]; 143119f89e23SAndrey Grodzovsky 143219f89e23SAndrey Grodzovsky for (i = 0; i < old_plane_count; i++) 143319f89e23SAndrey Grodzovsky if (!dc_remove_plane_from_context(dc, stream, del_planes[i], context)) 143419f89e23SAndrey Grodzovsky return false; 143519f89e23SAndrey Grodzovsky 143619f89e23SAndrey Grodzovsky return true; 143719f89e23SAndrey Grodzovsky } 143819f89e23SAndrey Grodzovsky 143919f89e23SAndrey Grodzovsky static bool add_all_planes_for_stream( 144019f89e23SAndrey Grodzovsky const struct dc *dc, 144119f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 144219f89e23SAndrey Grodzovsky const struct dc_validation_set set[], 144319f89e23SAndrey Grodzovsky int set_count, 1444608ac7bbSJerry Zuo struct dc_state *context) 144519f89e23SAndrey Grodzovsky { 144619f89e23SAndrey Grodzovsky int i, j; 144719f89e23SAndrey Grodzovsky 144819f89e23SAndrey Grodzovsky for (i = 0; i < set_count; i++) 144919f89e23SAndrey Grodzovsky if (set[i].stream == stream) 145019f89e23SAndrey Grodzovsky break; 145119f89e23SAndrey Grodzovsky 145219f89e23SAndrey Grodzovsky if (i == set_count) { 145319f89e23SAndrey Grodzovsky dm_error("Stream %p not found in set!\n", stream); 145419f89e23SAndrey Grodzovsky return false; 145519f89e23SAndrey Grodzovsky } 145619f89e23SAndrey Grodzovsky 145719f89e23SAndrey Grodzovsky for (j = 0; j < set[i].plane_count; j++) 145819f89e23SAndrey Grodzovsky if (!dc_add_plane_to_context(dc, stream, set[i].plane_states[j], context)) 145919f89e23SAndrey Grodzovsky return false; 146019f89e23SAndrey Grodzovsky 146119f89e23SAndrey Grodzovsky return true; 146219f89e23SAndrey Grodzovsky } 146319f89e23SAndrey Grodzovsky 146419f89e23SAndrey Grodzovsky bool dc_add_all_planes_for_stream( 146519f89e23SAndrey Grodzovsky const struct dc *dc, 146619f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 146719f89e23SAndrey Grodzovsky struct dc_plane_state * const *plane_states, 146819f89e23SAndrey Grodzovsky int plane_count, 1469608ac7bbSJerry Zuo struct dc_state *context) 147019f89e23SAndrey Grodzovsky { 147119f89e23SAndrey Grodzovsky struct dc_validation_set set; 147219f89e23SAndrey Grodzovsky int i; 147319f89e23SAndrey Grodzovsky 147419f89e23SAndrey Grodzovsky set.stream = stream; 147519f89e23SAndrey Grodzovsky set.plane_count = plane_count; 147619f89e23SAndrey Grodzovsky 147719f89e23SAndrey Grodzovsky for (i = 0; i < plane_count; i++) 147819f89e23SAndrey Grodzovsky set.plane_states[i] = plane_states[i]; 147919f89e23SAndrey Grodzovsky 148019f89e23SAndrey Grodzovsky return add_all_planes_for_stream(dc, stream, &set, 1, context); 148119f89e23SAndrey Grodzovsky } 148219f89e23SAndrey Grodzovsky 148319f89e23SAndrey Grodzovsky 14846b622181SJulian Parkin static bool is_hdr_static_meta_changed(struct dc_stream_state *cur_stream, 14856b622181SJulian Parkin struct dc_stream_state *new_stream) 14866b622181SJulian Parkin { 14876b622181SJulian Parkin if (cur_stream == NULL) 14886b622181SJulian Parkin return true; 14896b622181SJulian Parkin 14906b622181SJulian Parkin if (memcmp(&cur_stream->hdr_static_metadata, 14916b622181SJulian Parkin &new_stream->hdr_static_metadata, 14926b622181SJulian Parkin sizeof(struct dc_info_packet)) != 0) 14936b622181SJulian Parkin return true; 14946b622181SJulian Parkin 14956b622181SJulian Parkin return false; 14966b622181SJulian Parkin } 14974562236bSHarry Wentland 14981336926fSAlvin lee static bool is_vsc_info_packet_changed(struct dc_stream_state *cur_stream, 14991336926fSAlvin lee struct dc_stream_state *new_stream) 15001336926fSAlvin lee { 15011336926fSAlvin lee if (cur_stream == NULL) 15021336926fSAlvin lee return true; 15031336926fSAlvin lee 15041336926fSAlvin lee if (memcmp(&cur_stream->vsc_infopacket, 15051336926fSAlvin lee &new_stream->vsc_infopacket, 15061336926fSAlvin lee sizeof(struct dc_info_packet)) != 0) 15071336926fSAlvin lee return true; 15081336926fSAlvin lee 15091336926fSAlvin lee return false; 15101336926fSAlvin lee } 15111336926fSAlvin lee 15120971c40eSHarry Wentland static bool is_timing_changed(struct dc_stream_state *cur_stream, 15130971c40eSHarry Wentland struct dc_stream_state *new_stream) 15144562236bSHarry Wentland { 15154562236bSHarry Wentland if (cur_stream == NULL) 15164562236bSHarry Wentland return true; 15174562236bSHarry Wentland 15184562236bSHarry Wentland /* If sink pointer changed, it means this is a hotplug, we should do 15194562236bSHarry Wentland * full hw setting. 15204562236bSHarry Wentland */ 15214562236bSHarry Wentland if (cur_stream->sink != new_stream->sink) 15224562236bSHarry Wentland return true; 15234562236bSHarry Wentland 15244562236bSHarry Wentland /* If output color space is changed, need to reprogram info frames */ 15254fa086b9SLeo (Sunpeng) Li if (cur_stream->output_color_space != new_stream->output_color_space) 15264562236bSHarry Wentland return true; 15274562236bSHarry Wentland 15284562236bSHarry Wentland return memcmp( 15294fa086b9SLeo (Sunpeng) Li &cur_stream->timing, 15304fa086b9SLeo (Sunpeng) Li &new_stream->timing, 15314562236bSHarry Wentland sizeof(struct dc_crtc_timing)) != 0; 15324562236bSHarry Wentland } 15334562236bSHarry Wentland 15344562236bSHarry Wentland static bool are_stream_backends_same( 15350971c40eSHarry Wentland struct dc_stream_state *stream_a, struct dc_stream_state *stream_b) 15364562236bSHarry Wentland { 15374562236bSHarry Wentland if (stream_a == stream_b) 15384562236bSHarry Wentland return true; 15394562236bSHarry Wentland 15404562236bSHarry Wentland if (stream_a == NULL || stream_b == NULL) 15414562236bSHarry Wentland return false; 15424562236bSHarry Wentland 15434562236bSHarry Wentland if (is_timing_changed(stream_a, stream_b)) 15444562236bSHarry Wentland return false; 15454562236bSHarry Wentland 15466b622181SJulian Parkin if (is_hdr_static_meta_changed(stream_a, stream_b)) 15476b622181SJulian Parkin return false; 15486b622181SJulian Parkin 15491e7e86c4SSamson Tam if (stream_a->dpms_off != stream_b->dpms_off) 15501e7e86c4SSamson Tam return false; 15511e7e86c4SSamson Tam 15521336926fSAlvin lee if (is_vsc_info_packet_changed(stream_a, stream_b)) 15531336926fSAlvin lee return false; 15541336926fSAlvin lee 15554562236bSHarry Wentland return true; 15564562236bSHarry Wentland } 15574562236bSHarry Wentland 15582119aa17SDavid Francis /** 15592119aa17SDavid Francis * dc_is_stream_unchanged() - Compare two stream states for equivalence. 15602119aa17SDavid Francis * 15612119aa17SDavid Francis * Checks if there a difference between the two states 15622119aa17SDavid Francis * that would require a mode change. 15632119aa17SDavid Francis * 15642119aa17SDavid Francis * Does not compare cursor position or attributes. 15652119aa17SDavid Francis */ 1566d54d29dbSBhawanpreet Lakha bool dc_is_stream_unchanged( 15670971c40eSHarry Wentland struct dc_stream_state *old_stream, struct dc_stream_state *stream) 15684562236bSHarry Wentland { 15694562236bSHarry Wentland 15704562236bSHarry Wentland if (!are_stream_backends_same(old_stream, stream)) 15714562236bSHarry Wentland return false; 15724562236bSHarry Wentland 15730460f9abSJun Lei if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param) 15740460f9abSJun Lei return false; 15750460f9abSJun Lei 15764562236bSHarry Wentland return true; 15774562236bSHarry Wentland } 15784562236bSHarry Wentland 15792119aa17SDavid Francis /** 15802119aa17SDavid Francis * dc_is_stream_scaling_unchanged() - Compare scaling rectangles of two streams. 15812119aa17SDavid Francis */ 15829a5d9c48SLeo (Sunpeng) Li bool dc_is_stream_scaling_unchanged( 15839a5d9c48SLeo (Sunpeng) Li struct dc_stream_state *old_stream, struct dc_stream_state *stream) 15849a5d9c48SLeo (Sunpeng) Li { 15859a5d9c48SLeo (Sunpeng) Li if (old_stream == stream) 15869a5d9c48SLeo (Sunpeng) Li return true; 15879a5d9c48SLeo (Sunpeng) Li 15889a5d9c48SLeo (Sunpeng) Li if (old_stream == NULL || stream == NULL) 15899a5d9c48SLeo (Sunpeng) Li return false; 15909a5d9c48SLeo (Sunpeng) Li 15919a5d9c48SLeo (Sunpeng) Li if (memcmp(&old_stream->src, 15929a5d9c48SLeo (Sunpeng) Li &stream->src, 15939a5d9c48SLeo (Sunpeng) Li sizeof(struct rect)) != 0) 15949a5d9c48SLeo (Sunpeng) Li return false; 15959a5d9c48SLeo (Sunpeng) Li 15969a5d9c48SLeo (Sunpeng) Li if (memcmp(&old_stream->dst, 15979a5d9c48SLeo (Sunpeng) Li &stream->dst, 15989a5d9c48SLeo (Sunpeng) Li sizeof(struct rect)) != 0) 15999a5d9c48SLeo (Sunpeng) Li return false; 16009a5d9c48SLeo (Sunpeng) Li 16019a5d9c48SLeo (Sunpeng) Li return true; 16029a5d9c48SLeo (Sunpeng) Li } 16039a5d9c48SLeo (Sunpeng) Li 16041dc90497SAndrey Grodzovsky static void update_stream_engine_usage( 16054562236bSHarry Wentland struct resource_context *res_ctx, 1606a2b8659dSTony Cheng const struct resource_pool *pool, 16071dc90497SAndrey Grodzovsky struct stream_encoder *stream_enc, 16081dc90497SAndrey Grodzovsky bool acquired) 16094562236bSHarry Wentland { 16104562236bSHarry Wentland int i; 16114562236bSHarry Wentland 1612a2b8659dSTony Cheng for (i = 0; i < pool->stream_enc_count; i++) { 1613a2b8659dSTony Cheng if (pool->stream_enc[i] == stream_enc) 16141dc90497SAndrey Grodzovsky res_ctx->is_stream_enc_acquired[i] = acquired; 16154562236bSHarry Wentland } 16164562236bSHarry Wentland } 16174562236bSHarry Wentland 16184562236bSHarry Wentland /* TODO: release audio object */ 16194176664bSCharlene Liu void update_audio_usage( 16204562236bSHarry Wentland struct resource_context *res_ctx, 1621a2b8659dSTony Cheng const struct resource_pool *pool, 16221dc90497SAndrey Grodzovsky struct audio *audio, 16231dc90497SAndrey Grodzovsky bool acquired) 16244562236bSHarry Wentland { 16254562236bSHarry Wentland int i; 1626a2b8659dSTony Cheng for (i = 0; i < pool->audio_count; i++) { 1627a2b8659dSTony Cheng if (pool->audios[i] == audio) 16281dc90497SAndrey Grodzovsky res_ctx->is_audio_acquired[i] = acquired; 16294562236bSHarry Wentland } 16304562236bSHarry Wentland } 16314562236bSHarry Wentland 16324562236bSHarry Wentland static int acquire_first_free_pipe( 16334562236bSHarry Wentland struct resource_context *res_ctx, 1634a2b8659dSTony Cheng const struct resource_pool *pool, 16350971c40eSHarry Wentland struct dc_stream_state *stream) 16364562236bSHarry Wentland { 16374562236bSHarry Wentland int i; 16384562236bSHarry Wentland 1639a2b8659dSTony Cheng for (i = 0; i < pool->pipe_count; i++) { 16404562236bSHarry Wentland if (!res_ctx->pipe_ctx[i].stream) { 16414562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 16424562236bSHarry Wentland 16436b670fa9SHarry Wentland pipe_ctx->stream_res.tg = pool->timing_generators[i]; 164486a66c4eSHarry Wentland pipe_ctx->plane_res.mi = pool->mis[i]; 16458feabd03SYue Hin Lau pipe_ctx->plane_res.hubp = pool->hubps[i]; 164686a66c4eSHarry Wentland pipe_ctx->plane_res.ipp = pool->ipps[i]; 164786a66c4eSHarry Wentland pipe_ctx->plane_res.xfm = pool->transforms[i]; 1648d94585a0SYue Hin Lau pipe_ctx->plane_res.dpp = pool->dpps[i]; 1649a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp = pool->opps[i]; 1650bc373a89SRoman Li if (pool->dpps[i]) 1651e07f541fSYongqiang Sun pipe_ctx->plane_res.mpcc_inst = pool->dpps[i]->inst; 16524562236bSHarry Wentland pipe_ctx->pipe_idx = i; 16534562236bSHarry Wentland 1654ff5ef992SAlex Deucher 16554562236bSHarry Wentland pipe_ctx->stream = stream; 16564562236bSHarry Wentland return i; 16574562236bSHarry Wentland } 16584562236bSHarry Wentland } 16594562236bSHarry Wentland return -1; 16604562236bSHarry Wentland } 16614562236bSHarry Wentland 1662a2b8659dSTony Cheng static struct audio *find_first_free_audio( 1663a2b8659dSTony Cheng struct resource_context *res_ctx, 1664cfb071f7SCharlene Liu const struct resource_pool *pool, 1665f24b0522SPaul Hsieh enum engine_id id, 1666f24b0522SPaul Hsieh enum dce_version dc_version) 16674562236bSHarry Wentland { 1668b5a41620SCharlene Liu int i, available_audio_count; 1669b5a41620SCharlene Liu 1670b5a41620SCharlene Liu available_audio_count = pool->audio_count; 1671b5a41620SCharlene Liu 1672b5a41620SCharlene Liu for (i = 0; i < available_audio_count; i++) { 16734176664bSCharlene Liu if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) { 1674cfb071f7SCharlene Liu /*we have enough audio endpoint, find the matching inst*/ 1675cfb071f7SCharlene Liu if (id != i) 1676cfb071f7SCharlene Liu continue; 1677a2b8659dSTony Cheng return pool->audios[i]; 16784562236bSHarry Wentland } 16794562236bSHarry Wentland } 16805feb9f07STai Man 16815feb9f07STai Man /* use engine id to find free audio */ 1682b5a41620SCharlene Liu if ((id < available_audio_count) && (res_ctx->is_audio_acquired[id] == false)) { 16835feb9f07STai Man return pool->audios[id]; 16845feb9f07STai Man } 168566bfd4fdSCharlene Liu /*not found the matching one, first come first serve*/ 1686b5a41620SCharlene Liu for (i = 0; i < available_audio_count; i++) { 16874176664bSCharlene Liu if (res_ctx->is_audio_acquired[i] == false) { 16884176664bSCharlene Liu return pool->audios[i]; 16894176664bSCharlene Liu } 16904176664bSCharlene Liu } 16914562236bSHarry Wentland return 0; 16924562236bSHarry Wentland } 16934562236bSHarry Wentland 16944562236bSHarry Wentland bool resource_is_stream_unchanged( 1695608ac7bbSJerry Zuo struct dc_state *old_context, struct dc_stream_state *stream) 16964562236bSHarry Wentland { 1697ab2541b6SAric Cyr int i; 16984562236bSHarry Wentland 1699ab2541b6SAric Cyr for (i = 0; i < old_context->stream_count; i++) { 17000971c40eSHarry Wentland struct dc_stream_state *old_stream = old_context->streams[i]; 17014562236bSHarry Wentland 17024562236bSHarry Wentland if (are_stream_backends_same(old_stream, stream)) 17034562236bSHarry Wentland return true; 17044562236bSHarry Wentland } 17054562236bSHarry Wentland 17064562236bSHarry Wentland return false; 17074562236bSHarry Wentland } 17084562236bSHarry Wentland 17092119aa17SDavid Francis /** 17102119aa17SDavid Francis * dc_add_stream_to_ctx() - Add a new dc_stream_state to a dc_state. 17112119aa17SDavid Francis */ 171213ab1b44SYongqiang Sun enum dc_status dc_add_stream_to_ctx( 17131dc90497SAndrey Grodzovsky struct dc *dc, 1714608ac7bbSJerry Zuo struct dc_state *new_ctx, 17151dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 17161dc90497SAndrey Grodzovsky { 17171dc90497SAndrey Grodzovsky enum dc_status res; 1718eb9714a2SWenjing Liu DC_LOGGER_INIT(dc->ctx->logger); 17191dc90497SAndrey Grodzovsky 1720ece4147fSKen Chalmers if (new_ctx->stream_count >= dc->res_pool->timing_generator_count) { 1721eb9714a2SWenjing Liu DC_LOG_WARNING("Max streams reached, can't add stream %p !\n", stream); 17221dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 17231dc90497SAndrey Grodzovsky } 17241dc90497SAndrey Grodzovsky 17251dc90497SAndrey Grodzovsky new_ctx->streams[new_ctx->stream_count] = stream; 17261dc90497SAndrey Grodzovsky dc_stream_retain(stream); 17271dc90497SAndrey Grodzovsky new_ctx->stream_count++; 17281dc90497SAndrey Grodzovsky 17291dc90497SAndrey Grodzovsky res = dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream); 17301dc90497SAndrey Grodzovsky if (res != DC_OK) 1731eb9714a2SWenjing Liu DC_LOG_WARNING("Adding stream %p to context failed with err %d!\n", stream, res); 17321dc90497SAndrey Grodzovsky 173313ab1b44SYongqiang Sun return res; 17341dc90497SAndrey Grodzovsky } 17351dc90497SAndrey Grodzovsky 17362119aa17SDavid Francis /** 17372119aa17SDavid Francis * dc_remove_stream_from_ctx() - Remove a stream from a dc_state. 17382119aa17SDavid Francis */ 173962c933f9SYongqiang Sun enum dc_status dc_remove_stream_from_ctx( 17401dc90497SAndrey Grodzovsky struct dc *dc, 1741608ac7bbSJerry Zuo struct dc_state *new_ctx, 17421dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 17431dc90497SAndrey Grodzovsky { 174419f89e23SAndrey Grodzovsky int i; 17451dc90497SAndrey Grodzovsky struct dc_context *dc_ctx = dc->ctx; 174622498036SDmytro Laktyushkin struct pipe_ctx *del_pipe = resource_get_head_pipe_for_stream(&new_ctx->res_ctx, stream); 174722498036SDmytro Laktyushkin struct pipe_ctx *odm_pipe; 174822498036SDmytro Laktyushkin 174922498036SDmytro Laktyushkin if (!del_pipe) { 175022498036SDmytro Laktyushkin DC_ERROR("Pipe not found for stream %p !\n", stream); 175122498036SDmytro Laktyushkin return DC_ERROR_UNEXPECTED; 175222498036SDmytro Laktyushkin } 175322498036SDmytro Laktyushkin 175422498036SDmytro Laktyushkin odm_pipe = del_pipe->next_odm_pipe; 17551dc90497SAndrey Grodzovsky 175619f89e23SAndrey Grodzovsky /* Release primary pipe */ 175719f89e23SAndrey Grodzovsky ASSERT(del_pipe->stream_res.stream_enc); 17581dc90497SAndrey Grodzovsky update_stream_engine_usage( 17591dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 17601dc90497SAndrey Grodzovsky dc->res_pool, 17611dc90497SAndrey Grodzovsky del_pipe->stream_res.stream_enc, 17621dc90497SAndrey Grodzovsky false); 17631dc90497SAndrey Grodzovsky 17641dc90497SAndrey Grodzovsky if (del_pipe->stream_res.audio) 17651dc90497SAndrey Grodzovsky update_audio_usage( 17661dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 17671dc90497SAndrey Grodzovsky dc->res_pool, 17681dc90497SAndrey Grodzovsky del_pipe->stream_res.audio, 17691dc90497SAndrey Grodzovsky false); 17701dc90497SAndrey Grodzovsky 17719d0dcecdSHarry Wentland resource_unreference_clock_source(&new_ctx->res_ctx, 17729d0dcecdSHarry Wentland dc->res_pool, 17739d0dcecdSHarry Wentland del_pipe->clock_source); 17749d0dcecdSHarry Wentland 1775e56ae556SNikola Cornij if (dc->res_pool->funcs->remove_stream_from_ctx) 1776e56ae556SNikola Cornij dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream); 1777e56ae556SNikola Cornij 177822498036SDmytro Laktyushkin while (odm_pipe) { 177922498036SDmytro Laktyushkin struct pipe_ctx *next_odm_pipe = odm_pipe->next_odm_pipe; 178022498036SDmytro Laktyushkin 178122498036SDmytro Laktyushkin memset(odm_pipe, 0, sizeof(*odm_pipe)); 178222498036SDmytro Laktyushkin odm_pipe = next_odm_pipe; 178322498036SDmytro Laktyushkin } 17841dc90497SAndrey Grodzovsky memset(del_pipe, 0, sizeof(*del_pipe)); 17856ffaa6fcSDmytro Laktyushkin 17861dc90497SAndrey Grodzovsky for (i = 0; i < new_ctx->stream_count; i++) 17871dc90497SAndrey Grodzovsky if (new_ctx->streams[i] == stream) 17881dc90497SAndrey Grodzovsky break; 17891dc90497SAndrey Grodzovsky 17901dc90497SAndrey Grodzovsky if (new_ctx->streams[i] != stream) { 17911dc90497SAndrey Grodzovsky DC_ERROR("Context doesn't have stream %p !\n", stream); 17921dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 17931dc90497SAndrey Grodzovsky } 17941dc90497SAndrey Grodzovsky 17951dc90497SAndrey Grodzovsky dc_stream_release(new_ctx->streams[i]); 17961dc90497SAndrey Grodzovsky new_ctx->stream_count--; 17971dc90497SAndrey Grodzovsky 17981dc90497SAndrey Grodzovsky /* Trim back arrays */ 17991dc90497SAndrey Grodzovsky for (; i < new_ctx->stream_count; i++) { 18001dc90497SAndrey Grodzovsky new_ctx->streams[i] = new_ctx->streams[i + 1]; 18011dc90497SAndrey Grodzovsky new_ctx->stream_status[i] = new_ctx->stream_status[i + 1]; 18021dc90497SAndrey Grodzovsky } 18031dc90497SAndrey Grodzovsky 18041dc90497SAndrey Grodzovsky new_ctx->streams[new_ctx->stream_count] = NULL; 18051dc90497SAndrey Grodzovsky memset( 18061dc90497SAndrey Grodzovsky &new_ctx->stream_status[new_ctx->stream_count], 18071dc90497SAndrey Grodzovsky 0, 18081dc90497SAndrey Grodzovsky sizeof(new_ctx->stream_status[0])); 18091dc90497SAndrey Grodzovsky 18101dc90497SAndrey Grodzovsky return DC_OK; 18111dc90497SAndrey Grodzovsky } 18121dc90497SAndrey Grodzovsky 18130971c40eSHarry Wentland static struct dc_stream_state *find_pll_sharable_stream( 18140971c40eSHarry Wentland struct dc_stream_state *stream_needs_pll, 1815608ac7bbSJerry Zuo struct dc_state *context) 18164562236bSHarry Wentland { 1817ab2541b6SAric Cyr int i; 18184562236bSHarry Wentland 1819ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 18200971c40eSHarry Wentland struct dc_stream_state *stream_has_pll = context->streams[i]; 18214562236bSHarry Wentland 18224562236bSHarry Wentland /* We are looking for non dp, non virtual stream */ 18234562236bSHarry Wentland if (resource_are_streams_timing_synchronizable( 18244562236bSHarry Wentland stream_needs_pll, stream_has_pll) 18254562236bSHarry Wentland && !dc_is_dp_signal(stream_has_pll->signal) 1826ceb3dbb4SJun Lei && stream_has_pll->link->connector_signal 18274562236bSHarry Wentland != SIGNAL_TYPE_VIRTUAL) 18284562236bSHarry Wentland return stream_has_pll; 1829ab2541b6SAric Cyr 18304562236bSHarry Wentland } 18314562236bSHarry Wentland 18324562236bSHarry Wentland return NULL; 18334562236bSHarry Wentland } 18344562236bSHarry Wentland 18354562236bSHarry Wentland static int get_norm_pix_clk(const struct dc_crtc_timing *timing) 18364562236bSHarry Wentland { 1837380604e2SKen Chalmers uint32_t pix_clk = timing->pix_clk_100hz; 18384562236bSHarry Wentland uint32_t normalized_pix_clk = pix_clk; 18394562236bSHarry Wentland 18404562236bSHarry Wentland if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) 18414562236bSHarry Wentland pix_clk /= 2; 1842cc4d99b8SCharlene Liu if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) { 18434562236bSHarry Wentland switch (timing->display_color_depth) { 18448897810aSJulian Parkin case COLOR_DEPTH_666: 18454562236bSHarry Wentland case COLOR_DEPTH_888: 18464562236bSHarry Wentland normalized_pix_clk = pix_clk; 18474562236bSHarry Wentland break; 18484562236bSHarry Wentland case COLOR_DEPTH_101010: 18494562236bSHarry Wentland normalized_pix_clk = (pix_clk * 30) / 24; 18504562236bSHarry Wentland break; 18514562236bSHarry Wentland case COLOR_DEPTH_121212: 18524562236bSHarry Wentland normalized_pix_clk = (pix_clk * 36) / 24; 18534562236bSHarry Wentland break; 18544562236bSHarry Wentland case COLOR_DEPTH_161616: 18554562236bSHarry Wentland normalized_pix_clk = (pix_clk * 48) / 24; 18564562236bSHarry Wentland break; 18574562236bSHarry Wentland default: 18584562236bSHarry Wentland ASSERT(0); 18594562236bSHarry Wentland break; 18604562236bSHarry Wentland } 1861cc4d99b8SCharlene Liu } 18624562236bSHarry Wentland return normalized_pix_clk; 18634562236bSHarry Wentland } 18644562236bSHarry Wentland 18650971c40eSHarry Wentland static void calculate_phy_pix_clks(struct dc_stream_state *stream) 18664562236bSHarry Wentland { 18674562236bSHarry Wentland /* update actual pixel clock on all streams */ 18684562236bSHarry Wentland if (dc_is_hdmi_signal(stream->signal)) 18694562236bSHarry Wentland stream->phy_pix_clk = get_norm_pix_clk( 1870380604e2SKen Chalmers &stream->timing) / 10; 18714562236bSHarry Wentland else 18724562236bSHarry Wentland stream->phy_pix_clk = 1873380604e2SKen Chalmers stream->timing.pix_clk_100hz / 10; 187439c03e00SCharlene Liu 187539c03e00SCharlene Liu if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) 187639c03e00SCharlene Liu stream->phy_pix_clk *= 2; 18774562236bSHarry Wentland } 18784562236bSHarry Wentland 1879d2d7885fSAnthony Koo static int acquire_resource_from_hw_enabled_state( 1880d2d7885fSAnthony Koo struct resource_context *res_ctx, 1881d2d7885fSAnthony Koo const struct resource_pool *pool, 1882d2d7885fSAnthony Koo struct dc_stream_state *stream) 1883d2d7885fSAnthony Koo { 1884d2d7885fSAnthony Koo struct dc_link *link = stream->link; 188508b66279SMartin Leung unsigned int i, inst, tg_inst = 0; 1886d2d7885fSAnthony Koo 1887d2d7885fSAnthony Koo /* Check for enabled DIG to identify enabled display */ 1888d2d7885fSAnthony Koo if (!link->link_enc->funcs->is_dig_enabled(link->link_enc)) 1889d2d7885fSAnthony Koo return -1; 1890d2d7885fSAnthony Koo 18915ec43edaSMartin Leung inst = link->link_enc->funcs->get_dig_frontend(link->link_enc); 1892d2d7885fSAnthony Koo 18937f7652eeSMartin Leung if (inst == ENGINE_ID_UNKNOWN) 18947f7652eeSMartin Leung return false; 1895d2d7885fSAnthony Koo 18967f7652eeSMartin Leung for (i = 0; i < pool->stream_enc_count; i++) { 18977f7652eeSMartin Leung if (pool->stream_enc[i]->id == inst) { 18987f7652eeSMartin Leung tg_inst = pool->stream_enc[i]->funcs->dig_source_otg( 18997f7652eeSMartin Leung pool->stream_enc[i]); 19007f7652eeSMartin Leung break; 19017f7652eeSMartin Leung } 19027f7652eeSMartin Leung } 1903d2d7885fSAnthony Koo 19047f7652eeSMartin Leung // tg_inst not found 19057f7652eeSMartin Leung if (i == pool->stream_enc_count) 19067f7652eeSMartin Leung return false; 19075ec43edaSMartin Leung 19085ec43edaSMartin Leung if (tg_inst >= pool->timing_generator_count) 19095ec43edaSMartin Leung return false; 19105ec43edaSMartin Leung 19115ec43edaSMartin Leung if (!res_ctx->pipe_ctx[tg_inst].stream) { 19125ec43edaSMartin Leung struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[tg_inst]; 19135ec43edaSMartin Leung 19145ec43edaSMartin Leung pipe_ctx->stream_res.tg = pool->timing_generators[tg_inst]; 19155ec43edaSMartin Leung pipe_ctx->plane_res.mi = pool->mis[tg_inst]; 19165ec43edaSMartin Leung pipe_ctx->plane_res.hubp = pool->hubps[tg_inst]; 19175ec43edaSMartin Leung pipe_ctx->plane_res.ipp = pool->ipps[tg_inst]; 19185ec43edaSMartin Leung pipe_ctx->plane_res.xfm = pool->transforms[tg_inst]; 19195ec43edaSMartin Leung pipe_ctx->plane_res.dpp = pool->dpps[tg_inst]; 19205ec43edaSMartin Leung pipe_ctx->stream_res.opp = pool->opps[tg_inst]; 19215ec43edaSMartin Leung 19225ec43edaSMartin Leung if (pool->dpps[tg_inst]) 19235ec43edaSMartin Leung pipe_ctx->plane_res.mpcc_inst = pool->dpps[tg_inst]->inst; 19245ec43edaSMartin Leung pipe_ctx->pipe_idx = tg_inst; 1925d2d7885fSAnthony Koo 1926d2d7885fSAnthony Koo pipe_ctx->stream = stream; 19275ec43edaSMartin Leung return tg_inst; 1928d2d7885fSAnthony Koo } 1929d2d7885fSAnthony Koo 1930d2d7885fSAnthony Koo return -1; 1931d2d7885fSAnthony Koo } 1932d2d7885fSAnthony Koo 19334562236bSHarry Wentland enum dc_status resource_map_pool_resources( 1934fb3466a4SBhawanpreet Lakha const struct dc *dc, 1935608ac7bbSJerry Zuo struct dc_state *context, 19361dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 19374562236bSHarry Wentland { 1938a2b8659dSTony Cheng const struct resource_pool *pool = dc->res_pool; 19391dc90497SAndrey Grodzovsky int i; 19401dc90497SAndrey Grodzovsky struct dc_context *dc_ctx = dc->ctx; 19411dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = NULL; 19421dc90497SAndrey Grodzovsky int pipe_idx = -1; 194346570f09SAnthony Koo struct dc_bios *dcb = dc->ctx->dc_bios; 19444562236bSHarry Wentland 19451dc90497SAndrey Grodzovsky /* TODO Check if this is needed */ 19461dc90497SAndrey Grodzovsky /*if (!resource_is_stream_unchanged(old_context, stream)) { 1947430ef426SDmytro Laktyushkin if (stream != NULL && old_context->streams[i] != NULL) { 19484b679bc3SCharlene Liu stream->bit_depth_params = 1949430ef426SDmytro Laktyushkin old_context->streams[i]->bit_depth_params; 1950430ef426SDmytro Laktyushkin stream->clamping = old_context->streams[i]->clamping; 19514562236bSHarry Wentland continue; 19524b679bc3SCharlene Liu } 19534b679bc3SCharlene Liu } 19544562236bSHarry Wentland */ 19554562236bSHarry Wentland 195608e1c28dSYogesh Mohan Marimuthu calculate_phy_pix_clks(stream); 195708e1c28dSYogesh Mohan Marimuthu 195846570f09SAnthony Koo /* TODO: Check Linux */ 195946570f09SAnthony Koo if (dc->config.allow_seamless_boot_optimization && 196046570f09SAnthony Koo !dcb->funcs->is_accelerated_mode(dcb)) { 196146570f09SAnthony Koo if (dc_validate_seamless_boot_timing(dc, stream->sink, &stream->timing)) 196246570f09SAnthony Koo stream->apply_seamless_boot_optimization = true; 196346570f09SAnthony Koo } 196446570f09SAnthony Koo 1965d2d7885fSAnthony Koo if (stream->apply_seamless_boot_optimization) 1966d2d7885fSAnthony Koo pipe_idx = acquire_resource_from_hw_enabled_state( 1967d2d7885fSAnthony Koo &context->res_ctx, 1968d2d7885fSAnthony Koo pool, 1969d2d7885fSAnthony Koo stream); 1970d2d7885fSAnthony Koo 1971d2d7885fSAnthony Koo if (pipe_idx < 0) 19724562236bSHarry Wentland /* acquire new resources */ 19735d11e9fcSDmytro Laktyushkin pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); 19741dc90497SAndrey Grodzovsky 1975dc37a9a0SLeo (Sunpeng) Li #ifdef CONFIG_DRM_AMD_DC_DCN1_0 19765d11e9fcSDmytro Laktyushkin if (pipe_idx < 0) 197713ab1b44SYongqiang Sun pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 197894c6d735SHarry Wentland #endif 197913ab1b44SYongqiang Sun 1980c5b38aecSDmytro Laktyushkin if (pipe_idx < 0 || context->res_ctx.pipe_ctx[pipe_idx].stream_res.tg == NULL) 19814562236bSHarry Wentland return DC_NO_CONTROLLER_RESOURCE; 19824562236bSHarry Wentland 19834562236bSHarry Wentland pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; 19844562236bSHarry Wentland 19858e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc = 198678cc70b1SWesley Chalmers dc->res_pool->funcs->find_first_free_match_stream_enc_for_link( 1987a2b8659dSTony Cheng &context->res_ctx, pool, stream); 19884562236bSHarry Wentland 19898e9c4c8cSHarry Wentland if (!pipe_ctx->stream_res.stream_enc) 199038684e46SEric Bernstein return DC_NO_STREAM_ENC_RESOURCE; 19914562236bSHarry Wentland 19921dc90497SAndrey Grodzovsky update_stream_engine_usage( 1993a2b8659dSTony Cheng &context->res_ctx, pool, 19941dc90497SAndrey Grodzovsky pipe_ctx->stream_res.stream_enc, 19951dc90497SAndrey Grodzovsky true); 19964562236bSHarry Wentland 19974562236bSHarry Wentland /* TODO: Add check if ASIC support and EDID audio */ 1998ceb3dbb4SJun Lei if (!stream->converter_disable_audio && 19994562236bSHarry Wentland dc_is_audio_capable_signal(pipe_ctx->stream->signal) && 2000ce08aad3SAlvin Lee stream->audio_info.mode_count && stream->audio_info.flags.all) { 2001afaacef4SHarry Wentland pipe_ctx->stream_res.audio = find_first_free_audio( 2002f24b0522SPaul Hsieh &context->res_ctx, pool, pipe_ctx->stream_res.stream_enc->id, dc_ctx->dce_version); 20034562236bSHarry Wentland 20044562236bSHarry Wentland /* 20054562236bSHarry Wentland * Audio assigned in order first come first get. 20064562236bSHarry Wentland * There are asics which has number of audio 20074562236bSHarry Wentland * resources less then number of pipes 20084562236bSHarry Wentland */ 2009afaacef4SHarry Wentland if (pipe_ctx->stream_res.audio) 20101dc90497SAndrey Grodzovsky update_audio_usage(&context->res_ctx, pool, 20111dc90497SAndrey Grodzovsky pipe_ctx->stream_res.audio, true); 20124562236bSHarry Wentland } 20134562236bSHarry Wentland 20149aef1a31SSivapiriyanKumarasamy /* Add ABM to the resource if on EDP */ 20159aef1a31SSivapiriyanKumarasamy if (pipe_ctx->stream && dc_is_embedded_signal(pipe_ctx->stream->signal)) 20169aef1a31SSivapiriyanKumarasamy pipe_ctx->stream_res.abm = pool->abm; 20179aef1a31SSivapiriyanKumarasamy 20181dc90497SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 20191dc90497SAndrey Grodzovsky if (context->streams[i] == stream) { 20206b670fa9SHarry Wentland context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; 20210f0bdca5SWenjing Liu context->stream_status[i].stream_enc_inst = pipe_ctx->stream_res.stream_enc->id; 20225fdb7c4cSNicholas Kazlauskas context->stream_status[i].audio_inst = 20235fdb7c4cSNicholas Kazlauskas pipe_ctx->stream_res.audio ? pipe_ctx->stream_res.audio->inst : -1; 20245fdb7c4cSNicholas Kazlauskas 20251dc90497SAndrey Grodzovsky return DC_OK; 20264562236bSHarry Wentland } 20274562236bSHarry Wentland 20281dc90497SAndrey Grodzovsky DC_ERROR("Stream %p not found in new ctx!\n", stream); 20291dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 20304562236bSHarry Wentland } 20314562236bSHarry Wentland 20322119aa17SDavid Francis /** 20332119aa17SDavid Francis * dc_resource_state_copy_construct_current() - Creates a new dc_state from existing state 20342119aa17SDavid Francis * Is a shallow copy. Increments refcounts on existing streams and planes. 20352119aa17SDavid Francis * @dc: copy out of dc->current_state 20362119aa17SDavid Francis * @dst_ctx: copy into this 20372119aa17SDavid Francis */ 2038f36cc577SBhawanpreet Lakha void dc_resource_state_copy_construct_current( 20391dc90497SAndrey Grodzovsky const struct dc *dc, 2040608ac7bbSJerry Zuo struct dc_state *dst_ctx) 20411dc90497SAndrey Grodzovsky { 2042f36cc577SBhawanpreet Lakha dc_resource_state_copy_construct(dc->current_state, dst_ctx); 20431dc90497SAndrey Grodzovsky } 20441dc90497SAndrey Grodzovsky 2045ab8db3e1SAndrey Grodzovsky 2046ab8db3e1SAndrey Grodzovsky void dc_resource_state_construct( 2047ab8db3e1SAndrey Grodzovsky const struct dc *dc, 2048ab8db3e1SAndrey Grodzovsky struct dc_state *dst_ctx) 2049ab8db3e1SAndrey Grodzovsky { 2050dc88b4a6SEric Yang dst_ctx->clk_mgr = dc->clk_mgr; 2051ab8db3e1SAndrey Grodzovsky } 2052ab8db3e1SAndrey Grodzovsky 20532119aa17SDavid Francis /** 20542119aa17SDavid Francis * dc_validate_global_state() - Determine if HW can support a given state 20552119aa17SDavid Francis * Checks HW resource availability and bandwidth requirement. 20562119aa17SDavid Francis * @dc: dc struct for this driver 20572119aa17SDavid Francis * @new_ctx: state to be validated 2058afcd526bSJoshua Aberback * @fast_validate: set to true if only yes/no to support matters 20592119aa17SDavid Francis * 20602119aa17SDavid Francis * Return: DC_OK if the result can be programmed. Otherwise, an error code. 20612119aa17SDavid Francis */ 2062e750d56dSYongqiang Sun enum dc_status dc_validate_global_state( 20631dc90497SAndrey Grodzovsky struct dc *dc, 2064afcd526bSJoshua Aberback struct dc_state *new_ctx, 2065afcd526bSJoshua Aberback bool fast_validate) 20661dc90497SAndrey Grodzovsky { 20671dc90497SAndrey Grodzovsky enum dc_status result = DC_ERROR_UNEXPECTED; 20681dc90497SAndrey Grodzovsky int i, j; 20691dc90497SAndrey Grodzovsky 2070e41ab030SHarry Wentland if (!new_ctx) 2071e41ab030SHarry Wentland return DC_ERROR_UNEXPECTED; 2072e41ab030SHarry Wentland 2073d596e5d0SYongqiang Sun if (dc->res_pool->funcs->validate_global) { 2074d596e5d0SYongqiang Sun result = dc->res_pool->funcs->validate_global(dc, new_ctx); 2075d596e5d0SYongqiang Sun if (result != DC_OK) 2076d596e5d0SYongqiang Sun return result; 2077d596e5d0SYongqiang Sun } 20781dc90497SAndrey Grodzovsky 2079e41ab030SHarry Wentland for (i = 0; i < new_ctx->stream_count; i++) { 20801dc90497SAndrey Grodzovsky struct dc_stream_state *stream = new_ctx->streams[i]; 20811dc90497SAndrey Grodzovsky 20821dc90497SAndrey Grodzovsky for (j = 0; j < dc->res_pool->pipe_count; j++) { 20831dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[j]; 20841dc90497SAndrey Grodzovsky 20851dc90497SAndrey Grodzovsky if (pipe_ctx->stream != stream) 20861dc90497SAndrey Grodzovsky continue; 20871dc90497SAndrey Grodzovsky 208874eac5f3SSu Sung Chung if (dc->res_pool->funcs->get_default_swizzle_mode && 208974eac5f3SSu Sung Chung pipe_ctx->plane_state && 209074eac5f3SSu Sung Chung pipe_ctx->plane_state->tiling_info.gfx9.swizzle == DC_SW_UNKNOWN) { 209174eac5f3SSu Sung Chung result = dc->res_pool->funcs->get_default_swizzle_mode(pipe_ctx->plane_state); 209274eac5f3SSu Sung Chung if (result != DC_OK) 209374eac5f3SSu Sung Chung return result; 209474eac5f3SSu Sung Chung } 209574eac5f3SSu Sung Chung 20961dc90497SAndrey Grodzovsky /* Switch to dp clock source only if there is 20971dc90497SAndrey Grodzovsky * no non dp stream that shares the same timing 20981dc90497SAndrey Grodzovsky * with the dp stream. 20991dc90497SAndrey Grodzovsky */ 21001dc90497SAndrey Grodzovsky if (dc_is_dp_signal(pipe_ctx->stream->signal) && 21011dc90497SAndrey Grodzovsky !find_pll_sharable_stream(stream, new_ctx)) { 21021dc90497SAndrey Grodzovsky 21039d0dcecdSHarry Wentland resource_unreference_clock_source( 21041dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 21051dc90497SAndrey Grodzovsky dc->res_pool, 21069d0dcecdSHarry Wentland pipe_ctx->clock_source); 21074a629536SHarry Wentland 21081dc90497SAndrey Grodzovsky pipe_ctx->clock_source = dc->res_pool->dp_clock_source; 21091dc90497SAndrey Grodzovsky resource_reference_clock_source( 21101dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 21111dc90497SAndrey Grodzovsky dc->res_pool, 21121dc90497SAndrey Grodzovsky pipe_ctx->clock_source); 21131dc90497SAndrey Grodzovsky } 21141dc90497SAndrey Grodzovsky } 21151dc90497SAndrey Grodzovsky } 21161dc90497SAndrey Grodzovsky 21171dc90497SAndrey Grodzovsky result = resource_build_scaling_params_for_context(dc, new_ctx); 21181dc90497SAndrey Grodzovsky 21191dc90497SAndrey Grodzovsky if (result == DC_OK) 2120afcd526bSJoshua Aberback if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, fast_validate)) 21211dc90497SAndrey Grodzovsky result = DC_FAIL_BANDWIDTH_VALIDATE; 21221dc90497SAndrey Grodzovsky 21231dc90497SAndrey Grodzovsky return result; 21241dc90497SAndrey Grodzovsky } 21251dc90497SAndrey Grodzovsky 21266e4d6beeSTony Cheng static void patch_gamut_packet_checksum( 2127e09b6473SAnthony Koo struct dc_info_packet *gamut_packet) 21284562236bSHarry Wentland { 21294562236bSHarry Wentland /* For gamut we recalc checksum */ 21306e4d6beeSTony Cheng if (gamut_packet->valid) { 21314562236bSHarry Wentland uint8_t chk_sum = 0; 21324562236bSHarry Wentland uint8_t *ptr; 21334562236bSHarry Wentland uint8_t i; 21344562236bSHarry Wentland 21354562236bSHarry Wentland /*start of the Gamut data. */ 21366e4d6beeSTony Cheng ptr = &gamut_packet->sb[3]; 21374562236bSHarry Wentland 21386e4d6beeSTony Cheng for (i = 0; i <= gamut_packet->sb[1]; i++) 21394562236bSHarry Wentland chk_sum += ptr[i]; 21404562236bSHarry Wentland 21416e4d6beeSTony Cheng gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum); 21421646a6feSAndrew Wong } 21434562236bSHarry Wentland } 21444562236bSHarry Wentland 21454562236bSHarry Wentland static void set_avi_info_frame( 2146e09b6473SAnthony Koo struct dc_info_packet *info_packet, 21474562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 21484562236bSHarry Wentland { 21490971c40eSHarry Wentland struct dc_stream_state *stream = pipe_ctx->stream; 21504562236bSHarry Wentland enum dc_color_space color_space = COLOR_SPACE_UNKNOWN; 21514562236bSHarry Wentland uint32_t pixel_encoding = 0; 21524562236bSHarry Wentland enum scanning_type scan_type = SCANNING_TYPE_NODATA; 21534562236bSHarry Wentland enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA; 21544562236bSHarry Wentland bool itc = false; 215550e27654SZeyu Fan uint8_t itc_value = 0; 21564562236bSHarry Wentland uint8_t cn0_cn1 = 0; 215750e27654SZeyu Fan unsigned int cn0_cn1_value = 0; 21584562236bSHarry Wentland uint8_t *check_sum = NULL; 21594562236bSHarry Wentland uint8_t byte_index = 0; 2160754e3673SAnthony Koo union hdmi_info_packet hdmi_info; 216150e27654SZeyu Fan union display_content_support support = {0}; 21624fa086b9SLeo (Sunpeng) Li unsigned int vic = pipe_ctx->stream->timing.vic; 216315e17335SCharlene Liu enum dc_timing_3d_format format; 21644562236bSHarry Wentland 2165754e3673SAnthony Koo memset(&hdmi_info, 0, sizeof(union hdmi_info_packet)); 2166754e3673SAnthony Koo 21674fa086b9SLeo (Sunpeng) Li color_space = pipe_ctx->stream->output_color_space; 2168e5f2038eSCharlene Liu if (color_space == COLOR_SPACE_UNKNOWN) 21694fa086b9SLeo (Sunpeng) Li color_space = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ? 2170e5f2038eSCharlene Liu COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709; 21714562236bSHarry Wentland 21724562236bSHarry Wentland /* Initialize header */ 2173e09b6473SAnthony Koo hdmi_info.bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI; 21744562236bSHarry Wentland /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall 21754562236bSHarry Wentland * not be used in HDMI 2.0 (Section 10.1) */ 2176e09b6473SAnthony Koo hdmi_info.bits.header.version = 2; 2177e09b6473SAnthony Koo hdmi_info.bits.header.length = HDMI_AVI_INFOFRAME_SIZE; 21784562236bSHarry Wentland 21794562236bSHarry Wentland /* 21804562236bSHarry Wentland * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built 21814562236bSHarry Wentland * according to HDMI 2.0 spec (Section 10.1) 21824562236bSHarry Wentland */ 21834562236bSHarry Wentland 21844fa086b9SLeo (Sunpeng) Li switch (stream->timing.pixel_encoding) { 21854562236bSHarry Wentland case PIXEL_ENCODING_YCBCR422: 21864562236bSHarry Wentland pixel_encoding = 1; 21874562236bSHarry Wentland break; 21884562236bSHarry Wentland 21894562236bSHarry Wentland case PIXEL_ENCODING_YCBCR444: 21904562236bSHarry Wentland pixel_encoding = 2; 21914562236bSHarry Wentland break; 21924562236bSHarry Wentland case PIXEL_ENCODING_YCBCR420: 21934562236bSHarry Wentland pixel_encoding = 3; 21944562236bSHarry Wentland break; 21954562236bSHarry Wentland 21964562236bSHarry Wentland case PIXEL_ENCODING_RGB: 21974562236bSHarry Wentland default: 21984562236bSHarry Wentland pixel_encoding = 0; 21994562236bSHarry Wentland } 22004562236bSHarry Wentland 22014562236bSHarry Wentland /* Y0_Y1_Y2 : The pixel encoding */ 22024562236bSHarry Wentland /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */ 2203e09b6473SAnthony Koo hdmi_info.bits.Y0_Y1_Y2 = pixel_encoding; 22044562236bSHarry Wentland 22054562236bSHarry Wentland /* A0 = 1 Active Format Information valid */ 2206e09b6473SAnthony Koo hdmi_info.bits.A0 = ACTIVE_FORMAT_VALID; 22074562236bSHarry Wentland 22084562236bSHarry Wentland /* B0, B1 = 3; Bar info data is valid */ 2209e09b6473SAnthony Koo hdmi_info.bits.B0_B1 = BAR_INFO_BOTH_VALID; 22104562236bSHarry Wentland 2211e09b6473SAnthony Koo hdmi_info.bits.SC0_SC1 = PICTURE_SCALING_UNIFORM; 22124562236bSHarry Wentland 22134562236bSHarry Wentland /* S0, S1 : Underscan / Overscan */ 22144562236bSHarry Wentland /* TODO: un-hardcode scan type */ 22154562236bSHarry Wentland scan_type = SCANNING_TYPE_UNDERSCAN; 2216e09b6473SAnthony Koo hdmi_info.bits.S0_S1 = scan_type; 22174562236bSHarry Wentland 22184562236bSHarry Wentland /* C0, C1 : Colorimetry */ 22198fde5884SCharlene Liu if (color_space == COLOR_SPACE_YCBCR709 || 222015e17335SCharlene Liu color_space == COLOR_SPACE_YCBCR709_LIMITED) 2221e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709; 22228fde5884SCharlene Liu else if (color_space == COLOR_SPACE_YCBCR601 || 22238fde5884SCharlene Liu color_space == COLOR_SPACE_YCBCR601_LIMITED) 2224e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_ITU601; 22258fde5884SCharlene Liu else { 2226e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_NO_DATA; 22278fde5884SCharlene Liu } 2228534db198SAmy Zhang if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE || 2229534db198SAmy Zhang color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE || 2230534db198SAmy Zhang color_space == COLOR_SPACE_2020_YCBCR) { 2231e09b6473SAnthony Koo hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR; 2232e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; 2233534db198SAmy Zhang } else if (color_space == COLOR_SPACE_ADOBERGB) { 2234e09b6473SAnthony Koo hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB; 2235e09b6473SAnthony Koo hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; 2236534db198SAmy Zhang } 2237534db198SAmy Zhang 22384562236bSHarry Wentland /* TODO: un-hardcode aspect ratio */ 22394fa086b9SLeo (Sunpeng) Li aspect = stream->timing.aspect_ratio; 22404562236bSHarry Wentland 22414562236bSHarry Wentland switch (aspect) { 22424562236bSHarry Wentland case ASPECT_RATIO_4_3: 22434562236bSHarry Wentland case ASPECT_RATIO_16_9: 2244e09b6473SAnthony Koo hdmi_info.bits.M0_M1 = aspect; 22454562236bSHarry Wentland break; 22464562236bSHarry Wentland 22474562236bSHarry Wentland case ASPECT_RATIO_NO_DATA: 22484562236bSHarry Wentland case ASPECT_RATIO_64_27: 22494562236bSHarry Wentland case ASPECT_RATIO_256_135: 22504562236bSHarry Wentland default: 2251e09b6473SAnthony Koo hdmi_info.bits.M0_M1 = 0; 22524562236bSHarry Wentland } 22534562236bSHarry Wentland 22544562236bSHarry Wentland /* Active Format Aspect ratio - same as Picture Aspect Ratio. */ 2255e09b6473SAnthony Koo hdmi_info.bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; 22564562236bSHarry Wentland 22574562236bSHarry Wentland /* TODO: un-hardcode cn0_cn1 and itc */ 225850e27654SZeyu Fan 22594562236bSHarry Wentland cn0_cn1 = 0; 226050e27654SZeyu Fan cn0_cn1_value = 0; 226150e27654SZeyu Fan 226250e27654SZeyu Fan itc = true; 226350e27654SZeyu Fan itc_value = 1; 226450e27654SZeyu Fan 2265ceb3dbb4SJun Lei support = stream->content_support; 22664562236bSHarry Wentland 22674562236bSHarry Wentland if (itc) { 226850e27654SZeyu Fan if (!support.bits.valid_content_type) { 226950e27654SZeyu Fan cn0_cn1_value = 0; 227050e27654SZeyu Fan } else { 227150e27654SZeyu Fan if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) { 227250e27654SZeyu Fan if (support.bits.graphics_content == 1) { 227350e27654SZeyu Fan cn0_cn1_value = 0; 227450e27654SZeyu Fan } 227550e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) { 227650e27654SZeyu Fan if (support.bits.photo_content == 1) { 227750e27654SZeyu Fan cn0_cn1_value = 1; 227850e27654SZeyu Fan } else { 227950e27654SZeyu Fan cn0_cn1_value = 0; 228050e27654SZeyu Fan itc_value = 0; 228150e27654SZeyu Fan } 228250e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) { 228350e27654SZeyu Fan if (support.bits.cinema_content == 1) { 228450e27654SZeyu Fan cn0_cn1_value = 2; 228550e27654SZeyu Fan } else { 228650e27654SZeyu Fan cn0_cn1_value = 0; 228750e27654SZeyu Fan itc_value = 0; 228850e27654SZeyu Fan } 228950e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) { 229050e27654SZeyu Fan if (support.bits.game_content == 1) { 229150e27654SZeyu Fan cn0_cn1_value = 3; 229250e27654SZeyu Fan } else { 229350e27654SZeyu Fan cn0_cn1_value = 0; 229450e27654SZeyu Fan itc_value = 0; 229550e27654SZeyu Fan } 229650e27654SZeyu Fan } 229750e27654SZeyu Fan } 2298e09b6473SAnthony Koo hdmi_info.bits.CN0_CN1 = cn0_cn1_value; 2299e09b6473SAnthony Koo hdmi_info.bits.ITC = itc_value; 23004562236bSHarry Wentland } 23014562236bSHarry Wentland 23024562236bSHarry Wentland /* TODO : We should handle YCC quantization */ 23034562236bSHarry Wentland /* but we do not have matrix calculation */ 2304ceb3dbb4SJun Lei if (stream->qs_bit == 1 && 2305ceb3dbb4SJun Lei stream->qy_bit == 1) { 230650e27654SZeyu Fan if (color_space == COLOR_SPACE_SRGB || 230750e27654SZeyu Fan color_space == COLOR_SPACE_2020_RGB_FULLRANGE) { 2308e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; 2309e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_FULL_RANGE; 231050e27654SZeyu Fan } else if (color_space == COLOR_SPACE_SRGB_LIMITED || 231150e27654SZeyu Fan color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) { 2312e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE; 2313e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 23144562236bSHarry Wentland } else { 2315e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 2316e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 23174562236bSHarry Wentland } 231850e27654SZeyu Fan } else { 2319e09b6473SAnthony Koo hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 2320e09b6473SAnthony Koo hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 232150e27654SZeyu Fan } 232250e27654SZeyu Fan 232315e17335SCharlene Liu ///VIC 23244fa086b9SLeo (Sunpeng) Li format = stream->timing.timing_3d_format; 232515e17335SCharlene Liu /*todo, add 3DStereo support*/ 232615e17335SCharlene Liu if (format != TIMING_3D_FORMAT_NONE) { 232715e17335SCharlene Liu // Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled 23284fa086b9SLeo (Sunpeng) Li switch (pipe_ctx->stream->timing.hdmi_vic) { 232915e17335SCharlene Liu case 1: 233015e17335SCharlene Liu vic = 95; 233115e17335SCharlene Liu break; 233215e17335SCharlene Liu case 2: 233315e17335SCharlene Liu vic = 94; 233415e17335SCharlene Liu break; 233515e17335SCharlene Liu case 3: 233615e17335SCharlene Liu vic = 93; 233715e17335SCharlene Liu break; 233815e17335SCharlene Liu case 4: 233915e17335SCharlene Liu vic = 98; 234015e17335SCharlene Liu break; 234115e17335SCharlene Liu default: 234215e17335SCharlene Liu break; 234315e17335SCharlene Liu } 234415e17335SCharlene Liu } 2345efa02336SChris Park /* If VIC >= 128, the Source shall use AVI InfoFrame Version 3*/ 2346e09b6473SAnthony Koo hdmi_info.bits.VIC0_VIC7 = vic; 2347efa02336SChris Park if (vic >= 128) 2348efa02336SChris Park hdmi_info.bits.header.version = 3; 2349efa02336SChris Park /* If (C1, C0)=(1, 1) and (EC2, EC1, EC0)=(1, 1, 1), 2350efa02336SChris Park * the Source shall use 20 AVI InfoFrame Version 4 2351efa02336SChris Park */ 2352efa02336SChris Park if (hdmi_info.bits.C0_C1 == COLORIMETRY_EXTENDED && 2353efa02336SChris Park hdmi_info.bits.EC0_EC2 == COLORIMETRYEX_RESERVED) { 2354efa02336SChris Park hdmi_info.bits.header.version = 4; 2355efa02336SChris Park hdmi_info.bits.header.length = 14; 2356efa02336SChris Park } 23574562236bSHarry Wentland 23584562236bSHarry Wentland /* pixel repetition 23594562236bSHarry Wentland * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel 23604562236bSHarry Wentland * repetition start from 1 */ 2361e09b6473SAnthony Koo hdmi_info.bits.PR0_PR3 = 0; 23624562236bSHarry Wentland 23634562236bSHarry Wentland /* Bar Info 23644562236bSHarry Wentland * barTop: Line Number of End of Top Bar. 23654562236bSHarry Wentland * barBottom: Line Number of Start of Bottom Bar. 23664562236bSHarry Wentland * barLeft: Pixel Number of End of Left Bar. 23674562236bSHarry Wentland * barRight: Pixel Number of Start of Right Bar. */ 2368e09b6473SAnthony Koo hdmi_info.bits.bar_top = stream->timing.v_border_top; 2369e09b6473SAnthony Koo hdmi_info.bits.bar_bottom = (stream->timing.v_total 23704fa086b9SLeo (Sunpeng) Li - stream->timing.v_border_bottom + 1); 2371e09b6473SAnthony Koo hdmi_info.bits.bar_left = stream->timing.h_border_left; 2372e09b6473SAnthony Koo hdmi_info.bits.bar_right = (stream->timing.h_total 23734fa086b9SLeo (Sunpeng) Li - stream->timing.h_border_right + 1); 23744562236bSHarry Wentland 23752f482c4fSChris Park /* Additional Colorimetry Extension 23762f482c4fSChris Park * Used in conduction with C0-C1 and EC0-EC2 23772f482c4fSChris Park * 0 = DCI-P3 RGB (D65) 23782f482c4fSChris Park * 1 = DCI-P3 RGB (theater) 23792f482c4fSChris Park */ 23802f482c4fSChris Park hdmi_info.bits.ACE0_ACE3 = 0; 23812f482c4fSChris Park 23824562236bSHarry Wentland /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ 2383e09b6473SAnthony Koo check_sum = &hdmi_info.packet_raw_data.sb[0]; 2384e8d726b7SReza Amini 2385efa02336SChris Park *check_sum = HDMI_INFOFRAME_TYPE_AVI + hdmi_info.bits.header.length + hdmi_info.bits.header.version; 23864562236bSHarry Wentland 2387efa02336SChris Park for (byte_index = 1; byte_index <= hdmi_info.bits.header.length; byte_index++) 2388e09b6473SAnthony Koo *check_sum += hdmi_info.packet_raw_data.sb[byte_index]; 23894562236bSHarry Wentland 23904562236bSHarry Wentland /* one byte complement */ 23914562236bSHarry Wentland *check_sum = (uint8_t) (0x100 - *check_sum); 23924562236bSHarry Wentland 23934562236bSHarry Wentland /* Store in hw_path_mode */ 2394e09b6473SAnthony Koo info_packet->hb0 = hdmi_info.packet_raw_data.hb0; 2395e09b6473SAnthony Koo info_packet->hb1 = hdmi_info.packet_raw_data.hb1; 2396e09b6473SAnthony Koo info_packet->hb2 = hdmi_info.packet_raw_data.hb2; 23974562236bSHarry Wentland 2398e09b6473SAnthony Koo for (byte_index = 0; byte_index < sizeof(hdmi_info.packet_raw_data.sb); byte_index++) 2399e09b6473SAnthony Koo info_packet->sb[byte_index] = hdmi_info.packet_raw_data.sb[byte_index]; 24004562236bSHarry Wentland 24014562236bSHarry Wentland info_packet->valid = true; 24024562236bSHarry Wentland } 24034562236bSHarry Wentland 24046e4d6beeSTony Cheng static void set_vendor_info_packet( 2405e09b6473SAnthony Koo struct dc_info_packet *info_packet, 24060971c40eSHarry Wentland struct dc_stream_state *stream) 24074562236bSHarry Wentland { 2408ecd0136bSHarmanprit Tatla /* SPD info packet for FreeSync */ 240915e17335SCharlene Liu 2410ecd0136bSHarmanprit Tatla /* Check if Freesync is supported. Return if false. If true, 2411ecd0136bSHarmanprit Tatla * set the corresponding bit in the info packet 2412ecd0136bSHarmanprit Tatla */ 2413ecd0136bSHarmanprit Tatla if (!stream->vsp_infopacket.valid) 24144562236bSHarry Wentland return; 24154562236bSHarry Wentland 2416ecd0136bSHarmanprit Tatla *info_packet = stream->vsp_infopacket; 24174562236bSHarry Wentland } 24184562236bSHarry Wentland 24196e4d6beeSTony Cheng static void set_spd_info_packet( 2420e09b6473SAnthony Koo struct dc_info_packet *info_packet, 24210971c40eSHarry Wentland struct dc_stream_state *stream) 24224562236bSHarry Wentland { 24234562236bSHarry Wentland /* SPD info packet for FreeSync */ 24244562236bSHarry Wentland 24254562236bSHarry Wentland /* Check if Freesync is supported. Return if false. If true, 24264562236bSHarry Wentland * set the corresponding bit in the info packet 24274562236bSHarry Wentland */ 242898e6436dSAnthony Koo if (!stream->vrr_infopacket.valid) 24294562236bSHarry Wentland return; 24304562236bSHarry Wentland 243198e6436dSAnthony Koo *info_packet = stream->vrr_infopacket; 24324562236bSHarry Wentland } 24334562236bSHarry Wentland 24341646a6feSAndrew Wong static void set_hdr_static_info_packet( 2435e09b6473SAnthony Koo struct dc_info_packet *info_packet, 24360971c40eSHarry Wentland struct dc_stream_state *stream) 24371646a6feSAndrew Wong { 24380eeef690SAnthony Koo /* HDR Static Metadata info packet for HDR10 */ 24391646a6feSAndrew Wong 2440a10dc97aSKrunoslav Kovac if (!stream->hdr_static_metadata.valid || 2441a10dc97aSKrunoslav Kovac stream->use_dynamic_meta) 244210bff005SYongqiang Sun return; 244310bff005SYongqiang Sun 24440eeef690SAnthony Koo *info_packet = stream->hdr_static_metadata; 24451646a6feSAndrew Wong } 24461646a6feSAndrew Wong 24476e4d6beeSTony Cheng static void set_vsc_info_packet( 2448e09b6473SAnthony Koo struct dc_info_packet *info_packet, 24490971c40eSHarry Wentland struct dc_stream_state *stream) 24504562236bSHarry Wentland { 24511336926fSAlvin lee if (!stream->vsc_infopacket.valid) 24524562236bSHarry Wentland return; 24534562236bSHarry Wentland 24541336926fSAlvin lee *info_packet = stream->vsc_infopacket; 24554562236bSHarry Wentland } 24564562236bSHarry Wentland 2457f36cc577SBhawanpreet Lakha void dc_resource_state_destruct(struct dc_state *context) 24584562236bSHarry Wentland { 24594562236bSHarry Wentland int i, j; 24604562236bSHarry Wentland 2461ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 24623be5262eSHarry Wentland for (j = 0; j < context->stream_status[i].plane_count; j++) 24633be5262eSHarry Wentland dc_plane_state_release( 24643be5262eSHarry Wentland context->stream_status[i].plane_states[j]); 24654562236bSHarry Wentland 24663be5262eSHarry Wentland context->stream_status[i].plane_count = 0; 24674fa086b9SLeo (Sunpeng) Li dc_stream_release(context->streams[i]); 2468ab2541b6SAric Cyr context->streams[i] = NULL; 24694562236bSHarry Wentland } 24704562236bSHarry Wentland } 24714562236bSHarry Wentland 2472f36cc577SBhawanpreet Lakha void dc_resource_state_copy_construct( 2473608ac7bbSJerry Zuo const struct dc_state *src_ctx, 2474608ac7bbSJerry Zuo struct dc_state *dst_ctx) 24754562236bSHarry Wentland { 24764562236bSHarry Wentland int i, j; 24778ee5702aSDave Airlie struct kref refcount = dst_ctx->refcount; 24784562236bSHarry Wentland 24794562236bSHarry Wentland *dst_ctx = *src_ctx; 24804562236bSHarry Wentland 2481a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 24824562236bSHarry Wentland struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i]; 24834562236bSHarry Wentland 24844562236bSHarry Wentland if (cur_pipe->top_pipe) 24854562236bSHarry Wentland cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; 24864562236bSHarry Wentland 24874562236bSHarry Wentland if (cur_pipe->bottom_pipe) 24884562236bSHarry Wentland cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; 2489b1f6d01cSDmytro Laktyushkin 2490b1f6d01cSDmytro Laktyushkin if (cur_pipe->next_odm_pipe) 2491b1f6d01cSDmytro Laktyushkin cur_pipe->next_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx]; 2492b1f6d01cSDmytro Laktyushkin 2493b1f6d01cSDmytro Laktyushkin if (cur_pipe->prev_odm_pipe) 2494b1f6d01cSDmytro Laktyushkin cur_pipe->prev_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx]; 24954562236bSHarry Wentland } 24964562236bSHarry Wentland 2497ab2541b6SAric Cyr for (i = 0; i < dst_ctx->stream_count; i++) { 24984fa086b9SLeo (Sunpeng) Li dc_stream_retain(dst_ctx->streams[i]); 24993be5262eSHarry Wentland for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++) 25003be5262eSHarry Wentland dc_plane_state_retain( 25013be5262eSHarry Wentland dst_ctx->stream_status[i].plane_states[j]); 25024562236bSHarry Wentland } 25039a3afbb3SAndrey Grodzovsky 25049a3afbb3SAndrey Grodzovsky /* context refcount should not be overridden */ 25058ee5702aSDave Airlie dst_ctx->refcount = refcount; 25069a3afbb3SAndrey Grodzovsky 25074562236bSHarry Wentland } 25084562236bSHarry Wentland 25094562236bSHarry Wentland struct clock_source *dc_resource_find_first_free_pll( 2510a2b8659dSTony Cheng struct resource_context *res_ctx, 2511a2b8659dSTony Cheng const struct resource_pool *pool) 25124562236bSHarry Wentland { 25134562236bSHarry Wentland int i; 25144562236bSHarry Wentland 2515a2b8659dSTony Cheng for (i = 0; i < pool->clk_src_count; ++i) { 25164562236bSHarry Wentland if (res_ctx->clock_source_ref_count[i] == 0) 2517a2b8659dSTony Cheng return pool->clock_sources[i]; 25184562236bSHarry Wentland } 25194562236bSHarry Wentland 25204562236bSHarry Wentland return NULL; 25214562236bSHarry Wentland } 25224562236bSHarry Wentland 25234562236bSHarry Wentland void resource_build_info_frame(struct pipe_ctx *pipe_ctx) 25244562236bSHarry Wentland { 25254562236bSHarry Wentland enum signal_type signal = SIGNAL_TYPE_NONE; 252696c50c0dSHarry Wentland struct encoder_info_frame *info = &pipe_ctx->stream_res.encoder_info_frame; 25274562236bSHarry Wentland 25284562236bSHarry Wentland /* default all packets to invalid */ 25296e4d6beeSTony Cheng info->avi.valid = false; 25306e4d6beeSTony Cheng info->gamut.valid = false; 25316e4d6beeSTony Cheng info->vendor.valid = false; 2532630e3573SJeff Smith info->spd.valid = false; 25336e4d6beeSTony Cheng info->hdrsmd.valid = false; 25346e4d6beeSTony Cheng info->vsc.valid = false; 25354562236bSHarry Wentland 25364562236bSHarry Wentland signal = pipe_ctx->stream->signal; 25374562236bSHarry Wentland 25384562236bSHarry Wentland /* HDMi and DP have different info packets*/ 25394562236bSHarry Wentland if (dc_is_hdmi_signal(signal)) { 25406e4d6beeSTony Cheng set_avi_info_frame(&info->avi, pipe_ctx); 25416e4d6beeSTony Cheng 25426e4d6beeSTony Cheng set_vendor_info_packet(&info->vendor, pipe_ctx->stream); 25436e4d6beeSTony Cheng 25446e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 25456e4d6beeSTony Cheng 254656ef6ed9SAnthony Koo set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 25476e4d6beeSTony Cheng 2548a33fa99dSHarry Wentland } else if (dc_is_dp_signal(signal)) { 25496e4d6beeSTony Cheng set_vsc_info_packet(&info->vsc, pipe_ctx->stream); 25506e4d6beeSTony Cheng 25516e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 25526e4d6beeSTony Cheng 255356ef6ed9SAnthony Koo set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 2554a33fa99dSHarry Wentland } 25554562236bSHarry Wentland 25566e4d6beeSTony Cheng patch_gamut_packet_checksum(&info->gamut); 25574562236bSHarry Wentland } 25584562236bSHarry Wentland 25594562236bSHarry Wentland enum dc_status resource_map_clock_resources( 2560fb3466a4SBhawanpreet Lakha const struct dc *dc, 2561608ac7bbSJerry Zuo struct dc_state *context, 25621dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 25634562236bSHarry Wentland { 25644562236bSHarry Wentland /* acquire new resources */ 25651dc90497SAndrey Grodzovsky const struct resource_pool *pool = dc->res_pool; 25661dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream( 25671dc90497SAndrey Grodzovsky &context->res_ctx, stream); 25684562236bSHarry Wentland 25691dc90497SAndrey Grodzovsky if (!pipe_ctx) 25701dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 25714562236bSHarry Wentland 25724562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal) 25734562236bSHarry Wentland || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) 2574a2b8659dSTony Cheng pipe_ctx->clock_source = pool->dp_clock_source; 25754562236bSHarry Wentland else { 25764562236bSHarry Wentland pipe_ctx->clock_source = NULL; 25774562236bSHarry Wentland 2578fb3466a4SBhawanpreet Lakha if (!dc->config.disable_disp_pll_sharing) 25794ed4e51bSMikita Lipski pipe_ctx->clock_source = resource_find_used_clk_src_for_sharing( 25804562236bSHarry Wentland &context->res_ctx, 25814562236bSHarry Wentland pipe_ctx); 25824562236bSHarry Wentland 25834562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 25844562236bSHarry Wentland pipe_ctx->clock_source = 2585a2b8659dSTony Cheng dc_resource_find_first_free_pll( 2586a2b8659dSTony Cheng &context->res_ctx, 2587a2b8659dSTony Cheng pool); 25884562236bSHarry Wentland } 25894562236bSHarry Wentland 25904562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 25914562236bSHarry Wentland return DC_NO_CLOCK_SOURCE_RESOURCE; 25924562236bSHarry Wentland 25934562236bSHarry Wentland resource_reference_clock_source( 2594a2b8659dSTony Cheng &context->res_ctx, pool, 25954562236bSHarry Wentland pipe_ctx->clock_source); 25964562236bSHarry Wentland 25974562236bSHarry Wentland return DC_OK; 25984562236bSHarry Wentland } 25994562236bSHarry Wentland 26004562236bSHarry Wentland /* 26014562236bSHarry Wentland * Note: We need to disable output if clock sources change, 26024562236bSHarry Wentland * since bios does optimization and doesn't apply if changing 26034562236bSHarry Wentland * PHY when not already disabled. 26044562236bSHarry Wentland */ 26054562236bSHarry Wentland bool pipe_need_reprogram( 26064562236bSHarry Wentland struct pipe_ctx *pipe_ctx_old, 26074562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 26084562236bSHarry Wentland { 2609cfe4645eSDmytro Laktyushkin if (!pipe_ctx_old->stream) 2610cfe4645eSDmytro Laktyushkin return false; 2611cfe4645eSDmytro Laktyushkin 26124562236bSHarry Wentland if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink) 26134562236bSHarry Wentland return true; 26144562236bSHarry Wentland 26154562236bSHarry Wentland if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal) 26164562236bSHarry Wentland return true; 26174562236bSHarry Wentland 2618afaacef4SHarry Wentland if (pipe_ctx_old->stream_res.audio != pipe_ctx->stream_res.audio) 26194562236bSHarry Wentland return true; 26204562236bSHarry Wentland 26214562236bSHarry Wentland if (pipe_ctx_old->clock_source != pipe_ctx->clock_source 26224562236bSHarry Wentland && pipe_ctx_old->stream != pipe_ctx->stream) 26234562236bSHarry Wentland return true; 26244562236bSHarry Wentland 26258e9c4c8cSHarry Wentland if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc) 26264562236bSHarry Wentland return true; 26274562236bSHarry Wentland 26284562236bSHarry Wentland if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 26294562236bSHarry Wentland return true; 26304562236bSHarry Wentland 26316b622181SJulian Parkin if (is_hdr_static_meta_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 26326b622181SJulian Parkin return true; 26334562236bSHarry Wentland 26341e7e86c4SSamson Tam if (pipe_ctx_old->stream->dpms_off != pipe_ctx->stream->dpms_off) 26351e7e86c4SSamson Tam return true; 26361e7e86c4SSamson Tam 26371336926fSAlvin lee if (is_vsc_info_packet_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 26381336926fSAlvin lee return true; 26391336926fSAlvin lee 2640eed928dcSCharlene Liu if (false == pipe_ctx_old->stream->link->link_state_valid && 2641eed928dcSCharlene Liu false == pipe_ctx_old->stream->dpms_off) 2642eed928dcSCharlene Liu return true; 2643eed928dcSCharlene Liu 26444562236bSHarry Wentland return false; 26454562236bSHarry Wentland } 2646529cad0fSDing Wang 26470971c40eSHarry Wentland void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, 2648529cad0fSDing Wang struct bit_depth_reduction_params *fmt_bit_depth) 2649529cad0fSDing Wang { 26504fa086b9SLeo (Sunpeng) Li enum dc_dither_option option = stream->dither_option; 2651529cad0fSDing Wang enum dc_pixel_encoding pixel_encoding = 26524fa086b9SLeo (Sunpeng) Li stream->timing.pixel_encoding; 2653529cad0fSDing Wang 2654529cad0fSDing Wang memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); 2655529cad0fSDing Wang 2656603767f9STony Cheng if (option == DITHER_OPTION_DEFAULT) { 2657603767f9STony Cheng switch (stream->timing.display_color_depth) { 2658603767f9STony Cheng case COLOR_DEPTH_666: 2659603767f9STony Cheng option = DITHER_OPTION_SPATIAL6; 2660603767f9STony Cheng break; 2661603767f9STony Cheng case COLOR_DEPTH_888: 2662603767f9STony Cheng option = DITHER_OPTION_SPATIAL8; 2663603767f9STony Cheng break; 2664603767f9STony Cheng case COLOR_DEPTH_101010: 2665603767f9STony Cheng option = DITHER_OPTION_SPATIAL10; 2666603767f9STony Cheng break; 2667603767f9STony Cheng default: 2668603767f9STony Cheng option = DITHER_OPTION_DISABLE; 2669603767f9STony Cheng } 2670603767f9STony Cheng } 2671603767f9STony Cheng 2672529cad0fSDing Wang if (option == DITHER_OPTION_DISABLE) 2673529cad0fSDing Wang return; 2674529cad0fSDing Wang 2675529cad0fSDing Wang if (option == DITHER_OPTION_TRUN6) { 2676529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2677529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 0; 2678529cad0fSDing Wang } else if (option == DITHER_OPTION_TRUN8 || 2679529cad0fSDing Wang option == DITHER_OPTION_TRUN8_SPATIAL6 || 2680529cad0fSDing Wang option == DITHER_OPTION_TRUN8_FM6) { 2681529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2682529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 1; 2683529cad0fSDing Wang } else if (option == DITHER_OPTION_TRUN10 || 2684529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL6 || 2685529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8 || 2686529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM8 || 2687529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM6 || 2688529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2689529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2690529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2691529cad0fSDing Wang } 2692529cad0fSDing Wang 2693529cad0fSDing Wang /* special case - Formatter can only reduce by 4 bits at most. 2694529cad0fSDing Wang * When reducing from 12 to 6 bits, 2695529cad0fSDing Wang * HW recommends we use trunc with round mode 2696529cad0fSDing Wang * (if we did nothing, trunc to 10 bits would be used) 2697529cad0fSDing Wang * note that any 12->10 bit reduction is ignored prior to DCE8, 2698529cad0fSDing Wang * as the input was 10 bits. 2699529cad0fSDing Wang */ 2700529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2701529cad0fSDing Wang option == DITHER_OPTION_SPATIAL6 || 2702529cad0fSDing Wang option == DITHER_OPTION_FM6) { 2703529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2704529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2705529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_MODE = 1; 2706529cad0fSDing Wang } 2707529cad0fSDing Wang 2708529cad0fSDing Wang /* spatial dither 2709529cad0fSDing Wang * note that spatial modes 1-3 are never used 2710529cad0fSDing Wang */ 2711529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2712529cad0fSDing Wang option == DITHER_OPTION_SPATIAL6 || 2713529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL6 || 2714529cad0fSDing Wang option == DITHER_OPTION_TRUN8_SPATIAL6) { 2715529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2716529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0; 2717529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2718529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2719529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2720529cad0fSDing Wang } else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM || 2721529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8 || 2722529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8_FM6 || 2723529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8 || 2724529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2725529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2726529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1; 2727529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2728529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2729529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2730529cad0fSDing Wang } else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM || 2731529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10 || 2732529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM8 || 2733529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM6) { 2734529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2735529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2; 2736529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2737529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2738529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2739529cad0fSDing Wang } 2740529cad0fSDing Wang 2741529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6 || 2742529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8 || 2743529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10) { 2744529cad0fSDing Wang fmt_bit_depth->flags.FRAME_RANDOM = 0; 2745529cad0fSDing Wang } else { 2746529cad0fSDing Wang fmt_bit_depth->flags.FRAME_RANDOM = 1; 2747529cad0fSDing Wang } 2748529cad0fSDing Wang 2749529cad0fSDing Wang ////////////////////// 2750529cad0fSDing Wang //// temporal dither 2751529cad0fSDing Wang ////////////////////// 2752529cad0fSDing Wang if (option == DITHER_OPTION_FM6 || 2753529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8_FM6 || 2754529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM6 || 2755529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM6 || 2756529cad0fSDing Wang option == DITHER_OPTION_TRUN8_FM6 || 2757529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2758529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2759529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0; 2760529cad0fSDing Wang } else if (option == DITHER_OPTION_FM8 || 2761529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM8 || 2762529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM8) { 2763529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2764529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1; 2765529cad0fSDing Wang } else if (option == DITHER_OPTION_FM10) { 2766529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2767529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2; 2768529cad0fSDing Wang } 2769529cad0fSDing Wang 2770529cad0fSDing Wang fmt_bit_depth->pixel_encoding = pixel_encoding; 2771529cad0fSDing Wang } 27729345d987SAndrey Grodzovsky 277362c933f9SYongqiang Sun enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) 27749345d987SAndrey Grodzovsky { 2775fb3466a4SBhawanpreet Lakha struct dc *core_dc = dc; 2776ceb3dbb4SJun Lei struct dc_link *link = stream->link; 27779345d987SAndrey Grodzovsky struct timing_generator *tg = core_dc->res_pool->timing_generators[0]; 27789345d987SAndrey Grodzovsky enum dc_status res = DC_OK; 27799345d987SAndrey Grodzovsky 27804fa086b9SLeo (Sunpeng) Li calculate_phy_pix_clks(stream); 27819345d987SAndrey Grodzovsky 27824fa086b9SLeo (Sunpeng) Li if (!tg->funcs->validate_timing(tg, &stream->timing)) 27839345d987SAndrey Grodzovsky res = DC_FAIL_CONTROLLER_VALIDATE; 27849345d987SAndrey Grodzovsky 2785248cbed6SEric Bernstein if (res == DC_OK) { 27869345d987SAndrey Grodzovsky if (!link->link_enc->funcs->validate_output_with_stream( 27874fa086b9SLeo (Sunpeng) Li link->link_enc, stream)) 27889345d987SAndrey Grodzovsky res = DC_FAIL_ENC_VALIDATE; 2789248cbed6SEric Bernstein } 27909345d987SAndrey Grodzovsky 27919345d987SAndrey Grodzovsky /* TODO: validate audio ASIC caps, encoder */ 27929345d987SAndrey Grodzovsky 27939345d987SAndrey Grodzovsky if (res == DC_OK) 27944fa086b9SLeo (Sunpeng) Li res = dc_link_validate_mode_timing(stream, 27959345d987SAndrey Grodzovsky link, 27964fa086b9SLeo (Sunpeng) Li &stream->timing); 27979345d987SAndrey Grodzovsky 279862c933f9SYongqiang Sun return res; 27999345d987SAndrey Grodzovsky } 2800792671d7SAndrey Grodzovsky 280162c933f9SYongqiang Sun enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) 2802792671d7SAndrey Grodzovsky { 280362c933f9SYongqiang Sun enum dc_status res = DC_OK; 280462c933f9SYongqiang Sun 2805792671d7SAndrey Grodzovsky /* TODO For now validates pixel format only */ 28068e7095b9SDmytro Laktyushkin if (dc->res_pool->funcs->validate_plane) 280762c933f9SYongqiang Sun return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps); 2808792671d7SAndrey Grodzovsky 280962c933f9SYongqiang Sun return res; 2810792671d7SAndrey Grodzovsky } 281174eac5f3SSu Sung Chung 281274eac5f3SSu Sung Chung unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format) 281374eac5f3SSu Sung Chung { 281474eac5f3SSu Sung Chung switch (format) { 281574eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 281674eac5f3SSu Sung Chung return 8; 281774eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 281874eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 281974eac5f3SSu Sung Chung return 12; 282074eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 282174eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 282274eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 282374eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 282474eac5f3SSu Sung Chung return 16; 282574eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 282674eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 282774eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 282874eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 282974eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 283074eac5f3SSu Sung Chung return 32; 283174eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 283274eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 283374eac5f3SSu Sung Chung case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 283474eac5f3SSu Sung Chung return 64; 283574eac5f3SSu Sung Chung default: 283674eac5f3SSu Sung Chung ASSERT_CRITICAL(false); 283774eac5f3SSu Sung Chung return -1; 283874eac5f3SSu Sung Chung } 283974eac5f3SSu Sung Chung } 2840