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 */ 254562236bSHarry Wentland #include "dm_services.h" 264562236bSHarry Wentland 274562236bSHarry Wentland #include "resource.h" 284562236bSHarry Wentland #include "include/irq_service_interface.h" 294562236bSHarry Wentland #include "link_encoder.h" 304562236bSHarry Wentland #include "stream_encoder.h" 314562236bSHarry Wentland #include "opp.h" 324562236bSHarry Wentland #include "timing_generator.h" 334562236bSHarry Wentland #include "transform.h" 34d94585a0SYue Hin Lau #include "dpp.h" 355ac3d3c9SCharlene Liu #include "core_types.h" 364562236bSHarry Wentland #include "set_mode_types.h" 374562236bSHarry Wentland #include "virtual/virtual_stream_encoder.h" 383b94a400STao #include "dpcd_defs.h" 394562236bSHarry Wentland 404562236bSHarry Wentland #include "dce80/dce80_resource.h" 414562236bSHarry Wentland #include "dce100/dce100_resource.h" 424562236bSHarry Wentland #include "dce110/dce110_resource.h" 434562236bSHarry Wentland #include "dce112/dce112_resource.h" 44ff5ef992SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 45ff5ef992SAlex Deucher #include "dcn10/dcn10_resource.h" 46ff5ef992SAlex Deucher #endif 472c8ad2d5SAlex Deucher #include "dce120/dce120_resource.h" 481296423bSBhawanpreet Lakha #define DC_LOGGER \ 491296423bSBhawanpreet Lakha ctx->logger 504562236bSHarry Wentland enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) 514562236bSHarry Wentland { 524562236bSHarry Wentland enum dce_version dc_version = DCE_VERSION_UNKNOWN; 534562236bSHarry Wentland switch (asic_id.chip_family) { 544562236bSHarry Wentland 554562236bSHarry Wentland case FAMILY_CI: 564562236bSHarry Wentland dc_version = DCE_VERSION_8_0; 574562236bSHarry Wentland break; 58ebfdf0d0SAlex Deucher case FAMILY_KV: 59ebfdf0d0SAlex Deucher if (ASIC_REV_IS_KALINDI(asic_id.hw_internal_rev) || 60ebfdf0d0SAlex Deucher ASIC_REV_IS_BHAVANI(asic_id.hw_internal_rev) || 61ebfdf0d0SAlex Deucher ASIC_REV_IS_GODAVARI(asic_id.hw_internal_rev)) 62ebfdf0d0SAlex Deucher dc_version = DCE_VERSION_8_3; 63ebfdf0d0SAlex Deucher else 64ebfdf0d0SAlex Deucher dc_version = DCE_VERSION_8_1; 65ebfdf0d0SAlex Deucher break; 664562236bSHarry Wentland case FAMILY_CZ: 674562236bSHarry Wentland dc_version = DCE_VERSION_11_0; 684562236bSHarry Wentland break; 694562236bSHarry Wentland 704562236bSHarry Wentland case FAMILY_VI: 714562236bSHarry Wentland if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) || 724562236bSHarry Wentland ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) { 734562236bSHarry Wentland dc_version = DCE_VERSION_10_0; 744562236bSHarry Wentland break; 754562236bSHarry Wentland } 764562236bSHarry Wentland if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) || 77b264d345SJordan Lazare ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || 78b264d345SJordan Lazare ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) { 794562236bSHarry Wentland dc_version = DCE_VERSION_11_2; 804562236bSHarry Wentland } 814562236bSHarry Wentland break; 822c8ad2d5SAlex Deucher case FAMILY_AI: 832c8ad2d5SAlex Deucher dc_version = DCE_VERSION_12_0; 842c8ad2d5SAlex Deucher break; 85ff5ef992SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 86ff5ef992SAlex Deucher case FAMILY_RV: 87ff5ef992SAlex Deucher dc_version = DCN_VERSION_1_0; 88ff5ef992SAlex Deucher break; 89ff5ef992SAlex Deucher #endif 904562236bSHarry Wentland default: 914562236bSHarry Wentland dc_version = DCE_VERSION_UNKNOWN; 924562236bSHarry Wentland break; 934562236bSHarry Wentland } 944562236bSHarry Wentland return dc_version; 954562236bSHarry Wentland } 964562236bSHarry Wentland 974562236bSHarry Wentland struct resource_pool *dc_create_resource_pool( 98fb3466a4SBhawanpreet Lakha struct dc *dc, 994562236bSHarry Wentland int num_virtual_links, 1004562236bSHarry Wentland enum dce_version dc_version, 1014562236bSHarry Wentland struct hw_asic_id asic_id) 1024562236bSHarry Wentland { 1035ac3d3c9SCharlene Liu struct resource_pool *res_pool = NULL; 1044562236bSHarry Wentland 1054562236bSHarry Wentland switch (dc_version) { 1064562236bSHarry Wentland case DCE_VERSION_8_0: 1075ac3d3c9SCharlene Liu res_pool = dce80_create_resource_pool( 1084562236bSHarry Wentland num_virtual_links, dc); 1095ac3d3c9SCharlene Liu break; 1107992a629SAlex Deucher case DCE_VERSION_8_1: 1117992a629SAlex Deucher res_pool = dce81_create_resource_pool( 1127992a629SAlex Deucher num_virtual_links, dc); 1137992a629SAlex Deucher break; 1147992a629SAlex Deucher case DCE_VERSION_8_3: 1157992a629SAlex Deucher res_pool = dce83_create_resource_pool( 1167992a629SAlex Deucher num_virtual_links, dc); 1177992a629SAlex Deucher break; 1184562236bSHarry Wentland case DCE_VERSION_10_0: 1195ac3d3c9SCharlene Liu res_pool = dce100_create_resource_pool( 1204562236bSHarry Wentland num_virtual_links, dc); 1215ac3d3c9SCharlene Liu break; 1224562236bSHarry Wentland case DCE_VERSION_11_0: 1235ac3d3c9SCharlene Liu res_pool = dce110_create_resource_pool( 1244562236bSHarry Wentland num_virtual_links, dc, asic_id); 1255ac3d3c9SCharlene Liu break; 1264562236bSHarry Wentland case DCE_VERSION_11_2: 1275ac3d3c9SCharlene Liu res_pool = dce112_create_resource_pool( 1284562236bSHarry Wentland num_virtual_links, dc); 1295ac3d3c9SCharlene Liu break; 1302c8ad2d5SAlex Deucher case DCE_VERSION_12_0: 1312c8ad2d5SAlex Deucher res_pool = dce120_create_resource_pool( 1322c8ad2d5SAlex Deucher num_virtual_links, dc); 1332c8ad2d5SAlex Deucher break; 134ff5ef992SAlex Deucher 135ff5ef992SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 136ff5ef992SAlex Deucher case DCN_VERSION_1_0: 137ff5ef992SAlex Deucher res_pool = dcn10_create_resource_pool( 138ff5ef992SAlex Deucher num_virtual_links, dc); 139ff5ef992SAlex Deucher break; 140ff5ef992SAlex Deucher #endif 1413639fa68SZeyu Fan 1423639fa68SZeyu Fan 1434562236bSHarry Wentland default: 1444562236bSHarry Wentland break; 1454562236bSHarry Wentland } 1465ac3d3c9SCharlene Liu if (res_pool != NULL) { 1471515a47bSHarry Wentland struct dc_firmware_info fw_info = { { 0 } }; 1484562236bSHarry Wentland 1495ac3d3c9SCharlene Liu if (dc->ctx->dc_bios->funcs->get_firmware_info( 1505ac3d3c9SCharlene Liu dc->ctx->dc_bios, &fw_info) == BP_RESULT_OK) { 1515ac3d3c9SCharlene Liu res_pool->ref_clock_inKhz = fw_info.pll_info.crystal_frequency; 1525ac3d3c9SCharlene Liu } else 1535ac3d3c9SCharlene Liu ASSERT_CRITICAL(false); 1545ac3d3c9SCharlene Liu } 1555ac3d3c9SCharlene Liu 1565ac3d3c9SCharlene Liu return res_pool; 1574562236bSHarry Wentland } 1584562236bSHarry Wentland 159fb3466a4SBhawanpreet Lakha void dc_destroy_resource_pool(struct dc *dc) 1604562236bSHarry Wentland { 1614562236bSHarry Wentland if (dc) { 1624562236bSHarry Wentland if (dc->res_pool) 1634562236bSHarry Wentland dc->res_pool->funcs->destroy(&dc->res_pool); 1644562236bSHarry Wentland 1652004f45eSHarry Wentland kfree(dc->hwseq); 1664562236bSHarry Wentland } 1674562236bSHarry Wentland } 1684562236bSHarry Wentland 1694562236bSHarry Wentland static void update_num_audio( 1704562236bSHarry Wentland const struct resource_straps *straps, 1714562236bSHarry Wentland unsigned int *num_audio, 1724562236bSHarry Wentland struct audio_support *aud_support) 1734562236bSHarry Wentland { 1744562236bSHarry Wentland aud_support->dp_audio = true; 175b8e9eb72SCharlene Liu aud_support->hdmi_audio_native = false; 176b8e9eb72SCharlene Liu aud_support->hdmi_audio_on_dongle = false; 177b8e9eb72SCharlene Liu 178b8e9eb72SCharlene Liu if (straps->hdmi_disable == 0) { 1794562236bSHarry Wentland if (straps->dc_pinstraps_audio & 0x2) { 1804562236bSHarry Wentland aud_support->hdmi_audio_on_dongle = true; 181b8e9eb72SCharlene Liu aud_support->hdmi_audio_native = true; 1824562236bSHarry Wentland } 1834562236bSHarry Wentland } 1844562236bSHarry Wentland 1854562236bSHarry Wentland switch (straps->audio_stream_number) { 1864562236bSHarry Wentland case 0: /* multi streams supported */ 1874562236bSHarry Wentland break; 1884562236bSHarry Wentland case 1: /* multi streams not supported */ 1894562236bSHarry Wentland *num_audio = 1; 1904562236bSHarry Wentland break; 1914562236bSHarry Wentland default: 1924562236bSHarry Wentland DC_ERR("DC: unexpected audio fuse!\n"); 19317a96033SJulia Lawall } 1944562236bSHarry Wentland } 1954562236bSHarry Wentland 1964562236bSHarry Wentland bool resource_construct( 1974562236bSHarry Wentland unsigned int num_virtual_links, 198fb3466a4SBhawanpreet Lakha struct dc *dc, 1994562236bSHarry Wentland struct resource_pool *pool, 2004562236bSHarry Wentland const struct resource_create_funcs *create_funcs) 2014562236bSHarry Wentland { 2024562236bSHarry Wentland struct dc_context *ctx = dc->ctx; 2034562236bSHarry Wentland const struct resource_caps *caps = pool->res_cap; 2044562236bSHarry Wentland int i; 2054562236bSHarry Wentland unsigned int num_audio = caps->num_audio; 2064562236bSHarry Wentland struct resource_straps straps = {0}; 2074562236bSHarry Wentland 2084562236bSHarry Wentland if (create_funcs->read_dce_straps) 2094562236bSHarry Wentland create_funcs->read_dce_straps(dc->ctx, &straps); 2104562236bSHarry Wentland 2114562236bSHarry Wentland pool->audio_count = 0; 2124562236bSHarry Wentland if (create_funcs->create_audio) { 2134562236bSHarry Wentland /* find the total number of streams available via the 2144562236bSHarry Wentland * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT 2154562236bSHarry Wentland * registers (one for each pin) starting from pin 1 2164562236bSHarry Wentland * up to the max number of audio pins. 2174562236bSHarry Wentland * We stop on the first pin where 2184562236bSHarry Wentland * PORT_CONNECTIVITY == 1 (as instructed by HW team). 2194562236bSHarry Wentland */ 2204562236bSHarry Wentland update_num_audio(&straps, &num_audio, &pool->audio_support); 2214562236bSHarry Wentland for (i = 0; i < pool->pipe_count && i < num_audio; i++) { 2224562236bSHarry Wentland struct audio *aud = create_funcs->create_audio(ctx, i); 2234562236bSHarry Wentland 2244562236bSHarry Wentland if (aud == NULL) { 2254562236bSHarry Wentland DC_ERR("DC: failed to create audio!\n"); 2264562236bSHarry Wentland return false; 2274562236bSHarry Wentland } 2284562236bSHarry Wentland 2294562236bSHarry Wentland if (!aud->funcs->endpoint_valid(aud)) { 2304562236bSHarry Wentland aud->funcs->destroy(&aud); 2314562236bSHarry Wentland break; 2324562236bSHarry Wentland } 2334562236bSHarry Wentland 2344562236bSHarry Wentland pool->audios[i] = aud; 2354562236bSHarry Wentland pool->audio_count++; 2364562236bSHarry Wentland } 2374562236bSHarry Wentland } 2384562236bSHarry Wentland 2394562236bSHarry Wentland pool->stream_enc_count = 0; 2404562236bSHarry Wentland if (create_funcs->create_stream_encoder) { 2414562236bSHarry Wentland for (i = 0; i < caps->num_stream_encoder; i++) { 2424562236bSHarry Wentland pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx); 2434562236bSHarry Wentland if (pool->stream_enc[i] == NULL) 2444562236bSHarry Wentland DC_ERR("DC: failed to create stream_encoder!\n"); 2454562236bSHarry Wentland pool->stream_enc_count++; 2464562236bSHarry Wentland } 2474562236bSHarry Wentland } 2484176664bSCharlene Liu dc->caps.dynamic_audio = false; 2494176664bSCharlene Liu if (pool->audio_count < pool->stream_enc_count) { 2504176664bSCharlene Liu dc->caps.dynamic_audio = true; 2514176664bSCharlene Liu } 2524562236bSHarry Wentland for (i = 0; i < num_virtual_links; i++) { 2534562236bSHarry Wentland pool->stream_enc[pool->stream_enc_count] = 2544562236bSHarry Wentland virtual_stream_encoder_create( 2554562236bSHarry Wentland ctx, ctx->dc_bios); 2564562236bSHarry Wentland if (pool->stream_enc[pool->stream_enc_count] == NULL) { 2574562236bSHarry Wentland DC_ERR("DC: failed to create stream_encoder!\n"); 2584562236bSHarry Wentland return false; 2594562236bSHarry Wentland } 2604562236bSHarry Wentland pool->stream_enc_count++; 2614562236bSHarry Wentland } 2624562236bSHarry Wentland 2634562236bSHarry Wentland dc->hwseq = create_funcs->create_hwseq(ctx); 2644562236bSHarry Wentland 2654562236bSHarry Wentland return true; 2664562236bSHarry Wentland } 2674562236bSHarry Wentland 2684562236bSHarry Wentland 26921e67d4dSHarry Wentland void resource_unreference_clock_source( 2704562236bSHarry Wentland struct resource_context *res_ctx, 271a2b8659dSTony Cheng const struct resource_pool *pool, 2724a629536SHarry Wentland struct clock_source *clock_source) 2734562236bSHarry Wentland { 2744562236bSHarry Wentland int i; 2754a629536SHarry Wentland 276a2b8659dSTony Cheng for (i = 0; i < pool->clk_src_count; i++) { 2774a629536SHarry Wentland if (pool->clock_sources[i] != clock_source) 2784562236bSHarry Wentland continue; 2794562236bSHarry Wentland 2804562236bSHarry Wentland res_ctx->clock_source_ref_count[i]--; 2814562236bSHarry Wentland 2824562236bSHarry Wentland break; 2834562236bSHarry Wentland } 2844562236bSHarry Wentland 28521e67d4dSHarry Wentland if (pool->dp_clock_source == clock_source) 2864562236bSHarry Wentland res_ctx->dp_clock_source_ref_count--; 2874562236bSHarry Wentland } 2884562236bSHarry Wentland 2894562236bSHarry Wentland void resource_reference_clock_source( 2904562236bSHarry Wentland struct resource_context *res_ctx, 291a2b8659dSTony Cheng const struct resource_pool *pool, 2924562236bSHarry Wentland struct clock_source *clock_source) 2934562236bSHarry Wentland { 2944562236bSHarry Wentland int i; 295a2b8659dSTony Cheng for (i = 0; i < pool->clk_src_count; i++) { 296a2b8659dSTony Cheng if (pool->clock_sources[i] != clock_source) 2974562236bSHarry Wentland continue; 2984562236bSHarry Wentland 2994562236bSHarry Wentland res_ctx->clock_source_ref_count[i]++; 3004562236bSHarry Wentland break; 3014562236bSHarry Wentland } 3024562236bSHarry Wentland 303a2b8659dSTony Cheng if (pool->dp_clock_source == clock_source) 3044562236bSHarry Wentland res_ctx->dp_clock_source_ref_count++; 3054562236bSHarry Wentland } 3064562236bSHarry Wentland 3074562236bSHarry Wentland bool resource_are_streams_timing_synchronizable( 3080971c40eSHarry Wentland struct dc_stream_state *stream1, 3090971c40eSHarry Wentland struct dc_stream_state *stream2) 3104562236bSHarry Wentland { 3114fa086b9SLeo (Sunpeng) Li if (stream1->timing.h_total != stream2->timing.h_total) 3124562236bSHarry Wentland return false; 3134562236bSHarry Wentland 3144fa086b9SLeo (Sunpeng) Li if (stream1->timing.v_total != stream2->timing.v_total) 3154562236bSHarry Wentland return false; 3164562236bSHarry Wentland 3174fa086b9SLeo (Sunpeng) Li if (stream1->timing.h_addressable 3184fa086b9SLeo (Sunpeng) Li != stream2->timing.h_addressable) 3194562236bSHarry Wentland return false; 3204562236bSHarry Wentland 3214fa086b9SLeo (Sunpeng) Li if (stream1->timing.v_addressable 3224fa086b9SLeo (Sunpeng) Li != stream2->timing.v_addressable) 3234562236bSHarry Wentland return false; 3244562236bSHarry Wentland 3254fa086b9SLeo (Sunpeng) Li if (stream1->timing.pix_clk_khz 3264fa086b9SLeo (Sunpeng) Li != stream2->timing.pix_clk_khz) 3274562236bSHarry Wentland return false; 3284562236bSHarry Wentland 3294562236bSHarry Wentland if (stream1->phy_pix_clk != stream2->phy_pix_clk 3307e2fe319SCharlene Liu && (!dc_is_dp_signal(stream1->signal) 3317e2fe319SCharlene Liu || !dc_is_dp_signal(stream2->signal))) 3324562236bSHarry Wentland return false; 3334562236bSHarry Wentland 3344562236bSHarry Wentland return true; 3354562236bSHarry Wentland } 3364562236bSHarry Wentland 3374562236bSHarry Wentland static bool is_sharable_clk_src( 3384562236bSHarry Wentland const struct pipe_ctx *pipe_with_clk_src, 3394562236bSHarry Wentland const struct pipe_ctx *pipe) 3404562236bSHarry Wentland { 3414562236bSHarry Wentland if (pipe_with_clk_src->clock_source == NULL) 3424562236bSHarry Wentland return false; 3434562236bSHarry Wentland 3444562236bSHarry Wentland if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL) 3454562236bSHarry Wentland return false; 3464562236bSHarry Wentland 3474562236bSHarry Wentland if (dc_is_dp_signal(pipe_with_clk_src->stream->signal)) 3484562236bSHarry Wentland return false; 3494562236bSHarry Wentland 3504562236bSHarry Wentland if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal) 3514562236bSHarry Wentland && dc_is_dvi_signal(pipe->stream->signal)) 3524562236bSHarry Wentland return false; 3534562236bSHarry Wentland 3544562236bSHarry Wentland if (dc_is_hdmi_signal(pipe->stream->signal) 3554562236bSHarry Wentland && dc_is_dvi_signal(pipe_with_clk_src->stream->signal)) 3564562236bSHarry Wentland return false; 3574562236bSHarry Wentland 3584562236bSHarry Wentland if (!resource_are_streams_timing_synchronizable( 3594562236bSHarry Wentland pipe_with_clk_src->stream, pipe->stream)) 3604562236bSHarry Wentland return false; 3614562236bSHarry Wentland 3624562236bSHarry Wentland return true; 3634562236bSHarry Wentland } 3644562236bSHarry Wentland 3654562236bSHarry Wentland struct clock_source *resource_find_used_clk_src_for_sharing( 3664562236bSHarry Wentland struct resource_context *res_ctx, 3674562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 3684562236bSHarry Wentland { 3694562236bSHarry Wentland int i; 3704562236bSHarry Wentland 3714562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 3724562236bSHarry Wentland if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx)) 3734562236bSHarry Wentland return res_ctx->pipe_ctx[i].clock_source; 3744562236bSHarry Wentland } 3754562236bSHarry Wentland 3764562236bSHarry Wentland return NULL; 3774562236bSHarry Wentland } 3784562236bSHarry Wentland 3794562236bSHarry Wentland static enum pixel_format convert_pixel_format_to_dalsurface( 3804562236bSHarry Wentland enum surface_pixel_format surface_pixel_format) 3814562236bSHarry Wentland { 3824562236bSHarry Wentland enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 3834562236bSHarry Wentland 3844562236bSHarry Wentland switch (surface_pixel_format) { 3854562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 3864562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_INDEX8; 3874562236bSHarry Wentland break; 3884562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 3894562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_RGB565; 3904562236bSHarry Wentland break; 3914562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 3924562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_RGB565; 3934562236bSHarry Wentland break; 3944562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 3954562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB8888; 3964562236bSHarry Wentland break; 3978693049aSTony Cheng case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 3984562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB8888; 3994562236bSHarry Wentland break; 4004562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 4014562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 4024562236bSHarry Wentland break; 4034562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 4044562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 4054562236bSHarry Wentland break; 4064562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 4074562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS; 4084562236bSHarry Wentland break; 4094562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 4104562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 4114562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_FP16; 4124562236bSHarry Wentland break; 4134562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 4144562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 41587449a90SAnthony Koo dal_pixel_format = PIXEL_FORMAT_420BPP8; 4164562236bSHarry Wentland break; 417ffbcd19aSVitaly Prosyak case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 418ffbcd19aSVitaly Prosyak case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 41987449a90SAnthony Koo dal_pixel_format = PIXEL_FORMAT_420BPP10; 420ffbcd19aSVitaly Prosyak break; 4214562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 4224562236bSHarry Wentland default: 4234562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 4244562236bSHarry Wentland break; 4254562236bSHarry Wentland } 4264562236bSHarry Wentland return dal_pixel_format; 4274562236bSHarry Wentland } 4284562236bSHarry Wentland 4294562236bSHarry Wentland static void rect_swap_helper(struct rect *rect) 4304562236bSHarry Wentland { 43199676f20SGustavo A. R. Silva swap(rect->height, rect->width); 43299676f20SGustavo A. R. Silva swap(rect->x, rect->y); 4334562236bSHarry Wentland } 4344562236bSHarry Wentland 435b2d0a103SDmytro Laktyushkin static void calculate_viewport(struct pipe_ctx *pipe_ctx) 4364562236bSHarry Wentland { 4373be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 4380971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 4396702a9acSHarry Wentland struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 4403be5262eSHarry Wentland struct rect surf_src = plane_state->src_rect; 4414562236bSHarry Wentland struct rect clip = { 0 }; 44287449a90SAnthony Koo int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 44387449a90SAnthony Koo || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 4441fbd2cfcSDmytro Laktyushkin bool pri_split = pipe_ctx->bottom_pipe && 4453be5262eSHarry Wentland pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; 4461fbd2cfcSDmytro Laktyushkin bool sec_split = pipe_ctx->top_pipe && 4473be5262eSHarry Wentland pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; 4484562236bSHarry Wentland 4497f5c22d1SVitaly Prosyak if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || 4507f5c22d1SVitaly Prosyak stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { 4517b779c99SVitaly Prosyak pri_split = false; 4527b779c99SVitaly Prosyak sec_split = false; 4537b779c99SVitaly Prosyak } 45486006a7fSDmytro Laktyushkin 4553be5262eSHarry Wentland if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 4563be5262eSHarry Wentland pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 45786006a7fSDmytro Laktyushkin rect_swap_helper(&surf_src); 45886006a7fSDmytro Laktyushkin 4594562236bSHarry Wentland /* The actual clip is an intersection between stream 4604562236bSHarry Wentland * source and surface clip 4614562236bSHarry Wentland */ 4623be5262eSHarry Wentland clip.x = stream->src.x > plane_state->clip_rect.x ? 4633be5262eSHarry Wentland stream->src.x : plane_state->clip_rect.x; 4644562236bSHarry Wentland 4651fbd2cfcSDmytro Laktyushkin clip.width = stream->src.x + stream->src.width < 4663be5262eSHarry Wentland plane_state->clip_rect.x + plane_state->clip_rect.width ? 4671fbd2cfcSDmytro Laktyushkin stream->src.x + stream->src.width - clip.x : 4683be5262eSHarry Wentland plane_state->clip_rect.x + plane_state->clip_rect.width - clip.x ; 4694562236bSHarry Wentland 4703be5262eSHarry Wentland clip.y = stream->src.y > plane_state->clip_rect.y ? 4713be5262eSHarry Wentland stream->src.y : plane_state->clip_rect.y; 4724562236bSHarry Wentland 4731fbd2cfcSDmytro Laktyushkin clip.height = stream->src.y + stream->src.height < 4743be5262eSHarry Wentland plane_state->clip_rect.y + plane_state->clip_rect.height ? 4751fbd2cfcSDmytro Laktyushkin stream->src.y + stream->src.height - clip.y : 4763be5262eSHarry Wentland plane_state->clip_rect.y + plane_state->clip_rect.height - clip.y ; 4774562236bSHarry Wentland 47886006a7fSDmytro Laktyushkin /* offset = surf_src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio 4794562236bSHarry Wentland * num_pixels = clip.num_pix * scl_ratio 4804562236bSHarry Wentland */ 4813be5262eSHarry Wentland data->viewport.x = surf_src.x + (clip.x - plane_state->dst_rect.x) * 4823be5262eSHarry Wentland surf_src.width / plane_state->dst_rect.width; 483b2d0a103SDmytro Laktyushkin data->viewport.width = clip.width * 4843be5262eSHarry Wentland surf_src.width / plane_state->dst_rect.width; 4854562236bSHarry Wentland 4863be5262eSHarry Wentland data->viewport.y = surf_src.y + (clip.y - plane_state->dst_rect.y) * 4873be5262eSHarry Wentland surf_src.height / plane_state->dst_rect.height; 488b2d0a103SDmytro Laktyushkin data->viewport.height = clip.height * 4893be5262eSHarry Wentland surf_src.height / plane_state->dst_rect.height; 4904562236bSHarry Wentland 491b2d0a103SDmytro Laktyushkin /* Round down, compensate in init */ 492b2d0a103SDmytro Laktyushkin data->viewport_c.x = data->viewport.x / vpc_div; 493b2d0a103SDmytro Laktyushkin data->viewport_c.y = data->viewport.y / vpc_div; 494b2d0a103SDmytro Laktyushkin data->inits.h_c = (data->viewport.x % vpc_div) != 0 ? 495b2d0a103SDmytro Laktyushkin dal_fixed31_32_half : dal_fixed31_32_zero; 496b2d0a103SDmytro Laktyushkin data->inits.v_c = (data->viewport.y % vpc_div) != 0 ? 497b2d0a103SDmytro Laktyushkin dal_fixed31_32_half : dal_fixed31_32_zero; 498b2d0a103SDmytro Laktyushkin /* Round up, assume original video size always even dimensions */ 499b2d0a103SDmytro Laktyushkin data->viewport_c.width = (data->viewport.width + vpc_div - 1) / vpc_div; 500b2d0a103SDmytro Laktyushkin data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; 501b2d0a103SDmytro Laktyushkin 502b2d0a103SDmytro Laktyushkin /* Handle hsplit */ 5030c31a821SYongqiang Sun if (sec_split) { 50416fb754aSDmytro Laktyushkin data->viewport.x += data->viewport.width / 2; 50516fb754aSDmytro Laktyushkin data->viewport_c.x += data->viewport_c.width / 2; 5069e6c74ceSDmytro Laktyushkin /* Ceil offset pipe */ 50716fb754aSDmytro Laktyushkin data->viewport.width = (data->viewport.width + 1) / 2; 50816fb754aSDmytro Laktyushkin data->viewport_c.width = (data->viewport_c.width + 1) / 2; 5090c31a821SYongqiang Sun } else if (pri_split) { 510b2d0a103SDmytro Laktyushkin data->viewport.width /= 2; 511b2d0a103SDmytro Laktyushkin data->viewport_c.width /= 2; 512b2d0a103SDmytro Laktyushkin } 5131fbd2cfcSDmytro Laktyushkin 5143be5262eSHarry Wentland if (plane_state->rotation == ROTATION_ANGLE_90 || 5153be5262eSHarry Wentland plane_state->rotation == ROTATION_ANGLE_270) { 5161fbd2cfcSDmytro Laktyushkin rect_swap_helper(&data->viewport_c); 5171fbd2cfcSDmytro Laktyushkin rect_swap_helper(&data->viewport); 5181fbd2cfcSDmytro Laktyushkin } 5199e6c74ceSDmytro Laktyushkin } 5204562236bSHarry Wentland 521b2d0a103SDmytro Laktyushkin static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip) 5224562236bSHarry Wentland { 5233be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 5240971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 5253be5262eSHarry Wentland struct rect surf_src = plane_state->src_rect; 5263be5262eSHarry Wentland struct rect surf_clip = plane_state->clip_rect; 527c802570eSDmytro Laktyushkin int recout_full_x, recout_full_y; 5280c31a821SYongqiang Sun bool pri_split = pipe_ctx->bottom_pipe && 5290c31a821SYongqiang Sun pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; 5300c31a821SYongqiang Sun bool sec_split = pipe_ctx->top_pipe && 5310c31a821SYongqiang Sun pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; 532b0131391SDmytro Laktyushkin bool top_bottom_split = stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; 5334562236bSHarry Wentland 5343be5262eSHarry Wentland if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 5353be5262eSHarry Wentland pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 53686006a7fSDmytro Laktyushkin rect_swap_helper(&surf_src); 53786006a7fSDmytro Laktyushkin 5386702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.x = stream->dst.x; 5394fa086b9SLeo (Sunpeng) Li if (stream->src.x < surf_clip.x) 5406702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.x += (surf_clip.x 5414fa086b9SLeo (Sunpeng) Li - stream->src.x) * stream->dst.width 5424fa086b9SLeo (Sunpeng) Li / stream->src.width; 5434562236bSHarry Wentland 5446702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.width = surf_clip.width * 5454fa086b9SLeo (Sunpeng) Li stream->dst.width / stream->src.width; 5466702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.recout.width + pipe_ctx->plane_res.scl_data.recout.x > 5474fa086b9SLeo (Sunpeng) Li stream->dst.x + stream->dst.width) 5486702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.width = 5494fa086b9SLeo (Sunpeng) Li stream->dst.x + stream->dst.width 5506702a9acSHarry Wentland - pipe_ctx->plane_res.scl_data.recout.x; 5514562236bSHarry Wentland 5526702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.y = stream->dst.y; 5534fa086b9SLeo (Sunpeng) Li if (stream->src.y < surf_clip.y) 5546702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.y += (surf_clip.y 5554fa086b9SLeo (Sunpeng) Li - stream->src.y) * stream->dst.height 5564fa086b9SLeo (Sunpeng) Li / stream->src.height; 5574562236bSHarry Wentland 5586702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.height = surf_clip.height * 5594fa086b9SLeo (Sunpeng) Li stream->dst.height / stream->src.height; 5606702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.recout.height + pipe_ctx->plane_res.scl_data.recout.y > 5614fa086b9SLeo (Sunpeng) Li stream->dst.y + stream->dst.height) 5626702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.height = 5634fa086b9SLeo (Sunpeng) Li stream->dst.y + stream->dst.height 5646702a9acSHarry Wentland - pipe_ctx->plane_res.scl_data.recout.y; 565b2d0a103SDmytro Laktyushkin 5667b779c99SVitaly Prosyak /* Handle h & vsplit */ 567b0131391SDmytro Laktyushkin if (sec_split && top_bottom_split) { 568b0131391SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.y += 569b0131391SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.height / 2; 5707b779c99SVitaly Prosyak /* Floor primary pipe, ceil 2ndary pipe */ 571b0131391SDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.height = 572b0131391SDmytro Laktyushkin (pipe_ctx->plane_res.scl_data.recout.height + 1) / 2; 573b0131391SDmytro Laktyushkin } else if (pri_split && top_bottom_split) 5746702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.height /= 2; 575b0131391SDmytro Laktyushkin else if (pri_split || sec_split) { 5760c31a821SYongqiang Sun /* HMirror XOR Secondary_pipe XOR Rotation_180 */ 5770c31a821SYongqiang Sun bool right_view = (sec_split != plane_state->horizontal_mirror) != 5780c31a821SYongqiang Sun (plane_state->rotation == ROTATION_ANGLE_180); 5790c31a821SYongqiang Sun 5800c31a821SYongqiang Sun if (plane_state->rotation == ROTATION_ANGLE_90 5810c31a821SYongqiang Sun || plane_state->rotation == ROTATION_ANGLE_270) 5820c31a821SYongqiang Sun /* Secondary_pipe XOR Rotation_270 */ 5830c31a821SYongqiang Sun right_view = (plane_state->rotation == ROTATION_ANGLE_270) != sec_split; 5840c31a821SYongqiang Sun 5850c31a821SYongqiang Sun if (right_view) { 5860c31a821SYongqiang Sun pipe_ctx->plane_res.scl_data.recout.x += 5870c31a821SYongqiang Sun pipe_ctx->plane_res.scl_data.recout.width / 2; 5880c31a821SYongqiang Sun /* Ceil offset pipe */ 5890c31a821SYongqiang Sun pipe_ctx->plane_res.scl_data.recout.width = 5900c31a821SYongqiang Sun (pipe_ctx->plane_res.scl_data.recout.width + 1) / 2; 5910c31a821SYongqiang Sun } else { 5926702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.width /= 2; 5934562236bSHarry Wentland } 5940c31a821SYongqiang Sun } 59586006a7fSDmytro Laktyushkin /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream surf_src offset) 59686006a7fSDmytro Laktyushkin * * 1/ stream scaling ratio) - (surf surf_src offset * 1/ full scl 597c802570eSDmytro Laktyushkin * ratio) 598c802570eSDmytro Laktyushkin */ 5993be5262eSHarry Wentland recout_full_x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x) 6004fa086b9SLeo (Sunpeng) Li * stream->dst.width / stream->src.width - 6013be5262eSHarry Wentland surf_src.x * plane_state->dst_rect.width / surf_src.width 6024fa086b9SLeo (Sunpeng) Li * stream->dst.width / stream->src.width; 6033be5262eSHarry Wentland recout_full_y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y) 6044fa086b9SLeo (Sunpeng) Li * stream->dst.height / stream->src.height - 6053be5262eSHarry Wentland surf_src.y * plane_state->dst_rect.height / surf_src.height 6064fa086b9SLeo (Sunpeng) Li * stream->dst.height / stream->src.height; 607c802570eSDmytro Laktyushkin 6086702a9acSHarry Wentland recout_skip->width = pipe_ctx->plane_res.scl_data.recout.x - recout_full_x; 6096702a9acSHarry Wentland recout_skip->height = pipe_ctx->plane_res.scl_data.recout.y - recout_full_y; 610b2d0a103SDmytro Laktyushkin } 611b2d0a103SDmytro Laktyushkin 612b2d0a103SDmytro Laktyushkin static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) 6134562236bSHarry Wentland { 6143be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 6150971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 6163be5262eSHarry Wentland struct rect surf_src = plane_state->src_rect; 6174fa086b9SLeo (Sunpeng) Li const int in_w = stream->src.width; 6184fa086b9SLeo (Sunpeng) Li const int in_h = stream->src.height; 6194fa086b9SLeo (Sunpeng) Li const int out_w = stream->dst.width; 6204fa086b9SLeo (Sunpeng) Li const int out_h = stream->dst.height; 6214562236bSHarry Wentland 6223be5262eSHarry Wentland if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 6233be5262eSHarry Wentland pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 62486006a7fSDmytro Laktyushkin rect_swap_helper(&surf_src); 62586006a7fSDmytro Laktyushkin 6266702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz = dal_fixed31_32_from_fraction( 62786006a7fSDmytro Laktyushkin surf_src.width, 6283be5262eSHarry Wentland plane_state->dst_rect.width); 6296702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert = dal_fixed31_32_from_fraction( 63086006a7fSDmytro Laktyushkin surf_src.height, 6313be5262eSHarry Wentland plane_state->dst_rect.height); 6324562236bSHarry Wentland 6334fa086b9SLeo (Sunpeng) Li if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) 6346702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value *= 2; 6354fa086b9SLeo (Sunpeng) Li else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) 6366702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value *= 2; 6374562236bSHarry Wentland 6386702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value = div64_s64( 6396702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value * in_h, out_h); 6406702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value = div64_s64( 6416702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value * in_w, out_w); 6424562236bSHarry Wentland 6436702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz_c = pipe_ctx->plane_res.scl_data.ratios.horz; 6446702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert_c = pipe_ctx->plane_res.scl_data.ratios.vert; 6454562236bSHarry Wentland 6466702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP8 6476702a9acSHarry Wentland || pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP10) { 6486702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz_c.value /= 2; 6496702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert_c.value /= 2; 6504562236bSHarry Wentland } 6514562236bSHarry Wentland } 6524562236bSHarry Wentland 653b2d0a103SDmytro Laktyushkin static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *recout_skip) 6544562236bSHarry Wentland { 6556702a9acSHarry Wentland struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 6563be5262eSHarry Wentland struct rect src = pipe_ctx->plane_state->src_rect; 65787449a90SAnthony Koo int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 65887449a90SAnthony Koo || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 659b0131391SDmytro Laktyushkin bool flip_vert_scan_dir = false, flip_horz_scan_dir = false; 660b2d0a103SDmytro Laktyushkin 661b0131391SDmytro Laktyushkin /* 662b0131391SDmytro Laktyushkin * Need to calculate the scan direction for viewport to make adjustments 663b0131391SDmytro Laktyushkin */ 664b0131391SDmytro Laktyushkin if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_180) { 665b0131391SDmytro Laktyushkin flip_vert_scan_dir = true; 666b0131391SDmytro Laktyushkin flip_horz_scan_dir = true; 667b0131391SDmytro Laktyushkin } else if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90) 668b0131391SDmytro Laktyushkin flip_vert_scan_dir = true; 669b0131391SDmytro Laktyushkin else if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 670b0131391SDmytro Laktyushkin flip_horz_scan_dir = true; 671b0131391SDmytro Laktyushkin if (pipe_ctx->plane_state->horizontal_mirror) 672b0131391SDmytro Laktyushkin flip_horz_scan_dir = !flip_horz_scan_dir; 673b0131391SDmytro Laktyushkin 6743be5262eSHarry Wentland if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 6753be5262eSHarry Wentland pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) { 67686006a7fSDmytro Laktyushkin rect_swap_helper(&src); 6771fbd2cfcSDmytro Laktyushkin rect_swap_helper(&data->viewport_c); 6781fbd2cfcSDmytro Laktyushkin rect_swap_helper(&data->viewport); 6791fbd2cfcSDmytro Laktyushkin } 6801fbd2cfcSDmytro Laktyushkin 681b2d0a103SDmytro Laktyushkin /* 682b2d0a103SDmytro Laktyushkin * Init calculated according to formula: 683b2d0a103SDmytro Laktyushkin * init = (scaling_ratio + number_of_taps + 1) / 2 684b2d0a103SDmytro Laktyushkin * init_bot = init + scaling_ratio 685b2d0a103SDmytro Laktyushkin * init_c = init + truncated_vp_c_offset(from calculate viewport) 686b2d0a103SDmytro Laktyushkin */ 687b2d0a103SDmytro Laktyushkin data->inits.h = dal_fixed31_32_div_int( 688b2d0a103SDmytro Laktyushkin dal_fixed31_32_add_int(data->ratios.horz, data->taps.h_taps + 1), 2); 689b2d0a103SDmytro Laktyushkin 690b2d0a103SDmytro Laktyushkin data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_div_int( 691b2d0a103SDmytro Laktyushkin dal_fixed31_32_add_int(data->ratios.horz_c, data->taps.h_taps_c + 1), 2)); 692b2d0a103SDmytro Laktyushkin 693b2d0a103SDmytro Laktyushkin data->inits.v = dal_fixed31_32_div_int( 694b2d0a103SDmytro Laktyushkin dal_fixed31_32_add_int(data->ratios.vert, data->taps.v_taps + 1), 2); 695b2d0a103SDmytro Laktyushkin 696b2d0a103SDmytro Laktyushkin data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_div_int( 697b2d0a103SDmytro Laktyushkin dal_fixed31_32_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2)); 698b2d0a103SDmytro Laktyushkin 699b2d0a103SDmytro Laktyushkin 700b2d0a103SDmytro Laktyushkin /* Adjust for viewport end clip-off */ 7014ee778dcSDmytro Laktyushkin if ((data->viewport.x + data->viewport.width) < (src.x + src.width) && !flip_horz_scan_dir) { 702b2d0a103SDmytro Laktyushkin int vp_clip = src.x + src.width - data->viewport.width - data->viewport.x; 7031fbd2cfcSDmytro Laktyushkin int int_part = dal_fixed31_32_floor( 7041fbd2cfcSDmytro Laktyushkin dal_fixed31_32_sub(data->inits.h, data->ratios.horz)); 705b2d0a103SDmytro Laktyushkin 7061fbd2cfcSDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 707b2d0a103SDmytro Laktyushkin data->viewport.width += int_part < vp_clip ? int_part : vp_clip; 708b2d0a103SDmytro Laktyushkin } 7094ee778dcSDmytro Laktyushkin if ((data->viewport.y + data->viewport.height) < (src.y + src.height) && !flip_vert_scan_dir) { 710b2d0a103SDmytro Laktyushkin int vp_clip = src.y + src.height - data->viewport.height - data->viewport.y; 7111fbd2cfcSDmytro Laktyushkin int int_part = dal_fixed31_32_floor( 7121fbd2cfcSDmytro Laktyushkin dal_fixed31_32_sub(data->inits.v, data->ratios.vert)); 713b2d0a103SDmytro Laktyushkin 7141fbd2cfcSDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 715b2d0a103SDmytro Laktyushkin data->viewport.height += int_part < vp_clip ? int_part : vp_clip; 716b2d0a103SDmytro Laktyushkin } 7174ee778dcSDmytro Laktyushkin if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div && !flip_horz_scan_dir) { 718b2d0a103SDmytro Laktyushkin int vp_clip = (src.x + src.width) / vpc_div - 719b2d0a103SDmytro Laktyushkin data->viewport_c.width - data->viewport_c.x; 7201fbd2cfcSDmytro Laktyushkin int int_part = dal_fixed31_32_floor( 7211fbd2cfcSDmytro Laktyushkin dal_fixed31_32_sub(data->inits.h_c, data->ratios.horz_c)); 722b2d0a103SDmytro Laktyushkin 7231fbd2cfcSDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 724b2d0a103SDmytro Laktyushkin data->viewport_c.width += int_part < vp_clip ? int_part : vp_clip; 725b2d0a103SDmytro Laktyushkin } 7264ee778dcSDmytro Laktyushkin if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div && !flip_vert_scan_dir) { 727b2d0a103SDmytro Laktyushkin int vp_clip = (src.y + src.height) / vpc_div - 728b2d0a103SDmytro Laktyushkin data->viewport_c.height - data->viewport_c.y; 7291fbd2cfcSDmytro Laktyushkin int int_part = dal_fixed31_32_floor( 7301fbd2cfcSDmytro Laktyushkin dal_fixed31_32_sub(data->inits.v_c, data->ratios.vert_c)); 731b2d0a103SDmytro Laktyushkin 7321fbd2cfcSDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 733b2d0a103SDmytro Laktyushkin data->viewport_c.height += int_part < vp_clip ? int_part : vp_clip; 734b2d0a103SDmytro Laktyushkin } 735b2d0a103SDmytro Laktyushkin 736b2d0a103SDmytro Laktyushkin /* Adjust for non-0 viewport offset */ 737737ae4eaSDmytro Laktyushkin if (data->viewport.x && !flip_horz_scan_dir) { 738b2d0a103SDmytro Laktyushkin int int_part; 739b2d0a103SDmytro Laktyushkin 740b2d0a103SDmytro Laktyushkin data->inits.h = dal_fixed31_32_add(data->inits.h, dal_fixed31_32_mul_int( 741b2d0a103SDmytro Laktyushkin data->ratios.horz, recout_skip->width)); 742b2d0a103SDmytro Laktyushkin int_part = dal_fixed31_32_floor(data->inits.h) - data->viewport.x; 743b2d0a103SDmytro Laktyushkin if (int_part < data->taps.h_taps) { 744b2d0a103SDmytro Laktyushkin int int_adj = data->viewport.x >= (data->taps.h_taps - int_part) ? 745b2d0a103SDmytro Laktyushkin (data->taps.h_taps - int_part) : data->viewport.x; 746b2d0a103SDmytro Laktyushkin data->viewport.x -= int_adj; 747b2d0a103SDmytro Laktyushkin data->viewport.width += int_adj; 748b2d0a103SDmytro Laktyushkin int_part += int_adj; 749b2d0a103SDmytro Laktyushkin } else if (int_part > data->taps.h_taps) { 750b2d0a103SDmytro Laktyushkin data->viewport.x += int_part - data->taps.h_taps; 751b2d0a103SDmytro Laktyushkin data->viewport.width -= int_part - data->taps.h_taps; 752b2d0a103SDmytro Laktyushkin int_part = data->taps.h_taps; 753b2d0a103SDmytro Laktyushkin } 754b2d0a103SDmytro Laktyushkin data->inits.h.value &= 0xffffffff; 755b2d0a103SDmytro Laktyushkin data->inits.h = dal_fixed31_32_add_int(data->inits.h, int_part); 756b2d0a103SDmytro Laktyushkin } 757b2d0a103SDmytro Laktyushkin 758737ae4eaSDmytro Laktyushkin if (data->viewport_c.x && !flip_horz_scan_dir) { 759b2d0a103SDmytro Laktyushkin int int_part; 760b2d0a103SDmytro Laktyushkin 761b2d0a103SDmytro Laktyushkin data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_mul_int( 762b2d0a103SDmytro Laktyushkin data->ratios.horz_c, recout_skip->width)); 763b2d0a103SDmytro Laktyushkin int_part = dal_fixed31_32_floor(data->inits.h_c) - data->viewport_c.x; 764b2d0a103SDmytro Laktyushkin if (int_part < data->taps.h_taps_c) { 765b2d0a103SDmytro Laktyushkin int int_adj = data->viewport_c.x >= (data->taps.h_taps_c - int_part) ? 766b2d0a103SDmytro Laktyushkin (data->taps.h_taps_c - int_part) : data->viewport_c.x; 767b2d0a103SDmytro Laktyushkin data->viewport_c.x -= int_adj; 768b2d0a103SDmytro Laktyushkin data->viewport_c.width += int_adj; 769b2d0a103SDmytro Laktyushkin int_part += int_adj; 770b2d0a103SDmytro Laktyushkin } else if (int_part > data->taps.h_taps_c) { 771b2d0a103SDmytro Laktyushkin data->viewport_c.x += int_part - data->taps.h_taps_c; 772b2d0a103SDmytro Laktyushkin data->viewport_c.width -= int_part - data->taps.h_taps_c; 773b2d0a103SDmytro Laktyushkin int_part = data->taps.h_taps_c; 774b2d0a103SDmytro Laktyushkin } 775b2d0a103SDmytro Laktyushkin data->inits.h_c.value &= 0xffffffff; 776b2d0a103SDmytro Laktyushkin data->inits.h_c = dal_fixed31_32_add_int(data->inits.h_c, int_part); 777b2d0a103SDmytro Laktyushkin } 778b2d0a103SDmytro Laktyushkin 779737ae4eaSDmytro Laktyushkin if (data->viewport.y && !flip_vert_scan_dir) { 780b2d0a103SDmytro Laktyushkin int int_part; 781b2d0a103SDmytro Laktyushkin 782b2d0a103SDmytro Laktyushkin data->inits.v = dal_fixed31_32_add(data->inits.v, dal_fixed31_32_mul_int( 783b2d0a103SDmytro Laktyushkin data->ratios.vert, recout_skip->height)); 784b2d0a103SDmytro Laktyushkin int_part = dal_fixed31_32_floor(data->inits.v) - data->viewport.y; 785b2d0a103SDmytro Laktyushkin if (int_part < data->taps.v_taps) { 786b2d0a103SDmytro Laktyushkin int int_adj = data->viewport.y >= (data->taps.v_taps - int_part) ? 787b2d0a103SDmytro Laktyushkin (data->taps.v_taps - int_part) : data->viewport.y; 788b2d0a103SDmytro Laktyushkin data->viewport.y -= int_adj; 789b2d0a103SDmytro Laktyushkin data->viewport.height += int_adj; 790b2d0a103SDmytro Laktyushkin int_part += int_adj; 791b2d0a103SDmytro Laktyushkin } else if (int_part > data->taps.v_taps) { 792b2d0a103SDmytro Laktyushkin data->viewport.y += int_part - data->taps.v_taps; 793b2d0a103SDmytro Laktyushkin data->viewport.height -= int_part - data->taps.v_taps; 794b2d0a103SDmytro Laktyushkin int_part = data->taps.v_taps; 795b2d0a103SDmytro Laktyushkin } 796b2d0a103SDmytro Laktyushkin data->inits.v.value &= 0xffffffff; 797b2d0a103SDmytro Laktyushkin data->inits.v = dal_fixed31_32_add_int(data->inits.v, int_part); 798b2d0a103SDmytro Laktyushkin } 799b2d0a103SDmytro Laktyushkin 800737ae4eaSDmytro Laktyushkin if (data->viewport_c.y && !flip_vert_scan_dir) { 801b2d0a103SDmytro Laktyushkin int int_part; 802b2d0a103SDmytro Laktyushkin 803b2d0a103SDmytro Laktyushkin data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_mul_int( 804b2d0a103SDmytro Laktyushkin data->ratios.vert_c, recout_skip->height)); 805b2d0a103SDmytro Laktyushkin int_part = dal_fixed31_32_floor(data->inits.v_c) - data->viewport_c.y; 806b2d0a103SDmytro Laktyushkin if (int_part < data->taps.v_taps_c) { 807b2d0a103SDmytro Laktyushkin int int_adj = data->viewport_c.y >= (data->taps.v_taps_c - int_part) ? 808b2d0a103SDmytro Laktyushkin (data->taps.v_taps_c - int_part) : data->viewport_c.y; 809b2d0a103SDmytro Laktyushkin data->viewport_c.y -= int_adj; 810b2d0a103SDmytro Laktyushkin data->viewport_c.height += int_adj; 811b2d0a103SDmytro Laktyushkin int_part += int_adj; 812b2d0a103SDmytro Laktyushkin } else if (int_part > data->taps.v_taps_c) { 813b2d0a103SDmytro Laktyushkin data->viewport_c.y += int_part - data->taps.v_taps_c; 814b2d0a103SDmytro Laktyushkin data->viewport_c.height -= int_part - data->taps.v_taps_c; 815b2d0a103SDmytro Laktyushkin int_part = data->taps.v_taps_c; 816b2d0a103SDmytro Laktyushkin } 817b2d0a103SDmytro Laktyushkin data->inits.v_c.value &= 0xffffffff; 818b2d0a103SDmytro Laktyushkin data->inits.v_c = dal_fixed31_32_add_int(data->inits.v_c, int_part); 819b2d0a103SDmytro Laktyushkin } 820b2d0a103SDmytro Laktyushkin 821b2d0a103SDmytro Laktyushkin /* Interlaced inits based on final vert inits */ 822b2d0a103SDmytro Laktyushkin data->inits.v_bot = dal_fixed31_32_add(data->inits.v, data->ratios.vert); 823b2d0a103SDmytro Laktyushkin data->inits.v_c_bot = dal_fixed31_32_add(data->inits.v_c, data->ratios.vert_c); 8241fbd2cfcSDmytro Laktyushkin 8253be5262eSHarry Wentland if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 8263be5262eSHarry Wentland pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) { 8271fbd2cfcSDmytro Laktyushkin rect_swap_helper(&data->viewport_c); 8281fbd2cfcSDmytro Laktyushkin rect_swap_helper(&data->viewport); 8291fbd2cfcSDmytro Laktyushkin } 830b2d0a103SDmytro Laktyushkin } 831b2d0a103SDmytro Laktyushkin 832b2d0a103SDmytro Laktyushkin bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) 833b2d0a103SDmytro Laktyushkin { 8343be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 8354fa086b9SLeo (Sunpeng) Li struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 836b2d0a103SDmytro Laktyushkin struct view recout_skip = { 0 }; 837b2d0a103SDmytro Laktyushkin bool res = false; 8381296423bSBhawanpreet Lakha struct dc_context *ctx = pipe_ctx->stream->ctx; 8394562236bSHarry Wentland /* Important: scaling ratio calculation requires pixel format, 8404562236bSHarry Wentland * lb depth calculation requires recout and taps require scaling ratios. 841b2d0a103SDmytro Laktyushkin * Inits require viewport, taps, ratios and recout of split pipe 8424562236bSHarry Wentland */ 8436702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface( 8443be5262eSHarry Wentland pipe_ctx->plane_state->format); 8454562236bSHarry Wentland 846b2d0a103SDmytro Laktyushkin calculate_scaling_ratios(pipe_ctx); 847b2d0a103SDmytro Laktyushkin 848b2d0a103SDmytro Laktyushkin calculate_viewport(pipe_ctx); 8494562236bSHarry Wentland 8506702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.viewport.height < 16 || pipe_ctx->plane_res.scl_data.viewport.width < 16) 8514562236bSHarry Wentland return false; 8524562236bSHarry Wentland 853b2d0a103SDmytro Laktyushkin calculate_recout(pipe_ctx, &recout_skip); 8544562236bSHarry Wentland 8554562236bSHarry Wentland /** 8564562236bSHarry Wentland * Setting line buffer pixel depth to 24bpp yields banding 8574562236bSHarry Wentland * on certain displays, such as the Sharp 4k 8584562236bSHarry Wentland */ 8596702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; 8604562236bSHarry Wentland 861199e458aSDmytro Laktyushkin pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left; 86258bb0e63SAndrew Jiang pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top; 863199e458aSDmytro Laktyushkin 86458bb0e63SAndrew Jiang pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right; 86558bb0e63SAndrew Jiang pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + timing->v_border_top + timing->v_border_bottom; 8664562236bSHarry Wentland 8671b6c8067SBhawanpreet Lakha 8684562236bSHarry Wentland /* Taps calculations */ 869d94585a0SYue Hin Lau if (pipe_ctx->plane_res.xfm != NULL) 87086a66c4eSHarry Wentland res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 87186a66c4eSHarry Wentland pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 8724562236bSHarry Wentland 873d94585a0SYue Hin Lau if (pipe_ctx->plane_res.dpp != NULL) 874d94585a0SYue Hin Lau res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 875d94585a0SYue Hin Lau pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 8764562236bSHarry Wentland if (!res) { 8774562236bSHarry Wentland /* Try 24 bpp linebuffer */ 8786702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; 8794562236bSHarry Wentland 8801b6c8067SBhawanpreet Lakha if (pipe_ctx->plane_res.xfm != NULL) 88186a66c4eSHarry Wentland res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 8821b6c8067SBhawanpreet Lakha pipe_ctx->plane_res.xfm, 8831b6c8067SBhawanpreet Lakha &pipe_ctx->plane_res.scl_data, 8841b6c8067SBhawanpreet Lakha &plane_state->scaling_quality); 885d94585a0SYue Hin Lau 8861b6c8067SBhawanpreet Lakha if (pipe_ctx->plane_res.dpp != NULL) 887d94585a0SYue Hin Lau res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 8881b6c8067SBhawanpreet Lakha pipe_ctx->plane_res.dpp, 8891b6c8067SBhawanpreet Lakha &pipe_ctx->plane_res.scl_data, 8901b6c8067SBhawanpreet Lakha &plane_state->scaling_quality); 8914562236bSHarry Wentland } 8924562236bSHarry Wentland 893b2d0a103SDmytro Laktyushkin if (res) 8941fbd2cfcSDmytro Laktyushkin /* May need to re-check lb size after this in some obscure scenario */ 895b2d0a103SDmytro Laktyushkin calculate_inits_and_adj_vp(pipe_ctx, &recout_skip); 896b2d0a103SDmytro Laktyushkin 8971296423bSBhawanpreet Lakha DC_LOG_SCALER( 8984562236bSHarry Wentland "%s: Viewport:\nheight:%d width:%d x:%d " 8994562236bSHarry Wentland "y:%d\n dst_rect:\nheight:%d width:%d x:%d " 9004562236bSHarry Wentland "y:%d\n", 9014562236bSHarry Wentland __func__, 9026702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.height, 9036702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.width, 9046702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.x, 9056702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.y, 9063be5262eSHarry Wentland plane_state->dst_rect.height, 9073be5262eSHarry Wentland plane_state->dst_rect.width, 9083be5262eSHarry Wentland plane_state->dst_rect.x, 9093be5262eSHarry Wentland plane_state->dst_rect.y); 9104562236bSHarry Wentland 9114562236bSHarry Wentland return res; 9124562236bSHarry Wentland } 9134562236bSHarry Wentland 9144562236bSHarry Wentland 9154562236bSHarry Wentland enum dc_status resource_build_scaling_params_for_context( 916fb3466a4SBhawanpreet Lakha const struct dc *dc, 917608ac7bbSJerry Zuo struct dc_state *context) 9184562236bSHarry Wentland { 9194562236bSHarry Wentland int i; 9204562236bSHarry Wentland 9214562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 9223be5262eSHarry Wentland if (context->res_ctx.pipe_ctx[i].plane_state != NULL && 9234562236bSHarry Wentland context->res_ctx.pipe_ctx[i].stream != NULL) 924b2d0a103SDmytro Laktyushkin if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i])) 925f84a8161STony Cheng return DC_FAIL_SCALING; 9264562236bSHarry Wentland } 9274562236bSHarry Wentland 9284562236bSHarry Wentland return DC_OK; 9294562236bSHarry Wentland } 9304562236bSHarry Wentland 931a2b8659dSTony Cheng struct pipe_ctx *find_idle_secondary_pipe( 932a2b8659dSTony Cheng struct resource_context *res_ctx, 933a2b8659dSTony Cheng const struct resource_pool *pool) 9344562236bSHarry Wentland { 9354562236bSHarry Wentland int i; 9364562236bSHarry Wentland struct pipe_ctx *secondary_pipe = NULL; 9374562236bSHarry Wentland 9384562236bSHarry Wentland /* 9394562236bSHarry Wentland * search backwards for the second pipe to keep pipe 9404562236bSHarry Wentland * assignment more consistent 9414562236bSHarry Wentland */ 9424562236bSHarry Wentland 943a2b8659dSTony Cheng for (i = pool->pipe_count - 1; i >= 0; i--) { 9444562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == NULL) { 9454562236bSHarry Wentland secondary_pipe = &res_ctx->pipe_ctx[i]; 9464562236bSHarry Wentland secondary_pipe->pipe_idx = i; 9474562236bSHarry Wentland break; 9484562236bSHarry Wentland } 9494562236bSHarry Wentland } 9504562236bSHarry Wentland 9514562236bSHarry Wentland 9524562236bSHarry Wentland return secondary_pipe; 9534562236bSHarry Wentland } 9544562236bSHarry Wentland 9554562236bSHarry Wentland struct pipe_ctx *resource_get_head_pipe_for_stream( 9564562236bSHarry Wentland struct resource_context *res_ctx, 9570971c40eSHarry Wentland struct dc_stream_state *stream) 9584562236bSHarry Wentland { 9594562236bSHarry Wentland int i; 960a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 9614562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == stream && 9621dc90497SAndrey Grodzovsky !res_ctx->pipe_ctx[i].top_pipe) { 9634562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 9644562236bSHarry Wentland break; 9654562236bSHarry Wentland } 9664562236bSHarry Wentland } 9674562236bSHarry Wentland return NULL; 9684562236bSHarry Wentland } 9694562236bSHarry Wentland 97019f89e23SAndrey Grodzovsky static struct pipe_ctx *resource_get_tail_pipe_for_stream( 97119f89e23SAndrey Grodzovsky struct resource_context *res_ctx, 97219f89e23SAndrey Grodzovsky struct dc_stream_state *stream) 97319f89e23SAndrey Grodzovsky { 97419f89e23SAndrey Grodzovsky struct pipe_ctx *head_pipe, *tail_pipe; 97519f89e23SAndrey Grodzovsky head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream); 97619f89e23SAndrey Grodzovsky 97719f89e23SAndrey Grodzovsky if (!head_pipe) 97819f89e23SAndrey Grodzovsky return NULL; 97919f89e23SAndrey Grodzovsky 98019f89e23SAndrey Grodzovsky tail_pipe = head_pipe->bottom_pipe; 98119f89e23SAndrey Grodzovsky 98219f89e23SAndrey Grodzovsky while (tail_pipe) { 98319f89e23SAndrey Grodzovsky head_pipe = tail_pipe; 98419f89e23SAndrey Grodzovsky tail_pipe = tail_pipe->bottom_pipe; 98519f89e23SAndrey Grodzovsky } 98619f89e23SAndrey Grodzovsky 98719f89e23SAndrey Grodzovsky return head_pipe; 98819f89e23SAndrey Grodzovsky } 98919f89e23SAndrey Grodzovsky 9904562236bSHarry Wentland /* 991ab2541b6SAric Cyr * A free_pipe for a stream is defined here as a pipe 992ab2541b6SAric Cyr * that has no surface attached yet 9934562236bSHarry Wentland */ 994ab2541b6SAric Cyr static struct pipe_ctx *acquire_free_pipe_for_stream( 995608ac7bbSJerry Zuo struct dc_state *context, 996a2b8659dSTony Cheng const struct resource_pool *pool, 9970971c40eSHarry Wentland struct dc_stream_state *stream) 9984562236bSHarry Wentland { 9994562236bSHarry Wentland int i; 1000745cc746SDmytro Laktyushkin struct resource_context *res_ctx = &context->res_ctx; 10014562236bSHarry Wentland 10024562236bSHarry Wentland struct pipe_ctx *head_pipe = NULL; 10034562236bSHarry Wentland 10044562236bSHarry Wentland /* Find head pipe, which has the back end set up*/ 10054562236bSHarry Wentland 10064562236bSHarry Wentland head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream); 10074562236bSHarry Wentland 1008e41ab030SHarry Wentland if (!head_pipe) { 10094562236bSHarry Wentland ASSERT(0); 1010e41ab030SHarry Wentland return NULL; 1011e41ab030SHarry Wentland } 10124562236bSHarry Wentland 10133be5262eSHarry Wentland if (!head_pipe->plane_state) 10144562236bSHarry Wentland return head_pipe; 10154562236bSHarry Wentland 10164562236bSHarry Wentland /* Re-use pipe already acquired for this stream if available*/ 1017a2b8659dSTony Cheng for (i = pool->pipe_count - 1; i >= 0; i--) { 10184562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == stream && 10193be5262eSHarry Wentland !res_ctx->pipe_ctx[i].plane_state) { 10204562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 10214562236bSHarry Wentland } 10224562236bSHarry Wentland } 10234562236bSHarry Wentland 10244562236bSHarry Wentland /* 10254562236bSHarry Wentland * At this point we have no re-useable pipe for this stream and we need 10264562236bSHarry Wentland * to acquire an idle one to satisfy the request 10274562236bSHarry Wentland */ 10284562236bSHarry Wentland 1029a2b8659dSTony Cheng if (!pool->funcs->acquire_idle_pipe_for_layer) 10304562236bSHarry Wentland return NULL; 10314562236bSHarry Wentland 1032a2b8659dSTony Cheng return pool->funcs->acquire_idle_pipe_for_layer(context, pool, stream); 10334562236bSHarry Wentland 10344562236bSHarry Wentland } 10354562236bSHarry Wentland 10360f9a536fSDmytro Laktyushkin #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 10370f9a536fSDmytro Laktyushkin static int acquire_first_split_pipe( 10380f9a536fSDmytro Laktyushkin struct resource_context *res_ctx, 10390f9a536fSDmytro Laktyushkin const struct resource_pool *pool, 10400971c40eSHarry Wentland struct dc_stream_state *stream) 10410f9a536fSDmytro Laktyushkin { 10420f9a536fSDmytro Laktyushkin int i; 10430f9a536fSDmytro Laktyushkin 10440f9a536fSDmytro Laktyushkin for (i = 0; i < pool->pipe_count; i++) { 10450f9a536fSDmytro Laktyushkin struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 10460f9a536fSDmytro Laktyushkin 10470f9a536fSDmytro Laktyushkin if (pipe_ctx->top_pipe && 10483be5262eSHarry Wentland pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state) { 10490f9a536fSDmytro Laktyushkin pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; 10500f9a536fSDmytro Laktyushkin if (pipe_ctx->bottom_pipe) 10510f9a536fSDmytro Laktyushkin pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; 10520f9a536fSDmytro Laktyushkin 10530f9a536fSDmytro Laktyushkin memset(pipe_ctx, 0, sizeof(*pipe_ctx)); 10546b670fa9SHarry Wentland pipe_ctx->stream_res.tg = pool->timing_generators[i]; 10558feabd03SYue Hin Lau pipe_ctx->plane_res.hubp = pool->hubps[i]; 105686a66c4eSHarry Wentland pipe_ctx->plane_res.ipp = pool->ipps[i]; 1057d94585a0SYue Hin Lau pipe_ctx->plane_res.dpp = pool->dpps[i]; 1058a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp = pool->opps[i]; 1059e07f541fSYongqiang Sun pipe_ctx->plane_res.mpcc_inst = pool->dpps[i]->inst; 10600f9a536fSDmytro Laktyushkin pipe_ctx->pipe_idx = i; 10610f9a536fSDmytro Laktyushkin 10620f9a536fSDmytro Laktyushkin pipe_ctx->stream = stream; 10630f9a536fSDmytro Laktyushkin return i; 10640f9a536fSDmytro Laktyushkin } 10650f9a536fSDmytro Laktyushkin } 10660f9a536fSDmytro Laktyushkin return -1; 10670f9a536fSDmytro Laktyushkin } 10680f9a536fSDmytro Laktyushkin #endif 10690f9a536fSDmytro Laktyushkin 107019f89e23SAndrey Grodzovsky bool dc_add_plane_to_context( 107119f89e23SAndrey Grodzovsky const struct dc *dc, 10720971c40eSHarry Wentland struct dc_stream_state *stream, 107319f89e23SAndrey Grodzovsky struct dc_plane_state *plane_state, 1074608ac7bbSJerry Zuo struct dc_state *context) 10754562236bSHarry Wentland { 10764562236bSHarry Wentland int i; 107719f89e23SAndrey Grodzovsky struct resource_pool *pool = dc->res_pool; 107819f89e23SAndrey Grodzovsky struct pipe_ctx *head_pipe, *tail_pipe, *free_pipe; 1079ab2541b6SAric Cyr struct dc_stream_status *stream_status = NULL; 10804562236bSHarry Wentland 1081ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) 10824fa086b9SLeo (Sunpeng) Li if (context->streams[i] == stream) { 1083ab2541b6SAric Cyr stream_status = &context->stream_status[i]; 10844562236bSHarry Wentland break; 10854562236bSHarry Wentland } 1086ab2541b6SAric Cyr if (stream_status == NULL) { 108719f89e23SAndrey Grodzovsky dm_error("Existing stream not found; failed to attach surface!\n"); 108819f89e23SAndrey Grodzovsky return false; 108919f89e23SAndrey Grodzovsky } 109019f89e23SAndrey Grodzovsky 109119f89e23SAndrey Grodzovsky 109219f89e23SAndrey Grodzovsky if (stream_status->plane_count == MAX_SURFACE_NUM) { 109319f89e23SAndrey Grodzovsky dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n", 109419f89e23SAndrey Grodzovsky plane_state, MAX_SURFACE_NUM); 109519f89e23SAndrey Grodzovsky return false; 109619f89e23SAndrey Grodzovsky } 109719f89e23SAndrey Grodzovsky 109819f89e23SAndrey Grodzovsky head_pipe = resource_get_head_pipe_for_stream(&context->res_ctx, stream); 109919f89e23SAndrey Grodzovsky 110019f89e23SAndrey Grodzovsky if (!head_pipe) { 110119f89e23SAndrey Grodzovsky dm_error("Head pipe not found for stream_state %p !\n", stream); 11024562236bSHarry Wentland return false; 11034562236bSHarry Wentland } 11044562236bSHarry Wentland 110519f89e23SAndrey Grodzovsky free_pipe = acquire_free_pipe_for_stream(context, pool, stream); 11064562236bSHarry Wentland 11070f9a536fSDmytro Laktyushkin #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 11080f9a536fSDmytro Laktyushkin if (!free_pipe) { 11090f9a536fSDmytro Laktyushkin int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 11100f9a536fSDmytro Laktyushkin if (pipe_idx >= 0) 11110f9a536fSDmytro Laktyushkin free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; 11120f9a536fSDmytro Laktyushkin } 11130f9a536fSDmytro Laktyushkin #endif 1114abb4986eSAndrew Jiang if (!free_pipe) 11154562236bSHarry Wentland return false; 11164562236bSHarry Wentland 1117abb4986eSAndrew Jiang /* retain new surfaces */ 1118abb4986eSAndrew Jiang dc_plane_state_retain(plane_state); 11193be5262eSHarry Wentland free_pipe->plane_state = plane_state; 11204562236bSHarry Wentland 112119f89e23SAndrey Grodzovsky if (head_pipe != free_pipe) { 112219f89e23SAndrey Grodzovsky 112319f89e23SAndrey Grodzovsky tail_pipe = resource_get_tail_pipe_for_stream(&context->res_ctx, stream); 112419f89e23SAndrey Grodzovsky ASSERT(tail_pipe); 112519f89e23SAndrey Grodzovsky 11266b670fa9SHarry Wentland free_pipe->stream_res.tg = tail_pipe->stream_res.tg; 1127a6a6cb34SHarry Wentland free_pipe->stream_res.opp = tail_pipe->stream_res.opp; 11288e9c4c8cSHarry Wentland free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; 1129afaacef4SHarry Wentland free_pipe->stream_res.audio = tail_pipe->stream_res.audio; 1130cfe4645eSDmytro Laktyushkin free_pipe->clock_source = tail_pipe->clock_source; 11314562236bSHarry Wentland free_pipe->top_pipe = tail_pipe; 11324562236bSHarry Wentland tail_pipe->bottom_pipe = free_pipe; 11334562236bSHarry Wentland } 11344562236bSHarry Wentland 11354562236bSHarry Wentland /* assign new surfaces*/ 113619f89e23SAndrey Grodzovsky stream_status->plane_states[stream_status->plane_count] = plane_state; 11374562236bSHarry Wentland 113819f89e23SAndrey Grodzovsky stream_status->plane_count++; 11394562236bSHarry Wentland 11404562236bSHarry Wentland return true; 11414562236bSHarry Wentland } 11424562236bSHarry Wentland 114319f89e23SAndrey Grodzovsky bool dc_remove_plane_from_context( 114419f89e23SAndrey Grodzovsky const struct dc *dc, 114519f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 114619f89e23SAndrey Grodzovsky struct dc_plane_state *plane_state, 1147608ac7bbSJerry Zuo struct dc_state *context) 114819f89e23SAndrey Grodzovsky { 114919f89e23SAndrey Grodzovsky int i; 115019f89e23SAndrey Grodzovsky struct dc_stream_status *stream_status = NULL; 115119f89e23SAndrey Grodzovsky struct resource_pool *pool = dc->res_pool; 115219f89e23SAndrey Grodzovsky 115319f89e23SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 115419f89e23SAndrey Grodzovsky if (context->streams[i] == stream) { 115519f89e23SAndrey Grodzovsky stream_status = &context->stream_status[i]; 115619f89e23SAndrey Grodzovsky break; 115719f89e23SAndrey Grodzovsky } 115819f89e23SAndrey Grodzovsky 115919f89e23SAndrey Grodzovsky if (stream_status == NULL) { 116019f89e23SAndrey Grodzovsky dm_error("Existing stream not found; failed to remove plane.\n"); 116119f89e23SAndrey Grodzovsky return false; 116219f89e23SAndrey Grodzovsky } 116319f89e23SAndrey Grodzovsky 116419f89e23SAndrey Grodzovsky /* release pipe for plane*/ 116519f89e23SAndrey Grodzovsky for (i = pool->pipe_count - 1; i >= 0; i--) { 116619f89e23SAndrey Grodzovsky struct pipe_ctx *pipe_ctx; 116719f89e23SAndrey Grodzovsky 116819f89e23SAndrey Grodzovsky if (context->res_ctx.pipe_ctx[i].plane_state == plane_state) { 116919f89e23SAndrey Grodzovsky pipe_ctx = &context->res_ctx.pipe_ctx[i]; 117019f89e23SAndrey Grodzovsky 117119f89e23SAndrey Grodzovsky if (pipe_ctx->top_pipe) 117219f89e23SAndrey Grodzovsky pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; 117319f89e23SAndrey Grodzovsky 117419f89e23SAndrey Grodzovsky /* Second condition is to avoid setting NULL to top pipe 117519f89e23SAndrey Grodzovsky * of tail pipe making it look like head pipe in subsequent 117619f89e23SAndrey Grodzovsky * deletes 117719f89e23SAndrey Grodzovsky */ 117819f89e23SAndrey Grodzovsky if (pipe_ctx->bottom_pipe && pipe_ctx->top_pipe) 117919f89e23SAndrey Grodzovsky pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; 118019f89e23SAndrey Grodzovsky 118119f89e23SAndrey Grodzovsky /* 118219f89e23SAndrey Grodzovsky * For head pipe detach surfaces from pipe for tail 118319f89e23SAndrey Grodzovsky * pipe just zero it out 118419f89e23SAndrey Grodzovsky */ 118519f89e23SAndrey Grodzovsky if (!pipe_ctx->top_pipe) { 118619f89e23SAndrey Grodzovsky pipe_ctx->plane_state = NULL; 118719f89e23SAndrey Grodzovsky pipe_ctx->bottom_pipe = NULL; 118819f89e23SAndrey Grodzovsky } else { 118919f89e23SAndrey Grodzovsky memset(pipe_ctx, 0, sizeof(*pipe_ctx)); 119019f89e23SAndrey Grodzovsky } 119119f89e23SAndrey Grodzovsky } 119219f89e23SAndrey Grodzovsky } 119319f89e23SAndrey Grodzovsky 119419f89e23SAndrey Grodzovsky 119519f89e23SAndrey Grodzovsky for (i = 0; i < stream_status->plane_count; i++) { 119619f89e23SAndrey Grodzovsky if (stream_status->plane_states[i] == plane_state) { 119719f89e23SAndrey Grodzovsky 119819f89e23SAndrey Grodzovsky dc_plane_state_release(stream_status->plane_states[i]); 119919f89e23SAndrey Grodzovsky break; 120019f89e23SAndrey Grodzovsky } 120119f89e23SAndrey Grodzovsky } 120219f89e23SAndrey Grodzovsky 120319f89e23SAndrey Grodzovsky if (i == stream_status->plane_count) { 120419f89e23SAndrey Grodzovsky dm_error("Existing plane_state not found; failed to detach it!\n"); 120519f89e23SAndrey Grodzovsky return false; 120619f89e23SAndrey Grodzovsky } 120719f89e23SAndrey Grodzovsky 120819f89e23SAndrey Grodzovsky stream_status->plane_count--; 120919f89e23SAndrey Grodzovsky 1210abb4986eSAndrew Jiang /* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */ 1211abb4986eSAndrew Jiang for (; i < stream_status->plane_count; i++) 121219f89e23SAndrey Grodzovsky stream_status->plane_states[i] = stream_status->plane_states[i + 1]; 121319f89e23SAndrey Grodzovsky 121419f89e23SAndrey Grodzovsky stream_status->plane_states[stream_status->plane_count] = NULL; 121519f89e23SAndrey Grodzovsky 121619f89e23SAndrey Grodzovsky return true; 121719f89e23SAndrey Grodzovsky } 121819f89e23SAndrey Grodzovsky 121919f89e23SAndrey Grodzovsky bool dc_rem_all_planes_for_stream( 122019f89e23SAndrey Grodzovsky const struct dc *dc, 122119f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 1222608ac7bbSJerry Zuo struct dc_state *context) 122319f89e23SAndrey Grodzovsky { 122419f89e23SAndrey Grodzovsky int i, old_plane_count; 122519f89e23SAndrey Grodzovsky struct dc_stream_status *stream_status = NULL; 122619f89e23SAndrey Grodzovsky struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 }; 122719f89e23SAndrey Grodzovsky 122819f89e23SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 122919f89e23SAndrey Grodzovsky if (context->streams[i] == stream) { 123019f89e23SAndrey Grodzovsky stream_status = &context->stream_status[i]; 123119f89e23SAndrey Grodzovsky break; 123219f89e23SAndrey Grodzovsky } 123319f89e23SAndrey Grodzovsky 123419f89e23SAndrey Grodzovsky if (stream_status == NULL) { 123519f89e23SAndrey Grodzovsky dm_error("Existing stream %p not found!\n", stream); 123619f89e23SAndrey Grodzovsky return false; 123719f89e23SAndrey Grodzovsky } 123819f89e23SAndrey Grodzovsky 123919f89e23SAndrey Grodzovsky old_plane_count = stream_status->plane_count; 124019f89e23SAndrey Grodzovsky 124119f89e23SAndrey Grodzovsky for (i = 0; i < old_plane_count; i++) 124219f89e23SAndrey Grodzovsky del_planes[i] = stream_status->plane_states[i]; 124319f89e23SAndrey Grodzovsky 124419f89e23SAndrey Grodzovsky for (i = 0; i < old_plane_count; i++) 124519f89e23SAndrey Grodzovsky if (!dc_remove_plane_from_context(dc, stream, del_planes[i], context)) 124619f89e23SAndrey Grodzovsky return false; 124719f89e23SAndrey Grodzovsky 124819f89e23SAndrey Grodzovsky return true; 124919f89e23SAndrey Grodzovsky } 125019f89e23SAndrey Grodzovsky 125119f89e23SAndrey Grodzovsky static bool add_all_planes_for_stream( 125219f89e23SAndrey Grodzovsky const struct dc *dc, 125319f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 125419f89e23SAndrey Grodzovsky const struct dc_validation_set set[], 125519f89e23SAndrey Grodzovsky int set_count, 1256608ac7bbSJerry Zuo struct dc_state *context) 125719f89e23SAndrey Grodzovsky { 125819f89e23SAndrey Grodzovsky int i, j; 125919f89e23SAndrey Grodzovsky 126019f89e23SAndrey Grodzovsky for (i = 0; i < set_count; i++) 126119f89e23SAndrey Grodzovsky if (set[i].stream == stream) 126219f89e23SAndrey Grodzovsky break; 126319f89e23SAndrey Grodzovsky 126419f89e23SAndrey Grodzovsky if (i == set_count) { 126519f89e23SAndrey Grodzovsky dm_error("Stream %p not found in set!\n", stream); 126619f89e23SAndrey Grodzovsky return false; 126719f89e23SAndrey Grodzovsky } 126819f89e23SAndrey Grodzovsky 126919f89e23SAndrey Grodzovsky for (j = 0; j < set[i].plane_count; j++) 127019f89e23SAndrey Grodzovsky if (!dc_add_plane_to_context(dc, stream, set[i].plane_states[j], context)) 127119f89e23SAndrey Grodzovsky return false; 127219f89e23SAndrey Grodzovsky 127319f89e23SAndrey Grodzovsky return true; 127419f89e23SAndrey Grodzovsky } 127519f89e23SAndrey Grodzovsky 127619f89e23SAndrey Grodzovsky bool dc_add_all_planes_for_stream( 127719f89e23SAndrey Grodzovsky const struct dc *dc, 127819f89e23SAndrey Grodzovsky struct dc_stream_state *stream, 127919f89e23SAndrey Grodzovsky struct dc_plane_state * const *plane_states, 128019f89e23SAndrey Grodzovsky int plane_count, 1281608ac7bbSJerry Zuo struct dc_state *context) 128219f89e23SAndrey Grodzovsky { 128319f89e23SAndrey Grodzovsky struct dc_validation_set set; 128419f89e23SAndrey Grodzovsky int i; 128519f89e23SAndrey Grodzovsky 128619f89e23SAndrey Grodzovsky set.stream = stream; 128719f89e23SAndrey Grodzovsky set.plane_count = plane_count; 128819f89e23SAndrey Grodzovsky 128919f89e23SAndrey Grodzovsky for (i = 0; i < plane_count; i++) 129019f89e23SAndrey Grodzovsky set.plane_states[i] = plane_states[i]; 129119f89e23SAndrey Grodzovsky 129219f89e23SAndrey Grodzovsky return add_all_planes_for_stream(dc, stream, &set, 1, context); 129319f89e23SAndrey Grodzovsky } 129419f89e23SAndrey Grodzovsky 129519f89e23SAndrey Grodzovsky 12964562236bSHarry Wentland 12970971c40eSHarry Wentland static bool is_timing_changed(struct dc_stream_state *cur_stream, 12980971c40eSHarry Wentland struct dc_stream_state *new_stream) 12994562236bSHarry Wentland { 13004562236bSHarry Wentland if (cur_stream == NULL) 13014562236bSHarry Wentland return true; 13024562236bSHarry Wentland 13034562236bSHarry Wentland /* If sink pointer changed, it means this is a hotplug, we should do 13044562236bSHarry Wentland * full hw setting. 13054562236bSHarry Wentland */ 13064562236bSHarry Wentland if (cur_stream->sink != new_stream->sink) 13074562236bSHarry Wentland return true; 13084562236bSHarry Wentland 13094562236bSHarry Wentland /* If output color space is changed, need to reprogram info frames */ 13104fa086b9SLeo (Sunpeng) Li if (cur_stream->output_color_space != new_stream->output_color_space) 13114562236bSHarry Wentland return true; 13124562236bSHarry Wentland 13134562236bSHarry Wentland return memcmp( 13144fa086b9SLeo (Sunpeng) Li &cur_stream->timing, 13154fa086b9SLeo (Sunpeng) Li &new_stream->timing, 13164562236bSHarry Wentland sizeof(struct dc_crtc_timing)) != 0; 13174562236bSHarry Wentland } 13184562236bSHarry Wentland 13194562236bSHarry Wentland static bool are_stream_backends_same( 13200971c40eSHarry Wentland struct dc_stream_state *stream_a, struct dc_stream_state *stream_b) 13214562236bSHarry Wentland { 13224562236bSHarry Wentland if (stream_a == stream_b) 13234562236bSHarry Wentland return true; 13244562236bSHarry Wentland 13254562236bSHarry Wentland if (stream_a == NULL || stream_b == NULL) 13264562236bSHarry Wentland return false; 13274562236bSHarry Wentland 13284562236bSHarry Wentland if (is_timing_changed(stream_a, stream_b)) 13294562236bSHarry Wentland return false; 13304562236bSHarry Wentland 13314562236bSHarry Wentland return true; 13324562236bSHarry Wentland } 13334562236bSHarry Wentland 1334d54d29dbSBhawanpreet Lakha bool dc_is_stream_unchanged( 13350971c40eSHarry Wentland struct dc_stream_state *old_stream, struct dc_stream_state *stream) 13364562236bSHarry Wentland { 13374562236bSHarry Wentland 13384562236bSHarry Wentland if (!are_stream_backends_same(old_stream, stream)) 13394562236bSHarry Wentland return false; 13404562236bSHarry Wentland 13414562236bSHarry Wentland return true; 13424562236bSHarry Wentland } 13434562236bSHarry Wentland 13449a5d9c48SLeo (Sunpeng) Li bool dc_is_stream_scaling_unchanged( 13459a5d9c48SLeo (Sunpeng) Li struct dc_stream_state *old_stream, struct dc_stream_state *stream) 13469a5d9c48SLeo (Sunpeng) Li { 13479a5d9c48SLeo (Sunpeng) Li if (old_stream == stream) 13489a5d9c48SLeo (Sunpeng) Li return true; 13499a5d9c48SLeo (Sunpeng) Li 13509a5d9c48SLeo (Sunpeng) Li if (old_stream == NULL || stream == NULL) 13519a5d9c48SLeo (Sunpeng) Li return false; 13529a5d9c48SLeo (Sunpeng) Li 13539a5d9c48SLeo (Sunpeng) Li if (memcmp(&old_stream->src, 13549a5d9c48SLeo (Sunpeng) Li &stream->src, 13559a5d9c48SLeo (Sunpeng) Li sizeof(struct rect)) != 0) 13569a5d9c48SLeo (Sunpeng) Li return false; 13579a5d9c48SLeo (Sunpeng) Li 13589a5d9c48SLeo (Sunpeng) Li if (memcmp(&old_stream->dst, 13599a5d9c48SLeo (Sunpeng) Li &stream->dst, 13609a5d9c48SLeo (Sunpeng) Li sizeof(struct rect)) != 0) 13619a5d9c48SLeo (Sunpeng) Li return false; 13629a5d9c48SLeo (Sunpeng) Li 13639a5d9c48SLeo (Sunpeng) Li return true; 13649a5d9c48SLeo (Sunpeng) Li } 13659a5d9c48SLeo (Sunpeng) Li 13661dc90497SAndrey Grodzovsky static void update_stream_engine_usage( 13674562236bSHarry Wentland struct resource_context *res_ctx, 1368a2b8659dSTony Cheng const struct resource_pool *pool, 13691dc90497SAndrey Grodzovsky struct stream_encoder *stream_enc, 13701dc90497SAndrey Grodzovsky bool acquired) 13714562236bSHarry Wentland { 13724562236bSHarry Wentland int i; 13734562236bSHarry Wentland 1374a2b8659dSTony Cheng for (i = 0; i < pool->stream_enc_count; i++) { 1375a2b8659dSTony Cheng if (pool->stream_enc[i] == stream_enc) 13761dc90497SAndrey Grodzovsky res_ctx->is_stream_enc_acquired[i] = acquired; 13774562236bSHarry Wentland } 13784562236bSHarry Wentland } 13794562236bSHarry Wentland 13804562236bSHarry Wentland /* TODO: release audio object */ 13814176664bSCharlene Liu void update_audio_usage( 13824562236bSHarry Wentland struct resource_context *res_ctx, 1383a2b8659dSTony Cheng const struct resource_pool *pool, 13841dc90497SAndrey Grodzovsky struct audio *audio, 13851dc90497SAndrey Grodzovsky bool acquired) 13864562236bSHarry Wentland { 13874562236bSHarry Wentland int i; 1388a2b8659dSTony Cheng for (i = 0; i < pool->audio_count; i++) { 1389a2b8659dSTony Cheng if (pool->audios[i] == audio) 13901dc90497SAndrey Grodzovsky res_ctx->is_audio_acquired[i] = acquired; 13914562236bSHarry Wentland } 13924562236bSHarry Wentland } 13934562236bSHarry Wentland 13944562236bSHarry Wentland static int acquire_first_free_pipe( 13954562236bSHarry Wentland struct resource_context *res_ctx, 1396a2b8659dSTony Cheng const struct resource_pool *pool, 13970971c40eSHarry Wentland struct dc_stream_state *stream) 13984562236bSHarry Wentland { 13994562236bSHarry Wentland int i; 14004562236bSHarry Wentland 1401a2b8659dSTony Cheng for (i = 0; i < pool->pipe_count; i++) { 14024562236bSHarry Wentland if (!res_ctx->pipe_ctx[i].stream) { 14034562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 14044562236bSHarry Wentland 14056b670fa9SHarry Wentland pipe_ctx->stream_res.tg = pool->timing_generators[i]; 140686a66c4eSHarry Wentland pipe_ctx->plane_res.mi = pool->mis[i]; 14078feabd03SYue Hin Lau pipe_ctx->plane_res.hubp = pool->hubps[i]; 140886a66c4eSHarry Wentland pipe_ctx->plane_res.ipp = pool->ipps[i]; 140986a66c4eSHarry Wentland pipe_ctx->plane_res.xfm = pool->transforms[i]; 1410d94585a0SYue Hin Lau pipe_ctx->plane_res.dpp = pool->dpps[i]; 1411a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp = pool->opps[i]; 1412bc373a89SRoman Li if (pool->dpps[i]) 1413e07f541fSYongqiang Sun pipe_ctx->plane_res.mpcc_inst = pool->dpps[i]->inst; 14144562236bSHarry Wentland pipe_ctx->pipe_idx = i; 14154562236bSHarry Wentland 1416ff5ef992SAlex Deucher 14174562236bSHarry Wentland pipe_ctx->stream = stream; 14184562236bSHarry Wentland return i; 14194562236bSHarry Wentland } 14204562236bSHarry Wentland } 14214562236bSHarry Wentland return -1; 14224562236bSHarry Wentland } 14234562236bSHarry Wentland 14244562236bSHarry Wentland static struct stream_encoder *find_first_free_match_stream_enc_for_link( 14254562236bSHarry Wentland struct resource_context *res_ctx, 1426a2b8659dSTony Cheng const struct resource_pool *pool, 14270971c40eSHarry Wentland struct dc_stream_state *stream) 14284562236bSHarry Wentland { 14294562236bSHarry Wentland int i; 14304562236bSHarry Wentland int j = -1; 1431d0778ebfSHarry Wentland struct dc_link *link = stream->sink->link; 14324562236bSHarry Wentland 1433a2b8659dSTony Cheng for (i = 0; i < pool->stream_enc_count; i++) { 14344562236bSHarry Wentland if (!res_ctx->is_stream_enc_acquired[i] && 1435a2b8659dSTony Cheng pool->stream_enc[i]) { 14364562236bSHarry Wentland /* Store first available for MST second display 14374562236bSHarry Wentland * in daisy chain use case */ 14384562236bSHarry Wentland j = i; 1439a2b8659dSTony Cheng if (pool->stream_enc[i]->id == 14404562236bSHarry Wentland link->link_enc->preferred_engine) 1441a2b8659dSTony Cheng return pool->stream_enc[i]; 14424562236bSHarry Wentland } 14434562236bSHarry Wentland } 14444562236bSHarry Wentland 14454562236bSHarry Wentland /* 14464562236bSHarry Wentland * below can happen in cases when stream encoder is acquired: 14474562236bSHarry Wentland * 1) for second MST display in chain, so preferred engine already 14484562236bSHarry Wentland * acquired; 14494562236bSHarry Wentland * 2) for another link, which preferred engine already acquired by any 14504562236bSHarry Wentland * MST configuration. 14514562236bSHarry Wentland * 14524562236bSHarry Wentland * If signal is of DP type and preferred engine not found, return last available 14534562236bSHarry Wentland * 14544562236bSHarry Wentland * TODO - This is just a patch up and a generic solution is 14554562236bSHarry Wentland * required for non DP connectors. 14564562236bSHarry Wentland */ 14574562236bSHarry Wentland 14584562236bSHarry Wentland if (j >= 0 && dc_is_dp_signal(stream->signal)) 1459a2b8659dSTony Cheng return pool->stream_enc[j]; 14604562236bSHarry Wentland 14614562236bSHarry Wentland return NULL; 14624562236bSHarry Wentland } 14634562236bSHarry Wentland 1464a2b8659dSTony Cheng static struct audio *find_first_free_audio( 1465a2b8659dSTony Cheng struct resource_context *res_ctx, 1466cfb071f7SCharlene Liu const struct resource_pool *pool, 1467cfb071f7SCharlene Liu enum engine_id id) 14684562236bSHarry Wentland { 14694562236bSHarry Wentland int i; 1470a2b8659dSTony Cheng for (i = 0; i < pool->audio_count; i++) { 14714176664bSCharlene Liu if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) { 1472cfb071f7SCharlene Liu /*we have enough audio endpoint, find the matching inst*/ 1473cfb071f7SCharlene Liu if (id != i) 1474cfb071f7SCharlene Liu continue; 1475cfb071f7SCharlene Liu 1476a2b8659dSTony Cheng return pool->audios[i]; 14774562236bSHarry Wentland } 14784562236bSHarry Wentland } 147966bfd4fdSCharlene Liu /*not found the matching one, first come first serve*/ 14804176664bSCharlene Liu for (i = 0; i < pool->audio_count; i++) { 14814176664bSCharlene Liu if (res_ctx->is_audio_acquired[i] == false) { 14824176664bSCharlene Liu return pool->audios[i]; 14834176664bSCharlene Liu } 14844176664bSCharlene Liu } 14854562236bSHarry Wentland return 0; 14864562236bSHarry Wentland } 14874562236bSHarry Wentland 14884562236bSHarry Wentland bool resource_is_stream_unchanged( 1489608ac7bbSJerry Zuo struct dc_state *old_context, struct dc_stream_state *stream) 14904562236bSHarry Wentland { 1491ab2541b6SAric Cyr int i; 14924562236bSHarry Wentland 1493ab2541b6SAric Cyr for (i = 0; i < old_context->stream_count; i++) { 14940971c40eSHarry Wentland struct dc_stream_state *old_stream = old_context->streams[i]; 14954562236bSHarry Wentland 14964562236bSHarry Wentland if (are_stream_backends_same(old_stream, stream)) 14974562236bSHarry Wentland return true; 14984562236bSHarry Wentland } 14994562236bSHarry Wentland 15004562236bSHarry Wentland return false; 15014562236bSHarry Wentland } 15024562236bSHarry Wentland 150313ab1b44SYongqiang Sun enum dc_status dc_add_stream_to_ctx( 15041dc90497SAndrey Grodzovsky struct dc *dc, 1505608ac7bbSJerry Zuo struct dc_state *new_ctx, 15061dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 15071dc90497SAndrey Grodzovsky { 15081dc90497SAndrey Grodzovsky struct dc_context *dc_ctx = dc->ctx; 15091dc90497SAndrey Grodzovsky enum dc_status res; 15101dc90497SAndrey Grodzovsky 15111dc90497SAndrey Grodzovsky if (new_ctx->stream_count >= dc->res_pool->pipe_count) { 15121dc90497SAndrey Grodzovsky DC_ERROR("Max streams reached, can add stream %p !\n", stream); 15131dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 15141dc90497SAndrey Grodzovsky } 15151dc90497SAndrey Grodzovsky 15161dc90497SAndrey Grodzovsky new_ctx->streams[new_ctx->stream_count] = stream; 15171dc90497SAndrey Grodzovsky dc_stream_retain(stream); 15181dc90497SAndrey Grodzovsky new_ctx->stream_count++; 15191dc90497SAndrey Grodzovsky 15201dc90497SAndrey Grodzovsky res = dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream); 15211dc90497SAndrey Grodzovsky if (res != DC_OK) 15221dc90497SAndrey Grodzovsky DC_ERROR("Adding stream %p to context failed with err %d!\n", stream, res); 15231dc90497SAndrey Grodzovsky 152413ab1b44SYongqiang Sun return res; 15251dc90497SAndrey Grodzovsky } 15261dc90497SAndrey Grodzovsky 152762c933f9SYongqiang Sun enum dc_status dc_remove_stream_from_ctx( 15281dc90497SAndrey Grodzovsky struct dc *dc, 1529608ac7bbSJerry Zuo struct dc_state *new_ctx, 15301dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 15311dc90497SAndrey Grodzovsky { 153219f89e23SAndrey Grodzovsky int i; 15331dc90497SAndrey Grodzovsky struct dc_context *dc_ctx = dc->ctx; 15341dc90497SAndrey Grodzovsky struct pipe_ctx *del_pipe = NULL; 15351dc90497SAndrey Grodzovsky 153619f89e23SAndrey Grodzovsky /* Release primary pipe */ 15371dc90497SAndrey Grodzovsky for (i = 0; i < MAX_PIPES; i++) { 153819f89e23SAndrey Grodzovsky if (new_ctx->res_ctx.pipe_ctx[i].stream == stream && 153919f89e23SAndrey Grodzovsky !new_ctx->res_ctx.pipe_ctx[i].top_pipe) { 15401dc90497SAndrey Grodzovsky del_pipe = &new_ctx->res_ctx.pipe_ctx[i]; 15411dc90497SAndrey Grodzovsky 154219f89e23SAndrey Grodzovsky ASSERT(del_pipe->stream_res.stream_enc); 15431dc90497SAndrey Grodzovsky update_stream_engine_usage( 15441dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 15451dc90497SAndrey Grodzovsky dc->res_pool, 15461dc90497SAndrey Grodzovsky del_pipe->stream_res.stream_enc, 15471dc90497SAndrey Grodzovsky false); 15481dc90497SAndrey Grodzovsky 15491dc90497SAndrey Grodzovsky if (del_pipe->stream_res.audio) 15501dc90497SAndrey Grodzovsky update_audio_usage( 15511dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 15521dc90497SAndrey Grodzovsky dc->res_pool, 15531dc90497SAndrey Grodzovsky del_pipe->stream_res.audio, 15541dc90497SAndrey Grodzovsky false); 15551dc90497SAndrey Grodzovsky 15569d0dcecdSHarry Wentland resource_unreference_clock_source(&new_ctx->res_ctx, 15579d0dcecdSHarry Wentland dc->res_pool, 15589d0dcecdSHarry Wentland del_pipe->clock_source); 15599d0dcecdSHarry Wentland 1560e56ae556SNikola Cornij if (dc->res_pool->funcs->remove_stream_from_ctx) 1561e56ae556SNikola Cornij dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream); 1562e56ae556SNikola Cornij 15631dc90497SAndrey Grodzovsky memset(del_pipe, 0, sizeof(*del_pipe)); 156419f89e23SAndrey Grodzovsky 156519f89e23SAndrey Grodzovsky break; 15661dc90497SAndrey Grodzovsky } 15671dc90497SAndrey Grodzovsky } 15681dc90497SAndrey Grodzovsky 15691dc90497SAndrey Grodzovsky if (!del_pipe) { 15701dc90497SAndrey Grodzovsky DC_ERROR("Pipe not found for stream %p !\n", stream); 15711dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 15721dc90497SAndrey Grodzovsky } 15731dc90497SAndrey Grodzovsky 15741dc90497SAndrey Grodzovsky for (i = 0; i < new_ctx->stream_count; i++) 15751dc90497SAndrey Grodzovsky if (new_ctx->streams[i] == stream) 15761dc90497SAndrey Grodzovsky break; 15771dc90497SAndrey Grodzovsky 15781dc90497SAndrey Grodzovsky if (new_ctx->streams[i] != stream) { 15791dc90497SAndrey Grodzovsky DC_ERROR("Context doesn't have stream %p !\n", stream); 15801dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 15811dc90497SAndrey Grodzovsky } 15821dc90497SAndrey Grodzovsky 15831dc90497SAndrey Grodzovsky dc_stream_release(new_ctx->streams[i]); 15841dc90497SAndrey Grodzovsky new_ctx->stream_count--; 15851dc90497SAndrey Grodzovsky 15861dc90497SAndrey Grodzovsky /* Trim back arrays */ 15871dc90497SAndrey Grodzovsky for (; i < new_ctx->stream_count; i++) { 15881dc90497SAndrey Grodzovsky new_ctx->streams[i] = new_ctx->streams[i + 1]; 15891dc90497SAndrey Grodzovsky new_ctx->stream_status[i] = new_ctx->stream_status[i + 1]; 15901dc90497SAndrey Grodzovsky } 15911dc90497SAndrey Grodzovsky 15921dc90497SAndrey Grodzovsky new_ctx->streams[new_ctx->stream_count] = NULL; 15931dc90497SAndrey Grodzovsky memset( 15941dc90497SAndrey Grodzovsky &new_ctx->stream_status[new_ctx->stream_count], 15951dc90497SAndrey Grodzovsky 0, 15961dc90497SAndrey Grodzovsky sizeof(new_ctx->stream_status[0])); 15971dc90497SAndrey Grodzovsky 15981dc90497SAndrey Grodzovsky return DC_OK; 15991dc90497SAndrey Grodzovsky } 16001dc90497SAndrey Grodzovsky 16014562236bSHarry Wentland static void copy_pipe_ctx( 16024562236bSHarry Wentland const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx) 16034562236bSHarry Wentland { 16043be5262eSHarry Wentland struct dc_plane_state *plane_state = to_pipe_ctx->plane_state; 16050971c40eSHarry Wentland struct dc_stream_state *stream = to_pipe_ctx->stream; 16064562236bSHarry Wentland 16074562236bSHarry Wentland *to_pipe_ctx = *from_pipe_ctx; 16084562236bSHarry Wentland to_pipe_ctx->stream = stream; 16093be5262eSHarry Wentland if (plane_state != NULL) 16103be5262eSHarry Wentland to_pipe_ctx->plane_state = plane_state; 16114562236bSHarry Wentland } 16124562236bSHarry Wentland 16130971c40eSHarry Wentland static struct dc_stream_state *find_pll_sharable_stream( 16140971c40eSHarry Wentland struct dc_stream_state *stream_needs_pll, 1615608ac7bbSJerry Zuo struct dc_state *context) 16164562236bSHarry Wentland { 1617ab2541b6SAric Cyr int i; 16184562236bSHarry Wentland 1619ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 16200971c40eSHarry Wentland struct dc_stream_state *stream_has_pll = context->streams[i]; 16214562236bSHarry Wentland 16224562236bSHarry Wentland /* We are looking for non dp, non virtual stream */ 16234562236bSHarry Wentland if (resource_are_streams_timing_synchronizable( 16244562236bSHarry Wentland stream_needs_pll, stream_has_pll) 16254562236bSHarry Wentland && !dc_is_dp_signal(stream_has_pll->signal) 1626d0778ebfSHarry Wentland && stream_has_pll->sink->link->connector_signal 16274562236bSHarry Wentland != SIGNAL_TYPE_VIRTUAL) 16284562236bSHarry Wentland return stream_has_pll; 1629ab2541b6SAric Cyr 16304562236bSHarry Wentland } 16314562236bSHarry Wentland 16324562236bSHarry Wentland return NULL; 16334562236bSHarry Wentland } 16344562236bSHarry Wentland 16354562236bSHarry Wentland static int get_norm_pix_clk(const struct dc_crtc_timing *timing) 16364562236bSHarry Wentland { 16374562236bSHarry Wentland uint32_t pix_clk = timing->pix_clk_khz; 16384562236bSHarry Wentland uint32_t normalized_pix_clk = pix_clk; 16394562236bSHarry Wentland 16404562236bSHarry Wentland if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) 16414562236bSHarry Wentland pix_clk /= 2; 1642cc4d99b8SCharlene Liu if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) { 16434562236bSHarry Wentland switch (timing->display_color_depth) { 16444562236bSHarry Wentland case COLOR_DEPTH_888: 16454562236bSHarry Wentland normalized_pix_clk = pix_clk; 16464562236bSHarry Wentland break; 16474562236bSHarry Wentland case COLOR_DEPTH_101010: 16484562236bSHarry Wentland normalized_pix_clk = (pix_clk * 30) / 24; 16494562236bSHarry Wentland break; 16504562236bSHarry Wentland case COLOR_DEPTH_121212: 16514562236bSHarry Wentland normalized_pix_clk = (pix_clk * 36) / 24; 16524562236bSHarry Wentland break; 16534562236bSHarry Wentland case COLOR_DEPTH_161616: 16544562236bSHarry Wentland normalized_pix_clk = (pix_clk * 48) / 24; 16554562236bSHarry Wentland break; 16564562236bSHarry Wentland default: 16574562236bSHarry Wentland ASSERT(0); 16584562236bSHarry Wentland break; 16594562236bSHarry Wentland } 1660cc4d99b8SCharlene Liu } 16614562236bSHarry Wentland return normalized_pix_clk; 16624562236bSHarry Wentland } 16634562236bSHarry Wentland 16640971c40eSHarry Wentland static void calculate_phy_pix_clks(struct dc_stream_state *stream) 16654562236bSHarry Wentland { 16664562236bSHarry Wentland /* update actual pixel clock on all streams */ 16674562236bSHarry Wentland if (dc_is_hdmi_signal(stream->signal)) 16684562236bSHarry Wentland stream->phy_pix_clk = get_norm_pix_clk( 16694fa086b9SLeo (Sunpeng) Li &stream->timing); 16704562236bSHarry Wentland else 16714562236bSHarry Wentland stream->phy_pix_clk = 16724fa086b9SLeo (Sunpeng) Li stream->timing.pix_clk_khz; 16734562236bSHarry Wentland } 16744562236bSHarry Wentland 16754562236bSHarry Wentland enum dc_status resource_map_pool_resources( 1676fb3466a4SBhawanpreet Lakha const struct dc *dc, 1677608ac7bbSJerry Zuo struct dc_state *context, 16781dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 16794562236bSHarry Wentland { 1680a2b8659dSTony Cheng const struct resource_pool *pool = dc->res_pool; 16811dc90497SAndrey Grodzovsky int i; 16821dc90497SAndrey Grodzovsky struct dc_context *dc_ctx = dc->ctx; 16831dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = NULL; 16841dc90497SAndrey Grodzovsky int pipe_idx = -1; 16854562236bSHarry Wentland 16861dc90497SAndrey Grodzovsky /* TODO Check if this is needed */ 16871dc90497SAndrey Grodzovsky /*if (!resource_is_stream_unchanged(old_context, stream)) { 1688430ef426SDmytro Laktyushkin if (stream != NULL && old_context->streams[i] != NULL) { 16894b679bc3SCharlene Liu stream->bit_depth_params = 1690430ef426SDmytro Laktyushkin old_context->streams[i]->bit_depth_params; 1691430ef426SDmytro Laktyushkin stream->clamping = old_context->streams[i]->clamping; 16924562236bSHarry Wentland continue; 16934b679bc3SCharlene Liu } 16944b679bc3SCharlene Liu } 16954562236bSHarry Wentland */ 16964562236bSHarry Wentland 16974562236bSHarry Wentland /* acquire new resources */ 16985d11e9fcSDmytro Laktyushkin pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); 16991dc90497SAndrey Grodzovsky 170094c6d735SHarry Wentland #ifdef CONFIG_DRM_AMD_DC_DCN1_0 17015d11e9fcSDmytro Laktyushkin if (pipe_idx < 0) 170213ab1b44SYongqiang Sun pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 170394c6d735SHarry Wentland #endif 170413ab1b44SYongqiang Sun 17054562236bSHarry Wentland if (pipe_idx < 0) 17064562236bSHarry Wentland return DC_NO_CONTROLLER_RESOURCE; 17074562236bSHarry Wentland 17084562236bSHarry Wentland pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; 17094562236bSHarry Wentland 17108e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc = 17114562236bSHarry Wentland find_first_free_match_stream_enc_for_link( 1712a2b8659dSTony Cheng &context->res_ctx, pool, stream); 17134562236bSHarry Wentland 17148e9c4c8cSHarry Wentland if (!pipe_ctx->stream_res.stream_enc) 17154562236bSHarry Wentland return DC_NO_STREAM_ENG_RESOURCE; 17164562236bSHarry Wentland 17171dc90497SAndrey Grodzovsky update_stream_engine_usage( 1718a2b8659dSTony Cheng &context->res_ctx, pool, 17191dc90497SAndrey Grodzovsky pipe_ctx->stream_res.stream_enc, 17201dc90497SAndrey Grodzovsky true); 17214562236bSHarry Wentland 17224562236bSHarry Wentland /* TODO: Add check if ASIC support and EDID audio */ 1723b73a22d3SHarry Wentland if (!stream->sink->converter_disable_audio && 17244562236bSHarry Wentland dc_is_audio_capable_signal(pipe_ctx->stream->signal) && 17254fa086b9SLeo (Sunpeng) Li stream->audio_info.mode_count) { 1726afaacef4SHarry Wentland pipe_ctx->stream_res.audio = find_first_free_audio( 1727cfb071f7SCharlene Liu &context->res_ctx, pool, pipe_ctx->stream_res.stream_enc->id); 17284562236bSHarry Wentland 17294562236bSHarry Wentland /* 17304562236bSHarry Wentland * Audio assigned in order first come first get. 17314562236bSHarry Wentland * There are asics which has number of audio 17324562236bSHarry Wentland * resources less then number of pipes 17334562236bSHarry Wentland */ 1734afaacef4SHarry Wentland if (pipe_ctx->stream_res.audio) 17351dc90497SAndrey Grodzovsky update_audio_usage(&context->res_ctx, pool, 17361dc90497SAndrey Grodzovsky pipe_ctx->stream_res.audio, true); 17374562236bSHarry Wentland } 17384562236bSHarry Wentland 17391dc90497SAndrey Grodzovsky for (i = 0; i < context->stream_count; i++) 17401dc90497SAndrey Grodzovsky if (context->streams[i] == stream) { 17416b670fa9SHarry Wentland context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; 17420f0bdca5SWenjing Liu context->stream_status[i].stream_enc_inst = pipe_ctx->stream_res.stream_enc->id; 17431dc90497SAndrey Grodzovsky return DC_OK; 17444562236bSHarry Wentland } 17454562236bSHarry Wentland 17461dc90497SAndrey Grodzovsky DC_ERROR("Stream %p not found in new ctx!\n", stream); 17471dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 17484562236bSHarry Wentland } 17494562236bSHarry Wentland 1750ab2541b6SAric Cyr /* first stream in the context is used to populate the rest */ 1751ab2541b6SAric Cyr void validate_guaranteed_copy_streams( 1752608ac7bbSJerry Zuo struct dc_state *context, 1753ab2541b6SAric Cyr int max_streams) 17544562236bSHarry Wentland { 17554562236bSHarry Wentland int i; 17564562236bSHarry Wentland 1757ab2541b6SAric Cyr for (i = 1; i < max_streams; i++) { 1758ab2541b6SAric Cyr context->streams[i] = context->streams[0]; 17594562236bSHarry Wentland 17604562236bSHarry Wentland copy_pipe_ctx(&context->res_ctx.pipe_ctx[0], 17614562236bSHarry Wentland &context->res_ctx.pipe_ctx[i]); 17624562236bSHarry Wentland context->res_ctx.pipe_ctx[i].stream = 17634562236bSHarry Wentland context->res_ctx.pipe_ctx[0].stream; 17644562236bSHarry Wentland 17654fa086b9SLeo (Sunpeng) Li dc_stream_retain(context->streams[i]); 1766ab2541b6SAric Cyr context->stream_count++; 17674562236bSHarry Wentland } 17684562236bSHarry Wentland } 17694562236bSHarry Wentland 1770f36cc577SBhawanpreet Lakha void dc_resource_state_copy_construct_current( 17711dc90497SAndrey Grodzovsky const struct dc *dc, 1772608ac7bbSJerry Zuo struct dc_state *dst_ctx) 17731dc90497SAndrey Grodzovsky { 1774f36cc577SBhawanpreet Lakha dc_resource_state_copy_construct(dc->current_state, dst_ctx); 17751dc90497SAndrey Grodzovsky } 17761dc90497SAndrey Grodzovsky 1777ab8db3e1SAndrey Grodzovsky 1778ab8db3e1SAndrey Grodzovsky void dc_resource_state_construct( 1779ab8db3e1SAndrey Grodzovsky const struct dc *dc, 1780ab8db3e1SAndrey Grodzovsky struct dc_state *dst_ctx) 1781ab8db3e1SAndrey Grodzovsky { 1782ab8db3e1SAndrey Grodzovsky dst_ctx->dis_clk = dc->res_pool->display_clock; 1783ab8db3e1SAndrey Grodzovsky } 1784ab8db3e1SAndrey Grodzovsky 1785e750d56dSYongqiang Sun enum dc_status dc_validate_global_state( 17861dc90497SAndrey Grodzovsky struct dc *dc, 1787608ac7bbSJerry Zuo struct dc_state *new_ctx) 17881dc90497SAndrey Grodzovsky { 17891dc90497SAndrey Grodzovsky enum dc_status result = DC_ERROR_UNEXPECTED; 17901dc90497SAndrey Grodzovsky int i, j; 17911dc90497SAndrey Grodzovsky 1792e41ab030SHarry Wentland if (!new_ctx) 1793e41ab030SHarry Wentland return DC_ERROR_UNEXPECTED; 1794e41ab030SHarry Wentland 1795d596e5d0SYongqiang Sun if (dc->res_pool->funcs->validate_global) { 1796d596e5d0SYongqiang Sun result = dc->res_pool->funcs->validate_global(dc, new_ctx); 1797d596e5d0SYongqiang Sun if (result != DC_OK) 1798d596e5d0SYongqiang Sun return result; 1799d596e5d0SYongqiang Sun } 18001dc90497SAndrey Grodzovsky 1801e41ab030SHarry Wentland for (i = 0; i < new_ctx->stream_count; i++) { 18021dc90497SAndrey Grodzovsky struct dc_stream_state *stream = new_ctx->streams[i]; 18031dc90497SAndrey Grodzovsky 18041dc90497SAndrey Grodzovsky for (j = 0; j < dc->res_pool->pipe_count; j++) { 18051dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[j]; 18061dc90497SAndrey Grodzovsky 18071dc90497SAndrey Grodzovsky if (pipe_ctx->stream != stream) 18081dc90497SAndrey Grodzovsky continue; 18091dc90497SAndrey Grodzovsky 18101dc90497SAndrey Grodzovsky /* Switch to dp clock source only if there is 18111dc90497SAndrey Grodzovsky * no non dp stream that shares the same timing 18121dc90497SAndrey Grodzovsky * with the dp stream. 18131dc90497SAndrey Grodzovsky */ 18141dc90497SAndrey Grodzovsky if (dc_is_dp_signal(pipe_ctx->stream->signal) && 18151dc90497SAndrey Grodzovsky !find_pll_sharable_stream(stream, new_ctx)) { 18161dc90497SAndrey Grodzovsky 18179d0dcecdSHarry Wentland resource_unreference_clock_source( 18181dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 18191dc90497SAndrey Grodzovsky dc->res_pool, 18209d0dcecdSHarry Wentland pipe_ctx->clock_source); 18214a629536SHarry Wentland 18221dc90497SAndrey Grodzovsky pipe_ctx->clock_source = dc->res_pool->dp_clock_source; 18231dc90497SAndrey Grodzovsky resource_reference_clock_source( 18241dc90497SAndrey Grodzovsky &new_ctx->res_ctx, 18251dc90497SAndrey Grodzovsky dc->res_pool, 18261dc90497SAndrey Grodzovsky pipe_ctx->clock_source); 18271dc90497SAndrey Grodzovsky } 18281dc90497SAndrey Grodzovsky } 18291dc90497SAndrey Grodzovsky } 18301dc90497SAndrey Grodzovsky 18311dc90497SAndrey Grodzovsky result = resource_build_scaling_params_for_context(dc, new_ctx); 18321dc90497SAndrey Grodzovsky 18331dc90497SAndrey Grodzovsky if (result == DC_OK) 18341dc90497SAndrey Grodzovsky if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx)) 18351dc90497SAndrey Grodzovsky result = DC_FAIL_BANDWIDTH_VALIDATE; 18361dc90497SAndrey Grodzovsky 18371dc90497SAndrey Grodzovsky return result; 18381dc90497SAndrey Grodzovsky } 18391dc90497SAndrey Grodzovsky 18406e4d6beeSTony Cheng static void patch_gamut_packet_checksum( 18416e4d6beeSTony Cheng struct encoder_info_packet *gamut_packet) 18424562236bSHarry Wentland { 18434562236bSHarry Wentland /* For gamut we recalc checksum */ 18446e4d6beeSTony Cheng if (gamut_packet->valid) { 18454562236bSHarry Wentland uint8_t chk_sum = 0; 18464562236bSHarry Wentland uint8_t *ptr; 18474562236bSHarry Wentland uint8_t i; 18484562236bSHarry Wentland 18494562236bSHarry Wentland /*start of the Gamut data. */ 18506e4d6beeSTony Cheng ptr = &gamut_packet->sb[3]; 18514562236bSHarry Wentland 18526e4d6beeSTony Cheng for (i = 0; i <= gamut_packet->sb[1]; i++) 18534562236bSHarry Wentland chk_sum += ptr[i]; 18544562236bSHarry Wentland 18556e4d6beeSTony Cheng gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum); 18561646a6feSAndrew Wong } 18574562236bSHarry Wentland } 18584562236bSHarry Wentland 18594562236bSHarry Wentland static void set_avi_info_frame( 18606e4d6beeSTony Cheng struct encoder_info_packet *info_packet, 18614562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 18624562236bSHarry Wentland { 18630971c40eSHarry Wentland struct dc_stream_state *stream = pipe_ctx->stream; 18644562236bSHarry Wentland enum dc_color_space color_space = COLOR_SPACE_UNKNOWN; 18654562236bSHarry Wentland struct info_frame info_frame = { {0} }; 18664562236bSHarry Wentland uint32_t pixel_encoding = 0; 18674562236bSHarry Wentland enum scanning_type scan_type = SCANNING_TYPE_NODATA; 18684562236bSHarry Wentland enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA; 18694562236bSHarry Wentland bool itc = false; 187050e27654SZeyu Fan uint8_t itc_value = 0; 18714562236bSHarry Wentland uint8_t cn0_cn1 = 0; 187250e27654SZeyu Fan unsigned int cn0_cn1_value = 0; 18734562236bSHarry Wentland uint8_t *check_sum = NULL; 18744562236bSHarry Wentland uint8_t byte_index = 0; 1875e8d726b7SReza Amini union hdmi_info_packet *hdmi_info = &info_frame.avi_info_packet.info_packet_hdmi; 187650e27654SZeyu Fan union display_content_support support = {0}; 18774fa086b9SLeo (Sunpeng) Li unsigned int vic = pipe_ctx->stream->timing.vic; 187815e17335SCharlene Liu enum dc_timing_3d_format format; 18794562236bSHarry Wentland 18804fa086b9SLeo (Sunpeng) Li color_space = pipe_ctx->stream->output_color_space; 1881e5f2038eSCharlene Liu if (color_space == COLOR_SPACE_UNKNOWN) 18824fa086b9SLeo (Sunpeng) Li color_space = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ? 1883e5f2038eSCharlene Liu COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709; 18844562236bSHarry Wentland 18854562236bSHarry Wentland /* Initialize header */ 1886e8d726b7SReza Amini hdmi_info->bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI; 18874562236bSHarry Wentland /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall 18884562236bSHarry Wentland * not be used in HDMI 2.0 (Section 10.1) */ 1889e8d726b7SReza Amini hdmi_info->bits.header.version = 2; 1890e8d726b7SReza Amini hdmi_info->bits.header.length = HDMI_AVI_INFOFRAME_SIZE; 18914562236bSHarry Wentland 18924562236bSHarry Wentland /* 18934562236bSHarry Wentland * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built 18944562236bSHarry Wentland * according to HDMI 2.0 spec (Section 10.1) 18954562236bSHarry Wentland */ 18964562236bSHarry Wentland 18974fa086b9SLeo (Sunpeng) Li switch (stream->timing.pixel_encoding) { 18984562236bSHarry Wentland case PIXEL_ENCODING_YCBCR422: 18994562236bSHarry Wentland pixel_encoding = 1; 19004562236bSHarry Wentland break; 19014562236bSHarry Wentland 19024562236bSHarry Wentland case PIXEL_ENCODING_YCBCR444: 19034562236bSHarry Wentland pixel_encoding = 2; 19044562236bSHarry Wentland break; 19054562236bSHarry Wentland case PIXEL_ENCODING_YCBCR420: 19064562236bSHarry Wentland pixel_encoding = 3; 19074562236bSHarry Wentland break; 19084562236bSHarry Wentland 19094562236bSHarry Wentland case PIXEL_ENCODING_RGB: 19104562236bSHarry Wentland default: 19114562236bSHarry Wentland pixel_encoding = 0; 19124562236bSHarry Wentland } 19134562236bSHarry Wentland 19144562236bSHarry Wentland /* Y0_Y1_Y2 : The pixel encoding */ 19154562236bSHarry Wentland /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */ 1916e8d726b7SReza Amini hdmi_info->bits.Y0_Y1_Y2 = pixel_encoding; 19174562236bSHarry Wentland 19184562236bSHarry Wentland /* A0 = 1 Active Format Information valid */ 1919e8d726b7SReza Amini hdmi_info->bits.A0 = ACTIVE_FORMAT_VALID; 19204562236bSHarry Wentland 19214562236bSHarry Wentland /* B0, B1 = 3; Bar info data is valid */ 1922e8d726b7SReza Amini hdmi_info->bits.B0_B1 = BAR_INFO_BOTH_VALID; 19234562236bSHarry Wentland 1924e8d726b7SReza Amini hdmi_info->bits.SC0_SC1 = PICTURE_SCALING_UNIFORM; 19254562236bSHarry Wentland 19264562236bSHarry Wentland /* S0, S1 : Underscan / Overscan */ 19274562236bSHarry Wentland /* TODO: un-hardcode scan type */ 19284562236bSHarry Wentland scan_type = SCANNING_TYPE_UNDERSCAN; 1929e8d726b7SReza Amini hdmi_info->bits.S0_S1 = scan_type; 19304562236bSHarry Wentland 19314562236bSHarry Wentland /* C0, C1 : Colorimetry */ 19328fde5884SCharlene Liu if (color_space == COLOR_SPACE_YCBCR709 || 193315e17335SCharlene Liu color_space == COLOR_SPACE_YCBCR709_LIMITED) 1934e8d726b7SReza Amini hdmi_info->bits.C0_C1 = COLORIMETRY_ITU709; 19358fde5884SCharlene Liu else if (color_space == COLOR_SPACE_YCBCR601 || 19368fde5884SCharlene Liu color_space == COLOR_SPACE_YCBCR601_LIMITED) 1937e8d726b7SReza Amini hdmi_info->bits.C0_C1 = COLORIMETRY_ITU601; 19388fde5884SCharlene Liu else { 1939e8d726b7SReza Amini hdmi_info->bits.C0_C1 = COLORIMETRY_NO_DATA; 19408fde5884SCharlene Liu } 1941534db198SAmy Zhang if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE || 1942534db198SAmy Zhang color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE || 1943534db198SAmy Zhang color_space == COLOR_SPACE_2020_YCBCR) { 1944e8d726b7SReza Amini hdmi_info->bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR; 1945e8d726b7SReza Amini hdmi_info->bits.C0_C1 = COLORIMETRY_EXTENDED; 1946534db198SAmy Zhang } else if (color_space == COLOR_SPACE_ADOBERGB) { 1947e8d726b7SReza Amini hdmi_info->bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB; 1948e8d726b7SReza Amini hdmi_info->bits.C0_C1 = COLORIMETRY_EXTENDED; 1949534db198SAmy Zhang } 1950534db198SAmy Zhang 19514562236bSHarry Wentland /* TODO: un-hardcode aspect ratio */ 19524fa086b9SLeo (Sunpeng) Li aspect = stream->timing.aspect_ratio; 19534562236bSHarry Wentland 19544562236bSHarry Wentland switch (aspect) { 19554562236bSHarry Wentland case ASPECT_RATIO_4_3: 19564562236bSHarry Wentland case ASPECT_RATIO_16_9: 1957e8d726b7SReza Amini hdmi_info->bits.M0_M1 = aspect; 19584562236bSHarry Wentland break; 19594562236bSHarry Wentland 19604562236bSHarry Wentland case ASPECT_RATIO_NO_DATA: 19614562236bSHarry Wentland case ASPECT_RATIO_64_27: 19624562236bSHarry Wentland case ASPECT_RATIO_256_135: 19634562236bSHarry Wentland default: 1964e8d726b7SReza Amini hdmi_info->bits.M0_M1 = 0; 19654562236bSHarry Wentland } 19664562236bSHarry Wentland 19674562236bSHarry Wentland /* Active Format Aspect ratio - same as Picture Aspect Ratio. */ 1968e8d726b7SReza Amini hdmi_info->bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; 19694562236bSHarry Wentland 19704562236bSHarry Wentland /* TODO: un-hardcode cn0_cn1 and itc */ 197150e27654SZeyu Fan 19724562236bSHarry Wentland cn0_cn1 = 0; 197350e27654SZeyu Fan cn0_cn1_value = 0; 197450e27654SZeyu Fan 197550e27654SZeyu Fan itc = true; 197650e27654SZeyu Fan itc_value = 1; 197750e27654SZeyu Fan 19784fa086b9SLeo (Sunpeng) Li support = stream->sink->edid_caps.content_support; 19794562236bSHarry Wentland 19804562236bSHarry Wentland if (itc) { 198150e27654SZeyu Fan if (!support.bits.valid_content_type) { 198250e27654SZeyu Fan cn0_cn1_value = 0; 198350e27654SZeyu Fan } else { 198450e27654SZeyu Fan if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) { 198550e27654SZeyu Fan if (support.bits.graphics_content == 1) { 198650e27654SZeyu Fan cn0_cn1_value = 0; 198750e27654SZeyu Fan } 198850e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) { 198950e27654SZeyu Fan if (support.bits.photo_content == 1) { 199050e27654SZeyu Fan cn0_cn1_value = 1; 199150e27654SZeyu Fan } else { 199250e27654SZeyu Fan cn0_cn1_value = 0; 199350e27654SZeyu Fan itc_value = 0; 199450e27654SZeyu Fan } 199550e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) { 199650e27654SZeyu Fan if (support.bits.cinema_content == 1) { 199750e27654SZeyu Fan cn0_cn1_value = 2; 199850e27654SZeyu Fan } else { 199950e27654SZeyu Fan cn0_cn1_value = 0; 200050e27654SZeyu Fan itc_value = 0; 200150e27654SZeyu Fan } 200250e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) { 200350e27654SZeyu Fan if (support.bits.game_content == 1) { 200450e27654SZeyu Fan cn0_cn1_value = 3; 200550e27654SZeyu Fan } else { 200650e27654SZeyu Fan cn0_cn1_value = 0; 200750e27654SZeyu Fan itc_value = 0; 200850e27654SZeyu Fan } 200950e27654SZeyu Fan } 201050e27654SZeyu Fan } 201150e27654SZeyu Fan hdmi_info->bits.CN0_CN1 = cn0_cn1_value; 201250e27654SZeyu Fan hdmi_info->bits.ITC = itc_value; 20134562236bSHarry Wentland } 20144562236bSHarry Wentland 20154562236bSHarry Wentland /* TODO : We should handle YCC quantization */ 20164562236bSHarry Wentland /* but we do not have matrix calculation */ 20174fa086b9SLeo (Sunpeng) Li if (stream->sink->edid_caps.qs_bit == 1 && 20184fa086b9SLeo (Sunpeng) Li stream->sink->edid_caps.qy_bit == 1) { 201950e27654SZeyu Fan if (color_space == COLOR_SPACE_SRGB || 202050e27654SZeyu Fan color_space == COLOR_SPACE_2020_RGB_FULLRANGE) { 2021e8d726b7SReza Amini hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; 2022e8d726b7SReza Amini hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_FULL_RANGE; 202350e27654SZeyu Fan } else if (color_space == COLOR_SPACE_SRGB_LIMITED || 202450e27654SZeyu Fan color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) { 2025e8d726b7SReza Amini hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE; 2026e8d726b7SReza Amini hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 20274562236bSHarry Wentland } else { 2028e8d726b7SReza Amini hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 2029e8d726b7SReza Amini hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 20304562236bSHarry Wentland } 203150e27654SZeyu Fan } else { 203250e27654SZeyu Fan hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 203350e27654SZeyu Fan hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 203450e27654SZeyu Fan } 203550e27654SZeyu Fan 203615e17335SCharlene Liu ///VIC 20374fa086b9SLeo (Sunpeng) Li format = stream->timing.timing_3d_format; 203815e17335SCharlene Liu /*todo, add 3DStereo support*/ 203915e17335SCharlene Liu if (format != TIMING_3D_FORMAT_NONE) { 204015e17335SCharlene Liu // Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled 20414fa086b9SLeo (Sunpeng) Li switch (pipe_ctx->stream->timing.hdmi_vic) { 204215e17335SCharlene Liu case 1: 204315e17335SCharlene Liu vic = 95; 204415e17335SCharlene Liu break; 204515e17335SCharlene Liu case 2: 204615e17335SCharlene Liu vic = 94; 204715e17335SCharlene Liu break; 204815e17335SCharlene Liu case 3: 204915e17335SCharlene Liu vic = 93; 205015e17335SCharlene Liu break; 205115e17335SCharlene Liu case 4: 205215e17335SCharlene Liu vic = 98; 205315e17335SCharlene Liu break; 205415e17335SCharlene Liu default: 205515e17335SCharlene Liu break; 205615e17335SCharlene Liu } 205715e17335SCharlene Liu } 205815e17335SCharlene Liu hdmi_info->bits.VIC0_VIC7 = vic; 20594562236bSHarry Wentland 20604562236bSHarry Wentland /* pixel repetition 20614562236bSHarry Wentland * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel 20624562236bSHarry Wentland * repetition start from 1 */ 2063e8d726b7SReza Amini hdmi_info->bits.PR0_PR3 = 0; 20644562236bSHarry Wentland 20654562236bSHarry Wentland /* Bar Info 20664562236bSHarry Wentland * barTop: Line Number of End of Top Bar. 20674562236bSHarry Wentland * barBottom: Line Number of Start of Bottom Bar. 20684562236bSHarry Wentland * barLeft: Pixel Number of End of Left Bar. 20694562236bSHarry Wentland * barRight: Pixel Number of Start of Right Bar. */ 20704fa086b9SLeo (Sunpeng) Li hdmi_info->bits.bar_top = stream->timing.v_border_top; 20714fa086b9SLeo (Sunpeng) Li hdmi_info->bits.bar_bottom = (stream->timing.v_total 20724fa086b9SLeo (Sunpeng) Li - stream->timing.v_border_bottom + 1); 20734fa086b9SLeo (Sunpeng) Li hdmi_info->bits.bar_left = stream->timing.h_border_left; 20744fa086b9SLeo (Sunpeng) Li hdmi_info->bits.bar_right = (stream->timing.h_total 20754fa086b9SLeo (Sunpeng) Li - stream->timing.h_border_right + 1); 20764562236bSHarry Wentland 20774562236bSHarry Wentland /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ 2078e8d726b7SReza Amini check_sum = &info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0]; 2079e8d726b7SReza Amini 20803e183c5fSDave Airlie *check_sum = HDMI_INFOFRAME_TYPE_AVI + HDMI_AVI_INFOFRAME_SIZE + 2; 20814562236bSHarry Wentland 20823e183c5fSDave Airlie for (byte_index = 1; byte_index <= HDMI_AVI_INFOFRAME_SIZE; byte_index++) 2083e8d726b7SReza Amini *check_sum += hdmi_info->packet_raw_data.sb[byte_index]; 20844562236bSHarry Wentland 20854562236bSHarry Wentland /* one byte complement */ 20864562236bSHarry Wentland *check_sum = (uint8_t) (0x100 - *check_sum); 20874562236bSHarry Wentland 20884562236bSHarry Wentland /* Store in hw_path_mode */ 2089e8d726b7SReza Amini info_packet->hb0 = hdmi_info->packet_raw_data.hb0; 2090e8d726b7SReza Amini info_packet->hb1 = hdmi_info->packet_raw_data.hb1; 2091e8d726b7SReza Amini info_packet->hb2 = hdmi_info->packet_raw_data.hb2; 20924562236bSHarry Wentland 2093e66e4d64SHarry Wentland for (byte_index = 0; byte_index < sizeof(info_frame.avi_info_packet. 2094e66e4d64SHarry Wentland info_packet_hdmi.packet_raw_data.sb); byte_index++) 20954562236bSHarry Wentland info_packet->sb[byte_index] = info_frame.avi_info_packet. 20964562236bSHarry Wentland info_packet_hdmi.packet_raw_data.sb[byte_index]; 20974562236bSHarry Wentland 20984562236bSHarry Wentland info_packet->valid = true; 20994562236bSHarry Wentland } 21004562236bSHarry Wentland 21016e4d6beeSTony Cheng static void set_vendor_info_packet( 21026e4d6beeSTony Cheng struct encoder_info_packet *info_packet, 21030971c40eSHarry Wentland struct dc_stream_state *stream) 21044562236bSHarry Wentland { 21054562236bSHarry Wentland uint32_t length = 0; 21064562236bSHarry Wentland bool hdmi_vic_mode = false; 21074562236bSHarry Wentland uint8_t checksum = 0; 21084562236bSHarry Wentland uint32_t i = 0; 21094562236bSHarry Wentland enum dc_timing_3d_format format; 211015e17335SCharlene Liu // Can be different depending on packet content /*todo*/ 211115e17335SCharlene Liu // unsigned int length = pPathMode->dolbyVision ? 24 : 5; 211215e17335SCharlene Liu 211315e17335SCharlene Liu info_packet->valid = false; 21144562236bSHarry Wentland 21154fa086b9SLeo (Sunpeng) Li format = stream->timing.timing_3d_format; 21164fa086b9SLeo (Sunpeng) Li if (stream->view_format == VIEW_3D_FORMAT_NONE) 21177f5c22d1SVitaly Prosyak format = TIMING_3D_FORMAT_NONE; 21184562236bSHarry Wentland 21194562236bSHarry Wentland /* Can be different depending on packet content */ 21204562236bSHarry Wentland length = 5; 21214562236bSHarry Wentland 21224fa086b9SLeo (Sunpeng) Li if (stream->timing.hdmi_vic != 0 21234fa086b9SLeo (Sunpeng) Li && stream->timing.h_total >= 3840 21244fa086b9SLeo (Sunpeng) Li && stream->timing.v_total >= 2160) 21254562236bSHarry Wentland hdmi_vic_mode = true; 21264562236bSHarry Wentland 21274562236bSHarry Wentland /* According to HDMI 1.4a CTS, VSIF should be sent 21284562236bSHarry Wentland * for both 3D stereo and HDMI VIC modes. 21294562236bSHarry Wentland * For all other modes, there is no VSIF sent. */ 21304562236bSHarry Wentland 21314562236bSHarry Wentland if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode) 21324562236bSHarry Wentland return; 21334562236bSHarry Wentland 21344562236bSHarry Wentland /* 24bit IEEE Registration identifier (0x000c03). LSB first. */ 21354562236bSHarry Wentland info_packet->sb[1] = 0x03; 21364562236bSHarry Wentland info_packet->sb[2] = 0x0C; 21374562236bSHarry Wentland info_packet->sb[3] = 0x00; 21384562236bSHarry Wentland 21394562236bSHarry Wentland /*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format. 21404562236bSHarry Wentland * The value for HDMI_Video_Format are: 21414562236bSHarry Wentland * 0x0 (0b000) - No additional HDMI video format is presented in this 21424562236bSHarry Wentland * packet 21434562236bSHarry Wentland * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC 21444562236bSHarry Wentland * parameter follows 21454562236bSHarry Wentland * 0x2 (0b010) - 3D format indication present. 3D_Structure and 21464562236bSHarry Wentland * potentially 3D_Ext_Data follows 21474562236bSHarry Wentland * 0x3..0x7 (0b011..0b111) - reserved for future use */ 21484562236bSHarry Wentland if (format != TIMING_3D_FORMAT_NONE) 21494562236bSHarry Wentland info_packet->sb[4] = (2 << 5); 21504562236bSHarry Wentland else if (hdmi_vic_mode) 21514562236bSHarry Wentland info_packet->sb[4] = (1 << 5); 21524562236bSHarry Wentland 21534562236bSHarry Wentland /* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2): 21544562236bSHarry Wentland * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure. 21554562236bSHarry Wentland * The value for 3D_Structure are: 21564562236bSHarry Wentland * 0x0 - Frame Packing 21574562236bSHarry Wentland * 0x1 - Field Alternative 21584562236bSHarry Wentland * 0x2 - Line Alternative 21594562236bSHarry Wentland * 0x3 - Side-by-Side (full) 21604562236bSHarry Wentland * 0x4 - L + depth 21614562236bSHarry Wentland * 0x5 - L + depth + graphics + graphics-depth 21624562236bSHarry Wentland * 0x6 - Top-and-Bottom 21634562236bSHarry Wentland * 0x7 - Reserved for future use 21644562236bSHarry Wentland * 0x8 - Side-by-Side (Half) 21654562236bSHarry Wentland * 0x9..0xE - Reserved for future use 21664562236bSHarry Wentland * 0xF - Not used */ 21674562236bSHarry Wentland switch (format) { 21684562236bSHarry Wentland case TIMING_3D_FORMAT_HW_FRAME_PACKING: 21694562236bSHarry Wentland case TIMING_3D_FORMAT_SW_FRAME_PACKING: 21704562236bSHarry Wentland info_packet->sb[5] = (0x0 << 4); 21714562236bSHarry Wentland break; 21724562236bSHarry Wentland 21734562236bSHarry Wentland case TIMING_3D_FORMAT_SIDE_BY_SIDE: 21744562236bSHarry Wentland case TIMING_3D_FORMAT_SBS_SW_PACKED: 21754562236bSHarry Wentland info_packet->sb[5] = (0x8 << 4); 21764562236bSHarry Wentland length = 6; 21774562236bSHarry Wentland break; 21784562236bSHarry Wentland 21794562236bSHarry Wentland case TIMING_3D_FORMAT_TOP_AND_BOTTOM: 21804562236bSHarry Wentland case TIMING_3D_FORMAT_TB_SW_PACKED: 21814562236bSHarry Wentland info_packet->sb[5] = (0x6 << 4); 21824562236bSHarry Wentland break; 21834562236bSHarry Wentland 21844562236bSHarry Wentland default: 21854562236bSHarry Wentland break; 21864562236bSHarry Wentland } 21874562236bSHarry Wentland 21884562236bSHarry Wentland /*PB5: If PB4 is set to 0x1 (extended resolution format) 21894562236bSHarry Wentland * fill PB5 with the correct HDMI VIC code */ 21904562236bSHarry Wentland if (hdmi_vic_mode) 21914fa086b9SLeo (Sunpeng) Li info_packet->sb[5] = stream->timing.hdmi_vic; 21924562236bSHarry Wentland 21934562236bSHarry Wentland /* Header */ 21943e183c5fSDave Airlie info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR; /* VSIF packet type. */ 21954562236bSHarry Wentland info_packet->hb1 = 0x01; /* Version */ 21964562236bSHarry Wentland 21974562236bSHarry Wentland /* 4 lower bits = Length, 4 higher bits = 0 (reserved) */ 21984562236bSHarry Wentland info_packet->hb2 = (uint8_t) (length); 21994562236bSHarry Wentland 22004562236bSHarry Wentland /* Calculate checksum */ 22014562236bSHarry Wentland checksum = 0; 22024562236bSHarry Wentland checksum += info_packet->hb0; 22034562236bSHarry Wentland checksum += info_packet->hb1; 22044562236bSHarry Wentland checksum += info_packet->hb2; 22054562236bSHarry Wentland 22064562236bSHarry Wentland for (i = 1; i <= length; i++) 22074562236bSHarry Wentland checksum += info_packet->sb[i]; 22084562236bSHarry Wentland 22094562236bSHarry Wentland info_packet->sb[0] = (uint8_t) (0x100 - checksum); 22104562236bSHarry Wentland 22114562236bSHarry Wentland info_packet->valid = true; 22124562236bSHarry Wentland } 22134562236bSHarry Wentland 22146e4d6beeSTony Cheng static void set_spd_info_packet( 22156e4d6beeSTony Cheng struct encoder_info_packet *info_packet, 22160971c40eSHarry Wentland struct dc_stream_state *stream) 22174562236bSHarry Wentland { 22184562236bSHarry Wentland /* SPD info packet for FreeSync */ 22194562236bSHarry Wentland 22204562236bSHarry Wentland unsigned char checksum = 0; 22214562236bSHarry Wentland unsigned int idx, payload_size = 0; 22224562236bSHarry Wentland 22234562236bSHarry Wentland /* Check if Freesync is supported. Return if false. If true, 22244562236bSHarry Wentland * set the corresponding bit in the info packet 22254562236bSHarry Wentland */ 22264fa086b9SLeo (Sunpeng) Li if (stream->freesync_ctx.supported == false) 22274562236bSHarry Wentland return; 22284562236bSHarry Wentland 22294562236bSHarry Wentland if (dc_is_hdmi_signal(stream->signal)) { 22304562236bSHarry Wentland 22314562236bSHarry Wentland /* HEADER */ 22324562236bSHarry Wentland 22334562236bSHarry Wentland /* HB0 = Packet Type = 0x83 (Source Product 22344562236bSHarry Wentland * Descriptor InfoFrame) 22354562236bSHarry Wentland */ 22363e183c5fSDave Airlie info_packet->hb0 = HDMI_INFOFRAME_TYPE_SPD; 22374562236bSHarry Wentland 22384562236bSHarry Wentland /* HB1 = Version = 0x01 */ 22394562236bSHarry Wentland info_packet->hb1 = 0x01; 22404562236bSHarry Wentland 22414562236bSHarry Wentland /* HB2 = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x08] */ 22424562236bSHarry Wentland info_packet->hb2 = 0x08; 22434562236bSHarry Wentland 22444562236bSHarry Wentland payload_size = 0x08; 22454562236bSHarry Wentland 22464562236bSHarry Wentland } else if (dc_is_dp_signal(stream->signal)) { 22474562236bSHarry Wentland 22484562236bSHarry Wentland /* HEADER */ 22494562236bSHarry Wentland 22504562236bSHarry Wentland /* HB0 = Secondary-data Packet ID = 0 - Only non-zero 22514562236bSHarry Wentland * when used to associate audio related info packets 22524562236bSHarry Wentland */ 22534562236bSHarry Wentland info_packet->hb0 = 0x00; 22544562236bSHarry Wentland 22554562236bSHarry Wentland /* HB1 = Packet Type = 0x83 (Source Product 22564562236bSHarry Wentland * Descriptor InfoFrame) 22574562236bSHarry Wentland */ 22583e183c5fSDave Airlie info_packet->hb1 = HDMI_INFOFRAME_TYPE_SPD; 22594562236bSHarry Wentland 22604562236bSHarry Wentland /* HB2 = [Bits 7:0 = Least significant eight bits - 22614562236bSHarry Wentland * For INFOFRAME, the value must be 1Bh] 22624562236bSHarry Wentland */ 22634562236bSHarry Wentland info_packet->hb2 = 0x1B; 22644562236bSHarry Wentland 22654562236bSHarry Wentland /* HB3 = [Bits 7:2 = INFOFRAME SDP Version Number = 0x1] 22664562236bSHarry Wentland * [Bits 1:0 = Most significant two bits = 0x00] 22674562236bSHarry Wentland */ 22684562236bSHarry Wentland info_packet->hb3 = 0x04; 22694562236bSHarry Wentland 22704562236bSHarry Wentland payload_size = 0x1B; 22714562236bSHarry Wentland } 22724562236bSHarry Wentland 22734562236bSHarry Wentland /* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */ 22744562236bSHarry Wentland info_packet->sb[1] = 0x1A; 22754562236bSHarry Wentland 22764562236bSHarry Wentland /* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */ 22774562236bSHarry Wentland info_packet->sb[2] = 0x00; 22784562236bSHarry Wentland 22794562236bSHarry Wentland /* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */ 22804562236bSHarry Wentland info_packet->sb[3] = 0x00; 22814562236bSHarry Wentland 22824562236bSHarry Wentland /* PB4 = Reserved */ 22834562236bSHarry Wentland info_packet->sb[4] = 0x00; 22844562236bSHarry Wentland 22854562236bSHarry Wentland /* PB5 = Reserved */ 22864562236bSHarry Wentland info_packet->sb[5] = 0x00; 22874562236bSHarry Wentland 22884562236bSHarry Wentland /* PB6 = [Bits 7:3 = Reserved] */ 22894562236bSHarry Wentland info_packet->sb[6] = 0x00; 22904562236bSHarry Wentland 22914fa086b9SLeo (Sunpeng) Li if (stream->freesync_ctx.supported == true) 22924562236bSHarry Wentland /* PB6 = [Bit 0 = FreeSync Supported] */ 22934562236bSHarry Wentland info_packet->sb[6] |= 0x01; 22944562236bSHarry Wentland 22954fa086b9SLeo (Sunpeng) Li if (stream->freesync_ctx.enabled == true) 22964562236bSHarry Wentland /* PB6 = [Bit 1 = FreeSync Enabled] */ 22974562236bSHarry Wentland info_packet->sb[6] |= 0x02; 22984562236bSHarry Wentland 22994fa086b9SLeo (Sunpeng) Li if (stream->freesync_ctx.active == true) 23004562236bSHarry Wentland /* PB6 = [Bit 2 = FreeSync Active] */ 23014562236bSHarry Wentland info_packet->sb[6] |= 0x04; 23024562236bSHarry Wentland 23034562236bSHarry Wentland /* PB7 = FreeSync Minimum refresh rate (Hz) */ 23044fa086b9SLeo (Sunpeng) Li info_packet->sb[7] = (unsigned char) (stream->freesync_ctx. 23054562236bSHarry Wentland min_refresh_in_micro_hz / 1000000); 23064562236bSHarry Wentland 23074562236bSHarry Wentland /* PB8 = FreeSync Maximum refresh rate (Hz) 23084562236bSHarry Wentland * 23094562236bSHarry Wentland * Note: We do not use the maximum capable refresh rate 23104562236bSHarry Wentland * of the panel, because we should never go above the field 23114562236bSHarry Wentland * rate of the mode timing set. 23124562236bSHarry Wentland */ 23134fa086b9SLeo (Sunpeng) Li info_packet->sb[8] = (unsigned char) (stream->freesync_ctx. 23144562236bSHarry Wentland nominal_refresh_in_micro_hz / 1000000); 23154562236bSHarry Wentland 23164562236bSHarry Wentland /* PB9 - PB27 = Reserved */ 23174562236bSHarry Wentland for (idx = 9; idx <= 27; idx++) 23184562236bSHarry Wentland info_packet->sb[idx] = 0x00; 23194562236bSHarry Wentland 23204562236bSHarry Wentland /* Calculate checksum */ 23214562236bSHarry Wentland checksum += info_packet->hb0; 23224562236bSHarry Wentland checksum += info_packet->hb1; 23234562236bSHarry Wentland checksum += info_packet->hb2; 23244562236bSHarry Wentland checksum += info_packet->hb3; 23254562236bSHarry Wentland 23264562236bSHarry Wentland for (idx = 1; idx <= payload_size; idx++) 23274562236bSHarry Wentland checksum += info_packet->sb[idx]; 23284562236bSHarry Wentland 23294562236bSHarry Wentland /* PB0 = Checksum (one byte complement) */ 23304562236bSHarry Wentland info_packet->sb[0] = (unsigned char) (0x100 - checksum); 23314562236bSHarry Wentland 23324562236bSHarry Wentland info_packet->valid = true; 23334562236bSHarry Wentland } 23344562236bSHarry Wentland 23351646a6feSAndrew Wong static void set_hdr_static_info_packet( 23366e4d6beeSTony Cheng struct encoder_info_packet *info_packet, 23370971c40eSHarry Wentland struct dc_stream_state *stream) 23381646a6feSAndrew Wong { 2339e5cf325bSHarry Wentland uint16_t i = 0; 23401646a6feSAndrew Wong enum signal_type signal = stream->signal; 2341e5cf325bSHarry Wentland uint32_t data; 23421646a6feSAndrew Wong 234356ef6ed9SAnthony Koo if (!stream->hdr_static_metadata.hdr_supported) 234410bff005SYongqiang Sun return; 234510bff005SYongqiang Sun 23461646a6feSAndrew Wong if (dc_is_hdmi_signal(signal)) { 23471646a6feSAndrew Wong info_packet->valid = true; 23481646a6feSAndrew Wong 23491646a6feSAndrew Wong info_packet->hb0 = 0x87; 23501646a6feSAndrew Wong info_packet->hb1 = 0x01; 23511646a6feSAndrew Wong info_packet->hb2 = 0x1A; 23521646a6feSAndrew Wong i = 1; 23531646a6feSAndrew Wong } else if (dc_is_dp_signal(signal)) { 23541646a6feSAndrew Wong info_packet->valid = true; 23551646a6feSAndrew Wong 23561646a6feSAndrew Wong info_packet->hb0 = 0x00; 23571646a6feSAndrew Wong info_packet->hb1 = 0x87; 23581646a6feSAndrew Wong info_packet->hb2 = 0x1D; 23591646a6feSAndrew Wong info_packet->hb3 = (0x13 << 2); 23601646a6feSAndrew Wong i = 2; 23611646a6feSAndrew Wong } 23621646a6feSAndrew Wong 236356ef6ed9SAnthony Koo data = stream->hdr_static_metadata.is_hdr; 23641646a6feSAndrew Wong info_packet->sb[i++] = data ? 0x02 : 0x00; 23651646a6feSAndrew Wong info_packet->sb[i++] = 0x00; 23661646a6feSAndrew Wong 236756ef6ed9SAnthony Koo data = stream->hdr_static_metadata.chromaticity_green_x / 2; 23681646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 23691646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 23701646a6feSAndrew Wong 237156ef6ed9SAnthony Koo data = stream->hdr_static_metadata.chromaticity_green_y / 2; 23721646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 23731646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 23741646a6feSAndrew Wong 237556ef6ed9SAnthony Koo data = stream->hdr_static_metadata.chromaticity_blue_x / 2; 23761646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 23771646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 23781646a6feSAndrew Wong 237956ef6ed9SAnthony Koo data = stream->hdr_static_metadata.chromaticity_blue_y / 2; 23801646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 23811646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 23821646a6feSAndrew Wong 238356ef6ed9SAnthony Koo data = stream->hdr_static_metadata.chromaticity_red_x / 2; 23841646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 23851646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 23861646a6feSAndrew Wong 238756ef6ed9SAnthony Koo data = stream->hdr_static_metadata.chromaticity_red_y / 2; 23881646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 23891646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 23901646a6feSAndrew Wong 239156ef6ed9SAnthony Koo data = stream->hdr_static_metadata.chromaticity_white_point_x / 2; 23921646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 23931646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 23941646a6feSAndrew Wong 239556ef6ed9SAnthony Koo data = stream->hdr_static_metadata.chromaticity_white_point_y / 2; 23961646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 23971646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 23981646a6feSAndrew Wong 239956ef6ed9SAnthony Koo data = stream->hdr_static_metadata.max_luminance; 24001646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 24011646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 24021646a6feSAndrew Wong 240356ef6ed9SAnthony Koo data = stream->hdr_static_metadata.min_luminance; 24041646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 24051646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 24061646a6feSAndrew Wong 240756ef6ed9SAnthony Koo data = stream->hdr_static_metadata.maximum_content_light_level; 24081646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 24091646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 24101646a6feSAndrew Wong 241156ef6ed9SAnthony Koo data = stream->hdr_static_metadata.maximum_frame_average_light_level; 24121646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 24131646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 24141646a6feSAndrew Wong 24151646a6feSAndrew Wong if (dc_is_hdmi_signal(signal)) { 24161646a6feSAndrew Wong uint32_t checksum = 0; 24171646a6feSAndrew Wong 24181646a6feSAndrew Wong checksum += info_packet->hb0; 24191646a6feSAndrew Wong checksum += info_packet->hb1; 24201646a6feSAndrew Wong checksum += info_packet->hb2; 24211646a6feSAndrew Wong 24221646a6feSAndrew Wong for (i = 1; i <= info_packet->hb2; i++) 24231646a6feSAndrew Wong checksum += info_packet->sb[i]; 24241646a6feSAndrew Wong 24251646a6feSAndrew Wong info_packet->sb[0] = 0x100 - checksum; 24261646a6feSAndrew Wong } else if (dc_is_dp_signal(signal)) { 24271646a6feSAndrew Wong info_packet->sb[0] = 0x01; 24281646a6feSAndrew Wong info_packet->sb[1] = 0x1A; 24291646a6feSAndrew Wong } 24301646a6feSAndrew Wong } 24311646a6feSAndrew Wong 24326e4d6beeSTony Cheng static void set_vsc_info_packet( 24336e4d6beeSTony Cheng struct encoder_info_packet *info_packet, 24340971c40eSHarry Wentland struct dc_stream_state *stream) 24354562236bSHarry Wentland { 24364562236bSHarry Wentland unsigned int vscPacketRevision = 0; 24374562236bSHarry Wentland unsigned int i; 24384562236bSHarry Wentland 24393b94a400STao /*VSC packet set to 2 when DP revision >= 1.2*/ 244085075fa0SXingyue Tao if (stream->psr_version != 0) { 24414562236bSHarry Wentland vscPacketRevision = 2; 24424562236bSHarry Wentland } 24434562236bSHarry Wentland 24444562236bSHarry Wentland /* VSC packet not needed based on the features 24454562236bSHarry Wentland * supported by this DP display 24464562236bSHarry Wentland */ 24474562236bSHarry Wentland if (vscPacketRevision == 0) 24484562236bSHarry Wentland return; 24494562236bSHarry Wentland 24504562236bSHarry Wentland if (vscPacketRevision == 0x2) { 24514562236bSHarry Wentland /* Secondary-data Packet ID = 0*/ 24524562236bSHarry Wentland info_packet->hb0 = 0x00; 24534562236bSHarry Wentland /* 07h - Packet Type Value indicating Video 24544562236bSHarry Wentland * Stream Configuration packet 24554562236bSHarry Wentland */ 24564562236bSHarry Wentland info_packet->hb1 = 0x07; 24574562236bSHarry Wentland /* 02h = VSC SDP supporting 3D stereo and PSR 24584562236bSHarry Wentland * (applies to eDP v1.3 or higher). 24594562236bSHarry Wentland */ 24604562236bSHarry Wentland info_packet->hb2 = 0x02; 24614562236bSHarry Wentland /* 08h = VSC packet supporting 3D stereo + PSR 24624562236bSHarry Wentland * (HB2 = 02h). 24634562236bSHarry Wentland */ 24644562236bSHarry Wentland info_packet->hb3 = 0x08; 24654562236bSHarry Wentland 24664562236bSHarry Wentland for (i = 0; i < 28; i++) 24674562236bSHarry Wentland info_packet->sb[i] = 0; 24684562236bSHarry Wentland 24694562236bSHarry Wentland info_packet->valid = true; 24704562236bSHarry Wentland } 24714562236bSHarry Wentland 24724562236bSHarry Wentland /*TODO: stereo 3D support and extend pixel encoding colorimetry*/ 24734562236bSHarry Wentland } 24744562236bSHarry Wentland 2475f36cc577SBhawanpreet Lakha void dc_resource_state_destruct(struct dc_state *context) 24764562236bSHarry Wentland { 24774562236bSHarry Wentland int i, j; 24784562236bSHarry Wentland 2479ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 24803be5262eSHarry Wentland for (j = 0; j < context->stream_status[i].plane_count; j++) 24813be5262eSHarry Wentland dc_plane_state_release( 24823be5262eSHarry Wentland context->stream_status[i].plane_states[j]); 24834562236bSHarry Wentland 24843be5262eSHarry Wentland context->stream_status[i].plane_count = 0; 24854fa086b9SLeo (Sunpeng) Li dc_stream_release(context->streams[i]); 2486ab2541b6SAric Cyr context->streams[i] = NULL; 24874562236bSHarry Wentland } 24884562236bSHarry Wentland } 24894562236bSHarry Wentland 24904562236bSHarry Wentland /* 2491ab2541b6SAric Cyr * Copy src_ctx into dst_ctx and retain all surfaces and streams referenced 24924562236bSHarry Wentland * by the src_ctx 24934562236bSHarry Wentland */ 2494f36cc577SBhawanpreet Lakha void dc_resource_state_copy_construct( 2495608ac7bbSJerry Zuo const struct dc_state *src_ctx, 2496608ac7bbSJerry Zuo struct dc_state *dst_ctx) 24974562236bSHarry Wentland { 24984562236bSHarry Wentland int i, j; 24998ee5702aSDave Airlie struct kref refcount = dst_ctx->refcount; 25004562236bSHarry Wentland 25014562236bSHarry Wentland *dst_ctx = *src_ctx; 25024562236bSHarry Wentland 2503a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 25044562236bSHarry Wentland struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i]; 25054562236bSHarry Wentland 25064562236bSHarry Wentland if (cur_pipe->top_pipe) 25074562236bSHarry Wentland cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; 25084562236bSHarry Wentland 25094562236bSHarry Wentland if (cur_pipe->bottom_pipe) 25104562236bSHarry Wentland cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; 25114562236bSHarry Wentland 25124562236bSHarry Wentland } 25134562236bSHarry Wentland 2514ab2541b6SAric Cyr for (i = 0; i < dst_ctx->stream_count; i++) { 25154fa086b9SLeo (Sunpeng) Li dc_stream_retain(dst_ctx->streams[i]); 25163be5262eSHarry Wentland for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++) 25173be5262eSHarry Wentland dc_plane_state_retain( 25183be5262eSHarry Wentland dst_ctx->stream_status[i].plane_states[j]); 25194562236bSHarry Wentland } 25209a3afbb3SAndrey Grodzovsky 25219a3afbb3SAndrey Grodzovsky /* context refcount should not be overridden */ 25228ee5702aSDave Airlie dst_ctx->refcount = refcount; 25239a3afbb3SAndrey Grodzovsky 25244562236bSHarry Wentland } 25254562236bSHarry Wentland 25264562236bSHarry Wentland struct clock_source *dc_resource_find_first_free_pll( 2527a2b8659dSTony Cheng struct resource_context *res_ctx, 2528a2b8659dSTony Cheng const struct resource_pool *pool) 25294562236bSHarry Wentland { 25304562236bSHarry Wentland int i; 25314562236bSHarry Wentland 2532a2b8659dSTony Cheng for (i = 0; i < pool->clk_src_count; ++i) { 25334562236bSHarry Wentland if (res_ctx->clock_source_ref_count[i] == 0) 2534a2b8659dSTony Cheng return pool->clock_sources[i]; 25354562236bSHarry Wentland } 25364562236bSHarry Wentland 25374562236bSHarry Wentland return NULL; 25384562236bSHarry Wentland } 25394562236bSHarry Wentland 25404562236bSHarry Wentland void resource_build_info_frame(struct pipe_ctx *pipe_ctx) 25414562236bSHarry Wentland { 25424562236bSHarry Wentland enum signal_type signal = SIGNAL_TYPE_NONE; 254396c50c0dSHarry Wentland struct encoder_info_frame *info = &pipe_ctx->stream_res.encoder_info_frame; 25444562236bSHarry Wentland 25454562236bSHarry Wentland /* default all packets to invalid */ 25466e4d6beeSTony Cheng info->avi.valid = false; 25476e4d6beeSTony Cheng info->gamut.valid = false; 25486e4d6beeSTony Cheng info->vendor.valid = false; 2549630e3573SJeff Smith info->spd.valid = false; 25506e4d6beeSTony Cheng info->hdrsmd.valid = false; 25516e4d6beeSTony Cheng info->vsc.valid = false; 25524562236bSHarry Wentland 25534562236bSHarry Wentland signal = pipe_ctx->stream->signal; 25544562236bSHarry Wentland 25554562236bSHarry Wentland /* HDMi and DP have different info packets*/ 25564562236bSHarry Wentland if (dc_is_hdmi_signal(signal)) { 25576e4d6beeSTony Cheng set_avi_info_frame(&info->avi, pipe_ctx); 25586e4d6beeSTony Cheng 25596e4d6beeSTony Cheng set_vendor_info_packet(&info->vendor, pipe_ctx->stream); 25606e4d6beeSTony Cheng 25616e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 25626e4d6beeSTony Cheng 256356ef6ed9SAnthony Koo set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 25646e4d6beeSTony Cheng 2565a33fa99dSHarry Wentland } else if (dc_is_dp_signal(signal)) { 25666e4d6beeSTony Cheng set_vsc_info_packet(&info->vsc, pipe_ctx->stream); 25676e4d6beeSTony Cheng 25686e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 25696e4d6beeSTony Cheng 257056ef6ed9SAnthony Koo set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 2571a33fa99dSHarry Wentland } 25724562236bSHarry Wentland 25736e4d6beeSTony Cheng patch_gamut_packet_checksum(&info->gamut); 25744562236bSHarry Wentland } 25754562236bSHarry Wentland 25764562236bSHarry Wentland enum dc_status resource_map_clock_resources( 2577fb3466a4SBhawanpreet Lakha const struct dc *dc, 2578608ac7bbSJerry Zuo struct dc_state *context, 25791dc90497SAndrey Grodzovsky struct dc_stream_state *stream) 25804562236bSHarry Wentland { 25814562236bSHarry Wentland /* acquire new resources */ 25821dc90497SAndrey Grodzovsky const struct resource_pool *pool = dc->res_pool; 25831dc90497SAndrey Grodzovsky struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream( 25841dc90497SAndrey Grodzovsky &context->res_ctx, stream); 25854562236bSHarry Wentland 25861dc90497SAndrey Grodzovsky if (!pipe_ctx) 25871dc90497SAndrey Grodzovsky return DC_ERROR_UNEXPECTED; 25884562236bSHarry Wentland 25894562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal) 25904562236bSHarry Wentland || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) 2591a2b8659dSTony Cheng pipe_ctx->clock_source = pool->dp_clock_source; 25924562236bSHarry Wentland else { 25934562236bSHarry Wentland pipe_ctx->clock_source = NULL; 25944562236bSHarry Wentland 2595fb3466a4SBhawanpreet Lakha if (!dc->config.disable_disp_pll_sharing) 25964ed4e51bSMikita Lipski pipe_ctx->clock_source = resource_find_used_clk_src_for_sharing( 25974562236bSHarry Wentland &context->res_ctx, 25984562236bSHarry Wentland pipe_ctx); 25994562236bSHarry Wentland 26004562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 26014562236bSHarry Wentland pipe_ctx->clock_source = 2602a2b8659dSTony Cheng dc_resource_find_first_free_pll( 2603a2b8659dSTony Cheng &context->res_ctx, 2604a2b8659dSTony Cheng pool); 26054562236bSHarry Wentland } 26064562236bSHarry Wentland 26074562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 26084562236bSHarry Wentland return DC_NO_CLOCK_SOURCE_RESOURCE; 26094562236bSHarry Wentland 26104562236bSHarry Wentland resource_reference_clock_source( 2611a2b8659dSTony Cheng &context->res_ctx, pool, 26124562236bSHarry Wentland pipe_ctx->clock_source); 26134562236bSHarry Wentland 26144562236bSHarry Wentland return DC_OK; 26154562236bSHarry Wentland } 26164562236bSHarry Wentland 26174562236bSHarry Wentland /* 26184562236bSHarry Wentland * Note: We need to disable output if clock sources change, 26194562236bSHarry Wentland * since bios does optimization and doesn't apply if changing 26204562236bSHarry Wentland * PHY when not already disabled. 26214562236bSHarry Wentland */ 26224562236bSHarry Wentland bool pipe_need_reprogram( 26234562236bSHarry Wentland struct pipe_ctx *pipe_ctx_old, 26244562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 26254562236bSHarry Wentland { 2626cfe4645eSDmytro Laktyushkin if (!pipe_ctx_old->stream) 2627cfe4645eSDmytro Laktyushkin return false; 2628cfe4645eSDmytro Laktyushkin 26294562236bSHarry Wentland if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink) 26304562236bSHarry Wentland return true; 26314562236bSHarry Wentland 26324562236bSHarry Wentland if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal) 26334562236bSHarry Wentland return true; 26344562236bSHarry Wentland 2635afaacef4SHarry Wentland if (pipe_ctx_old->stream_res.audio != pipe_ctx->stream_res.audio) 26364562236bSHarry Wentland return true; 26374562236bSHarry Wentland 26384562236bSHarry Wentland if (pipe_ctx_old->clock_source != pipe_ctx->clock_source 26394562236bSHarry Wentland && pipe_ctx_old->stream != pipe_ctx->stream) 26404562236bSHarry Wentland return true; 26414562236bSHarry Wentland 26428e9c4c8cSHarry Wentland if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc) 26434562236bSHarry Wentland return true; 26444562236bSHarry Wentland 26454562236bSHarry Wentland if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 26464562236bSHarry Wentland return true; 26474562236bSHarry Wentland 26484562236bSHarry Wentland 26494562236bSHarry Wentland return false; 26504562236bSHarry Wentland } 2651529cad0fSDing Wang 26520971c40eSHarry Wentland void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, 2653529cad0fSDing Wang struct bit_depth_reduction_params *fmt_bit_depth) 2654529cad0fSDing Wang { 26554fa086b9SLeo (Sunpeng) Li enum dc_dither_option option = stream->dither_option; 2656529cad0fSDing Wang enum dc_pixel_encoding pixel_encoding = 26574fa086b9SLeo (Sunpeng) Li stream->timing.pixel_encoding; 2658529cad0fSDing Wang 2659529cad0fSDing Wang memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); 2660529cad0fSDing Wang 2661603767f9STony Cheng if (option == DITHER_OPTION_DEFAULT) { 2662603767f9STony Cheng switch (stream->timing.display_color_depth) { 2663603767f9STony Cheng case COLOR_DEPTH_666: 2664603767f9STony Cheng option = DITHER_OPTION_SPATIAL6; 2665603767f9STony Cheng break; 2666603767f9STony Cheng case COLOR_DEPTH_888: 2667603767f9STony Cheng option = DITHER_OPTION_SPATIAL8; 2668603767f9STony Cheng break; 2669603767f9STony Cheng case COLOR_DEPTH_101010: 2670603767f9STony Cheng option = DITHER_OPTION_SPATIAL10; 2671603767f9STony Cheng break; 2672603767f9STony Cheng default: 2673603767f9STony Cheng option = DITHER_OPTION_DISABLE; 2674603767f9STony Cheng } 2675603767f9STony Cheng } 2676603767f9STony Cheng 2677529cad0fSDing Wang if (option == DITHER_OPTION_DISABLE) 2678529cad0fSDing Wang return; 2679529cad0fSDing Wang 2680529cad0fSDing Wang if (option == DITHER_OPTION_TRUN6) { 2681529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2682529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 0; 2683529cad0fSDing Wang } else if (option == DITHER_OPTION_TRUN8 || 2684529cad0fSDing Wang option == DITHER_OPTION_TRUN8_SPATIAL6 || 2685529cad0fSDing Wang option == DITHER_OPTION_TRUN8_FM6) { 2686529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2687529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 1; 2688529cad0fSDing Wang } else if (option == DITHER_OPTION_TRUN10 || 2689529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL6 || 2690529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8 || 2691529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM8 || 2692529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM6 || 2693529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2694529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2695529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2696529cad0fSDing Wang } 2697529cad0fSDing Wang 2698529cad0fSDing Wang /* special case - Formatter can only reduce by 4 bits at most. 2699529cad0fSDing Wang * When reducing from 12 to 6 bits, 2700529cad0fSDing Wang * HW recommends we use trunc with round mode 2701529cad0fSDing Wang * (if we did nothing, trunc to 10 bits would be used) 2702529cad0fSDing Wang * note that any 12->10 bit reduction is ignored prior to DCE8, 2703529cad0fSDing Wang * as the input was 10 bits. 2704529cad0fSDing Wang */ 2705529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2706529cad0fSDing Wang option == DITHER_OPTION_SPATIAL6 || 2707529cad0fSDing Wang option == DITHER_OPTION_FM6) { 2708529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2709529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2710529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_MODE = 1; 2711529cad0fSDing Wang } 2712529cad0fSDing Wang 2713529cad0fSDing Wang /* spatial dither 2714529cad0fSDing Wang * note that spatial modes 1-3 are never used 2715529cad0fSDing Wang */ 2716529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2717529cad0fSDing Wang option == DITHER_OPTION_SPATIAL6 || 2718529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL6 || 2719529cad0fSDing Wang option == DITHER_OPTION_TRUN8_SPATIAL6) { 2720529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2721529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0; 2722529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2723529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2724529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2725529cad0fSDing Wang } else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM || 2726529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8 || 2727529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8_FM6 || 2728529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8 || 2729529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2730529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2731529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1; 2732529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2733529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2734529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2735529cad0fSDing Wang } else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM || 2736529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10 || 2737529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM8 || 2738529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM6) { 2739529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2740529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2; 2741529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2742529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2743529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2744529cad0fSDing Wang } 2745529cad0fSDing Wang 2746529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6 || 2747529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8 || 2748529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10) { 2749529cad0fSDing Wang fmt_bit_depth->flags.FRAME_RANDOM = 0; 2750529cad0fSDing Wang } else { 2751529cad0fSDing Wang fmt_bit_depth->flags.FRAME_RANDOM = 1; 2752529cad0fSDing Wang } 2753529cad0fSDing Wang 2754529cad0fSDing Wang ////////////////////// 2755529cad0fSDing Wang //// temporal dither 2756529cad0fSDing Wang ////////////////////// 2757529cad0fSDing Wang if (option == DITHER_OPTION_FM6 || 2758529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8_FM6 || 2759529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM6 || 2760529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM6 || 2761529cad0fSDing Wang option == DITHER_OPTION_TRUN8_FM6 || 2762529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2763529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2764529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0; 2765529cad0fSDing Wang } else if (option == DITHER_OPTION_FM8 || 2766529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM8 || 2767529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM8) { 2768529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2769529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1; 2770529cad0fSDing Wang } else if (option == DITHER_OPTION_FM10) { 2771529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2772529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2; 2773529cad0fSDing Wang } 2774529cad0fSDing Wang 2775529cad0fSDing Wang fmt_bit_depth->pixel_encoding = pixel_encoding; 2776529cad0fSDing Wang } 27779345d987SAndrey Grodzovsky 277862c933f9SYongqiang Sun enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) 27799345d987SAndrey Grodzovsky { 2780fb3466a4SBhawanpreet Lakha struct dc *core_dc = dc; 27814fa086b9SLeo (Sunpeng) Li struct dc_link *link = stream->sink->link; 27829345d987SAndrey Grodzovsky struct timing_generator *tg = core_dc->res_pool->timing_generators[0]; 27839345d987SAndrey Grodzovsky enum dc_status res = DC_OK; 27849345d987SAndrey Grodzovsky 27854fa086b9SLeo (Sunpeng) Li calculate_phy_pix_clks(stream); 27869345d987SAndrey Grodzovsky 27874fa086b9SLeo (Sunpeng) Li if (!tg->funcs->validate_timing(tg, &stream->timing)) 27889345d987SAndrey Grodzovsky res = DC_FAIL_CONTROLLER_VALIDATE; 27899345d987SAndrey Grodzovsky 27909345d987SAndrey Grodzovsky if (res == DC_OK) 27919345d987SAndrey Grodzovsky if (!link->link_enc->funcs->validate_output_with_stream( 27924fa086b9SLeo (Sunpeng) Li link->link_enc, stream)) 27939345d987SAndrey Grodzovsky res = DC_FAIL_ENC_VALIDATE; 27949345d987SAndrey Grodzovsky 27959345d987SAndrey Grodzovsky /* TODO: validate audio ASIC caps, encoder */ 27969345d987SAndrey Grodzovsky 27979345d987SAndrey Grodzovsky if (res == DC_OK) 27984fa086b9SLeo (Sunpeng) Li res = dc_link_validate_mode_timing(stream, 27999345d987SAndrey Grodzovsky link, 28004fa086b9SLeo (Sunpeng) Li &stream->timing); 28019345d987SAndrey Grodzovsky 280262c933f9SYongqiang Sun return res; 28039345d987SAndrey Grodzovsky } 2804792671d7SAndrey Grodzovsky 280562c933f9SYongqiang Sun enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) 2806792671d7SAndrey Grodzovsky { 280762c933f9SYongqiang Sun enum dc_status res = DC_OK; 280862c933f9SYongqiang Sun 2809792671d7SAndrey Grodzovsky /* TODO For now validates pixel format only */ 28108e7095b9SDmytro Laktyushkin if (dc->res_pool->funcs->validate_plane) 281162c933f9SYongqiang Sun return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps); 2812792671d7SAndrey Grodzovsky 281362c933f9SYongqiang Sun return res; 2814792671d7SAndrey Grodzovsky } 2815