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" 345ac3d3c9SCharlene Liu #include "core_types.h" 354562236bSHarry Wentland #include "set_mode_types.h" 364562236bSHarry Wentland #include "virtual/virtual_stream_encoder.h" 374562236bSHarry Wentland 384562236bSHarry Wentland #include "dce80/dce80_resource.h" 394562236bSHarry Wentland #include "dce100/dce100_resource.h" 404562236bSHarry Wentland #include "dce110/dce110_resource.h" 414562236bSHarry Wentland #include "dce112/dce112_resource.h" 42ff5ef992SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 43ff5ef992SAlex Deucher #include "dcn10/dcn10_resource.h" 44ff5ef992SAlex Deucher #endif 452c8ad2d5SAlex Deucher #include "dce120/dce120_resource.h" 464562236bSHarry Wentland 474562236bSHarry Wentland enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) 484562236bSHarry Wentland { 494562236bSHarry Wentland enum dce_version dc_version = DCE_VERSION_UNKNOWN; 504562236bSHarry Wentland switch (asic_id.chip_family) { 514562236bSHarry Wentland 524562236bSHarry Wentland case FAMILY_CI: 534562236bSHarry Wentland case FAMILY_KV: 544562236bSHarry Wentland dc_version = DCE_VERSION_8_0; 554562236bSHarry Wentland break; 564562236bSHarry Wentland case FAMILY_CZ: 574562236bSHarry Wentland dc_version = DCE_VERSION_11_0; 584562236bSHarry Wentland break; 594562236bSHarry Wentland 604562236bSHarry Wentland case FAMILY_VI: 614562236bSHarry Wentland if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) || 624562236bSHarry Wentland ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) { 634562236bSHarry Wentland dc_version = DCE_VERSION_10_0; 644562236bSHarry Wentland break; 654562236bSHarry Wentland } 664562236bSHarry Wentland if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) || 67b264d345SJordan Lazare ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || 68b264d345SJordan Lazare ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) { 694562236bSHarry Wentland dc_version = DCE_VERSION_11_2; 704562236bSHarry Wentland } 714562236bSHarry Wentland break; 722c8ad2d5SAlex Deucher case FAMILY_AI: 732c8ad2d5SAlex Deucher dc_version = DCE_VERSION_12_0; 742c8ad2d5SAlex Deucher break; 75ff5ef992SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 76ff5ef992SAlex Deucher case FAMILY_RV: 77ff5ef992SAlex Deucher dc_version = DCN_VERSION_1_0; 78ff5ef992SAlex Deucher break; 79ff5ef992SAlex Deucher #endif 804562236bSHarry Wentland default: 814562236bSHarry Wentland dc_version = DCE_VERSION_UNKNOWN; 824562236bSHarry Wentland break; 834562236bSHarry Wentland } 844562236bSHarry Wentland return dc_version; 854562236bSHarry Wentland } 864562236bSHarry Wentland 874562236bSHarry Wentland struct resource_pool *dc_create_resource_pool( 884562236bSHarry Wentland struct core_dc *dc, 894562236bSHarry Wentland int num_virtual_links, 904562236bSHarry Wentland enum dce_version dc_version, 914562236bSHarry Wentland struct hw_asic_id asic_id) 924562236bSHarry Wentland { 935ac3d3c9SCharlene Liu struct resource_pool *res_pool = NULL; 944562236bSHarry Wentland 954562236bSHarry Wentland switch (dc_version) { 964562236bSHarry Wentland case DCE_VERSION_8_0: 975ac3d3c9SCharlene Liu res_pool = dce80_create_resource_pool( 984562236bSHarry Wentland num_virtual_links, dc); 995ac3d3c9SCharlene Liu break; 1004562236bSHarry Wentland case DCE_VERSION_10_0: 1015ac3d3c9SCharlene Liu res_pool = dce100_create_resource_pool( 1024562236bSHarry Wentland num_virtual_links, dc); 1035ac3d3c9SCharlene Liu break; 1044562236bSHarry Wentland case DCE_VERSION_11_0: 1055ac3d3c9SCharlene Liu res_pool = dce110_create_resource_pool( 1064562236bSHarry Wentland num_virtual_links, dc, asic_id); 1075ac3d3c9SCharlene Liu break; 1084562236bSHarry Wentland case DCE_VERSION_11_2: 1095ac3d3c9SCharlene Liu res_pool = dce112_create_resource_pool( 1104562236bSHarry Wentland num_virtual_links, dc); 1115ac3d3c9SCharlene Liu break; 1122c8ad2d5SAlex Deucher case DCE_VERSION_12_0: 1132c8ad2d5SAlex Deucher res_pool = dce120_create_resource_pool( 1142c8ad2d5SAlex Deucher num_virtual_links, dc); 1152c8ad2d5SAlex Deucher break; 116ff5ef992SAlex Deucher 117ff5ef992SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 118ff5ef992SAlex Deucher case DCN_VERSION_1_0: 119ff5ef992SAlex Deucher res_pool = dcn10_create_resource_pool( 120ff5ef992SAlex Deucher num_virtual_links, dc); 121ff5ef992SAlex Deucher break; 122ff5ef992SAlex Deucher #endif 1233639fa68SZeyu Fan 1243639fa68SZeyu Fan 1254562236bSHarry Wentland default: 1264562236bSHarry Wentland break; 1274562236bSHarry Wentland } 1285ac3d3c9SCharlene Liu if (res_pool != NULL) { 1291515a47bSHarry Wentland struct dc_firmware_info fw_info = { { 0 } }; 1304562236bSHarry Wentland 1315ac3d3c9SCharlene Liu if (dc->ctx->dc_bios->funcs->get_firmware_info( 1325ac3d3c9SCharlene Liu dc->ctx->dc_bios, &fw_info) == BP_RESULT_OK) { 1335ac3d3c9SCharlene Liu res_pool->ref_clock_inKhz = fw_info.pll_info.crystal_frequency; 1345ac3d3c9SCharlene Liu } else 1355ac3d3c9SCharlene Liu ASSERT_CRITICAL(false); 1365ac3d3c9SCharlene Liu } 1375ac3d3c9SCharlene Liu 1385ac3d3c9SCharlene Liu return res_pool; 1394562236bSHarry Wentland } 1404562236bSHarry Wentland 1414562236bSHarry Wentland void dc_destroy_resource_pool(struct core_dc *dc) 1424562236bSHarry Wentland { 1434562236bSHarry Wentland if (dc) { 1444562236bSHarry Wentland if (dc->res_pool) 1454562236bSHarry Wentland dc->res_pool->funcs->destroy(&dc->res_pool); 1464562236bSHarry Wentland 1474562236bSHarry Wentland if (dc->hwseq) 1484562236bSHarry Wentland dm_free(dc->hwseq); 1494562236bSHarry Wentland } 1504562236bSHarry Wentland } 1514562236bSHarry Wentland 1524562236bSHarry Wentland static void update_num_audio( 1534562236bSHarry Wentland const struct resource_straps *straps, 1544562236bSHarry Wentland unsigned int *num_audio, 1554562236bSHarry Wentland struct audio_support *aud_support) 1564562236bSHarry Wentland { 1574562236bSHarry Wentland if (straps->hdmi_disable == 0) { 1584562236bSHarry Wentland aud_support->hdmi_audio_native = true; 1594562236bSHarry Wentland aud_support->hdmi_audio_on_dongle = true; 1604562236bSHarry Wentland aud_support->dp_audio = true; 1614562236bSHarry Wentland } else { 1624562236bSHarry Wentland if (straps->dc_pinstraps_audio & 0x2) { 1634562236bSHarry Wentland aud_support->hdmi_audio_on_dongle = true; 1644562236bSHarry Wentland aud_support->dp_audio = true; 1654562236bSHarry Wentland } else { 1664562236bSHarry Wentland aud_support->dp_audio = true; 1674562236bSHarry Wentland } 1684562236bSHarry Wentland } 1694562236bSHarry Wentland 1704562236bSHarry Wentland switch (straps->audio_stream_number) { 1714562236bSHarry Wentland case 0: /* multi streams supported */ 1724562236bSHarry Wentland break; 1734562236bSHarry Wentland case 1: /* multi streams not supported */ 1744562236bSHarry Wentland *num_audio = 1; 1754562236bSHarry Wentland break; 1764562236bSHarry Wentland default: 1774562236bSHarry Wentland DC_ERR("DC: unexpected audio fuse!\n"); 17817a96033SJulia Lawall } 1794562236bSHarry Wentland } 1804562236bSHarry Wentland 1814562236bSHarry Wentland bool resource_construct( 1824562236bSHarry Wentland unsigned int num_virtual_links, 1834562236bSHarry Wentland struct core_dc *dc, 1844562236bSHarry Wentland struct resource_pool *pool, 1854562236bSHarry Wentland const struct resource_create_funcs *create_funcs) 1864562236bSHarry Wentland { 1874562236bSHarry Wentland struct dc_context *ctx = dc->ctx; 1884562236bSHarry Wentland const struct resource_caps *caps = pool->res_cap; 1894562236bSHarry Wentland int i; 1904562236bSHarry Wentland unsigned int num_audio = caps->num_audio; 1914562236bSHarry Wentland struct resource_straps straps = {0}; 1924562236bSHarry Wentland 1934562236bSHarry Wentland if (create_funcs->read_dce_straps) 1944562236bSHarry Wentland create_funcs->read_dce_straps(dc->ctx, &straps); 1954562236bSHarry Wentland 1964562236bSHarry Wentland pool->audio_count = 0; 1974562236bSHarry Wentland if (create_funcs->create_audio) { 1984562236bSHarry Wentland /* find the total number of streams available via the 1994562236bSHarry Wentland * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT 2004562236bSHarry Wentland * registers (one for each pin) starting from pin 1 2014562236bSHarry Wentland * up to the max number of audio pins. 2024562236bSHarry Wentland * We stop on the first pin where 2034562236bSHarry Wentland * PORT_CONNECTIVITY == 1 (as instructed by HW team). 2044562236bSHarry Wentland */ 2054562236bSHarry Wentland update_num_audio(&straps, &num_audio, &pool->audio_support); 2064562236bSHarry Wentland for (i = 0; i < pool->pipe_count && i < num_audio; i++) { 2074562236bSHarry Wentland struct audio *aud = create_funcs->create_audio(ctx, i); 2084562236bSHarry Wentland 2094562236bSHarry Wentland if (aud == NULL) { 2104562236bSHarry Wentland DC_ERR("DC: failed to create audio!\n"); 2114562236bSHarry Wentland return false; 2124562236bSHarry Wentland } 2134562236bSHarry Wentland 2144562236bSHarry Wentland if (!aud->funcs->endpoint_valid(aud)) { 2154562236bSHarry Wentland aud->funcs->destroy(&aud); 2164562236bSHarry Wentland break; 2174562236bSHarry Wentland } 2184562236bSHarry Wentland 2194562236bSHarry Wentland pool->audios[i] = aud; 2204562236bSHarry Wentland pool->audio_count++; 2214562236bSHarry Wentland } 2224562236bSHarry Wentland } 2234562236bSHarry Wentland 2244562236bSHarry Wentland pool->stream_enc_count = 0; 2254562236bSHarry Wentland if (create_funcs->create_stream_encoder) { 2264562236bSHarry Wentland for (i = 0; i < caps->num_stream_encoder; i++) { 2274562236bSHarry Wentland pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx); 2284562236bSHarry Wentland if (pool->stream_enc[i] == NULL) 2294562236bSHarry Wentland DC_ERR("DC: failed to create stream_encoder!\n"); 2304562236bSHarry Wentland pool->stream_enc_count++; 2314562236bSHarry Wentland } 2324562236bSHarry Wentland } 2334562236bSHarry Wentland 2344562236bSHarry Wentland for (i = 0; i < num_virtual_links; i++) { 2354562236bSHarry Wentland pool->stream_enc[pool->stream_enc_count] = 2364562236bSHarry Wentland virtual_stream_encoder_create( 2374562236bSHarry Wentland ctx, ctx->dc_bios); 2384562236bSHarry Wentland if (pool->stream_enc[pool->stream_enc_count] == NULL) { 2394562236bSHarry Wentland DC_ERR("DC: failed to create stream_encoder!\n"); 2404562236bSHarry Wentland return false; 2414562236bSHarry Wentland } 2424562236bSHarry Wentland pool->stream_enc_count++; 2434562236bSHarry Wentland } 2444562236bSHarry Wentland 2454562236bSHarry Wentland dc->hwseq = create_funcs->create_hwseq(ctx); 2464562236bSHarry Wentland 2474562236bSHarry Wentland return true; 2484562236bSHarry Wentland } 2494562236bSHarry Wentland 2504562236bSHarry Wentland 2514562236bSHarry Wentland void resource_unreference_clock_source( 2524562236bSHarry Wentland struct resource_context *res_ctx, 253a2b8659dSTony Cheng const struct resource_pool *pool, 2548c737fccSYongqiang Sun struct clock_source **clock_source) 2554562236bSHarry Wentland { 2564562236bSHarry Wentland int i; 257a2b8659dSTony Cheng for (i = 0; i < pool->clk_src_count; i++) { 258a2b8659dSTony Cheng if (pool->clock_sources[i] != *clock_source) 2594562236bSHarry Wentland continue; 2604562236bSHarry Wentland 2614562236bSHarry Wentland res_ctx->clock_source_ref_count[i]--; 2624562236bSHarry Wentland 2634562236bSHarry Wentland if (res_ctx->clock_source_ref_count[i] == 0) 2648c737fccSYongqiang Sun (*clock_source)->funcs->cs_power_down(*clock_source); 2654562236bSHarry Wentland 2664562236bSHarry Wentland break; 2674562236bSHarry Wentland } 2684562236bSHarry Wentland 269a2b8659dSTony Cheng if (pool->dp_clock_source == *clock_source) { 2704562236bSHarry Wentland res_ctx->dp_clock_source_ref_count--; 2714562236bSHarry Wentland 2724562236bSHarry Wentland if (res_ctx->dp_clock_source_ref_count == 0) 2738c737fccSYongqiang Sun (*clock_source)->funcs->cs_power_down(*clock_source); 2744562236bSHarry Wentland } 2758c737fccSYongqiang Sun *clock_source = NULL; 2764562236bSHarry Wentland } 2774562236bSHarry Wentland 2784562236bSHarry Wentland void resource_reference_clock_source( 2794562236bSHarry Wentland struct resource_context *res_ctx, 280a2b8659dSTony Cheng const struct resource_pool *pool, 2814562236bSHarry Wentland struct clock_source *clock_source) 2824562236bSHarry Wentland { 2834562236bSHarry Wentland int i; 284a2b8659dSTony Cheng for (i = 0; i < pool->clk_src_count; i++) { 285a2b8659dSTony Cheng if (pool->clock_sources[i] != clock_source) 2864562236bSHarry Wentland continue; 2874562236bSHarry Wentland 2884562236bSHarry Wentland res_ctx->clock_source_ref_count[i]++; 2894562236bSHarry Wentland break; 2904562236bSHarry Wentland } 2914562236bSHarry Wentland 292a2b8659dSTony Cheng if (pool->dp_clock_source == clock_source) 2934562236bSHarry Wentland res_ctx->dp_clock_source_ref_count++; 2944562236bSHarry Wentland } 2954562236bSHarry Wentland 2964562236bSHarry Wentland bool resource_are_streams_timing_synchronizable( 2970971c40eSHarry Wentland struct dc_stream_state *stream1, 2980971c40eSHarry Wentland struct dc_stream_state *stream2) 2994562236bSHarry Wentland { 3004fa086b9SLeo (Sunpeng) Li if (stream1->timing.h_total != stream2->timing.h_total) 3014562236bSHarry Wentland return false; 3024562236bSHarry Wentland 3034fa086b9SLeo (Sunpeng) Li if (stream1->timing.v_total != stream2->timing.v_total) 3044562236bSHarry Wentland return false; 3054562236bSHarry Wentland 3064fa086b9SLeo (Sunpeng) Li if (stream1->timing.h_addressable 3074fa086b9SLeo (Sunpeng) Li != stream2->timing.h_addressable) 3084562236bSHarry Wentland return false; 3094562236bSHarry Wentland 3104fa086b9SLeo (Sunpeng) Li if (stream1->timing.v_addressable 3114fa086b9SLeo (Sunpeng) Li != stream2->timing.v_addressable) 3124562236bSHarry Wentland return false; 3134562236bSHarry Wentland 3144fa086b9SLeo (Sunpeng) Li if (stream1->timing.pix_clk_khz 3154fa086b9SLeo (Sunpeng) Li != stream2->timing.pix_clk_khz) 3164562236bSHarry Wentland return false; 3174562236bSHarry Wentland 3184562236bSHarry Wentland if (stream1->phy_pix_clk != stream2->phy_pix_clk 3197e2fe319SCharlene Liu && (!dc_is_dp_signal(stream1->signal) 3207e2fe319SCharlene Liu || !dc_is_dp_signal(stream2->signal))) 3214562236bSHarry Wentland return false; 3224562236bSHarry Wentland 3234562236bSHarry Wentland return true; 3244562236bSHarry Wentland } 3254562236bSHarry Wentland 3264562236bSHarry Wentland static bool is_sharable_clk_src( 3274562236bSHarry Wentland const struct pipe_ctx *pipe_with_clk_src, 3284562236bSHarry Wentland const struct pipe_ctx *pipe) 3294562236bSHarry Wentland { 3304562236bSHarry Wentland if (pipe_with_clk_src->clock_source == NULL) 3314562236bSHarry Wentland return false; 3324562236bSHarry Wentland 3334562236bSHarry Wentland if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL) 3344562236bSHarry Wentland return false; 3354562236bSHarry Wentland 3364562236bSHarry Wentland if (dc_is_dp_signal(pipe_with_clk_src->stream->signal)) 3374562236bSHarry Wentland return false; 3384562236bSHarry Wentland 3394562236bSHarry Wentland if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal) 3404562236bSHarry Wentland && dc_is_dvi_signal(pipe->stream->signal)) 3414562236bSHarry Wentland return false; 3424562236bSHarry Wentland 3434562236bSHarry Wentland if (dc_is_hdmi_signal(pipe->stream->signal) 3444562236bSHarry Wentland && dc_is_dvi_signal(pipe_with_clk_src->stream->signal)) 3454562236bSHarry Wentland return false; 3464562236bSHarry Wentland 3474562236bSHarry Wentland if (!resource_are_streams_timing_synchronizable( 3484562236bSHarry Wentland pipe_with_clk_src->stream, pipe->stream)) 3494562236bSHarry Wentland return false; 3504562236bSHarry Wentland 3514562236bSHarry Wentland return true; 3524562236bSHarry Wentland } 3534562236bSHarry Wentland 3544562236bSHarry Wentland struct clock_source *resource_find_used_clk_src_for_sharing( 3554562236bSHarry Wentland struct resource_context *res_ctx, 3564562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 3574562236bSHarry Wentland { 3584562236bSHarry Wentland int i; 3594562236bSHarry Wentland 3604562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 3614562236bSHarry Wentland if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx)) 3624562236bSHarry Wentland return res_ctx->pipe_ctx[i].clock_source; 3634562236bSHarry Wentland } 3644562236bSHarry Wentland 3654562236bSHarry Wentland return NULL; 3664562236bSHarry Wentland } 3674562236bSHarry Wentland 3684562236bSHarry Wentland static enum pixel_format convert_pixel_format_to_dalsurface( 3694562236bSHarry Wentland enum surface_pixel_format surface_pixel_format) 3704562236bSHarry Wentland { 3714562236bSHarry Wentland enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 3724562236bSHarry Wentland 3734562236bSHarry Wentland switch (surface_pixel_format) { 3744562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 3754562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_INDEX8; 3764562236bSHarry Wentland break; 3774562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 3784562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_RGB565; 3794562236bSHarry Wentland break; 3804562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 3814562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_RGB565; 3824562236bSHarry Wentland break; 3834562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 3844562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB8888; 3854562236bSHarry Wentland break; 3868693049aSTony Cheng case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 3874562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB8888; 3884562236bSHarry Wentland break; 3894562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 3904562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 3914562236bSHarry Wentland break; 3924562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 3934562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 3944562236bSHarry Wentland break; 3954562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 3964562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS; 3974562236bSHarry Wentland break; 3984562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 3994562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 4004562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_FP16; 4014562236bSHarry Wentland break; 4024562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 4034562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 40487449a90SAnthony Koo dal_pixel_format = PIXEL_FORMAT_420BPP8; 4054562236bSHarry Wentland break; 406ffbcd19aSVitaly Prosyak case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 407ffbcd19aSVitaly Prosyak case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 40887449a90SAnthony Koo dal_pixel_format = PIXEL_FORMAT_420BPP10; 409ffbcd19aSVitaly Prosyak break; 4104562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 4114562236bSHarry Wentland default: 4124562236bSHarry Wentland dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 4134562236bSHarry Wentland break; 4144562236bSHarry Wentland } 4154562236bSHarry Wentland return dal_pixel_format; 4164562236bSHarry Wentland } 4174562236bSHarry Wentland 4184562236bSHarry Wentland static void rect_swap_helper(struct rect *rect) 4194562236bSHarry Wentland { 4204562236bSHarry Wentland uint32_t temp = 0; 4214562236bSHarry Wentland 4224562236bSHarry Wentland temp = rect->height; 4234562236bSHarry Wentland rect->height = rect->width; 4244562236bSHarry Wentland rect->width = temp; 4254562236bSHarry Wentland 4264562236bSHarry Wentland temp = rect->x; 4274562236bSHarry Wentland rect->x = rect->y; 4284562236bSHarry Wentland rect->y = temp; 4294562236bSHarry Wentland } 4304562236bSHarry Wentland 431b2d0a103SDmytro Laktyushkin static void calculate_viewport(struct pipe_ctx *pipe_ctx) 4324562236bSHarry Wentland { 4333be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 4340971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 4356702a9acSHarry Wentland struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 4363be5262eSHarry Wentland struct rect surf_src = plane_state->src_rect; 4374562236bSHarry Wentland struct rect clip = { 0 }; 43887449a90SAnthony Koo int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 43987449a90SAnthony Koo || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 4401fbd2cfcSDmytro Laktyushkin bool pri_split = pipe_ctx->bottom_pipe && 4413be5262eSHarry Wentland pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; 4421fbd2cfcSDmytro Laktyushkin bool sec_split = pipe_ctx->top_pipe && 4433be5262eSHarry Wentland pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; 4444562236bSHarry Wentland 4457f5c22d1SVitaly Prosyak if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || 4467f5c22d1SVitaly Prosyak stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { 4477b779c99SVitaly Prosyak pri_split = false; 4487b779c99SVitaly Prosyak sec_split = false; 4497b779c99SVitaly Prosyak } 45086006a7fSDmytro Laktyushkin 4513be5262eSHarry Wentland if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 4523be5262eSHarry Wentland pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 45386006a7fSDmytro Laktyushkin rect_swap_helper(&surf_src); 45486006a7fSDmytro Laktyushkin 4554562236bSHarry Wentland /* The actual clip is an intersection between stream 4564562236bSHarry Wentland * source and surface clip 4574562236bSHarry Wentland */ 4583be5262eSHarry Wentland clip.x = stream->src.x > plane_state->clip_rect.x ? 4593be5262eSHarry Wentland stream->src.x : plane_state->clip_rect.x; 4604562236bSHarry Wentland 4611fbd2cfcSDmytro Laktyushkin clip.width = stream->src.x + stream->src.width < 4623be5262eSHarry Wentland plane_state->clip_rect.x + plane_state->clip_rect.width ? 4631fbd2cfcSDmytro Laktyushkin stream->src.x + stream->src.width - clip.x : 4643be5262eSHarry Wentland plane_state->clip_rect.x + plane_state->clip_rect.width - clip.x ; 4654562236bSHarry Wentland 4663be5262eSHarry Wentland clip.y = stream->src.y > plane_state->clip_rect.y ? 4673be5262eSHarry Wentland stream->src.y : plane_state->clip_rect.y; 4684562236bSHarry Wentland 4691fbd2cfcSDmytro Laktyushkin clip.height = stream->src.y + stream->src.height < 4703be5262eSHarry Wentland plane_state->clip_rect.y + plane_state->clip_rect.height ? 4711fbd2cfcSDmytro Laktyushkin stream->src.y + stream->src.height - clip.y : 4723be5262eSHarry Wentland plane_state->clip_rect.y + plane_state->clip_rect.height - clip.y ; 4734562236bSHarry Wentland 47486006a7fSDmytro Laktyushkin /* offset = surf_src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio 4754562236bSHarry Wentland * num_pixels = clip.num_pix * scl_ratio 4764562236bSHarry Wentland */ 4773be5262eSHarry Wentland data->viewport.x = surf_src.x + (clip.x - plane_state->dst_rect.x) * 4783be5262eSHarry Wentland surf_src.width / plane_state->dst_rect.width; 479b2d0a103SDmytro Laktyushkin data->viewport.width = clip.width * 4803be5262eSHarry Wentland surf_src.width / plane_state->dst_rect.width; 4814562236bSHarry Wentland 4823be5262eSHarry Wentland data->viewport.y = surf_src.y + (clip.y - plane_state->dst_rect.y) * 4833be5262eSHarry Wentland surf_src.height / plane_state->dst_rect.height; 484b2d0a103SDmytro Laktyushkin data->viewport.height = clip.height * 4853be5262eSHarry Wentland surf_src.height / plane_state->dst_rect.height; 4864562236bSHarry Wentland 487b2d0a103SDmytro Laktyushkin /* Round down, compensate in init */ 488b2d0a103SDmytro Laktyushkin data->viewport_c.x = data->viewport.x / vpc_div; 489b2d0a103SDmytro Laktyushkin data->viewport_c.y = data->viewport.y / vpc_div; 490b2d0a103SDmytro Laktyushkin data->inits.h_c = (data->viewport.x % vpc_div) != 0 ? 491b2d0a103SDmytro Laktyushkin dal_fixed31_32_half : dal_fixed31_32_zero; 492b2d0a103SDmytro Laktyushkin data->inits.v_c = (data->viewport.y % vpc_div) != 0 ? 493b2d0a103SDmytro Laktyushkin dal_fixed31_32_half : dal_fixed31_32_zero; 494b2d0a103SDmytro Laktyushkin /* Round up, assume original video size always even dimensions */ 495b2d0a103SDmytro Laktyushkin data->viewport_c.width = (data->viewport.width + vpc_div - 1) / vpc_div; 496b2d0a103SDmytro Laktyushkin data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; 497b2d0a103SDmytro Laktyushkin 498b2d0a103SDmytro Laktyushkin /* Handle hsplit */ 4991fbd2cfcSDmytro Laktyushkin if (pri_split || sec_split) { 5001fbd2cfcSDmytro Laktyushkin /* HMirror XOR Secondary_pipe XOR Rotation_180 */ 5013be5262eSHarry Wentland bool right_view = (sec_split != plane_state->horizontal_mirror) != 5023be5262eSHarry Wentland (plane_state->rotation == ROTATION_ANGLE_180); 5039e6c74ceSDmytro Laktyushkin 5043be5262eSHarry Wentland if (plane_state->rotation == ROTATION_ANGLE_90 5053be5262eSHarry Wentland || plane_state->rotation == ROTATION_ANGLE_270) 5061fbd2cfcSDmytro Laktyushkin /* Secondary_pipe XOR Rotation_270 */ 5073be5262eSHarry Wentland right_view = (plane_state->rotation == ROTATION_ANGLE_270) != sec_split; 5089e6c74ceSDmytro Laktyushkin 5099e6c74ceSDmytro Laktyushkin if (right_view) { 510b2d0a103SDmytro Laktyushkin data->viewport.width /= 2; 511b2d0a103SDmytro Laktyushkin data->viewport_c.width /= 2; 512b2d0a103SDmytro Laktyushkin data->viewport.x += data->viewport.width; 513b2d0a103SDmytro Laktyushkin data->viewport_c.x += data->viewport_c.width; 5149e6c74ceSDmytro Laktyushkin /* Ceil offset pipe */ 515b2d0a103SDmytro Laktyushkin data->viewport.width += data->viewport.width % 2; 516b2d0a103SDmytro Laktyushkin data->viewport_c.width += data->viewport_c.width % 2; 5179e6c74ceSDmytro Laktyushkin } else { 518b2d0a103SDmytro Laktyushkin data->viewport.width /= 2; 519b2d0a103SDmytro Laktyushkin data->viewport_c.width /= 2; 520b2d0a103SDmytro Laktyushkin } 5214562236bSHarry Wentland } 5221fbd2cfcSDmytro Laktyushkin 5233be5262eSHarry Wentland if (plane_state->rotation == ROTATION_ANGLE_90 || 5243be5262eSHarry Wentland plane_state->rotation == ROTATION_ANGLE_270) { 5251fbd2cfcSDmytro Laktyushkin rect_swap_helper(&data->viewport_c); 5261fbd2cfcSDmytro Laktyushkin rect_swap_helper(&data->viewport); 5271fbd2cfcSDmytro Laktyushkin } 5289e6c74ceSDmytro Laktyushkin } 5294562236bSHarry Wentland 530b2d0a103SDmytro Laktyushkin static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip) 5314562236bSHarry Wentland { 5323be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 5330971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 5343be5262eSHarry Wentland struct rect surf_src = plane_state->src_rect; 5353be5262eSHarry Wentland struct rect surf_clip = plane_state->clip_rect; 536c802570eSDmytro Laktyushkin int recout_full_x, recout_full_y; 5374562236bSHarry Wentland 5383be5262eSHarry Wentland if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 5393be5262eSHarry Wentland pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 54086006a7fSDmytro Laktyushkin rect_swap_helper(&surf_src); 54186006a7fSDmytro Laktyushkin 5426702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.x = stream->dst.x; 5434fa086b9SLeo (Sunpeng) Li if (stream->src.x < surf_clip.x) 5446702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.x += (surf_clip.x 5454fa086b9SLeo (Sunpeng) Li - stream->src.x) * stream->dst.width 5464fa086b9SLeo (Sunpeng) Li / stream->src.width; 5474562236bSHarry Wentland 5486702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.width = surf_clip.width * 5494fa086b9SLeo (Sunpeng) Li stream->dst.width / stream->src.width; 5506702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.recout.width + pipe_ctx->plane_res.scl_data.recout.x > 5514fa086b9SLeo (Sunpeng) Li stream->dst.x + stream->dst.width) 5526702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.width = 5534fa086b9SLeo (Sunpeng) Li stream->dst.x + stream->dst.width 5546702a9acSHarry Wentland - pipe_ctx->plane_res.scl_data.recout.x; 5554562236bSHarry Wentland 5566702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.y = stream->dst.y; 5574fa086b9SLeo (Sunpeng) Li if (stream->src.y < surf_clip.y) 5586702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.y += (surf_clip.y 5594fa086b9SLeo (Sunpeng) Li - stream->src.y) * stream->dst.height 5604fa086b9SLeo (Sunpeng) Li / stream->src.height; 5614562236bSHarry Wentland 5626702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.height = surf_clip.height * 5634fa086b9SLeo (Sunpeng) Li stream->dst.height / stream->src.height; 5646702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.recout.height + pipe_ctx->plane_res.scl_data.recout.y > 5654fa086b9SLeo (Sunpeng) Li stream->dst.y + stream->dst.height) 5666702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.height = 5674fa086b9SLeo (Sunpeng) Li stream->dst.y + stream->dst.height 5686702a9acSHarry Wentland - pipe_ctx->plane_res.scl_data.recout.y; 569b2d0a103SDmytro Laktyushkin 5707b779c99SVitaly Prosyak /* Handle h & vsplit */ 5713be5262eSHarry Wentland if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->plane_state == 5723be5262eSHarry Wentland pipe_ctx->plane_state) { 5734fa086b9SLeo (Sunpeng) Li if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { 5746702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.height /= 2; 5756702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.y += pipe_ctx->plane_res.scl_data.recout.height; 5767b779c99SVitaly Prosyak /* Floor primary pipe, ceil 2ndary pipe */ 5776702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.height += pipe_ctx->plane_res.scl_data.recout.height % 2; 5787b779c99SVitaly Prosyak } else { 5796702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.width /= 2; 5806702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.x += pipe_ctx->plane_res.scl_data.recout.width; 5816702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.width += pipe_ctx->plane_res.scl_data.recout.width % 2; 5827b779c99SVitaly Prosyak } 5837b779c99SVitaly Prosyak } else if (pipe_ctx->bottom_pipe && 5843be5262eSHarry Wentland pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state) { 5854fa086b9SLeo (Sunpeng) Li if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) 5866702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.height /= 2; 5877b779c99SVitaly Prosyak else 5886702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.width /= 2; 5894562236bSHarry Wentland } 5904562236bSHarry Wentland 59186006a7fSDmytro Laktyushkin /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream surf_src offset) 59286006a7fSDmytro Laktyushkin * * 1/ stream scaling ratio) - (surf surf_src offset * 1/ full scl 593c802570eSDmytro Laktyushkin * ratio) 594c802570eSDmytro Laktyushkin */ 5953be5262eSHarry Wentland recout_full_x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x) 5964fa086b9SLeo (Sunpeng) Li * stream->dst.width / stream->src.width - 5973be5262eSHarry Wentland surf_src.x * plane_state->dst_rect.width / surf_src.width 5984fa086b9SLeo (Sunpeng) Li * stream->dst.width / stream->src.width; 5993be5262eSHarry Wentland recout_full_y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y) 6004fa086b9SLeo (Sunpeng) Li * stream->dst.height / stream->src.height - 6013be5262eSHarry Wentland surf_src.y * plane_state->dst_rect.height / surf_src.height 6024fa086b9SLeo (Sunpeng) Li * stream->dst.height / stream->src.height; 603c802570eSDmytro Laktyushkin 6046702a9acSHarry Wentland recout_skip->width = pipe_ctx->plane_res.scl_data.recout.x - recout_full_x; 6056702a9acSHarry Wentland recout_skip->height = pipe_ctx->plane_res.scl_data.recout.y - recout_full_y; 606b2d0a103SDmytro Laktyushkin } 607b2d0a103SDmytro Laktyushkin 608b2d0a103SDmytro Laktyushkin static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) 6094562236bSHarry Wentland { 6103be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 6110971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 6123be5262eSHarry Wentland struct rect surf_src = plane_state->src_rect; 6134fa086b9SLeo (Sunpeng) Li const int in_w = stream->src.width; 6144fa086b9SLeo (Sunpeng) Li const int in_h = stream->src.height; 6154fa086b9SLeo (Sunpeng) Li const int out_w = stream->dst.width; 6164fa086b9SLeo (Sunpeng) Li const int out_h = stream->dst.height; 6174562236bSHarry Wentland 6183be5262eSHarry Wentland if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 6193be5262eSHarry Wentland pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 62086006a7fSDmytro Laktyushkin rect_swap_helper(&surf_src); 62186006a7fSDmytro Laktyushkin 6226702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz = dal_fixed31_32_from_fraction( 62386006a7fSDmytro Laktyushkin surf_src.width, 6243be5262eSHarry Wentland plane_state->dst_rect.width); 6256702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert = dal_fixed31_32_from_fraction( 62686006a7fSDmytro Laktyushkin surf_src.height, 6273be5262eSHarry Wentland plane_state->dst_rect.height); 6284562236bSHarry Wentland 6294fa086b9SLeo (Sunpeng) Li if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) 6306702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value *= 2; 6314fa086b9SLeo (Sunpeng) Li else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) 6326702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value *= 2; 6334562236bSHarry Wentland 6346702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value = div64_s64( 6356702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert.value * in_h, out_h); 6366702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value = div64_s64( 6376702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz.value * in_w, out_w); 6384562236bSHarry Wentland 6396702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz_c = pipe_ctx->plane_res.scl_data.ratios.horz; 6406702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert_c = pipe_ctx->plane_res.scl_data.ratios.vert; 6414562236bSHarry Wentland 6426702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP8 6436702a9acSHarry Wentland || pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP10) { 6446702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.horz_c.value /= 2; 6456702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.ratios.vert_c.value /= 2; 6464562236bSHarry Wentland } 6474562236bSHarry Wentland } 6484562236bSHarry Wentland 649b2d0a103SDmytro Laktyushkin static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *recout_skip) 6504562236bSHarry Wentland { 6516702a9acSHarry Wentland struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 6523be5262eSHarry Wentland struct rect src = pipe_ctx->plane_state->src_rect; 65387449a90SAnthony Koo int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 65487449a90SAnthony Koo || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 655b2d0a103SDmytro Laktyushkin 65686006a7fSDmytro Laktyushkin 6573be5262eSHarry Wentland if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 6583be5262eSHarry Wentland pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) { 65986006a7fSDmytro Laktyushkin rect_swap_helper(&src); 6601fbd2cfcSDmytro Laktyushkin rect_swap_helper(&data->viewport_c); 6611fbd2cfcSDmytro Laktyushkin rect_swap_helper(&data->viewport); 6621fbd2cfcSDmytro Laktyushkin } 6631fbd2cfcSDmytro Laktyushkin 664b2d0a103SDmytro Laktyushkin /* 665b2d0a103SDmytro Laktyushkin * Init calculated according to formula: 666b2d0a103SDmytro Laktyushkin * init = (scaling_ratio + number_of_taps + 1) / 2 667b2d0a103SDmytro Laktyushkin * init_bot = init + scaling_ratio 668b2d0a103SDmytro Laktyushkin * init_c = init + truncated_vp_c_offset(from calculate viewport) 669b2d0a103SDmytro Laktyushkin */ 670b2d0a103SDmytro Laktyushkin data->inits.h = dal_fixed31_32_div_int( 671b2d0a103SDmytro Laktyushkin dal_fixed31_32_add_int(data->ratios.horz, data->taps.h_taps + 1), 2); 672b2d0a103SDmytro Laktyushkin 673b2d0a103SDmytro Laktyushkin data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_div_int( 674b2d0a103SDmytro Laktyushkin dal_fixed31_32_add_int(data->ratios.horz_c, data->taps.h_taps_c + 1), 2)); 675b2d0a103SDmytro Laktyushkin 676b2d0a103SDmytro Laktyushkin data->inits.v = dal_fixed31_32_div_int( 677b2d0a103SDmytro Laktyushkin dal_fixed31_32_add_int(data->ratios.vert, data->taps.v_taps + 1), 2); 678b2d0a103SDmytro Laktyushkin 679b2d0a103SDmytro Laktyushkin data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_div_int( 680b2d0a103SDmytro Laktyushkin dal_fixed31_32_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2)); 681b2d0a103SDmytro Laktyushkin 682b2d0a103SDmytro Laktyushkin 683b2d0a103SDmytro Laktyushkin /* Adjust for viewport end clip-off */ 684b2d0a103SDmytro Laktyushkin if ((data->viewport.x + data->viewport.width) < (src.x + src.width)) { 685b2d0a103SDmytro Laktyushkin int vp_clip = src.x + src.width - data->viewport.width - data->viewport.x; 6861fbd2cfcSDmytro Laktyushkin int int_part = dal_fixed31_32_floor( 6871fbd2cfcSDmytro Laktyushkin dal_fixed31_32_sub(data->inits.h, data->ratios.horz)); 688b2d0a103SDmytro Laktyushkin 6891fbd2cfcSDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 690b2d0a103SDmytro Laktyushkin data->viewport.width += int_part < vp_clip ? int_part : vp_clip; 691b2d0a103SDmytro Laktyushkin } 692b2d0a103SDmytro Laktyushkin if ((data->viewport.y + data->viewport.height) < (src.y + src.height)) { 693b2d0a103SDmytro Laktyushkin int vp_clip = src.y + src.height - data->viewport.height - data->viewport.y; 6941fbd2cfcSDmytro Laktyushkin int int_part = dal_fixed31_32_floor( 6951fbd2cfcSDmytro Laktyushkin dal_fixed31_32_sub(data->inits.v, data->ratios.vert)); 696b2d0a103SDmytro Laktyushkin 6971fbd2cfcSDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 698b2d0a103SDmytro Laktyushkin data->viewport.height += int_part < vp_clip ? int_part : vp_clip; 699b2d0a103SDmytro Laktyushkin } 700b2d0a103SDmytro Laktyushkin if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div) { 701b2d0a103SDmytro Laktyushkin int vp_clip = (src.x + src.width) / vpc_div - 702b2d0a103SDmytro Laktyushkin data->viewport_c.width - data->viewport_c.x; 7031fbd2cfcSDmytro Laktyushkin int int_part = dal_fixed31_32_floor( 7041fbd2cfcSDmytro Laktyushkin dal_fixed31_32_sub(data->inits.h_c, data->ratios.horz_c)); 705b2d0a103SDmytro Laktyushkin 7061fbd2cfcSDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 707b2d0a103SDmytro Laktyushkin data->viewport_c.width += int_part < vp_clip ? int_part : vp_clip; 708b2d0a103SDmytro Laktyushkin } 709b2d0a103SDmytro Laktyushkin if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div) { 710b2d0a103SDmytro Laktyushkin int vp_clip = (src.y + src.height) / vpc_div - 711b2d0a103SDmytro Laktyushkin data->viewport_c.height - data->viewport_c.y; 7121fbd2cfcSDmytro Laktyushkin int int_part = dal_fixed31_32_floor( 7131fbd2cfcSDmytro Laktyushkin dal_fixed31_32_sub(data->inits.v_c, data->ratios.vert_c)); 714b2d0a103SDmytro Laktyushkin 7151fbd2cfcSDmytro Laktyushkin int_part = int_part > 0 ? int_part : 0; 716b2d0a103SDmytro Laktyushkin data->viewport_c.height += int_part < vp_clip ? int_part : vp_clip; 717b2d0a103SDmytro Laktyushkin } 718b2d0a103SDmytro Laktyushkin 719b2d0a103SDmytro Laktyushkin /* Adjust for non-0 viewport offset */ 720b2d0a103SDmytro Laktyushkin if (data->viewport.x) { 721b2d0a103SDmytro Laktyushkin int int_part; 722b2d0a103SDmytro Laktyushkin 723b2d0a103SDmytro Laktyushkin data->inits.h = dal_fixed31_32_add(data->inits.h, dal_fixed31_32_mul_int( 724b2d0a103SDmytro Laktyushkin data->ratios.horz, recout_skip->width)); 725b2d0a103SDmytro Laktyushkin int_part = dal_fixed31_32_floor(data->inits.h) - data->viewport.x; 726b2d0a103SDmytro Laktyushkin if (int_part < data->taps.h_taps) { 727b2d0a103SDmytro Laktyushkin int int_adj = data->viewport.x >= (data->taps.h_taps - int_part) ? 728b2d0a103SDmytro Laktyushkin (data->taps.h_taps - int_part) : data->viewport.x; 729b2d0a103SDmytro Laktyushkin data->viewport.x -= int_adj; 730b2d0a103SDmytro Laktyushkin data->viewport.width += int_adj; 731b2d0a103SDmytro Laktyushkin int_part += int_adj; 732b2d0a103SDmytro Laktyushkin } else if (int_part > data->taps.h_taps) { 733b2d0a103SDmytro Laktyushkin data->viewport.x += int_part - data->taps.h_taps; 734b2d0a103SDmytro Laktyushkin data->viewport.width -= int_part - data->taps.h_taps; 735b2d0a103SDmytro Laktyushkin int_part = data->taps.h_taps; 736b2d0a103SDmytro Laktyushkin } 737b2d0a103SDmytro Laktyushkin data->inits.h.value &= 0xffffffff; 738b2d0a103SDmytro Laktyushkin data->inits.h = dal_fixed31_32_add_int(data->inits.h, int_part); 739b2d0a103SDmytro Laktyushkin } 740b2d0a103SDmytro Laktyushkin 741b2d0a103SDmytro Laktyushkin if (data->viewport_c.x) { 742b2d0a103SDmytro Laktyushkin int int_part; 743b2d0a103SDmytro Laktyushkin 744b2d0a103SDmytro Laktyushkin data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_mul_int( 745b2d0a103SDmytro Laktyushkin data->ratios.horz_c, recout_skip->width)); 746b2d0a103SDmytro Laktyushkin int_part = dal_fixed31_32_floor(data->inits.h_c) - data->viewport_c.x; 747b2d0a103SDmytro Laktyushkin if (int_part < data->taps.h_taps_c) { 748b2d0a103SDmytro Laktyushkin int int_adj = data->viewport_c.x >= (data->taps.h_taps_c - int_part) ? 749b2d0a103SDmytro Laktyushkin (data->taps.h_taps_c - int_part) : data->viewport_c.x; 750b2d0a103SDmytro Laktyushkin data->viewport_c.x -= int_adj; 751b2d0a103SDmytro Laktyushkin data->viewport_c.width += int_adj; 752b2d0a103SDmytro Laktyushkin int_part += int_adj; 753b2d0a103SDmytro Laktyushkin } else if (int_part > data->taps.h_taps_c) { 754b2d0a103SDmytro Laktyushkin data->viewport_c.x += int_part - data->taps.h_taps_c; 755b2d0a103SDmytro Laktyushkin data->viewport_c.width -= int_part - data->taps.h_taps_c; 756b2d0a103SDmytro Laktyushkin int_part = data->taps.h_taps_c; 757b2d0a103SDmytro Laktyushkin } 758b2d0a103SDmytro Laktyushkin data->inits.h_c.value &= 0xffffffff; 759b2d0a103SDmytro Laktyushkin data->inits.h_c = dal_fixed31_32_add_int(data->inits.h_c, int_part); 760b2d0a103SDmytro Laktyushkin } 761b2d0a103SDmytro Laktyushkin 762b2d0a103SDmytro Laktyushkin if (data->viewport.y) { 763b2d0a103SDmytro Laktyushkin int int_part; 764b2d0a103SDmytro Laktyushkin 765b2d0a103SDmytro Laktyushkin data->inits.v = dal_fixed31_32_add(data->inits.v, dal_fixed31_32_mul_int( 766b2d0a103SDmytro Laktyushkin data->ratios.vert, recout_skip->height)); 767b2d0a103SDmytro Laktyushkin int_part = dal_fixed31_32_floor(data->inits.v) - data->viewport.y; 768b2d0a103SDmytro Laktyushkin if (int_part < data->taps.v_taps) { 769b2d0a103SDmytro Laktyushkin int int_adj = data->viewport.y >= (data->taps.v_taps - int_part) ? 770b2d0a103SDmytro Laktyushkin (data->taps.v_taps - int_part) : data->viewport.y; 771b2d0a103SDmytro Laktyushkin data->viewport.y -= int_adj; 772b2d0a103SDmytro Laktyushkin data->viewport.height += int_adj; 773b2d0a103SDmytro Laktyushkin int_part += int_adj; 774b2d0a103SDmytro Laktyushkin } else if (int_part > data->taps.v_taps) { 775b2d0a103SDmytro Laktyushkin data->viewport.y += int_part - data->taps.v_taps; 776b2d0a103SDmytro Laktyushkin data->viewport.height -= int_part - data->taps.v_taps; 777b2d0a103SDmytro Laktyushkin int_part = data->taps.v_taps; 778b2d0a103SDmytro Laktyushkin } 779b2d0a103SDmytro Laktyushkin data->inits.v.value &= 0xffffffff; 780b2d0a103SDmytro Laktyushkin data->inits.v = dal_fixed31_32_add_int(data->inits.v, int_part); 781b2d0a103SDmytro Laktyushkin } 782b2d0a103SDmytro Laktyushkin 783b2d0a103SDmytro Laktyushkin if (data->viewport_c.y) { 784b2d0a103SDmytro Laktyushkin int int_part; 785b2d0a103SDmytro Laktyushkin 786b2d0a103SDmytro Laktyushkin data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_mul_int( 787b2d0a103SDmytro Laktyushkin data->ratios.vert_c, recout_skip->height)); 788b2d0a103SDmytro Laktyushkin int_part = dal_fixed31_32_floor(data->inits.v_c) - data->viewport_c.y; 789b2d0a103SDmytro Laktyushkin if (int_part < data->taps.v_taps_c) { 790b2d0a103SDmytro Laktyushkin int int_adj = data->viewport_c.y >= (data->taps.v_taps_c - int_part) ? 791b2d0a103SDmytro Laktyushkin (data->taps.v_taps_c - int_part) : data->viewport_c.y; 792b2d0a103SDmytro Laktyushkin data->viewport_c.y -= int_adj; 793b2d0a103SDmytro Laktyushkin data->viewport_c.height += int_adj; 794b2d0a103SDmytro Laktyushkin int_part += int_adj; 795b2d0a103SDmytro Laktyushkin } else if (int_part > data->taps.v_taps_c) { 796b2d0a103SDmytro Laktyushkin data->viewport_c.y += int_part - data->taps.v_taps_c; 797b2d0a103SDmytro Laktyushkin data->viewport_c.height -= int_part - data->taps.v_taps_c; 798b2d0a103SDmytro Laktyushkin int_part = data->taps.v_taps_c; 799b2d0a103SDmytro Laktyushkin } 800b2d0a103SDmytro Laktyushkin data->inits.v_c.value &= 0xffffffff; 801b2d0a103SDmytro Laktyushkin data->inits.v_c = dal_fixed31_32_add_int(data->inits.v_c, int_part); 802b2d0a103SDmytro Laktyushkin } 803b2d0a103SDmytro Laktyushkin 804b2d0a103SDmytro Laktyushkin /* Interlaced inits based on final vert inits */ 805b2d0a103SDmytro Laktyushkin data->inits.v_bot = dal_fixed31_32_add(data->inits.v, data->ratios.vert); 806b2d0a103SDmytro Laktyushkin data->inits.v_c_bot = dal_fixed31_32_add(data->inits.v_c, data->ratios.vert_c); 8071fbd2cfcSDmytro Laktyushkin 8083be5262eSHarry Wentland if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 8093be5262eSHarry Wentland pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) { 8101fbd2cfcSDmytro Laktyushkin rect_swap_helper(&data->viewport_c); 8111fbd2cfcSDmytro Laktyushkin rect_swap_helper(&data->viewport); 8121fbd2cfcSDmytro Laktyushkin } 813b2d0a103SDmytro Laktyushkin } 814b2d0a103SDmytro Laktyushkin 815b2d0a103SDmytro Laktyushkin bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) 816b2d0a103SDmytro Laktyushkin { 8173be5262eSHarry Wentland const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 8184fa086b9SLeo (Sunpeng) Li struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 819b2d0a103SDmytro Laktyushkin struct view recout_skip = { 0 }; 820b2d0a103SDmytro Laktyushkin bool res = false; 821b2d0a103SDmytro Laktyushkin 8224562236bSHarry Wentland /* Important: scaling ratio calculation requires pixel format, 8234562236bSHarry Wentland * lb depth calculation requires recout and taps require scaling ratios. 824b2d0a103SDmytro Laktyushkin * Inits require viewport, taps, ratios and recout of split pipe 8254562236bSHarry Wentland */ 8266702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface( 8273be5262eSHarry Wentland pipe_ctx->plane_state->format); 8284562236bSHarry Wentland 829b2d0a103SDmytro Laktyushkin calculate_scaling_ratios(pipe_ctx); 830b2d0a103SDmytro Laktyushkin 831b2d0a103SDmytro Laktyushkin calculate_viewport(pipe_ctx); 8324562236bSHarry Wentland 8336702a9acSHarry Wentland if (pipe_ctx->plane_res.scl_data.viewport.height < 16 || pipe_ctx->plane_res.scl_data.viewport.width < 16) 8344562236bSHarry Wentland return false; 8354562236bSHarry Wentland 836b2d0a103SDmytro Laktyushkin calculate_recout(pipe_ctx, &recout_skip); 8374562236bSHarry Wentland 8384562236bSHarry Wentland /** 8394562236bSHarry Wentland * Setting line buffer pixel depth to 24bpp yields banding 8404562236bSHarry Wentland * on certain displays, such as the Sharp 4k 8414562236bSHarry Wentland */ 8426702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; 8434562236bSHarry Wentland 8446702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable; 8456702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable; 8464562236bSHarry Wentland 8474562236bSHarry Wentland /* Taps calculations */ 84886a66c4eSHarry Wentland res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 84986a66c4eSHarry Wentland pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 8504562236bSHarry Wentland 8514562236bSHarry Wentland if (!res) { 8524562236bSHarry Wentland /* Try 24 bpp linebuffer */ 8536702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; 8544562236bSHarry Wentland 85586a66c4eSHarry Wentland res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 85686a66c4eSHarry Wentland pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 8574562236bSHarry Wentland } 8584562236bSHarry Wentland 859b2d0a103SDmytro Laktyushkin if (res) 8601fbd2cfcSDmytro Laktyushkin /* May need to re-check lb size after this in some obscure scenario */ 861b2d0a103SDmytro Laktyushkin calculate_inits_and_adj_vp(pipe_ctx, &recout_skip); 862b2d0a103SDmytro Laktyushkin 8634562236bSHarry Wentland dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_SCALER, 8644562236bSHarry Wentland "%s: Viewport:\nheight:%d width:%d x:%d " 8654562236bSHarry Wentland "y:%d\n dst_rect:\nheight:%d width:%d x:%d " 8664562236bSHarry Wentland "y:%d\n", 8674562236bSHarry Wentland __func__, 8686702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.height, 8696702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.width, 8706702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.x, 8716702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.y, 8723be5262eSHarry Wentland plane_state->dst_rect.height, 8733be5262eSHarry Wentland plane_state->dst_rect.width, 8743be5262eSHarry Wentland plane_state->dst_rect.x, 8753be5262eSHarry Wentland plane_state->dst_rect.y); 8764562236bSHarry Wentland 8774562236bSHarry Wentland return res; 8784562236bSHarry Wentland } 8794562236bSHarry Wentland 8804562236bSHarry Wentland 8814562236bSHarry Wentland enum dc_status resource_build_scaling_params_for_context( 8824562236bSHarry Wentland const struct core_dc *dc, 8834562236bSHarry Wentland struct validate_context *context) 8844562236bSHarry Wentland { 8854562236bSHarry Wentland int i; 8864562236bSHarry Wentland 8874562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 8883be5262eSHarry Wentland if (context->res_ctx.pipe_ctx[i].plane_state != NULL && 8894562236bSHarry Wentland context->res_ctx.pipe_ctx[i].stream != NULL) 890b2d0a103SDmytro Laktyushkin if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i])) 891f84a8161STony Cheng return DC_FAIL_SCALING; 8924562236bSHarry Wentland } 8934562236bSHarry Wentland 8944562236bSHarry Wentland return DC_OK; 8954562236bSHarry Wentland } 8964562236bSHarry Wentland 897a2b8659dSTony Cheng struct pipe_ctx *find_idle_secondary_pipe( 898a2b8659dSTony Cheng struct resource_context *res_ctx, 899a2b8659dSTony Cheng const struct resource_pool *pool) 9004562236bSHarry Wentland { 9014562236bSHarry Wentland int i; 9024562236bSHarry Wentland struct pipe_ctx *secondary_pipe = NULL; 9034562236bSHarry Wentland 9044562236bSHarry Wentland /* 9054562236bSHarry Wentland * search backwards for the second pipe to keep pipe 9064562236bSHarry Wentland * assignment more consistent 9074562236bSHarry Wentland */ 9084562236bSHarry Wentland 909a2b8659dSTony Cheng for (i = pool->pipe_count - 1; i >= 0; i--) { 9104562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == NULL) { 9114562236bSHarry Wentland secondary_pipe = &res_ctx->pipe_ctx[i]; 9124562236bSHarry Wentland secondary_pipe->pipe_idx = i; 9134562236bSHarry Wentland break; 9144562236bSHarry Wentland } 9154562236bSHarry Wentland } 9164562236bSHarry Wentland 9174562236bSHarry Wentland 9184562236bSHarry Wentland return secondary_pipe; 9194562236bSHarry Wentland } 9204562236bSHarry Wentland 9214562236bSHarry Wentland struct pipe_ctx *resource_get_head_pipe_for_stream( 9224562236bSHarry Wentland struct resource_context *res_ctx, 9230971c40eSHarry Wentland struct dc_stream_state *stream) 9244562236bSHarry Wentland { 9254562236bSHarry Wentland int i; 926a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 9274562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == stream && 9288e9c4c8cSHarry Wentland res_ctx->pipe_ctx[i].stream_res.stream_enc) { 9294562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 9304562236bSHarry Wentland break; 9314562236bSHarry Wentland } 9324562236bSHarry Wentland } 9334562236bSHarry Wentland return NULL; 9344562236bSHarry Wentland } 9354562236bSHarry Wentland 9364562236bSHarry Wentland /* 937ab2541b6SAric Cyr * A free_pipe for a stream is defined here as a pipe 938ab2541b6SAric Cyr * that has no surface attached yet 9394562236bSHarry Wentland */ 940ab2541b6SAric Cyr static struct pipe_ctx *acquire_free_pipe_for_stream( 941745cc746SDmytro Laktyushkin struct validate_context *context, 942a2b8659dSTony Cheng const struct resource_pool *pool, 9430971c40eSHarry Wentland struct dc_stream_state *stream) 9444562236bSHarry Wentland { 9454562236bSHarry Wentland int i; 946745cc746SDmytro Laktyushkin struct resource_context *res_ctx = &context->res_ctx; 9474562236bSHarry Wentland 9484562236bSHarry Wentland struct pipe_ctx *head_pipe = NULL; 9494562236bSHarry Wentland 9504562236bSHarry Wentland /* Find head pipe, which has the back end set up*/ 9514562236bSHarry Wentland 9524562236bSHarry Wentland head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream); 9534562236bSHarry Wentland 9544562236bSHarry Wentland if (!head_pipe) 9554562236bSHarry Wentland ASSERT(0); 9564562236bSHarry Wentland 9573be5262eSHarry Wentland if (!head_pipe->plane_state) 9584562236bSHarry Wentland return head_pipe; 9594562236bSHarry Wentland 9604562236bSHarry Wentland /* Re-use pipe already acquired for this stream if available*/ 961a2b8659dSTony Cheng for (i = pool->pipe_count - 1; i >= 0; i--) { 9624562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == stream && 9633be5262eSHarry Wentland !res_ctx->pipe_ctx[i].plane_state) { 9644562236bSHarry Wentland return &res_ctx->pipe_ctx[i]; 9654562236bSHarry Wentland } 9664562236bSHarry Wentland } 9674562236bSHarry Wentland 9684562236bSHarry Wentland /* 9694562236bSHarry Wentland * At this point we have no re-useable pipe for this stream and we need 9704562236bSHarry Wentland * to acquire an idle one to satisfy the request 9714562236bSHarry Wentland */ 9724562236bSHarry Wentland 973a2b8659dSTony Cheng if (!pool->funcs->acquire_idle_pipe_for_layer) 9744562236bSHarry Wentland return NULL; 9754562236bSHarry Wentland 976a2b8659dSTony Cheng return pool->funcs->acquire_idle_pipe_for_layer(context, pool, stream); 9774562236bSHarry Wentland 9784562236bSHarry Wentland } 9794562236bSHarry Wentland 980ab2541b6SAric Cyr static void release_free_pipes_for_stream( 9814562236bSHarry Wentland struct resource_context *res_ctx, 9820971c40eSHarry Wentland struct dc_stream_state *stream) 9834562236bSHarry Wentland { 9844562236bSHarry Wentland int i; 9854562236bSHarry Wentland 986a2b8659dSTony Cheng for (i = MAX_PIPES - 1; i >= 0; i--) { 98705a19c39SDmytro Laktyushkin /* never release the topmost pipe*/ 9884562236bSHarry Wentland if (res_ctx->pipe_ctx[i].stream == stream && 98905a19c39SDmytro Laktyushkin res_ctx->pipe_ctx[i].top_pipe && 9903be5262eSHarry Wentland !res_ctx->pipe_ctx[i].plane_state) { 99105a19c39SDmytro Laktyushkin memset(&res_ctx->pipe_ctx[i], 0, sizeof(struct pipe_ctx)); 9924562236bSHarry Wentland } 9934562236bSHarry Wentland } 9944562236bSHarry Wentland } 9954562236bSHarry Wentland 9960f9a536fSDmytro Laktyushkin #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 9970f9a536fSDmytro Laktyushkin static int acquire_first_split_pipe( 9980f9a536fSDmytro Laktyushkin struct resource_context *res_ctx, 9990f9a536fSDmytro Laktyushkin const struct resource_pool *pool, 10000971c40eSHarry Wentland struct dc_stream_state *stream) 10010f9a536fSDmytro Laktyushkin { 10020f9a536fSDmytro Laktyushkin int i; 10030f9a536fSDmytro Laktyushkin 10040f9a536fSDmytro Laktyushkin for (i = 0; i < pool->pipe_count; i++) { 10050f9a536fSDmytro Laktyushkin struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 10060f9a536fSDmytro Laktyushkin 10070f9a536fSDmytro Laktyushkin if (pipe_ctx->top_pipe && 10083be5262eSHarry Wentland pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state) { 10090f9a536fSDmytro Laktyushkin pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; 10100f9a536fSDmytro Laktyushkin if (pipe_ctx->bottom_pipe) 10110f9a536fSDmytro Laktyushkin pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; 10120f9a536fSDmytro Laktyushkin 10130f9a536fSDmytro Laktyushkin memset(pipe_ctx, 0, sizeof(*pipe_ctx)); 10146b670fa9SHarry Wentland pipe_ctx->stream_res.tg = pool->timing_generators[i]; 101586a66c4eSHarry Wentland pipe_ctx->plane_res.mi = pool->mis[i]; 101686a66c4eSHarry Wentland pipe_ctx->plane_res.ipp = pool->ipps[i]; 101786a66c4eSHarry Wentland pipe_ctx->plane_res.xfm = pool->transforms[i]; 1018a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp = pool->opps[i]; 10190f9a536fSDmytro Laktyushkin pipe_ctx->dis_clk = pool->display_clock; 10200f9a536fSDmytro Laktyushkin pipe_ctx->pipe_idx = i; 10210f9a536fSDmytro Laktyushkin 10220f9a536fSDmytro Laktyushkin pipe_ctx->stream = stream; 10230f9a536fSDmytro Laktyushkin return i; 10240f9a536fSDmytro Laktyushkin } 10250f9a536fSDmytro Laktyushkin } 10260f9a536fSDmytro Laktyushkin return -1; 10270f9a536fSDmytro Laktyushkin } 10280f9a536fSDmytro Laktyushkin #endif 10290f9a536fSDmytro Laktyushkin 10304562236bSHarry Wentland bool resource_attach_surfaces_to_context( 10313be5262eSHarry Wentland struct dc_plane_state * const *plane_states, 10324562236bSHarry Wentland int surface_count, 10330971c40eSHarry Wentland struct dc_stream_state *stream, 1034a2b8659dSTony Cheng struct validate_context *context, 1035a2b8659dSTony Cheng const struct resource_pool *pool) 10364562236bSHarry Wentland { 10374562236bSHarry Wentland int i; 10384562236bSHarry Wentland struct pipe_ctx *tail_pipe; 1039ab2541b6SAric Cyr struct dc_stream_status *stream_status = NULL; 10404562236bSHarry Wentland 10414562236bSHarry Wentland 10424562236bSHarry Wentland if (surface_count > MAX_SURFACE_NUM) { 10434562236bSHarry Wentland dm_error("Surface: can not attach %d surfaces! Maximum is: %d\n", 10444562236bSHarry Wentland surface_count, MAX_SURFACE_NUM); 10454562236bSHarry Wentland return false; 10464562236bSHarry Wentland } 10474562236bSHarry Wentland 1048ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) 10494fa086b9SLeo (Sunpeng) Li if (context->streams[i] == stream) { 1050ab2541b6SAric Cyr stream_status = &context->stream_status[i]; 10514562236bSHarry Wentland break; 10524562236bSHarry Wentland } 1053ab2541b6SAric Cyr if (stream_status == NULL) { 1054ab2541b6SAric Cyr dm_error("Existing stream not found; failed to attach surfaces\n"); 10554562236bSHarry Wentland return false; 10564562236bSHarry Wentland } 10574562236bSHarry Wentland 10584562236bSHarry Wentland /* retain new surfaces */ 10594562236bSHarry Wentland for (i = 0; i < surface_count; i++) 10603be5262eSHarry Wentland dc_plane_state_retain(plane_states[i]); 10614562236bSHarry Wentland 106205a19c39SDmytro Laktyushkin /* detach surfaces from pipes */ 106305a19c39SDmytro Laktyushkin for (i = 0; i < pool->pipe_count; i++) 106405a19c39SDmytro Laktyushkin if (context->res_ctx.pipe_ctx[i].stream == stream) { 10653be5262eSHarry Wentland context->res_ctx.pipe_ctx[i].plane_state = NULL; 106605a19c39SDmytro Laktyushkin context->res_ctx.pipe_ctx[i].bottom_pipe = NULL; 106705a19c39SDmytro Laktyushkin } 10684562236bSHarry Wentland 10694562236bSHarry Wentland /* release existing surfaces*/ 10703be5262eSHarry Wentland for (i = 0; i < stream_status->plane_count; i++) 10713be5262eSHarry Wentland dc_plane_state_release(stream_status->plane_states[i]); 10724562236bSHarry Wentland 10733be5262eSHarry Wentland for (i = surface_count; i < stream_status->plane_count; i++) 10743be5262eSHarry Wentland stream_status->plane_states[i] = NULL; 10754562236bSHarry Wentland 10764562236bSHarry Wentland tail_pipe = NULL; 10774562236bSHarry Wentland for (i = 0; i < surface_count; i++) { 10783be5262eSHarry Wentland struct dc_plane_state *plane_state = plane_states[i]; 1079a2b8659dSTony Cheng struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream( 10804fa086b9SLeo (Sunpeng) Li context, pool, stream); 10814562236bSHarry Wentland 10820f9a536fSDmytro Laktyushkin #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 10830f9a536fSDmytro Laktyushkin if (!free_pipe) { 10840f9a536fSDmytro Laktyushkin int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 10850f9a536fSDmytro Laktyushkin if (pipe_idx >= 0) 10860f9a536fSDmytro Laktyushkin free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; 10870f9a536fSDmytro Laktyushkin } 10880f9a536fSDmytro Laktyushkin #endif 10894562236bSHarry Wentland if (!free_pipe) { 10903be5262eSHarry Wentland stream_status->plane_states[i] = NULL; 10914562236bSHarry Wentland return false; 10924562236bSHarry Wentland } 10934562236bSHarry Wentland 10943be5262eSHarry Wentland free_pipe->plane_state = plane_state; 10954562236bSHarry Wentland 10964562236bSHarry Wentland if (tail_pipe) { 10976b670fa9SHarry Wentland free_pipe->stream_res.tg = tail_pipe->stream_res.tg; 1098a6a6cb34SHarry Wentland free_pipe->stream_res.opp = tail_pipe->stream_res.opp; 10998e9c4c8cSHarry Wentland free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; 1100cfe4645eSDmytro Laktyushkin free_pipe->audio = tail_pipe->audio; 1101cfe4645eSDmytro Laktyushkin free_pipe->clock_source = tail_pipe->clock_source; 11024562236bSHarry Wentland free_pipe->top_pipe = tail_pipe; 11034562236bSHarry Wentland tail_pipe->bottom_pipe = free_pipe; 11044562236bSHarry Wentland } 11054562236bSHarry Wentland 11064562236bSHarry Wentland tail_pipe = free_pipe; 11074562236bSHarry Wentland } 11084562236bSHarry Wentland 11094fa086b9SLeo (Sunpeng) Li release_free_pipes_for_stream(&context->res_ctx, stream); 11104562236bSHarry Wentland 11114562236bSHarry Wentland /* assign new surfaces*/ 11124562236bSHarry Wentland for (i = 0; i < surface_count; i++) 11133be5262eSHarry Wentland stream_status->plane_states[i] = plane_states[i]; 11144562236bSHarry Wentland 11153be5262eSHarry Wentland stream_status->plane_count = surface_count; 11164562236bSHarry Wentland 11174562236bSHarry Wentland return true; 11184562236bSHarry Wentland } 11194562236bSHarry Wentland 11204562236bSHarry Wentland 11210971c40eSHarry Wentland static bool is_timing_changed(struct dc_stream_state *cur_stream, 11220971c40eSHarry Wentland struct dc_stream_state *new_stream) 11234562236bSHarry Wentland { 11244562236bSHarry Wentland if (cur_stream == NULL) 11254562236bSHarry Wentland return true; 11264562236bSHarry Wentland 11274562236bSHarry Wentland /* If sink pointer changed, it means this is a hotplug, we should do 11284562236bSHarry Wentland * full hw setting. 11294562236bSHarry Wentland */ 11304562236bSHarry Wentland if (cur_stream->sink != new_stream->sink) 11314562236bSHarry Wentland return true; 11324562236bSHarry Wentland 11334562236bSHarry Wentland /* If output color space is changed, need to reprogram info frames */ 11344fa086b9SLeo (Sunpeng) Li if (cur_stream->output_color_space != new_stream->output_color_space) 11354562236bSHarry Wentland return true; 11364562236bSHarry Wentland 11374562236bSHarry Wentland return memcmp( 11384fa086b9SLeo (Sunpeng) Li &cur_stream->timing, 11394fa086b9SLeo (Sunpeng) Li &new_stream->timing, 11404562236bSHarry Wentland sizeof(struct dc_crtc_timing)) != 0; 11414562236bSHarry Wentland } 11424562236bSHarry Wentland 11434562236bSHarry Wentland static bool are_stream_backends_same( 11440971c40eSHarry Wentland struct dc_stream_state *stream_a, struct dc_stream_state *stream_b) 11454562236bSHarry Wentland { 11464562236bSHarry Wentland if (stream_a == stream_b) 11474562236bSHarry Wentland return true; 11484562236bSHarry Wentland 11494562236bSHarry Wentland if (stream_a == NULL || stream_b == NULL) 11504562236bSHarry Wentland return false; 11514562236bSHarry Wentland 11524562236bSHarry Wentland if (is_timing_changed(stream_a, stream_b)) 11534562236bSHarry Wentland return false; 11544562236bSHarry Wentland 11554562236bSHarry Wentland return true; 11564562236bSHarry Wentland } 11574562236bSHarry Wentland 1158d54d29dbSBhawanpreet Lakha bool dc_is_stream_unchanged( 11590971c40eSHarry Wentland struct dc_stream_state *old_stream, struct dc_stream_state *stream) 11604562236bSHarry Wentland { 11614562236bSHarry Wentland 11624562236bSHarry Wentland if (!are_stream_backends_same(old_stream, stream)) 11634562236bSHarry Wentland return false; 11644562236bSHarry Wentland 11654562236bSHarry Wentland return true; 11664562236bSHarry Wentland } 11674562236bSHarry Wentland 11684562236bSHarry Wentland bool resource_validate_attach_surfaces( 11694562236bSHarry Wentland const struct dc_validation_set set[], 11704562236bSHarry Wentland int set_count, 11714562236bSHarry Wentland const struct validate_context *old_context, 1172a2b8659dSTony Cheng struct validate_context *context, 1173a2b8659dSTony Cheng const struct resource_pool *pool) 11744562236bSHarry Wentland { 11754562236bSHarry Wentland int i, j; 11764562236bSHarry Wentland 11774562236bSHarry Wentland for (i = 0; i < set_count; i++) { 1178430ef426SDmytro Laktyushkin for (j = 0; old_context && j < old_context->stream_count; j++) 1179d54d29dbSBhawanpreet Lakha if (dc_is_stream_unchanged( 1180ab2541b6SAric Cyr old_context->streams[j], 1181ab2541b6SAric Cyr context->streams[i])) { 11824562236bSHarry Wentland if (!resource_attach_surfaces_to_context( 11833be5262eSHarry Wentland old_context->stream_status[j].plane_states, 11843be5262eSHarry Wentland old_context->stream_status[j].plane_count, 11854fa086b9SLeo (Sunpeng) Li context->streams[i], 1186a2b8659dSTony Cheng context, pool)) 11874562236bSHarry Wentland return false; 1188ab2541b6SAric Cyr context->stream_status[i] = old_context->stream_status[j]; 11894562236bSHarry Wentland } 11903be5262eSHarry Wentland if (set[i].plane_count != 0) 11914562236bSHarry Wentland if (!resource_attach_surfaces_to_context( 11923be5262eSHarry Wentland set[i].plane_states, 11933be5262eSHarry Wentland set[i].plane_count, 11944fa086b9SLeo (Sunpeng) Li context->streams[i], 1195a2b8659dSTony Cheng context, pool)) 11964562236bSHarry Wentland return false; 11974562236bSHarry Wentland 11984562236bSHarry Wentland } 11994562236bSHarry Wentland 12004562236bSHarry Wentland return true; 12014562236bSHarry Wentland } 12024562236bSHarry Wentland 12034562236bSHarry Wentland /* Maximum TMDS single link pixel clock 165MHz */ 12044562236bSHarry Wentland #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000 1205909e8c9eSCharlene Liu #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000 12064562236bSHarry Wentland 12074562236bSHarry Wentland static void set_stream_engine_in_use( 12084562236bSHarry Wentland struct resource_context *res_ctx, 1209a2b8659dSTony Cheng const struct resource_pool *pool, 12104562236bSHarry Wentland struct stream_encoder *stream_enc) 12114562236bSHarry Wentland { 12124562236bSHarry Wentland int i; 12134562236bSHarry Wentland 1214a2b8659dSTony Cheng for (i = 0; i < pool->stream_enc_count; i++) { 1215a2b8659dSTony Cheng if (pool->stream_enc[i] == stream_enc) 12164562236bSHarry Wentland res_ctx->is_stream_enc_acquired[i] = true; 12174562236bSHarry Wentland } 12184562236bSHarry Wentland } 12194562236bSHarry Wentland 12204562236bSHarry Wentland /* TODO: release audio object */ 12214562236bSHarry Wentland static void set_audio_in_use( 12224562236bSHarry Wentland struct resource_context *res_ctx, 1223a2b8659dSTony Cheng const struct resource_pool *pool, 12244562236bSHarry Wentland struct audio *audio) 12254562236bSHarry Wentland { 12264562236bSHarry Wentland int i; 1227a2b8659dSTony Cheng for (i = 0; i < pool->audio_count; i++) { 1228a2b8659dSTony Cheng if (pool->audios[i] == audio) 12294562236bSHarry Wentland res_ctx->is_audio_acquired[i] = true; 12304562236bSHarry Wentland } 12314562236bSHarry Wentland } 12324562236bSHarry Wentland 12334562236bSHarry Wentland static int acquire_first_free_pipe( 12344562236bSHarry Wentland struct resource_context *res_ctx, 1235a2b8659dSTony Cheng const struct resource_pool *pool, 12360971c40eSHarry Wentland struct dc_stream_state *stream) 12374562236bSHarry Wentland { 12384562236bSHarry Wentland int i; 12394562236bSHarry Wentland 1240a2b8659dSTony Cheng for (i = 0; i < pool->pipe_count; i++) { 12414562236bSHarry Wentland if (!res_ctx->pipe_ctx[i].stream) { 12424562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 12434562236bSHarry Wentland 12446b670fa9SHarry Wentland pipe_ctx->stream_res.tg = pool->timing_generators[i]; 124586a66c4eSHarry Wentland pipe_ctx->plane_res.mi = pool->mis[i]; 124686a66c4eSHarry Wentland pipe_ctx->plane_res.ipp = pool->ipps[i]; 124786a66c4eSHarry Wentland pipe_ctx->plane_res.xfm = pool->transforms[i]; 1248a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp = pool->opps[i]; 1249a2b8659dSTony Cheng pipe_ctx->dis_clk = pool->display_clock; 12504562236bSHarry Wentland pipe_ctx->pipe_idx = i; 12514562236bSHarry Wentland 1252ff5ef992SAlex Deucher 12534562236bSHarry Wentland pipe_ctx->stream = stream; 12544562236bSHarry Wentland return i; 12554562236bSHarry Wentland } 12564562236bSHarry Wentland } 12574562236bSHarry Wentland return -1; 12584562236bSHarry Wentland } 12594562236bSHarry Wentland 12604562236bSHarry Wentland static struct stream_encoder *find_first_free_match_stream_enc_for_link( 12614562236bSHarry Wentland struct resource_context *res_ctx, 1262a2b8659dSTony Cheng const struct resource_pool *pool, 12630971c40eSHarry Wentland struct dc_stream_state *stream) 12644562236bSHarry Wentland { 12654562236bSHarry Wentland int i; 12664562236bSHarry Wentland int j = -1; 1267d0778ebfSHarry Wentland struct dc_link *link = stream->sink->link; 12684562236bSHarry Wentland 1269a2b8659dSTony Cheng for (i = 0; i < pool->stream_enc_count; i++) { 12704562236bSHarry Wentland if (!res_ctx->is_stream_enc_acquired[i] && 1271a2b8659dSTony Cheng pool->stream_enc[i]) { 12724562236bSHarry Wentland /* Store first available for MST second display 12734562236bSHarry Wentland * in daisy chain use case */ 12744562236bSHarry Wentland j = i; 1275a2b8659dSTony Cheng if (pool->stream_enc[i]->id == 12764562236bSHarry Wentland link->link_enc->preferred_engine) 1277a2b8659dSTony Cheng return pool->stream_enc[i]; 12784562236bSHarry Wentland } 12794562236bSHarry Wentland } 12804562236bSHarry Wentland 12814562236bSHarry Wentland /* 12824562236bSHarry Wentland * below can happen in cases when stream encoder is acquired: 12834562236bSHarry Wentland * 1) for second MST display in chain, so preferred engine already 12844562236bSHarry Wentland * acquired; 12854562236bSHarry Wentland * 2) for another link, which preferred engine already acquired by any 12864562236bSHarry Wentland * MST configuration. 12874562236bSHarry Wentland * 12884562236bSHarry Wentland * If signal is of DP type and preferred engine not found, return last available 12894562236bSHarry Wentland * 12904562236bSHarry Wentland * TODO - This is just a patch up and a generic solution is 12914562236bSHarry Wentland * required for non DP connectors. 12924562236bSHarry Wentland */ 12934562236bSHarry Wentland 12944562236bSHarry Wentland if (j >= 0 && dc_is_dp_signal(stream->signal)) 1295a2b8659dSTony Cheng return pool->stream_enc[j]; 12964562236bSHarry Wentland 12974562236bSHarry Wentland return NULL; 12984562236bSHarry Wentland } 12994562236bSHarry Wentland 1300a2b8659dSTony Cheng static struct audio *find_first_free_audio( 1301a2b8659dSTony Cheng struct resource_context *res_ctx, 1302a2b8659dSTony Cheng const struct resource_pool *pool) 13034562236bSHarry Wentland { 13044562236bSHarry Wentland int i; 1305a2b8659dSTony Cheng for (i = 0; i < pool->audio_count; i++) { 13064562236bSHarry Wentland if (res_ctx->is_audio_acquired[i] == false) { 1307a2b8659dSTony Cheng return pool->audios[i]; 13084562236bSHarry Wentland } 13094562236bSHarry Wentland } 13104562236bSHarry Wentland 13114562236bSHarry Wentland return 0; 13124562236bSHarry Wentland } 13134562236bSHarry Wentland 13140971c40eSHarry Wentland static void update_stream_signal(struct dc_stream_state *stream) 13154562236bSHarry Wentland { 13164fa086b9SLeo (Sunpeng) Li if (stream->output_signal == SIGNAL_TYPE_NONE) { 13174fa086b9SLeo (Sunpeng) Li struct dc_sink *dc_sink = stream->sink; 13184562236bSHarry Wentland 13192796eaeeSJoshua Aberback if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) 1320d0778ebfSHarry Wentland stream->signal = stream->sink->link->connector_signal; 13212796eaeeSJoshua Aberback else 13222796eaeeSJoshua Aberback stream->signal = dc_sink->sink_signal; 13238b32076cSSylvia Tsai } else { 13244fa086b9SLeo (Sunpeng) Li stream->signal = stream->output_signal; 13258b32076cSSylvia Tsai } 13268b32076cSSylvia Tsai 132756dcade3SHarry Wentland if (dc_is_dvi_signal(stream->signal)) { 13284fa086b9SLeo (Sunpeng) Li if (stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST && 13294fa086b9SLeo (Sunpeng) Li stream->sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) 13308b32076cSSylvia Tsai stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; 133156dcade3SHarry Wentland else 133256dcade3SHarry Wentland stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; 133356dcade3SHarry Wentland } 13344562236bSHarry Wentland } 13354562236bSHarry Wentland 13364562236bSHarry Wentland bool resource_is_stream_unchanged( 13370971c40eSHarry Wentland struct validate_context *old_context, struct dc_stream_state *stream) 13384562236bSHarry Wentland { 1339ab2541b6SAric Cyr int i; 13404562236bSHarry Wentland 1341ab2541b6SAric Cyr for (i = 0; i < old_context->stream_count; i++) { 13420971c40eSHarry Wentland struct dc_stream_state *old_stream = old_context->streams[i]; 13434562236bSHarry Wentland 13444562236bSHarry Wentland if (are_stream_backends_same(old_stream, stream)) 13454562236bSHarry Wentland return true; 13464562236bSHarry Wentland } 13474562236bSHarry Wentland 13484562236bSHarry Wentland return false; 13494562236bSHarry Wentland } 13504562236bSHarry Wentland 13514562236bSHarry Wentland static void copy_pipe_ctx( 13524562236bSHarry Wentland const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx) 13534562236bSHarry Wentland { 13543be5262eSHarry Wentland struct dc_plane_state *plane_state = to_pipe_ctx->plane_state; 13550971c40eSHarry Wentland struct dc_stream_state *stream = to_pipe_ctx->stream; 13564562236bSHarry Wentland 13574562236bSHarry Wentland *to_pipe_ctx = *from_pipe_ctx; 13584562236bSHarry Wentland to_pipe_ctx->stream = stream; 13593be5262eSHarry Wentland if (plane_state != NULL) 13603be5262eSHarry Wentland to_pipe_ctx->plane_state = plane_state; 13614562236bSHarry Wentland } 13624562236bSHarry Wentland 13630971c40eSHarry Wentland static struct dc_stream_state *find_pll_sharable_stream( 13640971c40eSHarry Wentland struct dc_stream_state *stream_needs_pll, 13654562236bSHarry Wentland struct validate_context *context) 13664562236bSHarry Wentland { 1367ab2541b6SAric Cyr int i; 13684562236bSHarry Wentland 1369ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 13700971c40eSHarry Wentland struct dc_stream_state *stream_has_pll = context->streams[i]; 13714562236bSHarry Wentland 13724562236bSHarry Wentland /* We are looking for non dp, non virtual stream */ 13734562236bSHarry Wentland if (resource_are_streams_timing_synchronizable( 13744562236bSHarry Wentland stream_needs_pll, stream_has_pll) 13754562236bSHarry Wentland && !dc_is_dp_signal(stream_has_pll->signal) 1376d0778ebfSHarry Wentland && stream_has_pll->sink->link->connector_signal 13774562236bSHarry Wentland != SIGNAL_TYPE_VIRTUAL) 13784562236bSHarry Wentland return stream_has_pll; 1379ab2541b6SAric Cyr 13804562236bSHarry Wentland } 13814562236bSHarry Wentland 13824562236bSHarry Wentland return NULL; 13834562236bSHarry Wentland } 13844562236bSHarry Wentland 13854562236bSHarry Wentland static int get_norm_pix_clk(const struct dc_crtc_timing *timing) 13864562236bSHarry Wentland { 13874562236bSHarry Wentland uint32_t pix_clk = timing->pix_clk_khz; 13884562236bSHarry Wentland uint32_t normalized_pix_clk = pix_clk; 13894562236bSHarry Wentland 13904562236bSHarry Wentland if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) 13914562236bSHarry Wentland pix_clk /= 2; 1392cc4d99b8SCharlene Liu if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) { 13934562236bSHarry Wentland switch (timing->display_color_depth) { 13944562236bSHarry Wentland case COLOR_DEPTH_888: 13954562236bSHarry Wentland normalized_pix_clk = pix_clk; 13964562236bSHarry Wentland break; 13974562236bSHarry Wentland case COLOR_DEPTH_101010: 13984562236bSHarry Wentland normalized_pix_clk = (pix_clk * 30) / 24; 13994562236bSHarry Wentland break; 14004562236bSHarry Wentland case COLOR_DEPTH_121212: 14014562236bSHarry Wentland normalized_pix_clk = (pix_clk * 36) / 24; 14024562236bSHarry Wentland break; 14034562236bSHarry Wentland case COLOR_DEPTH_161616: 14044562236bSHarry Wentland normalized_pix_clk = (pix_clk * 48) / 24; 14054562236bSHarry Wentland break; 14064562236bSHarry Wentland default: 14074562236bSHarry Wentland ASSERT(0); 14084562236bSHarry Wentland break; 14094562236bSHarry Wentland } 1410cc4d99b8SCharlene Liu } 14114562236bSHarry Wentland return normalized_pix_clk; 14124562236bSHarry Wentland } 14134562236bSHarry Wentland 14140971c40eSHarry Wentland static void calculate_phy_pix_clks(struct dc_stream_state *stream) 14154562236bSHarry Wentland { 14164562236bSHarry Wentland update_stream_signal(stream); 14174562236bSHarry Wentland 14184562236bSHarry Wentland /* update actual pixel clock on all streams */ 14194562236bSHarry Wentland if (dc_is_hdmi_signal(stream->signal)) 14204562236bSHarry Wentland stream->phy_pix_clk = get_norm_pix_clk( 14214fa086b9SLeo (Sunpeng) Li &stream->timing); 14224562236bSHarry Wentland else 14234562236bSHarry Wentland stream->phy_pix_clk = 14244fa086b9SLeo (Sunpeng) Li stream->timing.pix_clk_khz; 14254562236bSHarry Wentland } 14264562236bSHarry Wentland 14274562236bSHarry Wentland enum dc_status resource_map_pool_resources( 14284562236bSHarry Wentland const struct core_dc *dc, 1429430ef426SDmytro Laktyushkin struct validate_context *context, 1430430ef426SDmytro Laktyushkin struct validate_context *old_context) 14314562236bSHarry Wentland { 1432a2b8659dSTony Cheng const struct resource_pool *pool = dc->res_pool; 1433ab2541b6SAric Cyr int i, j; 14344562236bSHarry Wentland 1435430ef426SDmytro Laktyushkin for (i = 0; old_context && i < context->stream_count; i++) { 14360971c40eSHarry Wentland struct dc_stream_state *stream = context->streams[i]; 14374562236bSHarry Wentland 1438430ef426SDmytro Laktyushkin if (!resource_is_stream_unchanged(old_context, stream)) { 1439430ef426SDmytro Laktyushkin if (stream != NULL && old_context->streams[i] != NULL) { 14404b679bc3SCharlene Liu stream->bit_depth_params = 1441430ef426SDmytro Laktyushkin old_context->streams[i]->bit_depth_params; 1442430ef426SDmytro Laktyushkin stream->clamping = old_context->streams[i]->clamping; 14434562236bSHarry Wentland continue; 14444b679bc3SCharlene Liu } 14454b679bc3SCharlene Liu } 14467e2fe319SCharlene Liu 14474562236bSHarry Wentland /* mark resources used for stream that is already active */ 1448a2b8659dSTony Cheng for (j = 0; j < pool->pipe_count; j++) { 14494562236bSHarry Wentland struct pipe_ctx *pipe_ctx = 1450ab2541b6SAric Cyr &context->res_ctx.pipe_ctx[j]; 14514562236bSHarry Wentland const struct pipe_ctx *old_pipe_ctx = 1452430ef426SDmytro Laktyushkin &old_context->res_ctx.pipe_ctx[j]; 14534562236bSHarry Wentland 14544562236bSHarry Wentland if (!are_stream_backends_same(old_pipe_ctx->stream, stream)) 14554562236bSHarry Wentland continue; 14564562236bSHarry Wentland 1457268cadbdSYongqiang Sun if (old_pipe_ctx->top_pipe) 1458268cadbdSYongqiang Sun continue; 1459268cadbdSYongqiang Sun 14604562236bSHarry Wentland pipe_ctx->stream = stream; 14614562236bSHarry Wentland copy_pipe_ctx(old_pipe_ctx, pipe_ctx); 14624562236bSHarry Wentland 14638c737fccSYongqiang Sun /* Split pipe resource, do not acquire back end */ 14648e9c4c8cSHarry Wentland if (!pipe_ctx->stream_res.stream_enc) 14658c737fccSYongqiang Sun continue; 14668c737fccSYongqiang Sun 14674562236bSHarry Wentland set_stream_engine_in_use( 1468a2b8659dSTony Cheng &context->res_ctx, pool, 14698e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc); 14704562236bSHarry Wentland 14714562236bSHarry Wentland /* Switch to dp clock source only if there is 14724562236bSHarry Wentland * no non dp stream that shares the same timing 14734562236bSHarry Wentland * with the dp stream. 14744562236bSHarry Wentland */ 14754562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal) && 14764562236bSHarry Wentland !find_pll_sharable_stream(stream, context)) 1477a2b8659dSTony Cheng pipe_ctx->clock_source = pool->dp_clock_source; 14784562236bSHarry Wentland 14794562236bSHarry Wentland resource_reference_clock_source( 1480a2b8659dSTony Cheng &context->res_ctx, pool, 14814562236bSHarry Wentland pipe_ctx->clock_source); 14824562236bSHarry Wentland 1483a2b8659dSTony Cheng set_audio_in_use(&context->res_ctx, pool, 14844562236bSHarry Wentland pipe_ctx->audio); 14854562236bSHarry Wentland } 14864562236bSHarry Wentland } 14874562236bSHarry Wentland 1488ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 14890971c40eSHarry Wentland struct dc_stream_state *stream = context->streams[i]; 14904562236bSHarry Wentland struct pipe_ctx *pipe_ctx = NULL; 14914562236bSHarry Wentland int pipe_idx = -1; 14924562236bSHarry Wentland 1493430ef426SDmytro Laktyushkin if (old_context && resource_is_stream_unchanged(old_context, stream)) 14944562236bSHarry Wentland continue; 14954562236bSHarry Wentland /* acquire new resources */ 14965d11e9fcSDmytro Laktyushkin pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); 14975d11e9fcSDmytro Laktyushkin #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 14985d11e9fcSDmytro Laktyushkin if (pipe_idx < 0) 14995d11e9fcSDmytro Laktyushkin acquire_first_split_pipe(&context->res_ctx, pool, stream); 15005d11e9fcSDmytro Laktyushkin #endif 15014562236bSHarry Wentland if (pipe_idx < 0) 15024562236bSHarry Wentland return DC_NO_CONTROLLER_RESOURCE; 15034562236bSHarry Wentland 15044562236bSHarry Wentland pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; 15054562236bSHarry Wentland 15068e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc = 15074562236bSHarry Wentland find_first_free_match_stream_enc_for_link( 1508a2b8659dSTony Cheng &context->res_ctx, pool, stream); 15094562236bSHarry Wentland 15108e9c4c8cSHarry Wentland if (!pipe_ctx->stream_res.stream_enc) 15114562236bSHarry Wentland return DC_NO_STREAM_ENG_RESOURCE; 15124562236bSHarry Wentland 15134562236bSHarry Wentland set_stream_engine_in_use( 1514a2b8659dSTony Cheng &context->res_ctx, pool, 15158e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc); 15164562236bSHarry Wentland 15174562236bSHarry Wentland /* TODO: Add check if ASIC support and EDID audio */ 1518b73a22d3SHarry Wentland if (!stream->sink->converter_disable_audio && 15194562236bSHarry Wentland dc_is_audio_capable_signal(pipe_ctx->stream->signal) && 15204fa086b9SLeo (Sunpeng) Li stream->audio_info.mode_count) { 15214562236bSHarry Wentland pipe_ctx->audio = find_first_free_audio( 1522a2b8659dSTony Cheng &context->res_ctx, pool); 15234562236bSHarry Wentland 15244562236bSHarry Wentland /* 15254562236bSHarry Wentland * Audio assigned in order first come first get. 15264562236bSHarry Wentland * There are asics which has number of audio 15274562236bSHarry Wentland * resources less then number of pipes 15284562236bSHarry Wentland */ 15294562236bSHarry Wentland if (pipe_ctx->audio) 15304562236bSHarry Wentland set_audio_in_use( 1531a2b8659dSTony Cheng &context->res_ctx, pool, 15324562236bSHarry Wentland pipe_ctx->audio); 15334562236bSHarry Wentland } 15344562236bSHarry Wentland 15356b670fa9SHarry Wentland context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; 15364562236bSHarry Wentland } 15374562236bSHarry Wentland 15384562236bSHarry Wentland return DC_OK; 15394562236bSHarry Wentland } 15404562236bSHarry Wentland 1541ab2541b6SAric Cyr /* first stream in the context is used to populate the rest */ 1542ab2541b6SAric Cyr void validate_guaranteed_copy_streams( 15434562236bSHarry Wentland struct validate_context *context, 1544ab2541b6SAric Cyr int max_streams) 15454562236bSHarry Wentland { 15464562236bSHarry Wentland int i; 15474562236bSHarry Wentland 1548ab2541b6SAric Cyr for (i = 1; i < max_streams; i++) { 1549ab2541b6SAric Cyr context->streams[i] = context->streams[0]; 15504562236bSHarry Wentland 15514562236bSHarry Wentland copy_pipe_ctx(&context->res_ctx.pipe_ctx[0], 15524562236bSHarry Wentland &context->res_ctx.pipe_ctx[i]); 15534562236bSHarry Wentland context->res_ctx.pipe_ctx[i].stream = 15544562236bSHarry Wentland context->res_ctx.pipe_ctx[0].stream; 15554562236bSHarry Wentland 15564fa086b9SLeo (Sunpeng) Li dc_stream_retain(context->streams[i]); 1557ab2541b6SAric Cyr context->stream_count++; 15584562236bSHarry Wentland } 15594562236bSHarry Wentland } 15604562236bSHarry Wentland 15616e4d6beeSTony Cheng static void patch_gamut_packet_checksum( 15626e4d6beeSTony Cheng struct encoder_info_packet *gamut_packet) 15634562236bSHarry Wentland { 15644562236bSHarry Wentland /* For gamut we recalc checksum */ 15656e4d6beeSTony Cheng if (gamut_packet->valid) { 15664562236bSHarry Wentland uint8_t chk_sum = 0; 15674562236bSHarry Wentland uint8_t *ptr; 15684562236bSHarry Wentland uint8_t i; 15694562236bSHarry Wentland 15704562236bSHarry Wentland /*start of the Gamut data. */ 15716e4d6beeSTony Cheng ptr = &gamut_packet->sb[3]; 15724562236bSHarry Wentland 15736e4d6beeSTony Cheng for (i = 0; i <= gamut_packet->sb[1]; i++) 15744562236bSHarry Wentland chk_sum += ptr[i]; 15754562236bSHarry Wentland 15766e4d6beeSTony Cheng gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum); 15771646a6feSAndrew Wong } 15784562236bSHarry Wentland } 15794562236bSHarry Wentland 15804562236bSHarry Wentland static void set_avi_info_frame( 15816e4d6beeSTony Cheng struct encoder_info_packet *info_packet, 15824562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 15834562236bSHarry Wentland { 15840971c40eSHarry Wentland struct dc_stream_state *stream = pipe_ctx->stream; 15854562236bSHarry Wentland enum dc_color_space color_space = COLOR_SPACE_UNKNOWN; 15864562236bSHarry Wentland struct info_frame info_frame = { {0} }; 15874562236bSHarry Wentland uint32_t pixel_encoding = 0; 15884562236bSHarry Wentland enum scanning_type scan_type = SCANNING_TYPE_NODATA; 15894562236bSHarry Wentland enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA; 15904562236bSHarry Wentland bool itc = false; 159150e27654SZeyu Fan uint8_t itc_value = 0; 15924562236bSHarry Wentland uint8_t cn0_cn1 = 0; 159350e27654SZeyu Fan unsigned int cn0_cn1_value = 0; 15944562236bSHarry Wentland uint8_t *check_sum = NULL; 15954562236bSHarry Wentland uint8_t byte_index = 0; 1596e8d726b7SReza Amini union hdmi_info_packet *hdmi_info = &info_frame.avi_info_packet.info_packet_hdmi; 159750e27654SZeyu Fan union display_content_support support = {0}; 15984fa086b9SLeo (Sunpeng) Li unsigned int vic = pipe_ctx->stream->timing.vic; 159915e17335SCharlene Liu enum dc_timing_3d_format format; 16004562236bSHarry Wentland 16014fa086b9SLeo (Sunpeng) Li color_space = pipe_ctx->stream->output_color_space; 1602e5f2038eSCharlene Liu if (color_space == COLOR_SPACE_UNKNOWN) 16034fa086b9SLeo (Sunpeng) Li color_space = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ? 1604e5f2038eSCharlene Liu COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709; 16054562236bSHarry Wentland 16064562236bSHarry Wentland /* Initialize header */ 1607e8d726b7SReza Amini hdmi_info->bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI; 16084562236bSHarry Wentland /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall 16094562236bSHarry Wentland * not be used in HDMI 2.0 (Section 10.1) */ 1610e8d726b7SReza Amini hdmi_info->bits.header.version = 2; 1611e8d726b7SReza Amini hdmi_info->bits.header.length = HDMI_AVI_INFOFRAME_SIZE; 16124562236bSHarry Wentland 16134562236bSHarry Wentland /* 16144562236bSHarry Wentland * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built 16154562236bSHarry Wentland * according to HDMI 2.0 spec (Section 10.1) 16164562236bSHarry Wentland */ 16174562236bSHarry Wentland 16184fa086b9SLeo (Sunpeng) Li switch (stream->timing.pixel_encoding) { 16194562236bSHarry Wentland case PIXEL_ENCODING_YCBCR422: 16204562236bSHarry Wentland pixel_encoding = 1; 16214562236bSHarry Wentland break; 16224562236bSHarry Wentland 16234562236bSHarry Wentland case PIXEL_ENCODING_YCBCR444: 16244562236bSHarry Wentland pixel_encoding = 2; 16254562236bSHarry Wentland break; 16264562236bSHarry Wentland case PIXEL_ENCODING_YCBCR420: 16274562236bSHarry Wentland pixel_encoding = 3; 16284562236bSHarry Wentland break; 16294562236bSHarry Wentland 16304562236bSHarry Wentland case PIXEL_ENCODING_RGB: 16314562236bSHarry Wentland default: 16324562236bSHarry Wentland pixel_encoding = 0; 16334562236bSHarry Wentland } 16344562236bSHarry Wentland 16354562236bSHarry Wentland /* Y0_Y1_Y2 : The pixel encoding */ 16364562236bSHarry Wentland /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */ 1637e8d726b7SReza Amini hdmi_info->bits.Y0_Y1_Y2 = pixel_encoding; 16384562236bSHarry Wentland 16394562236bSHarry Wentland /* A0 = 1 Active Format Information valid */ 1640e8d726b7SReza Amini hdmi_info->bits.A0 = ACTIVE_FORMAT_VALID; 16414562236bSHarry Wentland 16424562236bSHarry Wentland /* B0, B1 = 3; Bar info data is valid */ 1643e8d726b7SReza Amini hdmi_info->bits.B0_B1 = BAR_INFO_BOTH_VALID; 16444562236bSHarry Wentland 1645e8d726b7SReza Amini hdmi_info->bits.SC0_SC1 = PICTURE_SCALING_UNIFORM; 16464562236bSHarry Wentland 16474562236bSHarry Wentland /* S0, S1 : Underscan / Overscan */ 16484562236bSHarry Wentland /* TODO: un-hardcode scan type */ 16494562236bSHarry Wentland scan_type = SCANNING_TYPE_UNDERSCAN; 1650e8d726b7SReza Amini hdmi_info->bits.S0_S1 = scan_type; 16514562236bSHarry Wentland 16524562236bSHarry Wentland /* C0, C1 : Colorimetry */ 16538fde5884SCharlene Liu if (color_space == COLOR_SPACE_YCBCR709 || 165415e17335SCharlene Liu color_space == COLOR_SPACE_YCBCR709_LIMITED) 1655e8d726b7SReza Amini hdmi_info->bits.C0_C1 = COLORIMETRY_ITU709; 16568fde5884SCharlene Liu else if (color_space == COLOR_SPACE_YCBCR601 || 16578fde5884SCharlene Liu color_space == COLOR_SPACE_YCBCR601_LIMITED) 1658e8d726b7SReza Amini hdmi_info->bits.C0_C1 = COLORIMETRY_ITU601; 16598fde5884SCharlene Liu else { 1660e8d726b7SReza Amini hdmi_info->bits.C0_C1 = COLORIMETRY_NO_DATA; 16618fde5884SCharlene Liu } 1662534db198SAmy Zhang if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE || 1663534db198SAmy Zhang color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE || 1664534db198SAmy Zhang color_space == COLOR_SPACE_2020_YCBCR) { 1665e8d726b7SReza Amini hdmi_info->bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR; 1666e8d726b7SReza Amini hdmi_info->bits.C0_C1 = COLORIMETRY_EXTENDED; 1667534db198SAmy Zhang } else if (color_space == COLOR_SPACE_ADOBERGB) { 1668e8d726b7SReza Amini hdmi_info->bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB; 1669e8d726b7SReza Amini hdmi_info->bits.C0_C1 = COLORIMETRY_EXTENDED; 1670534db198SAmy Zhang } 1671534db198SAmy Zhang 16724562236bSHarry Wentland /* TODO: un-hardcode aspect ratio */ 16734fa086b9SLeo (Sunpeng) Li aspect = stream->timing.aspect_ratio; 16744562236bSHarry Wentland 16754562236bSHarry Wentland switch (aspect) { 16764562236bSHarry Wentland case ASPECT_RATIO_4_3: 16774562236bSHarry Wentland case ASPECT_RATIO_16_9: 1678e8d726b7SReza Amini hdmi_info->bits.M0_M1 = aspect; 16794562236bSHarry Wentland break; 16804562236bSHarry Wentland 16814562236bSHarry Wentland case ASPECT_RATIO_NO_DATA: 16824562236bSHarry Wentland case ASPECT_RATIO_64_27: 16834562236bSHarry Wentland case ASPECT_RATIO_256_135: 16844562236bSHarry Wentland default: 1685e8d726b7SReza Amini hdmi_info->bits.M0_M1 = 0; 16864562236bSHarry Wentland } 16874562236bSHarry Wentland 16884562236bSHarry Wentland /* Active Format Aspect ratio - same as Picture Aspect Ratio. */ 1689e8d726b7SReza Amini hdmi_info->bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; 16904562236bSHarry Wentland 16914562236bSHarry Wentland /* TODO: un-hardcode cn0_cn1 and itc */ 169250e27654SZeyu Fan 16934562236bSHarry Wentland cn0_cn1 = 0; 169450e27654SZeyu Fan cn0_cn1_value = 0; 169550e27654SZeyu Fan 169650e27654SZeyu Fan itc = true; 169750e27654SZeyu Fan itc_value = 1; 169850e27654SZeyu Fan 16994fa086b9SLeo (Sunpeng) Li support = stream->sink->edid_caps.content_support; 17004562236bSHarry Wentland 17014562236bSHarry Wentland if (itc) { 170250e27654SZeyu Fan if (!support.bits.valid_content_type) { 170350e27654SZeyu Fan cn0_cn1_value = 0; 170450e27654SZeyu Fan } else { 170550e27654SZeyu Fan if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) { 170650e27654SZeyu Fan if (support.bits.graphics_content == 1) { 170750e27654SZeyu Fan cn0_cn1_value = 0; 170850e27654SZeyu Fan } 170950e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) { 171050e27654SZeyu Fan if (support.bits.photo_content == 1) { 171150e27654SZeyu Fan cn0_cn1_value = 1; 171250e27654SZeyu Fan } else { 171350e27654SZeyu Fan cn0_cn1_value = 0; 171450e27654SZeyu Fan itc_value = 0; 171550e27654SZeyu Fan } 171650e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) { 171750e27654SZeyu Fan if (support.bits.cinema_content == 1) { 171850e27654SZeyu Fan cn0_cn1_value = 2; 171950e27654SZeyu Fan } else { 172050e27654SZeyu Fan cn0_cn1_value = 0; 172150e27654SZeyu Fan itc_value = 0; 172250e27654SZeyu Fan } 172350e27654SZeyu Fan } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) { 172450e27654SZeyu Fan if (support.bits.game_content == 1) { 172550e27654SZeyu Fan cn0_cn1_value = 3; 172650e27654SZeyu Fan } else { 172750e27654SZeyu Fan cn0_cn1_value = 0; 172850e27654SZeyu Fan itc_value = 0; 172950e27654SZeyu Fan } 173050e27654SZeyu Fan } 173150e27654SZeyu Fan } 173250e27654SZeyu Fan hdmi_info->bits.CN0_CN1 = cn0_cn1_value; 173350e27654SZeyu Fan hdmi_info->bits.ITC = itc_value; 17344562236bSHarry Wentland } 17354562236bSHarry Wentland 17364562236bSHarry Wentland /* TODO : We should handle YCC quantization */ 17374562236bSHarry Wentland /* but we do not have matrix calculation */ 17384fa086b9SLeo (Sunpeng) Li if (stream->sink->edid_caps.qs_bit == 1 && 17394fa086b9SLeo (Sunpeng) Li stream->sink->edid_caps.qy_bit == 1) { 174050e27654SZeyu Fan if (color_space == COLOR_SPACE_SRGB || 174150e27654SZeyu Fan color_space == COLOR_SPACE_2020_RGB_FULLRANGE) { 1742e8d726b7SReza Amini hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; 1743e8d726b7SReza Amini hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_FULL_RANGE; 174450e27654SZeyu Fan } else if (color_space == COLOR_SPACE_SRGB_LIMITED || 174550e27654SZeyu Fan color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) { 1746e8d726b7SReza Amini hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE; 1747e8d726b7SReza Amini hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 17484562236bSHarry Wentland } else { 1749e8d726b7SReza Amini hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 1750e8d726b7SReza Amini hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 17514562236bSHarry Wentland } 175250e27654SZeyu Fan } else { 175350e27654SZeyu Fan hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 175450e27654SZeyu Fan hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 175550e27654SZeyu Fan } 175650e27654SZeyu Fan 175715e17335SCharlene Liu ///VIC 17584fa086b9SLeo (Sunpeng) Li format = stream->timing.timing_3d_format; 175915e17335SCharlene Liu /*todo, add 3DStereo support*/ 176015e17335SCharlene Liu if (format != TIMING_3D_FORMAT_NONE) { 176115e17335SCharlene Liu // Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled 17624fa086b9SLeo (Sunpeng) Li switch (pipe_ctx->stream->timing.hdmi_vic) { 176315e17335SCharlene Liu case 1: 176415e17335SCharlene Liu vic = 95; 176515e17335SCharlene Liu break; 176615e17335SCharlene Liu case 2: 176715e17335SCharlene Liu vic = 94; 176815e17335SCharlene Liu break; 176915e17335SCharlene Liu case 3: 177015e17335SCharlene Liu vic = 93; 177115e17335SCharlene Liu break; 177215e17335SCharlene Liu case 4: 177315e17335SCharlene Liu vic = 98; 177415e17335SCharlene Liu break; 177515e17335SCharlene Liu default: 177615e17335SCharlene Liu break; 177715e17335SCharlene Liu } 177815e17335SCharlene Liu } 177915e17335SCharlene Liu hdmi_info->bits.VIC0_VIC7 = vic; 17804562236bSHarry Wentland 17814562236bSHarry Wentland /* pixel repetition 17824562236bSHarry Wentland * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel 17834562236bSHarry Wentland * repetition start from 1 */ 1784e8d726b7SReza Amini hdmi_info->bits.PR0_PR3 = 0; 17854562236bSHarry Wentland 17864562236bSHarry Wentland /* Bar Info 17874562236bSHarry Wentland * barTop: Line Number of End of Top Bar. 17884562236bSHarry Wentland * barBottom: Line Number of Start of Bottom Bar. 17894562236bSHarry Wentland * barLeft: Pixel Number of End of Left Bar. 17904562236bSHarry Wentland * barRight: Pixel Number of Start of Right Bar. */ 17914fa086b9SLeo (Sunpeng) Li hdmi_info->bits.bar_top = stream->timing.v_border_top; 17924fa086b9SLeo (Sunpeng) Li hdmi_info->bits.bar_bottom = (stream->timing.v_total 17934fa086b9SLeo (Sunpeng) Li - stream->timing.v_border_bottom + 1); 17944fa086b9SLeo (Sunpeng) Li hdmi_info->bits.bar_left = stream->timing.h_border_left; 17954fa086b9SLeo (Sunpeng) Li hdmi_info->bits.bar_right = (stream->timing.h_total 17964fa086b9SLeo (Sunpeng) Li - stream->timing.h_border_right + 1); 17974562236bSHarry Wentland 17984562236bSHarry Wentland /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ 1799e8d726b7SReza Amini check_sum = &info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0]; 1800e8d726b7SReza Amini 18013e183c5fSDave Airlie *check_sum = HDMI_INFOFRAME_TYPE_AVI + HDMI_AVI_INFOFRAME_SIZE + 2; 18024562236bSHarry Wentland 18033e183c5fSDave Airlie for (byte_index = 1; byte_index <= HDMI_AVI_INFOFRAME_SIZE; byte_index++) 1804e8d726b7SReza Amini *check_sum += hdmi_info->packet_raw_data.sb[byte_index]; 18054562236bSHarry Wentland 18064562236bSHarry Wentland /* one byte complement */ 18074562236bSHarry Wentland *check_sum = (uint8_t) (0x100 - *check_sum); 18084562236bSHarry Wentland 18094562236bSHarry Wentland /* Store in hw_path_mode */ 1810e8d726b7SReza Amini info_packet->hb0 = hdmi_info->packet_raw_data.hb0; 1811e8d726b7SReza Amini info_packet->hb1 = hdmi_info->packet_raw_data.hb1; 1812e8d726b7SReza Amini info_packet->hb2 = hdmi_info->packet_raw_data.hb2; 18134562236bSHarry Wentland 1814e66e4d64SHarry Wentland for (byte_index = 0; byte_index < sizeof(info_frame.avi_info_packet. 1815e66e4d64SHarry Wentland info_packet_hdmi.packet_raw_data.sb); byte_index++) 18164562236bSHarry Wentland info_packet->sb[byte_index] = info_frame.avi_info_packet. 18174562236bSHarry Wentland info_packet_hdmi.packet_raw_data.sb[byte_index]; 18184562236bSHarry Wentland 18194562236bSHarry Wentland info_packet->valid = true; 18204562236bSHarry Wentland } 18214562236bSHarry Wentland 18226e4d6beeSTony Cheng static void set_vendor_info_packet( 18236e4d6beeSTony Cheng struct encoder_info_packet *info_packet, 18240971c40eSHarry Wentland struct dc_stream_state *stream) 18254562236bSHarry Wentland { 18264562236bSHarry Wentland uint32_t length = 0; 18274562236bSHarry Wentland bool hdmi_vic_mode = false; 18284562236bSHarry Wentland uint8_t checksum = 0; 18294562236bSHarry Wentland uint32_t i = 0; 18304562236bSHarry Wentland enum dc_timing_3d_format format; 183115e17335SCharlene Liu // Can be different depending on packet content /*todo*/ 183215e17335SCharlene Liu // unsigned int length = pPathMode->dolbyVision ? 24 : 5; 183315e17335SCharlene Liu 183415e17335SCharlene Liu info_packet->valid = false; 18354562236bSHarry Wentland 18364fa086b9SLeo (Sunpeng) Li format = stream->timing.timing_3d_format; 18374fa086b9SLeo (Sunpeng) Li if (stream->view_format == VIEW_3D_FORMAT_NONE) 18387f5c22d1SVitaly Prosyak format = TIMING_3D_FORMAT_NONE; 18394562236bSHarry Wentland 18404562236bSHarry Wentland /* Can be different depending on packet content */ 18414562236bSHarry Wentland length = 5; 18424562236bSHarry Wentland 18434fa086b9SLeo (Sunpeng) Li if (stream->timing.hdmi_vic != 0 18444fa086b9SLeo (Sunpeng) Li && stream->timing.h_total >= 3840 18454fa086b9SLeo (Sunpeng) Li && stream->timing.v_total >= 2160) 18464562236bSHarry Wentland hdmi_vic_mode = true; 18474562236bSHarry Wentland 18484562236bSHarry Wentland /* According to HDMI 1.4a CTS, VSIF should be sent 18494562236bSHarry Wentland * for both 3D stereo and HDMI VIC modes. 18504562236bSHarry Wentland * For all other modes, there is no VSIF sent. */ 18514562236bSHarry Wentland 18524562236bSHarry Wentland if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode) 18534562236bSHarry Wentland return; 18544562236bSHarry Wentland 18554562236bSHarry Wentland /* 24bit IEEE Registration identifier (0x000c03). LSB first. */ 18564562236bSHarry Wentland info_packet->sb[1] = 0x03; 18574562236bSHarry Wentland info_packet->sb[2] = 0x0C; 18584562236bSHarry Wentland info_packet->sb[3] = 0x00; 18594562236bSHarry Wentland 18604562236bSHarry Wentland /*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format. 18614562236bSHarry Wentland * The value for HDMI_Video_Format are: 18624562236bSHarry Wentland * 0x0 (0b000) - No additional HDMI video format is presented in this 18634562236bSHarry Wentland * packet 18644562236bSHarry Wentland * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC 18654562236bSHarry Wentland * parameter follows 18664562236bSHarry Wentland * 0x2 (0b010) - 3D format indication present. 3D_Structure and 18674562236bSHarry Wentland * potentially 3D_Ext_Data follows 18684562236bSHarry Wentland * 0x3..0x7 (0b011..0b111) - reserved for future use */ 18694562236bSHarry Wentland if (format != TIMING_3D_FORMAT_NONE) 18704562236bSHarry Wentland info_packet->sb[4] = (2 << 5); 18714562236bSHarry Wentland else if (hdmi_vic_mode) 18724562236bSHarry Wentland info_packet->sb[4] = (1 << 5); 18734562236bSHarry Wentland 18744562236bSHarry Wentland /* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2): 18754562236bSHarry Wentland * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure. 18764562236bSHarry Wentland * The value for 3D_Structure are: 18774562236bSHarry Wentland * 0x0 - Frame Packing 18784562236bSHarry Wentland * 0x1 - Field Alternative 18794562236bSHarry Wentland * 0x2 - Line Alternative 18804562236bSHarry Wentland * 0x3 - Side-by-Side (full) 18814562236bSHarry Wentland * 0x4 - L + depth 18824562236bSHarry Wentland * 0x5 - L + depth + graphics + graphics-depth 18834562236bSHarry Wentland * 0x6 - Top-and-Bottom 18844562236bSHarry Wentland * 0x7 - Reserved for future use 18854562236bSHarry Wentland * 0x8 - Side-by-Side (Half) 18864562236bSHarry Wentland * 0x9..0xE - Reserved for future use 18874562236bSHarry Wentland * 0xF - Not used */ 18884562236bSHarry Wentland switch (format) { 18894562236bSHarry Wentland case TIMING_3D_FORMAT_HW_FRAME_PACKING: 18904562236bSHarry Wentland case TIMING_3D_FORMAT_SW_FRAME_PACKING: 18914562236bSHarry Wentland info_packet->sb[5] = (0x0 << 4); 18924562236bSHarry Wentland break; 18934562236bSHarry Wentland 18944562236bSHarry Wentland case TIMING_3D_FORMAT_SIDE_BY_SIDE: 18954562236bSHarry Wentland case TIMING_3D_FORMAT_SBS_SW_PACKED: 18964562236bSHarry Wentland info_packet->sb[5] = (0x8 << 4); 18974562236bSHarry Wentland length = 6; 18984562236bSHarry Wentland break; 18994562236bSHarry Wentland 19004562236bSHarry Wentland case TIMING_3D_FORMAT_TOP_AND_BOTTOM: 19014562236bSHarry Wentland case TIMING_3D_FORMAT_TB_SW_PACKED: 19024562236bSHarry Wentland info_packet->sb[5] = (0x6 << 4); 19034562236bSHarry Wentland break; 19044562236bSHarry Wentland 19054562236bSHarry Wentland default: 19064562236bSHarry Wentland break; 19074562236bSHarry Wentland } 19084562236bSHarry Wentland 19094562236bSHarry Wentland /*PB5: If PB4 is set to 0x1 (extended resolution format) 19104562236bSHarry Wentland * fill PB5 with the correct HDMI VIC code */ 19114562236bSHarry Wentland if (hdmi_vic_mode) 19124fa086b9SLeo (Sunpeng) Li info_packet->sb[5] = stream->timing.hdmi_vic; 19134562236bSHarry Wentland 19144562236bSHarry Wentland /* Header */ 19153e183c5fSDave Airlie info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR; /* VSIF packet type. */ 19164562236bSHarry Wentland info_packet->hb1 = 0x01; /* Version */ 19174562236bSHarry Wentland 19184562236bSHarry Wentland /* 4 lower bits = Length, 4 higher bits = 0 (reserved) */ 19194562236bSHarry Wentland info_packet->hb2 = (uint8_t) (length); 19204562236bSHarry Wentland 19214562236bSHarry Wentland /* Calculate checksum */ 19224562236bSHarry Wentland checksum = 0; 19234562236bSHarry Wentland checksum += info_packet->hb0; 19244562236bSHarry Wentland checksum += info_packet->hb1; 19254562236bSHarry Wentland checksum += info_packet->hb2; 19264562236bSHarry Wentland 19274562236bSHarry Wentland for (i = 1; i <= length; i++) 19284562236bSHarry Wentland checksum += info_packet->sb[i]; 19294562236bSHarry Wentland 19304562236bSHarry Wentland info_packet->sb[0] = (uint8_t) (0x100 - checksum); 19314562236bSHarry Wentland 19324562236bSHarry Wentland info_packet->valid = true; 19334562236bSHarry Wentland } 19344562236bSHarry Wentland 19356e4d6beeSTony Cheng static void set_spd_info_packet( 19366e4d6beeSTony Cheng struct encoder_info_packet *info_packet, 19370971c40eSHarry Wentland struct dc_stream_state *stream) 19384562236bSHarry Wentland { 19394562236bSHarry Wentland /* SPD info packet for FreeSync */ 19404562236bSHarry Wentland 19414562236bSHarry Wentland unsigned char checksum = 0; 19424562236bSHarry Wentland unsigned int idx, payload_size = 0; 19434562236bSHarry Wentland 19444562236bSHarry Wentland /* Check if Freesync is supported. Return if false. If true, 19454562236bSHarry Wentland * set the corresponding bit in the info packet 19464562236bSHarry Wentland */ 19474fa086b9SLeo (Sunpeng) Li if (stream->freesync_ctx.supported == false) 19484562236bSHarry Wentland return; 19494562236bSHarry Wentland 19504562236bSHarry Wentland if (dc_is_hdmi_signal(stream->signal)) { 19514562236bSHarry Wentland 19524562236bSHarry Wentland /* HEADER */ 19534562236bSHarry Wentland 19544562236bSHarry Wentland /* HB0 = Packet Type = 0x83 (Source Product 19554562236bSHarry Wentland * Descriptor InfoFrame) 19564562236bSHarry Wentland */ 19573e183c5fSDave Airlie info_packet->hb0 = HDMI_INFOFRAME_TYPE_SPD; 19584562236bSHarry Wentland 19594562236bSHarry Wentland /* HB1 = Version = 0x01 */ 19604562236bSHarry Wentland info_packet->hb1 = 0x01; 19614562236bSHarry Wentland 19624562236bSHarry Wentland /* HB2 = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x08] */ 19634562236bSHarry Wentland info_packet->hb2 = 0x08; 19644562236bSHarry Wentland 19654562236bSHarry Wentland payload_size = 0x08; 19664562236bSHarry Wentland 19674562236bSHarry Wentland } else if (dc_is_dp_signal(stream->signal)) { 19684562236bSHarry Wentland 19694562236bSHarry Wentland /* HEADER */ 19704562236bSHarry Wentland 19714562236bSHarry Wentland /* HB0 = Secondary-data Packet ID = 0 - Only non-zero 19724562236bSHarry Wentland * when used to associate audio related info packets 19734562236bSHarry Wentland */ 19744562236bSHarry Wentland info_packet->hb0 = 0x00; 19754562236bSHarry Wentland 19764562236bSHarry Wentland /* HB1 = Packet Type = 0x83 (Source Product 19774562236bSHarry Wentland * Descriptor InfoFrame) 19784562236bSHarry Wentland */ 19793e183c5fSDave Airlie info_packet->hb1 = HDMI_INFOFRAME_TYPE_SPD; 19804562236bSHarry Wentland 19814562236bSHarry Wentland /* HB2 = [Bits 7:0 = Least significant eight bits - 19824562236bSHarry Wentland * For INFOFRAME, the value must be 1Bh] 19834562236bSHarry Wentland */ 19844562236bSHarry Wentland info_packet->hb2 = 0x1B; 19854562236bSHarry Wentland 19864562236bSHarry Wentland /* HB3 = [Bits 7:2 = INFOFRAME SDP Version Number = 0x1] 19874562236bSHarry Wentland * [Bits 1:0 = Most significant two bits = 0x00] 19884562236bSHarry Wentland */ 19894562236bSHarry Wentland info_packet->hb3 = 0x04; 19904562236bSHarry Wentland 19914562236bSHarry Wentland payload_size = 0x1B; 19924562236bSHarry Wentland } 19934562236bSHarry Wentland 19944562236bSHarry Wentland /* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */ 19954562236bSHarry Wentland info_packet->sb[1] = 0x1A; 19964562236bSHarry Wentland 19974562236bSHarry Wentland /* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */ 19984562236bSHarry Wentland info_packet->sb[2] = 0x00; 19994562236bSHarry Wentland 20004562236bSHarry Wentland /* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */ 20014562236bSHarry Wentland info_packet->sb[3] = 0x00; 20024562236bSHarry Wentland 20034562236bSHarry Wentland /* PB4 = Reserved */ 20044562236bSHarry Wentland info_packet->sb[4] = 0x00; 20054562236bSHarry Wentland 20064562236bSHarry Wentland /* PB5 = Reserved */ 20074562236bSHarry Wentland info_packet->sb[5] = 0x00; 20084562236bSHarry Wentland 20094562236bSHarry Wentland /* PB6 = [Bits 7:3 = Reserved] */ 20104562236bSHarry Wentland info_packet->sb[6] = 0x00; 20114562236bSHarry Wentland 20124fa086b9SLeo (Sunpeng) Li if (stream->freesync_ctx.supported == true) 20134562236bSHarry Wentland /* PB6 = [Bit 0 = FreeSync Supported] */ 20144562236bSHarry Wentland info_packet->sb[6] |= 0x01; 20154562236bSHarry Wentland 20164fa086b9SLeo (Sunpeng) Li if (stream->freesync_ctx.enabled == true) 20174562236bSHarry Wentland /* PB6 = [Bit 1 = FreeSync Enabled] */ 20184562236bSHarry Wentland info_packet->sb[6] |= 0x02; 20194562236bSHarry Wentland 20204fa086b9SLeo (Sunpeng) Li if (stream->freesync_ctx.active == true) 20214562236bSHarry Wentland /* PB6 = [Bit 2 = FreeSync Active] */ 20224562236bSHarry Wentland info_packet->sb[6] |= 0x04; 20234562236bSHarry Wentland 20244562236bSHarry Wentland /* PB7 = FreeSync Minimum refresh rate (Hz) */ 20254fa086b9SLeo (Sunpeng) Li info_packet->sb[7] = (unsigned char) (stream->freesync_ctx. 20264562236bSHarry Wentland min_refresh_in_micro_hz / 1000000); 20274562236bSHarry Wentland 20284562236bSHarry Wentland /* PB8 = FreeSync Maximum refresh rate (Hz) 20294562236bSHarry Wentland * 20304562236bSHarry Wentland * Note: We do not use the maximum capable refresh rate 20314562236bSHarry Wentland * of the panel, because we should never go above the field 20324562236bSHarry Wentland * rate of the mode timing set. 20334562236bSHarry Wentland */ 20344fa086b9SLeo (Sunpeng) Li info_packet->sb[8] = (unsigned char) (stream->freesync_ctx. 20354562236bSHarry Wentland nominal_refresh_in_micro_hz / 1000000); 20364562236bSHarry Wentland 20374562236bSHarry Wentland /* PB9 - PB27 = Reserved */ 20384562236bSHarry Wentland for (idx = 9; idx <= 27; idx++) 20394562236bSHarry Wentland info_packet->sb[idx] = 0x00; 20404562236bSHarry Wentland 20414562236bSHarry Wentland /* Calculate checksum */ 20424562236bSHarry Wentland checksum += info_packet->hb0; 20434562236bSHarry Wentland checksum += info_packet->hb1; 20444562236bSHarry Wentland checksum += info_packet->hb2; 20454562236bSHarry Wentland checksum += info_packet->hb3; 20464562236bSHarry Wentland 20474562236bSHarry Wentland for (idx = 1; idx <= payload_size; idx++) 20484562236bSHarry Wentland checksum += info_packet->sb[idx]; 20494562236bSHarry Wentland 20504562236bSHarry Wentland /* PB0 = Checksum (one byte complement) */ 20514562236bSHarry Wentland info_packet->sb[0] = (unsigned char) (0x100 - checksum); 20524562236bSHarry Wentland 20534562236bSHarry Wentland info_packet->valid = true; 20544562236bSHarry Wentland } 20554562236bSHarry Wentland 20561646a6feSAndrew Wong static void set_hdr_static_info_packet( 20576e4d6beeSTony Cheng struct encoder_info_packet *info_packet, 20583be5262eSHarry Wentland struct dc_plane_state *plane_state, 20590971c40eSHarry Wentland struct dc_stream_state *stream) 20601646a6feSAndrew Wong { 2061e5cf325bSHarry Wentland uint16_t i = 0; 20621646a6feSAndrew Wong enum signal_type signal = stream->signal; 2063e5cf325bSHarry Wentland struct dc_hdr_static_metadata hdr_metadata; 2064e5cf325bSHarry Wentland uint32_t data; 20651646a6feSAndrew Wong 20663be5262eSHarry Wentland if (!plane_state) 20671646a6feSAndrew Wong return; 20681646a6feSAndrew Wong 20693be5262eSHarry Wentland hdr_metadata = plane_state->hdr_static_ctx; 20701646a6feSAndrew Wong 207170063a59SAmy Zhang if (!hdr_metadata.hdr_supported) 207210bff005SYongqiang Sun return; 207310bff005SYongqiang Sun 20741646a6feSAndrew Wong if (dc_is_hdmi_signal(signal)) { 20751646a6feSAndrew Wong info_packet->valid = true; 20761646a6feSAndrew Wong 20771646a6feSAndrew Wong info_packet->hb0 = 0x87; 20781646a6feSAndrew Wong info_packet->hb1 = 0x01; 20791646a6feSAndrew Wong info_packet->hb2 = 0x1A; 20801646a6feSAndrew Wong i = 1; 20811646a6feSAndrew Wong } else if (dc_is_dp_signal(signal)) { 20821646a6feSAndrew Wong info_packet->valid = true; 20831646a6feSAndrew Wong 20841646a6feSAndrew Wong info_packet->hb0 = 0x00; 20851646a6feSAndrew Wong info_packet->hb1 = 0x87; 20861646a6feSAndrew Wong info_packet->hb2 = 0x1D; 20871646a6feSAndrew Wong info_packet->hb3 = (0x13 << 2); 20881646a6feSAndrew Wong i = 2; 20891646a6feSAndrew Wong } 20901646a6feSAndrew Wong 20911646a6feSAndrew Wong data = hdr_metadata.is_hdr; 20921646a6feSAndrew Wong info_packet->sb[i++] = data ? 0x02 : 0x00; 20931646a6feSAndrew Wong info_packet->sb[i++] = 0x00; 20941646a6feSAndrew Wong 20951646a6feSAndrew Wong data = hdr_metadata.chromaticity_green_x / 2; 20961646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 20971646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 20981646a6feSAndrew Wong 20991646a6feSAndrew Wong data = hdr_metadata.chromaticity_green_y / 2; 21001646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 21011646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 21021646a6feSAndrew Wong 21031646a6feSAndrew Wong data = hdr_metadata.chromaticity_blue_x / 2; 21041646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 21051646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 21061646a6feSAndrew Wong 21071646a6feSAndrew Wong data = hdr_metadata.chromaticity_blue_y / 2; 21081646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 21091646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 21101646a6feSAndrew Wong 21111646a6feSAndrew Wong data = hdr_metadata.chromaticity_red_x / 2; 21121646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 21131646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 21141646a6feSAndrew Wong 21151646a6feSAndrew Wong data = hdr_metadata.chromaticity_red_y / 2; 21161646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 21171646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 21181646a6feSAndrew Wong 21191646a6feSAndrew Wong data = hdr_metadata.chromaticity_white_point_x / 2; 21201646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 21211646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 21221646a6feSAndrew Wong 21231646a6feSAndrew Wong data = hdr_metadata.chromaticity_white_point_y / 2; 21241646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 21251646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 21261646a6feSAndrew Wong 21271646a6feSAndrew Wong data = hdr_metadata.max_luminance; 21281646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 21291646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 21301646a6feSAndrew Wong 21311646a6feSAndrew Wong data = hdr_metadata.min_luminance; 21321646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 21331646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 21341646a6feSAndrew Wong 21351646a6feSAndrew Wong data = hdr_metadata.maximum_content_light_level; 21361646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 21371646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 21381646a6feSAndrew Wong 21391646a6feSAndrew Wong data = hdr_metadata.maximum_frame_average_light_level; 21401646a6feSAndrew Wong info_packet->sb[i++] = data & 0xFF; 21411646a6feSAndrew Wong info_packet->sb[i++] = (data & 0xFF00) >> 8; 21421646a6feSAndrew Wong 21431646a6feSAndrew Wong if (dc_is_hdmi_signal(signal)) { 21441646a6feSAndrew Wong uint32_t checksum = 0; 21451646a6feSAndrew Wong 21461646a6feSAndrew Wong checksum += info_packet->hb0; 21471646a6feSAndrew Wong checksum += info_packet->hb1; 21481646a6feSAndrew Wong checksum += info_packet->hb2; 21491646a6feSAndrew Wong 21501646a6feSAndrew Wong for (i = 1; i <= info_packet->hb2; i++) 21511646a6feSAndrew Wong checksum += info_packet->sb[i]; 21521646a6feSAndrew Wong 21531646a6feSAndrew Wong info_packet->sb[0] = 0x100 - checksum; 21541646a6feSAndrew Wong } else if (dc_is_dp_signal(signal)) { 21551646a6feSAndrew Wong info_packet->sb[0] = 0x01; 21561646a6feSAndrew Wong info_packet->sb[1] = 0x1A; 21571646a6feSAndrew Wong } 21581646a6feSAndrew Wong } 21591646a6feSAndrew Wong 21606e4d6beeSTony Cheng static void set_vsc_info_packet( 21616e4d6beeSTony Cheng struct encoder_info_packet *info_packet, 21620971c40eSHarry Wentland struct dc_stream_state *stream) 21634562236bSHarry Wentland { 21644562236bSHarry Wentland unsigned int vscPacketRevision = 0; 21654562236bSHarry Wentland unsigned int i; 21664562236bSHarry Wentland 216794267b3dSSylvia Tsai if (stream->sink->link->psr_enabled) { 21684562236bSHarry Wentland vscPacketRevision = 2; 21694562236bSHarry Wentland } 21704562236bSHarry Wentland 21714562236bSHarry Wentland /* VSC packet not needed based on the features 21724562236bSHarry Wentland * supported by this DP display 21734562236bSHarry Wentland */ 21744562236bSHarry Wentland if (vscPacketRevision == 0) 21754562236bSHarry Wentland return; 21764562236bSHarry Wentland 21774562236bSHarry Wentland if (vscPacketRevision == 0x2) { 21784562236bSHarry Wentland /* Secondary-data Packet ID = 0*/ 21794562236bSHarry Wentland info_packet->hb0 = 0x00; 21804562236bSHarry Wentland /* 07h - Packet Type Value indicating Video 21814562236bSHarry Wentland * Stream Configuration packet 21824562236bSHarry Wentland */ 21834562236bSHarry Wentland info_packet->hb1 = 0x07; 21844562236bSHarry Wentland /* 02h = VSC SDP supporting 3D stereo and PSR 21854562236bSHarry Wentland * (applies to eDP v1.3 or higher). 21864562236bSHarry Wentland */ 21874562236bSHarry Wentland info_packet->hb2 = 0x02; 21884562236bSHarry Wentland /* 08h = VSC packet supporting 3D stereo + PSR 21894562236bSHarry Wentland * (HB2 = 02h). 21904562236bSHarry Wentland */ 21914562236bSHarry Wentland info_packet->hb3 = 0x08; 21924562236bSHarry Wentland 21934562236bSHarry Wentland for (i = 0; i < 28; i++) 21944562236bSHarry Wentland info_packet->sb[i] = 0; 21954562236bSHarry Wentland 21964562236bSHarry Wentland info_packet->valid = true; 21974562236bSHarry Wentland } 21984562236bSHarry Wentland 21994562236bSHarry Wentland /*TODO: stereo 3D support and extend pixel encoding colorimetry*/ 22004562236bSHarry Wentland } 22014562236bSHarry Wentland 22028122a253SHarry Wentland void dc_resource_validate_ctx_destruct(struct validate_context *context) 22034562236bSHarry Wentland { 22044562236bSHarry Wentland int i, j; 22054562236bSHarry Wentland 2206ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 22073be5262eSHarry Wentland for (j = 0; j < context->stream_status[i].plane_count; j++) 22083be5262eSHarry Wentland dc_plane_state_release( 22093be5262eSHarry Wentland context->stream_status[i].plane_states[j]); 22104562236bSHarry Wentland 22113be5262eSHarry Wentland context->stream_status[i].plane_count = 0; 22124fa086b9SLeo (Sunpeng) Li dc_stream_release(context->streams[i]); 2213ab2541b6SAric Cyr context->streams[i] = NULL; 22144562236bSHarry Wentland } 22154562236bSHarry Wentland } 22164562236bSHarry Wentland 22174562236bSHarry Wentland /* 2218ab2541b6SAric Cyr * Copy src_ctx into dst_ctx and retain all surfaces and streams referenced 22194562236bSHarry Wentland * by the src_ctx 22204562236bSHarry Wentland */ 22218122a253SHarry Wentland void dc_resource_validate_ctx_copy_construct( 22224562236bSHarry Wentland const struct validate_context *src_ctx, 22234562236bSHarry Wentland struct validate_context *dst_ctx) 22244562236bSHarry Wentland { 22254562236bSHarry Wentland int i, j; 22269a3afbb3SAndrey Grodzovsky int ref_count = dst_ctx->ref_count; 22274562236bSHarry Wentland 22284562236bSHarry Wentland *dst_ctx = *src_ctx; 22294562236bSHarry Wentland 2230a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 22314562236bSHarry Wentland struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i]; 22324562236bSHarry Wentland 22334562236bSHarry Wentland if (cur_pipe->top_pipe) 22344562236bSHarry Wentland cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; 22354562236bSHarry Wentland 22364562236bSHarry Wentland if (cur_pipe->bottom_pipe) 22374562236bSHarry Wentland cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; 22384562236bSHarry Wentland 22394562236bSHarry Wentland } 22404562236bSHarry Wentland 2241ab2541b6SAric Cyr for (i = 0; i < dst_ctx->stream_count; i++) { 22424fa086b9SLeo (Sunpeng) Li dc_stream_retain(dst_ctx->streams[i]); 22433be5262eSHarry Wentland for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++) 22443be5262eSHarry Wentland dc_plane_state_retain( 22453be5262eSHarry Wentland dst_ctx->stream_status[i].plane_states[j]); 22464562236bSHarry Wentland } 22479a3afbb3SAndrey Grodzovsky 22489a3afbb3SAndrey Grodzovsky /* context refcount should not be overridden */ 22499a3afbb3SAndrey Grodzovsky dst_ctx->ref_count = ref_count; 22509a3afbb3SAndrey Grodzovsky 22514562236bSHarry Wentland } 22524562236bSHarry Wentland 22534562236bSHarry Wentland struct clock_source *dc_resource_find_first_free_pll( 2254a2b8659dSTony Cheng struct resource_context *res_ctx, 2255a2b8659dSTony Cheng const struct resource_pool *pool) 22564562236bSHarry Wentland { 22574562236bSHarry Wentland int i; 22584562236bSHarry Wentland 2259a2b8659dSTony Cheng for (i = 0; i < pool->clk_src_count; ++i) { 22604562236bSHarry Wentland if (res_ctx->clock_source_ref_count[i] == 0) 2261a2b8659dSTony Cheng return pool->clock_sources[i]; 22624562236bSHarry Wentland } 22634562236bSHarry Wentland 22644562236bSHarry Wentland return NULL; 22654562236bSHarry Wentland } 22664562236bSHarry Wentland 22674562236bSHarry Wentland void resource_build_info_frame(struct pipe_ctx *pipe_ctx) 22684562236bSHarry Wentland { 22694562236bSHarry Wentland enum signal_type signal = SIGNAL_TYPE_NONE; 22706e4d6beeSTony Cheng struct encoder_info_frame *info = &pipe_ctx->encoder_info_frame; 22714562236bSHarry Wentland 22724562236bSHarry Wentland /* default all packets to invalid */ 22736e4d6beeSTony Cheng info->avi.valid = false; 22746e4d6beeSTony Cheng info->gamut.valid = false; 22756e4d6beeSTony Cheng info->vendor.valid = false; 2276630e3573SJeff Smith info->spd.valid = false; 22776e4d6beeSTony Cheng info->hdrsmd.valid = false; 22786e4d6beeSTony Cheng info->vsc.valid = false; 22794562236bSHarry Wentland 22804562236bSHarry Wentland signal = pipe_ctx->stream->signal; 22814562236bSHarry Wentland 22824562236bSHarry Wentland /* HDMi and DP have different info packets*/ 22834562236bSHarry Wentland if (dc_is_hdmi_signal(signal)) { 22846e4d6beeSTony Cheng set_avi_info_frame(&info->avi, pipe_ctx); 22856e4d6beeSTony Cheng 22866e4d6beeSTony Cheng set_vendor_info_packet(&info->vendor, pipe_ctx->stream); 22876e4d6beeSTony Cheng 22886e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 22896e4d6beeSTony Cheng 22906e4d6beeSTony Cheng set_hdr_static_info_packet(&info->hdrsmd, 22913be5262eSHarry Wentland pipe_ctx->plane_state, pipe_ctx->stream); 22926e4d6beeSTony Cheng 2293a33fa99dSHarry Wentland } else if (dc_is_dp_signal(signal)) { 22946e4d6beeSTony Cheng set_vsc_info_packet(&info->vsc, pipe_ctx->stream); 22956e4d6beeSTony Cheng 22966e4d6beeSTony Cheng set_spd_info_packet(&info->spd, pipe_ctx->stream); 22976e4d6beeSTony Cheng 22986e4d6beeSTony Cheng set_hdr_static_info_packet(&info->hdrsmd, 22993be5262eSHarry Wentland pipe_ctx->plane_state, pipe_ctx->stream); 2300a33fa99dSHarry Wentland } 23014562236bSHarry Wentland 23026e4d6beeSTony Cheng patch_gamut_packet_checksum(&info->gamut); 23034562236bSHarry Wentland } 23044562236bSHarry Wentland 23054562236bSHarry Wentland enum dc_status resource_map_clock_resources( 23064562236bSHarry Wentland const struct core_dc *dc, 2307430ef426SDmytro Laktyushkin struct validate_context *context, 2308430ef426SDmytro Laktyushkin struct validate_context *old_context) 23094562236bSHarry Wentland { 2310ab2541b6SAric Cyr int i, j; 2311a2b8659dSTony Cheng const struct resource_pool *pool = dc->res_pool; 23124562236bSHarry Wentland 23134562236bSHarry Wentland /* acquire new resources */ 2314ab2541b6SAric Cyr for (i = 0; i < context->stream_count; i++) { 23150971c40eSHarry Wentland struct dc_stream_state *stream = context->streams[i]; 23164562236bSHarry Wentland 2317430ef426SDmytro Laktyushkin if (old_context && resource_is_stream_unchanged(old_context, stream)) 23184562236bSHarry Wentland continue; 23194562236bSHarry Wentland 2320ab2541b6SAric Cyr for (j = 0; j < MAX_PIPES; j++) { 23214562236bSHarry Wentland struct pipe_ctx *pipe_ctx = 2322ab2541b6SAric Cyr &context->res_ctx.pipe_ctx[j]; 23234562236bSHarry Wentland 2324ab2541b6SAric Cyr if (context->res_ctx.pipe_ctx[j].stream != stream) 23254562236bSHarry Wentland continue; 23264562236bSHarry Wentland 23274562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal) 23284562236bSHarry Wentland || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) 2329a2b8659dSTony Cheng pipe_ctx->clock_source = pool->dp_clock_source; 23304562236bSHarry Wentland else { 23314562236bSHarry Wentland pipe_ctx->clock_source = NULL; 23324562236bSHarry Wentland 23334562236bSHarry Wentland if (!dc->public.config.disable_disp_pll_sharing) 23344562236bSHarry Wentland resource_find_used_clk_src_for_sharing( 23354562236bSHarry Wentland &context->res_ctx, 23364562236bSHarry Wentland pipe_ctx); 23374562236bSHarry Wentland 23384562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 23394562236bSHarry Wentland pipe_ctx->clock_source = 2340a2b8659dSTony Cheng dc_resource_find_first_free_pll( 2341a2b8659dSTony Cheng &context->res_ctx, 2342a2b8659dSTony Cheng pool); 23434562236bSHarry Wentland } 23444562236bSHarry Wentland 23454562236bSHarry Wentland if (pipe_ctx->clock_source == NULL) 23464562236bSHarry Wentland return DC_NO_CLOCK_SOURCE_RESOURCE; 23474562236bSHarry Wentland 23484562236bSHarry Wentland resource_reference_clock_source( 2349a2b8659dSTony Cheng &context->res_ctx, pool, 23504562236bSHarry Wentland pipe_ctx->clock_source); 23514562236bSHarry Wentland 23524562236bSHarry Wentland /* only one cs per stream regardless of mpo */ 23534562236bSHarry Wentland break; 23544562236bSHarry Wentland } 23554562236bSHarry Wentland } 23564562236bSHarry Wentland 23574562236bSHarry Wentland return DC_OK; 23584562236bSHarry Wentland } 23594562236bSHarry Wentland 23604562236bSHarry Wentland /* 23614562236bSHarry Wentland * Note: We need to disable output if clock sources change, 23624562236bSHarry Wentland * since bios does optimization and doesn't apply if changing 23634562236bSHarry Wentland * PHY when not already disabled. 23644562236bSHarry Wentland */ 23654562236bSHarry Wentland bool pipe_need_reprogram( 23664562236bSHarry Wentland struct pipe_ctx *pipe_ctx_old, 23674562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 23684562236bSHarry Wentland { 2369cfe4645eSDmytro Laktyushkin if (!pipe_ctx_old->stream) 2370cfe4645eSDmytro Laktyushkin return false; 2371cfe4645eSDmytro Laktyushkin 23724562236bSHarry Wentland if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink) 23734562236bSHarry Wentland return true; 23744562236bSHarry Wentland 23754562236bSHarry Wentland if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal) 23764562236bSHarry Wentland return true; 23774562236bSHarry Wentland 23784562236bSHarry Wentland if (pipe_ctx_old->audio != pipe_ctx->audio) 23794562236bSHarry Wentland return true; 23804562236bSHarry Wentland 23814562236bSHarry Wentland if (pipe_ctx_old->clock_source != pipe_ctx->clock_source 23824562236bSHarry Wentland && pipe_ctx_old->stream != pipe_ctx->stream) 23834562236bSHarry Wentland return true; 23844562236bSHarry Wentland 23858e9c4c8cSHarry Wentland if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc) 23864562236bSHarry Wentland return true; 23874562236bSHarry Wentland 23884562236bSHarry Wentland if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 23894562236bSHarry Wentland return true; 23904562236bSHarry Wentland 23914562236bSHarry Wentland 23924562236bSHarry Wentland return false; 23934562236bSHarry Wentland } 2394529cad0fSDing Wang 23950971c40eSHarry Wentland void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, 2396529cad0fSDing Wang struct bit_depth_reduction_params *fmt_bit_depth) 2397529cad0fSDing Wang { 23984fa086b9SLeo (Sunpeng) Li enum dc_dither_option option = stream->dither_option; 2399529cad0fSDing Wang enum dc_pixel_encoding pixel_encoding = 24004fa086b9SLeo (Sunpeng) Li stream->timing.pixel_encoding; 2401529cad0fSDing Wang 2402529cad0fSDing Wang memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); 2403529cad0fSDing Wang 2404529cad0fSDing Wang if (option == DITHER_OPTION_DISABLE) 2405529cad0fSDing Wang return; 2406529cad0fSDing Wang 2407529cad0fSDing Wang if (option == DITHER_OPTION_TRUN6) { 2408529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2409529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 0; 2410529cad0fSDing Wang } else if (option == DITHER_OPTION_TRUN8 || 2411529cad0fSDing Wang option == DITHER_OPTION_TRUN8_SPATIAL6 || 2412529cad0fSDing Wang option == DITHER_OPTION_TRUN8_FM6) { 2413529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2414529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 1; 2415529cad0fSDing Wang } else if (option == DITHER_OPTION_TRUN10 || 2416529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL6 || 2417529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8 || 2418529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM8 || 2419529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM6 || 2420529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2421529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2422529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2423529cad0fSDing Wang } 2424529cad0fSDing Wang 2425529cad0fSDing Wang /* special case - Formatter can only reduce by 4 bits at most. 2426529cad0fSDing Wang * When reducing from 12 to 6 bits, 2427529cad0fSDing Wang * HW recommends we use trunc with round mode 2428529cad0fSDing Wang * (if we did nothing, trunc to 10 bits would be used) 2429529cad0fSDing Wang * note that any 12->10 bit reduction is ignored prior to DCE8, 2430529cad0fSDing Wang * as the input was 10 bits. 2431529cad0fSDing Wang */ 2432529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2433529cad0fSDing Wang option == DITHER_OPTION_SPATIAL6 || 2434529cad0fSDing Wang option == DITHER_OPTION_FM6) { 2435529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2436529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2437529cad0fSDing Wang fmt_bit_depth->flags.TRUNCATE_MODE = 1; 2438529cad0fSDing Wang } 2439529cad0fSDing Wang 2440529cad0fSDing Wang /* spatial dither 2441529cad0fSDing Wang * note that spatial modes 1-3 are never used 2442529cad0fSDing Wang */ 2443529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2444529cad0fSDing Wang option == DITHER_OPTION_SPATIAL6 || 2445529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL6 || 2446529cad0fSDing Wang option == DITHER_OPTION_TRUN8_SPATIAL6) { 2447529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2448529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0; 2449529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2450529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2451529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2452529cad0fSDing Wang } else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM || 2453529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8 || 2454529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8_FM6 || 2455529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8 || 2456529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2457529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2458529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1; 2459529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2460529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2461529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2462529cad0fSDing Wang } else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM || 2463529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10 || 2464529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM8 || 2465529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM6) { 2466529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2467529cad0fSDing Wang fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2; 2468529cad0fSDing Wang fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2469529cad0fSDing Wang fmt_bit_depth->flags.RGB_RANDOM = 2470529cad0fSDing Wang (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2471529cad0fSDing Wang } 2472529cad0fSDing Wang 2473529cad0fSDing Wang if (option == DITHER_OPTION_SPATIAL6 || 2474529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8 || 2475529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10) { 2476529cad0fSDing Wang fmt_bit_depth->flags.FRAME_RANDOM = 0; 2477529cad0fSDing Wang } else { 2478529cad0fSDing Wang fmt_bit_depth->flags.FRAME_RANDOM = 1; 2479529cad0fSDing Wang } 2480529cad0fSDing Wang 2481529cad0fSDing Wang ////////////////////// 2482529cad0fSDing Wang //// temporal dither 2483529cad0fSDing Wang ////////////////////// 2484529cad0fSDing Wang if (option == DITHER_OPTION_FM6 || 2485529cad0fSDing Wang option == DITHER_OPTION_SPATIAL8_FM6 || 2486529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM6 || 2487529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM6 || 2488529cad0fSDing Wang option == DITHER_OPTION_TRUN8_FM6 || 2489529cad0fSDing Wang option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2490529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2491529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0; 2492529cad0fSDing Wang } else if (option == DITHER_OPTION_FM8 || 2493529cad0fSDing Wang option == DITHER_OPTION_SPATIAL10_FM8 || 2494529cad0fSDing Wang option == DITHER_OPTION_TRUN10_FM8) { 2495529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2496529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1; 2497529cad0fSDing Wang } else if (option == DITHER_OPTION_FM10) { 2498529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2499529cad0fSDing Wang fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2; 2500529cad0fSDing Wang } 2501529cad0fSDing Wang 2502529cad0fSDing Wang fmt_bit_depth->pixel_encoding = pixel_encoding; 2503529cad0fSDing Wang } 25049345d987SAndrey Grodzovsky 25050971c40eSHarry Wentland bool dc_validate_stream(const struct dc *dc, struct dc_stream_state *stream) 25069345d987SAndrey Grodzovsky { 25079345d987SAndrey Grodzovsky struct core_dc *core_dc = DC_TO_CORE(dc); 25089345d987SAndrey Grodzovsky struct dc_context *dc_ctx = core_dc->ctx; 25094fa086b9SLeo (Sunpeng) Li struct dc_link *link = stream->sink->link; 25109345d987SAndrey Grodzovsky struct timing_generator *tg = core_dc->res_pool->timing_generators[0]; 25119345d987SAndrey Grodzovsky enum dc_status res = DC_OK; 25129345d987SAndrey Grodzovsky 25134fa086b9SLeo (Sunpeng) Li calculate_phy_pix_clks(stream); 25149345d987SAndrey Grodzovsky 25154fa086b9SLeo (Sunpeng) Li if (!tg->funcs->validate_timing(tg, &stream->timing)) 25169345d987SAndrey Grodzovsky res = DC_FAIL_CONTROLLER_VALIDATE; 25179345d987SAndrey Grodzovsky 25189345d987SAndrey Grodzovsky if (res == DC_OK) 25199345d987SAndrey Grodzovsky if (!link->link_enc->funcs->validate_output_with_stream( 25204fa086b9SLeo (Sunpeng) Li link->link_enc, stream)) 25219345d987SAndrey Grodzovsky res = DC_FAIL_ENC_VALIDATE; 25229345d987SAndrey Grodzovsky 25239345d987SAndrey Grodzovsky /* TODO: validate audio ASIC caps, encoder */ 25249345d987SAndrey Grodzovsky 25259345d987SAndrey Grodzovsky if (res == DC_OK) 25264fa086b9SLeo (Sunpeng) Li res = dc_link_validate_mode_timing(stream, 25279345d987SAndrey Grodzovsky link, 25284fa086b9SLeo (Sunpeng) Li &stream->timing); 25299345d987SAndrey Grodzovsky 25309345d987SAndrey Grodzovsky if (res != DC_OK) 25319345d987SAndrey Grodzovsky DC_ERROR("Failed validation for stream %p, err:%d, !\n", 25329345d987SAndrey Grodzovsky stream, res); 25339345d987SAndrey Grodzovsky 25349345d987SAndrey Grodzovsky return res == DC_OK; 25359345d987SAndrey Grodzovsky } 2536792671d7SAndrey Grodzovsky 2537c9614aebSHarry Wentland bool dc_validate_plane(const struct dc *dc, const struct dc_plane_state *plane_state) 2538792671d7SAndrey Grodzovsky { 2539792671d7SAndrey Grodzovsky struct core_dc *core_dc = DC_TO_CORE(dc); 2540792671d7SAndrey Grodzovsky 2541792671d7SAndrey Grodzovsky /* TODO For now validates pixel format only */ 2542c9614aebSHarry Wentland if (core_dc->res_pool->funcs->validate_plane) 2543c9614aebSHarry Wentland return core_dc->res_pool->funcs->validate_plane(plane_state) == DC_OK; 2544792671d7SAndrey Grodzovsky 2545792671d7SAndrey Grodzovsky return true; 2546792671d7SAndrey Grodzovsky } 2547