14562236bSHarry Wentland /* 24562236bSHarry Wentland * Copyright 2015 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 */ 25c366be54SSam Ravnborg 26c366be54SSam Ravnborg #include <linux/delay.h> 27c366be54SSam Ravnborg 284562236bSHarry Wentland #include "dm_services.h" 294562236bSHarry Wentland #include "dc.h" 304562236bSHarry Wentland #include "dc_bios_types.h" 314562236bSHarry Wentland #include "core_types.h" 324562236bSHarry Wentland #include "core_status.h" 334562236bSHarry Wentland #include "resource.h" 344562236bSHarry Wentland #include "dm_helpers.h" 354562236bSHarry Wentland #include "dce110_timing_generator.h" 3698489c02SLeo (Sunpeng) Li #include "dce/dce_hwseq.h" 3787401969SAndrew Jiang #include "gpio_service_interface.h" 384562236bSHarry Wentland 391663ae1cSBhawanpreet Lakha #include "dce110_compressor.h" 401663ae1cSBhawanpreet Lakha 414562236bSHarry Wentland #include "bios/bios_parser_helper.h" 424562236bSHarry Wentland #include "timing_generator.h" 434562236bSHarry Wentland #include "mem_input.h" 444562236bSHarry Wentland #include "opp.h" 454562236bSHarry Wentland #include "ipp.h" 464562236bSHarry Wentland #include "transform.h" 474562236bSHarry Wentland #include "stream_encoder.h" 484562236bSHarry Wentland #include "link_encoder.h" 4964d283cbSJimmy Kizito #include "link_enc_cfg.h" 5087401969SAndrew Jiang #include "link_hwss.h" 51f9fc6f39SMichael Strauss #include "dc_link_dp.h" 528fe44c08SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN) 5364b1d0e8SNicholas Kazlauskas #include "dccg.h" 5464b1d0e8SNicholas Kazlauskas #endif 554562236bSHarry Wentland #include "clock_source.h" 56dc88b4a6SEric Yang #include "clk_mgr.h" 575e7773a2SAnthony Koo #include "abm.h" 584562236bSHarry Wentland #include "audio.h" 5908b16886SZeyu Fan #include "reg_helper.h" 60d4caa72eSAnthony Koo #include "panel_cntl.h" 613550d622SLeo (Hanghong) Ma #include "inc/link_dpcd.h" 623550d622SLeo (Hanghong) Ma #include "dpcd_defs.h" 634562236bSHarry Wentland /* include DCE11 register header files */ 644562236bSHarry Wentland #include "dce/dce_11_0_d.h" 654562236bSHarry Wentland #include "dce/dce_11_0_sh_mask.h" 66e266fdf6SVitaly Prosyak #include "custom_float.h" 674562236bSHarry Wentland 684cac1e6dSYongqiang Sun #include "atomfirmware.h" 694cac1e6dSYongqiang Sun 70a76eb7d3SLee Jones #include "dcn10/dcn10_hw_sequencer.h" 716e4a14ccSLee Jones 7278c77382SAnthony Koo #define GAMMA_HW_POINTS_NUM 256 7378c77382SAnthony Koo 7487401969SAndrew Jiang /* 7587401969SAndrew Jiang * All values are in milliseconds; 7687401969SAndrew Jiang * For eDP, after power-up/power/down, 7787401969SAndrew Jiang * 300/500 msec max. delay from LCDVCC to black video generation 7887401969SAndrew Jiang */ 7987401969SAndrew Jiang #define PANEL_POWER_UP_TIMEOUT 300 8087401969SAndrew Jiang #define PANEL_POWER_DOWN_TIMEOUT 500 8187401969SAndrew Jiang #define HPD_CHECK_INTERVAL 10 8296577cf8SHersen Wu #define OLED_POST_T7_DELAY 100 8396577cf8SHersen Wu #define OLED_PRE_T11_DELAY 150 8487401969SAndrew Jiang 855eefbc40SYue Hin Lau #define CTX \ 865eefbc40SYue Hin Lau hws->ctx 875d4b05ddSBhawanpreet Lakha 885d4b05ddSBhawanpreet Lakha #define DC_LOGGER_INIT() 895d4b05ddSBhawanpreet Lakha 905eefbc40SYue Hin Lau #define REG(reg)\ 915eefbc40SYue Hin Lau hws->regs->reg 925eefbc40SYue Hin Lau 935eefbc40SYue Hin Lau #undef FN 945eefbc40SYue Hin Lau #define FN(reg_name, field_name) \ 955eefbc40SYue Hin Lau hws->shifts->field_name, hws->masks->field_name 965eefbc40SYue Hin Lau 974562236bSHarry Wentland struct dce110_hw_seq_reg_offsets { 984562236bSHarry Wentland uint32_t crtc; 994562236bSHarry Wentland }; 1004562236bSHarry Wentland 1014562236bSHarry Wentland static const struct dce110_hw_seq_reg_offsets reg_offsets[] = { 1024562236bSHarry Wentland { 1034562236bSHarry Wentland .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), 1044562236bSHarry Wentland }, 1054562236bSHarry Wentland { 1064562236bSHarry Wentland .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), 1074562236bSHarry Wentland }, 1084562236bSHarry Wentland { 1094562236bSHarry Wentland .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), 1104562236bSHarry Wentland }, 1114562236bSHarry Wentland { 1124562236bSHarry Wentland .crtc = (mmCRTCV_GSL_CONTROL - mmCRTC_GSL_CONTROL), 1134562236bSHarry Wentland } 1144562236bSHarry Wentland }; 1154562236bSHarry Wentland 1164562236bSHarry Wentland #define HW_REG_BLND(reg, id)\ 1174562236bSHarry Wentland (reg + reg_offsets[id].blnd) 1184562236bSHarry Wentland 1194562236bSHarry Wentland #define HW_REG_CRTC(reg, id)\ 1204562236bSHarry Wentland (reg + reg_offsets[id].crtc) 1214562236bSHarry Wentland 1224562236bSHarry Wentland #define MAX_WATERMARK 0xFFFF 1234562236bSHarry Wentland #define SAFE_NBP_MARK 0x7FFF 1244562236bSHarry Wentland 1254562236bSHarry Wentland /******************************************************************************* 1264562236bSHarry Wentland * Private definitions 1274562236bSHarry Wentland ******************************************************************************/ 1284562236bSHarry Wentland /***************************PIPE_CONTROL***********************************/ 1294562236bSHarry Wentland static void dce110_init_pte(struct dc_context *ctx) 1304562236bSHarry Wentland { 1314562236bSHarry Wentland uint32_t addr; 1324562236bSHarry Wentland uint32_t value = 0; 1334562236bSHarry Wentland uint32_t chunk_int = 0; 1344562236bSHarry Wentland uint32_t chunk_mul = 0; 1354562236bSHarry Wentland 1364562236bSHarry Wentland addr = mmUNP_DVMM_PTE_CONTROL; 1374562236bSHarry Wentland value = dm_read_reg(ctx, addr); 1384562236bSHarry Wentland 1394562236bSHarry Wentland set_reg_field_value( 1404562236bSHarry Wentland value, 1414562236bSHarry Wentland 0, 1424562236bSHarry Wentland DVMM_PTE_CONTROL, 1434562236bSHarry Wentland DVMM_USE_SINGLE_PTE); 1444562236bSHarry Wentland 1454562236bSHarry Wentland set_reg_field_value( 1464562236bSHarry Wentland value, 1474562236bSHarry Wentland 1, 1484562236bSHarry Wentland DVMM_PTE_CONTROL, 1494562236bSHarry Wentland DVMM_PTE_BUFFER_MODE0); 1504562236bSHarry Wentland 1514562236bSHarry Wentland set_reg_field_value( 1524562236bSHarry Wentland value, 1534562236bSHarry Wentland 1, 1544562236bSHarry Wentland DVMM_PTE_CONTROL, 1554562236bSHarry Wentland DVMM_PTE_BUFFER_MODE1); 1564562236bSHarry Wentland 1574562236bSHarry Wentland dm_write_reg(ctx, addr, value); 1584562236bSHarry Wentland 1594562236bSHarry Wentland addr = mmDVMM_PTE_REQ; 1604562236bSHarry Wentland value = dm_read_reg(ctx, addr); 1614562236bSHarry Wentland 1624562236bSHarry Wentland chunk_int = get_reg_field_value( 1634562236bSHarry Wentland value, 1644562236bSHarry Wentland DVMM_PTE_REQ, 1654562236bSHarry Wentland HFLIP_PTEREQ_PER_CHUNK_INT); 1664562236bSHarry Wentland 1674562236bSHarry Wentland chunk_mul = get_reg_field_value( 1684562236bSHarry Wentland value, 1694562236bSHarry Wentland DVMM_PTE_REQ, 1704562236bSHarry Wentland HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); 1714562236bSHarry Wentland 1724562236bSHarry Wentland if (chunk_int != 0x4 || chunk_mul != 0x4) { 1734562236bSHarry Wentland 1744562236bSHarry Wentland set_reg_field_value( 1754562236bSHarry Wentland value, 1764562236bSHarry Wentland 255, 1774562236bSHarry Wentland DVMM_PTE_REQ, 1784562236bSHarry Wentland MAX_PTEREQ_TO_ISSUE); 1794562236bSHarry Wentland 1804562236bSHarry Wentland set_reg_field_value( 1814562236bSHarry Wentland value, 1824562236bSHarry Wentland 4, 1834562236bSHarry Wentland DVMM_PTE_REQ, 1844562236bSHarry Wentland HFLIP_PTEREQ_PER_CHUNK_INT); 1854562236bSHarry Wentland 1864562236bSHarry Wentland set_reg_field_value( 1874562236bSHarry Wentland value, 1884562236bSHarry Wentland 4, 1894562236bSHarry Wentland DVMM_PTE_REQ, 1904562236bSHarry Wentland HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); 1914562236bSHarry Wentland 1924562236bSHarry Wentland dm_write_reg(ctx, addr, value); 1934562236bSHarry Wentland } 1944562236bSHarry Wentland } 1954562236bSHarry Wentland /**************************************************************************/ 1964562236bSHarry Wentland 1974562236bSHarry Wentland static void enable_display_pipe_clock_gating( 1984562236bSHarry Wentland struct dc_context *ctx, 1994562236bSHarry Wentland bool clock_gating) 2004562236bSHarry Wentland { 2014562236bSHarry Wentland /*TODO*/ 2024562236bSHarry Wentland } 2034562236bSHarry Wentland 2044562236bSHarry Wentland static bool dce110_enable_display_power_gating( 205fb3466a4SBhawanpreet Lakha struct dc *dc, 2064562236bSHarry Wentland uint8_t controller_id, 2074562236bSHarry Wentland struct dc_bios *dcb, 2084562236bSHarry Wentland enum pipe_gating_control power_gating) 2094562236bSHarry Wentland { 2104562236bSHarry Wentland enum bp_result bp_result = BP_RESULT_OK; 2114562236bSHarry Wentland enum bp_pipe_control_action cntl; 2124562236bSHarry Wentland struct dc_context *ctx = dc->ctx; 2134562236bSHarry Wentland unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; 2144562236bSHarry Wentland 2154562236bSHarry Wentland if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) 2164562236bSHarry Wentland return true; 2174562236bSHarry Wentland 2184562236bSHarry Wentland if (power_gating == PIPE_GATING_CONTROL_INIT) 2194562236bSHarry Wentland cntl = ASIC_PIPE_INIT; 2204562236bSHarry Wentland else if (power_gating == PIPE_GATING_CONTROL_ENABLE) 2214562236bSHarry Wentland cntl = ASIC_PIPE_ENABLE; 2224562236bSHarry Wentland else 2234562236bSHarry Wentland cntl = ASIC_PIPE_DISABLE; 2244562236bSHarry Wentland 2254562236bSHarry Wentland if (controller_id == underlay_idx) 2264562236bSHarry Wentland controller_id = CONTROLLER_ID_UNDERLAY0 - 1; 2274562236bSHarry Wentland 2284562236bSHarry Wentland if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0){ 2294562236bSHarry Wentland 2304562236bSHarry Wentland bp_result = dcb->funcs->enable_disp_power_gating( 2314562236bSHarry Wentland dcb, controller_id + 1, cntl); 2324562236bSHarry Wentland 2334562236bSHarry Wentland /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2 2344562236bSHarry Wentland * by default when command table is called 2354562236bSHarry Wentland * 2364562236bSHarry Wentland * Bios parser accepts controller_id = 6 as indicative of 2374562236bSHarry Wentland * underlay pipe in dce110. But we do not support more 2384562236bSHarry Wentland * than 3. 2394562236bSHarry Wentland */ 2404562236bSHarry Wentland if (controller_id < CONTROLLER_ID_MAX - 1) 2414562236bSHarry Wentland dm_write_reg(ctx, 2424562236bSHarry Wentland HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE, controller_id), 2434562236bSHarry Wentland 0); 2444562236bSHarry Wentland } 2454562236bSHarry Wentland 2464562236bSHarry Wentland if (power_gating != PIPE_GATING_CONTROL_ENABLE) 2474562236bSHarry Wentland dce110_init_pte(ctx); 2484562236bSHarry Wentland 2494562236bSHarry Wentland if (bp_result == BP_RESULT_OK) 2504562236bSHarry Wentland return true; 2514562236bSHarry Wentland else 2524562236bSHarry Wentland return false; 2534562236bSHarry Wentland } 2544562236bSHarry Wentland 2554562236bSHarry Wentland static void build_prescale_params(struct ipp_prescale_params *prescale_params, 2563be5262eSHarry Wentland const struct dc_plane_state *plane_state) 2574562236bSHarry Wentland { 2584562236bSHarry Wentland prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED; 2594562236bSHarry Wentland 2603be5262eSHarry Wentland switch (plane_state->format) { 2611352c779SNicholas Kazlauskas case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 2621352c779SNicholas Kazlauskas prescale_params->scale = 0x2082; 2631352c779SNicholas Kazlauskas break; 2644562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 2658693049aSTony Cheng case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 2664562236bSHarry Wentland prescale_params->scale = 0x2020; 2674562236bSHarry Wentland break; 2684562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 2694562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 2704562236bSHarry Wentland prescale_params->scale = 0x2008; 2714562236bSHarry Wentland break; 2724562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 273050cd3d6SMario Kleiner case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: 2744562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 2754562236bSHarry Wentland prescale_params->scale = 0x2000; 2764562236bSHarry Wentland break; 2774562236bSHarry Wentland default: 2784562236bSHarry Wentland ASSERT(false); 279d7194cf6SAric Cyr break; 2804562236bSHarry Wentland } 2814562236bSHarry Wentland } 2824562236bSHarry Wentland 283a6114e85SHarry Wentland static bool 28478c77382SAnthony Koo dce110_set_input_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, 2853be5262eSHarry Wentland const struct dc_plane_state *plane_state) 2864562236bSHarry Wentland { 28786a66c4eSHarry Wentland struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; 2887b0c470fSLeo (Sunpeng) Li const struct dc_transfer_func *tf = NULL; 28990e508baSAnthony Koo struct ipp_prescale_params prescale_params = { 0 }; 29090e508baSAnthony Koo bool result = true; 29190e508baSAnthony Koo 29290e508baSAnthony Koo if (ipp == NULL) 29390e508baSAnthony Koo return false; 29490e508baSAnthony Koo 2953be5262eSHarry Wentland if (plane_state->in_transfer_func) 2963be5262eSHarry Wentland tf = plane_state->in_transfer_func; 29790e508baSAnthony Koo 2983be5262eSHarry Wentland build_prescale_params(&prescale_params, plane_state); 29990e508baSAnthony Koo ipp->funcs->ipp_program_prescale(ipp, &prescale_params); 30090e508baSAnthony Koo 30184ffa801SLeo (Sunpeng) Li if (plane_state->gamma_correction && 30284ffa801SLeo (Sunpeng) Li !plane_state->gamma_correction->is_identity && 30384ffa801SLeo (Sunpeng) Li dce_use_lut(plane_state->format)) 3043be5262eSHarry Wentland ipp->funcs->ipp_program_input_lut(ipp, plane_state->gamma_correction); 305d7194cf6SAric Cyr 30690e508baSAnthony Koo if (tf == NULL) { 30790e508baSAnthony Koo /* Default case if no input transfer function specified */ 308a6114e85SHarry Wentland ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); 3097b0c470fSLeo (Sunpeng) Li } else if (tf->type == TF_TYPE_PREDEFINED) { 3107b0c470fSLeo (Sunpeng) Li switch (tf->tf) { 31190e508baSAnthony Koo case TRANSFER_FUNCTION_SRGB: 312a6114e85SHarry Wentland ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); 31390e508baSAnthony Koo break; 31490e508baSAnthony Koo case TRANSFER_FUNCTION_BT709: 315a6114e85SHarry Wentland ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_xvYCC); 31690e508baSAnthony Koo break; 31790e508baSAnthony Koo case TRANSFER_FUNCTION_LINEAR: 318a6114e85SHarry Wentland ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); 31990e508baSAnthony Koo break; 32090e508baSAnthony Koo case TRANSFER_FUNCTION_PQ: 32190e508baSAnthony Koo default: 32290e508baSAnthony Koo result = false; 323d7194cf6SAric Cyr break; 32490e508baSAnthony Koo } 3257b0c470fSLeo (Sunpeng) Li } else if (tf->type == TF_TYPE_BYPASS) { 32670063a59SAmy Zhang ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); 32790e508baSAnthony Koo } else { 32890e508baSAnthony Koo /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/ 32990e508baSAnthony Koo result = false; 33090e508baSAnthony Koo } 33190e508baSAnthony Koo 33290e508baSAnthony Koo return result; 33390e508baSAnthony Koo } 33490e508baSAnthony Koo 335bd1be8e8SHarry Wentland static bool convert_to_custom_float(struct pwl_result_data *rgb_resulted, 336fcd2f4bfSAmy Zhang struct curve_points *arr_points, 337fcd2f4bfSAmy Zhang uint32_t hw_points_num) 338fcd2f4bfSAmy Zhang { 339fcd2f4bfSAmy Zhang struct custom_float_format fmt; 340fcd2f4bfSAmy Zhang 341fcd2f4bfSAmy Zhang struct pwl_result_data *rgb = rgb_resulted; 342fcd2f4bfSAmy Zhang 343fcd2f4bfSAmy Zhang uint32_t i = 0; 344fcd2f4bfSAmy Zhang 345fcd2f4bfSAmy Zhang fmt.exponenta_bits = 6; 346fcd2f4bfSAmy Zhang fmt.mantissa_bits = 12; 347fcd2f4bfSAmy Zhang fmt.sign = true; 348fcd2f4bfSAmy Zhang 349bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(arr_points[0].x, &fmt, 350fcd2f4bfSAmy Zhang &arr_points[0].custom_float_x)) { 351fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 352fcd2f4bfSAmy Zhang return false; 353fcd2f4bfSAmy Zhang } 354fcd2f4bfSAmy Zhang 355bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(arr_points[0].offset, &fmt, 356fcd2f4bfSAmy Zhang &arr_points[0].custom_float_offset)) { 357fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 358fcd2f4bfSAmy Zhang return false; 359fcd2f4bfSAmy Zhang } 360fcd2f4bfSAmy Zhang 361bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(arr_points[0].slope, &fmt, 362fcd2f4bfSAmy Zhang &arr_points[0].custom_float_slope)) { 363fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 364fcd2f4bfSAmy Zhang return false; 365fcd2f4bfSAmy Zhang } 366fcd2f4bfSAmy Zhang 367fcd2f4bfSAmy Zhang fmt.mantissa_bits = 10; 368fcd2f4bfSAmy Zhang fmt.sign = false; 369fcd2f4bfSAmy Zhang 370bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(arr_points[1].x, &fmt, 371fcd2f4bfSAmy Zhang &arr_points[1].custom_float_x)) { 372fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 373fcd2f4bfSAmy Zhang return false; 374fcd2f4bfSAmy Zhang } 375fcd2f4bfSAmy Zhang 376bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(arr_points[1].y, &fmt, 377fcd2f4bfSAmy Zhang &arr_points[1].custom_float_y)) { 378fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 379fcd2f4bfSAmy Zhang return false; 380fcd2f4bfSAmy Zhang } 381fcd2f4bfSAmy Zhang 3824d06ccd0SHarry Wentland if (!convert_to_custom_float_format(arr_points[1].slope, &fmt, 3834d06ccd0SHarry Wentland &arr_points[1].custom_float_slope)) { 384fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 385fcd2f4bfSAmy Zhang return false; 386fcd2f4bfSAmy Zhang } 387fcd2f4bfSAmy Zhang 388fcd2f4bfSAmy Zhang fmt.mantissa_bits = 12; 389fcd2f4bfSAmy Zhang fmt.sign = true; 390fcd2f4bfSAmy Zhang 391fcd2f4bfSAmy Zhang while (i != hw_points_num) { 392bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(rgb->red, &fmt, 393fcd2f4bfSAmy Zhang &rgb->red_reg)) { 394fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 395fcd2f4bfSAmy Zhang return false; 396fcd2f4bfSAmy Zhang } 397fcd2f4bfSAmy Zhang 398bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(rgb->green, &fmt, 399fcd2f4bfSAmy Zhang &rgb->green_reg)) { 400fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 401fcd2f4bfSAmy Zhang return false; 402fcd2f4bfSAmy Zhang } 403fcd2f4bfSAmy Zhang 404bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(rgb->blue, &fmt, 405fcd2f4bfSAmy Zhang &rgb->blue_reg)) { 406fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 407fcd2f4bfSAmy Zhang return false; 408fcd2f4bfSAmy Zhang } 409fcd2f4bfSAmy Zhang 410bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(rgb->delta_red, &fmt, 411fcd2f4bfSAmy Zhang &rgb->delta_red_reg)) { 412fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 413fcd2f4bfSAmy Zhang return false; 414fcd2f4bfSAmy Zhang } 415fcd2f4bfSAmy Zhang 416bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(rgb->delta_green, &fmt, 417fcd2f4bfSAmy Zhang &rgb->delta_green_reg)) { 418fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 419fcd2f4bfSAmy Zhang return false; 420fcd2f4bfSAmy Zhang } 421fcd2f4bfSAmy Zhang 422bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(rgb->delta_blue, &fmt, 423fcd2f4bfSAmy Zhang &rgb->delta_blue_reg)) { 424fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 425fcd2f4bfSAmy Zhang return false; 426fcd2f4bfSAmy Zhang } 427fcd2f4bfSAmy Zhang 428fcd2f4bfSAmy Zhang ++rgb; 429fcd2f4bfSAmy Zhang ++i; 430fcd2f4bfSAmy Zhang } 431fcd2f4bfSAmy Zhang 432fcd2f4bfSAmy Zhang return true; 433fcd2f4bfSAmy Zhang } 434fcd2f4bfSAmy Zhang 43508616da5SLeo (Sunpeng) Li #define MAX_LOW_POINT 25 4368f8372c7SKrunoslav Kovac #define NUMBER_REGIONS 16 4378f8372c7SKrunoslav Kovac #define NUMBER_SW_SEGMENTS 16 4388f8372c7SKrunoslav Kovac 439b310b081SHarry Wentland static bool 440b310b081SHarry Wentland dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf, 441b310b081SHarry Wentland struct pwl_params *regamma_params) 442fcd2f4bfSAmy Zhang { 44323ae4f8eSAmy Zhang struct curve_points *arr_points; 44423ae4f8eSAmy Zhang struct pwl_result_data *rgb_resulted; 44523ae4f8eSAmy Zhang struct pwl_result_data *rgb; 44623ae4f8eSAmy Zhang struct pwl_result_data *rgb_plus_1; 447fcd2f4bfSAmy Zhang struct fixed31_32 y_r; 448fcd2f4bfSAmy Zhang struct fixed31_32 y_g; 449fcd2f4bfSAmy Zhang struct fixed31_32 y_b; 450fcd2f4bfSAmy Zhang struct fixed31_32 y1_min; 451fcd2f4bfSAmy Zhang struct fixed31_32 y3_max; 452fcd2f4bfSAmy Zhang 4538f8372c7SKrunoslav Kovac int32_t region_start, region_end; 4548f8372c7SKrunoslav Kovac uint32_t i, j, k, seg_distr[NUMBER_REGIONS], increment, start_index, hw_points; 45523ae4f8eSAmy Zhang 456b310b081SHarry Wentland if (output_tf == NULL || regamma_params == NULL || output_tf->type == TF_TYPE_BYPASS) 45723ae4f8eSAmy Zhang return false; 45823ae4f8eSAmy Zhang 45923ae4f8eSAmy Zhang arr_points = regamma_params->arr_points; 46023ae4f8eSAmy Zhang rgb_resulted = regamma_params->rgb_resulted; 46123ae4f8eSAmy Zhang hw_points = 0; 462fcd2f4bfSAmy Zhang 463fcd2f4bfSAmy Zhang memset(regamma_params, 0, sizeof(struct pwl_params)); 464fcd2f4bfSAmy Zhang 465fcd2f4bfSAmy Zhang if (output_tf->tf == TRANSFER_FUNCTION_PQ) { 466534db198SAmy Zhang /* 16 segments 467fcd2f4bfSAmy Zhang * segments are from 2^-11 to 2^5 468fcd2f4bfSAmy Zhang */ 46908616da5SLeo (Sunpeng) Li region_start = -11; 47008616da5SLeo (Sunpeng) Li region_end = region_start + NUMBER_REGIONS; 471fcd2f4bfSAmy Zhang 4728f8372c7SKrunoslav Kovac for (i = 0; i < NUMBER_REGIONS; i++) 4738f8372c7SKrunoslav Kovac seg_distr[i] = 4; 474534db198SAmy Zhang 475fcd2f4bfSAmy Zhang } else { 476534db198SAmy Zhang /* 10 segments 477fc6de1c5SLeo (Sunpeng) Li * segment is from 2^-10 to 2^1 478fc6de1c5SLeo (Sunpeng) Li * We include an extra segment for range [2^0, 2^1). This is to 479fc6de1c5SLeo (Sunpeng) Li * ensure that colors with normalized values of 1 don't miss the 480fc6de1c5SLeo (Sunpeng) Li * LUT. 481fcd2f4bfSAmy Zhang */ 4828f8372c7SKrunoslav Kovac region_start = -10; 483fc6de1c5SLeo (Sunpeng) Li region_end = 1; 484534db198SAmy Zhang 4858f8372c7SKrunoslav Kovac seg_distr[0] = 4; 486534db198SAmy Zhang seg_distr[1] = 4; 487534db198SAmy Zhang seg_distr[2] = 4; 488534db198SAmy Zhang seg_distr[3] = 4; 489534db198SAmy Zhang seg_distr[4] = 4; 490534db198SAmy Zhang seg_distr[5] = 4; 491534db198SAmy Zhang seg_distr[6] = 4; 492534db198SAmy Zhang seg_distr[7] = 4; 4938f8372c7SKrunoslav Kovac seg_distr[8] = 4; 4948f8372c7SKrunoslav Kovac seg_distr[9] = 4; 495fc6de1c5SLeo (Sunpeng) Li seg_distr[10] = 0; 496534db198SAmy Zhang seg_distr[11] = -1; 497534db198SAmy Zhang seg_distr[12] = -1; 498534db198SAmy Zhang seg_distr[13] = -1; 499534db198SAmy Zhang seg_distr[14] = -1; 500534db198SAmy Zhang seg_distr[15] = -1; 501fcd2f4bfSAmy Zhang } 502fcd2f4bfSAmy Zhang 503534db198SAmy Zhang for (k = 0; k < 16; k++) { 504534db198SAmy Zhang if (seg_distr[k] != -1) 505534db198SAmy Zhang hw_points += (1 << seg_distr[k]); 506534db198SAmy Zhang } 507534db198SAmy Zhang 508fcd2f4bfSAmy Zhang j = 0; 5098f8372c7SKrunoslav Kovac for (k = 0; k < (region_end - region_start); k++) { 510ec47734aSLeo (Sunpeng) Li increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]); 5118f8372c7SKrunoslav Kovac start_index = (region_start + k + MAX_LOW_POINT) * 5128f8372c7SKrunoslav Kovac NUMBER_SW_SEGMENTS; 5138f8372c7SKrunoslav Kovac for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS; 5148f8372c7SKrunoslav Kovac i += increment) { 515534db198SAmy Zhang if (j == hw_points - 1) 516fcd2f4bfSAmy Zhang break; 517fcd2f4bfSAmy Zhang rgb_resulted[j].red = output_tf->tf_pts.red[i]; 518fcd2f4bfSAmy Zhang rgb_resulted[j].green = output_tf->tf_pts.green[i]; 519fcd2f4bfSAmy Zhang rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; 520fcd2f4bfSAmy Zhang j++; 521fcd2f4bfSAmy Zhang } 522534db198SAmy Zhang } 523534db198SAmy Zhang 524534db198SAmy Zhang /* last point */ 5258f8372c7SKrunoslav Kovac start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS; 526b310b081SHarry Wentland rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index]; 527b310b081SHarry Wentland rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index]; 528b310b081SHarry Wentland rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index]; 529fcd2f4bfSAmy Zhang 530eb0e5154SDmytro Laktyushkin arr_points[0].x = dc_fixpt_pow(dc_fixpt_from_int(2), 531eb0e5154SDmytro Laktyushkin dc_fixpt_from_int(region_start)); 532eb0e5154SDmytro Laktyushkin arr_points[1].x = dc_fixpt_pow(dc_fixpt_from_int(2), 533eb0e5154SDmytro Laktyushkin dc_fixpt_from_int(region_end)); 534fcd2f4bfSAmy Zhang 535fcd2f4bfSAmy Zhang y_r = rgb_resulted[0].red; 536fcd2f4bfSAmy Zhang y_g = rgb_resulted[0].green; 537fcd2f4bfSAmy Zhang y_b = rgb_resulted[0].blue; 538fcd2f4bfSAmy Zhang 539eb0e5154SDmytro Laktyushkin y1_min = dc_fixpt_min(y_r, dc_fixpt_min(y_g, y_b)); 540fcd2f4bfSAmy Zhang 541fcd2f4bfSAmy Zhang arr_points[0].y = y1_min; 542eb0e5154SDmytro Laktyushkin arr_points[0].slope = dc_fixpt_div(arr_points[0].y, 543fcd2f4bfSAmy Zhang arr_points[0].x); 544fcd2f4bfSAmy Zhang 545fcd2f4bfSAmy Zhang y_r = rgb_resulted[hw_points - 1].red; 546fcd2f4bfSAmy Zhang y_g = rgb_resulted[hw_points - 1].green; 547fcd2f4bfSAmy Zhang y_b = rgb_resulted[hw_points - 1].blue; 548fcd2f4bfSAmy Zhang 549fcd2f4bfSAmy Zhang /* see comment above, m_arrPoints[1].y should be the Y value for the 550fcd2f4bfSAmy Zhang * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) 551fcd2f4bfSAmy Zhang */ 552eb0e5154SDmytro Laktyushkin y3_max = dc_fixpt_max(y_r, dc_fixpt_max(y_g, y_b)); 553fcd2f4bfSAmy Zhang 554fcd2f4bfSAmy Zhang arr_points[1].y = y3_max; 555fcd2f4bfSAmy Zhang 556eb0e5154SDmytro Laktyushkin arr_points[1].slope = dc_fixpt_zero; 557fcd2f4bfSAmy Zhang 558fcd2f4bfSAmy Zhang if (output_tf->tf == TRANSFER_FUNCTION_PQ) { 559fcd2f4bfSAmy Zhang /* for PQ, we want to have a straight line from last HW X point, 560fcd2f4bfSAmy Zhang * and the slope to be such that we hit 1.0 at 10000 nits. 561fcd2f4bfSAmy Zhang */ 562eb0e5154SDmytro Laktyushkin const struct fixed31_32 end_value = dc_fixpt_from_int(125); 563fcd2f4bfSAmy Zhang 564eb0e5154SDmytro Laktyushkin arr_points[1].slope = dc_fixpt_div( 565eb0e5154SDmytro Laktyushkin dc_fixpt_sub(dc_fixpt_one, arr_points[1].y), 566eb0e5154SDmytro Laktyushkin dc_fixpt_sub(end_value, arr_points[1].x)); 567fcd2f4bfSAmy Zhang } 568fcd2f4bfSAmy Zhang 569fcd2f4bfSAmy Zhang regamma_params->hw_points_num = hw_points; 570fcd2f4bfSAmy Zhang 57169133b89SAric Cyr k = 0; 57269133b89SAric Cyr for (i = 1; i < 16; i++) { 573534db198SAmy Zhang if (seg_distr[k] != -1) { 574b310b081SHarry Wentland regamma_params->arr_curve_points[k].segments_num = seg_distr[k]; 575534db198SAmy Zhang regamma_params->arr_curve_points[i].offset = 576b310b081SHarry Wentland regamma_params->arr_curve_points[k].offset + (1 << seg_distr[k]); 577fcd2f4bfSAmy Zhang } 57869133b89SAric Cyr k++; 579534db198SAmy Zhang } 580534db198SAmy Zhang 581534db198SAmy Zhang if (seg_distr[k] != -1) 582b310b081SHarry Wentland regamma_params->arr_curve_points[k].segments_num = seg_distr[k]; 583fcd2f4bfSAmy Zhang 58423ae4f8eSAmy Zhang rgb = rgb_resulted; 58523ae4f8eSAmy Zhang rgb_plus_1 = rgb_resulted + 1; 586fcd2f4bfSAmy Zhang 587fcd2f4bfSAmy Zhang i = 1; 588fcd2f4bfSAmy Zhang 589fcd2f4bfSAmy Zhang while (i != hw_points + 1) { 590eb0e5154SDmytro Laktyushkin if (dc_fixpt_lt(rgb_plus_1->red, rgb->red)) 591fcd2f4bfSAmy Zhang rgb_plus_1->red = rgb->red; 592eb0e5154SDmytro Laktyushkin if (dc_fixpt_lt(rgb_plus_1->green, rgb->green)) 593fcd2f4bfSAmy Zhang rgb_plus_1->green = rgb->green; 594eb0e5154SDmytro Laktyushkin if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue)) 595fcd2f4bfSAmy Zhang rgb_plus_1->blue = rgb->blue; 596fcd2f4bfSAmy Zhang 597eb0e5154SDmytro Laktyushkin rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red); 598eb0e5154SDmytro Laktyushkin rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green); 599eb0e5154SDmytro Laktyushkin rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue); 600fcd2f4bfSAmy Zhang 601fcd2f4bfSAmy Zhang ++rgb_plus_1; 602fcd2f4bfSAmy Zhang ++rgb; 603fcd2f4bfSAmy Zhang ++i; 604fcd2f4bfSAmy Zhang } 605fcd2f4bfSAmy Zhang 606fcd2f4bfSAmy Zhang convert_to_custom_float(rgb_resulted, arr_points, hw_points); 607fcd2f4bfSAmy Zhang 608fcd2f4bfSAmy Zhang return true; 609fcd2f4bfSAmy Zhang } 610fcd2f4bfSAmy Zhang 611a6114e85SHarry Wentland static bool 61278c77382SAnthony Koo dce110_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, 6130971c40eSHarry Wentland const struct dc_stream_state *stream) 61490e508baSAnthony Koo { 61586a66c4eSHarry Wentland struct transform *xfm = pipe_ctx->plane_res.xfm; 6164562236bSHarry Wentland 6177a09f5beSYue Hin Lau xfm->funcs->opp_power_on_regamma_lut(xfm, true); 6187a09f5beSYue Hin Lau xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; 6194562236bSHarry Wentland 6204fa086b9SLeo (Sunpeng) Li if (stream->out_transfer_func && 621efd52204SHarry Wentland stream->out_transfer_func->type == TF_TYPE_PREDEFINED && 622efd52204SHarry Wentland stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { 6237a09f5beSYue Hin Lau xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB); 624efd52204SHarry Wentland } else if (dce110_translate_regamma_to_hw_format(stream->out_transfer_func, 625efd52204SHarry Wentland &xfm->regamma_params)) { 6267a09f5beSYue Hin Lau xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params); 6277a09f5beSYue Hin Lau xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER); 6284562236bSHarry Wentland } else { 6297a09f5beSYue Hin Lau xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_BYPASS); 6304562236bSHarry Wentland } 6314562236bSHarry Wentland 6327a09f5beSYue Hin Lau xfm->funcs->opp_power_on_regamma_lut(xfm, false); 6334562236bSHarry Wentland 634cc0cb445SLeon Elazar return true; 6354562236bSHarry Wentland } 6364562236bSHarry Wentland 6374562236bSHarry Wentland void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) 6384562236bSHarry Wentland { 63902553f57SEric Bernstein bool is_hdmi_tmds; 6406f0db2dcSKrunoslav Kovac bool is_dp; 6416f0db2dcSKrunoslav Kovac 64286e2e1beSHersen Wu ASSERT(pipe_ctx->stream); 64386e2e1beSHersen Wu 6448e9c4c8cSHarry Wentland if (pipe_ctx->stream_res.stream_enc == NULL) 64586e2e1beSHersen Wu return; /* this is not root pipe */ 64686e2e1beSHersen Wu 64702553f57SEric Bernstein is_hdmi_tmds = dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal); 6486f0db2dcSKrunoslav Kovac is_dp = dc_is_dp_signal(pipe_ctx->stream->signal); 6496f0db2dcSKrunoslav Kovac 65002553f57SEric Bernstein if (!is_hdmi_tmds && !is_dp) 6516f0db2dcSKrunoslav Kovac return; 6526f0db2dcSKrunoslav Kovac 65302553f57SEric Bernstein if (is_hdmi_tmds) 6548e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets( 6558e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc, 65696c50c0dSHarry Wentland &pipe_ctx->stream_res.encoder_info_frame); 6576f0db2dcSKrunoslav Kovac else 6588e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets( 6598e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc, 66096c50c0dSHarry Wentland &pipe_ctx->stream_res.encoder_info_frame); 6614562236bSHarry Wentland } 6624562236bSHarry Wentland 6634562236bSHarry Wentland void dce110_enable_stream(struct pipe_ctx *pipe_ctx) 6644562236bSHarry Wentland { 6654562236bSHarry Wentland enum dc_lane_count lane_count = 666ceb3dbb4SJun Lei pipe_ctx->stream->link->cur_link_settings.lane_count; 6674fa086b9SLeo (Sunpeng) Li struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 668ceb3dbb4SJun Lei struct dc_link *link = pipe_ctx->stream->link; 669f42ea55bSAnthony Koo const struct dc *dc = link->dc; 670f215a57dSEric Yang 6714562236bSHarry Wentland uint32_t active_total_with_borders; 6724562236bSHarry Wentland uint32_t early_control = 0; 6736b670fa9SHarry Wentland struct timing_generator *tg = pipe_ctx->stream_res.tg; 6744562236bSHarry Wentland 675f215a57dSEric Yang /* For MST, there are multiply stream go to only one link. 676f215a57dSEric Yang * connect DIG back_end to front_end while enable_stream and 677f215a57dSEric Yang * disconnect them during disable_stream 678f215a57dSEric Yang * BY this, it is logic clean to separate stream and link */ 679f215a57dSEric Yang link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, 680f215a57dSEric Yang pipe_ctx->stream_res.stream_enc->id, true); 681f215a57dSEric Yang 682f42ea55bSAnthony Koo dc->hwss.update_info_frame(pipe_ctx); 683f215a57dSEric Yang 6844562236bSHarry Wentland /* enable early control to avoid corruption on DP monitor*/ 6854562236bSHarry Wentland active_total_with_borders = 6864562236bSHarry Wentland timing->h_addressable 6874562236bSHarry Wentland + timing->h_border_left 6884562236bSHarry Wentland + timing->h_border_right; 6894562236bSHarry Wentland 6904562236bSHarry Wentland if (lane_count != 0) 6914562236bSHarry Wentland early_control = active_total_with_borders % lane_count; 6924562236bSHarry Wentland 6934562236bSHarry Wentland if (early_control == 0) 6944562236bSHarry Wentland early_control = lane_count; 6954562236bSHarry Wentland 6964562236bSHarry Wentland tg->funcs->set_early_control(tg, early_control); 6974562236bSHarry Wentland 6984562236bSHarry Wentland /* enable audio only within mode set */ 699afaacef4SHarry Wentland if (pipe_ctx->stream_res.audio != NULL) { 7004562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal)) 7018e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc); 7024562236bSHarry Wentland } 7034562236bSHarry Wentland 704f215a57dSEric Yang 705f215a57dSEric Yang 7064562236bSHarry Wentland 7074562236bSHarry Wentland } 7084562236bSHarry Wentland 7095eefbc40SYue Hin Lau static enum bp_result link_transmitter_control( 71087401969SAndrew Jiang struct dc_bios *bios, 7115eefbc40SYue Hin Lau struct bp_transmitter_control *cntl) 7125eefbc40SYue Hin Lau { 7135eefbc40SYue Hin Lau enum bp_result result; 7145eefbc40SYue Hin Lau 71587401969SAndrew Jiang result = bios->funcs->transmitter_control(bios, cntl); 7165eefbc40SYue Hin Lau 7175eefbc40SYue Hin Lau return result; 7185eefbc40SYue Hin Lau } 7195eefbc40SYue Hin Lau 72087401969SAndrew Jiang /* 72187401969SAndrew Jiang * @brief 72287401969SAndrew Jiang * eDP only. 72387401969SAndrew Jiang */ 7248a31820bSMartin Leung void dce110_edp_wait_for_hpd_ready( 725069d418fSAndrew Jiang struct dc_link *link, 72687401969SAndrew Jiang bool power_up) 72787401969SAndrew Jiang { 728069d418fSAndrew Jiang struct dc_context *ctx = link->ctx; 729069d418fSAndrew Jiang struct graphics_object_id connector = link->link_enc->connector; 73087401969SAndrew Jiang struct gpio *hpd; 7316798d042SLewis Huang struct dc_sink *sink = link->local_sink; 73287401969SAndrew Jiang bool edp_hpd_high = false; 73387401969SAndrew Jiang uint32_t time_elapsed = 0; 73487401969SAndrew Jiang uint32_t timeout = power_up ? 73587401969SAndrew Jiang PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT; 73687401969SAndrew Jiang 73787401969SAndrew Jiang if (dal_graphics_object_id_get_connector_id(connector) 73887401969SAndrew Jiang != CONNECTOR_ID_EDP) { 73987401969SAndrew Jiang BREAK_TO_DEBUGGER(); 74087401969SAndrew Jiang return; 74187401969SAndrew Jiang } 74287401969SAndrew Jiang 74387401969SAndrew Jiang if (!power_up) 74487401969SAndrew Jiang /* 74587401969SAndrew Jiang * From KV, we will not HPD low after turning off VCC - 74687401969SAndrew Jiang * instead, we will check the SW timer in power_up(). 74787401969SAndrew Jiang */ 74887401969SAndrew Jiang return; 74987401969SAndrew Jiang 75087401969SAndrew Jiang /* 75187401969SAndrew Jiang * When we power on/off the eDP panel, 75287401969SAndrew Jiang * we need to wait until SENSE bit is high/low. 75387401969SAndrew Jiang */ 75487401969SAndrew Jiang 75587401969SAndrew Jiang /* obtain HPD */ 75687401969SAndrew Jiang /* TODO what to do with this? */ 75787401969SAndrew Jiang hpd = get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service); 75887401969SAndrew Jiang 75987401969SAndrew Jiang if (!hpd) { 76087401969SAndrew Jiang BREAK_TO_DEBUGGER(); 76187401969SAndrew Jiang return; 76287401969SAndrew Jiang } 76387401969SAndrew Jiang 7646798d042SLewis Huang if (sink != NULL) { 7656798d042SLewis Huang if (sink->edid_caps.panel_patch.extra_t3_ms > 0) { 7666798d042SLewis Huang int extra_t3_in_ms = sink->edid_caps.panel_patch.extra_t3_ms; 7676798d042SLewis Huang 7686798d042SLewis Huang msleep(extra_t3_in_ms); 7696798d042SLewis Huang } 7706798d042SLewis Huang } 7716798d042SLewis Huang 77287401969SAndrew Jiang dal_gpio_open(hpd, GPIO_MODE_INTERRUPT); 77387401969SAndrew Jiang 77487401969SAndrew Jiang /* wait until timeout or panel detected */ 77587401969SAndrew Jiang 77687401969SAndrew Jiang do { 77787401969SAndrew Jiang uint32_t detected = 0; 77887401969SAndrew Jiang 77987401969SAndrew Jiang dal_gpio_get_value(hpd, &detected); 78087401969SAndrew Jiang 78187401969SAndrew Jiang if (!(detected ^ power_up)) { 78287401969SAndrew Jiang edp_hpd_high = true; 78387401969SAndrew Jiang break; 78487401969SAndrew Jiang } 78587401969SAndrew Jiang 78687401969SAndrew Jiang msleep(HPD_CHECK_INTERVAL); 78787401969SAndrew Jiang 78887401969SAndrew Jiang time_elapsed += HPD_CHECK_INTERVAL; 78987401969SAndrew Jiang } while (time_elapsed < timeout); 79087401969SAndrew Jiang 79187401969SAndrew Jiang dal_gpio_close(hpd); 79287401969SAndrew Jiang 79387401969SAndrew Jiang dal_gpio_destroy_irq(&hpd); 79487401969SAndrew Jiang 79587401969SAndrew Jiang if (false == edp_hpd_high) { 7961296423bSBhawanpreet Lakha DC_LOG_ERROR( 79787401969SAndrew Jiang "%s: wait timed out!\n", __func__); 79887401969SAndrew Jiang } 79987401969SAndrew Jiang } 80087401969SAndrew Jiang 8018a31820bSMartin Leung void dce110_edp_power_control( 802069d418fSAndrew Jiang struct dc_link *link, 80387401969SAndrew Jiang bool power_up) 80487401969SAndrew Jiang { 805069d418fSAndrew Jiang struct dc_context *ctx = link->ctx; 80687401969SAndrew Jiang struct bp_transmitter_control cntl = { 0 }; 80787401969SAndrew Jiang enum bp_result bp_result; 80806ddcee4SJake Wang uint8_t panel_instance; 80987401969SAndrew Jiang 81087401969SAndrew Jiang 811069d418fSAndrew Jiang if (dal_graphics_object_id_get_connector_id(link->link_enc->connector) 81287401969SAndrew Jiang != CONNECTOR_ID_EDP) { 81387401969SAndrew Jiang BREAK_TO_DEBUGGER(); 81487401969SAndrew Jiang return; 81587401969SAndrew Jiang } 81687401969SAndrew Jiang 817ffadb9d6SAnthony Koo if (!link->panel_cntl) 818904fb6e0SAnthony Koo return; 819d4caa72eSAnthony Koo if (power_up != 820d4caa72eSAnthony Koo link->panel_cntl->funcs->is_panel_powered_on(link->panel_cntl)) { 821172c9b77SAshley Thomas 82278d5d04dSCharlene Liu unsigned long long current_ts = dm_get_timestamp(ctx); 823172c9b77SAshley Thomas unsigned long long time_since_edp_poweroff_ms = 82493ed1814SHugo Hu div64_u64(dm_get_elapse_time_in_ns( 82578d5d04dSCharlene Liu ctx, 82678d5d04dSCharlene Liu current_ts, 82793ed1814SHugo Hu link->link_trace.time_stamp.edp_poweroff), 1000000); 828172c9b77SAshley Thomas unsigned long long time_since_edp_poweron_ms = 829172c9b77SAshley Thomas div64_u64(dm_get_elapse_time_in_ns( 830172c9b77SAshley Thomas ctx, 831172c9b77SAshley Thomas current_ts, 832172c9b77SAshley Thomas link->link_trace.time_stamp.edp_poweron), 1000000); 833172c9b77SAshley Thomas DC_LOG_HW_RESUME_S3( 834172c9b77SAshley Thomas "%s: transition: power_up=%d current_ts=%llu edp_poweroff=%llu edp_poweron=%llu time_since_edp_poweroff_ms=%llu time_since_edp_poweron_ms=%llu", 835172c9b77SAshley Thomas __func__, 836172c9b77SAshley Thomas power_up, 837172c9b77SAshley Thomas current_ts, 838172c9b77SAshley Thomas link->link_trace.time_stamp.edp_poweroff, 839172c9b77SAshley Thomas link->link_trace.time_stamp.edp_poweron, 840172c9b77SAshley Thomas time_since_edp_poweroff_ms, 841172c9b77SAshley Thomas time_since_edp_poweron_ms); 84278d5d04dSCharlene Liu 843172c9b77SAshley Thomas /* Send VBIOS command to prompt eDP panel power */ 844172c9b77SAshley Thomas if (power_up) { 845172c9b77SAshley Thomas /* edp requires a min of 500ms from LCDVDD off to on */ 846172c9b77SAshley Thomas unsigned long long remaining_min_edp_poweroff_time_ms = 500; 847ff587987SHugo Hu 848172c9b77SAshley Thomas /* add time defined by a patch, if any (usually patch extra_t12_ms is 0) */ 8496c4fff06SYue Hin Lau if (link->local_sink != NULL) 850172c9b77SAshley Thomas remaining_min_edp_poweroff_time_ms += 851172c9b77SAshley Thomas link->local_sink->edid_caps.panel_patch.extra_t12_ms; 85278d5d04dSCharlene Liu 853172c9b77SAshley Thomas /* Adjust remaining_min_edp_poweroff_time_ms if this is not the first time. */ 854172c9b77SAshley Thomas if (link->link_trace.time_stamp.edp_poweroff != 0) { 855172c9b77SAshley Thomas if (time_since_edp_poweroff_ms < remaining_min_edp_poweroff_time_ms) 856172c9b77SAshley Thomas remaining_min_edp_poweroff_time_ms = 857172c9b77SAshley Thomas remaining_min_edp_poweroff_time_ms - time_since_edp_poweroff_ms; 858172c9b77SAshley Thomas else 859172c9b77SAshley Thomas remaining_min_edp_poweroff_time_ms = 0; 86078d5d04dSCharlene Liu } 86178d5d04dSCharlene Liu 862172c9b77SAshley Thomas if (remaining_min_edp_poweroff_time_ms) { 863172c9b77SAshley Thomas DC_LOG_HW_RESUME_S3( 864172c9b77SAshley Thomas "%s: remaining_min_edp_poweroff_time_ms=%llu: begin wait.\n", 865172c9b77SAshley Thomas __func__, remaining_min_edp_poweroff_time_ms); 866172c9b77SAshley Thomas msleep(remaining_min_edp_poweroff_time_ms); 867172c9b77SAshley Thomas DC_LOG_HW_RESUME_S3( 868172c9b77SAshley Thomas "%s: remaining_min_edp_poweroff_time_ms=%llu: end wait.\n", 869172c9b77SAshley Thomas __func__, remaining_min_edp_poweroff_time_ms); 870172c9b77SAshley Thomas dm_output_to_console("%s: wait %lld ms to power on eDP.\n", 871172c9b77SAshley Thomas __func__, remaining_min_edp_poweroff_time_ms); 872172c9b77SAshley Thomas } else { 873172c9b77SAshley Thomas DC_LOG_HW_RESUME_S3( 874172c9b77SAshley Thomas "%s: remaining_min_edp_poweroff_time_ms=%llu: no wait required.\n", 875172c9b77SAshley Thomas __func__, remaining_min_edp_poweroff_time_ms); 876172c9b77SAshley Thomas } 87778d5d04dSCharlene Liu } 87887401969SAndrew Jiang 8791296423bSBhawanpreet Lakha DC_LOG_HW_RESUME_S3( 880172c9b77SAshley Thomas "%s: BEGIN: Panel Power action: %s\n", 88187401969SAndrew Jiang __func__, (power_up ? "On":"Off")); 88287401969SAndrew Jiang 88387401969SAndrew Jiang cntl.action = power_up ? 88487401969SAndrew Jiang TRANSMITTER_CONTROL_POWER_ON : 88587401969SAndrew Jiang TRANSMITTER_CONTROL_POWER_OFF; 886069d418fSAndrew Jiang cntl.transmitter = link->link_enc->transmitter; 887069d418fSAndrew Jiang cntl.connector_obj_id = link->link_enc->connector; 88887401969SAndrew Jiang cntl.coherent = false; 88987401969SAndrew Jiang cntl.lanes_number = LANE_COUNT_FOUR; 890069d418fSAndrew Jiang cntl.hpd_sel = link->link_enc->hpd_source; 89106ddcee4SJake Wang panel_instance = link->panel_cntl->inst; 8928a0e210cSChris Park 8938a0e210cSChris Park if (ctx->dc->ctx->dmub_srv && 8948a0e210cSChris Park ctx->dc->debug.dmub_command_table) { 8958a0e210cSChris Park if (cntl.action == TRANSMITTER_CONTROL_POWER_ON) 8968a0e210cSChris Park bp_result = ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, 89706ddcee4SJake Wang LVTMA_CONTROL_POWER_ON, 89806ddcee4SJake Wang panel_instance); 8998a0e210cSChris Park else 9008a0e210cSChris Park bp_result = ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, 90106ddcee4SJake Wang LVTMA_CONTROL_POWER_OFF, 90206ddcee4SJake Wang panel_instance); 9038a0e210cSChris Park } 9048a0e210cSChris Park 90587401969SAndrew Jiang bp_result = link_transmitter_control(ctx->dc_bios, &cntl); 90687401969SAndrew Jiang 907172c9b77SAshley Thomas DC_LOG_HW_RESUME_S3( 908172c9b77SAshley Thomas "%s: END: Panel Power action: %s bp_result=%u\n", 909172c9b77SAshley Thomas __func__, (power_up ? "On":"Off"), 910172c9b77SAshley Thomas bp_result); 911172c9b77SAshley Thomas 91278d5d04dSCharlene Liu if (!power_up) 91378d5d04dSCharlene Liu /*save driver power off time stamp*/ 91478d5d04dSCharlene Liu link->link_trace.time_stamp.edp_poweroff = dm_get_timestamp(ctx); 91578d5d04dSCharlene Liu else 91678d5d04dSCharlene Liu link->link_trace.time_stamp.edp_poweron = dm_get_timestamp(ctx); 91778d5d04dSCharlene Liu 918172c9b77SAshley Thomas DC_LOG_HW_RESUME_S3( 919172c9b77SAshley Thomas "%s: updated values: edp_poweroff=%llu edp_poweron=%llu\n", 920172c9b77SAshley Thomas __func__, 921172c9b77SAshley Thomas link->link_trace.time_stamp.edp_poweroff, 922172c9b77SAshley Thomas link->link_trace.time_stamp.edp_poweron); 923172c9b77SAshley Thomas 92487401969SAndrew Jiang if (bp_result != BP_RESULT_OK) 9251296423bSBhawanpreet Lakha DC_LOG_ERROR( 92687401969SAndrew Jiang "%s: Panel Power bp_result: %d\n", 92787401969SAndrew Jiang __func__, bp_result); 92887401969SAndrew Jiang } else { 9291296423bSBhawanpreet Lakha DC_LOG_HW_RESUME_S3( 93087401969SAndrew Jiang "%s: Skipping Panel Power action: %s\n", 93187401969SAndrew Jiang __func__, (power_up ? "On":"Off")); 93287401969SAndrew Jiang } 93387401969SAndrew Jiang } 9345eefbc40SYue Hin Lau 935cf3a2627SJun Lei void dce110_edp_wait_for_T12( 936cf3a2627SJun Lei struct dc_link *link) 937cf3a2627SJun Lei { 938cf3a2627SJun Lei struct dc_context *ctx = link->ctx; 939cf3a2627SJun Lei 940cf3a2627SJun Lei if (dal_graphics_object_id_get_connector_id(link->link_enc->connector) 941cf3a2627SJun Lei != CONNECTOR_ID_EDP) { 942cf3a2627SJun Lei BREAK_TO_DEBUGGER(); 943cf3a2627SJun Lei return; 944cf3a2627SJun Lei } 945cf3a2627SJun Lei 946cf3a2627SJun Lei if (!link->panel_cntl) 947cf3a2627SJun Lei return; 948cf3a2627SJun Lei 949cf3a2627SJun Lei if (!link->panel_cntl->funcs->is_panel_powered_on(link->panel_cntl) && 950cf3a2627SJun Lei link->link_trace.time_stamp.edp_poweroff != 0) { 951cf3a2627SJun Lei unsigned int t12_duration = 500; // Default T12 as per spec 952cf3a2627SJun Lei unsigned long long current_ts = dm_get_timestamp(ctx); 953cf3a2627SJun Lei unsigned long long time_since_edp_poweroff_ms = 954cf3a2627SJun Lei div64_u64(dm_get_elapse_time_in_ns( 955cf3a2627SJun Lei ctx, 956cf3a2627SJun Lei current_ts, 957cf3a2627SJun Lei link->link_trace.time_stamp.edp_poweroff), 1000000); 958cf3a2627SJun Lei 959cf3a2627SJun Lei t12_duration += link->local_sink->edid_caps.panel_patch.extra_t12_ms; // Add extra T12 960cf3a2627SJun Lei 961cf3a2627SJun Lei if (time_since_edp_poweroff_ms < t12_duration) 962cf3a2627SJun Lei msleep(t12_duration - time_since_edp_poweroff_ms); 963cf3a2627SJun Lei } 964cf3a2627SJun Lei } 965cf3a2627SJun Lei 9665eefbc40SYue Hin Lau /*todo: cloned in stream enc, fix*/ 9675eefbc40SYue Hin Lau /* 9685eefbc40SYue Hin Lau * @brief 9695eefbc40SYue Hin Lau * eDP only. Control the backlight of the eDP panel 9705eefbc40SYue Hin Lau */ 9718a31820bSMartin Leung void dce110_edp_backlight_control( 9725eefbc40SYue Hin Lau struct dc_link *link, 9735eefbc40SYue Hin Lau bool enable) 9745eefbc40SYue Hin Lau { 975069d418fSAndrew Jiang struct dc_context *ctx = link->ctx; 9765eefbc40SYue Hin Lau struct bp_transmitter_control cntl = { 0 }; 97706ddcee4SJake Wang uint8_t panel_instance; 9785eefbc40SYue Hin Lau 979069d418fSAndrew Jiang if (dal_graphics_object_id_get_connector_id(link->link_enc->connector) 9805eefbc40SYue Hin Lau != CONNECTOR_ID_EDP) { 9815eefbc40SYue Hin Lau BREAK_TO_DEBUGGER(); 9825eefbc40SYue Hin Lau return; 9835eefbc40SYue Hin Lau } 9845eefbc40SYue Hin Lau 985014427adSSherry if (link->panel_cntl) { 986014427adSSherry bool is_backlight_on = link->panel_cntl->funcs->is_panel_backlight_on(link->panel_cntl); 987014427adSSherry 988014427adSSherry if ((enable && is_backlight_on) || (!enable && !is_backlight_on)) { 9891296423bSBhawanpreet Lakha DC_LOG_HW_RESUME_S3( 990014427adSSherry "%s: panel already powered up/off. Do nothing.\n", 9915eefbc40SYue Hin Lau __func__); 9925eefbc40SYue Hin Lau return; 9935eefbc40SYue Hin Lau } 994014427adSSherry } 9955eefbc40SYue Hin Lau 9965eefbc40SYue Hin Lau /* Send VBIOS command to control eDP panel backlight */ 9975eefbc40SYue Hin Lau 9981296423bSBhawanpreet Lakha DC_LOG_HW_RESUME_S3( 9995eefbc40SYue Hin Lau "%s: backlight action: %s\n", 10005eefbc40SYue Hin Lau __func__, (enable ? "On":"Off")); 10015eefbc40SYue Hin Lau 10025eefbc40SYue Hin Lau cntl.action = enable ? 10035eefbc40SYue Hin Lau TRANSMITTER_CONTROL_BACKLIGHT_ON : 10045eefbc40SYue Hin Lau TRANSMITTER_CONTROL_BACKLIGHT_OFF; 100587401969SAndrew Jiang 10065eefbc40SYue Hin Lau /*cntl.engine_id = ctx->engine;*/ 10075eefbc40SYue Hin Lau cntl.transmitter = link->link_enc->transmitter; 10085eefbc40SYue Hin Lau cntl.connector_obj_id = link->link_enc->connector; 10095eefbc40SYue Hin Lau /*todo: unhardcode*/ 10105eefbc40SYue Hin Lau cntl.lanes_number = LANE_COUNT_FOUR; 10115eefbc40SYue Hin Lau cntl.hpd_sel = link->link_enc->hpd_source; 1012cf1835f0SCharlene Liu cntl.signal = SIGNAL_TYPE_EDP; 10135eefbc40SYue Hin Lau 10145eefbc40SYue Hin Lau /* For eDP, the following delays might need to be considered 10155eefbc40SYue Hin Lau * after link training completed: 10165eefbc40SYue Hin Lau * idle period - min. accounts for required BS-Idle pattern, 10175eefbc40SYue Hin Lau * max. allows for source frame synchronization); 10185eefbc40SYue Hin Lau * 50 msec max. delay from valid video data from source 10195eefbc40SYue Hin Lau * to video on dislpay or backlight enable. 10205eefbc40SYue Hin Lau * 10215eefbc40SYue Hin Lau * Disable the delay for now. 10225eefbc40SYue Hin Lau * Enable it in the future if necessary. 10235eefbc40SYue Hin Lau */ 10245eefbc40SYue Hin Lau /* dc_service_sleep_in_milliseconds(50); */ 10255180d4a4SCharlene Liu /*edp 1.2*/ 102606ddcee4SJake Wang panel_instance = link->panel_cntl->inst; 1027a5148245SZhan Liu 1028a5148245SZhan Liu if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) { 1029a5148245SZhan Liu if (!link->dc->config.edp_no_power_sequencing) 1030a5148245SZhan Liu /* 1031a5148245SZhan Liu * Sometimes, DP receiver chip power-controlled externally by an 1032a5148245SZhan Liu * Embedded Controller could be treated and used as eDP, 1033a5148245SZhan Liu * if it drives mobile display. In this case, 1034a5148245SZhan Liu * we shouldn't be doing power-sequencing, hence we can skip 1035a5148245SZhan Liu * waiting for T7-ready. 1036a5148245SZhan Liu */ 10375180d4a4SCharlene Liu edp_receiver_ready_T7(link); 1038a5148245SZhan Liu else 1039a5148245SZhan Liu DC_LOG_DC("edp_receiver_ready_T7 skipped\n"); 1040a5148245SZhan Liu } 10418a0e210cSChris Park 10428a0e210cSChris Park if (ctx->dc->ctx->dmub_srv && 10438a0e210cSChris Park ctx->dc->debug.dmub_command_table) { 10448a0e210cSChris Park if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) 10458a0e210cSChris Park ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, 104606ddcee4SJake Wang LVTMA_CONTROL_LCD_BLON, 104706ddcee4SJake Wang panel_instance); 10488a0e210cSChris Park else 10498a0e210cSChris Park ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, 105006ddcee4SJake Wang LVTMA_CONTROL_LCD_BLOFF, 105106ddcee4SJake Wang panel_instance); 10528a0e210cSChris Park } 10538a0e210cSChris Park 1054069d418fSAndrew Jiang link_transmitter_control(ctx->dc_bios, &cntl); 105596577cf8SHersen Wu 105696577cf8SHersen Wu if (enable && link->dpcd_sink_ext_caps.bits.oled) 105796577cf8SHersen Wu msleep(OLED_POST_T7_DELAY); 105896577cf8SHersen Wu 105996577cf8SHersen Wu if (link->dpcd_sink_ext_caps.bits.oled || 106096577cf8SHersen Wu link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 || 106196577cf8SHersen Wu link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1) 106296577cf8SHersen Wu dc_link_backlight_enable_aux(link, enable); 106396577cf8SHersen Wu 106469b9723aSCharlene Liu /*edp 1.2*/ 1065a5148245SZhan Liu if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF) { 1066a5148245SZhan Liu if (!link->dc->config.edp_no_power_sequencing) 1067a5148245SZhan Liu /* 1068a5148245SZhan Liu * Sometimes, DP receiver chip power-controlled externally by an 1069a5148245SZhan Liu * Embedded Controller could be treated and used as eDP, 1070a5148245SZhan Liu * if it drives mobile display. In this case, 1071a5148245SZhan Liu * we shouldn't be doing power-sequencing, hence we can skip 1072a5148245SZhan Liu * waiting for T9-ready. 1073a5148245SZhan Liu */ 10743a372bedSHugo Hu edp_add_delay_for_T9(link); 1075a5148245SZhan Liu else 1076a5148245SZhan Liu DC_LOG_DC("edp_receiver_ready_T9 skipped\n"); 1077a5148245SZhan Liu } 107896577cf8SHersen Wu 107996577cf8SHersen Wu if (!enable && link->dpcd_sink_ext_caps.bits.oled) 108096577cf8SHersen Wu msleep(OLED_PRE_T11_DELAY); 10815eefbc40SYue Hin Lau } 10825eefbc40SYue Hin Lau 10831a05873fSAnthony Koo void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx) 10844562236bSHarry Wentland { 10851a05873fSAnthony Koo /* notify audio driver for audio modes of monitor */ 10862b77dcc5SAnthony Koo struct dc *dc; 10871d0610bcSAlvin Lee struct clk_mgr *clk_mgr; 10881a05873fSAnthony Koo unsigned int i, num_audio = 1; 10891a05873fSAnthony Koo 10901d0610bcSAlvin Lee if (!pipe_ctx->stream) 10911d0610bcSAlvin Lee return; 10921d0610bcSAlvin Lee 10932b77dcc5SAnthony Koo dc = pipe_ctx->stream->ctx->dc; 10942b77dcc5SAnthony Koo clk_mgr = dc->clk_mgr; 10951d0610bcSAlvin Lee 10960a32df9cSEryk Brol if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == true) 10970a32df9cSEryk Brol return; 10980a32df9cSEryk Brol 10991a05873fSAnthony Koo if (pipe_ctx->stream_res.audio) { 11001a05873fSAnthony Koo for (i = 0; i < MAX_PIPES; i++) { 11011a05873fSAnthony Koo /*current_state not updated yet*/ 11022b77dcc5SAnthony Koo if (dc->current_state->res_ctx.pipe_ctx[i].stream_res.audio != NULL) 11031a05873fSAnthony Koo num_audio++; 11041a05873fSAnthony Koo } 11051a05873fSAnthony Koo 11061a05873fSAnthony Koo pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio); 11071a05873fSAnthony Koo 1108170a2398SSu Sung Chung if (num_audio >= 1 && clk_mgr->funcs->enable_pme_wa) 11091a05873fSAnthony Koo /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ 1110170a2398SSu Sung Chung clk_mgr->funcs->enable_pme_wa(clk_mgr); 11111a05873fSAnthony Koo /* un-mute audio */ 11121a05873fSAnthony Koo /* TODO: audio should be per stream rather than per link */ 1113f01ee019SFangzhi Zuo #if defined(CONFIG_DRM_AMD_DC_DCN) 1114f01ee019SFangzhi Zuo if (is_dp_128b_132b_signal(pipe_ctx)) 1115f01ee019SFangzhi Zuo pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->audio_mute_control( 1116f01ee019SFangzhi Zuo pipe_ctx->stream_res.hpo_dp_stream_enc, false); 1117f01ee019SFangzhi Zuo else 11181a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( 11191a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc, false); 1120f01ee019SFangzhi Zuo #else 1121f01ee019SFangzhi Zuo pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( 1122f01ee019SFangzhi Zuo pipe_ctx->stream_res.stream_enc, false); 1123f01ee019SFangzhi Zuo #endif 11240a32df9cSEryk Brol if (pipe_ctx->stream_res.audio) 11250a32df9cSEryk Brol pipe_ctx->stream_res.audio->enabled = true; 11261a05873fSAnthony Koo } 11273550d622SLeo (Hanghong) Ma 11283550d622SLeo (Hanghong) Ma if (dc_is_dp_signal(pipe_ctx->stream->signal)) 11293550d622SLeo (Hanghong) Ma dp_source_sequence_trace(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_ENABLE_AUDIO_STREAM); 11301a05873fSAnthony Koo } 11311a05873fSAnthony Koo 113257430404SSu Sung Chung void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx) 11331a05873fSAnthony Koo { 11341d0610bcSAlvin Lee struct dc *dc; 11351d0610bcSAlvin Lee struct clk_mgr *clk_mgr; 11361d0610bcSAlvin Lee 11371d0610bcSAlvin Lee if (!pipe_ctx || !pipe_ctx->stream) 11381d0610bcSAlvin Lee return; 11391d0610bcSAlvin Lee 11401d0610bcSAlvin Lee dc = pipe_ctx->stream->ctx->dc; 11411d0610bcSAlvin Lee clk_mgr = dc->clk_mgr; 11424562236bSHarry Wentland 11430a32df9cSEryk Brol if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == false) 11440a32df9cSEryk Brol return; 11450a32df9cSEryk Brol 1146f01ee019SFangzhi Zuo #if defined(CONFIG_DRM_AMD_DC_DCN) 1147f01ee019SFangzhi Zuo if (is_dp_128b_132b_signal(pipe_ctx)) 1148f01ee019SFangzhi Zuo pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->audio_mute_control( 1149f01ee019SFangzhi Zuo pipe_ctx->stream_res.hpo_dp_stream_enc, true); 1150f01ee019SFangzhi Zuo else 11512b7c97d6SCharlene Liu pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( 11522b7c97d6SCharlene Liu pipe_ctx->stream_res.stream_enc, true); 1153f01ee019SFangzhi Zuo #else 1154f01ee019SFangzhi Zuo pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( 1155f01ee019SFangzhi Zuo pipe_ctx->stream_res.stream_enc, true); 1156f01ee019SFangzhi Zuo #endif 1157afaacef4SHarry Wentland if (pipe_ctx->stream_res.audio) { 11583f52aa9fSNicholas Kazlauskas pipe_ctx->stream_res.audio->enabled = false; 11593f52aa9fSNicholas Kazlauskas 11604562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal)) 1161f01ee019SFangzhi Zuo #if defined(CONFIG_DRM_AMD_DC_DCN) 1162f01ee019SFangzhi Zuo if (is_dp_128b_132b_signal(pipe_ctx)) 1163f01ee019SFangzhi Zuo pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_disable( 1164f01ee019SFangzhi Zuo pipe_ctx->stream_res.hpo_dp_stream_enc); 1165f01ee019SFangzhi Zuo else 11668e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( 11678e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc); 1168f01ee019SFangzhi Zuo #else 1169f01ee019SFangzhi Zuo pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( 1170f01ee019SFangzhi Zuo pipe_ctx->stream_res.stream_enc); 1171f01ee019SFangzhi Zuo #endif 11724562236bSHarry Wentland else 11738e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( 11748e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc); 117557430404SSu Sung Chung 1176170a2398SSu Sung Chung if (clk_mgr->funcs->enable_pme_wa) 1177070fe724SCharlene Liu /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ 1178170a2398SSu Sung Chung clk_mgr->funcs->enable_pme_wa(clk_mgr); 11794562236bSHarry Wentland 11804562236bSHarry Wentland /* TODO: notify audio driver for if audio modes list changed 11814562236bSHarry Wentland * add audio mode list change flag */ 11824562236bSHarry Wentland /* dal_audio_disable_azalia_audio_jack_presence(stream->audio, 11834562236bSHarry Wentland * stream->stream_engine_id); 11844562236bSHarry Wentland */ 11854562236bSHarry Wentland } 11863550d622SLeo (Hanghong) Ma 11873550d622SLeo (Hanghong) Ma if (dc_is_dp_signal(pipe_ctx->stream->signal)) 11883550d622SLeo (Hanghong) Ma dp_source_sequence_trace(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_DISABLE_AUDIO_STREAM); 11891a05873fSAnthony Koo } 11904562236bSHarry Wentland 119157430404SSu Sung Chung void dce110_disable_stream(struct pipe_ctx *pipe_ctx) 11921a05873fSAnthony Koo { 11931a05873fSAnthony Koo struct dc_stream_state *stream = pipe_ctx->stream; 1194ceb3dbb4SJun Lei struct dc_link *link = stream->link; 11951a05873fSAnthony Koo struct dc *dc = pipe_ctx->stream->ctx->dc; 119664d283cbSJimmy Kizito struct link_encoder *link_enc = NULL; 11971a05873fSAnthony Koo 1198ac42fd63SWenjing Liu if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) { 11991a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets( 12001a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc); 1201ac42fd63SWenjing Liu pipe_ctx->stream_res.stream_enc->funcs->hdmi_reset_stream_attribute( 1202ac42fd63SWenjing Liu pipe_ctx->stream_res.stream_enc); 1203ac42fd63SWenjing Liu } 12041a05873fSAnthony Koo 1205f01ee019SFangzhi Zuo #if defined(CONFIG_DRM_AMD_DC_DCN) 1206f01ee019SFangzhi Zuo if (is_dp_128b_132b_signal(pipe_ctx)) { 1207f01ee019SFangzhi Zuo pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->stop_dp_info_packets( 1208f01ee019SFangzhi Zuo pipe_ctx->stream_res.hpo_dp_stream_enc); 1209f01ee019SFangzhi Zuo } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) 1210f01ee019SFangzhi Zuo #else 12111a05873fSAnthony Koo if (dc_is_dp_signal(pipe_ctx->stream->signal)) 1212f01ee019SFangzhi Zuo #endif 12131a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets( 12141a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc); 12151a05873fSAnthony Koo 121657430404SSu Sung Chung dc->hwss.disable_audio_stream(pipe_ctx); 1217904623eeSYongqiang Sun 121864d283cbSJimmy Kizito /* Link encoder may have been dynamically assigned to non-physical display endpoint. */ 121964d283cbSJimmy Kizito if (link->ep_type == DISPLAY_ENDPOINT_PHY) 122064d283cbSJimmy Kizito link_enc = link->link_enc; 122164d283cbSJimmy Kizito else if (dc->res_pool->funcs->link_encs_assign) 12220d4b4253SJimmy Kizito link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); 122364d283cbSJimmy Kizito ASSERT(link_enc); 122464d283cbSJimmy Kizito 1225f01ee019SFangzhi Zuo #if defined(CONFIG_DRM_AMD_DC_DCN) 1226f01ee019SFangzhi Zuo if (is_dp_128b_132b_signal(pipe_ctx)) { 1227f01ee019SFangzhi Zuo pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->disable( 1228f01ee019SFangzhi Zuo pipe_ctx->stream_res.hpo_dp_stream_enc); 1229f01ee019SFangzhi Zuo setup_dp_hpo_stream(pipe_ctx, false); 1230f01ee019SFangzhi Zuo /* TODO - DP2.0 HW: unmap stream from link encoder here */ 1231f01ee019SFangzhi Zuo } else { 123264d283cbSJimmy Kizito if (link_enc) 123364d283cbSJimmy Kizito link_enc->funcs->connect_dig_be_to_fe( 123464d283cbSJimmy Kizito link_enc, 12358e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->id, 12364562236bSHarry Wentland false); 1237f01ee019SFangzhi Zuo } 1238f01ee019SFangzhi Zuo #else 123964d283cbSJimmy Kizito if (link_enc) 124064d283cbSJimmy Kizito link_enc->funcs->connect_dig_be_to_fe( 1241f01ee019SFangzhi Zuo link->link_enc, 1242f01ee019SFangzhi Zuo pipe_ctx->stream_res.stream_enc->id, 1243f01ee019SFangzhi Zuo false); 1244f01ee019SFangzhi Zuo #endif 12453550d622SLeo (Hanghong) Ma if (dc_is_dp_signal(pipe_ctx->stream->signal)) 12463550d622SLeo (Hanghong) Ma dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISCONNECT_DIG_FE_BE); 1247*0a068b68SJake Wang 1248*0a068b68SJake Wang #if defined(CONFIG_DRM_AMD_DC_DCN) 1249*0a068b68SJake Wang if (dc->hwseq->funcs.setup_hpo_hw_control && is_dp_128b_132b_signal(pipe_ctx)) 1250*0a068b68SJake Wang dc->hwseq->funcs.setup_hpo_hw_control(dc->hwseq, false); 1251*0a068b68SJake Wang #endif 1252*0a068b68SJake Wang 12534562236bSHarry Wentland } 12544562236bSHarry Wentland 12554562236bSHarry Wentland void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, 12564562236bSHarry Wentland struct dc_link_settings *link_settings) 12574562236bSHarry Wentland { 12584562236bSHarry Wentland struct encoder_unblank_param params = { { 0 } }; 125941b49742SCharlene Liu struct dc_stream_state *stream = pipe_ctx->stream; 1260ceb3dbb4SJun Lei struct dc_link *link = stream->link; 1261f42ea55bSAnthony Koo struct dce_hwseq *hws = link->dc->hwseq; 12624562236bSHarry Wentland 12634562236bSHarry Wentland /* only 3 items below are used by unblank */ 12647fe538a4SCharlene Liu params.timing = pipe_ctx->stream->timing; 12654562236bSHarry Wentland params.link_settings.link_rate = link_settings->link_rate; 126641b49742SCharlene Liu 126741b49742SCharlene Liu if (dc_is_dp_signal(pipe_ctx->stream->signal)) 12683550d622SLeo (Hanghong) Ma pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, ¶ms); 126941b49742SCharlene Liu 127014d6f644SYongqiang Sun if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { 1271f42ea55bSAnthony Koo hws->funcs.edp_backlight_control(link, true); 127214d6f644SYongqiang Sun } 127341b49742SCharlene Liu } 12742c850b7bSDmytro Laktyushkin 127541b49742SCharlene Liu void dce110_blank_stream(struct pipe_ctx *pipe_ctx) 127641b49742SCharlene Liu { 127741b49742SCharlene Liu struct dc_stream_state *stream = pipe_ctx->stream; 1278ceb3dbb4SJun Lei struct dc_link *link = stream->link; 1279f42ea55bSAnthony Koo struct dce_hwseq *hws = link->dc->hwseq; 128041b49742SCharlene Liu 1281ab892598SRoman Li if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { 1282f42ea55bSAnthony Koo hws->funcs.edp_backlight_control(link, false); 12833ba01817SYongqiang Sun link->dc->hwss.set_abm_immediate_disable(pipe_ctx); 1284ab892598SRoman Li } 128541b49742SCharlene Liu 1286f01ee019SFangzhi Zuo #if defined(CONFIG_DRM_AMD_DC_DCN) 1287f01ee019SFangzhi Zuo if (is_dp_128b_132b_signal(pipe_ctx)) { 1288f01ee019SFangzhi Zuo /* TODO - DP2.0 HW: Set ODM mode in dp hpo encoder here */ 1289f01ee019SFangzhi Zuo pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_blank( 1290f01ee019SFangzhi Zuo pipe_ctx->stream_res.hpo_dp_stream_enc); 1291f01ee019SFangzhi Zuo } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) { 1292f01ee019SFangzhi Zuo #else 1293eec3303dSAric Cyr if (dc_is_dp_signal(pipe_ctx->stream->signal)) { 1294f01ee019SFangzhi Zuo #endif 12953550d622SLeo (Hanghong) Ma pipe_ctx->stream_res.stream_enc->funcs->dp_blank(link, pipe_ctx->stream_res.stream_enc); 1296eec3303dSAric Cyr 12973a372bedSHugo Hu if (!dc_is_embedded_signal(pipe_ctx->stream->signal)) { 1298eec3303dSAric Cyr /* 1299eec3303dSAric Cyr * After output is idle pattern some sinks need time to recognize the stream 1300eec3303dSAric Cyr * has changed or they enter protection state and hang. 1301eec3303dSAric Cyr */ 1302eec3303dSAric Cyr msleep(60); 13033a372bedSHugo Hu } else if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP) 13043a372bedSHugo Hu edp_receiver_ready_T9(link); 1305eec3303dSAric Cyr } 1306eec3303dSAric Cyr 13074562236bSHarry Wentland } 13084562236bSHarry Wentland 130915e17335SCharlene Liu 131015e17335SCharlene Liu void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) 131115e17335SCharlene Liu { 13128e9c4c8cSHarry Wentland if (pipe_ctx != NULL && pipe_ctx->stream_res.stream_enc != NULL) 13138e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->set_avmute(pipe_ctx->stream_res.stream_enc, enable); 131415e17335SCharlene Liu } 131515e17335SCharlene Liu 13164562236bSHarry Wentland static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id) 13174562236bSHarry Wentland { 13184562236bSHarry Wentland switch (crtc_id) { 13194562236bSHarry Wentland case CONTROLLER_ID_D0: 13204562236bSHarry Wentland return DTO_SOURCE_ID0; 13214562236bSHarry Wentland case CONTROLLER_ID_D1: 13224562236bSHarry Wentland return DTO_SOURCE_ID1; 13234562236bSHarry Wentland case CONTROLLER_ID_D2: 13244562236bSHarry Wentland return DTO_SOURCE_ID2; 13254562236bSHarry Wentland case CONTROLLER_ID_D3: 13264562236bSHarry Wentland return DTO_SOURCE_ID3; 13274562236bSHarry Wentland case CONTROLLER_ID_D4: 13284562236bSHarry Wentland return DTO_SOURCE_ID4; 13294562236bSHarry Wentland case CONTROLLER_ID_D5: 13304562236bSHarry Wentland return DTO_SOURCE_ID5; 13314562236bSHarry Wentland default: 13324562236bSHarry Wentland return DTO_SOURCE_UNKNOWN; 13334562236bSHarry Wentland } 13344562236bSHarry Wentland } 13354562236bSHarry Wentland 13364562236bSHarry Wentland static void build_audio_output( 1337ab8db3e1SAndrey Grodzovsky struct dc_state *state, 13384562236bSHarry Wentland const struct pipe_ctx *pipe_ctx, 13394562236bSHarry Wentland struct audio_output *audio_output) 13404562236bSHarry Wentland { 13410971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 13428e9c4c8cSHarry Wentland audio_output->engine_id = pipe_ctx->stream_res.stream_enc->id; 13434562236bSHarry Wentland 13444562236bSHarry Wentland audio_output->signal = pipe_ctx->stream->signal; 13454562236bSHarry Wentland 13464562236bSHarry Wentland /* audio_crtc_info */ 13474562236bSHarry Wentland 13484562236bSHarry Wentland audio_output->crtc_info.h_total = 13494fa086b9SLeo (Sunpeng) Li stream->timing.h_total; 13504562236bSHarry Wentland 13514562236bSHarry Wentland /* 13524562236bSHarry Wentland * Audio packets are sent during actual CRTC blank physical signal, we 13534562236bSHarry Wentland * need to specify actual active signal portion 13544562236bSHarry Wentland */ 13554562236bSHarry Wentland audio_output->crtc_info.h_active = 13564fa086b9SLeo (Sunpeng) Li stream->timing.h_addressable 13574fa086b9SLeo (Sunpeng) Li + stream->timing.h_border_left 13584fa086b9SLeo (Sunpeng) Li + stream->timing.h_border_right; 13594562236bSHarry Wentland 13604562236bSHarry Wentland audio_output->crtc_info.v_active = 13614fa086b9SLeo (Sunpeng) Li stream->timing.v_addressable 13624fa086b9SLeo (Sunpeng) Li + stream->timing.v_border_top 13634fa086b9SLeo (Sunpeng) Li + stream->timing.v_border_bottom; 13644562236bSHarry Wentland 13654562236bSHarry Wentland audio_output->crtc_info.pixel_repetition = 1; 13664562236bSHarry Wentland 13674562236bSHarry Wentland audio_output->crtc_info.interlaced = 13684fa086b9SLeo (Sunpeng) Li stream->timing.flags.INTERLACE; 13694562236bSHarry Wentland 13704562236bSHarry Wentland audio_output->crtc_info.refresh_rate = 137140fd9090SNevenko Stupar (stream->timing.pix_clk_100hz*100)/ 13724fa086b9SLeo (Sunpeng) Li (stream->timing.h_total*stream->timing.v_total); 13734562236bSHarry Wentland 13744562236bSHarry Wentland audio_output->crtc_info.color_depth = 13754fa086b9SLeo (Sunpeng) Li stream->timing.display_color_depth; 13764562236bSHarry Wentland 137740fd9090SNevenko Stupar audio_output->crtc_info.requested_pixel_clock_100Hz = 137840fd9090SNevenko Stupar pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz; 13794562236bSHarry Wentland 138040fd9090SNevenko Stupar audio_output->crtc_info.calculated_pixel_clock_100Hz = 138140fd9090SNevenko Stupar pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz; 13824562236bSHarry Wentland 138387b58768SCharlene Liu /*for HDMI, audio ACR is with deep color ratio factor*/ 13842166d9fbSCharlene Liu if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal) && 138540fd9090SNevenko Stupar audio_output->crtc_info.requested_pixel_clock_100Hz == 138640fd9090SNevenko Stupar (stream->timing.pix_clk_100hz)) { 138710688217SHarry Wentland if (pipe_ctx->stream_res.pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) { 138840fd9090SNevenko Stupar audio_output->crtc_info.requested_pixel_clock_100Hz = 138940fd9090SNevenko Stupar audio_output->crtc_info.requested_pixel_clock_100Hz/2; 139040fd9090SNevenko Stupar audio_output->crtc_info.calculated_pixel_clock_100Hz = 139140fd9090SNevenko Stupar pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz/2; 139287b58768SCharlene Liu 139387b58768SCharlene Liu } 139487b58768SCharlene Liu } 139587b58768SCharlene Liu 1396ed476602SAhzo if (state->clk_mgr && 1397ed476602SAhzo (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT || 1398ed476602SAhzo pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)) { 13994562236bSHarry Wentland audio_output->pll_info.dp_dto_source_clock_in_khz = 14000de34efcSDmytro Laktyushkin state->clk_mgr->funcs->get_dp_ref_clk_frequency( 14010de34efcSDmytro Laktyushkin state->clk_mgr); 14024562236bSHarry Wentland } 14034562236bSHarry Wentland 14044562236bSHarry Wentland audio_output->pll_info.feed_back_divider = 14054562236bSHarry Wentland pipe_ctx->pll_settings.feedback_divider; 14064562236bSHarry Wentland 14074562236bSHarry Wentland audio_output->pll_info.dto_source = 14084562236bSHarry Wentland translate_to_dto_source( 1409e07f541fSYongqiang Sun pipe_ctx->stream_res.tg->inst + 1); 14104562236bSHarry Wentland 14114562236bSHarry Wentland /* TODO hard code to enable for now. Need get from stream */ 14124562236bSHarry Wentland audio_output->pll_info.ss_enabled = true; 14134562236bSHarry Wentland 14144562236bSHarry Wentland audio_output->pll_info.ss_percentage = 14154562236bSHarry Wentland pipe_ctx->pll_settings.ss_percentage; 14164562236bSHarry Wentland } 14174562236bSHarry Wentland 1418fb3466a4SBhawanpreet Lakha static void program_scaler(const struct dc *dc, 14194562236bSHarry Wentland const struct pipe_ctx *pipe_ctx) 14204562236bSHarry Wentland { 14214562236bSHarry Wentland struct tg_color color = {0}; 14224562236bSHarry Wentland 1423b86a1aa3SBhawanpreet Lakha #if defined(CONFIG_DRM_AMD_DC_DCN) 1424ff5ef992SAlex Deucher /* TOFPGA */ 142586a66c4eSHarry Wentland if (pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth == NULL) 1426ff5ef992SAlex Deucher return; 1427ff5ef992SAlex Deucher #endif 1428ff5ef992SAlex Deucher 1429bf53769dSGloria Li if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) 14304562236bSHarry Wentland get_surface_visual_confirm_color(pipe_ctx, &color); 14314562236bSHarry Wentland else 14324562236bSHarry Wentland color_space_to_black_color(dc, 14334fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->output_color_space, 14344562236bSHarry Wentland &color); 14354562236bSHarry Wentland 143686a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth( 143786a66c4eSHarry Wentland pipe_ctx->plane_res.xfm, 14386702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth, 14394562236bSHarry Wentland &pipe_ctx->stream->bit_depth_params); 14404562236bSHarry Wentland 144112750d16SEric Yang if (pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color) { 144212750d16SEric Yang /* 144312750d16SEric Yang * The way 420 is packed, 2 channels carry Y component, 1 channel 144412750d16SEric Yang * alternate between Cb and Cr, so both channels need the pixel 144512750d16SEric Yang * value for Y 144612750d16SEric Yang */ 144712750d16SEric Yang if (pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) 144812750d16SEric Yang color.color_r_cr = color.color_g_y; 144912750d16SEric Yang 14506b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color( 14516b670fa9SHarry Wentland pipe_ctx->stream_res.tg, 14524562236bSHarry Wentland &color); 145312750d16SEric Yang } 14544562236bSHarry Wentland 145586a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm, 14566702a9acSHarry Wentland &pipe_ctx->plane_res.scl_data); 14574562236bSHarry Wentland } 14584562236bSHarry Wentland 14593158223eSEric Bernstein static enum dc_status dce110_enable_stream_timing( 14604562236bSHarry Wentland struct pipe_ctx *pipe_ctx, 1461608ac7bbSJerry Zuo struct dc_state *context, 1462fb3466a4SBhawanpreet Lakha struct dc *dc) 14634562236bSHarry Wentland { 14640971c40eSHarry Wentland struct dc_stream_state *stream = pipe_ctx->stream; 1465608ac7bbSJerry Zuo struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx. 14664562236bSHarry Wentland pipe_ctx[pipe_ctx->pipe_idx]; 14674562236bSHarry Wentland struct tg_color black_color = {0}; 14684562236bSHarry Wentland 14694562236bSHarry Wentland if (!pipe_ctx_old->stream) { 14704562236bSHarry Wentland 14714562236bSHarry Wentland /* program blank color */ 14724562236bSHarry Wentland color_space_to_black_color(dc, 14734fa086b9SLeo (Sunpeng) Li stream->output_color_space, &black_color); 14746b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->set_blank_color( 14756b670fa9SHarry Wentland pipe_ctx->stream_res.tg, 14764562236bSHarry Wentland &black_color); 14774b5e7d62SHersen Wu 14784562236bSHarry Wentland /* 14794562236bSHarry Wentland * Must blank CRTC after disabling power gating and before any 14804562236bSHarry Wentland * programming, otherwise CRTC will be hung in bad state 14814562236bSHarry Wentland */ 14826b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true); 14834562236bSHarry Wentland 14844562236bSHarry Wentland if (false == pipe_ctx->clock_source->funcs->program_pix_clk( 14854562236bSHarry Wentland pipe_ctx->clock_source, 148610688217SHarry Wentland &pipe_ctx->stream_res.pix_clk_params, 14874562236bSHarry Wentland &pipe_ctx->pll_settings)) { 14884562236bSHarry Wentland BREAK_TO_DEBUGGER(); 14894562236bSHarry Wentland return DC_ERROR_UNEXPECTED; 14904562236bSHarry Wentland } 14914562236bSHarry Wentland 14926b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->program_timing( 14936b670fa9SHarry Wentland pipe_ctx->stream_res.tg, 14944fa086b9SLeo (Sunpeng) Li &stream->timing, 1495e7e10c46SDmytro Laktyushkin 0, 1496e7e10c46SDmytro Laktyushkin 0, 1497e7e10c46SDmytro Laktyushkin 0, 1498e7e10c46SDmytro Laktyushkin 0, 1499e7e10c46SDmytro Laktyushkin pipe_ctx->stream->signal, 15004562236bSHarry Wentland true); 15014562236bSHarry Wentland } 15024562236bSHarry Wentland 15034562236bSHarry Wentland if (!pipe_ctx_old->stream) { 15046b670fa9SHarry Wentland if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc( 15056b670fa9SHarry Wentland pipe_ctx->stream_res.tg)) { 15064562236bSHarry Wentland BREAK_TO_DEBUGGER(); 15074562236bSHarry Wentland return DC_ERROR_UNEXPECTED; 15084562236bSHarry Wentland } 15094562236bSHarry Wentland } 15104562236bSHarry Wentland 15114562236bSHarry Wentland return DC_OK; 15124562236bSHarry Wentland } 15134562236bSHarry Wentland 15144562236bSHarry Wentland static enum dc_status apply_single_controller_ctx_to_hw( 15154562236bSHarry Wentland struct pipe_ctx *pipe_ctx, 1516608ac7bbSJerry Zuo struct dc_state *context, 1517fb3466a4SBhawanpreet Lakha struct dc *dc) 15184562236bSHarry Wentland { 15190971c40eSHarry Wentland struct dc_stream_state *stream = pipe_ctx->stream; 15203550d622SLeo (Hanghong) Ma struct dc_link *link = stream->link; 15219c0fb8d4SAnthony Koo struct drr_params params = {0}; 15229c0fb8d4SAnthony Koo unsigned int event_triggers = 0; 1523b1f6d01cSDmytro Laktyushkin struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe; 1524f42ea55bSAnthony Koo struct dce_hwseq *hws = dc->hwseq; 15254562236bSHarry Wentland 1526f42ea55bSAnthony Koo if (hws->funcs.disable_stream_gating) { 1527f42ea55bSAnthony Koo hws->funcs.disable_stream_gating(dc, pipe_ctx); 1528240d09d0SGary Kattan } 1529240d09d0SGary Kattan 15301a05873fSAnthony Koo if (pipe_ctx->stream_res.audio != NULL) { 15311a05873fSAnthony Koo struct audio_output audio_output; 15321a05873fSAnthony Koo 15331a05873fSAnthony Koo build_audio_output(context, pipe_ctx, &audio_output); 15341a05873fSAnthony Koo 15351a05873fSAnthony Koo if (dc_is_dp_signal(pipe_ctx->stream->signal)) 1536f01ee019SFangzhi Zuo #if defined(CONFIG_DRM_AMD_DC_DCN) 1537f01ee019SFangzhi Zuo if (is_dp_128b_132b_signal(pipe_ctx)) 1538f01ee019SFangzhi Zuo pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_setup( 1539f01ee019SFangzhi Zuo pipe_ctx->stream_res.hpo_dp_stream_enc, 1540f01ee019SFangzhi Zuo pipe_ctx->stream_res.audio->inst, 1541f01ee019SFangzhi Zuo &pipe_ctx->stream->audio_info); 1542f01ee019SFangzhi Zuo else 15431a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( 15441a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc, 15451a05873fSAnthony Koo pipe_ctx->stream_res.audio->inst, 15461a05873fSAnthony Koo &pipe_ctx->stream->audio_info); 1547f01ee019SFangzhi Zuo #else 1548f01ee019SFangzhi Zuo pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( 1549f01ee019SFangzhi Zuo pipe_ctx->stream_res.stream_enc, 1550f01ee019SFangzhi Zuo pipe_ctx->stream_res.audio->inst, 1551f01ee019SFangzhi Zuo &pipe_ctx->stream->audio_info); 1552f01ee019SFangzhi Zuo #endif 15531a05873fSAnthony Koo else 15541a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup( 15551a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc, 15561a05873fSAnthony Koo pipe_ctx->stream_res.audio->inst, 15571a05873fSAnthony Koo &pipe_ctx->stream->audio_info, 15581a05873fSAnthony Koo &audio_output.crtc_info); 15591a05873fSAnthony Koo 15601a05873fSAnthony Koo pipe_ctx->stream_res.audio->funcs->az_configure( 15611a05873fSAnthony Koo pipe_ctx->stream_res.audio, 15621a05873fSAnthony Koo pipe_ctx->stream->signal, 15631a05873fSAnthony Koo &audio_output.crtc_info, 15641a05873fSAnthony Koo &pipe_ctx->stream->audio_info); 15651a05873fSAnthony Koo } 15661a05873fSAnthony Koo 1567f01ee019SFangzhi Zuo #if defined(CONFIG_DRM_AMD_DC_DCN) 1568f01ee019SFangzhi Zuo /* DCN3.1 FPGA Workaround 1569f01ee019SFangzhi Zuo * Need to enable HPO DP Stream Encoder before setting OTG master enable. 1570f01ee019SFangzhi Zuo * To do so, move calling function enable_stream_timing to only be done AFTER calling 1571f01ee019SFangzhi Zuo * function core_link_enable_stream 1572f01ee019SFangzhi Zuo */ 1573f01ee019SFangzhi Zuo if (!(hws->wa.dp_hpo_and_otg_sequence && is_dp_128b_132b_signal(pipe_ctx))) 1574f01ee019SFangzhi Zuo #endif 15754562236bSHarry Wentland /* */ 1576d2d7885fSAnthony Koo /* Do not touch stream timing on seamless boot optimization. */ 1577d2d7885fSAnthony Koo if (!pipe_ctx->stream->apply_seamless_boot_optimization) 1578f42ea55bSAnthony Koo hws->funcs.enable_stream_timing(pipe_ctx, context, dc); 15794562236bSHarry Wentland 1580f42ea55bSAnthony Koo if (hws->funcs.setup_vupdate_interrupt) 1581f42ea55bSAnthony Koo hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx); 1582a122b62dSAnthony Koo 15839c0fb8d4SAnthony Koo params.vertical_total_min = stream->adjust.v_total_min; 15849c0fb8d4SAnthony Koo params.vertical_total_max = stream->adjust.v_total_max; 15859c0fb8d4SAnthony Koo if (pipe_ctx->stream_res.tg->funcs->set_drr) 15869c0fb8d4SAnthony Koo pipe_ctx->stream_res.tg->funcs->set_drr( 15879c0fb8d4SAnthony Koo pipe_ctx->stream_res.tg, ¶ms); 15889c0fb8d4SAnthony Koo 15899c0fb8d4SAnthony Koo // DRR should set trigger event to monitor surface update event 15909c0fb8d4SAnthony Koo if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0) 15919c0fb8d4SAnthony Koo event_triggers = 0x80; 15925b5abe95SAnthony Koo /* Event triggers and num frames initialized for DRR, but can be 15935b5abe95SAnthony Koo * later updated for PSR use. Note DRR trigger events are generated 15945b5abe95SAnthony Koo * regardless of whether num frames met. 15955b5abe95SAnthony Koo */ 15969c0fb8d4SAnthony Koo if (pipe_ctx->stream_res.tg->funcs->set_static_screen_control) 15979c0fb8d4SAnthony Koo pipe_ctx->stream_res.tg->funcs->set_static_screen_control( 15985b5abe95SAnthony Koo pipe_ctx->stream_res.tg, event_triggers, 2); 15999c0fb8d4SAnthony Koo 1600248cbed6SEric Bernstein if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) 1601d2c460e7Shersen wu pipe_ctx->stream_res.stream_enc->funcs->dig_connect_to_otg( 1602d2c460e7Shersen wu pipe_ctx->stream_res.stream_enc, 1603d2c460e7Shersen wu pipe_ctx->stream_res.tg->inst); 1604aa9c4abeSNikola Cornij 16053550d622SLeo (Hanghong) Ma if (dc_is_dp_signal(pipe_ctx->stream->signal)) 16063550d622SLeo (Hanghong) Ma dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_OTG); 16073550d622SLeo (Hanghong) Ma 1608f0c4d997SCorbin McElhanney pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion( 1609f0c4d997SCorbin McElhanney pipe_ctx->stream_res.opp, 1610f0c4d997SCorbin McElhanney COLOR_SPACE_YCBCR601, 1611f0c4d997SCorbin McElhanney stream->timing.display_color_depth, 1612661a8cd9SDmytro Laktyushkin stream->signal); 16134562236bSHarry Wentland 1614a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp->funcs->opp_program_fmt( 1615a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp, 1616181a888fSCharlene Liu &stream->bit_depth_params, 1617181a888fSCharlene Liu &stream->clamping); 1618b1f6d01cSDmytro Laktyushkin while (odm_pipe) { 16197ed4e635SHarry Wentland odm_pipe->stream_res.opp->funcs->opp_set_dyn_expansion( 16207ed4e635SHarry Wentland odm_pipe->stream_res.opp, 16217ed4e635SHarry Wentland COLOR_SPACE_YCBCR601, 16227ed4e635SHarry Wentland stream->timing.display_color_depth, 16237ed4e635SHarry Wentland stream->signal); 16247ed4e635SHarry Wentland 16257ed4e635SHarry Wentland odm_pipe->stream_res.opp->funcs->opp_program_fmt( 16267ed4e635SHarry Wentland odm_pipe->stream_res.opp, 16277ed4e635SHarry Wentland &stream->bit_depth_params, 16287ed4e635SHarry Wentland &stream->clamping); 1629b1f6d01cSDmytro Laktyushkin odm_pipe = odm_pipe->next_odm_pipe; 16307ed4e635SHarry Wentland } 1631603767f9STony Cheng 16321e7e86c4SSamson Tam if (!stream->dpms_off) 1633ab8db3e1SAndrey Grodzovsky core_link_enable_stream(context, pipe_ctx); 16344562236bSHarry Wentland 1635f01ee019SFangzhi Zuo #if defined(CONFIG_DRM_AMD_DC_DCN) 1636f01ee019SFangzhi Zuo /* DCN3.1 FPGA Workaround 1637f01ee019SFangzhi Zuo * Need to enable HPO DP Stream Encoder before setting OTG master enable. 1638f01ee019SFangzhi Zuo * To do so, move calling function enable_stream_timing to only be done AFTER calling 1639f01ee019SFangzhi Zuo * function core_link_enable_stream 1640f01ee019SFangzhi Zuo */ 1641f01ee019SFangzhi Zuo if (hws->wa.dp_hpo_and_otg_sequence && is_dp_128b_132b_signal(pipe_ctx)) { 1642f01ee019SFangzhi Zuo if (!pipe_ctx->stream->apply_seamless_boot_optimization) 1643f01ee019SFangzhi Zuo hws->funcs.enable_stream_timing(pipe_ctx, context, dc); 1644f01ee019SFangzhi Zuo } 1645f01ee019SFangzhi Zuo #endif 1646f01ee019SFangzhi Zuo 16476702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; 16484562236bSHarry Wentland 1649d1ebfdd8SWyatt Wood pipe_ctx->stream->link->psr_settings.psr_feature_enabled = false; 165094267b3dSSylvia Tsai 16514562236bSHarry Wentland return DC_OK; 16524562236bSHarry Wentland } 16534562236bSHarry Wentland 16544562236bSHarry Wentland /******************************************************************************/ 16554562236bSHarry Wentland 1656fb3466a4SBhawanpreet Lakha static void power_down_encoders(struct dc *dc) 16574562236bSHarry Wentland { 1658c494e579SAgustin Gutierrez int i, j; 1659b9b171ffSHersen Wu 16604562236bSHarry Wentland for (i = 0; i < dc->link_count; i++) { 1661d4c2a96fSLewis Huang enum signal_type signal = dc->links[i]->connector_signal; 1662a0c38ebaSCharlene Liu 1663c494e579SAgustin Gutierrez if ((signal == SIGNAL_TYPE_EDP) || 1664c494e579SAgustin Gutierrez (signal == SIGNAL_TYPE_DISPLAY_PORT)) { 1665c494e579SAgustin Gutierrez if (dc->links[i]->link_enc->funcs->get_dig_frontend && 1666c494e579SAgustin Gutierrez dc->links[i]->link_enc->funcs->is_dig_enabled(dc->links[i]->link_enc)) { 1667c494e579SAgustin Gutierrez unsigned int fe = dc->links[i]->link_enc->funcs->get_dig_frontend( 1668c494e579SAgustin Gutierrez dc->links[i]->link_enc); 1669c494e579SAgustin Gutierrez 1670c494e579SAgustin Gutierrez for (j = 0; j < dc->res_pool->stream_enc_count; j++) { 1671c494e579SAgustin Gutierrez if (fe == dc->res_pool->stream_enc[j]->id) { 1672c494e579SAgustin Gutierrez dc->res_pool->stream_enc[j]->funcs->dp_blank(dc->links[i], 1673c494e579SAgustin Gutierrez dc->res_pool->stream_enc[j]); 1674c494e579SAgustin Gutierrez break; 1675c494e579SAgustin Gutierrez } 1676c494e579SAgustin Gutierrez } 1677c494e579SAgustin Gutierrez } 1678c494e579SAgustin Gutierrez 1679c494e579SAgustin Gutierrez if (!dc->links[i]->wa_flags.dp_keep_receiver_powered) 1680c494e579SAgustin Gutierrez dp_receiver_power_ctrl(dc->links[i], false); 1681c494e579SAgustin Gutierrez } 1682c494e579SAgustin Gutierrez 16834338ffa8SSung Lee if (signal != SIGNAL_TYPE_EDP) 16844338ffa8SSung Lee signal = SIGNAL_TYPE_NONE; 16854338ffa8SSung Lee 168664d283cbSJimmy Kizito if (dc->links[i]->ep_type == DISPLAY_ENDPOINT_PHY) 16874562236bSHarry Wentland dc->links[i]->link_enc->funcs->disable_output( 1688069d418fSAndrew Jiang dc->links[i]->link_enc, signal); 1689b56e90eaSPaul Hsieh 1690b56e90eaSPaul Hsieh dc->links[i]->link_status.link_active = false; 169107920450SJoshua Aberback memset(&dc->links[i]->cur_link_settings, 0, 169207920450SJoshua Aberback sizeof(dc->links[i]->cur_link_settings)); 16934562236bSHarry Wentland } 16944562236bSHarry Wentland } 16954562236bSHarry Wentland 1696fb3466a4SBhawanpreet Lakha static void power_down_controllers(struct dc *dc) 16974562236bSHarry Wentland { 16984562236bSHarry Wentland int i; 16994562236bSHarry Wentland 17007f93c1deSCharlene Liu for (i = 0; i < dc->res_pool->timing_generator_count; i++) { 17014562236bSHarry Wentland dc->res_pool->timing_generators[i]->funcs->disable_crtc( 17024562236bSHarry Wentland dc->res_pool->timing_generators[i]); 17034562236bSHarry Wentland } 17044562236bSHarry Wentland } 17054562236bSHarry Wentland 1706fb3466a4SBhawanpreet Lakha static void power_down_clock_sources(struct dc *dc) 17074562236bSHarry Wentland { 17084562236bSHarry Wentland int i; 17094562236bSHarry Wentland 17104562236bSHarry Wentland if (dc->res_pool->dp_clock_source->funcs->cs_power_down( 17114562236bSHarry Wentland dc->res_pool->dp_clock_source) == false) 17124562236bSHarry Wentland dm_error("Failed to power down pll! (dp clk src)\n"); 17134562236bSHarry Wentland 17144562236bSHarry Wentland for (i = 0; i < dc->res_pool->clk_src_count; i++) { 17154562236bSHarry Wentland if (dc->res_pool->clock_sources[i]->funcs->cs_power_down( 17164562236bSHarry Wentland dc->res_pool->clock_sources[i]) == false) 17174562236bSHarry Wentland dm_error("Failed to power down pll! (clk src index=%d)\n", i); 17184562236bSHarry Wentland } 17194562236bSHarry Wentland } 17204562236bSHarry Wentland 1721fb3466a4SBhawanpreet Lakha static void power_down_all_hw_blocks(struct dc *dc) 17224562236bSHarry Wentland { 17234562236bSHarry Wentland power_down_encoders(dc); 17244562236bSHarry Wentland 17254562236bSHarry Wentland power_down_controllers(dc); 17264562236bSHarry Wentland 17274562236bSHarry Wentland power_down_clock_sources(dc); 17281663ae1cSBhawanpreet Lakha 17292f3bfb27SRoman Li if (dc->fbc_compressor) 17301663ae1cSBhawanpreet Lakha dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); 17314562236bSHarry Wentland } 17324562236bSHarry Wentland 17334562236bSHarry Wentland static void disable_vga_and_power_gate_all_controllers( 1734fb3466a4SBhawanpreet Lakha struct dc *dc) 17354562236bSHarry Wentland { 17364562236bSHarry Wentland int i; 17374562236bSHarry Wentland struct timing_generator *tg; 17384562236bSHarry Wentland struct dc_context *ctx = dc->ctx; 17394562236bSHarry Wentland 17407f93c1deSCharlene Liu for (i = 0; i < dc->res_pool->timing_generator_count; i++) { 17414562236bSHarry Wentland tg = dc->res_pool->timing_generators[i]; 17424562236bSHarry Wentland 17430a87425aSTony Cheng if (tg->funcs->disable_vga) 17444562236bSHarry Wentland tg->funcs->disable_vga(tg); 17457f93c1deSCharlene Liu } 17467f93c1deSCharlene Liu for (i = 0; i < dc->res_pool->pipe_count; i++) { 17474562236bSHarry Wentland /* Enable CLOCK gating for each pipe BEFORE controller 17484562236bSHarry Wentland * powergating. */ 17494562236bSHarry Wentland enable_display_pipe_clock_gating(ctx, 17504562236bSHarry Wentland true); 17514562236bSHarry Wentland 1752e6c258cbSYongqiang Sun dc->current_state->res_ctx.pipe_ctx[i].pipe_idx = i; 17537f914a62SYongqiang Sun dc->hwss.disable_plane(dc, 1754e6c258cbSYongqiang Sun &dc->current_state->res_ctx.pipe_ctx[i]); 17554562236bSHarry Wentland } 17564562236bSHarry Wentland } 17574562236bSHarry Wentland 17583de5aa81SSivapiriyanKumarasamy 175945a1261bSJake Wang static void get_edp_streams(struct dc_state *context, 176045a1261bSJake Wang struct dc_stream_state **edp_streams, 176145a1261bSJake Wang int *edp_stream_num) 17623de5aa81SSivapiriyanKumarasamy { 17633de5aa81SSivapiriyanKumarasamy int i; 17643de5aa81SSivapiriyanKumarasamy 176545a1261bSJake Wang *edp_stream_num = 0; 17663de5aa81SSivapiriyanKumarasamy for (i = 0; i < context->stream_count; i++) { 176745a1261bSJake Wang if (context->streams[i]->signal == SIGNAL_TYPE_EDP) { 176845a1261bSJake Wang edp_streams[*edp_stream_num] = context->streams[i]; 176945a1261bSJake Wang if (++(*edp_stream_num) == MAX_NUM_EDP) 177045a1261bSJake Wang return; 17713de5aa81SSivapiriyanKumarasamy } 177245a1261bSJake Wang } 17733de5aa81SSivapiriyanKumarasamy } 17743de5aa81SSivapiriyanKumarasamy 177545a1261bSJake Wang static void get_edp_links_with_sink( 177625292028SYongqiang Sun struct dc *dc, 177745a1261bSJake Wang struct dc_link **edp_links_with_sink, 177845a1261bSJake Wang int *edp_with_sink_num) 177925292028SYongqiang Sun { 178025292028SYongqiang Sun int i; 178125292028SYongqiang Sun 178225292028SYongqiang Sun /* check if there is an eDP panel not in use */ 178345a1261bSJake Wang *edp_with_sink_num = 0; 178425292028SYongqiang Sun for (i = 0; i < dc->link_count; i++) { 178525292028SYongqiang Sun if (dc->links[i]->local_sink && 178625292028SYongqiang Sun dc->links[i]->local_sink->sink_signal == SIGNAL_TYPE_EDP) { 178745a1261bSJake Wang edp_links_with_sink[*edp_with_sink_num] = dc->links[i]; 178845a1261bSJake Wang if (++(*edp_with_sink_num) == MAX_NUM_EDP) 178945a1261bSJake Wang return; 179025292028SYongqiang Sun } 179125292028SYongqiang Sun } 179225292028SYongqiang Sun } 179325292028SYongqiang Sun 17941c17952eSLee Jones /* 17954562236bSHarry Wentland * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need: 17964562236bSHarry Wentland * 1. Power down all DC HW blocks 17974562236bSHarry Wentland * 2. Disable VGA engine on all controllers 17984562236bSHarry Wentland * 3. Enable power gating for controller 17994562236bSHarry Wentland * 4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS) 18004562236bSHarry Wentland */ 180125292028SYongqiang Sun void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) 18024562236bSHarry Wentland { 180345a1261bSJake Wang struct dc_link *edp_links_with_sink[MAX_NUM_EDP]; 180445a1261bSJake Wang struct dc_link *edp_links[MAX_NUM_EDP]; 180545a1261bSJake Wang struct dc_stream_state *edp_streams[MAX_NUM_EDP]; 180645a1261bSJake Wang struct dc_link *edp_link_with_sink = NULL; 180745a1261bSJake Wang struct dc_link *edp_link = NULL; 18083de5aa81SSivapiriyanKumarasamy struct dc_stream_state *edp_stream = NULL; 180945a1261bSJake Wang struct dce_hwseq *hws = dc->hwseq; 181045a1261bSJake Wang int edp_with_sink_num; 181145a1261bSJake Wang int edp_num; 181245a1261bSJake Wang int edp_stream_num; 181345a1261bSJake Wang int i; 1814be4b289fSSivapiriyanKumarasamy bool can_apply_edp_fast_boot = false; 1815ce72741bSAnthony Koo bool can_apply_seamless_boot = false; 18163de5aa81SSivapiriyanKumarasamy bool keep_edp_vdd_on = false; 18170eda55caSMichael Strauss DC_LOGGER_INIT(); 18180eda55caSMichael Strauss 181945a1261bSJake Wang 182045a1261bSJake Wang get_edp_links_with_sink(dc, edp_links_with_sink, &edp_with_sink_num); 182145a1261bSJake Wang get_edp_links(dc, edp_links, &edp_num); 1822ce72741bSAnthony Koo 1823f42ea55bSAnthony Koo if (hws->funcs.init_pipes) 1824f42ea55bSAnthony Koo hws->funcs.init_pipes(dc, context); 1825be4b289fSSivapiriyanKumarasamy 182645a1261bSJake Wang get_edp_streams(context, edp_streams, &edp_stream_num); 18273de5aa81SSivapiriyanKumarasamy 1828be4b289fSSivapiriyanKumarasamy // Check fastboot support, disable on DCE8 because of blank screens 182945a1261bSJake Wang if (edp_num && dc->ctx->dce_version != DCE_VERSION_8_0 && 1830be4b289fSSivapiriyanKumarasamy dc->ctx->dce_version != DCE_VERSION_8_1 && 1831be4b289fSSivapiriyanKumarasamy dc->ctx->dce_version != DCE_VERSION_8_3) { 183245a1261bSJake Wang for (i = 0; i < edp_num; i++) { 183345a1261bSJake Wang edp_link = edp_links[i]; 1834be4b289fSSivapiriyanKumarasamy // enable fastboot if backend is enabled on eDP 1835be4b289fSSivapiriyanKumarasamy if (edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc)) { 18363de5aa81SSivapiriyanKumarasamy /* Set optimization flag on eDP stream*/ 183745a1261bSJake Wang if (edp_stream_num && edp_link->link_status.link_active) { 183845a1261bSJake Wang edp_stream = edp_streams[0]; 1839f9fc6f39SMichael Strauss can_apply_edp_fast_boot = !is_edp_ilr_optimization_required(edp_stream->link, &edp_stream->timing); 1840f9fc6f39SMichael Strauss edp_stream->apply_edp_fast_boot_optimization = can_apply_edp_fast_boot; 18410eda55caSMichael Strauss if (can_apply_edp_fast_boot) 18420eda55caSMichael Strauss DC_LOG_EVENT_LINK_TRAINING("eDP fast boot disabled to optimize link rate\n"); 1843f9fc6f39SMichael Strauss 184445a1261bSJake Wang break; 1845be4b289fSSivapiriyanKumarasamy } 1846be4b289fSSivapiriyanKumarasamy } 184745a1261bSJake Wang } 18483de5aa81SSivapiriyanKumarasamy // We are trying to enable eDP, don't power down VDD 184945a1261bSJake Wang if (edp_stream_num) 18503de5aa81SSivapiriyanKumarasamy keep_edp_vdd_on = true; 1851be4b289fSSivapiriyanKumarasamy } 1852be4b289fSSivapiriyanKumarasamy 1853be4b289fSSivapiriyanKumarasamy // Check seamless boot support 1854ce72741bSAnthony Koo for (i = 0; i < context->stream_count; i++) { 1855ce72741bSAnthony Koo if (context->streams[i]->apply_seamless_boot_optimization) { 1856ce72741bSAnthony Koo can_apply_seamless_boot = true; 1857ce72741bSAnthony Koo break; 1858ce72741bSAnthony Koo } 1859ce72741bSAnthony Koo } 18604cac1e6dSYongqiang Sun 1861be4b289fSSivapiriyanKumarasamy /* eDP should not have stream in resume from S4 and so even with VBios post 1862be4b289fSSivapiriyanKumarasamy * it should get turned off 18632c37e49aSYongqiang Sun */ 186445a1261bSJake Wang if (edp_with_sink_num) 186545a1261bSJake Wang edp_link_with_sink = edp_links_with_sink[0]; 186645a1261bSJake Wang 1867be4b289fSSivapiriyanKumarasamy if (!can_apply_edp_fast_boot && !can_apply_seamless_boot) { 18683de5aa81SSivapiriyanKumarasamy if (edp_link_with_sink && !keep_edp_vdd_on) { 18694cac1e6dSYongqiang Sun /*turn off backlight before DP_blank and encoder powered down*/ 1870f42ea55bSAnthony Koo hws->funcs.edp_backlight_control(edp_link_with_sink, false); 1871c5fc7f59SCharlene Liu } 1872c5fc7f59SCharlene Liu /*resume from S3, no vbios posting, no need to power down again*/ 187325292028SYongqiang Sun power_down_all_hw_blocks(dc); 18744562236bSHarry Wentland disable_vga_and_power_gate_all_controllers(dc); 18753de5aa81SSivapiriyanKumarasamy if (edp_link_with_sink && !keep_edp_vdd_on) 1876be4b289fSSivapiriyanKumarasamy dc->hwss.edp_power_control(edp_link_with_sink, false); 1877c5fc7f59SCharlene Liu } 18781c5ea40cSYao Wang1 bios_set_scratch_acc_mode_change(dc->ctx->dc_bios, 1); 18794562236bSHarry Wentland } 18804562236bSHarry Wentland 18814562236bSHarry Wentland static uint32_t compute_pstate_blackout_duration( 18824562236bSHarry Wentland struct bw_fixed blackout_duration, 18830971c40eSHarry Wentland const struct dc_stream_state *stream) 18844562236bSHarry Wentland { 18854562236bSHarry Wentland uint32_t total_dest_line_time_ns; 18864562236bSHarry Wentland uint32_t pstate_blackout_duration_ns; 18874562236bSHarry Wentland 18884562236bSHarry Wentland pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24; 18894562236bSHarry Wentland 18904562236bSHarry Wentland total_dest_line_time_ns = 1000000UL * 1891380604e2SKen Chalmers (stream->timing.h_total * 10) / 1892380604e2SKen Chalmers stream->timing.pix_clk_100hz + 18934562236bSHarry Wentland pstate_blackout_duration_ns; 18944562236bSHarry Wentland 18954562236bSHarry Wentland return total_dest_line_time_ns; 18964562236bSHarry Wentland } 18974562236bSHarry Wentland 1898f774b339SEric Yang static void dce110_set_displaymarks( 1899fb3466a4SBhawanpreet Lakha const struct dc *dc, 1900608ac7bbSJerry Zuo struct dc_state *context) 19014562236bSHarry Wentland { 19024562236bSHarry Wentland uint8_t i, num_pipes; 19034562236bSHarry Wentland unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; 19044562236bSHarry Wentland 19054562236bSHarry Wentland for (i = 0, num_pipes = 0; i < MAX_PIPES; i++) { 19064562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 19074562236bSHarry Wentland uint32_t total_dest_line_time_ns; 19084562236bSHarry Wentland 19094562236bSHarry Wentland if (pipe_ctx->stream == NULL) 19104562236bSHarry Wentland continue; 19114562236bSHarry Wentland 19124562236bSHarry Wentland total_dest_line_time_ns = compute_pstate_blackout_duration( 191377a4ea53SBhawanpreet Lakha dc->bw_vbios->blackout_duration, pipe_ctx->stream); 191486a66c4eSHarry Wentland pipe_ctx->plane_res.mi->funcs->mem_input_program_display_marks( 191586a66c4eSHarry Wentland pipe_ctx->plane_res.mi, 1916813d20dcSAidan Wood context->bw_ctx.bw.dce.nbp_state_change_wm_ns[num_pipes], 1917813d20dcSAidan Wood context->bw_ctx.bw.dce.stutter_exit_wm_ns[num_pipes], 1918813d20dcSAidan Wood context->bw_ctx.bw.dce.stutter_entry_wm_ns[num_pipes], 1919813d20dcSAidan Wood context->bw_ctx.bw.dce.urgent_wm_ns[num_pipes], 19204562236bSHarry Wentland total_dest_line_time_ns); 19214562236bSHarry Wentland if (i == underlay_idx) { 19224562236bSHarry Wentland num_pipes++; 192386a66c4eSHarry Wentland pipe_ctx->plane_res.mi->funcs->mem_input_program_chroma_display_marks( 192486a66c4eSHarry Wentland pipe_ctx->plane_res.mi, 1925813d20dcSAidan Wood context->bw_ctx.bw.dce.nbp_state_change_wm_ns[num_pipes], 1926813d20dcSAidan Wood context->bw_ctx.bw.dce.stutter_exit_wm_ns[num_pipes], 1927813d20dcSAidan Wood context->bw_ctx.bw.dce.urgent_wm_ns[num_pipes], 19284562236bSHarry Wentland total_dest_line_time_ns); 19294562236bSHarry Wentland } 19304562236bSHarry Wentland num_pipes++; 19314562236bSHarry Wentland } 19324562236bSHarry Wentland } 19334562236bSHarry Wentland 1934fab55d61SDmytro Laktyushkin void dce110_set_safe_displaymarks( 1935a2b8659dSTony Cheng struct resource_context *res_ctx, 1936a2b8659dSTony Cheng const struct resource_pool *pool) 19374562236bSHarry Wentland { 19384562236bSHarry Wentland int i; 1939a2b8659dSTony Cheng int underlay_idx = pool->underlay_pipe_index; 19409037d802SDmytro Laktyushkin struct dce_watermarks max_marks = { 19414562236bSHarry Wentland MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK }; 19429037d802SDmytro Laktyushkin struct dce_watermarks nbp_marks = { 19434562236bSHarry Wentland SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK }; 19443722c794SMikita Lipski struct dce_watermarks min_marks = { 0, 0, 0, 0}; 19454562236bSHarry Wentland 19464562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 19478feabd03SYue Hin Lau if (res_ctx->pipe_ctx[i].stream == NULL || res_ctx->pipe_ctx[i].plane_res.mi == NULL) 19484562236bSHarry Wentland continue; 19494562236bSHarry Wentland 195086a66c4eSHarry Wentland res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_display_marks( 195186a66c4eSHarry Wentland res_ctx->pipe_ctx[i].plane_res.mi, 19524562236bSHarry Wentland nbp_marks, 19534562236bSHarry Wentland max_marks, 19543722c794SMikita Lipski min_marks, 19554562236bSHarry Wentland max_marks, 19564562236bSHarry Wentland MAX_WATERMARK); 19578feabd03SYue Hin Lau 19584562236bSHarry Wentland if (i == underlay_idx) 195986a66c4eSHarry Wentland res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_chroma_display_marks( 196086a66c4eSHarry Wentland res_ctx->pipe_ctx[i].plane_res.mi, 19614562236bSHarry Wentland nbp_marks, 19624562236bSHarry Wentland max_marks, 19634562236bSHarry Wentland max_marks, 19644562236bSHarry Wentland MAX_WATERMARK); 19658feabd03SYue Hin Lau 19664562236bSHarry Wentland } 19674562236bSHarry Wentland } 19684562236bSHarry Wentland 19694562236bSHarry Wentland /******************************************************************************* 19704562236bSHarry Wentland * Public functions 19714562236bSHarry Wentland ******************************************************************************/ 19724562236bSHarry Wentland 19734562236bSHarry Wentland static void set_drr(struct pipe_ctx **pipe_ctx, 197449c70eceSAlvin Lee int num_pipes, struct dc_crtc_timing_adjust adjust) 19754562236bSHarry Wentland { 19764562236bSHarry Wentland int i = 0; 19774562236bSHarry Wentland struct drr_params params = {0}; 197898e6436dSAnthony Koo // DRR should set trigger event to monitor surface update event 197998e6436dSAnthony Koo unsigned int event_triggers = 0x80; 19805b5abe95SAnthony Koo // Note DRR trigger events are generated regardless of whether num frames met. 19815b5abe95SAnthony Koo unsigned int num_frames = 2; 19824562236bSHarry Wentland 198349c70eceSAlvin Lee params.vertical_total_max = adjust.v_total_max; 198449c70eceSAlvin Lee params.vertical_total_min = adjust.v_total_min; 19854562236bSHarry Wentland 19864562236bSHarry Wentland /* TODO: If multiple pipes are to be supported, you need 198798e6436dSAnthony Koo * some GSL stuff. Static screen triggers may be programmed differently 198898e6436dSAnthony Koo * as well. 19894562236bSHarry Wentland */ 19904562236bSHarry Wentland for (i = 0; i < num_pipes; i++) { 199198e6436dSAnthony Koo pipe_ctx[i]->stream_res.tg->funcs->set_drr( 199298e6436dSAnthony Koo pipe_ctx[i]->stream_res.tg, ¶ms); 199398e6436dSAnthony Koo 199449c70eceSAlvin Lee if (adjust.v_total_max != 0 && adjust.v_total_min != 0) 199598e6436dSAnthony Koo pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control( 199698e6436dSAnthony Koo pipe_ctx[i]->stream_res.tg, 19975b5abe95SAnthony Koo event_triggers, num_frames); 19984562236bSHarry Wentland } 19994562236bSHarry Wentland } 20004562236bSHarry Wentland 200172ada5f7SEric Cook static void get_position(struct pipe_ctx **pipe_ctx, 200272ada5f7SEric Cook int num_pipes, 200372ada5f7SEric Cook struct crtc_position *position) 200472ada5f7SEric Cook { 200572ada5f7SEric Cook int i = 0; 200672ada5f7SEric Cook 200772ada5f7SEric Cook /* TODO: handle pipes > 1 200872ada5f7SEric Cook */ 200972ada5f7SEric Cook for (i = 0; i < num_pipes; i++) 20106b670fa9SHarry Wentland pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position); 201172ada5f7SEric Cook } 201272ada5f7SEric Cook 20134562236bSHarry Wentland static void set_static_screen_control(struct pipe_ctx **pipe_ctx, 20145b5abe95SAnthony Koo int num_pipes, const struct dc_static_screen_params *params) 20154562236bSHarry Wentland { 20164562236bSHarry Wentland unsigned int i; 20175b5abe95SAnthony Koo unsigned int triggers = 0; 201894267b3dSSylvia Tsai 20195b5abe95SAnthony Koo if (params->triggers.overlay_update) 20205b5abe95SAnthony Koo triggers |= 0x100; 20215b5abe95SAnthony Koo if (params->triggers.surface_update) 20225b5abe95SAnthony Koo triggers |= 0x80; 20235b5abe95SAnthony Koo if (params->triggers.cursor_update) 20245b5abe95SAnthony Koo triggers |= 0x2; 20255b5abe95SAnthony Koo if (params->triggers.force_trigger) 20265b5abe95SAnthony Koo triggers |= 0x1; 20274562236bSHarry Wentland 2028593f79a2SAlex Deucher if (num_pipes) { 2029593f79a2SAlex Deucher struct dc *dc = pipe_ctx[0]->stream->ctx->dc; 2030593f79a2SAlex Deucher 2031593f79a2SAlex Deucher if (dc->fbc_compressor) 20325b5abe95SAnthony Koo triggers |= 0x84; 2033593f79a2SAlex Deucher } 2034c3aa1d67SBhawanpreet Lakha 20354562236bSHarry Wentland for (i = 0; i < num_pipes; i++) 20366b670fa9SHarry Wentland pipe_ctx[i]->stream_res.tg->funcs-> 20375b5abe95SAnthony Koo set_static_screen_control(pipe_ctx[i]->stream_res.tg, 20385b5abe95SAnthony Koo triggers, params->num_frames); 20394562236bSHarry Wentland } 20404562236bSHarry Wentland 2041f6baff4dSHarry Wentland /* 2042690b5e39SRoman Li * Check if FBC can be enabled 2043690b5e39SRoman Li */ 20449c6569deSHarry Wentland static bool should_enable_fbc(struct dc *dc, 20453bc4aaa9SRoman Li struct dc_state *context, 20463bc4aaa9SRoman Li uint32_t *pipe_idx) 2047690b5e39SRoman Li { 20483bc4aaa9SRoman Li uint32_t i; 20493bc4aaa9SRoman Li struct pipe_ctx *pipe_ctx = NULL; 20503bc4aaa9SRoman Li struct resource_context *res_ctx = &context->res_ctx; 205165d38262Shersen wu unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; 20523bc4aaa9SRoman Li 2053690b5e39SRoman Li 2054690b5e39SRoman Li ASSERT(dc->fbc_compressor); 2055690b5e39SRoman Li 2056690b5e39SRoman Li /* FBC memory should be allocated */ 2057690b5e39SRoman Li if (!dc->ctx->fbc_gpu_addr) 20589c6569deSHarry Wentland return false; 2059690b5e39SRoman Li 2060690b5e39SRoman Li /* Only supports single display */ 2061690b5e39SRoman Li if (context->stream_count != 1) 20629c6569deSHarry Wentland return false; 2063690b5e39SRoman Li 20643bc4aaa9SRoman Li for (i = 0; i < dc->res_pool->pipe_count; i++) { 20653bc4aaa9SRoman Li if (res_ctx->pipe_ctx[i].stream) { 206665d38262Shersen wu 20673bc4aaa9SRoman Li pipe_ctx = &res_ctx->pipe_ctx[i]; 206865d38262Shersen wu 206965d38262Shersen wu if (!pipe_ctx) 207065d38262Shersen wu continue; 207165d38262Shersen wu 207265d38262Shersen wu /* fbc not applicable on underlay pipe */ 207365d38262Shersen wu if (pipe_ctx->pipe_idx != underlay_idx) { 20743bc4aaa9SRoman Li *pipe_idx = i; 20753bc4aaa9SRoman Li break; 20763bc4aaa9SRoman Li } 20773bc4aaa9SRoman Li } 207865d38262Shersen wu } 20793bc4aaa9SRoman Li 208065d38262Shersen wu if (i == dc->res_pool->pipe_count) 208165d38262Shersen wu return false; 208265d38262Shersen wu 2083ceb3dbb4SJun Lei if (!pipe_ctx->stream->link) 208465d38262Shersen wu return false; 20857a840773SRoman Li 2086690b5e39SRoman Li /* Only supports eDP */ 2087ceb3dbb4SJun Lei if (pipe_ctx->stream->link->connector_signal != SIGNAL_TYPE_EDP) 20889c6569deSHarry Wentland return false; 2089690b5e39SRoman Li 2090690b5e39SRoman Li /* PSR should not be enabled */ 2091d1ebfdd8SWyatt Wood if (pipe_ctx->stream->link->psr_settings.psr_feature_enabled) 20929c6569deSHarry Wentland return false; 2093690b5e39SRoman Li 209493984bbcSShirish S /* Nothing to compress */ 209593984bbcSShirish S if (!pipe_ctx->plane_state) 20969c6569deSHarry Wentland return false; 209793984bbcSShirish S 209805230fa9SRoman Li /* Only for non-linear tiling */ 209905230fa9SRoman Li if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) 21009c6569deSHarry Wentland return false; 210105230fa9SRoman Li 21029c6569deSHarry Wentland return true; 2103690b5e39SRoman Li } 2104690b5e39SRoman Li 2105690b5e39SRoman Li /* 2106690b5e39SRoman Li * Enable FBC 2107690b5e39SRoman Li */ 210865d38262Shersen wu static void enable_fbc( 210965d38262Shersen wu struct dc *dc, 2110608ac7bbSJerry Zuo struct dc_state *context) 2111690b5e39SRoman Li { 21123bc4aaa9SRoman Li uint32_t pipe_idx = 0; 21133bc4aaa9SRoman Li 21143bc4aaa9SRoman Li if (should_enable_fbc(dc, context, &pipe_idx)) { 2115690b5e39SRoman Li /* Program GRPH COMPRESSED ADDRESS and PITCH */ 2116690b5e39SRoman Li struct compr_addr_and_pitch_params params = {0, 0, 0}; 2117690b5e39SRoman Li struct compressor *compr = dc->fbc_compressor; 21183bc4aaa9SRoman Li struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; 21193bc4aaa9SRoman Li 21209c6569deSHarry Wentland params.source_view_width = pipe_ctx->stream->timing.h_addressable; 21219c6569deSHarry Wentland params.source_view_height = pipe_ctx->stream->timing.v_addressable; 212265d38262Shersen wu params.inst = pipe_ctx->stream_res.tg->inst; 2123690b5e39SRoman Li compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr; 2124690b5e39SRoman Li 2125690b5e39SRoman Li compr->funcs->surface_address_and_pitch(compr, ¶ms); 2126690b5e39SRoman Li compr->funcs->set_fbc_invalidation_triggers(compr, 1); 2127690b5e39SRoman Li 2128690b5e39SRoman Li compr->funcs->enable_fbc(compr, ¶ms); 2129690b5e39SRoman Li } 2130690b5e39SRoman Li } 2131690b5e39SRoman Li 213254e8695eSDmytro Laktyushkin static void dce110_reset_hw_ctx_wrap( 2133fb3466a4SBhawanpreet Lakha struct dc *dc, 2134608ac7bbSJerry Zuo struct dc_state *context) 21354562236bSHarry Wentland { 21364562236bSHarry Wentland int i; 21374562236bSHarry Wentland 21384562236bSHarry Wentland /* Reset old context */ 21394562236bSHarry Wentland /* look up the targets that have been removed since last commit */ 2140a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 21414562236bSHarry Wentland struct pipe_ctx *pipe_ctx_old = 2142608ac7bbSJerry Zuo &dc->current_state->res_ctx.pipe_ctx[i]; 21434562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 21444562236bSHarry Wentland 21454562236bSHarry Wentland /* Note: We need to disable output if clock sources change, 21464562236bSHarry Wentland * since bios does optimization and doesn't apply if changing 21474562236bSHarry Wentland * PHY when not already disabled. 21484562236bSHarry Wentland */ 21494562236bSHarry Wentland 21504562236bSHarry Wentland /* Skip underlay pipe since it will be handled in commit surface*/ 21514562236bSHarry Wentland if (!pipe_ctx_old->stream || pipe_ctx_old->top_pipe) 21524562236bSHarry Wentland continue; 21534562236bSHarry Wentland 21544562236bSHarry Wentland if (!pipe_ctx->stream || 215554e8695eSDmytro Laktyushkin pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { 215621e67d4dSHarry Wentland struct clock_source *old_clk = pipe_ctx_old->clock_source; 215721e67d4dSHarry Wentland 2158827f11e9SLeo (Sunpeng) Li /* Disable if new stream is null. O/w, if stream is 2159827f11e9SLeo (Sunpeng) Li * disabled already, no need to disable again. 2160827f11e9SLeo (Sunpeng) Li */ 216157430404SSu Sung Chung if (!pipe_ctx->stream || !pipe_ctx->stream->dpms_off) { 216257430404SSu Sung Chung core_link_disable_stream(pipe_ctx_old); 216357430404SSu Sung Chung 216457430404SSu Sung Chung /* free acquired resources*/ 216557430404SSu Sung Chung if (pipe_ctx_old->stream_res.audio) { 216657430404SSu Sung Chung /*disable az_endpoint*/ 216757430404SSu Sung Chung pipe_ctx_old->stream_res.audio->funcs-> 216857430404SSu Sung Chung az_disable(pipe_ctx_old->stream_res.audio); 216957430404SSu Sung Chung 217057430404SSu Sung Chung /*free audio*/ 217157430404SSu Sung Chung if (dc->caps.dynamic_audio == true) { 217257430404SSu Sung Chung /*we have to dynamic arbitrate the audio endpoints*/ 217357430404SSu Sung Chung /*we free the resource, need reset is_audio_acquired*/ 217457430404SSu Sung Chung update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, 217557430404SSu Sung Chung pipe_ctx_old->stream_res.audio, false); 217657430404SSu Sung Chung pipe_ctx_old->stream_res.audio = NULL; 217757430404SSu Sung Chung } 217857430404SSu Sung Chung } 217957430404SSu Sung Chung } 2180d050f8edSHersen Wu 21816b670fa9SHarry Wentland pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true); 21826b670fa9SHarry Wentland if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) { 218354e8695eSDmytro Laktyushkin dm_error("DC: failed to blank crtc!\n"); 218454e8695eSDmytro Laktyushkin BREAK_TO_DEBUGGER(); 218554e8695eSDmytro Laktyushkin } 21866b670fa9SHarry Wentland pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg); 218786a66c4eSHarry Wentland pipe_ctx_old->plane_res.mi->funcs->free_mem_input( 2188608ac7bbSJerry Zuo pipe_ctx_old->plane_res.mi, dc->current_state->stream_count); 218954e8695eSDmytro Laktyushkin 2190ad8960a6SMikita Lipski if (old_clk && 0 == resource_get_clock_source_reference(&context->res_ctx, 2191ad8960a6SMikita Lipski dc->res_pool, 2192ad8960a6SMikita Lipski old_clk)) 219321e67d4dSHarry Wentland old_clk->funcs->cs_power_down(old_clk); 219421e67d4dSHarry Wentland 21957f914a62SYongqiang Sun dc->hwss.disable_plane(dc, pipe_ctx_old); 219654e8695eSDmytro Laktyushkin 219754e8695eSDmytro Laktyushkin pipe_ctx_old->stream = NULL; 219854e8695eSDmytro Laktyushkin } 21994562236bSHarry Wentland } 22004562236bSHarry Wentland } 22014562236bSHarry Wentland 22021a05873fSAnthony Koo static void dce110_setup_audio_dto( 22031a05873fSAnthony Koo struct dc *dc, 22041a05873fSAnthony Koo struct dc_state *context) 22051a05873fSAnthony Koo { 22061a05873fSAnthony Koo int i; 22071a05873fSAnthony Koo 22081a05873fSAnthony Koo /* program audio wall clock. use HDMI as clock source if HDMI 22091a05873fSAnthony Koo * audio active. Otherwise, use DP as clock source 22101a05873fSAnthony Koo * first, loop to find any HDMI audio, if not, loop find DP audio 22111a05873fSAnthony Koo */ 22121a05873fSAnthony Koo /* Setup audio rate clock source */ 22131a05873fSAnthony Koo /* Issue: 22141a05873fSAnthony Koo * Audio lag happened on DP monitor when unplug a HDMI monitor 22151a05873fSAnthony Koo * 22161a05873fSAnthony Koo * Cause: 22171a05873fSAnthony Koo * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL 22181a05873fSAnthony Koo * is set to either dto0 or dto1, audio should work fine. 22191a05873fSAnthony Koo * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1, 22201a05873fSAnthony Koo * set to dto0 will cause audio lag. 22211a05873fSAnthony Koo * 22221a05873fSAnthony Koo * Solution: 22231a05873fSAnthony Koo * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx, 22241a05873fSAnthony Koo * find first available pipe with audio, setup audio wall DTO per topology 22251a05873fSAnthony Koo * instead of per pipe. 22261a05873fSAnthony Koo */ 22271a05873fSAnthony Koo for (i = 0; i < dc->res_pool->pipe_count; i++) { 22281a05873fSAnthony Koo struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 22291a05873fSAnthony Koo 22301a05873fSAnthony Koo if (pipe_ctx->stream == NULL) 22311a05873fSAnthony Koo continue; 22321a05873fSAnthony Koo 22331a05873fSAnthony Koo if (pipe_ctx->top_pipe) 22341a05873fSAnthony Koo continue; 22351a05873fSAnthony Koo if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) 22361a05873fSAnthony Koo continue; 22371a05873fSAnthony Koo if (pipe_ctx->stream_res.audio != NULL) { 22381a05873fSAnthony Koo struct audio_output audio_output; 22391a05873fSAnthony Koo 22401a05873fSAnthony Koo build_audio_output(context, pipe_ctx, &audio_output); 22411a05873fSAnthony Koo 22428fe44c08SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN) 224364b1d0e8SNicholas Kazlauskas /* For DCN3.1, audio to HPO FRL encoder is using audio DTBCLK DTO */ 224464b1d0e8SNicholas Kazlauskas if (dc->res_pool->dccg && dc->res_pool->dccg->funcs->set_audio_dtbclk_dto) { 224564b1d0e8SNicholas Kazlauskas /* disable audio DTBCLK DTO */ 224664b1d0e8SNicholas Kazlauskas dc->res_pool->dccg->funcs->set_audio_dtbclk_dto( 224764b1d0e8SNicholas Kazlauskas dc->res_pool->dccg, 0); 224864b1d0e8SNicholas Kazlauskas 22491a05873fSAnthony Koo pipe_ctx->stream_res.audio->funcs->wall_dto_setup( 22501a05873fSAnthony Koo pipe_ctx->stream_res.audio, 22511a05873fSAnthony Koo pipe_ctx->stream->signal, 22521a05873fSAnthony Koo &audio_output.crtc_info, 22531a05873fSAnthony Koo &audio_output.pll_info); 225464b1d0e8SNicholas Kazlauskas } else 225564b1d0e8SNicholas Kazlauskas pipe_ctx->stream_res.audio->funcs->wall_dto_setup( 225664b1d0e8SNicholas Kazlauskas pipe_ctx->stream_res.audio, 225764b1d0e8SNicholas Kazlauskas pipe_ctx->stream->signal, 225864b1d0e8SNicholas Kazlauskas &audio_output.crtc_info, 225964b1d0e8SNicholas Kazlauskas &audio_output.pll_info); 226064b1d0e8SNicholas Kazlauskas #else 226164b1d0e8SNicholas Kazlauskas pipe_ctx->stream_res.audio->funcs->wall_dto_setup( 226264b1d0e8SNicholas Kazlauskas pipe_ctx->stream_res.audio, 226364b1d0e8SNicholas Kazlauskas pipe_ctx->stream->signal, 226464b1d0e8SNicholas Kazlauskas &audio_output.crtc_info, 226564b1d0e8SNicholas Kazlauskas &audio_output.pll_info); 226664b1d0e8SNicholas Kazlauskas #endif 22671a05873fSAnthony Koo break; 22681a05873fSAnthony Koo } 22691a05873fSAnthony Koo } 22701a05873fSAnthony Koo 22711a05873fSAnthony Koo /* no HDMI audio is found, try DP audio */ 22721a05873fSAnthony Koo if (i == dc->res_pool->pipe_count) { 22731a05873fSAnthony Koo for (i = 0; i < dc->res_pool->pipe_count; i++) { 22741a05873fSAnthony Koo struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 22751a05873fSAnthony Koo 22761a05873fSAnthony Koo if (pipe_ctx->stream == NULL) 22771a05873fSAnthony Koo continue; 22781a05873fSAnthony Koo 22791a05873fSAnthony Koo if (pipe_ctx->top_pipe) 22801a05873fSAnthony Koo continue; 22811a05873fSAnthony Koo 22821a05873fSAnthony Koo if (!dc_is_dp_signal(pipe_ctx->stream->signal)) 22831a05873fSAnthony Koo continue; 22841a05873fSAnthony Koo 22851a05873fSAnthony Koo if (pipe_ctx->stream_res.audio != NULL) { 22861a05873fSAnthony Koo struct audio_output audio_output; 22871a05873fSAnthony Koo 22881a05873fSAnthony Koo build_audio_output(context, pipe_ctx, &audio_output); 22891a05873fSAnthony Koo 22901a05873fSAnthony Koo pipe_ctx->stream_res.audio->funcs->wall_dto_setup( 22911a05873fSAnthony Koo pipe_ctx->stream_res.audio, 22921a05873fSAnthony Koo pipe_ctx->stream->signal, 22931a05873fSAnthony Koo &audio_output.crtc_info, 22941a05873fSAnthony Koo &audio_output.pll_info); 22951a05873fSAnthony Koo break; 22961a05873fSAnthony Koo } 22971a05873fSAnthony Koo } 22981a05873fSAnthony Koo } 22991a05873fSAnthony Koo } 2300cf437593SDmytro Laktyushkin 23014562236bSHarry Wentland enum dc_status dce110_apply_ctx_to_hw( 2302fb3466a4SBhawanpreet Lakha struct dc *dc, 2303608ac7bbSJerry Zuo struct dc_state *context) 23044562236bSHarry Wentland { 2305f42ea55bSAnthony Koo struct dce_hwseq *hws = dc->hwseq; 23064562236bSHarry Wentland struct dc_bios *dcb = dc->ctx->dc_bios; 23074562236bSHarry Wentland enum dc_status status; 23084562236bSHarry Wentland int i; 23094562236bSHarry Wentland 23104562236bSHarry Wentland /* Reset old context */ 23114562236bSHarry Wentland /* look up the targets that have been removed since last commit */ 2312f42ea55bSAnthony Koo hws->funcs.reset_hw_ctx_wrap(dc, context); 23134562236bSHarry Wentland 23144562236bSHarry Wentland /* Skip applying if no targets */ 2315ab2541b6SAric Cyr if (context->stream_count <= 0) 23164562236bSHarry Wentland return DC_OK; 23174562236bSHarry Wentland 23184562236bSHarry Wentland /* Apply new context */ 23194562236bSHarry Wentland dcb->funcs->set_scratch_critical_state(dcb, true); 23204562236bSHarry Wentland 23214562236bSHarry Wentland /* below is for real asic only */ 2322a2b8659dSTony Cheng for (i = 0; i < dc->res_pool->pipe_count; i++) { 23234562236bSHarry Wentland struct pipe_ctx *pipe_ctx_old = 2324608ac7bbSJerry Zuo &dc->current_state->res_ctx.pipe_ctx[i]; 23254562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 23264562236bSHarry Wentland 23274562236bSHarry Wentland if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe) 23284562236bSHarry Wentland continue; 23294562236bSHarry Wentland 23304562236bSHarry Wentland if (pipe_ctx->stream == pipe_ctx_old->stream) { 23314562236bSHarry Wentland if (pipe_ctx_old->clock_source != pipe_ctx->clock_source) 23324562236bSHarry Wentland dce_crtc_switch_to_clk_src(dc->hwseq, 23334562236bSHarry Wentland pipe_ctx->clock_source, i); 23344562236bSHarry Wentland continue; 23354562236bSHarry Wentland } 23364562236bSHarry Wentland 2337f42ea55bSAnthony Koo hws->funcs.enable_display_power_gating( 23384562236bSHarry Wentland dc, i, dc->ctx->dc_bios, 23394562236bSHarry Wentland PIPE_GATING_CONTROL_DISABLE); 23404562236bSHarry Wentland } 23414562236bSHarry Wentland 23422f3bfb27SRoman Li if (dc->fbc_compressor) 23431663ae1cSBhawanpreet Lakha dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); 23445099114bSAlex Deucher 23451a05873fSAnthony Koo dce110_setup_audio_dto(dc, context); 2346ab8812a3SHersen Wu 2347a2b8659dSTony Cheng for (i = 0; i < dc->res_pool->pipe_count; i++) { 2348ab8812a3SHersen Wu struct pipe_ctx *pipe_ctx_old = 2349608ac7bbSJerry Zuo &dc->current_state->res_ctx.pipe_ctx[i]; 2350ab8812a3SHersen Wu struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 2351ab8812a3SHersen Wu 2352ab8812a3SHersen Wu if (pipe_ctx->stream == NULL) 2353ab8812a3SHersen Wu continue; 2354ab8812a3SHersen Wu 2355eed928dcSCharlene Liu if (pipe_ctx->stream == pipe_ctx_old->stream && 2356eed928dcSCharlene Liu pipe_ctx->stream->link->link_state_valid) { 2357ab8812a3SHersen Wu continue; 2358eed928dcSCharlene Liu } 2359ab8812a3SHersen Wu 23605b92d9d4SHarry Wentland if (pipe_ctx_old->stream && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) 2361313bf4ffSYongqiang Sun continue; 2362313bf4ffSYongqiang Sun 2363b1f6d01cSDmytro Laktyushkin if (pipe_ctx->top_pipe || pipe_ctx->prev_odm_pipe) 2364ab8812a3SHersen Wu continue; 2365ab8812a3SHersen Wu 23664562236bSHarry Wentland status = apply_single_controller_ctx_to_hw( 23674562236bSHarry Wentland pipe_ctx, 23684562236bSHarry Wentland context, 23694562236bSHarry Wentland dc); 23704562236bSHarry Wentland 23714562236bSHarry Wentland if (DC_OK != status) 23724562236bSHarry Wentland return status; 23734562236bSHarry Wentland } 23744562236bSHarry Wentland 2375690b5e39SRoman Li if (dc->fbc_compressor) 237665d38262Shersen wu enable_fbc(dc, dc->current_state); 237765d38262Shersen wu 237865d38262Shersen wu dcb->funcs->set_scratch_critical_state(dcb, false); 2379690b5e39SRoman Li 23804562236bSHarry Wentland return DC_OK; 23814562236bSHarry Wentland } 23824562236bSHarry Wentland 23834562236bSHarry Wentland /******************************************************************************* 23844562236bSHarry Wentland * Front End programming 23854562236bSHarry Wentland ******************************************************************************/ 23864562236bSHarry Wentland static void set_default_colors(struct pipe_ctx *pipe_ctx) 23874562236bSHarry Wentland { 23884562236bSHarry Wentland struct default_adjustment default_adjust = { 0 }; 23894562236bSHarry Wentland 23904562236bSHarry Wentland default_adjust.force_hw_default = false; 239134996173SHarry Wentland default_adjust.in_color_space = pipe_ctx->plane_state->color_space; 239234996173SHarry Wentland default_adjust.out_color_space = pipe_ctx->stream->output_color_space; 23934562236bSHarry Wentland default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW; 23946702a9acSHarry Wentland default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format; 23954562236bSHarry Wentland 23964562236bSHarry Wentland /* display color depth */ 23974562236bSHarry Wentland default_adjust.color_depth = 23984fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->timing.display_color_depth; 23994562236bSHarry Wentland 24004562236bSHarry Wentland /* Lb color depth */ 24016702a9acSHarry Wentland default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth; 24024562236bSHarry Wentland 240386a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default( 240486a66c4eSHarry Wentland pipe_ctx->plane_res.xfm, &default_adjust); 24054562236bSHarry Wentland } 24064562236bSHarry Wentland 2407b06b7680SLeon Elazar 2408b06b7680SLeon Elazar /******************************************************************************* 2409b06b7680SLeon Elazar * In order to turn on/off specific surface we will program 2410b06b7680SLeon Elazar * Blender + CRTC 2411b06b7680SLeon Elazar * 2412b06b7680SLeon Elazar * In case that we have two surfaces and they have a different visibility 2413b06b7680SLeon Elazar * we can't turn off the CRTC since it will turn off the entire display 2414b06b7680SLeon Elazar * 2415b06b7680SLeon Elazar * |----------------------------------------------- | 2416b06b7680SLeon Elazar * |bottom pipe|curr pipe | | | 2417b06b7680SLeon Elazar * |Surface |Surface | Blender | CRCT | 2418b06b7680SLeon Elazar * |visibility |visibility | Configuration| | 2419b06b7680SLeon Elazar * |------------------------------------------------| 2420b06b7680SLeon Elazar * | off | off | CURRENT_PIPE | blank | 2421b06b7680SLeon Elazar * | off | on | CURRENT_PIPE | unblank | 2422b06b7680SLeon Elazar * | on | off | OTHER_PIPE | unblank | 2423b06b7680SLeon Elazar * | on | on | BLENDING | unblank | 2424b06b7680SLeon Elazar * -------------------------------------------------| 2425b06b7680SLeon Elazar * 2426b06b7680SLeon Elazar ******************************************************************************/ 2427fb3466a4SBhawanpreet Lakha static void program_surface_visibility(const struct dc *dc, 24284562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 24294562236bSHarry Wentland { 24304562236bSHarry Wentland enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE; 2431b06b7680SLeon Elazar bool blank_target = false; 24324562236bSHarry Wentland 24334562236bSHarry Wentland if (pipe_ctx->bottom_pipe) { 2434b06b7680SLeon Elazar 2435b06b7680SLeon Elazar /* For now we are supporting only two pipes */ 2436b06b7680SLeon Elazar ASSERT(pipe_ctx->bottom_pipe->bottom_pipe == NULL); 2437b06b7680SLeon Elazar 24383be5262eSHarry Wentland if (pipe_ctx->bottom_pipe->plane_state->visible) { 24393be5262eSHarry Wentland if (pipe_ctx->plane_state->visible) 24404562236bSHarry Wentland blender_mode = BLND_MODE_BLENDING; 24414562236bSHarry Wentland else 24424562236bSHarry Wentland blender_mode = BLND_MODE_OTHER_PIPE; 2443b06b7680SLeon Elazar 24443be5262eSHarry Wentland } else if (!pipe_ctx->plane_state->visible) 2445b06b7680SLeon Elazar blank_target = true; 2446b06b7680SLeon Elazar 24473be5262eSHarry Wentland } else if (!pipe_ctx->plane_state->visible) 2448b06b7680SLeon Elazar blank_target = true; 2449b06b7680SLeon Elazar 2450e07f541fSYongqiang Sun dce_set_blender_mode(dc->hwseq, pipe_ctx->stream_res.tg->inst, blender_mode); 24516b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, blank_target); 2452b06b7680SLeon Elazar 24534562236bSHarry Wentland } 24544562236bSHarry Wentland 24551bf56e62SZeyu Fan static void program_gamut_remap(struct pipe_ctx *pipe_ctx) 24561bf56e62SZeyu Fan { 2457146a9f63SKrunoslav Kovac int i = 0; 24581bf56e62SZeyu Fan struct xfm_grph_csc_adjustment adjust; 24591bf56e62SZeyu Fan memset(&adjust, 0, sizeof(adjust)); 24601bf56e62SZeyu Fan adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; 24611bf56e62SZeyu Fan 24621bf56e62SZeyu Fan 24634fa086b9SLeo (Sunpeng) Li if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { 24641bf56e62SZeyu Fan adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; 2465146a9f63SKrunoslav Kovac 2466146a9f63SKrunoslav Kovac for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++) 2467146a9f63SKrunoslav Kovac adjust.temperature_matrix[i] = 2468146a9f63SKrunoslav Kovac pipe_ctx->stream->gamut_remap_matrix.matrix[i]; 24691bf56e62SZeyu Fan } 24701bf56e62SZeyu Fan 247186a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); 24721bf56e62SZeyu Fan } 2473fb3466a4SBhawanpreet Lakha static void update_plane_addr(const struct dc *dc, 24744562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 24754562236bSHarry Wentland { 24763be5262eSHarry Wentland struct dc_plane_state *plane_state = pipe_ctx->plane_state; 24774562236bSHarry Wentland 24783be5262eSHarry Wentland if (plane_state == NULL) 24794562236bSHarry Wentland return; 24804562236bSHarry Wentland 248186a66c4eSHarry Wentland pipe_ctx->plane_res.mi->funcs->mem_input_program_surface_flip_and_addr( 248286a66c4eSHarry Wentland pipe_ctx->plane_res.mi, 24833be5262eSHarry Wentland &plane_state->address, 24843be5262eSHarry Wentland plane_state->flip_immediate); 24854562236bSHarry Wentland 24863be5262eSHarry Wentland plane_state->status.requested_address = plane_state->address; 24874562236bSHarry Wentland } 24884562236bSHarry Wentland 2489f774b339SEric Yang static void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) 24904562236bSHarry Wentland { 24913be5262eSHarry Wentland struct dc_plane_state *plane_state = pipe_ctx->plane_state; 24924562236bSHarry Wentland 24933be5262eSHarry Wentland if (plane_state == NULL) 24944562236bSHarry Wentland return; 24954562236bSHarry Wentland 24963be5262eSHarry Wentland plane_state->status.is_flip_pending = 249786a66c4eSHarry Wentland pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending( 249886a66c4eSHarry Wentland pipe_ctx->plane_res.mi); 24994562236bSHarry Wentland 25003be5262eSHarry Wentland if (plane_state->status.is_flip_pending && !plane_state->visible) 250186a66c4eSHarry Wentland pipe_ctx->plane_res.mi->current_address = pipe_ctx->plane_res.mi->request_address; 25024562236bSHarry Wentland 250386a66c4eSHarry Wentland plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address; 250486a66c4eSHarry Wentland if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && 25056b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye) { 25063be5262eSHarry Wentland plane_state->status.is_right_eye =\ 25076b670fa9SHarry Wentland !pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg); 25087f5c22d1SVitaly Prosyak } 25094562236bSHarry Wentland } 25104562236bSHarry Wentland 2511fb3466a4SBhawanpreet Lakha void dce110_power_down(struct dc *dc) 25124562236bSHarry Wentland { 25134562236bSHarry Wentland power_down_all_hw_blocks(dc); 25144562236bSHarry Wentland disable_vga_and_power_gate_all_controllers(dc); 25154562236bSHarry Wentland } 25164562236bSHarry Wentland 25174562236bSHarry Wentland static bool wait_for_reset_trigger_to_occur( 25184562236bSHarry Wentland struct dc_context *dc_ctx, 25194562236bSHarry Wentland struct timing_generator *tg) 25204562236bSHarry Wentland { 25214562236bSHarry Wentland bool rc = false; 25224562236bSHarry Wentland 25234562236bSHarry Wentland /* To avoid endless loop we wait at most 25244562236bSHarry Wentland * frames_to_wait_on_triggered_reset frames for the reset to occur. */ 25254562236bSHarry Wentland const uint32_t frames_to_wait_on_triggered_reset = 10; 25264562236bSHarry Wentland uint32_t i; 25274562236bSHarry Wentland 25284562236bSHarry Wentland for (i = 0; i < frames_to_wait_on_triggered_reset; i++) { 25294562236bSHarry Wentland 25304562236bSHarry Wentland if (!tg->funcs->is_counter_moving(tg)) { 25314562236bSHarry Wentland DC_ERROR("TG counter is not moving!\n"); 25324562236bSHarry Wentland break; 25334562236bSHarry Wentland } 25344562236bSHarry Wentland 25354562236bSHarry Wentland if (tg->funcs->did_triggered_reset_occur(tg)) { 25364562236bSHarry Wentland rc = true; 25374562236bSHarry Wentland /* usually occurs at i=1 */ 25384562236bSHarry Wentland DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n", 25394562236bSHarry Wentland i); 25404562236bSHarry Wentland break; 25414562236bSHarry Wentland } 25424562236bSHarry Wentland 25434562236bSHarry Wentland /* Wait for one frame. */ 25444562236bSHarry Wentland tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE); 25454562236bSHarry Wentland tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK); 25464562236bSHarry Wentland } 25474562236bSHarry Wentland 25484562236bSHarry Wentland if (false == rc) 25494562236bSHarry Wentland DC_ERROR("GSL: Timeout on reset trigger!\n"); 25504562236bSHarry Wentland 25514562236bSHarry Wentland return rc; 25524562236bSHarry Wentland } 25534562236bSHarry Wentland 25544562236bSHarry Wentland /* Enable timing synchronization for a group of Timing Generators. */ 25554562236bSHarry Wentland static void dce110_enable_timing_synchronization( 2556fb3466a4SBhawanpreet Lakha struct dc *dc, 25574562236bSHarry Wentland int group_index, 25584562236bSHarry Wentland int group_size, 25594562236bSHarry Wentland struct pipe_ctx *grouped_pipes[]) 25604562236bSHarry Wentland { 25614562236bSHarry Wentland struct dc_context *dc_ctx = dc->ctx; 25624562236bSHarry Wentland struct dcp_gsl_params gsl_params = { 0 }; 25634562236bSHarry Wentland int i; 25644562236bSHarry Wentland 25654562236bSHarry Wentland DC_SYNC_INFO("GSL: Setting-up...\n"); 25664562236bSHarry Wentland 25674562236bSHarry Wentland /* Designate a single TG in the group as a master. 25684562236bSHarry Wentland * Since HW doesn't care which one, we always assign 25694562236bSHarry Wentland * the 1st one in the group. */ 25704562236bSHarry Wentland gsl_params.gsl_group = 0; 25716b670fa9SHarry Wentland gsl_params.gsl_master = grouped_pipes[0]->stream_res.tg->inst; 25724562236bSHarry Wentland 25734562236bSHarry Wentland for (i = 0; i < group_size; i++) 25746b670fa9SHarry Wentland grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock( 25756b670fa9SHarry Wentland grouped_pipes[i]->stream_res.tg, &gsl_params); 25764562236bSHarry Wentland 25774562236bSHarry Wentland /* Reset slave controllers on master VSync */ 25784562236bSHarry Wentland DC_SYNC_INFO("GSL: enabling trigger-reset\n"); 25794562236bSHarry Wentland 25804562236bSHarry Wentland for (i = 1 /* skip the master */; i < group_size; i++) 25816b670fa9SHarry Wentland grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger( 2582fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg, 2583fa2123dbSMikita Lipski gsl_params.gsl_group); 25844562236bSHarry Wentland 25854562236bSHarry Wentland for (i = 1 /* skip the master */; i < group_size; i++) { 25864562236bSHarry Wentland DC_SYNC_INFO("GSL: waiting for reset to occur.\n"); 25876b670fa9SHarry Wentland wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg); 2588fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger( 2589fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg); 25904562236bSHarry Wentland } 25914562236bSHarry Wentland 25924562236bSHarry Wentland /* GSL Vblank synchronization is a one time sync mechanism, assumption 25934562236bSHarry Wentland * is that the sync'ed displays will not drift out of sync over time*/ 25944562236bSHarry Wentland DC_SYNC_INFO("GSL: Restoring register states.\n"); 25954562236bSHarry Wentland for (i = 0; i < group_size; i++) 25966b670fa9SHarry Wentland grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg); 25974562236bSHarry Wentland 25984562236bSHarry Wentland DC_SYNC_INFO("GSL: Set-up complete.\n"); 25994562236bSHarry Wentland } 26004562236bSHarry Wentland 2601fa2123dbSMikita Lipski static void dce110_enable_per_frame_crtc_position_reset( 2602fa2123dbSMikita Lipski struct dc *dc, 2603fa2123dbSMikita Lipski int group_size, 2604fa2123dbSMikita Lipski struct pipe_ctx *grouped_pipes[]) 2605fa2123dbSMikita Lipski { 2606fa2123dbSMikita Lipski struct dc_context *dc_ctx = dc->ctx; 2607fa2123dbSMikita Lipski struct dcp_gsl_params gsl_params = { 0 }; 2608fa2123dbSMikita Lipski int i; 2609fa2123dbSMikita Lipski 2610fa2123dbSMikita Lipski gsl_params.gsl_group = 0; 261137cd85ceSDavid Francis gsl_params.gsl_master = 0; 2612fa2123dbSMikita Lipski 2613fa2123dbSMikita Lipski for (i = 0; i < group_size; i++) 2614fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock( 2615fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg, &gsl_params); 2616fa2123dbSMikita Lipski 2617fa2123dbSMikita Lipski DC_SYNC_INFO("GSL: enabling trigger-reset\n"); 2618fa2123dbSMikita Lipski 2619fa2123dbSMikita Lipski for (i = 1; i < group_size; i++) 2620fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset( 2621fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg, 2622fa2123dbSMikita Lipski gsl_params.gsl_master, 2623fa2123dbSMikita Lipski &grouped_pipes[i]->stream->triggered_crtc_reset); 2624fa2123dbSMikita Lipski 2625fa2123dbSMikita Lipski DC_SYNC_INFO("GSL: waiting for reset to occur.\n"); 2626fa2123dbSMikita Lipski for (i = 1; i < group_size; i++) 2627fa2123dbSMikita Lipski wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg); 2628fa2123dbSMikita Lipski 2629fa2123dbSMikita Lipski for (i = 0; i < group_size; i++) 2630fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg); 2631fa2123dbSMikita Lipski 2632fa2123dbSMikita Lipski } 2633fa2123dbSMikita Lipski 2634fb55546eSAnthony Koo static void init_pipes(struct dc *dc, struct dc_state *context) 2635fb55546eSAnthony Koo { 2636fb55546eSAnthony Koo // Do nothing 2637fb55546eSAnthony Koo } 2638fb55546eSAnthony Koo 2639fb3466a4SBhawanpreet Lakha static void init_hw(struct dc *dc) 26404562236bSHarry Wentland { 26414562236bSHarry Wentland int i; 26424562236bSHarry Wentland struct dc_bios *bp; 26434562236bSHarry Wentland struct transform *xfm; 26445e7773a2SAnthony Koo struct abm *abm; 264570d9e8cbSPaul Hsieh struct dmcu *dmcu; 2646f42ea55bSAnthony Koo struct dce_hwseq *hws = dc->hwseq; 26473ba01817SYongqiang Sun uint32_t backlight = MAX_BACKLIGHT_LEVEL; 26484562236bSHarry Wentland 26494562236bSHarry Wentland bp = dc->ctx->dc_bios; 26504562236bSHarry Wentland for (i = 0; i < dc->res_pool->pipe_count; i++) { 26514562236bSHarry Wentland xfm = dc->res_pool->transforms[i]; 26524562236bSHarry Wentland xfm->funcs->transform_reset(xfm); 26534562236bSHarry Wentland 2654f42ea55bSAnthony Koo hws->funcs.enable_display_power_gating( 26554562236bSHarry Wentland dc, i, bp, 26564562236bSHarry Wentland PIPE_GATING_CONTROL_INIT); 2657f42ea55bSAnthony Koo hws->funcs.enable_display_power_gating( 26584562236bSHarry Wentland dc, i, bp, 26594562236bSHarry Wentland PIPE_GATING_CONTROL_DISABLE); 2660f42ea55bSAnthony Koo hws->funcs.enable_display_pipe_clock_gating( 26614562236bSHarry Wentland dc->ctx, 26624562236bSHarry Wentland true); 26634562236bSHarry Wentland } 26644562236bSHarry Wentland 2665e166ad43SJulia Lawall dce_clock_gating_power_up(dc->hwseq, false); 26664562236bSHarry Wentland /***************************************/ 26674562236bSHarry Wentland 26684562236bSHarry Wentland for (i = 0; i < dc->link_count; i++) { 26694562236bSHarry Wentland /****************************************/ 26704562236bSHarry Wentland /* Power up AND update implementation according to the 26714562236bSHarry Wentland * required signal (which may be different from the 26724562236bSHarry Wentland * default signal on connector). */ 2673d0778ebfSHarry Wentland struct dc_link *link = dc->links[i]; 2674069d418fSAndrew Jiang 26754562236bSHarry Wentland link->link_enc->funcs->hw_init(link->link_enc); 26764562236bSHarry Wentland } 26774562236bSHarry Wentland 26784562236bSHarry Wentland for (i = 0; i < dc->res_pool->pipe_count; i++) { 26794562236bSHarry Wentland struct timing_generator *tg = dc->res_pool->timing_generators[i]; 26804562236bSHarry Wentland 26814562236bSHarry Wentland tg->funcs->disable_vga(tg); 26824562236bSHarry Wentland 26834562236bSHarry Wentland /* Blank controller using driver code instead of 26844562236bSHarry Wentland * command table. */ 26854562236bSHarry Wentland tg->funcs->set_blank(tg, true); 26864b5e7d62SHersen Wu hwss_wait_for_blank_complete(tg); 26874562236bSHarry Wentland } 26884562236bSHarry Wentland 26894562236bSHarry Wentland for (i = 0; i < dc->res_pool->audio_count; i++) { 26904562236bSHarry Wentland struct audio *audio = dc->res_pool->audios[i]; 26914562236bSHarry Wentland audio->funcs->hw_init(audio); 26924562236bSHarry Wentland } 26935e7773a2SAnthony Koo 26943ba01817SYongqiang Sun for (i = 0; i < dc->link_count; i++) { 26953ba01817SYongqiang Sun struct dc_link *link = dc->links[i]; 26963ba01817SYongqiang Sun 26973ba01817SYongqiang Sun if (link->panel_cntl) 26983ba01817SYongqiang Sun backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl); 26994562236bSHarry Wentland } 27005099114bSAlex Deucher 27013ba01817SYongqiang Sun abm = dc->res_pool->abm; 27023ba01817SYongqiang Sun if (abm != NULL) 27033ba01817SYongqiang Sun abm->funcs->abm_init(abm, backlight); 27043ba01817SYongqiang Sun 270570d9e8cbSPaul Hsieh dmcu = dc->res_pool->dmcu; 270670d9e8cbSPaul Hsieh if (dmcu != NULL && abm != NULL) 270770d9e8cbSPaul Hsieh abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu); 270870d9e8cbSPaul Hsieh 27092f3bfb27SRoman Li if (dc->fbc_compressor) 27101663ae1cSBhawanpreet Lakha dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor); 2711690b5e39SRoman Li 27126728b30cSAnthony Koo } 27134562236bSHarry Wentland 27149566b675SDmytro Laktyushkin 27159566b675SDmytro Laktyushkin void dce110_prepare_bandwidth( 2716fb3466a4SBhawanpreet Lakha struct dc *dc, 27179566b675SDmytro Laktyushkin struct dc_state *context) 2718cf437593SDmytro Laktyushkin { 2719dc88b4a6SEric Yang struct clk_mgr *dccg = dc->clk_mgr; 2720fab55d61SDmytro Laktyushkin 2721fab55d61SDmytro Laktyushkin dce110_set_safe_displaymarks(&context->res_ctx, dc->res_pool); 2722cf437593SDmytro Laktyushkin 27235a83c932SNicholas Kazlauskas dccg->funcs->update_clocks( 27245a83c932SNicholas Kazlauskas dccg, 272524f7dd7eSDmytro Laktyushkin context, 27269566b675SDmytro Laktyushkin false); 27279566b675SDmytro Laktyushkin } 27289566b675SDmytro Laktyushkin 27299566b675SDmytro Laktyushkin void dce110_optimize_bandwidth( 27309566b675SDmytro Laktyushkin struct dc *dc, 27319566b675SDmytro Laktyushkin struct dc_state *context) 27329566b675SDmytro Laktyushkin { 2733dc88b4a6SEric Yang struct clk_mgr *dccg = dc->clk_mgr; 27349566b675SDmytro Laktyushkin 27359566b675SDmytro Laktyushkin dce110_set_displaymarks(dc, context); 27369566b675SDmytro Laktyushkin 27379566b675SDmytro Laktyushkin dccg->funcs->update_clocks( 27389566b675SDmytro Laktyushkin dccg, 27399566b675SDmytro Laktyushkin context, 27409566b675SDmytro Laktyushkin true); 27414562236bSHarry Wentland } 27424562236bSHarry Wentland 27434562236bSHarry Wentland static void dce110_program_front_end_for_pipe( 2744fb3466a4SBhawanpreet Lakha struct dc *dc, struct pipe_ctx *pipe_ctx) 27454562236bSHarry Wentland { 274686a66c4eSHarry Wentland struct mem_input *mi = pipe_ctx->plane_res.mi; 27473be5262eSHarry Wentland struct dc_plane_state *plane_state = pipe_ctx->plane_state; 27484562236bSHarry Wentland struct xfm_grph_csc_adjustment adjust; 27494562236bSHarry Wentland struct out_csc_color_matrix tbl_entry; 27504562236bSHarry Wentland unsigned int i; 2751f42ea55bSAnthony Koo struct dce_hwseq *hws = dc->hwseq; 2752f42ea55bSAnthony Koo 27535d4b05ddSBhawanpreet Lakha DC_LOGGER_INIT(); 27544562236bSHarry Wentland memset(&tbl_entry, 0, sizeof(tbl_entry)); 27554562236bSHarry Wentland 27564562236bSHarry Wentland memset(&adjust, 0, sizeof(adjust)); 27574562236bSHarry Wentland adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; 27584562236bSHarry Wentland 2759e07f541fSYongqiang Sun dce_enable_fe_clock(dc->hwseq, mi->inst, true); 27604562236bSHarry Wentland 27614562236bSHarry Wentland set_default_colors(pipe_ctx); 27624fa086b9SLeo (Sunpeng) Li if (pipe_ctx->stream->csc_color_matrix.enable_adjustment 27634562236bSHarry Wentland == true) { 27644562236bSHarry Wentland tbl_entry.color_space = 27654fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->output_color_space; 27664562236bSHarry Wentland 27674562236bSHarry Wentland for (i = 0; i < 12; i++) 27684562236bSHarry Wentland tbl_entry.regval[i] = 27694fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->csc_color_matrix.matrix[i]; 27704562236bSHarry Wentland 277186a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment 277286a66c4eSHarry Wentland (pipe_ctx->plane_res.xfm, &tbl_entry); 27734562236bSHarry Wentland } 27744562236bSHarry Wentland 27754fa086b9SLeo (Sunpeng) Li if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { 27764562236bSHarry Wentland adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; 2777146a9f63SKrunoslav Kovac 2778146a9f63SKrunoslav Kovac for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++) 2779146a9f63SKrunoslav Kovac adjust.temperature_matrix[i] = 2780146a9f63SKrunoslav Kovac pipe_ctx->stream->gamut_remap_matrix.matrix[i]; 27814562236bSHarry Wentland } 27824562236bSHarry Wentland 278386a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); 27844562236bSHarry Wentland 27856702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; 2786c1473558SAndrey Grodzovsky 27874562236bSHarry Wentland program_scaler(dc, pipe_ctx); 27884562236bSHarry Wentland 27894562236bSHarry Wentland mi->funcs->mem_input_program_surface_config( 27904562236bSHarry Wentland mi, 27913be5262eSHarry Wentland plane_state->format, 27923be5262eSHarry Wentland &plane_state->tiling_info, 27933be5262eSHarry Wentland &plane_state->plane_size, 27943be5262eSHarry Wentland plane_state->rotation, 2795624d7c47SYongqiang Sun NULL, 27964b28b76bSDmytro Laktyushkin false); 27974b28b76bSDmytro Laktyushkin if (mi->funcs->set_blank) 27983be5262eSHarry Wentland mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible); 27994562236bSHarry Wentland 2800fb3466a4SBhawanpreet Lakha if (dc->config.gpu_vm_support) 28014562236bSHarry Wentland mi->funcs->mem_input_program_pte_vm( 280286a66c4eSHarry Wentland pipe_ctx->plane_res.mi, 28033be5262eSHarry Wentland plane_state->format, 28043be5262eSHarry Wentland &plane_state->tiling_info, 28053be5262eSHarry Wentland plane_state->rotation); 28064562236bSHarry Wentland 2807067c878aSYongqiang Sun /* Moved programming gamma from dc to hwss */ 2808405c50a0SAndrew Jiang if (pipe_ctx->plane_state->update_flags.bits.full_update || 2809405c50a0SAndrew Jiang pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change || 2810405c50a0SAndrew Jiang pipe_ctx->plane_state->update_flags.bits.gamma_change) 2811f42ea55bSAnthony Koo hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state); 2812405c50a0SAndrew Jiang 2813405c50a0SAndrew Jiang if (pipe_ctx->plane_state->update_flags.bits.full_update) 2814f42ea55bSAnthony Koo hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream); 2815067c878aSYongqiang Sun 28161296423bSBhawanpreet Lakha DC_LOG_SURFACE( 28173032deb5SBhawanpreet Lakha "Pipe:%d %p: addr hi:0x%x, " 28184562236bSHarry Wentland "addr low:0x%x, " 28194562236bSHarry Wentland "src: %d, %d, %d," 28204562236bSHarry Wentland " %d; dst: %d, %d, %d, %d;" 28214562236bSHarry Wentland "clip: %d, %d, %d, %d\n", 28224562236bSHarry Wentland pipe_ctx->pipe_idx, 28233032deb5SBhawanpreet Lakha (void *) pipe_ctx->plane_state, 28243be5262eSHarry Wentland pipe_ctx->plane_state->address.grph.addr.high_part, 28253be5262eSHarry Wentland pipe_ctx->plane_state->address.grph.addr.low_part, 28263be5262eSHarry Wentland pipe_ctx->plane_state->src_rect.x, 28273be5262eSHarry Wentland pipe_ctx->plane_state->src_rect.y, 28283be5262eSHarry Wentland pipe_ctx->plane_state->src_rect.width, 28293be5262eSHarry Wentland pipe_ctx->plane_state->src_rect.height, 28303be5262eSHarry Wentland pipe_ctx->plane_state->dst_rect.x, 28313be5262eSHarry Wentland pipe_ctx->plane_state->dst_rect.y, 28323be5262eSHarry Wentland pipe_ctx->plane_state->dst_rect.width, 28333be5262eSHarry Wentland pipe_ctx->plane_state->dst_rect.height, 28343be5262eSHarry Wentland pipe_ctx->plane_state->clip_rect.x, 28353be5262eSHarry Wentland pipe_ctx->plane_state->clip_rect.y, 28363be5262eSHarry Wentland pipe_ctx->plane_state->clip_rect.width, 28373be5262eSHarry Wentland pipe_ctx->plane_state->clip_rect.height); 28384562236bSHarry Wentland 28391296423bSBhawanpreet Lakha DC_LOG_SURFACE( 28404562236bSHarry Wentland "Pipe %d: width, height, x, y\n" 28414562236bSHarry Wentland "viewport:%d, %d, %d, %d\n" 28424562236bSHarry Wentland "recout: %d, %d, %d, %d\n", 28434562236bSHarry Wentland pipe_ctx->pipe_idx, 28446702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.width, 28456702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.height, 28466702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.x, 28476702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.y, 28486702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.width, 28496702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.height, 28506702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.x, 28516702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.y); 28524562236bSHarry Wentland } 28534562236bSHarry Wentland 28544562236bSHarry Wentland static void dce110_apply_ctx_for_surface( 2855fb3466a4SBhawanpreet Lakha struct dc *dc, 28563e9ad616SEric Yang const struct dc_stream_state *stream, 28573e9ad616SEric Yang int num_planes, 2858608ac7bbSJerry Zuo struct dc_state *context) 28594562236bSHarry Wentland { 28602194e3aeSRoman Li int i; 28614562236bSHarry Wentland 28623e9ad616SEric Yang if (num_planes == 0) 28634562236bSHarry Wentland return; 28644562236bSHarry Wentland 286565d38262Shersen wu if (dc->fbc_compressor) 286665d38262Shersen wu dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); 286765d38262Shersen wu 28683e9ad616SEric Yang for (i = 0; i < dc->res_pool->pipe_count; i++) { 28693dc780ecSYongqiang Sun struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 28704562236bSHarry Wentland 2871a2607aefSHarry Wentland if (pipe_ctx->stream != stream) 28724562236bSHarry Wentland continue; 28734562236bSHarry Wentland 28743b21b6d2SJerry Zuo /* Need to allocate mem before program front end for Fiji */ 28753b21b6d2SJerry Zuo pipe_ctx->plane_res.mi->funcs->allocate_mem_input( 28763b21b6d2SJerry Zuo pipe_ctx->plane_res.mi, 28773b21b6d2SJerry Zuo pipe_ctx->stream->timing.h_total, 28783b21b6d2SJerry Zuo pipe_ctx->stream->timing.v_total, 2879380604e2SKen Chalmers pipe_ctx->stream->timing.pix_clk_100hz / 10, 28803b21b6d2SJerry Zuo context->stream_count); 28813b21b6d2SJerry Zuo 28824562236bSHarry Wentland dce110_program_front_end_for_pipe(dc, pipe_ctx); 28834f804817SYongqiang Sun 28844f804817SYongqiang Sun dc->hwss.update_plane_addr(dc, pipe_ctx); 28854f804817SYongqiang Sun 2886b06b7680SLeon Elazar program_surface_visibility(dc, pipe_ctx); 28874562236bSHarry Wentland 28884562236bSHarry Wentland } 28893dc780ecSYongqiang Sun 289065d38262Shersen wu if (dc->fbc_compressor) 289112a8bd88SShirish S enable_fbc(dc, context); 28924562236bSHarry Wentland } 28934562236bSHarry Wentland 2894bbf5f6c3SAnthony Koo static void dce110_post_unlock_program_front_end( 2895bbf5f6c3SAnthony Koo struct dc *dc, 2896bbf5f6c3SAnthony Koo struct dc_state *context) 2897bbf5f6c3SAnthony Koo { 2898bbf5f6c3SAnthony Koo } 2899009114f6SAnthony Koo 2900e6c258cbSYongqiang Sun static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx) 29014562236bSHarry Wentland { 2902f42ea55bSAnthony Koo struct dce_hwseq *hws = dc->hwseq; 2903bc373a89SRoman Li int fe_idx = pipe_ctx->plane_res.mi ? 2904bc373a89SRoman Li pipe_ctx->plane_res.mi->inst : pipe_ctx->pipe_idx; 2905e6c258cbSYongqiang Sun 29067950f0f9SDmytro Laktyushkin /* Do not power down fe when stream is active on dce*/ 2907608ac7bbSJerry Zuo if (dc->current_state->res_ctx.pipe_ctx[fe_idx].stream) 29084562236bSHarry Wentland return; 29094562236bSHarry Wentland 2910f42ea55bSAnthony Koo hws->funcs.enable_display_power_gating( 2911cfe4645eSDmytro Laktyushkin dc, fe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE); 2912cfe4645eSDmytro Laktyushkin 2913cfe4645eSDmytro Laktyushkin dc->res_pool->transforms[fe_idx]->funcs->transform_reset( 2914cfe4645eSDmytro Laktyushkin dc->res_pool->transforms[fe_idx]); 29154562236bSHarry Wentland } 29164562236bSHarry Wentland 29176be425f3SEric Yang static void dce110_wait_for_mpcc_disconnect( 2918fb3466a4SBhawanpreet Lakha struct dc *dc, 29196be425f3SEric Yang struct resource_pool *res_pool, 29206be425f3SEric Yang struct pipe_ctx *pipe_ctx) 2921b6762f0cSEric Yang { 2922b6762f0cSEric Yang /* do nothing*/ 2923b6762f0cSEric Yang } 2924b6762f0cSEric Yang 29254bd0dc68SJoshua Aberback static void program_output_csc(struct dc *dc, 29264bd0dc68SJoshua Aberback struct pipe_ctx *pipe_ctx, 29274bd0dc68SJoshua Aberback enum dc_color_space colorspace, 29284bd0dc68SJoshua Aberback uint16_t *matrix, 29294bd0dc68SJoshua Aberback int opp_id) 29304bd0dc68SJoshua Aberback { 29314bd0dc68SJoshua Aberback int i; 29324bd0dc68SJoshua Aberback struct out_csc_color_matrix tbl_entry; 29334bd0dc68SJoshua Aberback 29344bd0dc68SJoshua Aberback if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { 29354bd0dc68SJoshua Aberback enum dc_color_space color_space = pipe_ctx->stream->output_color_space; 29364bd0dc68SJoshua Aberback 29374bd0dc68SJoshua Aberback for (i = 0; i < 12; i++) 29384bd0dc68SJoshua Aberback tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; 29394bd0dc68SJoshua Aberback 29404bd0dc68SJoshua Aberback tbl_entry.color_space = color_space; 29414bd0dc68SJoshua Aberback 29424bd0dc68SJoshua Aberback pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment( 29434bd0dc68SJoshua Aberback pipe_ctx->plane_res.xfm, &tbl_entry); 29444bd0dc68SJoshua Aberback } 29454bd0dc68SJoshua Aberback } 29464bd0dc68SJoshua Aberback 2947faf0389fSJason Yan static void dce110_set_cursor_position(struct pipe_ctx *pipe_ctx) 294833fd17d9SEric Yang { 294933fd17d9SEric Yang struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position; 295033fd17d9SEric Yang struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; 295133fd17d9SEric Yang struct mem_input *mi = pipe_ctx->plane_res.mi; 295233fd17d9SEric Yang struct dc_cursor_mi_param param = { 2953380604e2SKen Chalmers .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10, 295433d7598dSJun Lei .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clocks.xtalin_clock_inKhz, 295539a9f4d8SDmytro Laktyushkin .viewport = pipe_ctx->plane_res.scl_data.viewport, 295639a9f4d8SDmytro Laktyushkin .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz, 295739a9f4d8SDmytro Laktyushkin .v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert, 295808ed681cSDmytro Laktyushkin .rotation = pipe_ctx->plane_state->rotation, 295908ed681cSDmytro Laktyushkin .mirror = pipe_ctx->plane_state->horizontal_mirror 296033fd17d9SEric Yang }; 296133fd17d9SEric Yang 296203a4059bSNicholas Kazlauskas /** 296303a4059bSNicholas Kazlauskas * If the cursor's source viewport is clipped then we need to 296403a4059bSNicholas Kazlauskas * translate the cursor to appear in the correct position on 296503a4059bSNicholas Kazlauskas * the screen. 296603a4059bSNicholas Kazlauskas * 296703a4059bSNicholas Kazlauskas * This translation isn't affected by scaling so it needs to be 296803a4059bSNicholas Kazlauskas * done *after* we adjust the position for the scale factor. 2969033baeeeSNicholas Kazlauskas * 2970033baeeeSNicholas Kazlauskas * This is only done by opt-in for now since there are still 2971033baeeeSNicholas Kazlauskas * some usecases like tiled display that might enable the 2972033baeeeSNicholas Kazlauskas * cursor on both streams while expecting dc to clip it. 297303a4059bSNicholas Kazlauskas */ 2974033baeeeSNicholas Kazlauskas if (pos_cpy.translate_by_source) { 297503a4059bSNicholas Kazlauskas pos_cpy.x += pipe_ctx->plane_state->src_rect.x; 297603a4059bSNicholas Kazlauskas pos_cpy.y += pipe_ctx->plane_state->src_rect.y; 2977033baeeeSNicholas Kazlauskas } 297803a4059bSNicholas Kazlauskas 297933fd17d9SEric Yang if (pipe_ctx->plane_state->address.type 298033fd17d9SEric Yang == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) 298133fd17d9SEric Yang pos_cpy.enable = false; 298233fd17d9SEric Yang 298333fd17d9SEric Yang if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) 298433fd17d9SEric Yang pos_cpy.enable = false; 298533fd17d9SEric Yang 2986dc75dd70SRoman Li if (ipp->funcs->ipp_cursor_set_position) 298733fd17d9SEric Yang ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); 2988dc75dd70SRoman Li if (mi->funcs->set_cursor_position) 298933fd17d9SEric Yang mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m); 299033fd17d9SEric Yang } 299133fd17d9SEric Yang 2992faf0389fSJason Yan static void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx) 299333fd17d9SEric Yang { 299433fd17d9SEric Yang struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes; 299533fd17d9SEric Yang 2996d1aaad05SHarry Wentland if (pipe_ctx->plane_res.ipp && 2997d1aaad05SHarry Wentland pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes) 299833fd17d9SEric Yang pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( 299933fd17d9SEric Yang pipe_ctx->plane_res.ipp, attributes); 300033fd17d9SEric Yang 3001d1aaad05SHarry Wentland if (pipe_ctx->plane_res.mi && 3002d1aaad05SHarry Wentland pipe_ctx->plane_res.mi->funcs->set_cursor_attributes) 300333fd17d9SEric Yang pipe_ctx->plane_res.mi->funcs->set_cursor_attributes( 300433fd17d9SEric Yang pipe_ctx->plane_res.mi, attributes); 300533fd17d9SEric Yang 3006d1aaad05SHarry Wentland if (pipe_ctx->plane_res.xfm && 3007d1aaad05SHarry Wentland pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes) 300833fd17d9SEric Yang pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes( 300933fd17d9SEric Yang pipe_ctx->plane_res.xfm, attributes); 301033fd17d9SEric Yang } 301133fd17d9SEric Yang 30124b0e95d1SYongqiang Sun bool dce110_set_backlight_level(struct pipe_ctx *pipe_ctx, 30134b0e95d1SYongqiang Sun uint32_t backlight_pwm_u16_16, 30144b0e95d1SYongqiang Sun uint32_t frame_ramp) 30154b0e95d1SYongqiang Sun { 30164b0e95d1SYongqiang Sun struct dc_link *link = pipe_ctx->stream->link; 30174b0e95d1SYongqiang Sun struct dc *dc = link->ctx->dc; 30184b0e95d1SYongqiang Sun struct abm *abm = pipe_ctx->stream_res.abm; 30193ba01817SYongqiang Sun struct panel_cntl *panel_cntl = link->panel_cntl; 30204b0e95d1SYongqiang Sun struct dmcu *dmcu = dc->res_pool->dmcu; 30214b0e95d1SYongqiang Sun bool fw_set_brightness = true; 30224b0e95d1SYongqiang Sun /* DMCU -1 for all controller id values, 30234b0e95d1SYongqiang Sun * therefore +1 here 30244b0e95d1SYongqiang Sun */ 30254b0e95d1SYongqiang Sun uint32_t controller_id = pipe_ctx->stream_res.tg->inst + 1; 30264b0e95d1SYongqiang Sun 30273ba01817SYongqiang Sun if (abm == NULL || panel_cntl == NULL || (abm->funcs->set_backlight_level_pwm == NULL)) 30284b0e95d1SYongqiang Sun return false; 30294b0e95d1SYongqiang Sun 30304b0e95d1SYongqiang Sun if (dmcu) 30314b0e95d1SYongqiang Sun fw_set_brightness = dmcu->funcs->is_dmcu_initialized(dmcu); 30324b0e95d1SYongqiang Sun 30333ba01817SYongqiang Sun if (!fw_set_brightness && panel_cntl->funcs->driver_set_backlight) 30343ba01817SYongqiang Sun panel_cntl->funcs->driver_set_backlight(panel_cntl, backlight_pwm_u16_16); 30353ba01817SYongqiang Sun else 30364b0e95d1SYongqiang Sun abm->funcs->set_backlight_level_pwm( 30374b0e95d1SYongqiang Sun abm, 30384b0e95d1SYongqiang Sun backlight_pwm_u16_16, 30394b0e95d1SYongqiang Sun frame_ramp, 30404b0e95d1SYongqiang Sun controller_id, 30413ba01817SYongqiang Sun link->panel_cntl->inst); 30424b0e95d1SYongqiang Sun 30434b0e95d1SYongqiang Sun return true; 30444b0e95d1SYongqiang Sun } 30454b0e95d1SYongqiang Sun 30463ba01817SYongqiang Sun void dce110_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx) 30473ba01817SYongqiang Sun { 30483ba01817SYongqiang Sun struct abm *abm = pipe_ctx->stream_res.abm; 30493ba01817SYongqiang Sun struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl; 30503ba01817SYongqiang Sun 30513ba01817SYongqiang Sun if (abm) 30523ba01817SYongqiang Sun abm->funcs->set_abm_immediate_disable(abm, 30533ba01817SYongqiang Sun pipe_ctx->stream->link->panel_cntl->inst); 30543ba01817SYongqiang Sun 30553ba01817SYongqiang Sun if (panel_cntl) 30563ba01817SYongqiang Sun panel_cntl->funcs->store_backlight_level(panel_cntl); 30573ba01817SYongqiang Sun } 30583ba01817SYongqiang Sun 3059474ac4a8SYongqiang Sun void dce110_set_pipe(struct pipe_ctx *pipe_ctx) 3060474ac4a8SYongqiang Sun { 3061474ac4a8SYongqiang Sun struct abm *abm = pipe_ctx->stream_res.abm; 3062474ac4a8SYongqiang Sun struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl; 3063474ac4a8SYongqiang Sun uint32_t otg_inst = pipe_ctx->stream_res.tg->inst + 1; 3064474ac4a8SYongqiang Sun 3065474ac4a8SYongqiang Sun if (abm && panel_cntl) 3066474ac4a8SYongqiang Sun abm->funcs->set_pipe(abm, otg_inst, panel_cntl->inst); 3067474ac4a8SYongqiang Sun } 3068474ac4a8SYongqiang Sun 30694562236bSHarry Wentland static const struct hw_sequencer_funcs dce110_funcs = { 30701bf56e62SZeyu Fan .program_gamut_remap = program_gamut_remap, 30714bd0dc68SJoshua Aberback .program_output_csc = program_output_csc, 30724562236bSHarry Wentland .init_hw = init_hw, 30734562236bSHarry Wentland .apply_ctx_to_hw = dce110_apply_ctx_to_hw, 30744562236bSHarry Wentland .apply_ctx_for_surface = dce110_apply_ctx_for_surface, 3075bbf5f6c3SAnthony Koo .post_unlock_program_front_end = dce110_post_unlock_program_front_end, 30764562236bSHarry Wentland .update_plane_addr = update_plane_addr, 30774562236bSHarry Wentland .update_pending_status = dce110_update_pending_status, 30784562236bSHarry Wentland .enable_accelerated_mode = dce110_enable_accelerated_mode, 30794562236bSHarry Wentland .enable_timing_synchronization = dce110_enable_timing_synchronization, 3080fa2123dbSMikita Lipski .enable_per_frame_crtc_position_reset = dce110_enable_per_frame_crtc_position_reset, 30814562236bSHarry Wentland .update_info_frame = dce110_update_info_frame, 30824562236bSHarry Wentland .enable_stream = dce110_enable_stream, 30834562236bSHarry Wentland .disable_stream = dce110_disable_stream, 30844562236bSHarry Wentland .unblank_stream = dce110_unblank_stream, 308541b49742SCharlene Liu .blank_stream = dce110_blank_stream, 30861a05873fSAnthony Koo .enable_audio_stream = dce110_enable_audio_stream, 30871a05873fSAnthony Koo .disable_audio_stream = dce110_disable_audio_stream, 30887f914a62SYongqiang Sun .disable_plane = dce110_power_down_fe, 30894562236bSHarry Wentland .pipe_control_lock = dce_pipe_control_lock, 3090009114f6SAnthony Koo .interdependent_update_lock = NULL, 30911e461c37SAric Cyr .cursor_lock = dce_pipe_control_lock, 30929566b675SDmytro Laktyushkin .prepare_bandwidth = dce110_prepare_bandwidth, 30939566b675SDmytro Laktyushkin .optimize_bandwidth = dce110_optimize_bandwidth, 30944562236bSHarry Wentland .set_drr = set_drr, 309572ada5f7SEric Cook .get_position = get_position, 30964562236bSHarry Wentland .set_static_screen_control = set_static_screen_control, 309715e17335SCharlene Liu .setup_stereo = NULL, 309815e17335SCharlene Liu .set_avmute = dce110_set_avmute, 309941f97c07SHersen Wu .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect, 3100099303e9SPeikang Zhang .edp_backlight_control = dce110_edp_backlight_control, 31018a31820bSMartin Leung .edp_power_control = dce110_edp_power_control, 31028a31820bSMartin Leung .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready, 310333fd17d9SEric Yang .set_cursor_position = dce110_set_cursor_position, 31044b0e95d1SYongqiang Sun .set_cursor_attribute = dce110_set_cursor_attribute, 31054b0e95d1SYongqiang Sun .set_backlight_level = dce110_set_backlight_level, 31063ba01817SYongqiang Sun .set_abm_immediate_disable = dce110_set_abm_immediate_disable, 3107474ac4a8SYongqiang Sun .set_pipe = dce110_set_pipe, 31084562236bSHarry Wentland }; 31094562236bSHarry Wentland 3110f42ea55bSAnthony Koo static const struct hwseq_private_funcs dce110_private_funcs = { 3111f42ea55bSAnthony Koo .init_pipes = init_pipes, 3112f42ea55bSAnthony Koo .update_plane_addr = update_plane_addr, 3113f42ea55bSAnthony Koo .set_input_transfer_func = dce110_set_input_transfer_func, 3114f42ea55bSAnthony Koo .set_output_transfer_func = dce110_set_output_transfer_func, 3115f42ea55bSAnthony Koo .power_down = dce110_power_down, 3116f42ea55bSAnthony Koo .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating, 3117f42ea55bSAnthony Koo .enable_display_power_gating = dce110_enable_display_power_gating, 3118f42ea55bSAnthony Koo .reset_hw_ctx_wrap = dce110_reset_hw_ctx_wrap, 3119f42ea55bSAnthony Koo .enable_stream_timing = dce110_enable_stream_timing, 3120f42ea55bSAnthony Koo .disable_stream_gating = NULL, 3121f42ea55bSAnthony Koo .enable_stream_gating = NULL, 3122f42ea55bSAnthony Koo .edp_backlight_control = dce110_edp_backlight_control, 3123f42ea55bSAnthony Koo }; 3124f42ea55bSAnthony Koo 3125c13b408bSDave Airlie void dce110_hw_sequencer_construct(struct dc *dc) 31264562236bSHarry Wentland { 31274562236bSHarry Wentland dc->hwss = dce110_funcs; 3128f42ea55bSAnthony Koo dc->hwseq->funcs = dce110_private_funcs; 31294562236bSHarry Wentland } 31304562236bSHarry Wentland 3131