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 */ 254562236bSHarry Wentland #include "dm_services.h" 264562236bSHarry Wentland #include "dc.h" 274562236bSHarry Wentland #include "dc_bios_types.h" 284562236bSHarry Wentland #include "core_types.h" 294562236bSHarry Wentland #include "core_status.h" 304562236bSHarry Wentland #include "resource.h" 314562236bSHarry Wentland #include "dm_helpers.h" 324562236bSHarry Wentland #include "dce110_hw_sequencer.h" 334562236bSHarry Wentland #include "dce110_timing_generator.h" 3498489c02SLeo (Sunpeng) Li #include "dce/dce_hwseq.h" 3587401969SAndrew Jiang #include "gpio_service_interface.h" 364562236bSHarry Wentland 371663ae1cSBhawanpreet Lakha #include "dce110_compressor.h" 381663ae1cSBhawanpreet Lakha 394562236bSHarry Wentland #include "bios/bios_parser_helper.h" 404562236bSHarry Wentland #include "timing_generator.h" 414562236bSHarry Wentland #include "mem_input.h" 424562236bSHarry Wentland #include "opp.h" 434562236bSHarry Wentland #include "ipp.h" 444562236bSHarry Wentland #include "transform.h" 454562236bSHarry Wentland #include "stream_encoder.h" 464562236bSHarry Wentland #include "link_encoder.h" 4787401969SAndrew Jiang #include "link_hwss.h" 484562236bSHarry Wentland #include "clock_source.h" 49dc88b4a6SEric Yang #include "clk_mgr.h" 505e7773a2SAnthony Koo #include "abm.h" 514562236bSHarry Wentland #include "audio.h" 5208b16886SZeyu Fan #include "reg_helper.h" 534562236bSHarry Wentland 544562236bSHarry Wentland /* include DCE11 register header files */ 554562236bSHarry Wentland #include "dce/dce_11_0_d.h" 564562236bSHarry Wentland #include "dce/dce_11_0_sh_mask.h" 57e266fdf6SVitaly Prosyak #include "custom_float.h" 584562236bSHarry Wentland 594cac1e6dSYongqiang Sun #include "atomfirmware.h" 604cac1e6dSYongqiang Sun 6187401969SAndrew Jiang /* 6287401969SAndrew Jiang * All values are in milliseconds; 6387401969SAndrew Jiang * For eDP, after power-up/power/down, 6487401969SAndrew Jiang * 300/500 msec max. delay from LCDVCC to black video generation 6587401969SAndrew Jiang */ 6687401969SAndrew Jiang #define PANEL_POWER_UP_TIMEOUT 300 6787401969SAndrew Jiang #define PANEL_POWER_DOWN_TIMEOUT 500 6887401969SAndrew Jiang #define HPD_CHECK_INTERVAL 10 6987401969SAndrew Jiang 705eefbc40SYue Hin Lau #define CTX \ 715eefbc40SYue Hin Lau hws->ctx 725d4b05ddSBhawanpreet Lakha 735d4b05ddSBhawanpreet Lakha #define DC_LOGGER_INIT() 745d4b05ddSBhawanpreet Lakha 755eefbc40SYue Hin Lau #define REG(reg)\ 765eefbc40SYue Hin Lau hws->regs->reg 775eefbc40SYue Hin Lau 785eefbc40SYue Hin Lau #undef FN 795eefbc40SYue Hin Lau #define FN(reg_name, field_name) \ 805eefbc40SYue Hin Lau hws->shifts->field_name, hws->masks->field_name 815eefbc40SYue Hin Lau 824562236bSHarry Wentland struct dce110_hw_seq_reg_offsets { 834562236bSHarry Wentland uint32_t crtc; 844562236bSHarry Wentland }; 854562236bSHarry Wentland 864562236bSHarry Wentland static const struct dce110_hw_seq_reg_offsets reg_offsets[] = { 874562236bSHarry Wentland { 884562236bSHarry Wentland .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), 894562236bSHarry Wentland }, 904562236bSHarry Wentland { 914562236bSHarry Wentland .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), 924562236bSHarry Wentland }, 934562236bSHarry Wentland { 944562236bSHarry Wentland .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), 954562236bSHarry Wentland }, 964562236bSHarry Wentland { 974562236bSHarry Wentland .crtc = (mmCRTCV_GSL_CONTROL - mmCRTC_GSL_CONTROL), 984562236bSHarry Wentland } 994562236bSHarry Wentland }; 1004562236bSHarry Wentland 1014562236bSHarry Wentland #define HW_REG_BLND(reg, id)\ 1024562236bSHarry Wentland (reg + reg_offsets[id].blnd) 1034562236bSHarry Wentland 1044562236bSHarry Wentland #define HW_REG_CRTC(reg, id)\ 1054562236bSHarry Wentland (reg + reg_offsets[id].crtc) 1064562236bSHarry Wentland 1074562236bSHarry Wentland #define MAX_WATERMARK 0xFFFF 1084562236bSHarry Wentland #define SAFE_NBP_MARK 0x7FFF 1094562236bSHarry Wentland 1104562236bSHarry Wentland /******************************************************************************* 1114562236bSHarry Wentland * Private definitions 1124562236bSHarry Wentland ******************************************************************************/ 1134562236bSHarry Wentland /***************************PIPE_CONTROL***********************************/ 1144562236bSHarry Wentland static void dce110_init_pte(struct dc_context *ctx) 1154562236bSHarry Wentland { 1164562236bSHarry Wentland uint32_t addr; 1174562236bSHarry Wentland uint32_t value = 0; 1184562236bSHarry Wentland uint32_t chunk_int = 0; 1194562236bSHarry Wentland uint32_t chunk_mul = 0; 1204562236bSHarry Wentland 1214562236bSHarry Wentland addr = mmUNP_DVMM_PTE_CONTROL; 1224562236bSHarry Wentland value = dm_read_reg(ctx, addr); 1234562236bSHarry Wentland 1244562236bSHarry Wentland set_reg_field_value( 1254562236bSHarry Wentland value, 1264562236bSHarry Wentland 0, 1274562236bSHarry Wentland DVMM_PTE_CONTROL, 1284562236bSHarry Wentland DVMM_USE_SINGLE_PTE); 1294562236bSHarry Wentland 1304562236bSHarry Wentland set_reg_field_value( 1314562236bSHarry Wentland value, 1324562236bSHarry Wentland 1, 1334562236bSHarry Wentland DVMM_PTE_CONTROL, 1344562236bSHarry Wentland DVMM_PTE_BUFFER_MODE0); 1354562236bSHarry Wentland 1364562236bSHarry Wentland set_reg_field_value( 1374562236bSHarry Wentland value, 1384562236bSHarry Wentland 1, 1394562236bSHarry Wentland DVMM_PTE_CONTROL, 1404562236bSHarry Wentland DVMM_PTE_BUFFER_MODE1); 1414562236bSHarry Wentland 1424562236bSHarry Wentland dm_write_reg(ctx, addr, value); 1434562236bSHarry Wentland 1444562236bSHarry Wentland addr = mmDVMM_PTE_REQ; 1454562236bSHarry Wentland value = dm_read_reg(ctx, addr); 1464562236bSHarry Wentland 1474562236bSHarry Wentland chunk_int = get_reg_field_value( 1484562236bSHarry Wentland value, 1494562236bSHarry Wentland DVMM_PTE_REQ, 1504562236bSHarry Wentland HFLIP_PTEREQ_PER_CHUNK_INT); 1514562236bSHarry Wentland 1524562236bSHarry Wentland chunk_mul = get_reg_field_value( 1534562236bSHarry Wentland value, 1544562236bSHarry Wentland DVMM_PTE_REQ, 1554562236bSHarry Wentland HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); 1564562236bSHarry Wentland 1574562236bSHarry Wentland if (chunk_int != 0x4 || chunk_mul != 0x4) { 1584562236bSHarry Wentland 1594562236bSHarry Wentland set_reg_field_value( 1604562236bSHarry Wentland value, 1614562236bSHarry Wentland 255, 1624562236bSHarry Wentland DVMM_PTE_REQ, 1634562236bSHarry Wentland MAX_PTEREQ_TO_ISSUE); 1644562236bSHarry Wentland 1654562236bSHarry Wentland set_reg_field_value( 1664562236bSHarry Wentland value, 1674562236bSHarry Wentland 4, 1684562236bSHarry Wentland DVMM_PTE_REQ, 1694562236bSHarry Wentland HFLIP_PTEREQ_PER_CHUNK_INT); 1704562236bSHarry Wentland 1714562236bSHarry Wentland set_reg_field_value( 1724562236bSHarry Wentland value, 1734562236bSHarry Wentland 4, 1744562236bSHarry Wentland DVMM_PTE_REQ, 1754562236bSHarry Wentland HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); 1764562236bSHarry Wentland 1774562236bSHarry Wentland dm_write_reg(ctx, addr, value); 1784562236bSHarry Wentland } 1794562236bSHarry Wentland } 1804562236bSHarry Wentland /**************************************************************************/ 1814562236bSHarry Wentland 1824562236bSHarry Wentland static void enable_display_pipe_clock_gating( 1834562236bSHarry Wentland struct dc_context *ctx, 1844562236bSHarry Wentland bool clock_gating) 1854562236bSHarry Wentland { 1864562236bSHarry Wentland /*TODO*/ 1874562236bSHarry Wentland } 1884562236bSHarry Wentland 1894562236bSHarry Wentland static bool dce110_enable_display_power_gating( 190fb3466a4SBhawanpreet Lakha struct dc *dc, 1914562236bSHarry Wentland uint8_t controller_id, 1924562236bSHarry Wentland struct dc_bios *dcb, 1934562236bSHarry Wentland enum pipe_gating_control power_gating) 1944562236bSHarry Wentland { 1954562236bSHarry Wentland enum bp_result bp_result = BP_RESULT_OK; 1964562236bSHarry Wentland enum bp_pipe_control_action cntl; 1974562236bSHarry Wentland struct dc_context *ctx = dc->ctx; 1984562236bSHarry Wentland unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; 1994562236bSHarry Wentland 2004562236bSHarry Wentland if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) 2014562236bSHarry Wentland return true; 2024562236bSHarry Wentland 2034562236bSHarry Wentland if (power_gating == PIPE_GATING_CONTROL_INIT) 2044562236bSHarry Wentland cntl = ASIC_PIPE_INIT; 2054562236bSHarry Wentland else if (power_gating == PIPE_GATING_CONTROL_ENABLE) 2064562236bSHarry Wentland cntl = ASIC_PIPE_ENABLE; 2074562236bSHarry Wentland else 2084562236bSHarry Wentland cntl = ASIC_PIPE_DISABLE; 2094562236bSHarry Wentland 2104562236bSHarry Wentland if (controller_id == underlay_idx) 2114562236bSHarry Wentland controller_id = CONTROLLER_ID_UNDERLAY0 - 1; 2124562236bSHarry Wentland 2134562236bSHarry Wentland if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0){ 2144562236bSHarry Wentland 2154562236bSHarry Wentland bp_result = dcb->funcs->enable_disp_power_gating( 2164562236bSHarry Wentland dcb, controller_id + 1, cntl); 2174562236bSHarry Wentland 2184562236bSHarry Wentland /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2 2194562236bSHarry Wentland * by default when command table is called 2204562236bSHarry Wentland * 2214562236bSHarry Wentland * Bios parser accepts controller_id = 6 as indicative of 2224562236bSHarry Wentland * underlay pipe in dce110. But we do not support more 2234562236bSHarry Wentland * than 3. 2244562236bSHarry Wentland */ 2254562236bSHarry Wentland if (controller_id < CONTROLLER_ID_MAX - 1) 2264562236bSHarry Wentland dm_write_reg(ctx, 2274562236bSHarry Wentland HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE, controller_id), 2284562236bSHarry Wentland 0); 2294562236bSHarry Wentland } 2304562236bSHarry Wentland 2314562236bSHarry Wentland if (power_gating != PIPE_GATING_CONTROL_ENABLE) 2324562236bSHarry Wentland dce110_init_pte(ctx); 2334562236bSHarry Wentland 2344562236bSHarry Wentland if (bp_result == BP_RESULT_OK) 2354562236bSHarry Wentland return true; 2364562236bSHarry Wentland else 2374562236bSHarry Wentland return false; 2384562236bSHarry Wentland } 2394562236bSHarry Wentland 2404562236bSHarry Wentland static void build_prescale_params(struct ipp_prescale_params *prescale_params, 2413be5262eSHarry Wentland const struct dc_plane_state *plane_state) 2424562236bSHarry Wentland { 2434562236bSHarry Wentland prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED; 2444562236bSHarry Wentland 2453be5262eSHarry Wentland switch (plane_state->format) { 2461352c779SNicholas Kazlauskas case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 2471352c779SNicholas Kazlauskas prescale_params->scale = 0x2082; 2481352c779SNicholas Kazlauskas break; 2494562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 2508693049aSTony Cheng case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 2514562236bSHarry Wentland prescale_params->scale = 0x2020; 2524562236bSHarry Wentland break; 2534562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 2544562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 2554562236bSHarry Wentland prescale_params->scale = 0x2008; 2564562236bSHarry Wentland break; 2574562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 2584562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 2594562236bSHarry Wentland prescale_params->scale = 0x2000; 2604562236bSHarry Wentland break; 2614562236bSHarry Wentland default: 2624562236bSHarry Wentland ASSERT(false); 263d7194cf6SAric Cyr break; 2644562236bSHarry Wentland } 2654562236bSHarry Wentland } 2664562236bSHarry Wentland 267a6114e85SHarry Wentland static bool 268a6114e85SHarry Wentland dce110_set_input_transfer_func(struct pipe_ctx *pipe_ctx, 2693be5262eSHarry Wentland const struct dc_plane_state *plane_state) 2704562236bSHarry Wentland { 27186a66c4eSHarry Wentland struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; 2727b0c470fSLeo (Sunpeng) Li const struct dc_transfer_func *tf = NULL; 27390e508baSAnthony Koo struct ipp_prescale_params prescale_params = { 0 }; 27490e508baSAnthony Koo bool result = true; 27590e508baSAnthony Koo 27690e508baSAnthony Koo if (ipp == NULL) 27790e508baSAnthony Koo return false; 27890e508baSAnthony Koo 2793be5262eSHarry Wentland if (plane_state->in_transfer_func) 2803be5262eSHarry Wentland tf = plane_state->in_transfer_func; 28190e508baSAnthony Koo 2823be5262eSHarry Wentland build_prescale_params(&prescale_params, plane_state); 28390e508baSAnthony Koo ipp->funcs->ipp_program_prescale(ipp, &prescale_params); 28490e508baSAnthony Koo 28584ffa801SLeo (Sunpeng) Li if (plane_state->gamma_correction && 28684ffa801SLeo (Sunpeng) Li !plane_state->gamma_correction->is_identity && 28784ffa801SLeo (Sunpeng) Li dce_use_lut(plane_state->format)) 2883be5262eSHarry Wentland ipp->funcs->ipp_program_input_lut(ipp, plane_state->gamma_correction); 289d7194cf6SAric Cyr 29090e508baSAnthony Koo if (tf == NULL) { 29190e508baSAnthony Koo /* Default case if no input transfer function specified */ 292a6114e85SHarry Wentland ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); 2937b0c470fSLeo (Sunpeng) Li } else if (tf->type == TF_TYPE_PREDEFINED) { 2947b0c470fSLeo (Sunpeng) Li switch (tf->tf) { 29590e508baSAnthony Koo case TRANSFER_FUNCTION_SRGB: 296a6114e85SHarry Wentland ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); 29790e508baSAnthony Koo break; 29890e508baSAnthony Koo case TRANSFER_FUNCTION_BT709: 299a6114e85SHarry Wentland ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_xvYCC); 30090e508baSAnthony Koo break; 30190e508baSAnthony Koo case TRANSFER_FUNCTION_LINEAR: 302a6114e85SHarry Wentland ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); 30390e508baSAnthony Koo break; 30490e508baSAnthony Koo case TRANSFER_FUNCTION_PQ: 30590e508baSAnthony Koo default: 30690e508baSAnthony Koo result = false; 307d7194cf6SAric Cyr break; 30890e508baSAnthony Koo } 3097b0c470fSLeo (Sunpeng) Li } else if (tf->type == TF_TYPE_BYPASS) { 31070063a59SAmy Zhang ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); 31190e508baSAnthony Koo } else { 31290e508baSAnthony Koo /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/ 31390e508baSAnthony Koo result = false; 31490e508baSAnthony Koo } 31590e508baSAnthony Koo 31690e508baSAnthony Koo return result; 31790e508baSAnthony Koo } 31890e508baSAnthony Koo 319bd1be8e8SHarry Wentland static bool convert_to_custom_float(struct pwl_result_data *rgb_resulted, 320fcd2f4bfSAmy Zhang struct curve_points *arr_points, 321fcd2f4bfSAmy Zhang uint32_t hw_points_num) 322fcd2f4bfSAmy Zhang { 323fcd2f4bfSAmy Zhang struct custom_float_format fmt; 324fcd2f4bfSAmy Zhang 325fcd2f4bfSAmy Zhang struct pwl_result_data *rgb = rgb_resulted; 326fcd2f4bfSAmy Zhang 327fcd2f4bfSAmy Zhang uint32_t i = 0; 328fcd2f4bfSAmy Zhang 329fcd2f4bfSAmy Zhang fmt.exponenta_bits = 6; 330fcd2f4bfSAmy Zhang fmt.mantissa_bits = 12; 331fcd2f4bfSAmy Zhang fmt.sign = true; 332fcd2f4bfSAmy Zhang 333bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(arr_points[0].x, &fmt, 334fcd2f4bfSAmy Zhang &arr_points[0].custom_float_x)) { 335fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 336fcd2f4bfSAmy Zhang return false; 337fcd2f4bfSAmy Zhang } 338fcd2f4bfSAmy Zhang 339bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(arr_points[0].offset, &fmt, 340fcd2f4bfSAmy Zhang &arr_points[0].custom_float_offset)) { 341fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 342fcd2f4bfSAmy Zhang return false; 343fcd2f4bfSAmy Zhang } 344fcd2f4bfSAmy Zhang 345bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(arr_points[0].slope, &fmt, 346fcd2f4bfSAmy Zhang &arr_points[0].custom_float_slope)) { 347fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 348fcd2f4bfSAmy Zhang return false; 349fcd2f4bfSAmy Zhang } 350fcd2f4bfSAmy Zhang 351fcd2f4bfSAmy Zhang fmt.mantissa_bits = 10; 352fcd2f4bfSAmy Zhang fmt.sign = false; 353fcd2f4bfSAmy Zhang 354bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(arr_points[1].x, &fmt, 355fcd2f4bfSAmy Zhang &arr_points[1].custom_float_x)) { 356fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 357fcd2f4bfSAmy Zhang return false; 358fcd2f4bfSAmy Zhang } 359fcd2f4bfSAmy Zhang 360bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(arr_points[1].y, &fmt, 361fcd2f4bfSAmy Zhang &arr_points[1].custom_float_y)) { 362fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 363fcd2f4bfSAmy Zhang return false; 364fcd2f4bfSAmy Zhang } 365fcd2f4bfSAmy Zhang 3664d06ccd0SHarry Wentland if (!convert_to_custom_float_format(arr_points[1].slope, &fmt, 3674d06ccd0SHarry Wentland &arr_points[1].custom_float_slope)) { 368fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 369fcd2f4bfSAmy Zhang return false; 370fcd2f4bfSAmy Zhang } 371fcd2f4bfSAmy Zhang 372fcd2f4bfSAmy Zhang fmt.mantissa_bits = 12; 373fcd2f4bfSAmy Zhang fmt.sign = true; 374fcd2f4bfSAmy Zhang 375fcd2f4bfSAmy Zhang while (i != hw_points_num) { 376bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(rgb->red, &fmt, 377fcd2f4bfSAmy Zhang &rgb->red_reg)) { 378fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 379fcd2f4bfSAmy Zhang return false; 380fcd2f4bfSAmy Zhang } 381fcd2f4bfSAmy Zhang 382bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(rgb->green, &fmt, 383fcd2f4bfSAmy Zhang &rgb->green_reg)) { 384fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 385fcd2f4bfSAmy Zhang return false; 386fcd2f4bfSAmy Zhang } 387fcd2f4bfSAmy Zhang 388bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(rgb->blue, &fmt, 389fcd2f4bfSAmy Zhang &rgb->blue_reg)) { 390fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 391fcd2f4bfSAmy Zhang return false; 392fcd2f4bfSAmy Zhang } 393fcd2f4bfSAmy Zhang 394bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(rgb->delta_red, &fmt, 395fcd2f4bfSAmy Zhang &rgb->delta_red_reg)) { 396fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 397fcd2f4bfSAmy Zhang return false; 398fcd2f4bfSAmy Zhang } 399fcd2f4bfSAmy Zhang 400bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(rgb->delta_green, &fmt, 401fcd2f4bfSAmy Zhang &rgb->delta_green_reg)) { 402fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 403fcd2f4bfSAmy Zhang return false; 404fcd2f4bfSAmy Zhang } 405fcd2f4bfSAmy Zhang 406bd1be8e8SHarry Wentland if (!convert_to_custom_float_format(rgb->delta_blue, &fmt, 407fcd2f4bfSAmy Zhang &rgb->delta_blue_reg)) { 408fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 409fcd2f4bfSAmy Zhang return false; 410fcd2f4bfSAmy Zhang } 411fcd2f4bfSAmy Zhang 412fcd2f4bfSAmy Zhang ++rgb; 413fcd2f4bfSAmy Zhang ++i; 414fcd2f4bfSAmy Zhang } 415fcd2f4bfSAmy Zhang 416fcd2f4bfSAmy Zhang return true; 417fcd2f4bfSAmy Zhang } 418fcd2f4bfSAmy Zhang 41908616da5SLeo (Sunpeng) Li #define MAX_LOW_POINT 25 4208f8372c7SKrunoslav Kovac #define NUMBER_REGIONS 16 4218f8372c7SKrunoslav Kovac #define NUMBER_SW_SEGMENTS 16 4228f8372c7SKrunoslav Kovac 423b310b081SHarry Wentland static bool 424b310b081SHarry Wentland dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf, 425b310b081SHarry Wentland struct pwl_params *regamma_params) 426fcd2f4bfSAmy Zhang { 42723ae4f8eSAmy Zhang struct curve_points *arr_points; 42823ae4f8eSAmy Zhang struct pwl_result_data *rgb_resulted; 42923ae4f8eSAmy Zhang struct pwl_result_data *rgb; 43023ae4f8eSAmy Zhang struct pwl_result_data *rgb_plus_1; 431fcd2f4bfSAmy Zhang struct fixed31_32 y_r; 432fcd2f4bfSAmy Zhang struct fixed31_32 y_g; 433fcd2f4bfSAmy Zhang struct fixed31_32 y_b; 434fcd2f4bfSAmy Zhang struct fixed31_32 y1_min; 435fcd2f4bfSAmy Zhang struct fixed31_32 y3_max; 436fcd2f4bfSAmy Zhang 4378f8372c7SKrunoslav Kovac int32_t region_start, region_end; 4388f8372c7SKrunoslav Kovac uint32_t i, j, k, seg_distr[NUMBER_REGIONS], increment, start_index, hw_points; 43923ae4f8eSAmy Zhang 440b310b081SHarry Wentland if (output_tf == NULL || regamma_params == NULL || output_tf->type == TF_TYPE_BYPASS) 44123ae4f8eSAmy Zhang return false; 44223ae4f8eSAmy Zhang 44323ae4f8eSAmy Zhang arr_points = regamma_params->arr_points; 44423ae4f8eSAmy Zhang rgb_resulted = regamma_params->rgb_resulted; 44523ae4f8eSAmy Zhang hw_points = 0; 446fcd2f4bfSAmy Zhang 447fcd2f4bfSAmy Zhang memset(regamma_params, 0, sizeof(struct pwl_params)); 448fcd2f4bfSAmy Zhang 449fcd2f4bfSAmy Zhang if (output_tf->tf == TRANSFER_FUNCTION_PQ) { 450534db198SAmy Zhang /* 16 segments 451fcd2f4bfSAmy Zhang * segments are from 2^-11 to 2^5 452fcd2f4bfSAmy Zhang */ 45308616da5SLeo (Sunpeng) Li region_start = -11; 45408616da5SLeo (Sunpeng) Li region_end = region_start + NUMBER_REGIONS; 455fcd2f4bfSAmy Zhang 4568f8372c7SKrunoslav Kovac for (i = 0; i < NUMBER_REGIONS; i++) 4578f8372c7SKrunoslav Kovac seg_distr[i] = 4; 458534db198SAmy Zhang 459fcd2f4bfSAmy Zhang } else { 460534db198SAmy Zhang /* 10 segments 461fc6de1c5SLeo (Sunpeng) Li * segment is from 2^-10 to 2^1 462fc6de1c5SLeo (Sunpeng) Li * We include an extra segment for range [2^0, 2^1). This is to 463fc6de1c5SLeo (Sunpeng) Li * ensure that colors with normalized values of 1 don't miss the 464fc6de1c5SLeo (Sunpeng) Li * LUT. 465fcd2f4bfSAmy Zhang */ 4668f8372c7SKrunoslav Kovac region_start = -10; 467fc6de1c5SLeo (Sunpeng) Li region_end = 1; 468534db198SAmy Zhang 4698f8372c7SKrunoslav Kovac seg_distr[0] = 4; 470534db198SAmy Zhang seg_distr[1] = 4; 471534db198SAmy Zhang seg_distr[2] = 4; 472534db198SAmy Zhang seg_distr[3] = 4; 473534db198SAmy Zhang seg_distr[4] = 4; 474534db198SAmy Zhang seg_distr[5] = 4; 475534db198SAmy Zhang seg_distr[6] = 4; 476534db198SAmy Zhang seg_distr[7] = 4; 4778f8372c7SKrunoslav Kovac seg_distr[8] = 4; 4788f8372c7SKrunoslav Kovac seg_distr[9] = 4; 479fc6de1c5SLeo (Sunpeng) Li seg_distr[10] = 0; 480534db198SAmy Zhang seg_distr[11] = -1; 481534db198SAmy Zhang seg_distr[12] = -1; 482534db198SAmy Zhang seg_distr[13] = -1; 483534db198SAmy Zhang seg_distr[14] = -1; 484534db198SAmy Zhang seg_distr[15] = -1; 485fcd2f4bfSAmy Zhang } 486fcd2f4bfSAmy Zhang 487534db198SAmy Zhang for (k = 0; k < 16; k++) { 488534db198SAmy Zhang if (seg_distr[k] != -1) 489534db198SAmy Zhang hw_points += (1 << seg_distr[k]); 490534db198SAmy Zhang } 491534db198SAmy Zhang 492fcd2f4bfSAmy Zhang j = 0; 4938f8372c7SKrunoslav Kovac for (k = 0; k < (region_end - region_start); k++) { 494ec47734aSLeo (Sunpeng) Li increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]); 4958f8372c7SKrunoslav Kovac start_index = (region_start + k + MAX_LOW_POINT) * 4968f8372c7SKrunoslav Kovac NUMBER_SW_SEGMENTS; 4978f8372c7SKrunoslav Kovac for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS; 4988f8372c7SKrunoslav Kovac i += increment) { 499534db198SAmy Zhang if (j == hw_points - 1) 500fcd2f4bfSAmy Zhang break; 501fcd2f4bfSAmy Zhang rgb_resulted[j].red = output_tf->tf_pts.red[i]; 502fcd2f4bfSAmy Zhang rgb_resulted[j].green = output_tf->tf_pts.green[i]; 503fcd2f4bfSAmy Zhang rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; 504fcd2f4bfSAmy Zhang j++; 505fcd2f4bfSAmy Zhang } 506534db198SAmy Zhang } 507534db198SAmy Zhang 508534db198SAmy Zhang /* last point */ 5098f8372c7SKrunoslav Kovac start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS; 510b310b081SHarry Wentland rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index]; 511b310b081SHarry Wentland rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index]; 512b310b081SHarry Wentland rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index]; 513fcd2f4bfSAmy Zhang 514eb0e5154SDmytro Laktyushkin arr_points[0].x = dc_fixpt_pow(dc_fixpt_from_int(2), 515eb0e5154SDmytro Laktyushkin dc_fixpt_from_int(region_start)); 516eb0e5154SDmytro Laktyushkin arr_points[1].x = dc_fixpt_pow(dc_fixpt_from_int(2), 517eb0e5154SDmytro Laktyushkin dc_fixpt_from_int(region_end)); 518fcd2f4bfSAmy Zhang 519fcd2f4bfSAmy Zhang y_r = rgb_resulted[0].red; 520fcd2f4bfSAmy Zhang y_g = rgb_resulted[0].green; 521fcd2f4bfSAmy Zhang y_b = rgb_resulted[0].blue; 522fcd2f4bfSAmy Zhang 523eb0e5154SDmytro Laktyushkin y1_min = dc_fixpt_min(y_r, dc_fixpt_min(y_g, y_b)); 524fcd2f4bfSAmy Zhang 525fcd2f4bfSAmy Zhang arr_points[0].y = y1_min; 526eb0e5154SDmytro Laktyushkin arr_points[0].slope = dc_fixpt_div(arr_points[0].y, 527fcd2f4bfSAmy Zhang arr_points[0].x); 528fcd2f4bfSAmy Zhang 529fcd2f4bfSAmy Zhang y_r = rgb_resulted[hw_points - 1].red; 530fcd2f4bfSAmy Zhang y_g = rgb_resulted[hw_points - 1].green; 531fcd2f4bfSAmy Zhang y_b = rgb_resulted[hw_points - 1].blue; 532fcd2f4bfSAmy Zhang 533fcd2f4bfSAmy Zhang /* see comment above, m_arrPoints[1].y should be the Y value for the 534fcd2f4bfSAmy Zhang * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) 535fcd2f4bfSAmy Zhang */ 536eb0e5154SDmytro Laktyushkin y3_max = dc_fixpt_max(y_r, dc_fixpt_max(y_g, y_b)); 537fcd2f4bfSAmy Zhang 538fcd2f4bfSAmy Zhang arr_points[1].y = y3_max; 539fcd2f4bfSAmy Zhang 540eb0e5154SDmytro Laktyushkin arr_points[1].slope = dc_fixpt_zero; 541fcd2f4bfSAmy Zhang 542fcd2f4bfSAmy Zhang if (output_tf->tf == TRANSFER_FUNCTION_PQ) { 543fcd2f4bfSAmy Zhang /* for PQ, we want to have a straight line from last HW X point, 544fcd2f4bfSAmy Zhang * and the slope to be such that we hit 1.0 at 10000 nits. 545fcd2f4bfSAmy Zhang */ 546eb0e5154SDmytro Laktyushkin const struct fixed31_32 end_value = dc_fixpt_from_int(125); 547fcd2f4bfSAmy Zhang 548eb0e5154SDmytro Laktyushkin arr_points[1].slope = dc_fixpt_div( 549eb0e5154SDmytro Laktyushkin dc_fixpt_sub(dc_fixpt_one, arr_points[1].y), 550eb0e5154SDmytro Laktyushkin dc_fixpt_sub(end_value, arr_points[1].x)); 551fcd2f4bfSAmy Zhang } 552fcd2f4bfSAmy Zhang 553fcd2f4bfSAmy Zhang regamma_params->hw_points_num = hw_points; 554fcd2f4bfSAmy Zhang 55569133b89SAric Cyr k = 0; 55669133b89SAric Cyr for (i = 1; i < 16; i++) { 557534db198SAmy Zhang if (seg_distr[k] != -1) { 558b310b081SHarry Wentland regamma_params->arr_curve_points[k].segments_num = seg_distr[k]; 559534db198SAmy Zhang regamma_params->arr_curve_points[i].offset = 560b310b081SHarry Wentland regamma_params->arr_curve_points[k].offset + (1 << seg_distr[k]); 561fcd2f4bfSAmy Zhang } 56269133b89SAric Cyr k++; 563534db198SAmy Zhang } 564534db198SAmy Zhang 565534db198SAmy Zhang if (seg_distr[k] != -1) 566b310b081SHarry Wentland regamma_params->arr_curve_points[k].segments_num = seg_distr[k]; 567fcd2f4bfSAmy Zhang 56823ae4f8eSAmy Zhang rgb = rgb_resulted; 56923ae4f8eSAmy Zhang rgb_plus_1 = rgb_resulted + 1; 570fcd2f4bfSAmy Zhang 571fcd2f4bfSAmy Zhang i = 1; 572fcd2f4bfSAmy Zhang 573fcd2f4bfSAmy Zhang while (i != hw_points + 1) { 574eb0e5154SDmytro Laktyushkin if (dc_fixpt_lt(rgb_plus_1->red, rgb->red)) 575fcd2f4bfSAmy Zhang rgb_plus_1->red = rgb->red; 576eb0e5154SDmytro Laktyushkin if (dc_fixpt_lt(rgb_plus_1->green, rgb->green)) 577fcd2f4bfSAmy Zhang rgb_plus_1->green = rgb->green; 578eb0e5154SDmytro Laktyushkin if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue)) 579fcd2f4bfSAmy Zhang rgb_plus_1->blue = rgb->blue; 580fcd2f4bfSAmy Zhang 581eb0e5154SDmytro Laktyushkin rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red); 582eb0e5154SDmytro Laktyushkin rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green); 583eb0e5154SDmytro Laktyushkin rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue); 584fcd2f4bfSAmy Zhang 585fcd2f4bfSAmy Zhang ++rgb_plus_1; 586fcd2f4bfSAmy Zhang ++rgb; 587fcd2f4bfSAmy Zhang ++i; 588fcd2f4bfSAmy Zhang } 589fcd2f4bfSAmy Zhang 590fcd2f4bfSAmy Zhang convert_to_custom_float(rgb_resulted, arr_points, hw_points); 591fcd2f4bfSAmy Zhang 592fcd2f4bfSAmy Zhang return true; 593fcd2f4bfSAmy Zhang } 594fcd2f4bfSAmy Zhang 595a6114e85SHarry Wentland static bool 596a6114e85SHarry Wentland dce110_set_output_transfer_func(struct pipe_ctx *pipe_ctx, 5970971c40eSHarry Wentland const struct dc_stream_state *stream) 59890e508baSAnthony Koo { 59986a66c4eSHarry Wentland struct transform *xfm = pipe_ctx->plane_res.xfm; 6004562236bSHarry Wentland 6017a09f5beSYue Hin Lau xfm->funcs->opp_power_on_regamma_lut(xfm, true); 6027a09f5beSYue Hin Lau xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; 6034562236bSHarry Wentland 6044fa086b9SLeo (Sunpeng) Li if (stream->out_transfer_func && 605efd52204SHarry Wentland stream->out_transfer_func->type == TF_TYPE_PREDEFINED && 606efd52204SHarry Wentland stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { 6077a09f5beSYue Hin Lau xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB); 608efd52204SHarry Wentland } else if (dce110_translate_regamma_to_hw_format(stream->out_transfer_func, 609efd52204SHarry Wentland &xfm->regamma_params)) { 6107a09f5beSYue Hin Lau xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params); 6117a09f5beSYue Hin Lau xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER); 6124562236bSHarry Wentland } else { 6137a09f5beSYue Hin Lau xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_BYPASS); 6144562236bSHarry Wentland } 6154562236bSHarry Wentland 6167a09f5beSYue Hin Lau xfm->funcs->opp_power_on_regamma_lut(xfm, false); 6174562236bSHarry Wentland 618cc0cb445SLeon Elazar return true; 6194562236bSHarry Wentland } 6204562236bSHarry Wentland 6214562236bSHarry Wentland void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) 6224562236bSHarry Wentland { 62302553f57SEric Bernstein bool is_hdmi_tmds; 6246f0db2dcSKrunoslav Kovac bool is_dp; 6256f0db2dcSKrunoslav Kovac 62686e2e1beSHersen Wu ASSERT(pipe_ctx->stream); 62786e2e1beSHersen Wu 6288e9c4c8cSHarry Wentland if (pipe_ctx->stream_res.stream_enc == NULL) 62986e2e1beSHersen Wu return; /* this is not root pipe */ 63086e2e1beSHersen Wu 63102553f57SEric Bernstein is_hdmi_tmds = dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal); 6326f0db2dcSKrunoslav Kovac is_dp = dc_is_dp_signal(pipe_ctx->stream->signal); 6336f0db2dcSKrunoslav Kovac 63402553f57SEric Bernstein if (!is_hdmi_tmds && !is_dp) 6356f0db2dcSKrunoslav Kovac return; 6366f0db2dcSKrunoslav Kovac 63702553f57SEric Bernstein if (is_hdmi_tmds) 6388e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets( 6398e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc, 64096c50c0dSHarry Wentland &pipe_ctx->stream_res.encoder_info_frame); 6416f0db2dcSKrunoslav Kovac else 6428e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets( 6438e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc, 64496c50c0dSHarry Wentland &pipe_ctx->stream_res.encoder_info_frame); 6454562236bSHarry Wentland } 6464562236bSHarry Wentland 6474562236bSHarry Wentland void dce110_enable_stream(struct pipe_ctx *pipe_ctx) 6484562236bSHarry Wentland { 6494562236bSHarry Wentland enum dc_lane_count lane_count = 650ceb3dbb4SJun Lei pipe_ctx->stream->link->cur_link_settings.lane_count; 6514562236bSHarry Wentland 6524fa086b9SLeo (Sunpeng) Li struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 653ceb3dbb4SJun Lei struct dc_link *link = pipe_ctx->stream->link; 6544562236bSHarry Wentland 655f215a57dSEric Yang 6564562236bSHarry Wentland uint32_t active_total_with_borders; 6574562236bSHarry Wentland uint32_t early_control = 0; 6586b670fa9SHarry Wentland struct timing_generator *tg = pipe_ctx->stream_res.tg; 6594562236bSHarry Wentland 660f215a57dSEric Yang /* For MST, there are multiply stream go to only one link. 661f215a57dSEric Yang * connect DIG back_end to front_end while enable_stream and 662f215a57dSEric Yang * disconnect them during disable_stream 663f215a57dSEric Yang * BY this, it is logic clean to separate stream and link */ 664f215a57dSEric Yang link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, 665f215a57dSEric Yang pipe_ctx->stream_res.stream_enc->id, true); 666f215a57dSEric Yang 667f215a57dSEric Yang /* update AVI info frame (HDMI, DP)*/ 668f215a57dSEric Yang /* TODO: FPGA may change to hwss.update_info_frame */ 6694562236bSHarry Wentland dce110_update_info_frame(pipe_ctx); 670f215a57dSEric Yang 6714562236bSHarry Wentland /* enable early control to avoid corruption on DP monitor*/ 6724562236bSHarry Wentland active_total_with_borders = 6734562236bSHarry Wentland timing->h_addressable 6744562236bSHarry Wentland + timing->h_border_left 6754562236bSHarry Wentland + timing->h_border_right; 6764562236bSHarry Wentland 6774562236bSHarry Wentland if (lane_count != 0) 6784562236bSHarry Wentland early_control = active_total_with_borders % lane_count; 6794562236bSHarry Wentland 6804562236bSHarry Wentland if (early_control == 0) 6814562236bSHarry Wentland early_control = lane_count; 6824562236bSHarry Wentland 6834562236bSHarry Wentland tg->funcs->set_early_control(tg, early_control); 6844562236bSHarry Wentland 6854562236bSHarry Wentland /* enable audio only within mode set */ 686afaacef4SHarry Wentland if (pipe_ctx->stream_res.audio != NULL) { 6874562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal)) 6888e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc); 6894562236bSHarry Wentland } 6904562236bSHarry Wentland 691f215a57dSEric Yang 692f215a57dSEric Yang 6934562236bSHarry Wentland 6944562236bSHarry Wentland } 6954562236bSHarry Wentland 6965eefbc40SYue Hin Lau /*todo: cloned in stream enc, fix*/ 6975eefbc40SYue Hin Lau static bool is_panel_backlight_on(struct dce_hwseq *hws) 6985eefbc40SYue Hin Lau { 6995eefbc40SYue Hin Lau uint32_t value; 7005eefbc40SYue Hin Lau 7015eefbc40SYue Hin Lau REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value); 7025eefbc40SYue Hin Lau 7035eefbc40SYue Hin Lau return value; 7045eefbc40SYue Hin Lau } 7055eefbc40SYue Hin Lau 70687401969SAndrew Jiang static bool is_panel_powered_on(struct dce_hwseq *hws) 70787401969SAndrew Jiang { 708d03f3f63SEric Yang uint32_t pwr_seq_state, dig_on, dig_on_ovrd; 70987401969SAndrew Jiang 710d03f3f63SEric Yang 711d03f3f63SEric Yang REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &pwr_seq_state); 712d03f3f63SEric Yang 713d03f3f63SEric Yang REG_GET_2(LVTMA_PWRSEQ_CNTL, LVTMA_DIGON, &dig_on, LVTMA_DIGON_OVRD, &dig_on_ovrd); 714d03f3f63SEric Yang 715d03f3f63SEric Yang return (pwr_seq_state == 1) || (dig_on == 1 && dig_on_ovrd == 1); 71687401969SAndrew Jiang } 71787401969SAndrew Jiang 7185eefbc40SYue Hin Lau static enum bp_result link_transmitter_control( 71987401969SAndrew Jiang struct dc_bios *bios, 7205eefbc40SYue Hin Lau struct bp_transmitter_control *cntl) 7215eefbc40SYue Hin Lau { 7225eefbc40SYue Hin Lau enum bp_result result; 7235eefbc40SYue Hin Lau 72487401969SAndrew Jiang result = bios->funcs->transmitter_control(bios, cntl); 7255eefbc40SYue Hin Lau 7265eefbc40SYue Hin Lau return result; 7275eefbc40SYue Hin Lau } 7285eefbc40SYue Hin Lau 72987401969SAndrew Jiang /* 73087401969SAndrew Jiang * @brief 73187401969SAndrew Jiang * eDP only. 73287401969SAndrew Jiang */ 73387401969SAndrew Jiang void hwss_edp_wait_for_hpd_ready( 734069d418fSAndrew Jiang struct dc_link *link, 73587401969SAndrew Jiang bool power_up) 73687401969SAndrew Jiang { 737069d418fSAndrew Jiang struct dc_context *ctx = link->ctx; 738069d418fSAndrew Jiang struct graphics_object_id connector = link->link_enc->connector; 73987401969SAndrew Jiang struct gpio *hpd; 74087401969SAndrew Jiang bool edp_hpd_high = false; 74187401969SAndrew Jiang uint32_t time_elapsed = 0; 74287401969SAndrew Jiang uint32_t timeout = power_up ? 74387401969SAndrew Jiang PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT; 74487401969SAndrew Jiang 74587401969SAndrew Jiang if (dal_graphics_object_id_get_connector_id(connector) 74687401969SAndrew Jiang != CONNECTOR_ID_EDP) { 74787401969SAndrew Jiang BREAK_TO_DEBUGGER(); 74887401969SAndrew Jiang return; 74987401969SAndrew Jiang } 75087401969SAndrew Jiang 75187401969SAndrew Jiang if (!power_up) 75287401969SAndrew Jiang /* 75387401969SAndrew Jiang * From KV, we will not HPD low after turning off VCC - 75487401969SAndrew Jiang * instead, we will check the SW timer in power_up(). 75587401969SAndrew Jiang */ 75687401969SAndrew Jiang return; 75787401969SAndrew Jiang 75887401969SAndrew Jiang /* 75987401969SAndrew Jiang * When we power on/off the eDP panel, 76087401969SAndrew Jiang * we need to wait until SENSE bit is high/low. 76187401969SAndrew Jiang */ 76287401969SAndrew Jiang 76387401969SAndrew Jiang /* obtain HPD */ 76487401969SAndrew Jiang /* TODO what to do with this? */ 76587401969SAndrew Jiang hpd = get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service); 76687401969SAndrew Jiang 76787401969SAndrew Jiang if (!hpd) { 76887401969SAndrew Jiang BREAK_TO_DEBUGGER(); 76987401969SAndrew Jiang return; 77087401969SAndrew Jiang } 77187401969SAndrew Jiang 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 80187401969SAndrew Jiang void hwss_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 dce_hwseq *hwseq = ctx->dc->hwseq; 80787401969SAndrew Jiang struct bp_transmitter_control cntl = { 0 }; 80887401969SAndrew Jiang enum bp_result bp_result; 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 81787401969SAndrew Jiang if (power_up != is_panel_powered_on(hwseq)) { 81887401969SAndrew Jiang /* Send VBIOS command to prompt eDP panel power */ 81978d5d04dSCharlene Liu if (power_up) { 82078d5d04dSCharlene Liu unsigned long long current_ts = dm_get_timestamp(ctx); 82178d5d04dSCharlene Liu unsigned long long duration_in_ms = 82293ed1814SHugo Hu div64_u64(dm_get_elapse_time_in_ns( 82378d5d04dSCharlene Liu ctx, 82478d5d04dSCharlene Liu current_ts, 82593ed1814SHugo Hu link->link_trace.time_stamp.edp_poweroff), 1000000); 82678d5d04dSCharlene Liu unsigned long long wait_time_ms = 0; 82778d5d04dSCharlene Liu 82878d5d04dSCharlene Liu /* max 500ms from LCDVDD off to on */ 8296c4fff06SYue Hin Lau unsigned long long edp_poweroff_time_ms = 500; 830ff587987SHugo Hu 8316c4fff06SYue Hin Lau if (link->local_sink != NULL) 8326c4fff06SYue Hin Lau edp_poweroff_time_ms = 8336c4fff06SYue Hin Lau 500 + link->local_sink->edid_caps.panel_patch.extra_t12_ms; 83478d5d04dSCharlene Liu if (link->link_trace.time_stamp.edp_poweroff == 0) 835ff587987SHugo Hu wait_time_ms = edp_poweroff_time_ms; 836ff587987SHugo Hu else if (duration_in_ms < edp_poweroff_time_ms) 837ff587987SHugo Hu wait_time_ms = edp_poweroff_time_ms - duration_in_ms; 83878d5d04dSCharlene Liu 83978d5d04dSCharlene Liu if (wait_time_ms) { 84078d5d04dSCharlene Liu msleep(wait_time_ms); 84178d5d04dSCharlene Liu dm_output_to_console("%s: wait %lld ms to power on eDP.\n", 84278d5d04dSCharlene Liu __func__, wait_time_ms); 84378d5d04dSCharlene Liu } 84478d5d04dSCharlene Liu 84578d5d04dSCharlene Liu } 84687401969SAndrew Jiang 8471296423bSBhawanpreet Lakha DC_LOG_HW_RESUME_S3( 84887401969SAndrew Jiang "%s: Panel Power action: %s\n", 84987401969SAndrew Jiang __func__, (power_up ? "On":"Off")); 85087401969SAndrew Jiang 85187401969SAndrew Jiang cntl.action = power_up ? 85287401969SAndrew Jiang TRANSMITTER_CONTROL_POWER_ON : 85387401969SAndrew Jiang TRANSMITTER_CONTROL_POWER_OFF; 854069d418fSAndrew Jiang cntl.transmitter = link->link_enc->transmitter; 855069d418fSAndrew Jiang cntl.connector_obj_id = link->link_enc->connector; 85687401969SAndrew Jiang cntl.coherent = false; 85787401969SAndrew Jiang cntl.lanes_number = LANE_COUNT_FOUR; 858069d418fSAndrew Jiang cntl.hpd_sel = link->link_enc->hpd_source; 85987401969SAndrew Jiang bp_result = link_transmitter_control(ctx->dc_bios, &cntl); 86087401969SAndrew Jiang 86178d5d04dSCharlene Liu if (!power_up) 86278d5d04dSCharlene Liu /*save driver power off time stamp*/ 86378d5d04dSCharlene Liu link->link_trace.time_stamp.edp_poweroff = dm_get_timestamp(ctx); 86478d5d04dSCharlene Liu else 86578d5d04dSCharlene Liu link->link_trace.time_stamp.edp_poweron = dm_get_timestamp(ctx); 86678d5d04dSCharlene Liu 86787401969SAndrew Jiang if (bp_result != BP_RESULT_OK) 8681296423bSBhawanpreet Lakha DC_LOG_ERROR( 86987401969SAndrew Jiang "%s: Panel Power bp_result: %d\n", 87087401969SAndrew Jiang __func__, bp_result); 87187401969SAndrew Jiang } else { 8721296423bSBhawanpreet Lakha DC_LOG_HW_RESUME_S3( 87387401969SAndrew Jiang "%s: Skipping Panel Power action: %s\n", 87487401969SAndrew Jiang __func__, (power_up ? "On":"Off")); 87587401969SAndrew Jiang } 87687401969SAndrew Jiang } 8775eefbc40SYue Hin Lau 8785eefbc40SYue Hin Lau /*todo: cloned in stream enc, fix*/ 8795eefbc40SYue Hin Lau /* 8805eefbc40SYue Hin Lau * @brief 8815eefbc40SYue Hin Lau * eDP only. Control the backlight of the eDP panel 8825eefbc40SYue Hin Lau */ 88387401969SAndrew Jiang void hwss_edp_backlight_control( 8845eefbc40SYue Hin Lau struct dc_link *link, 8855eefbc40SYue Hin Lau bool enable) 8865eefbc40SYue Hin Lau { 887069d418fSAndrew Jiang struct dc_context *ctx = link->ctx; 888069d418fSAndrew Jiang struct dce_hwseq *hws = ctx->dc->hwseq; 8895eefbc40SYue Hin Lau struct bp_transmitter_control cntl = { 0 }; 8905eefbc40SYue Hin Lau 891069d418fSAndrew Jiang if (dal_graphics_object_id_get_connector_id(link->link_enc->connector) 8925eefbc40SYue Hin Lau != CONNECTOR_ID_EDP) { 8935eefbc40SYue Hin Lau BREAK_TO_DEBUGGER(); 8945eefbc40SYue Hin Lau return; 8955eefbc40SYue Hin Lau } 8965eefbc40SYue Hin Lau 8975eefbc40SYue Hin Lau if (enable && is_panel_backlight_on(hws)) { 8981296423bSBhawanpreet Lakha DC_LOG_HW_RESUME_S3( 8995eefbc40SYue Hin Lau "%s: panel already powered up. Do nothing.\n", 9005eefbc40SYue Hin Lau __func__); 9015eefbc40SYue Hin Lau return; 9025eefbc40SYue Hin Lau } 9035eefbc40SYue Hin Lau 9045eefbc40SYue Hin Lau /* Send VBIOS command to control eDP panel backlight */ 9055eefbc40SYue Hin Lau 9061296423bSBhawanpreet Lakha DC_LOG_HW_RESUME_S3( 9075eefbc40SYue Hin Lau "%s: backlight action: %s\n", 9085eefbc40SYue Hin Lau __func__, (enable ? "On":"Off")); 9095eefbc40SYue Hin Lau 9105eefbc40SYue Hin Lau cntl.action = enable ? 9115eefbc40SYue Hin Lau TRANSMITTER_CONTROL_BACKLIGHT_ON : 9125eefbc40SYue Hin Lau TRANSMITTER_CONTROL_BACKLIGHT_OFF; 91387401969SAndrew Jiang 9145eefbc40SYue Hin Lau /*cntl.engine_id = ctx->engine;*/ 9155eefbc40SYue Hin Lau cntl.transmitter = link->link_enc->transmitter; 9165eefbc40SYue Hin Lau cntl.connector_obj_id = link->link_enc->connector; 9175eefbc40SYue Hin Lau /*todo: unhardcode*/ 9185eefbc40SYue Hin Lau cntl.lanes_number = LANE_COUNT_FOUR; 9195eefbc40SYue Hin Lau cntl.hpd_sel = link->link_enc->hpd_source; 920cf1835f0SCharlene Liu cntl.signal = SIGNAL_TYPE_EDP; 9215eefbc40SYue Hin Lau 9225eefbc40SYue Hin Lau /* For eDP, the following delays might need to be considered 9235eefbc40SYue Hin Lau * after link training completed: 9245eefbc40SYue Hin Lau * idle period - min. accounts for required BS-Idle pattern, 9255eefbc40SYue Hin Lau * max. allows for source frame synchronization); 9265eefbc40SYue Hin Lau * 50 msec max. delay from valid video data from source 9275eefbc40SYue Hin Lau * to video on dislpay or backlight enable. 9285eefbc40SYue Hin Lau * 9295eefbc40SYue Hin Lau * Disable the delay for now. 9305eefbc40SYue Hin Lau * Enable it in the future if necessary. 9315eefbc40SYue Hin Lau */ 9325eefbc40SYue Hin Lau /* dc_service_sleep_in_milliseconds(50); */ 9335180d4a4SCharlene Liu /*edp 1.2*/ 9345180d4a4SCharlene Liu if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) 9355180d4a4SCharlene Liu edp_receiver_ready_T7(link); 936069d418fSAndrew Jiang link_transmitter_control(ctx->dc_bios, &cntl); 93769b9723aSCharlene Liu /*edp 1.2*/ 9385180d4a4SCharlene Liu if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF) 93969b9723aSCharlene Liu edp_receiver_ready_T9(link); 9405eefbc40SYue Hin Lau } 9415eefbc40SYue Hin Lau 94276d981a9SAlex Deucher // Static helper function which calls the correct function 94376d981a9SAlex Deucher // based on pp_smu version 94476d981a9SAlex Deucher static void set_pme_wa_enable_by_version(struct dc *dc) 94576d981a9SAlex Deucher { 94676d981a9SAlex Deucher struct pp_smu_funcs *pp_smu = NULL; 94776d981a9SAlex Deucher 94876d981a9SAlex Deucher if (dc->res_pool->pp_smu) 94976d981a9SAlex Deucher pp_smu = dc->res_pool->pp_smu; 95076d981a9SAlex Deucher 95176d981a9SAlex Deucher if (pp_smu) { 95276d981a9SAlex Deucher if (pp_smu->ctx.ver == PP_SMU_VER_RV && pp_smu->rv_funcs.set_pme_wa_enable) 95376d981a9SAlex Deucher pp_smu->rv_funcs.set_pme_wa_enable(&(pp_smu->ctx)); 95476d981a9SAlex Deucher } 95576d981a9SAlex Deucher } 95676d981a9SAlex Deucher 9571a05873fSAnthony Koo void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx) 9584562236bSHarry Wentland { 9591a05873fSAnthony Koo /* notify audio driver for audio modes of monitor */ 9600f1a6ad7SJun Lei struct dc *core_dc = pipe_ctx->stream->ctx->dc; 9610f1a6ad7SJun Lei struct pp_smu_funcs *pp_smu = NULL; 9621a05873fSAnthony Koo unsigned int i, num_audio = 1; 9631a05873fSAnthony Koo 9640a32df9cSEryk Brol if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == true) 9650a32df9cSEryk Brol return; 9660a32df9cSEryk Brol 9670f1a6ad7SJun Lei if (core_dc->res_pool->pp_smu) 9680f1a6ad7SJun Lei pp_smu = core_dc->res_pool->pp_smu; 9690f1a6ad7SJun Lei 9701a05873fSAnthony Koo if (pipe_ctx->stream_res.audio) { 9711a05873fSAnthony Koo for (i = 0; i < MAX_PIPES; i++) { 9721a05873fSAnthony Koo /*current_state not updated yet*/ 9731a05873fSAnthony Koo if (core_dc->current_state->res_ctx.pipe_ctx[i].stream_res.audio != NULL) 9741a05873fSAnthony Koo num_audio++; 9751a05873fSAnthony Koo } 9761a05873fSAnthony Koo 9771a05873fSAnthony Koo pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio); 9781a05873fSAnthony Koo 97976d981a9SAlex Deucher if (num_audio >= 1 && pp_smu != NULL) 9801a05873fSAnthony Koo /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ 98176d981a9SAlex Deucher set_pme_wa_enable_by_version(core_dc); 9821a05873fSAnthony Koo /* un-mute audio */ 9831a05873fSAnthony Koo /* TODO: audio should be per stream rather than per link */ 9841a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( 9851a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc, false); 9860a32df9cSEryk Brol if (pipe_ctx->stream_res.audio) 9870a32df9cSEryk Brol pipe_ctx->stream_res.audio->enabled = true; 9881a05873fSAnthony Koo } 9891a05873fSAnthony Koo } 9901a05873fSAnthony Koo 9911a05873fSAnthony Koo void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option) 9921a05873fSAnthony Koo { 9934176664bSCharlene Liu struct dc *dc = pipe_ctx->stream->ctx->dc; 9940f1a6ad7SJun Lei struct pp_smu_funcs *pp_smu = NULL; 9954562236bSHarry Wentland 9960a32df9cSEryk Brol if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == false) 9970a32df9cSEryk Brol return; 9980a32df9cSEryk Brol 9992b7c97d6SCharlene Liu pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( 10002b7c97d6SCharlene Liu pipe_ctx->stream_res.stream_enc, true); 1001afaacef4SHarry Wentland if (pipe_ctx->stream_res.audio) { 10020f1a6ad7SJun Lei if (dc->res_pool->pp_smu) 10030f1a6ad7SJun Lei pp_smu = dc->res_pool->pp_smu; 1004070fe724SCharlene Liu 10057c357e61SCharlene Liu if (option != KEEP_ACQUIRED_RESOURCE || 10060f1a6ad7SJun Lei !dc->debug.az_endpoint_mute_only) 10077c357e61SCharlene Liu /*only disalbe az_endpoint if power down or free*/ 1008afaacef4SHarry Wentland pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); 10094562236bSHarry Wentland 10104562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal)) 10118e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( 10128e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc); 10134562236bSHarry Wentland else 10148e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( 10158e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc); 10164176664bSCharlene Liu /*don't free audio if it is from retrain or internal disable stream*/ 10174176664bSCharlene Liu if (option == FREE_ACQUIRED_RESOURCE && dc->caps.dynamic_audio == true) { 10184176664bSCharlene Liu /*we have to dynamic arbitrate the audio endpoints*/ 10194176664bSCharlene Liu /*we free the resource, need reset is_audio_acquired*/ 10204176664bSCharlene Liu update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false); 1021fb5fb63aSCharlene Liu pipe_ctx->stream_res.audio = NULL; 10224176664bSCharlene Liu } 102376d981a9SAlex Deucher if (pp_smu != NULL) 1024070fe724SCharlene Liu /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ 102576d981a9SAlex Deucher set_pme_wa_enable_by_version(dc); 10264562236bSHarry Wentland 10274562236bSHarry Wentland /* TODO: notify audio driver for if audio modes list changed 10284562236bSHarry Wentland * add audio mode list change flag */ 10294562236bSHarry Wentland /* dal_audio_disable_azalia_audio_jack_presence(stream->audio, 10304562236bSHarry Wentland * stream->stream_engine_id); 10314562236bSHarry Wentland */ 10320a32df9cSEryk Brol if (pipe_ctx->stream_res.audio) 10330a32df9cSEryk Brol pipe_ctx->stream_res.audio->enabled = false; 10344562236bSHarry Wentland } 10351a05873fSAnthony Koo } 10364562236bSHarry Wentland 10371a05873fSAnthony Koo void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) 10381a05873fSAnthony Koo { 10391a05873fSAnthony Koo struct dc_stream_state *stream = pipe_ctx->stream; 1040ceb3dbb4SJun Lei struct dc_link *link = stream->link; 10411a05873fSAnthony Koo struct dc *dc = pipe_ctx->stream->ctx->dc; 10421a05873fSAnthony Koo 104302553f57SEric Bernstein if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) 10441a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets( 10451a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc); 10461a05873fSAnthony Koo 10471a05873fSAnthony Koo if (dc_is_dp_signal(pipe_ctx->stream->signal)) 10481a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets( 10491a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc); 10501a05873fSAnthony Koo 10511a05873fSAnthony Koo dc->hwss.disable_audio_stream(pipe_ctx, option); 1052904623eeSYongqiang Sun 10534562236bSHarry Wentland link->link_enc->funcs->connect_dig_be_to_fe( 10544562236bSHarry Wentland link->link_enc, 10558e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->id, 10564562236bSHarry Wentland false); 10574562236bSHarry Wentland 10584562236bSHarry Wentland } 10594562236bSHarry Wentland 10604562236bSHarry Wentland void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, 10614562236bSHarry Wentland struct dc_link_settings *link_settings) 10624562236bSHarry Wentland { 10634562236bSHarry Wentland struct encoder_unblank_param params = { { 0 } }; 106441b49742SCharlene Liu struct dc_stream_state *stream = pipe_ctx->stream; 1065ceb3dbb4SJun Lei struct dc_link *link = stream->link; 10664562236bSHarry Wentland 10674562236bSHarry Wentland /* only 3 items below are used by unblank */ 10687fe538a4SCharlene Liu params.timing = pipe_ctx->stream->timing; 10694562236bSHarry Wentland params.link_settings.link_rate = link_settings->link_rate; 107041b49742SCharlene Liu 107141b49742SCharlene Liu if (dc_is_dp_signal(pipe_ctx->stream->signal)) 10728e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms); 107341b49742SCharlene Liu 107414d6f644SYongqiang Sun if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { 107541b49742SCharlene Liu link->dc->hwss.edp_backlight_control(link, true); 107614d6f644SYongqiang Sun } 107741b49742SCharlene Liu } 10782c850b7bSDmytro Laktyushkin 107941b49742SCharlene Liu void dce110_blank_stream(struct pipe_ctx *pipe_ctx) 108041b49742SCharlene Liu { 108141b49742SCharlene Liu struct dc_stream_state *stream = pipe_ctx->stream; 1082ceb3dbb4SJun Lei struct dc_link *link = stream->link; 108341b49742SCharlene Liu 1084ab892598SRoman Li if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { 108541b49742SCharlene Liu link->dc->hwss.edp_backlight_control(link, false); 1086ab892598SRoman Li dc_link_set_abm_disable(link); 1087ab892598SRoman Li } 108841b49742SCharlene Liu 108941b49742SCharlene Liu if (dc_is_dp_signal(pipe_ctx->stream->signal)) 109041b49742SCharlene Liu pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); 10914562236bSHarry Wentland } 10924562236bSHarry Wentland 109315e17335SCharlene Liu 109415e17335SCharlene Liu void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) 109515e17335SCharlene Liu { 10968e9c4c8cSHarry Wentland if (pipe_ctx != NULL && pipe_ctx->stream_res.stream_enc != NULL) 10978e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->set_avmute(pipe_ctx->stream_res.stream_enc, enable); 109815e17335SCharlene Liu } 109915e17335SCharlene Liu 11004562236bSHarry Wentland static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id) 11014562236bSHarry Wentland { 11024562236bSHarry Wentland switch (crtc_id) { 11034562236bSHarry Wentland case CONTROLLER_ID_D0: 11044562236bSHarry Wentland return DTO_SOURCE_ID0; 11054562236bSHarry Wentland case CONTROLLER_ID_D1: 11064562236bSHarry Wentland return DTO_SOURCE_ID1; 11074562236bSHarry Wentland case CONTROLLER_ID_D2: 11084562236bSHarry Wentland return DTO_SOURCE_ID2; 11094562236bSHarry Wentland case CONTROLLER_ID_D3: 11104562236bSHarry Wentland return DTO_SOURCE_ID3; 11114562236bSHarry Wentland case CONTROLLER_ID_D4: 11124562236bSHarry Wentland return DTO_SOURCE_ID4; 11134562236bSHarry Wentland case CONTROLLER_ID_D5: 11144562236bSHarry Wentland return DTO_SOURCE_ID5; 11154562236bSHarry Wentland default: 11164562236bSHarry Wentland return DTO_SOURCE_UNKNOWN; 11174562236bSHarry Wentland } 11184562236bSHarry Wentland } 11194562236bSHarry Wentland 11204562236bSHarry Wentland static void build_audio_output( 1121ab8db3e1SAndrey Grodzovsky struct dc_state *state, 11224562236bSHarry Wentland const struct pipe_ctx *pipe_ctx, 11234562236bSHarry Wentland struct audio_output *audio_output) 11244562236bSHarry Wentland { 11250971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 11268e9c4c8cSHarry Wentland audio_output->engine_id = pipe_ctx->stream_res.stream_enc->id; 11274562236bSHarry Wentland 11284562236bSHarry Wentland audio_output->signal = pipe_ctx->stream->signal; 11294562236bSHarry Wentland 11304562236bSHarry Wentland /* audio_crtc_info */ 11314562236bSHarry Wentland 11324562236bSHarry Wentland audio_output->crtc_info.h_total = 11334fa086b9SLeo (Sunpeng) Li stream->timing.h_total; 11344562236bSHarry Wentland 11354562236bSHarry Wentland /* 11364562236bSHarry Wentland * Audio packets are sent during actual CRTC blank physical signal, we 11374562236bSHarry Wentland * need to specify actual active signal portion 11384562236bSHarry Wentland */ 11394562236bSHarry Wentland audio_output->crtc_info.h_active = 11404fa086b9SLeo (Sunpeng) Li stream->timing.h_addressable 11414fa086b9SLeo (Sunpeng) Li + stream->timing.h_border_left 11424fa086b9SLeo (Sunpeng) Li + stream->timing.h_border_right; 11434562236bSHarry Wentland 11444562236bSHarry Wentland audio_output->crtc_info.v_active = 11454fa086b9SLeo (Sunpeng) Li stream->timing.v_addressable 11464fa086b9SLeo (Sunpeng) Li + stream->timing.v_border_top 11474fa086b9SLeo (Sunpeng) Li + stream->timing.v_border_bottom; 11484562236bSHarry Wentland 11494562236bSHarry Wentland audio_output->crtc_info.pixel_repetition = 1; 11504562236bSHarry Wentland 11514562236bSHarry Wentland audio_output->crtc_info.interlaced = 11524fa086b9SLeo (Sunpeng) Li stream->timing.flags.INTERLACE; 11534562236bSHarry Wentland 11544562236bSHarry Wentland audio_output->crtc_info.refresh_rate = 1155380604e2SKen Chalmers (stream->timing.pix_clk_100hz*10000)/ 11564fa086b9SLeo (Sunpeng) Li (stream->timing.h_total*stream->timing.v_total); 11574562236bSHarry Wentland 11584562236bSHarry Wentland audio_output->crtc_info.color_depth = 11594fa086b9SLeo (Sunpeng) Li stream->timing.display_color_depth; 11604562236bSHarry Wentland 11614562236bSHarry Wentland audio_output->crtc_info.requested_pixel_clock = 1162380604e2SKen Chalmers pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10; 11634562236bSHarry Wentland 11644562236bSHarry Wentland audio_output->crtc_info.calculated_pixel_clock = 1165380604e2SKen Chalmers pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10; 11664562236bSHarry Wentland 116787b58768SCharlene Liu /*for HDMI, audio ACR is with deep color ratio factor*/ 116887b58768SCharlene Liu if (dc_is_hdmi_signal(pipe_ctx->stream->signal) && 116987b58768SCharlene Liu audio_output->crtc_info.requested_pixel_clock == 1170380604e2SKen Chalmers (stream->timing.pix_clk_100hz / 10)) { 117110688217SHarry Wentland if (pipe_ctx->stream_res.pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) { 117287b58768SCharlene Liu audio_output->crtc_info.requested_pixel_clock = 117387b58768SCharlene Liu audio_output->crtc_info.requested_pixel_clock/2; 117487b58768SCharlene Liu audio_output->crtc_info.calculated_pixel_clock = 1175380604e2SKen Chalmers pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz/20; 117687b58768SCharlene Liu 117787b58768SCharlene Liu } 117887b58768SCharlene Liu } 117987b58768SCharlene Liu 11804562236bSHarry Wentland if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT || 11814562236bSHarry Wentland pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { 11824562236bSHarry Wentland audio_output->pll_info.dp_dto_source_clock_in_khz = 11830de34efcSDmytro Laktyushkin state->clk_mgr->funcs->get_dp_ref_clk_frequency( 11840de34efcSDmytro Laktyushkin state->clk_mgr); 11854562236bSHarry Wentland } 11864562236bSHarry Wentland 11874562236bSHarry Wentland audio_output->pll_info.feed_back_divider = 11884562236bSHarry Wentland pipe_ctx->pll_settings.feedback_divider; 11894562236bSHarry Wentland 11904562236bSHarry Wentland audio_output->pll_info.dto_source = 11914562236bSHarry Wentland translate_to_dto_source( 1192e07f541fSYongqiang Sun pipe_ctx->stream_res.tg->inst + 1); 11934562236bSHarry Wentland 11944562236bSHarry Wentland /* TODO hard code to enable for now. Need get from stream */ 11954562236bSHarry Wentland audio_output->pll_info.ss_enabled = true; 11964562236bSHarry Wentland 11974562236bSHarry Wentland audio_output->pll_info.ss_percentage = 11984562236bSHarry Wentland pipe_ctx->pll_settings.ss_percentage; 11994562236bSHarry Wentland } 12004562236bSHarry Wentland 12014562236bSHarry Wentland static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx, 12024562236bSHarry Wentland struct tg_color *color) 12034562236bSHarry Wentland { 12042a54bd6eSJerry (Fangzhi) Zuo uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->stream_res.tg->inst) / 4; 12054562236bSHarry Wentland 12066702a9acSHarry Wentland switch (pipe_ctx->plane_res.scl_data.format) { 12074562236bSHarry Wentland case PIXEL_FORMAT_ARGB8888: 12084562236bSHarry Wentland /* set boarder color to red */ 12094562236bSHarry Wentland color->color_r_cr = color_value; 12104562236bSHarry Wentland break; 12114562236bSHarry Wentland 12124562236bSHarry Wentland case PIXEL_FORMAT_ARGB2101010: 12134562236bSHarry Wentland /* set boarder color to blue */ 12144562236bSHarry Wentland color->color_b_cb = color_value; 12154562236bSHarry Wentland break; 121687449a90SAnthony Koo case PIXEL_FORMAT_420BPP8: 12174562236bSHarry Wentland /* set boarder color to green */ 12184562236bSHarry Wentland color->color_g_y = color_value; 12194562236bSHarry Wentland break; 122087449a90SAnthony Koo case PIXEL_FORMAT_420BPP10: 122187449a90SAnthony Koo /* set boarder color to yellow */ 122287449a90SAnthony Koo color->color_g_y = color_value; 122387449a90SAnthony Koo color->color_r_cr = color_value; 122487449a90SAnthony Koo break; 12254562236bSHarry Wentland case PIXEL_FORMAT_FP16: 12264562236bSHarry Wentland /* set boarder color to white */ 12274562236bSHarry Wentland color->color_r_cr = color_value; 12284562236bSHarry Wentland color->color_b_cb = color_value; 12294562236bSHarry Wentland color->color_g_y = color_value; 12304562236bSHarry Wentland break; 12314562236bSHarry Wentland default: 12324562236bSHarry Wentland break; 12334562236bSHarry Wentland } 12344562236bSHarry Wentland } 12354562236bSHarry Wentland 1236fb3466a4SBhawanpreet Lakha static void program_scaler(const struct dc *dc, 12374562236bSHarry Wentland const struct pipe_ctx *pipe_ctx) 12384562236bSHarry Wentland { 12394562236bSHarry Wentland struct tg_color color = {0}; 12404562236bSHarry Wentland 1241dc37a9a0SLeo (Sunpeng) Li #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 1242ff5ef992SAlex Deucher /* TOFPGA */ 124386a66c4eSHarry Wentland if (pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth == NULL) 1244ff5ef992SAlex Deucher return; 1245ff5ef992SAlex Deucher #endif 1246ff5ef992SAlex Deucher 1247bf53769dSGloria Li if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) 12484562236bSHarry Wentland get_surface_visual_confirm_color(pipe_ctx, &color); 12494562236bSHarry Wentland else 12504562236bSHarry Wentland color_space_to_black_color(dc, 12514fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->output_color_space, 12524562236bSHarry Wentland &color); 12534562236bSHarry Wentland 125486a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth( 125586a66c4eSHarry Wentland pipe_ctx->plane_res.xfm, 12566702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth, 12574562236bSHarry Wentland &pipe_ctx->stream->bit_depth_params); 12584562236bSHarry Wentland 125912750d16SEric Yang if (pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color) { 126012750d16SEric Yang /* 126112750d16SEric Yang * The way 420 is packed, 2 channels carry Y component, 1 channel 126212750d16SEric Yang * alternate between Cb and Cr, so both channels need the pixel 126312750d16SEric Yang * value for Y 126412750d16SEric Yang */ 126512750d16SEric Yang if (pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) 126612750d16SEric Yang color.color_r_cr = color.color_g_y; 126712750d16SEric Yang 12686b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color( 12696b670fa9SHarry Wentland pipe_ctx->stream_res.tg, 12704562236bSHarry Wentland &color); 127112750d16SEric Yang } 12724562236bSHarry Wentland 127386a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm, 12746702a9acSHarry Wentland &pipe_ctx->plane_res.scl_data); 12754562236bSHarry Wentland } 12764562236bSHarry Wentland 12773158223eSEric Bernstein static enum dc_status dce110_enable_stream_timing( 12784562236bSHarry Wentland struct pipe_ctx *pipe_ctx, 1279608ac7bbSJerry Zuo struct dc_state *context, 1280fb3466a4SBhawanpreet Lakha struct dc *dc) 12814562236bSHarry Wentland { 12820971c40eSHarry Wentland struct dc_stream_state *stream = pipe_ctx->stream; 1283608ac7bbSJerry Zuo struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx. 12844562236bSHarry Wentland pipe_ctx[pipe_ctx->pipe_idx]; 12854562236bSHarry Wentland struct tg_color black_color = {0}; 12864562236bSHarry Wentland 12874562236bSHarry Wentland if (!pipe_ctx_old->stream) { 12884562236bSHarry Wentland 12894562236bSHarry Wentland /* program blank color */ 12904562236bSHarry Wentland color_space_to_black_color(dc, 12914fa086b9SLeo (Sunpeng) Li stream->output_color_space, &black_color); 12926b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->set_blank_color( 12936b670fa9SHarry Wentland pipe_ctx->stream_res.tg, 12944562236bSHarry Wentland &black_color); 12954b5e7d62SHersen Wu 12964562236bSHarry Wentland /* 12974562236bSHarry Wentland * Must blank CRTC after disabling power gating and before any 12984562236bSHarry Wentland * programming, otherwise CRTC will be hung in bad state 12994562236bSHarry Wentland */ 13006b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true); 13014562236bSHarry Wentland 13024562236bSHarry Wentland if (false == pipe_ctx->clock_source->funcs->program_pix_clk( 13034562236bSHarry Wentland pipe_ctx->clock_source, 130410688217SHarry Wentland &pipe_ctx->stream_res.pix_clk_params, 13054562236bSHarry Wentland &pipe_ctx->pll_settings)) { 13064562236bSHarry Wentland BREAK_TO_DEBUGGER(); 13074562236bSHarry Wentland return DC_ERROR_UNEXPECTED; 13084562236bSHarry Wentland } 13094562236bSHarry Wentland 13106b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->program_timing( 13116b670fa9SHarry Wentland pipe_ctx->stream_res.tg, 13124fa086b9SLeo (Sunpeng) Li &stream->timing, 1313e7e10c46SDmytro Laktyushkin 0, 1314e7e10c46SDmytro Laktyushkin 0, 1315e7e10c46SDmytro Laktyushkin 0, 1316e7e10c46SDmytro Laktyushkin 0, 1317e7e10c46SDmytro Laktyushkin pipe_ctx->stream->signal, 13184562236bSHarry Wentland true); 13194562236bSHarry Wentland } 13204562236bSHarry Wentland 13214562236bSHarry Wentland if (!pipe_ctx_old->stream) { 13226b670fa9SHarry Wentland if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc( 13236b670fa9SHarry Wentland pipe_ctx->stream_res.tg)) { 13244562236bSHarry Wentland BREAK_TO_DEBUGGER(); 13254562236bSHarry Wentland return DC_ERROR_UNEXPECTED; 13264562236bSHarry Wentland } 13274562236bSHarry Wentland } 13284562236bSHarry Wentland 13294562236bSHarry Wentland return DC_OK; 13304562236bSHarry Wentland } 13314562236bSHarry Wentland 13324562236bSHarry Wentland static enum dc_status apply_single_controller_ctx_to_hw( 13334562236bSHarry Wentland struct pipe_ctx *pipe_ctx, 1334608ac7bbSJerry Zuo struct dc_state *context, 1335fb3466a4SBhawanpreet Lakha struct dc *dc) 13364562236bSHarry Wentland { 13370971c40eSHarry Wentland struct dc_stream_state *stream = pipe_ctx->stream; 13389c0fb8d4SAnthony Koo struct drr_params params = {0}; 13399c0fb8d4SAnthony Koo unsigned int event_triggers = 0; 13404562236bSHarry Wentland 1341240d09d0SGary Kattan if (dc->hwss.disable_stream_gating) { 1342240d09d0SGary Kattan dc->hwss.disable_stream_gating(dc, pipe_ctx); 1343240d09d0SGary Kattan } 1344240d09d0SGary Kattan 13451a05873fSAnthony Koo if (pipe_ctx->stream_res.audio != NULL) { 13461a05873fSAnthony Koo struct audio_output audio_output; 13471a05873fSAnthony Koo 13481a05873fSAnthony Koo build_audio_output(context, pipe_ctx, &audio_output); 13491a05873fSAnthony Koo 13501a05873fSAnthony Koo if (dc_is_dp_signal(pipe_ctx->stream->signal)) 13511a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( 13521a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc, 13531a05873fSAnthony Koo pipe_ctx->stream_res.audio->inst, 13541a05873fSAnthony Koo &pipe_ctx->stream->audio_info); 13551a05873fSAnthony Koo else 13561a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup( 13571a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc, 13581a05873fSAnthony Koo pipe_ctx->stream_res.audio->inst, 13591a05873fSAnthony Koo &pipe_ctx->stream->audio_info, 13601a05873fSAnthony Koo &audio_output.crtc_info); 13611a05873fSAnthony Koo 13621a05873fSAnthony Koo pipe_ctx->stream_res.audio->funcs->az_configure( 13631a05873fSAnthony Koo pipe_ctx->stream_res.audio, 13641a05873fSAnthony Koo pipe_ctx->stream->signal, 13651a05873fSAnthony Koo &audio_output.crtc_info, 13661a05873fSAnthony Koo &pipe_ctx->stream->audio_info); 13671a05873fSAnthony Koo } 13681a05873fSAnthony Koo 13694562236bSHarry Wentland /* */ 1370d2d7885fSAnthony Koo /* Do not touch stream timing on seamless boot optimization. */ 1371d2d7885fSAnthony Koo if (!pipe_ctx->stream->apply_seamless_boot_optimization) 13723158223eSEric Bernstein dc->hwss.enable_stream_timing(pipe_ctx, context, dc); 13734562236bSHarry Wentland 1374d6001aedSYongqiang Sun if (dc->hwss.setup_vupdate_interrupt) 1375d6001aedSYongqiang Sun dc->hwss.setup_vupdate_interrupt(pipe_ctx); 1376a122b62dSAnthony Koo 13779c0fb8d4SAnthony Koo params.vertical_total_min = stream->adjust.v_total_min; 13789c0fb8d4SAnthony Koo params.vertical_total_max = stream->adjust.v_total_max; 13799c0fb8d4SAnthony Koo if (pipe_ctx->stream_res.tg->funcs->set_drr) 13809c0fb8d4SAnthony Koo pipe_ctx->stream_res.tg->funcs->set_drr( 13819c0fb8d4SAnthony Koo pipe_ctx->stream_res.tg, ¶ms); 13829c0fb8d4SAnthony Koo 13839c0fb8d4SAnthony Koo // DRR should set trigger event to monitor surface update event 13849c0fb8d4SAnthony Koo if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0) 13859c0fb8d4SAnthony Koo event_triggers = 0x80; 13869c0fb8d4SAnthony Koo if (pipe_ctx->stream_res.tg->funcs->set_static_screen_control) 13879c0fb8d4SAnthony Koo pipe_ctx->stream_res.tg->funcs->set_static_screen_control( 13889c0fb8d4SAnthony Koo pipe_ctx->stream_res.tg, event_triggers); 13899c0fb8d4SAnthony Koo 1390248cbed6SEric Bernstein if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) 1391d2c460e7Shersen wu pipe_ctx->stream_res.stream_enc->funcs->dig_connect_to_otg( 1392d2c460e7Shersen wu pipe_ctx->stream_res.stream_enc, 1393d2c460e7Shersen wu pipe_ctx->stream_res.tg->inst); 1394aa9c4abeSNikola Cornij 1395f0c4d997SCorbin McElhanney pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion( 1396f0c4d997SCorbin McElhanney pipe_ctx->stream_res.opp, 1397f0c4d997SCorbin McElhanney COLOR_SPACE_YCBCR601, 1398f0c4d997SCorbin McElhanney stream->timing.display_color_depth, 1399661a8cd9SDmytro Laktyushkin stream->signal); 14004562236bSHarry Wentland 1401a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp->funcs->opp_program_fmt( 1402a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp, 1403181a888fSCharlene Liu &stream->bit_depth_params, 1404181a888fSCharlene Liu &stream->clamping); 1405603767f9STony Cheng 14061e7e86c4SSamson Tam if (!stream->dpms_off) 1407ab8db3e1SAndrey Grodzovsky core_link_enable_stream(context, pipe_ctx); 14084562236bSHarry Wentland 14096702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; 14104562236bSHarry Wentland 1411ceb3dbb4SJun Lei pipe_ctx->stream->link->psr_enabled = false; 141294267b3dSSylvia Tsai 14134562236bSHarry Wentland return DC_OK; 14144562236bSHarry Wentland } 14154562236bSHarry Wentland 14164562236bSHarry Wentland /******************************************************************************/ 14174562236bSHarry Wentland 1418fb3466a4SBhawanpreet Lakha static void power_down_encoders(struct dc *dc) 14194562236bSHarry Wentland { 14204562236bSHarry Wentland int i; 1421a0c38ebaSCharlene Liu enum connector_id connector_id; 142268d77dd8SAndrew Jiang enum signal_type signal = SIGNAL_TYPE_NONE; 1423b9b171ffSHersen Wu 1424b9b171ffSHersen Wu /* do not know BIOS back-front mapping, simply blank all. It will not 1425b9b171ffSHersen Wu * hurt for non-DP 1426b9b171ffSHersen Wu */ 1427b9b171ffSHersen Wu for (i = 0; i < dc->res_pool->stream_enc_count; i++) { 1428b9b171ffSHersen Wu dc->res_pool->stream_enc[i]->funcs->dp_blank( 1429b9b171ffSHersen Wu dc->res_pool->stream_enc[i]); 1430b9b171ffSHersen Wu } 1431b9b171ffSHersen Wu 14324562236bSHarry Wentland for (i = 0; i < dc->link_count; i++) { 1433a0c38ebaSCharlene Liu connector_id = dal_graphics_object_id_get_connector_id(dc->links[i]->link_id); 1434a0c38ebaSCharlene Liu if ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || 1435a0c38ebaSCharlene Liu (connector_id == CONNECTOR_ID_EDP)) { 1436a0c38ebaSCharlene Liu 1437a0c38ebaSCharlene Liu if (!dc->links[i]->wa_flags.dp_keep_receiver_powered) 1438a0c38ebaSCharlene Liu dp_receiver_power_ctrl(dc->links[i], false); 1439904623eeSYongqiang Sun if (connector_id == CONNECTOR_ID_EDP) 144068d77dd8SAndrew Jiang signal = SIGNAL_TYPE_EDP; 1441a0c38ebaSCharlene Liu } 1442a0c38ebaSCharlene Liu 14434562236bSHarry Wentland dc->links[i]->link_enc->funcs->disable_output( 1444069d418fSAndrew Jiang dc->links[i]->link_enc, signal); 14454562236bSHarry Wentland } 14464562236bSHarry Wentland } 14474562236bSHarry Wentland 1448fb3466a4SBhawanpreet Lakha static void power_down_controllers(struct dc *dc) 14494562236bSHarry Wentland { 14504562236bSHarry Wentland int i; 14514562236bSHarry Wentland 14527f93c1deSCharlene Liu for (i = 0; i < dc->res_pool->timing_generator_count; i++) { 14534562236bSHarry Wentland dc->res_pool->timing_generators[i]->funcs->disable_crtc( 14544562236bSHarry Wentland dc->res_pool->timing_generators[i]); 14554562236bSHarry Wentland } 14564562236bSHarry Wentland } 14574562236bSHarry Wentland 1458fb3466a4SBhawanpreet Lakha static void power_down_clock_sources(struct dc *dc) 14594562236bSHarry Wentland { 14604562236bSHarry Wentland int i; 14614562236bSHarry Wentland 14624562236bSHarry Wentland if (dc->res_pool->dp_clock_source->funcs->cs_power_down( 14634562236bSHarry Wentland dc->res_pool->dp_clock_source) == false) 14644562236bSHarry Wentland dm_error("Failed to power down pll! (dp clk src)\n"); 14654562236bSHarry Wentland 14664562236bSHarry Wentland for (i = 0; i < dc->res_pool->clk_src_count; i++) { 14674562236bSHarry Wentland if (dc->res_pool->clock_sources[i]->funcs->cs_power_down( 14684562236bSHarry Wentland dc->res_pool->clock_sources[i]) == false) 14694562236bSHarry Wentland dm_error("Failed to power down pll! (clk src index=%d)\n", i); 14704562236bSHarry Wentland } 14714562236bSHarry Wentland } 14724562236bSHarry Wentland 1473fb3466a4SBhawanpreet Lakha static void power_down_all_hw_blocks(struct dc *dc) 14744562236bSHarry Wentland { 14754562236bSHarry Wentland power_down_encoders(dc); 14764562236bSHarry Wentland 14774562236bSHarry Wentland power_down_controllers(dc); 14784562236bSHarry Wentland 14794562236bSHarry Wentland power_down_clock_sources(dc); 14801663ae1cSBhawanpreet Lakha 14812f3bfb27SRoman Li if (dc->fbc_compressor) 14821663ae1cSBhawanpreet Lakha dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); 14834562236bSHarry Wentland } 14844562236bSHarry Wentland 14854562236bSHarry Wentland static void disable_vga_and_power_gate_all_controllers( 1486fb3466a4SBhawanpreet Lakha struct dc *dc) 14874562236bSHarry Wentland { 14884562236bSHarry Wentland int i; 14894562236bSHarry Wentland struct timing_generator *tg; 14904562236bSHarry Wentland struct dc_context *ctx = dc->ctx; 14914562236bSHarry Wentland 14927f93c1deSCharlene Liu for (i = 0; i < dc->res_pool->timing_generator_count; i++) { 14934562236bSHarry Wentland tg = dc->res_pool->timing_generators[i]; 14944562236bSHarry Wentland 14950a87425aSTony Cheng if (tg->funcs->disable_vga) 14964562236bSHarry Wentland tg->funcs->disable_vga(tg); 14977f93c1deSCharlene Liu } 14987f93c1deSCharlene Liu for (i = 0; i < dc->res_pool->pipe_count; i++) { 14994562236bSHarry Wentland /* Enable CLOCK gating for each pipe BEFORE controller 15004562236bSHarry Wentland * powergating. */ 15014562236bSHarry Wentland enable_display_pipe_clock_gating(ctx, 15024562236bSHarry Wentland true); 15034562236bSHarry Wentland 1504e6c258cbSYongqiang Sun dc->current_state->res_ctx.pipe_ctx[i].pipe_idx = i; 15057f914a62SYongqiang Sun dc->hwss.disable_plane(dc, 1506e6c258cbSYongqiang Sun &dc->current_state->res_ctx.pipe_ctx[i]); 15074562236bSHarry Wentland } 15084562236bSHarry Wentland } 15094562236bSHarry Wentland 15103de5aa81SSivapiriyanKumarasamy 15113de5aa81SSivapiriyanKumarasamy static struct dc_stream_state *get_edp_stream(struct dc_state *context) 15123de5aa81SSivapiriyanKumarasamy { 15133de5aa81SSivapiriyanKumarasamy int i; 15143de5aa81SSivapiriyanKumarasamy 15153de5aa81SSivapiriyanKumarasamy for (i = 0; i < context->stream_count; i++) { 15163de5aa81SSivapiriyanKumarasamy if (context->streams[i]->signal == SIGNAL_TYPE_EDP) 15173de5aa81SSivapiriyanKumarasamy return context->streams[i]; 15183de5aa81SSivapiriyanKumarasamy } 15193de5aa81SSivapiriyanKumarasamy return NULL; 15203de5aa81SSivapiriyanKumarasamy } 15213de5aa81SSivapiriyanKumarasamy 1522be4b289fSSivapiriyanKumarasamy static struct dc_link *get_edp_link(struct dc *dc) 1523339cc82aSYongqiang Sun { 1524339cc82aSYongqiang Sun int i; 1525339cc82aSYongqiang Sun 1526be4b289fSSivapiriyanKumarasamy // report any eDP links, even unconnected DDI's 1527f0c0761bSYongqiang Sun for (i = 0; i < dc->link_count; i++) { 1528f0c0761bSYongqiang Sun if (dc->links[i]->connector_signal == SIGNAL_TYPE_EDP) 1529f0c0761bSYongqiang Sun return dc->links[i]; 1530339cc82aSYongqiang Sun } 1531f0c0761bSYongqiang Sun return NULL; 1532339cc82aSYongqiang Sun } 1533339cc82aSYongqiang Sun 1534be4b289fSSivapiriyanKumarasamy static struct dc_link *get_edp_link_with_sink( 153525292028SYongqiang Sun struct dc *dc, 153625292028SYongqiang Sun struct dc_state *context) 153725292028SYongqiang Sun { 153825292028SYongqiang Sun int i; 153925292028SYongqiang Sun struct dc_link *link = NULL; 154025292028SYongqiang Sun 154125292028SYongqiang Sun /* check if there is an eDP panel not in use */ 154225292028SYongqiang Sun for (i = 0; i < dc->link_count; i++) { 154325292028SYongqiang Sun if (dc->links[i]->local_sink && 154425292028SYongqiang Sun dc->links[i]->local_sink->sink_signal == SIGNAL_TYPE_EDP) { 154525292028SYongqiang Sun link = dc->links[i]; 154625292028SYongqiang Sun break; 154725292028SYongqiang Sun } 154825292028SYongqiang Sun } 154925292028SYongqiang Sun 155025292028SYongqiang Sun return link; 155125292028SYongqiang Sun } 155225292028SYongqiang Sun 15534562236bSHarry Wentland /** 15544562236bSHarry Wentland * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need: 15554562236bSHarry Wentland * 1. Power down all DC HW blocks 15564562236bSHarry Wentland * 2. Disable VGA engine on all controllers 15574562236bSHarry Wentland * 3. Enable power gating for controller 15584562236bSHarry Wentland * 4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS) 15594562236bSHarry Wentland */ 156025292028SYongqiang Sun void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) 15614562236bSHarry Wentland { 1562d82f9942SAnthony Koo int i; 1563be4b289fSSivapiriyanKumarasamy struct dc_link *edp_link_with_sink = get_edp_link_with_sink(dc, context); 1564be4b289fSSivapiriyanKumarasamy struct dc_link *edp_link = get_edp_link(dc); 15653de5aa81SSivapiriyanKumarasamy struct dc_stream_state *edp_stream = NULL; 1566be4b289fSSivapiriyanKumarasamy bool can_apply_edp_fast_boot = false; 1567ce72741bSAnthony Koo bool can_apply_seamless_boot = false; 15683de5aa81SSivapiriyanKumarasamy bool keep_edp_vdd_on = false; 1569ce72741bSAnthony Koo 1570be4b289fSSivapiriyanKumarasamy if (dc->hwss.init_pipes) 1571be4b289fSSivapiriyanKumarasamy dc->hwss.init_pipes(dc, context); 1572be4b289fSSivapiriyanKumarasamy 15733de5aa81SSivapiriyanKumarasamy edp_stream = get_edp_stream(context); 15743de5aa81SSivapiriyanKumarasamy 1575be4b289fSSivapiriyanKumarasamy // Check fastboot support, disable on DCE8 because of blank screens 1576be4b289fSSivapiriyanKumarasamy if (edp_link && dc->ctx->dce_version != DCE_VERSION_8_0 && 1577be4b289fSSivapiriyanKumarasamy dc->ctx->dce_version != DCE_VERSION_8_1 && 1578be4b289fSSivapiriyanKumarasamy dc->ctx->dce_version != DCE_VERSION_8_3) { 1579be4b289fSSivapiriyanKumarasamy 1580be4b289fSSivapiriyanKumarasamy // enable fastboot if backend is enabled on eDP 1581be4b289fSSivapiriyanKumarasamy if (edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc)) { 15823de5aa81SSivapiriyanKumarasamy /* Set optimization flag on eDP stream*/ 15833de5aa81SSivapiriyanKumarasamy if (edp_stream) { 15843de5aa81SSivapiriyanKumarasamy edp_stream->apply_edp_fast_boot_optimization = true; 1585be4b289fSSivapiriyanKumarasamy can_apply_edp_fast_boot = true; 1586be4b289fSSivapiriyanKumarasamy } 1587be4b289fSSivapiriyanKumarasamy } 15883de5aa81SSivapiriyanKumarasamy 15893de5aa81SSivapiriyanKumarasamy // We are trying to enable eDP, don't power down VDD 15903de5aa81SSivapiriyanKumarasamy if (edp_stream) 15913de5aa81SSivapiriyanKumarasamy keep_edp_vdd_on = true; 1592be4b289fSSivapiriyanKumarasamy } 1593be4b289fSSivapiriyanKumarasamy 1594be4b289fSSivapiriyanKumarasamy // Check seamless boot support 1595ce72741bSAnthony Koo for (i = 0; i < context->stream_count; i++) { 1596ce72741bSAnthony Koo if (context->streams[i]->apply_seamless_boot_optimization) { 1597ce72741bSAnthony Koo can_apply_seamless_boot = true; 1598ce72741bSAnthony Koo break; 1599ce72741bSAnthony Koo } 1600ce72741bSAnthony Koo } 16014cac1e6dSYongqiang Sun 1602be4b289fSSivapiriyanKumarasamy /* eDP should not have stream in resume from S4 and so even with VBios post 1603be4b289fSSivapiriyanKumarasamy * it should get turned off 16042c37e49aSYongqiang Sun */ 1605be4b289fSSivapiriyanKumarasamy if (!can_apply_edp_fast_boot && !can_apply_seamless_boot) { 16063de5aa81SSivapiriyanKumarasamy if (edp_link_with_sink && !keep_edp_vdd_on) { 16074cac1e6dSYongqiang Sun /*turn off backlight before DP_blank and encoder powered down*/ 1608be4b289fSSivapiriyanKumarasamy dc->hwss.edp_backlight_control(edp_link_with_sink, false); 1609c5fc7f59SCharlene Liu } 1610c5fc7f59SCharlene Liu /*resume from S3, no vbios posting, no need to power down again*/ 161125292028SYongqiang Sun power_down_all_hw_blocks(dc); 16124562236bSHarry Wentland disable_vga_and_power_gate_all_controllers(dc); 16133de5aa81SSivapiriyanKumarasamy if (edp_link_with_sink && !keep_edp_vdd_on) 1614be4b289fSSivapiriyanKumarasamy dc->hwss.edp_power_control(edp_link_with_sink, false); 1615c5fc7f59SCharlene Liu } 16164562236bSHarry Wentland bios_set_scratch_acc_mode_change(dc->ctx->dc_bios); 16174562236bSHarry Wentland } 16184562236bSHarry Wentland 16194562236bSHarry Wentland static uint32_t compute_pstate_blackout_duration( 16204562236bSHarry Wentland struct bw_fixed blackout_duration, 16210971c40eSHarry Wentland const struct dc_stream_state *stream) 16224562236bSHarry Wentland { 16234562236bSHarry Wentland uint32_t total_dest_line_time_ns; 16244562236bSHarry Wentland uint32_t pstate_blackout_duration_ns; 16254562236bSHarry Wentland 16264562236bSHarry Wentland pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24; 16274562236bSHarry Wentland 16284562236bSHarry Wentland total_dest_line_time_ns = 1000000UL * 1629380604e2SKen Chalmers (stream->timing.h_total * 10) / 1630380604e2SKen Chalmers stream->timing.pix_clk_100hz + 16314562236bSHarry Wentland pstate_blackout_duration_ns; 16324562236bSHarry Wentland 16334562236bSHarry Wentland return total_dest_line_time_ns; 16344562236bSHarry Wentland } 16354562236bSHarry Wentland 1636f774b339SEric Yang static void dce110_set_displaymarks( 1637fb3466a4SBhawanpreet Lakha const struct dc *dc, 1638608ac7bbSJerry Zuo struct dc_state *context) 16394562236bSHarry Wentland { 16404562236bSHarry Wentland uint8_t i, num_pipes; 16414562236bSHarry Wentland unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; 16424562236bSHarry Wentland 16434562236bSHarry Wentland for (i = 0, num_pipes = 0; i < MAX_PIPES; i++) { 16444562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 16454562236bSHarry Wentland uint32_t total_dest_line_time_ns; 16464562236bSHarry Wentland 16474562236bSHarry Wentland if (pipe_ctx->stream == NULL) 16484562236bSHarry Wentland continue; 16494562236bSHarry Wentland 16504562236bSHarry Wentland total_dest_line_time_ns = compute_pstate_blackout_duration( 165177a4ea53SBhawanpreet Lakha dc->bw_vbios->blackout_duration, pipe_ctx->stream); 165286a66c4eSHarry Wentland pipe_ctx->plane_res.mi->funcs->mem_input_program_display_marks( 165386a66c4eSHarry Wentland pipe_ctx->plane_res.mi, 1654813d20dcSAidan Wood context->bw_ctx.bw.dce.nbp_state_change_wm_ns[num_pipes], 1655813d20dcSAidan Wood context->bw_ctx.bw.dce.stutter_exit_wm_ns[num_pipes], 1656813d20dcSAidan Wood context->bw_ctx.bw.dce.stutter_entry_wm_ns[num_pipes], 1657813d20dcSAidan Wood context->bw_ctx.bw.dce.urgent_wm_ns[num_pipes], 16584562236bSHarry Wentland total_dest_line_time_ns); 16594562236bSHarry Wentland if (i == underlay_idx) { 16604562236bSHarry Wentland num_pipes++; 166186a66c4eSHarry Wentland pipe_ctx->plane_res.mi->funcs->mem_input_program_chroma_display_marks( 166286a66c4eSHarry Wentland pipe_ctx->plane_res.mi, 1663813d20dcSAidan Wood context->bw_ctx.bw.dce.nbp_state_change_wm_ns[num_pipes], 1664813d20dcSAidan Wood context->bw_ctx.bw.dce.stutter_exit_wm_ns[num_pipes], 1665813d20dcSAidan Wood context->bw_ctx.bw.dce.urgent_wm_ns[num_pipes], 16664562236bSHarry Wentland total_dest_line_time_ns); 16674562236bSHarry Wentland } 16684562236bSHarry Wentland num_pipes++; 16694562236bSHarry Wentland } 16704562236bSHarry Wentland } 16714562236bSHarry Wentland 1672fab55d61SDmytro Laktyushkin void dce110_set_safe_displaymarks( 1673a2b8659dSTony Cheng struct resource_context *res_ctx, 1674a2b8659dSTony Cheng const struct resource_pool *pool) 16754562236bSHarry Wentland { 16764562236bSHarry Wentland int i; 1677a2b8659dSTony Cheng int underlay_idx = pool->underlay_pipe_index; 16789037d802SDmytro Laktyushkin struct dce_watermarks max_marks = { 16794562236bSHarry Wentland MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK }; 16809037d802SDmytro Laktyushkin struct dce_watermarks nbp_marks = { 16814562236bSHarry Wentland SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK }; 16823722c794SMikita Lipski struct dce_watermarks min_marks = { 0, 0, 0, 0}; 16834562236bSHarry Wentland 16844562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 16858feabd03SYue Hin Lau if (res_ctx->pipe_ctx[i].stream == NULL || res_ctx->pipe_ctx[i].plane_res.mi == NULL) 16864562236bSHarry Wentland continue; 16874562236bSHarry Wentland 168886a66c4eSHarry Wentland res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_display_marks( 168986a66c4eSHarry Wentland res_ctx->pipe_ctx[i].plane_res.mi, 16904562236bSHarry Wentland nbp_marks, 16914562236bSHarry Wentland max_marks, 16923722c794SMikita Lipski min_marks, 16934562236bSHarry Wentland max_marks, 16944562236bSHarry Wentland MAX_WATERMARK); 16958feabd03SYue Hin Lau 16964562236bSHarry Wentland if (i == underlay_idx) 169786a66c4eSHarry Wentland res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_chroma_display_marks( 169886a66c4eSHarry Wentland res_ctx->pipe_ctx[i].plane_res.mi, 16994562236bSHarry Wentland nbp_marks, 17004562236bSHarry Wentland max_marks, 17014562236bSHarry Wentland max_marks, 17024562236bSHarry Wentland MAX_WATERMARK); 17038feabd03SYue Hin Lau 17044562236bSHarry Wentland } 17054562236bSHarry Wentland } 17064562236bSHarry Wentland 17074562236bSHarry Wentland /******************************************************************************* 17084562236bSHarry Wentland * Public functions 17094562236bSHarry Wentland ******************************************************************************/ 17104562236bSHarry Wentland 17114562236bSHarry Wentland static void set_drr(struct pipe_ctx **pipe_ctx, 17124562236bSHarry Wentland int num_pipes, int vmin, int vmax) 17134562236bSHarry Wentland { 17144562236bSHarry Wentland int i = 0; 17154562236bSHarry Wentland struct drr_params params = {0}; 171698e6436dSAnthony Koo // DRR should set trigger event to monitor surface update event 171798e6436dSAnthony Koo unsigned int event_triggers = 0x80; 17184562236bSHarry Wentland 17194562236bSHarry Wentland params.vertical_total_max = vmax; 17204562236bSHarry Wentland params.vertical_total_min = vmin; 17214562236bSHarry Wentland 17224562236bSHarry Wentland /* TODO: If multiple pipes are to be supported, you need 172398e6436dSAnthony Koo * some GSL stuff. Static screen triggers may be programmed differently 172498e6436dSAnthony Koo * as well. 17254562236bSHarry Wentland */ 17264562236bSHarry Wentland for (i = 0; i < num_pipes; i++) { 172798e6436dSAnthony Koo pipe_ctx[i]->stream_res.tg->funcs->set_drr( 172898e6436dSAnthony Koo pipe_ctx[i]->stream_res.tg, ¶ms); 172998e6436dSAnthony Koo 173098e6436dSAnthony Koo if (vmax != 0 && vmin != 0) 173198e6436dSAnthony Koo pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control( 173298e6436dSAnthony Koo pipe_ctx[i]->stream_res.tg, 173398e6436dSAnthony Koo event_triggers); 17344562236bSHarry Wentland } 17354562236bSHarry Wentland } 17364562236bSHarry Wentland 173772ada5f7SEric Cook static void get_position(struct pipe_ctx **pipe_ctx, 173872ada5f7SEric Cook int num_pipes, 173972ada5f7SEric Cook struct crtc_position *position) 174072ada5f7SEric Cook { 174172ada5f7SEric Cook int i = 0; 174272ada5f7SEric Cook 174372ada5f7SEric Cook /* TODO: handle pipes > 1 174472ada5f7SEric Cook */ 174572ada5f7SEric Cook for (i = 0; i < num_pipes; i++) 17466b670fa9SHarry Wentland pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position); 174772ada5f7SEric Cook } 174872ada5f7SEric Cook 17494562236bSHarry Wentland static void set_static_screen_control(struct pipe_ctx **pipe_ctx, 175094267b3dSSylvia Tsai int num_pipes, const struct dc_static_screen_events *events) 17514562236bSHarry Wentland { 17524562236bSHarry Wentland unsigned int i; 175394267b3dSSylvia Tsai unsigned int value = 0; 175494267b3dSSylvia Tsai 175594267b3dSSylvia Tsai if (events->overlay_update) 175694267b3dSSylvia Tsai value |= 0x100; 175794267b3dSSylvia Tsai if (events->surface_update) 175894267b3dSSylvia Tsai value |= 0x80; 175994267b3dSSylvia Tsai if (events->cursor_update) 176094267b3dSSylvia Tsai value |= 0x2; 1761ed8462acSCharlene Liu if (events->force_trigger) 1762ed8462acSCharlene Liu value |= 0x1; 17634562236bSHarry Wentland 1764593f79a2SAlex Deucher if (num_pipes) { 1765593f79a2SAlex Deucher struct dc *dc = pipe_ctx[0]->stream->ctx->dc; 1766593f79a2SAlex Deucher 1767593f79a2SAlex Deucher if (dc->fbc_compressor) 1768c3aa1d67SBhawanpreet Lakha value |= 0x84; 1769593f79a2SAlex Deucher } 1770c3aa1d67SBhawanpreet Lakha 17714562236bSHarry Wentland for (i = 0; i < num_pipes; i++) 17726b670fa9SHarry Wentland pipe_ctx[i]->stream_res.tg->funcs-> 17736b670fa9SHarry Wentland set_static_screen_control(pipe_ctx[i]->stream_res.tg, value); 17744562236bSHarry Wentland } 17754562236bSHarry Wentland 1776f6baff4dSHarry Wentland /* 1777690b5e39SRoman Li * Check if FBC can be enabled 1778690b5e39SRoman Li */ 17799c6569deSHarry Wentland static bool should_enable_fbc(struct dc *dc, 17803bc4aaa9SRoman Li struct dc_state *context, 17813bc4aaa9SRoman Li uint32_t *pipe_idx) 1782690b5e39SRoman Li { 17833bc4aaa9SRoman Li uint32_t i; 17843bc4aaa9SRoman Li struct pipe_ctx *pipe_ctx = NULL; 17853bc4aaa9SRoman Li struct resource_context *res_ctx = &context->res_ctx; 178665d38262Shersen wu unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; 17873bc4aaa9SRoman Li 1788690b5e39SRoman Li 1789690b5e39SRoman Li ASSERT(dc->fbc_compressor); 1790690b5e39SRoman Li 1791690b5e39SRoman Li /* FBC memory should be allocated */ 1792690b5e39SRoman Li if (!dc->ctx->fbc_gpu_addr) 17939c6569deSHarry Wentland return false; 1794690b5e39SRoman Li 1795690b5e39SRoman Li /* Only supports single display */ 1796690b5e39SRoman Li if (context->stream_count != 1) 17979c6569deSHarry Wentland return false; 1798690b5e39SRoman Li 17993bc4aaa9SRoman Li for (i = 0; i < dc->res_pool->pipe_count; i++) { 18003bc4aaa9SRoman Li if (res_ctx->pipe_ctx[i].stream) { 180165d38262Shersen wu 18023bc4aaa9SRoman Li pipe_ctx = &res_ctx->pipe_ctx[i]; 180365d38262Shersen wu 180465d38262Shersen wu if (!pipe_ctx) 180565d38262Shersen wu continue; 180665d38262Shersen wu 180765d38262Shersen wu /* fbc not applicable on underlay pipe */ 180865d38262Shersen wu if (pipe_ctx->pipe_idx != underlay_idx) { 18093bc4aaa9SRoman Li *pipe_idx = i; 18103bc4aaa9SRoman Li break; 18113bc4aaa9SRoman Li } 18123bc4aaa9SRoman Li } 181365d38262Shersen wu } 18143bc4aaa9SRoman Li 181565d38262Shersen wu if (i == dc->res_pool->pipe_count) 181665d38262Shersen wu return false; 181765d38262Shersen wu 1818ceb3dbb4SJun Lei if (!pipe_ctx->stream->link) 181965d38262Shersen wu return false; 18207a840773SRoman Li 1821690b5e39SRoman Li /* Only supports eDP */ 1822ceb3dbb4SJun Lei if (pipe_ctx->stream->link->connector_signal != SIGNAL_TYPE_EDP) 18239c6569deSHarry Wentland return false; 1824690b5e39SRoman Li 1825690b5e39SRoman Li /* PSR should not be enabled */ 1826ceb3dbb4SJun Lei if (pipe_ctx->stream->link->psr_enabled) 18279c6569deSHarry Wentland return false; 1828690b5e39SRoman Li 182993984bbcSShirish S /* Nothing to compress */ 183093984bbcSShirish S if (!pipe_ctx->plane_state) 18319c6569deSHarry Wentland return false; 183293984bbcSShirish S 183305230fa9SRoman Li /* Only for non-linear tiling */ 183405230fa9SRoman Li if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) 18359c6569deSHarry Wentland return false; 183605230fa9SRoman Li 18379c6569deSHarry Wentland return true; 1838690b5e39SRoman Li } 1839690b5e39SRoman Li 1840690b5e39SRoman Li /* 1841690b5e39SRoman Li * Enable FBC 1842690b5e39SRoman Li */ 184365d38262Shersen wu static void enable_fbc( 184465d38262Shersen wu struct dc *dc, 1845608ac7bbSJerry Zuo struct dc_state *context) 1846690b5e39SRoman Li { 18473bc4aaa9SRoman Li uint32_t pipe_idx = 0; 18483bc4aaa9SRoman Li 18493bc4aaa9SRoman Li if (should_enable_fbc(dc, context, &pipe_idx)) { 1850690b5e39SRoman Li /* Program GRPH COMPRESSED ADDRESS and PITCH */ 1851690b5e39SRoman Li struct compr_addr_and_pitch_params params = {0, 0, 0}; 1852690b5e39SRoman Li struct compressor *compr = dc->fbc_compressor; 18533bc4aaa9SRoman Li struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; 18543bc4aaa9SRoman Li 18559c6569deSHarry Wentland params.source_view_width = pipe_ctx->stream->timing.h_addressable; 18569c6569deSHarry Wentland params.source_view_height = pipe_ctx->stream->timing.v_addressable; 185765d38262Shersen wu params.inst = pipe_ctx->stream_res.tg->inst; 1858690b5e39SRoman Li compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr; 1859690b5e39SRoman Li 1860690b5e39SRoman Li compr->funcs->surface_address_and_pitch(compr, ¶ms); 1861690b5e39SRoman Li compr->funcs->set_fbc_invalidation_triggers(compr, 1); 1862690b5e39SRoman Li 1863690b5e39SRoman Li compr->funcs->enable_fbc(compr, ¶ms); 1864690b5e39SRoman Li } 1865690b5e39SRoman Li } 1866690b5e39SRoman Li 186754e8695eSDmytro Laktyushkin static void dce110_reset_hw_ctx_wrap( 1868fb3466a4SBhawanpreet Lakha struct dc *dc, 1869608ac7bbSJerry Zuo struct dc_state *context) 18704562236bSHarry Wentland { 18714562236bSHarry Wentland int i; 18724562236bSHarry Wentland 18734562236bSHarry Wentland /* Reset old context */ 18744562236bSHarry Wentland /* look up the targets that have been removed since last commit */ 1875a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 18764562236bSHarry Wentland struct pipe_ctx *pipe_ctx_old = 1877608ac7bbSJerry Zuo &dc->current_state->res_ctx.pipe_ctx[i]; 18784562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 18794562236bSHarry Wentland 18804562236bSHarry Wentland /* Note: We need to disable output if clock sources change, 18814562236bSHarry Wentland * since bios does optimization and doesn't apply if changing 18824562236bSHarry Wentland * PHY when not already disabled. 18834562236bSHarry Wentland */ 18844562236bSHarry Wentland 18854562236bSHarry Wentland /* Skip underlay pipe since it will be handled in commit surface*/ 18864562236bSHarry Wentland if (!pipe_ctx_old->stream || pipe_ctx_old->top_pipe) 18874562236bSHarry Wentland continue; 18884562236bSHarry Wentland 18894562236bSHarry Wentland if (!pipe_ctx->stream || 189054e8695eSDmytro Laktyushkin pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { 189121e67d4dSHarry Wentland struct clock_source *old_clk = pipe_ctx_old->clock_source; 189221e67d4dSHarry Wentland 1893827f11e9SLeo (Sunpeng) Li /* Disable if new stream is null. O/w, if stream is 1894827f11e9SLeo (Sunpeng) Li * disabled already, no need to disable again. 1895827f11e9SLeo (Sunpeng) Li */ 1896827f11e9SLeo (Sunpeng) Li if (!pipe_ctx->stream || !pipe_ctx->stream->dpms_off) 18974176664bSCharlene Liu core_link_disable_stream(pipe_ctx_old, FREE_ACQUIRED_RESOURCE); 1898d050f8edSHersen Wu 18996b670fa9SHarry Wentland pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true); 19006b670fa9SHarry Wentland if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) { 190154e8695eSDmytro Laktyushkin dm_error("DC: failed to blank crtc!\n"); 190254e8695eSDmytro Laktyushkin BREAK_TO_DEBUGGER(); 190354e8695eSDmytro Laktyushkin } 19046b670fa9SHarry Wentland pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg); 190586a66c4eSHarry Wentland pipe_ctx_old->plane_res.mi->funcs->free_mem_input( 1906608ac7bbSJerry Zuo pipe_ctx_old->plane_res.mi, dc->current_state->stream_count); 190754e8695eSDmytro Laktyushkin 1908ad8960a6SMikita Lipski if (old_clk && 0 == resource_get_clock_source_reference(&context->res_ctx, 1909ad8960a6SMikita Lipski dc->res_pool, 1910ad8960a6SMikita Lipski old_clk)) 191121e67d4dSHarry Wentland old_clk->funcs->cs_power_down(old_clk); 191221e67d4dSHarry Wentland 19137f914a62SYongqiang Sun dc->hwss.disable_plane(dc, pipe_ctx_old); 191454e8695eSDmytro Laktyushkin 191554e8695eSDmytro Laktyushkin pipe_ctx_old->stream = NULL; 191654e8695eSDmytro Laktyushkin } 19174562236bSHarry Wentland } 19184562236bSHarry Wentland } 19194562236bSHarry Wentland 19201a05873fSAnthony Koo static void dce110_setup_audio_dto( 19211a05873fSAnthony Koo struct dc *dc, 19221a05873fSAnthony Koo struct dc_state *context) 19231a05873fSAnthony Koo { 19241a05873fSAnthony Koo int i; 19251a05873fSAnthony Koo 19261a05873fSAnthony Koo /* program audio wall clock. use HDMI as clock source if HDMI 19271a05873fSAnthony Koo * audio active. Otherwise, use DP as clock source 19281a05873fSAnthony Koo * first, loop to find any HDMI audio, if not, loop find DP audio 19291a05873fSAnthony Koo */ 19301a05873fSAnthony Koo /* Setup audio rate clock source */ 19311a05873fSAnthony Koo /* Issue: 19321a05873fSAnthony Koo * Audio lag happened on DP monitor when unplug a HDMI monitor 19331a05873fSAnthony Koo * 19341a05873fSAnthony Koo * Cause: 19351a05873fSAnthony Koo * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL 19361a05873fSAnthony Koo * is set to either dto0 or dto1, audio should work fine. 19371a05873fSAnthony Koo * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1, 19381a05873fSAnthony Koo * set to dto0 will cause audio lag. 19391a05873fSAnthony Koo * 19401a05873fSAnthony Koo * Solution: 19411a05873fSAnthony Koo * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx, 19421a05873fSAnthony Koo * find first available pipe with audio, setup audio wall DTO per topology 19431a05873fSAnthony Koo * instead of per pipe. 19441a05873fSAnthony Koo */ 19451a05873fSAnthony Koo for (i = 0; i < dc->res_pool->pipe_count; i++) { 19461a05873fSAnthony Koo struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 19471a05873fSAnthony Koo 19481a05873fSAnthony Koo if (pipe_ctx->stream == NULL) 19491a05873fSAnthony Koo continue; 19501a05873fSAnthony Koo 19511a05873fSAnthony Koo if (pipe_ctx->top_pipe) 19521a05873fSAnthony Koo continue; 19531a05873fSAnthony Koo 19541a05873fSAnthony Koo if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) 19551a05873fSAnthony Koo continue; 19561a05873fSAnthony Koo 19571a05873fSAnthony Koo if (pipe_ctx->stream_res.audio != NULL) { 19581a05873fSAnthony Koo struct audio_output audio_output; 19591a05873fSAnthony Koo 19601a05873fSAnthony Koo build_audio_output(context, pipe_ctx, &audio_output); 19611a05873fSAnthony Koo 19621a05873fSAnthony Koo pipe_ctx->stream_res.audio->funcs->wall_dto_setup( 19631a05873fSAnthony Koo pipe_ctx->stream_res.audio, 19641a05873fSAnthony Koo pipe_ctx->stream->signal, 19651a05873fSAnthony Koo &audio_output.crtc_info, 19661a05873fSAnthony Koo &audio_output.pll_info); 19671a05873fSAnthony Koo break; 19681a05873fSAnthony Koo } 19691a05873fSAnthony Koo } 19701a05873fSAnthony Koo 19711a05873fSAnthony Koo /* no HDMI audio is found, try DP audio */ 19721a05873fSAnthony Koo if (i == dc->res_pool->pipe_count) { 19731a05873fSAnthony Koo for (i = 0; i < dc->res_pool->pipe_count; i++) { 19741a05873fSAnthony Koo struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 19751a05873fSAnthony Koo 19761a05873fSAnthony Koo if (pipe_ctx->stream == NULL) 19771a05873fSAnthony Koo continue; 19781a05873fSAnthony Koo 19791a05873fSAnthony Koo if (pipe_ctx->top_pipe) 19801a05873fSAnthony Koo continue; 19811a05873fSAnthony Koo 19821a05873fSAnthony Koo if (!dc_is_dp_signal(pipe_ctx->stream->signal)) 19831a05873fSAnthony Koo continue; 19841a05873fSAnthony Koo 19851a05873fSAnthony Koo if (pipe_ctx->stream_res.audio != NULL) { 19861a05873fSAnthony Koo struct audio_output audio_output; 19871a05873fSAnthony Koo 19881a05873fSAnthony Koo build_audio_output(context, pipe_ctx, &audio_output); 19891a05873fSAnthony Koo 19901a05873fSAnthony Koo pipe_ctx->stream_res.audio->funcs->wall_dto_setup( 19911a05873fSAnthony Koo pipe_ctx->stream_res.audio, 19921a05873fSAnthony Koo pipe_ctx->stream->signal, 19931a05873fSAnthony Koo &audio_output.crtc_info, 19941a05873fSAnthony Koo &audio_output.pll_info); 19951a05873fSAnthony Koo break; 19961a05873fSAnthony Koo } 19971a05873fSAnthony Koo } 19981a05873fSAnthony Koo } 19991a05873fSAnthony Koo } 2000cf437593SDmytro Laktyushkin 20014562236bSHarry Wentland enum dc_status dce110_apply_ctx_to_hw( 2002fb3466a4SBhawanpreet Lakha struct dc *dc, 2003608ac7bbSJerry Zuo struct dc_state *context) 20044562236bSHarry Wentland { 20054562236bSHarry Wentland struct dc_bios *dcb = dc->ctx->dc_bios; 20064562236bSHarry Wentland enum dc_status status; 20074562236bSHarry Wentland int i; 20084562236bSHarry Wentland 20094562236bSHarry Wentland /* Reset old context */ 20104562236bSHarry Wentland /* look up the targets that have been removed since last commit */ 20114562236bSHarry Wentland dc->hwss.reset_hw_ctx_wrap(dc, context); 20124562236bSHarry Wentland 20134562236bSHarry Wentland /* Skip applying if no targets */ 2014ab2541b6SAric Cyr if (context->stream_count <= 0) 20154562236bSHarry Wentland return DC_OK; 20164562236bSHarry Wentland 20174562236bSHarry Wentland /* Apply new context */ 20184562236bSHarry Wentland dcb->funcs->set_scratch_critical_state(dcb, true); 20194562236bSHarry Wentland 20204562236bSHarry Wentland /* below is for real asic only */ 2021a2b8659dSTony Cheng for (i = 0; i < dc->res_pool->pipe_count; i++) { 20224562236bSHarry Wentland struct pipe_ctx *pipe_ctx_old = 2023608ac7bbSJerry Zuo &dc->current_state->res_ctx.pipe_ctx[i]; 20244562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 20254562236bSHarry Wentland 20264562236bSHarry Wentland if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe) 20274562236bSHarry Wentland continue; 20284562236bSHarry Wentland 20294562236bSHarry Wentland if (pipe_ctx->stream == pipe_ctx_old->stream) { 20304562236bSHarry Wentland if (pipe_ctx_old->clock_source != pipe_ctx->clock_source) 20314562236bSHarry Wentland dce_crtc_switch_to_clk_src(dc->hwseq, 20324562236bSHarry Wentland pipe_ctx->clock_source, i); 20334562236bSHarry Wentland continue; 20344562236bSHarry Wentland } 20354562236bSHarry Wentland 20364562236bSHarry Wentland dc->hwss.enable_display_power_gating( 20374562236bSHarry Wentland dc, i, dc->ctx->dc_bios, 20384562236bSHarry Wentland PIPE_GATING_CONTROL_DISABLE); 20394562236bSHarry Wentland } 20404562236bSHarry Wentland 20412f3bfb27SRoman Li if (dc->fbc_compressor) 20421663ae1cSBhawanpreet Lakha dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); 20435099114bSAlex Deucher 20441a05873fSAnthony Koo dce110_setup_audio_dto(dc, context); 2045ab8812a3SHersen Wu 2046a2b8659dSTony Cheng for (i = 0; i < dc->res_pool->pipe_count; i++) { 2047ab8812a3SHersen Wu struct pipe_ctx *pipe_ctx_old = 2048608ac7bbSJerry Zuo &dc->current_state->res_ctx.pipe_ctx[i]; 2049ab8812a3SHersen Wu struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 2050ab8812a3SHersen Wu 2051ab8812a3SHersen Wu if (pipe_ctx->stream == NULL) 2052ab8812a3SHersen Wu continue; 2053ab8812a3SHersen Wu 2054eed928dcSCharlene Liu if (pipe_ctx->stream == pipe_ctx_old->stream && 2055eed928dcSCharlene Liu pipe_ctx->stream->link->link_state_valid) { 2056ab8812a3SHersen Wu continue; 2057eed928dcSCharlene Liu } 2058ab8812a3SHersen Wu 20595b92d9d4SHarry Wentland if (pipe_ctx_old->stream && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) 2060313bf4ffSYongqiang Sun continue; 2061313bf4ffSYongqiang Sun 2062ab8812a3SHersen Wu if (pipe_ctx->top_pipe) 2063ab8812a3SHersen Wu continue; 2064ab8812a3SHersen Wu 20654562236bSHarry Wentland status = apply_single_controller_ctx_to_hw( 20664562236bSHarry Wentland pipe_ctx, 20674562236bSHarry Wentland context, 20684562236bSHarry Wentland dc); 20694562236bSHarry Wentland 20704562236bSHarry Wentland if (DC_OK != status) 20714562236bSHarry Wentland return status; 20724562236bSHarry Wentland } 20734562236bSHarry Wentland 2074690b5e39SRoman Li if (dc->fbc_compressor) 207565d38262Shersen wu enable_fbc(dc, dc->current_state); 207665d38262Shersen wu 207765d38262Shersen wu dcb->funcs->set_scratch_critical_state(dcb, false); 2078690b5e39SRoman Li 20794562236bSHarry Wentland return DC_OK; 20804562236bSHarry Wentland } 20814562236bSHarry Wentland 20824562236bSHarry Wentland /******************************************************************************* 20834562236bSHarry Wentland * Front End programming 20844562236bSHarry Wentland ******************************************************************************/ 20854562236bSHarry Wentland static void set_default_colors(struct pipe_ctx *pipe_ctx) 20864562236bSHarry Wentland { 20874562236bSHarry Wentland struct default_adjustment default_adjust = { 0 }; 20884562236bSHarry Wentland 20894562236bSHarry Wentland default_adjust.force_hw_default = false; 209034996173SHarry Wentland default_adjust.in_color_space = pipe_ctx->plane_state->color_space; 209134996173SHarry Wentland default_adjust.out_color_space = pipe_ctx->stream->output_color_space; 20924562236bSHarry Wentland default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW; 20936702a9acSHarry Wentland default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format; 20944562236bSHarry Wentland 20954562236bSHarry Wentland /* display color depth */ 20964562236bSHarry Wentland default_adjust.color_depth = 20974fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->timing.display_color_depth; 20984562236bSHarry Wentland 20994562236bSHarry Wentland /* Lb color depth */ 21006702a9acSHarry Wentland default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth; 21014562236bSHarry Wentland 210286a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default( 210386a66c4eSHarry Wentland pipe_ctx->plane_res.xfm, &default_adjust); 21044562236bSHarry Wentland } 21054562236bSHarry Wentland 2106b06b7680SLeon Elazar 2107b06b7680SLeon Elazar /******************************************************************************* 2108b06b7680SLeon Elazar * In order to turn on/off specific surface we will program 2109b06b7680SLeon Elazar * Blender + CRTC 2110b06b7680SLeon Elazar * 2111b06b7680SLeon Elazar * In case that we have two surfaces and they have a different visibility 2112b06b7680SLeon Elazar * we can't turn off the CRTC since it will turn off the entire display 2113b06b7680SLeon Elazar * 2114b06b7680SLeon Elazar * |----------------------------------------------- | 2115b06b7680SLeon Elazar * |bottom pipe|curr pipe | | | 2116b06b7680SLeon Elazar * |Surface |Surface | Blender | CRCT | 2117b06b7680SLeon Elazar * |visibility |visibility | Configuration| | 2118b06b7680SLeon Elazar * |------------------------------------------------| 2119b06b7680SLeon Elazar * | off | off | CURRENT_PIPE | blank | 2120b06b7680SLeon Elazar * | off | on | CURRENT_PIPE | unblank | 2121b06b7680SLeon Elazar * | on | off | OTHER_PIPE | unblank | 2122b06b7680SLeon Elazar * | on | on | BLENDING | unblank | 2123b06b7680SLeon Elazar * -------------------------------------------------| 2124b06b7680SLeon Elazar * 2125b06b7680SLeon Elazar ******************************************************************************/ 2126fb3466a4SBhawanpreet Lakha static void program_surface_visibility(const struct dc *dc, 21274562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 21284562236bSHarry Wentland { 21294562236bSHarry Wentland enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE; 2130b06b7680SLeon Elazar bool blank_target = false; 21314562236bSHarry Wentland 21324562236bSHarry Wentland if (pipe_ctx->bottom_pipe) { 2133b06b7680SLeon Elazar 2134b06b7680SLeon Elazar /* For now we are supporting only two pipes */ 2135b06b7680SLeon Elazar ASSERT(pipe_ctx->bottom_pipe->bottom_pipe == NULL); 2136b06b7680SLeon Elazar 21373be5262eSHarry Wentland if (pipe_ctx->bottom_pipe->plane_state->visible) { 21383be5262eSHarry Wentland if (pipe_ctx->plane_state->visible) 21394562236bSHarry Wentland blender_mode = BLND_MODE_BLENDING; 21404562236bSHarry Wentland else 21414562236bSHarry Wentland blender_mode = BLND_MODE_OTHER_PIPE; 2142b06b7680SLeon Elazar 21433be5262eSHarry Wentland } else if (!pipe_ctx->plane_state->visible) 2144b06b7680SLeon Elazar blank_target = true; 2145b06b7680SLeon Elazar 21463be5262eSHarry Wentland } else if (!pipe_ctx->plane_state->visible) 2147b06b7680SLeon Elazar blank_target = true; 2148b06b7680SLeon Elazar 2149e07f541fSYongqiang Sun dce_set_blender_mode(dc->hwseq, pipe_ctx->stream_res.tg->inst, blender_mode); 21506b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, blank_target); 2151b06b7680SLeon Elazar 21524562236bSHarry Wentland } 21534562236bSHarry Wentland 21541bf56e62SZeyu Fan static void program_gamut_remap(struct pipe_ctx *pipe_ctx) 21551bf56e62SZeyu Fan { 2156146a9f63SKrunoslav Kovac int i = 0; 21571bf56e62SZeyu Fan struct xfm_grph_csc_adjustment adjust; 21581bf56e62SZeyu Fan memset(&adjust, 0, sizeof(adjust)); 21591bf56e62SZeyu Fan adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; 21601bf56e62SZeyu Fan 21611bf56e62SZeyu Fan 21624fa086b9SLeo (Sunpeng) Li if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { 21631bf56e62SZeyu Fan adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; 2164146a9f63SKrunoslav Kovac 2165146a9f63SKrunoslav Kovac for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++) 2166146a9f63SKrunoslav Kovac adjust.temperature_matrix[i] = 2167146a9f63SKrunoslav Kovac pipe_ctx->stream->gamut_remap_matrix.matrix[i]; 21681bf56e62SZeyu Fan } 21691bf56e62SZeyu Fan 217086a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); 21711bf56e62SZeyu Fan } 2172fb3466a4SBhawanpreet Lakha static void update_plane_addr(const struct dc *dc, 21734562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 21744562236bSHarry Wentland { 21753be5262eSHarry Wentland struct dc_plane_state *plane_state = pipe_ctx->plane_state; 21764562236bSHarry Wentland 21773be5262eSHarry Wentland if (plane_state == NULL) 21784562236bSHarry Wentland return; 21794562236bSHarry Wentland 218086a66c4eSHarry Wentland pipe_ctx->plane_res.mi->funcs->mem_input_program_surface_flip_and_addr( 218186a66c4eSHarry Wentland pipe_ctx->plane_res.mi, 21823be5262eSHarry Wentland &plane_state->address, 21833be5262eSHarry Wentland plane_state->flip_immediate); 21844562236bSHarry Wentland 21853be5262eSHarry Wentland plane_state->status.requested_address = plane_state->address; 21864562236bSHarry Wentland } 21874562236bSHarry Wentland 2188f774b339SEric Yang static void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) 21894562236bSHarry Wentland { 21903be5262eSHarry Wentland struct dc_plane_state *plane_state = pipe_ctx->plane_state; 21914562236bSHarry Wentland 21923be5262eSHarry Wentland if (plane_state == NULL) 21934562236bSHarry Wentland return; 21944562236bSHarry Wentland 21953be5262eSHarry Wentland plane_state->status.is_flip_pending = 219686a66c4eSHarry Wentland pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending( 219786a66c4eSHarry Wentland pipe_ctx->plane_res.mi); 21984562236bSHarry Wentland 21993be5262eSHarry Wentland if (plane_state->status.is_flip_pending && !plane_state->visible) 220086a66c4eSHarry Wentland pipe_ctx->plane_res.mi->current_address = pipe_ctx->plane_res.mi->request_address; 22014562236bSHarry Wentland 220286a66c4eSHarry Wentland plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address; 220386a66c4eSHarry Wentland if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && 22046b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye) { 22053be5262eSHarry Wentland plane_state->status.is_right_eye =\ 22066b670fa9SHarry Wentland !pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg); 22077f5c22d1SVitaly Prosyak } 22084562236bSHarry Wentland } 22094562236bSHarry Wentland 2210fb3466a4SBhawanpreet Lakha void dce110_power_down(struct dc *dc) 22114562236bSHarry Wentland { 22124562236bSHarry Wentland power_down_all_hw_blocks(dc); 22134562236bSHarry Wentland disable_vga_and_power_gate_all_controllers(dc); 22144562236bSHarry Wentland } 22154562236bSHarry Wentland 22164562236bSHarry Wentland static bool wait_for_reset_trigger_to_occur( 22174562236bSHarry Wentland struct dc_context *dc_ctx, 22184562236bSHarry Wentland struct timing_generator *tg) 22194562236bSHarry Wentland { 22204562236bSHarry Wentland bool rc = false; 22214562236bSHarry Wentland 22224562236bSHarry Wentland /* To avoid endless loop we wait at most 22234562236bSHarry Wentland * frames_to_wait_on_triggered_reset frames for the reset to occur. */ 22244562236bSHarry Wentland const uint32_t frames_to_wait_on_triggered_reset = 10; 22254562236bSHarry Wentland uint32_t i; 22264562236bSHarry Wentland 22274562236bSHarry Wentland for (i = 0; i < frames_to_wait_on_triggered_reset; i++) { 22284562236bSHarry Wentland 22294562236bSHarry Wentland if (!tg->funcs->is_counter_moving(tg)) { 22304562236bSHarry Wentland DC_ERROR("TG counter is not moving!\n"); 22314562236bSHarry Wentland break; 22324562236bSHarry Wentland } 22334562236bSHarry Wentland 22344562236bSHarry Wentland if (tg->funcs->did_triggered_reset_occur(tg)) { 22354562236bSHarry Wentland rc = true; 22364562236bSHarry Wentland /* usually occurs at i=1 */ 22374562236bSHarry Wentland DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n", 22384562236bSHarry Wentland i); 22394562236bSHarry Wentland break; 22404562236bSHarry Wentland } 22414562236bSHarry Wentland 22424562236bSHarry Wentland /* Wait for one frame. */ 22434562236bSHarry Wentland tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE); 22444562236bSHarry Wentland tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK); 22454562236bSHarry Wentland } 22464562236bSHarry Wentland 22474562236bSHarry Wentland if (false == rc) 22484562236bSHarry Wentland DC_ERROR("GSL: Timeout on reset trigger!\n"); 22494562236bSHarry Wentland 22504562236bSHarry Wentland return rc; 22514562236bSHarry Wentland } 22524562236bSHarry Wentland 22534562236bSHarry Wentland /* Enable timing synchronization for a group of Timing Generators. */ 22544562236bSHarry Wentland static void dce110_enable_timing_synchronization( 2255fb3466a4SBhawanpreet Lakha struct dc *dc, 22564562236bSHarry Wentland int group_index, 22574562236bSHarry Wentland int group_size, 22584562236bSHarry Wentland struct pipe_ctx *grouped_pipes[]) 22594562236bSHarry Wentland { 22604562236bSHarry Wentland struct dc_context *dc_ctx = dc->ctx; 22614562236bSHarry Wentland struct dcp_gsl_params gsl_params = { 0 }; 22624562236bSHarry Wentland int i; 22634562236bSHarry Wentland 22644562236bSHarry Wentland DC_SYNC_INFO("GSL: Setting-up...\n"); 22654562236bSHarry Wentland 22664562236bSHarry Wentland /* Designate a single TG in the group as a master. 22674562236bSHarry Wentland * Since HW doesn't care which one, we always assign 22684562236bSHarry Wentland * the 1st one in the group. */ 22694562236bSHarry Wentland gsl_params.gsl_group = 0; 22706b670fa9SHarry Wentland gsl_params.gsl_master = grouped_pipes[0]->stream_res.tg->inst; 22714562236bSHarry Wentland 22724562236bSHarry Wentland for (i = 0; i < group_size; i++) 22736b670fa9SHarry Wentland grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock( 22746b670fa9SHarry Wentland grouped_pipes[i]->stream_res.tg, &gsl_params); 22754562236bSHarry Wentland 22764562236bSHarry Wentland /* Reset slave controllers on master VSync */ 22774562236bSHarry Wentland DC_SYNC_INFO("GSL: enabling trigger-reset\n"); 22784562236bSHarry Wentland 22794562236bSHarry Wentland for (i = 1 /* skip the master */; i < group_size; i++) 22806b670fa9SHarry Wentland grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger( 2281fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg, 2282fa2123dbSMikita Lipski gsl_params.gsl_group); 22834562236bSHarry Wentland 22844562236bSHarry Wentland for (i = 1 /* skip the master */; i < group_size; i++) { 22854562236bSHarry Wentland DC_SYNC_INFO("GSL: waiting for reset to occur.\n"); 22866b670fa9SHarry Wentland wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg); 2287fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger( 2288fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg); 22894562236bSHarry Wentland } 22904562236bSHarry Wentland 22914562236bSHarry Wentland /* GSL Vblank synchronization is a one time sync mechanism, assumption 22924562236bSHarry Wentland * is that the sync'ed displays will not drift out of sync over time*/ 22934562236bSHarry Wentland DC_SYNC_INFO("GSL: Restoring register states.\n"); 22944562236bSHarry Wentland for (i = 0; i < group_size; i++) 22956b670fa9SHarry Wentland grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg); 22964562236bSHarry Wentland 22974562236bSHarry Wentland DC_SYNC_INFO("GSL: Set-up complete.\n"); 22984562236bSHarry Wentland } 22994562236bSHarry Wentland 2300fa2123dbSMikita Lipski static void dce110_enable_per_frame_crtc_position_reset( 2301fa2123dbSMikita Lipski struct dc *dc, 2302fa2123dbSMikita Lipski int group_size, 2303fa2123dbSMikita Lipski struct pipe_ctx *grouped_pipes[]) 2304fa2123dbSMikita Lipski { 2305fa2123dbSMikita Lipski struct dc_context *dc_ctx = dc->ctx; 2306fa2123dbSMikita Lipski struct dcp_gsl_params gsl_params = { 0 }; 2307fa2123dbSMikita Lipski int i; 2308fa2123dbSMikita Lipski 2309fa2123dbSMikita Lipski gsl_params.gsl_group = 0; 231037cd85ceSDavid Francis gsl_params.gsl_master = 0; 2311fa2123dbSMikita Lipski 2312fa2123dbSMikita Lipski for (i = 0; i < group_size; i++) 2313fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock( 2314fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg, &gsl_params); 2315fa2123dbSMikita Lipski 2316fa2123dbSMikita Lipski DC_SYNC_INFO("GSL: enabling trigger-reset\n"); 2317fa2123dbSMikita Lipski 2318fa2123dbSMikita Lipski for (i = 1; i < group_size; i++) 2319fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset( 2320fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg, 2321fa2123dbSMikita Lipski gsl_params.gsl_master, 2322fa2123dbSMikita Lipski &grouped_pipes[i]->stream->triggered_crtc_reset); 2323fa2123dbSMikita Lipski 2324fa2123dbSMikita Lipski DC_SYNC_INFO("GSL: waiting for reset to occur.\n"); 2325fa2123dbSMikita Lipski for (i = 1; i < group_size; i++) 2326fa2123dbSMikita Lipski wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg); 2327fa2123dbSMikita Lipski 2328fa2123dbSMikita Lipski for (i = 0; i < group_size; i++) 2329fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg); 2330fa2123dbSMikita Lipski 2331fa2123dbSMikita Lipski } 2332fa2123dbSMikita Lipski 2333fb55546eSAnthony Koo static void init_pipes(struct dc *dc, struct dc_state *context) 2334fb55546eSAnthony Koo { 2335fb55546eSAnthony Koo // Do nothing 2336fb55546eSAnthony Koo } 2337fb55546eSAnthony Koo 2338fb3466a4SBhawanpreet Lakha static void init_hw(struct dc *dc) 23394562236bSHarry Wentland { 23404562236bSHarry Wentland int i; 23414562236bSHarry Wentland struct dc_bios *bp; 23424562236bSHarry Wentland struct transform *xfm; 23435e7773a2SAnthony Koo struct abm *abm; 234470d9e8cbSPaul Hsieh struct dmcu *dmcu; 23454562236bSHarry Wentland 23464562236bSHarry Wentland bp = dc->ctx->dc_bios; 23474562236bSHarry Wentland for (i = 0; i < dc->res_pool->pipe_count; i++) { 23484562236bSHarry Wentland xfm = dc->res_pool->transforms[i]; 23494562236bSHarry Wentland xfm->funcs->transform_reset(xfm); 23504562236bSHarry Wentland 23514562236bSHarry Wentland dc->hwss.enable_display_power_gating( 23524562236bSHarry Wentland dc, i, bp, 23534562236bSHarry Wentland PIPE_GATING_CONTROL_INIT); 23544562236bSHarry Wentland dc->hwss.enable_display_power_gating( 23554562236bSHarry Wentland dc, i, bp, 23564562236bSHarry Wentland PIPE_GATING_CONTROL_DISABLE); 23574562236bSHarry Wentland dc->hwss.enable_display_pipe_clock_gating( 23584562236bSHarry Wentland dc->ctx, 23594562236bSHarry Wentland true); 23604562236bSHarry Wentland } 23614562236bSHarry Wentland 2362e166ad43SJulia Lawall dce_clock_gating_power_up(dc->hwseq, false); 23634562236bSHarry Wentland /***************************************/ 23644562236bSHarry Wentland 23654562236bSHarry Wentland for (i = 0; i < dc->link_count; i++) { 23664562236bSHarry Wentland /****************************************/ 23674562236bSHarry Wentland /* Power up AND update implementation according to the 23684562236bSHarry Wentland * required signal (which may be different from the 23694562236bSHarry Wentland * default signal on connector). */ 2370d0778ebfSHarry Wentland struct dc_link *link = dc->links[i]; 2371069d418fSAndrew Jiang 23724562236bSHarry Wentland link->link_enc->funcs->hw_init(link->link_enc); 23734562236bSHarry Wentland } 23744562236bSHarry Wentland 23754562236bSHarry Wentland for (i = 0; i < dc->res_pool->pipe_count; i++) { 23764562236bSHarry Wentland struct timing_generator *tg = dc->res_pool->timing_generators[i]; 23774562236bSHarry Wentland 23784562236bSHarry Wentland tg->funcs->disable_vga(tg); 23794562236bSHarry Wentland 23804562236bSHarry Wentland /* Blank controller using driver code instead of 23814562236bSHarry Wentland * command table. */ 23824562236bSHarry Wentland tg->funcs->set_blank(tg, true); 23834b5e7d62SHersen Wu hwss_wait_for_blank_complete(tg); 23844562236bSHarry Wentland } 23854562236bSHarry Wentland 23864562236bSHarry Wentland for (i = 0; i < dc->res_pool->audio_count; i++) { 23874562236bSHarry Wentland struct audio *audio = dc->res_pool->audios[i]; 23884562236bSHarry Wentland audio->funcs->hw_init(audio); 23894562236bSHarry Wentland } 23905e7773a2SAnthony Koo 23915e7773a2SAnthony Koo abm = dc->res_pool->abm; 23926728b30cSAnthony Koo if (abm != NULL) { 23936728b30cSAnthony Koo abm->funcs->init_backlight(abm); 23945e7773a2SAnthony Koo abm->funcs->abm_init(abm); 23954562236bSHarry Wentland } 23965099114bSAlex Deucher 239770d9e8cbSPaul Hsieh dmcu = dc->res_pool->dmcu; 239870d9e8cbSPaul Hsieh if (dmcu != NULL && abm != NULL) 239970d9e8cbSPaul Hsieh abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu); 240070d9e8cbSPaul Hsieh 24012f3bfb27SRoman Li if (dc->fbc_compressor) 24021663ae1cSBhawanpreet Lakha dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor); 2403690b5e39SRoman Li 24046728b30cSAnthony Koo } 24054562236bSHarry Wentland 24069566b675SDmytro Laktyushkin 24079566b675SDmytro Laktyushkin void dce110_prepare_bandwidth( 2408fb3466a4SBhawanpreet Lakha struct dc *dc, 24099566b675SDmytro Laktyushkin struct dc_state *context) 2410cf437593SDmytro Laktyushkin { 2411dc88b4a6SEric Yang struct clk_mgr *dccg = dc->clk_mgr; 2412fab55d61SDmytro Laktyushkin 2413fab55d61SDmytro Laktyushkin dce110_set_safe_displaymarks(&context->res_ctx, dc->res_pool); 2414cf437593SDmytro Laktyushkin 24155a83c932SNicholas Kazlauskas dccg->funcs->update_clocks( 24165a83c932SNicholas Kazlauskas dccg, 241724f7dd7eSDmytro Laktyushkin context, 24189566b675SDmytro Laktyushkin false); 24199566b675SDmytro Laktyushkin } 24209566b675SDmytro Laktyushkin 24219566b675SDmytro Laktyushkin void dce110_optimize_bandwidth( 24229566b675SDmytro Laktyushkin struct dc *dc, 24239566b675SDmytro Laktyushkin struct dc_state *context) 24249566b675SDmytro Laktyushkin { 2425dc88b4a6SEric Yang struct clk_mgr *dccg = dc->clk_mgr; 24269566b675SDmytro Laktyushkin 24279566b675SDmytro Laktyushkin dce110_set_displaymarks(dc, context); 24289566b675SDmytro Laktyushkin 24299566b675SDmytro Laktyushkin dccg->funcs->update_clocks( 24309566b675SDmytro Laktyushkin dccg, 24319566b675SDmytro Laktyushkin context, 24329566b675SDmytro Laktyushkin true); 24334562236bSHarry Wentland } 24344562236bSHarry Wentland 24354562236bSHarry Wentland static void dce110_program_front_end_for_pipe( 2436fb3466a4SBhawanpreet Lakha struct dc *dc, struct pipe_ctx *pipe_ctx) 24374562236bSHarry Wentland { 243886a66c4eSHarry Wentland struct mem_input *mi = pipe_ctx->plane_res.mi; 24394562236bSHarry Wentland struct pipe_ctx *old_pipe = NULL; 24403be5262eSHarry Wentland struct dc_plane_state *plane_state = pipe_ctx->plane_state; 24414562236bSHarry Wentland struct xfm_grph_csc_adjustment adjust; 24424562236bSHarry Wentland struct out_csc_color_matrix tbl_entry; 24434562236bSHarry Wentland unsigned int i; 24445d4b05ddSBhawanpreet Lakha DC_LOGGER_INIT(); 24454562236bSHarry Wentland memset(&tbl_entry, 0, sizeof(tbl_entry)); 24464562236bSHarry Wentland 2447608ac7bbSJerry Zuo if (dc->current_state) 2448608ac7bbSJerry Zuo old_pipe = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; 24494562236bSHarry Wentland 24504562236bSHarry Wentland memset(&adjust, 0, sizeof(adjust)); 24514562236bSHarry Wentland adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; 24524562236bSHarry Wentland 2453e07f541fSYongqiang Sun dce_enable_fe_clock(dc->hwseq, mi->inst, true); 24544562236bSHarry Wentland 24554562236bSHarry Wentland set_default_colors(pipe_ctx); 24564fa086b9SLeo (Sunpeng) Li if (pipe_ctx->stream->csc_color_matrix.enable_adjustment 24574562236bSHarry Wentland == true) { 24584562236bSHarry Wentland tbl_entry.color_space = 24594fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->output_color_space; 24604562236bSHarry Wentland 24614562236bSHarry Wentland for (i = 0; i < 12; i++) 24624562236bSHarry Wentland tbl_entry.regval[i] = 24634fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->csc_color_matrix.matrix[i]; 24644562236bSHarry Wentland 246586a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment 246686a66c4eSHarry Wentland (pipe_ctx->plane_res.xfm, &tbl_entry); 24674562236bSHarry Wentland } 24684562236bSHarry Wentland 24694fa086b9SLeo (Sunpeng) Li if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { 24704562236bSHarry Wentland adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; 2471146a9f63SKrunoslav Kovac 2472146a9f63SKrunoslav Kovac for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++) 2473146a9f63SKrunoslav Kovac adjust.temperature_matrix[i] = 2474146a9f63SKrunoslav Kovac pipe_ctx->stream->gamut_remap_matrix.matrix[i]; 24754562236bSHarry Wentland } 24764562236bSHarry Wentland 247786a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); 24784562236bSHarry Wentland 24796702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; 2480c1473558SAndrey Grodzovsky 24814562236bSHarry Wentland program_scaler(dc, pipe_ctx); 24824562236bSHarry Wentland 24834562236bSHarry Wentland mi->funcs->mem_input_program_surface_config( 24844562236bSHarry Wentland mi, 24853be5262eSHarry Wentland plane_state->format, 24863be5262eSHarry Wentland &plane_state->tiling_info, 24873be5262eSHarry Wentland &plane_state->plane_size, 24883be5262eSHarry Wentland plane_state->rotation, 2489624d7c47SYongqiang Sun NULL, 24904b28b76bSDmytro Laktyushkin false); 24914b28b76bSDmytro Laktyushkin if (mi->funcs->set_blank) 24923be5262eSHarry Wentland mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible); 24934562236bSHarry Wentland 2494fb3466a4SBhawanpreet Lakha if (dc->config.gpu_vm_support) 24954562236bSHarry Wentland mi->funcs->mem_input_program_pte_vm( 249686a66c4eSHarry Wentland pipe_ctx->plane_res.mi, 24973be5262eSHarry Wentland plane_state->format, 24983be5262eSHarry Wentland &plane_state->tiling_info, 24993be5262eSHarry Wentland plane_state->rotation); 25004562236bSHarry Wentland 2501067c878aSYongqiang Sun /* Moved programming gamma from dc to hwss */ 2502405c50a0SAndrew Jiang if (pipe_ctx->plane_state->update_flags.bits.full_update || 2503405c50a0SAndrew Jiang pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change || 2504405c50a0SAndrew Jiang pipe_ctx->plane_state->update_flags.bits.gamma_change) 2505a6114e85SHarry Wentland dc->hwss.set_input_transfer_func(pipe_ctx, pipe_ctx->plane_state); 2506405c50a0SAndrew Jiang 2507405c50a0SAndrew Jiang if (pipe_ctx->plane_state->update_flags.bits.full_update) 2508a6114e85SHarry Wentland dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream); 2509067c878aSYongqiang Sun 25101296423bSBhawanpreet Lakha DC_LOG_SURFACE( 25113032deb5SBhawanpreet Lakha "Pipe:%d %p: addr hi:0x%x, " 25124562236bSHarry Wentland "addr low:0x%x, " 25134562236bSHarry Wentland "src: %d, %d, %d," 25144562236bSHarry Wentland " %d; dst: %d, %d, %d, %d;" 25154562236bSHarry Wentland "clip: %d, %d, %d, %d\n", 25164562236bSHarry Wentland pipe_ctx->pipe_idx, 25173032deb5SBhawanpreet Lakha (void *) pipe_ctx->plane_state, 25183be5262eSHarry Wentland pipe_ctx->plane_state->address.grph.addr.high_part, 25193be5262eSHarry Wentland pipe_ctx->plane_state->address.grph.addr.low_part, 25203be5262eSHarry Wentland pipe_ctx->plane_state->src_rect.x, 25213be5262eSHarry Wentland pipe_ctx->plane_state->src_rect.y, 25223be5262eSHarry Wentland pipe_ctx->plane_state->src_rect.width, 25233be5262eSHarry Wentland pipe_ctx->plane_state->src_rect.height, 25243be5262eSHarry Wentland pipe_ctx->plane_state->dst_rect.x, 25253be5262eSHarry Wentland pipe_ctx->plane_state->dst_rect.y, 25263be5262eSHarry Wentland pipe_ctx->plane_state->dst_rect.width, 25273be5262eSHarry Wentland pipe_ctx->plane_state->dst_rect.height, 25283be5262eSHarry Wentland pipe_ctx->plane_state->clip_rect.x, 25293be5262eSHarry Wentland pipe_ctx->plane_state->clip_rect.y, 25303be5262eSHarry Wentland pipe_ctx->plane_state->clip_rect.width, 25313be5262eSHarry Wentland pipe_ctx->plane_state->clip_rect.height); 25324562236bSHarry Wentland 25331296423bSBhawanpreet Lakha DC_LOG_SURFACE( 25344562236bSHarry Wentland "Pipe %d: width, height, x, y\n" 25354562236bSHarry Wentland "viewport:%d, %d, %d, %d\n" 25364562236bSHarry Wentland "recout: %d, %d, %d, %d\n", 25374562236bSHarry Wentland pipe_ctx->pipe_idx, 25386702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.width, 25396702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.height, 25406702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.x, 25416702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.y, 25426702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.width, 25436702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.height, 25446702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.x, 25456702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.y); 25464562236bSHarry Wentland } 25474562236bSHarry Wentland 25484562236bSHarry Wentland static void dce110_apply_ctx_for_surface( 2549fb3466a4SBhawanpreet Lakha struct dc *dc, 25503e9ad616SEric Yang const struct dc_stream_state *stream, 25513e9ad616SEric Yang int num_planes, 2552608ac7bbSJerry Zuo struct dc_state *context) 25534562236bSHarry Wentland { 25542194e3aeSRoman Li int i; 25554562236bSHarry Wentland 25563e9ad616SEric Yang if (num_planes == 0) 25574562236bSHarry Wentland return; 25584562236bSHarry Wentland 255965d38262Shersen wu if (dc->fbc_compressor) 256065d38262Shersen wu dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); 256165d38262Shersen wu 25623e9ad616SEric Yang for (i = 0; i < dc->res_pool->pipe_count; i++) { 25633dc780ecSYongqiang Sun struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 25643dc780ecSYongqiang Sun struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; 25653dc780ecSYongqiang Sun 25662194e3aeSRoman Li if (stream == pipe_ctx->stream) { 25673dc780ecSYongqiang Sun if (!pipe_ctx->top_pipe && 25683dc780ecSYongqiang Sun (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) 25693dc780ecSYongqiang Sun dc->hwss.pipe_control_lock(dc, pipe_ctx, true); 25703e9ad616SEric Yang } 25713e9ad616SEric Yang } 25723e9ad616SEric Yang 2573a2b8659dSTony Cheng for (i = 0; i < dc->res_pool->pipe_count; i++) { 25744562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 25754562236bSHarry Wentland 2576a2607aefSHarry Wentland if (pipe_ctx->stream != stream) 25774562236bSHarry Wentland continue; 25784562236bSHarry Wentland 25793b21b6d2SJerry Zuo /* Need to allocate mem before program front end for Fiji */ 25803b21b6d2SJerry Zuo pipe_ctx->plane_res.mi->funcs->allocate_mem_input( 25813b21b6d2SJerry Zuo pipe_ctx->plane_res.mi, 25823b21b6d2SJerry Zuo pipe_ctx->stream->timing.h_total, 25833b21b6d2SJerry Zuo pipe_ctx->stream->timing.v_total, 2584380604e2SKen Chalmers pipe_ctx->stream->timing.pix_clk_100hz / 10, 25853b21b6d2SJerry Zuo context->stream_count); 25863b21b6d2SJerry Zuo 25874562236bSHarry Wentland dce110_program_front_end_for_pipe(dc, pipe_ctx); 25884f804817SYongqiang Sun 25894f804817SYongqiang Sun dc->hwss.update_plane_addr(dc, pipe_ctx); 25904f804817SYongqiang Sun 2591b06b7680SLeon Elazar program_surface_visibility(dc, pipe_ctx); 25924562236bSHarry Wentland 25934562236bSHarry Wentland } 25943dc780ecSYongqiang Sun 25953dc780ecSYongqiang Sun for (i = 0; i < dc->res_pool->pipe_count; i++) { 25963dc780ecSYongqiang Sun struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 25973dc780ecSYongqiang Sun struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; 25983dc780ecSYongqiang Sun 25993dc780ecSYongqiang Sun if ((stream == pipe_ctx->stream) && 26003dc780ecSYongqiang Sun (!pipe_ctx->top_pipe) && 26013dc780ecSYongqiang Sun (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) 26023dc780ecSYongqiang Sun dc->hwss.pipe_control_lock(dc, pipe_ctx, false); 26033dc780ecSYongqiang Sun } 260465d38262Shersen wu 260565d38262Shersen wu if (dc->fbc_compressor) 260612a8bd88SShirish S enable_fbc(dc, context); 26074562236bSHarry Wentland } 26084562236bSHarry Wentland 2609e6c258cbSYongqiang Sun static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx) 26104562236bSHarry Wentland { 2611bc373a89SRoman Li int fe_idx = pipe_ctx->plane_res.mi ? 2612bc373a89SRoman Li pipe_ctx->plane_res.mi->inst : pipe_ctx->pipe_idx; 2613e6c258cbSYongqiang Sun 26147950f0f9SDmytro Laktyushkin /* Do not power down fe when stream is active on dce*/ 2615608ac7bbSJerry Zuo if (dc->current_state->res_ctx.pipe_ctx[fe_idx].stream) 26164562236bSHarry Wentland return; 26174562236bSHarry Wentland 26184562236bSHarry Wentland dc->hwss.enable_display_power_gating( 2619cfe4645eSDmytro Laktyushkin dc, fe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE); 2620cfe4645eSDmytro Laktyushkin 2621cfe4645eSDmytro Laktyushkin dc->res_pool->transforms[fe_idx]->funcs->transform_reset( 2622cfe4645eSDmytro Laktyushkin dc->res_pool->transforms[fe_idx]); 26234562236bSHarry Wentland } 26244562236bSHarry Wentland 26256be425f3SEric Yang static void dce110_wait_for_mpcc_disconnect( 2626fb3466a4SBhawanpreet Lakha struct dc *dc, 26276be425f3SEric Yang struct resource_pool *res_pool, 26286be425f3SEric Yang struct pipe_ctx *pipe_ctx) 2629b6762f0cSEric Yang { 2630b6762f0cSEric Yang /* do nothing*/ 2631b6762f0cSEric Yang } 2632b6762f0cSEric Yang 26334bd0dc68SJoshua Aberback static void program_output_csc(struct dc *dc, 26344bd0dc68SJoshua Aberback struct pipe_ctx *pipe_ctx, 26354bd0dc68SJoshua Aberback enum dc_color_space colorspace, 26364bd0dc68SJoshua Aberback uint16_t *matrix, 26374bd0dc68SJoshua Aberback int opp_id) 26384bd0dc68SJoshua Aberback { 26394bd0dc68SJoshua Aberback int i; 26404bd0dc68SJoshua Aberback struct out_csc_color_matrix tbl_entry; 26414bd0dc68SJoshua Aberback 26424bd0dc68SJoshua Aberback if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { 26434bd0dc68SJoshua Aberback enum dc_color_space color_space = pipe_ctx->stream->output_color_space; 26444bd0dc68SJoshua Aberback 26454bd0dc68SJoshua Aberback for (i = 0; i < 12; i++) 26464bd0dc68SJoshua Aberback tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; 26474bd0dc68SJoshua Aberback 26484bd0dc68SJoshua Aberback tbl_entry.color_space = color_space; 26494bd0dc68SJoshua Aberback 26504bd0dc68SJoshua Aberback pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment( 26514bd0dc68SJoshua Aberback pipe_ctx->plane_res.xfm, &tbl_entry); 26524bd0dc68SJoshua Aberback } 26534bd0dc68SJoshua Aberback } 26544bd0dc68SJoshua Aberback 265533fd17d9SEric Yang void dce110_set_cursor_position(struct pipe_ctx *pipe_ctx) 265633fd17d9SEric Yang { 265733fd17d9SEric Yang struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position; 265833fd17d9SEric Yang struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; 265933fd17d9SEric Yang struct mem_input *mi = pipe_ctx->plane_res.mi; 266033fd17d9SEric Yang struct dc_cursor_mi_param param = { 2661380604e2SKen Chalmers .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10, 266233d7598dSJun Lei .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clocks.xtalin_clock_inKhz, 266339a9f4d8SDmytro Laktyushkin .viewport = pipe_ctx->plane_res.scl_data.viewport, 266439a9f4d8SDmytro Laktyushkin .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz, 266539a9f4d8SDmytro Laktyushkin .v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert, 266608ed681cSDmytro Laktyushkin .rotation = pipe_ctx->plane_state->rotation, 266708ed681cSDmytro Laktyushkin .mirror = pipe_ctx->plane_state->horizontal_mirror 266833fd17d9SEric Yang }; 266933fd17d9SEric Yang 267033fd17d9SEric Yang if (pipe_ctx->plane_state->address.type 267133fd17d9SEric Yang == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) 267233fd17d9SEric Yang pos_cpy.enable = false; 267333fd17d9SEric Yang 267433fd17d9SEric Yang if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) 267533fd17d9SEric Yang pos_cpy.enable = false; 267633fd17d9SEric Yang 2677dc75dd70SRoman Li if (ipp->funcs->ipp_cursor_set_position) 267833fd17d9SEric Yang ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); 2679dc75dd70SRoman Li if (mi->funcs->set_cursor_position) 268033fd17d9SEric Yang mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m); 268133fd17d9SEric Yang } 268233fd17d9SEric Yang 268333fd17d9SEric Yang void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx) 268433fd17d9SEric Yang { 268533fd17d9SEric Yang struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes; 268633fd17d9SEric Yang 2687d1aaad05SHarry Wentland if (pipe_ctx->plane_res.ipp && 2688d1aaad05SHarry Wentland pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes) 268933fd17d9SEric Yang pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( 269033fd17d9SEric Yang pipe_ctx->plane_res.ipp, attributes); 269133fd17d9SEric Yang 2692d1aaad05SHarry Wentland if (pipe_ctx->plane_res.mi && 2693d1aaad05SHarry Wentland pipe_ctx->plane_res.mi->funcs->set_cursor_attributes) 269433fd17d9SEric Yang pipe_ctx->plane_res.mi->funcs->set_cursor_attributes( 269533fd17d9SEric Yang pipe_ctx->plane_res.mi, attributes); 269633fd17d9SEric Yang 2697d1aaad05SHarry Wentland if (pipe_ctx->plane_res.xfm && 2698d1aaad05SHarry Wentland pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes) 269933fd17d9SEric Yang pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes( 270033fd17d9SEric Yang pipe_ctx->plane_res.xfm, attributes); 270133fd17d9SEric Yang } 270233fd17d9SEric Yang 27034562236bSHarry Wentland static const struct hw_sequencer_funcs dce110_funcs = { 27041bf56e62SZeyu Fan .program_gamut_remap = program_gamut_remap, 27054bd0dc68SJoshua Aberback .program_output_csc = program_output_csc, 27064562236bSHarry Wentland .init_hw = init_hw, 2707fb55546eSAnthony Koo .init_pipes = init_pipes, 27084562236bSHarry Wentland .apply_ctx_to_hw = dce110_apply_ctx_to_hw, 27094562236bSHarry Wentland .apply_ctx_for_surface = dce110_apply_ctx_for_surface, 27104562236bSHarry Wentland .update_plane_addr = update_plane_addr, 27114562236bSHarry Wentland .update_pending_status = dce110_update_pending_status, 2712d7194cf6SAric Cyr .set_input_transfer_func = dce110_set_input_transfer_func, 271390e508baSAnthony Koo .set_output_transfer_func = dce110_set_output_transfer_func, 27144562236bSHarry Wentland .power_down = dce110_power_down, 27154562236bSHarry Wentland .enable_accelerated_mode = dce110_enable_accelerated_mode, 27164562236bSHarry Wentland .enable_timing_synchronization = dce110_enable_timing_synchronization, 2717fa2123dbSMikita Lipski .enable_per_frame_crtc_position_reset = dce110_enable_per_frame_crtc_position_reset, 27184562236bSHarry Wentland .update_info_frame = dce110_update_info_frame, 27194562236bSHarry Wentland .enable_stream = dce110_enable_stream, 27204562236bSHarry Wentland .disable_stream = dce110_disable_stream, 27214562236bSHarry Wentland .unblank_stream = dce110_unblank_stream, 272241b49742SCharlene Liu .blank_stream = dce110_blank_stream, 27231a05873fSAnthony Koo .enable_audio_stream = dce110_enable_audio_stream, 27241a05873fSAnthony Koo .disable_audio_stream = dce110_disable_audio_stream, 27254562236bSHarry Wentland .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating, 27264562236bSHarry Wentland .enable_display_power_gating = dce110_enable_display_power_gating, 27277f914a62SYongqiang Sun .disable_plane = dce110_power_down_fe, 27284562236bSHarry Wentland .pipe_control_lock = dce_pipe_control_lock, 27299566b675SDmytro Laktyushkin .prepare_bandwidth = dce110_prepare_bandwidth, 27309566b675SDmytro Laktyushkin .optimize_bandwidth = dce110_optimize_bandwidth, 27314562236bSHarry Wentland .set_drr = set_drr, 273272ada5f7SEric Cook .get_position = get_position, 27334562236bSHarry Wentland .set_static_screen_control = set_static_screen_control, 273454e8695eSDmytro Laktyushkin .reset_hw_ctx_wrap = dce110_reset_hw_ctx_wrap, 27353158223eSEric Bernstein .enable_stream_timing = dce110_enable_stream_timing, 2736240d09d0SGary Kattan .disable_stream_gating = NULL, 2737240d09d0SGary Kattan .enable_stream_gating = NULL, 273815e17335SCharlene Liu .setup_stereo = NULL, 273915e17335SCharlene Liu .set_avmute = dce110_set_avmute, 274041f97c07SHersen Wu .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect, 274187401969SAndrew Jiang .edp_backlight_control = hwss_edp_backlight_control, 274287401969SAndrew Jiang .edp_power_control = hwss_edp_power_control, 2743904623eeSYongqiang Sun .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready, 274433fd17d9SEric Yang .set_cursor_position = dce110_set_cursor_position, 274533fd17d9SEric Yang .set_cursor_attribute = dce110_set_cursor_attribute 27464562236bSHarry Wentland }; 27474562236bSHarry Wentland 2748c13b408bSDave Airlie void dce110_hw_sequencer_construct(struct dc *dc) 27494562236bSHarry Wentland { 27504562236bSHarry Wentland dc->hwss = dce110_funcs; 27514562236bSHarry Wentland } 27524562236bSHarry Wentland 2753