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 */ 6697ed4e635SHarry Wentland 6707ed4e635SHarry Wentland #if defined(CONFIG_DRM_AMD_DC_DCN2_0) 6717ed4e635SHarry Wentland if (pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata != NULL && 6727ed4e635SHarry Wentland pipe_ctx->plane_res.hubp != NULL) { 6737ed4e635SHarry Wentland if (pipe_ctx->stream->dmdata_address.quad_part != 0) { 6747ed4e635SHarry Wentland /* if using dynamic meta, don't set up generic infopackets */ 6757ed4e635SHarry Wentland pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false; 6767ed4e635SHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata( 6777ed4e635SHarry Wentland pipe_ctx->stream_res.stream_enc, 6787ed4e635SHarry Wentland true, pipe_ctx->plane_res.hubp->inst, 6797ed4e635SHarry Wentland dc_is_dp_signal(pipe_ctx->stream->signal) ? 6807ed4e635SHarry Wentland dmdata_dp : dmdata_hdmi); 6817ed4e635SHarry Wentland } else 6827ed4e635SHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata( 6837ed4e635SHarry Wentland pipe_ctx->stream_res.stream_enc, 6847ed4e635SHarry Wentland false, pipe_ctx->plane_res.hubp->inst, 6857ed4e635SHarry Wentland dc_is_dp_signal(pipe_ctx->stream->signal) ? 6867ed4e635SHarry Wentland dmdata_dp : dmdata_hdmi); 6877ed4e635SHarry Wentland } 6887ed4e635SHarry Wentland #endif 689f215a57dSEric Yang 6904562236bSHarry Wentland /* enable early control to avoid corruption on DP monitor*/ 6914562236bSHarry Wentland active_total_with_borders = 6924562236bSHarry Wentland timing->h_addressable 6934562236bSHarry Wentland + timing->h_border_left 6944562236bSHarry Wentland + timing->h_border_right; 6954562236bSHarry Wentland 6964562236bSHarry Wentland if (lane_count != 0) 6974562236bSHarry Wentland early_control = active_total_with_borders % lane_count; 6984562236bSHarry Wentland 6994562236bSHarry Wentland if (early_control == 0) 7004562236bSHarry Wentland early_control = lane_count; 7014562236bSHarry Wentland 7024562236bSHarry Wentland tg->funcs->set_early_control(tg, early_control); 7034562236bSHarry Wentland 7044562236bSHarry Wentland /* enable audio only within mode set */ 705afaacef4SHarry Wentland if (pipe_ctx->stream_res.audio != NULL) { 7064562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal)) 7078e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc); 7084562236bSHarry Wentland } 7094562236bSHarry Wentland 710f215a57dSEric Yang 711f215a57dSEric Yang 7124562236bSHarry Wentland 7134562236bSHarry Wentland } 7144562236bSHarry Wentland 7155eefbc40SYue Hin Lau /*todo: cloned in stream enc, fix*/ 7165eefbc40SYue Hin Lau static bool is_panel_backlight_on(struct dce_hwseq *hws) 7175eefbc40SYue Hin Lau { 7185eefbc40SYue Hin Lau uint32_t value; 7195eefbc40SYue Hin Lau 7205eefbc40SYue Hin Lau REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value); 7215eefbc40SYue Hin Lau 7225eefbc40SYue Hin Lau return value; 7235eefbc40SYue Hin Lau } 7245eefbc40SYue Hin Lau 72587401969SAndrew Jiang static bool is_panel_powered_on(struct dce_hwseq *hws) 72687401969SAndrew Jiang { 727d03f3f63SEric Yang uint32_t pwr_seq_state, dig_on, dig_on_ovrd; 72887401969SAndrew Jiang 729d03f3f63SEric Yang 730d03f3f63SEric Yang REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &pwr_seq_state); 731d03f3f63SEric Yang 732d03f3f63SEric Yang REG_GET_2(LVTMA_PWRSEQ_CNTL, LVTMA_DIGON, &dig_on, LVTMA_DIGON_OVRD, &dig_on_ovrd); 733d03f3f63SEric Yang 734d03f3f63SEric Yang return (pwr_seq_state == 1) || (dig_on == 1 && dig_on_ovrd == 1); 73587401969SAndrew Jiang } 73687401969SAndrew Jiang 7375eefbc40SYue Hin Lau static enum bp_result link_transmitter_control( 73887401969SAndrew Jiang struct dc_bios *bios, 7395eefbc40SYue Hin Lau struct bp_transmitter_control *cntl) 7405eefbc40SYue Hin Lau { 7415eefbc40SYue Hin Lau enum bp_result result; 7425eefbc40SYue Hin Lau 74387401969SAndrew Jiang result = bios->funcs->transmitter_control(bios, cntl); 7445eefbc40SYue Hin Lau 7455eefbc40SYue Hin Lau return result; 7465eefbc40SYue Hin Lau } 7475eefbc40SYue Hin Lau 74887401969SAndrew Jiang /* 74987401969SAndrew Jiang * @brief 75087401969SAndrew Jiang * eDP only. 75187401969SAndrew Jiang */ 75287401969SAndrew Jiang void hwss_edp_wait_for_hpd_ready( 753069d418fSAndrew Jiang struct dc_link *link, 75487401969SAndrew Jiang bool power_up) 75587401969SAndrew Jiang { 756069d418fSAndrew Jiang struct dc_context *ctx = link->ctx; 757069d418fSAndrew Jiang struct graphics_object_id connector = link->link_enc->connector; 75887401969SAndrew Jiang struct gpio *hpd; 75987401969SAndrew Jiang bool edp_hpd_high = false; 76087401969SAndrew Jiang uint32_t time_elapsed = 0; 76187401969SAndrew Jiang uint32_t timeout = power_up ? 76287401969SAndrew Jiang PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT; 76387401969SAndrew Jiang 76487401969SAndrew Jiang if (dal_graphics_object_id_get_connector_id(connector) 76587401969SAndrew Jiang != CONNECTOR_ID_EDP) { 76687401969SAndrew Jiang BREAK_TO_DEBUGGER(); 76787401969SAndrew Jiang return; 76887401969SAndrew Jiang } 76987401969SAndrew Jiang 77087401969SAndrew Jiang if (!power_up) 77187401969SAndrew Jiang /* 77287401969SAndrew Jiang * From KV, we will not HPD low after turning off VCC - 77387401969SAndrew Jiang * instead, we will check the SW timer in power_up(). 77487401969SAndrew Jiang */ 77587401969SAndrew Jiang return; 77687401969SAndrew Jiang 77787401969SAndrew Jiang /* 77887401969SAndrew Jiang * When we power on/off the eDP panel, 77987401969SAndrew Jiang * we need to wait until SENSE bit is high/low. 78087401969SAndrew Jiang */ 78187401969SAndrew Jiang 78287401969SAndrew Jiang /* obtain HPD */ 78387401969SAndrew Jiang /* TODO what to do with this? */ 78487401969SAndrew Jiang hpd = get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service); 78587401969SAndrew Jiang 78687401969SAndrew Jiang if (!hpd) { 78787401969SAndrew Jiang BREAK_TO_DEBUGGER(); 78887401969SAndrew Jiang return; 78987401969SAndrew Jiang } 79087401969SAndrew Jiang 79187401969SAndrew Jiang dal_gpio_open(hpd, GPIO_MODE_INTERRUPT); 79287401969SAndrew Jiang 79387401969SAndrew Jiang /* wait until timeout or panel detected */ 79487401969SAndrew Jiang 79587401969SAndrew Jiang do { 79687401969SAndrew Jiang uint32_t detected = 0; 79787401969SAndrew Jiang 79887401969SAndrew Jiang dal_gpio_get_value(hpd, &detected); 79987401969SAndrew Jiang 80087401969SAndrew Jiang if (!(detected ^ power_up)) { 80187401969SAndrew Jiang edp_hpd_high = true; 80287401969SAndrew Jiang break; 80387401969SAndrew Jiang } 80487401969SAndrew Jiang 80587401969SAndrew Jiang msleep(HPD_CHECK_INTERVAL); 80687401969SAndrew Jiang 80787401969SAndrew Jiang time_elapsed += HPD_CHECK_INTERVAL; 80887401969SAndrew Jiang } while (time_elapsed < timeout); 80987401969SAndrew Jiang 81087401969SAndrew Jiang dal_gpio_close(hpd); 81187401969SAndrew Jiang 81287401969SAndrew Jiang dal_gpio_destroy_irq(&hpd); 81387401969SAndrew Jiang 81487401969SAndrew Jiang if (false == edp_hpd_high) { 8151296423bSBhawanpreet Lakha DC_LOG_ERROR( 81687401969SAndrew Jiang "%s: wait timed out!\n", __func__); 81787401969SAndrew Jiang } 81887401969SAndrew Jiang } 81987401969SAndrew Jiang 82087401969SAndrew Jiang void hwss_edp_power_control( 821069d418fSAndrew Jiang struct dc_link *link, 82287401969SAndrew Jiang bool power_up) 82387401969SAndrew Jiang { 824069d418fSAndrew Jiang struct dc_context *ctx = link->ctx; 82587401969SAndrew Jiang struct dce_hwseq *hwseq = ctx->dc->hwseq; 82687401969SAndrew Jiang struct bp_transmitter_control cntl = { 0 }; 82787401969SAndrew Jiang enum bp_result bp_result; 82887401969SAndrew Jiang 82987401969SAndrew Jiang 830069d418fSAndrew Jiang if (dal_graphics_object_id_get_connector_id(link->link_enc->connector) 83187401969SAndrew Jiang != CONNECTOR_ID_EDP) { 83287401969SAndrew Jiang BREAK_TO_DEBUGGER(); 83387401969SAndrew Jiang return; 83487401969SAndrew Jiang } 83587401969SAndrew Jiang 83687401969SAndrew Jiang if (power_up != is_panel_powered_on(hwseq)) { 83787401969SAndrew Jiang /* Send VBIOS command to prompt eDP panel power */ 83878d5d04dSCharlene Liu if (power_up) { 83978d5d04dSCharlene Liu unsigned long long current_ts = dm_get_timestamp(ctx); 84078d5d04dSCharlene Liu unsigned long long duration_in_ms = 84193ed1814SHugo Hu div64_u64(dm_get_elapse_time_in_ns( 84278d5d04dSCharlene Liu ctx, 84378d5d04dSCharlene Liu current_ts, 84493ed1814SHugo Hu link->link_trace.time_stamp.edp_poweroff), 1000000); 84578d5d04dSCharlene Liu unsigned long long wait_time_ms = 0; 84678d5d04dSCharlene Liu 84778d5d04dSCharlene Liu /* max 500ms from LCDVDD off to on */ 8486c4fff06SYue Hin Lau unsigned long long edp_poweroff_time_ms = 500; 849ff587987SHugo Hu 8506c4fff06SYue Hin Lau if (link->local_sink != NULL) 8516c4fff06SYue Hin Lau edp_poweroff_time_ms = 8526c4fff06SYue Hin Lau 500 + link->local_sink->edid_caps.panel_patch.extra_t12_ms; 85378d5d04dSCharlene Liu if (link->link_trace.time_stamp.edp_poweroff == 0) 854ff587987SHugo Hu wait_time_ms = edp_poweroff_time_ms; 855ff587987SHugo Hu else if (duration_in_ms < edp_poweroff_time_ms) 856ff587987SHugo Hu wait_time_ms = edp_poweroff_time_ms - duration_in_ms; 85778d5d04dSCharlene Liu 85878d5d04dSCharlene Liu if (wait_time_ms) { 85978d5d04dSCharlene Liu msleep(wait_time_ms); 86078d5d04dSCharlene Liu dm_output_to_console("%s: wait %lld ms to power on eDP.\n", 86178d5d04dSCharlene Liu __func__, wait_time_ms); 86278d5d04dSCharlene Liu } 86378d5d04dSCharlene Liu 86478d5d04dSCharlene Liu } 86587401969SAndrew Jiang 8661296423bSBhawanpreet Lakha DC_LOG_HW_RESUME_S3( 86787401969SAndrew Jiang "%s: Panel Power action: %s\n", 86887401969SAndrew Jiang __func__, (power_up ? "On":"Off")); 86987401969SAndrew Jiang 87087401969SAndrew Jiang cntl.action = power_up ? 87187401969SAndrew Jiang TRANSMITTER_CONTROL_POWER_ON : 87287401969SAndrew Jiang TRANSMITTER_CONTROL_POWER_OFF; 873069d418fSAndrew Jiang cntl.transmitter = link->link_enc->transmitter; 874069d418fSAndrew Jiang cntl.connector_obj_id = link->link_enc->connector; 87587401969SAndrew Jiang cntl.coherent = false; 87687401969SAndrew Jiang cntl.lanes_number = LANE_COUNT_FOUR; 877069d418fSAndrew Jiang cntl.hpd_sel = link->link_enc->hpd_source; 87887401969SAndrew Jiang bp_result = link_transmitter_control(ctx->dc_bios, &cntl); 87987401969SAndrew Jiang 88078d5d04dSCharlene Liu if (!power_up) 88178d5d04dSCharlene Liu /*save driver power off time stamp*/ 88278d5d04dSCharlene Liu link->link_trace.time_stamp.edp_poweroff = dm_get_timestamp(ctx); 88378d5d04dSCharlene Liu else 88478d5d04dSCharlene Liu link->link_trace.time_stamp.edp_poweron = dm_get_timestamp(ctx); 88578d5d04dSCharlene Liu 88687401969SAndrew Jiang if (bp_result != BP_RESULT_OK) 8871296423bSBhawanpreet Lakha DC_LOG_ERROR( 88887401969SAndrew Jiang "%s: Panel Power bp_result: %d\n", 88987401969SAndrew Jiang __func__, bp_result); 89087401969SAndrew Jiang } else { 8911296423bSBhawanpreet Lakha DC_LOG_HW_RESUME_S3( 89287401969SAndrew Jiang "%s: Skipping Panel Power action: %s\n", 89387401969SAndrew Jiang __func__, (power_up ? "On":"Off")); 89487401969SAndrew Jiang } 89587401969SAndrew Jiang } 8965eefbc40SYue Hin Lau 8975eefbc40SYue Hin Lau /*todo: cloned in stream enc, fix*/ 8985eefbc40SYue Hin Lau /* 8995eefbc40SYue Hin Lau * @brief 9005eefbc40SYue Hin Lau * eDP only. Control the backlight of the eDP panel 9015eefbc40SYue Hin Lau */ 90287401969SAndrew Jiang void hwss_edp_backlight_control( 9035eefbc40SYue Hin Lau struct dc_link *link, 9045eefbc40SYue Hin Lau bool enable) 9055eefbc40SYue Hin Lau { 906069d418fSAndrew Jiang struct dc_context *ctx = link->ctx; 907069d418fSAndrew Jiang struct dce_hwseq *hws = ctx->dc->hwseq; 9085eefbc40SYue Hin Lau struct bp_transmitter_control cntl = { 0 }; 9095eefbc40SYue Hin Lau 910069d418fSAndrew Jiang if (dal_graphics_object_id_get_connector_id(link->link_enc->connector) 9115eefbc40SYue Hin Lau != CONNECTOR_ID_EDP) { 9125eefbc40SYue Hin Lau BREAK_TO_DEBUGGER(); 9135eefbc40SYue Hin Lau return; 9145eefbc40SYue Hin Lau } 9155eefbc40SYue Hin Lau 9165eefbc40SYue Hin Lau if (enable && is_panel_backlight_on(hws)) { 9171296423bSBhawanpreet Lakha DC_LOG_HW_RESUME_S3( 9185eefbc40SYue Hin Lau "%s: panel already powered up. Do nothing.\n", 9195eefbc40SYue Hin Lau __func__); 9205eefbc40SYue Hin Lau return; 9215eefbc40SYue Hin Lau } 9225eefbc40SYue Hin Lau 9235eefbc40SYue Hin Lau /* Send VBIOS command to control eDP panel backlight */ 9245eefbc40SYue Hin Lau 9251296423bSBhawanpreet Lakha DC_LOG_HW_RESUME_S3( 9265eefbc40SYue Hin Lau "%s: backlight action: %s\n", 9275eefbc40SYue Hin Lau __func__, (enable ? "On":"Off")); 9285eefbc40SYue Hin Lau 9295eefbc40SYue Hin Lau cntl.action = enable ? 9305eefbc40SYue Hin Lau TRANSMITTER_CONTROL_BACKLIGHT_ON : 9315eefbc40SYue Hin Lau TRANSMITTER_CONTROL_BACKLIGHT_OFF; 93287401969SAndrew Jiang 9335eefbc40SYue Hin Lau /*cntl.engine_id = ctx->engine;*/ 9345eefbc40SYue Hin Lau cntl.transmitter = link->link_enc->transmitter; 9355eefbc40SYue Hin Lau cntl.connector_obj_id = link->link_enc->connector; 9365eefbc40SYue Hin Lau /*todo: unhardcode*/ 9375eefbc40SYue Hin Lau cntl.lanes_number = LANE_COUNT_FOUR; 9385eefbc40SYue Hin Lau cntl.hpd_sel = link->link_enc->hpd_source; 939cf1835f0SCharlene Liu cntl.signal = SIGNAL_TYPE_EDP; 9405eefbc40SYue Hin Lau 9415eefbc40SYue Hin Lau /* For eDP, the following delays might need to be considered 9425eefbc40SYue Hin Lau * after link training completed: 9435eefbc40SYue Hin Lau * idle period - min. accounts for required BS-Idle pattern, 9445eefbc40SYue Hin Lau * max. allows for source frame synchronization); 9455eefbc40SYue Hin Lau * 50 msec max. delay from valid video data from source 9465eefbc40SYue Hin Lau * to video on dislpay or backlight enable. 9475eefbc40SYue Hin Lau * 9485eefbc40SYue Hin Lau * Disable the delay for now. 9495eefbc40SYue Hin Lau * Enable it in the future if necessary. 9505eefbc40SYue Hin Lau */ 9515eefbc40SYue Hin Lau /* dc_service_sleep_in_milliseconds(50); */ 9525180d4a4SCharlene Liu /*edp 1.2*/ 9535180d4a4SCharlene Liu if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) 9545180d4a4SCharlene Liu edp_receiver_ready_T7(link); 955069d418fSAndrew Jiang link_transmitter_control(ctx->dc_bios, &cntl); 95669b9723aSCharlene Liu /*edp 1.2*/ 9575180d4a4SCharlene Liu if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF) 95869b9723aSCharlene Liu edp_receiver_ready_T9(link); 9595eefbc40SYue Hin Lau } 9605eefbc40SYue Hin Lau 96176d981a9SAlex Deucher // Static helper function which calls the correct function 96276d981a9SAlex Deucher // based on pp_smu version 96376d981a9SAlex Deucher static void set_pme_wa_enable_by_version(struct dc *dc) 96476d981a9SAlex Deucher { 96576d981a9SAlex Deucher struct pp_smu_funcs *pp_smu = NULL; 96676d981a9SAlex Deucher 96776d981a9SAlex Deucher if (dc->res_pool->pp_smu) 96876d981a9SAlex Deucher pp_smu = dc->res_pool->pp_smu; 96976d981a9SAlex Deucher 97076d981a9SAlex Deucher if (pp_smu) { 97176d981a9SAlex Deucher if (pp_smu->ctx.ver == PP_SMU_VER_RV && pp_smu->rv_funcs.set_pme_wa_enable) 97276d981a9SAlex Deucher pp_smu->rv_funcs.set_pme_wa_enable(&(pp_smu->ctx)); 9737ed4e635SHarry Wentland #ifdef CONFIG_DRM_AMD_DC_DCN2_0 9747ed4e635SHarry Wentland else if (pp_smu->ctx.ver == PP_SMU_VER_NV && pp_smu->nv_funcs.set_pme_wa_enable) 9757ed4e635SHarry Wentland pp_smu->nv_funcs.set_pme_wa_enable(&(pp_smu->ctx)); 9767ed4e635SHarry Wentland #endif 97776d981a9SAlex Deucher } 97876d981a9SAlex Deucher } 97976d981a9SAlex Deucher 9801a05873fSAnthony Koo void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx) 9814562236bSHarry Wentland { 9821a05873fSAnthony Koo /* notify audio driver for audio modes of monitor */ 9830f1a6ad7SJun Lei struct dc *core_dc = pipe_ctx->stream->ctx->dc; 9840f1a6ad7SJun Lei struct pp_smu_funcs *pp_smu = NULL; 9851a05873fSAnthony Koo unsigned int i, num_audio = 1; 9861a05873fSAnthony Koo 9870a32df9cSEryk Brol if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == true) 9880a32df9cSEryk Brol return; 9890a32df9cSEryk Brol 9900f1a6ad7SJun Lei if (core_dc->res_pool->pp_smu) 9910f1a6ad7SJun Lei pp_smu = core_dc->res_pool->pp_smu; 9920f1a6ad7SJun Lei 9931a05873fSAnthony Koo if (pipe_ctx->stream_res.audio) { 9941a05873fSAnthony Koo for (i = 0; i < MAX_PIPES; i++) { 9951a05873fSAnthony Koo /*current_state not updated yet*/ 9961a05873fSAnthony Koo if (core_dc->current_state->res_ctx.pipe_ctx[i].stream_res.audio != NULL) 9971a05873fSAnthony Koo num_audio++; 9981a05873fSAnthony Koo } 9991a05873fSAnthony Koo 10001a05873fSAnthony Koo pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio); 10011a05873fSAnthony Koo 100276d981a9SAlex Deucher if (num_audio >= 1 && pp_smu != NULL) 10031a05873fSAnthony Koo /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ 100476d981a9SAlex Deucher set_pme_wa_enable_by_version(core_dc); 10051a05873fSAnthony Koo /* un-mute audio */ 10061a05873fSAnthony Koo /* TODO: audio should be per stream rather than per link */ 10071a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( 10081a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc, false); 10090a32df9cSEryk Brol if (pipe_ctx->stream_res.audio) 10100a32df9cSEryk Brol pipe_ctx->stream_res.audio->enabled = true; 10111a05873fSAnthony Koo } 10121a05873fSAnthony Koo } 10131a05873fSAnthony Koo 10141a05873fSAnthony Koo void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option) 10151a05873fSAnthony Koo { 10164176664bSCharlene Liu struct dc *dc = pipe_ctx->stream->ctx->dc; 10170f1a6ad7SJun Lei struct pp_smu_funcs *pp_smu = NULL; 10184562236bSHarry Wentland 10190a32df9cSEryk Brol if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == false) 10200a32df9cSEryk Brol return; 10210a32df9cSEryk Brol 10222b7c97d6SCharlene Liu pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( 10232b7c97d6SCharlene Liu pipe_ctx->stream_res.stream_enc, true); 1024afaacef4SHarry Wentland if (pipe_ctx->stream_res.audio) { 10250f1a6ad7SJun Lei if (dc->res_pool->pp_smu) 10260f1a6ad7SJun Lei pp_smu = dc->res_pool->pp_smu; 1027070fe724SCharlene Liu 10287c357e61SCharlene Liu if (option != KEEP_ACQUIRED_RESOURCE || 10290f1a6ad7SJun Lei !dc->debug.az_endpoint_mute_only) 10307c357e61SCharlene Liu /*only disalbe az_endpoint if power down or free*/ 1031afaacef4SHarry Wentland pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); 10324562236bSHarry Wentland 10334562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal)) 10348e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( 10358e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc); 10364562236bSHarry Wentland else 10378e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( 10388e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc); 10394176664bSCharlene Liu /*don't free audio if it is from retrain or internal disable stream*/ 10404176664bSCharlene Liu if (option == FREE_ACQUIRED_RESOURCE && dc->caps.dynamic_audio == true) { 10414176664bSCharlene Liu /*we have to dynamic arbitrate the audio endpoints*/ 10424176664bSCharlene Liu /*we free the resource, need reset is_audio_acquired*/ 10434176664bSCharlene Liu update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false); 1044fb5fb63aSCharlene Liu pipe_ctx->stream_res.audio = NULL; 10454176664bSCharlene Liu } 104676d981a9SAlex Deucher if (pp_smu != NULL) 1047070fe724SCharlene Liu /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ 104876d981a9SAlex Deucher set_pme_wa_enable_by_version(dc); 10494562236bSHarry Wentland 10504562236bSHarry Wentland /* TODO: notify audio driver for if audio modes list changed 10514562236bSHarry Wentland * add audio mode list change flag */ 10524562236bSHarry Wentland /* dal_audio_disable_azalia_audio_jack_presence(stream->audio, 10534562236bSHarry Wentland * stream->stream_engine_id); 10544562236bSHarry Wentland */ 10550a32df9cSEryk Brol if (pipe_ctx->stream_res.audio) 10560a32df9cSEryk Brol pipe_ctx->stream_res.audio->enabled = false; 10574562236bSHarry Wentland } 10581a05873fSAnthony Koo } 10594562236bSHarry Wentland 10601a05873fSAnthony Koo void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) 10611a05873fSAnthony Koo { 10621a05873fSAnthony Koo struct dc_stream_state *stream = pipe_ctx->stream; 1063ceb3dbb4SJun Lei struct dc_link *link = stream->link; 10641a05873fSAnthony Koo struct dc *dc = pipe_ctx->stream->ctx->dc; 10651a05873fSAnthony Koo 106602553f57SEric Bernstein if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) 10671a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets( 10681a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc); 10691a05873fSAnthony Koo 10701a05873fSAnthony Koo if (dc_is_dp_signal(pipe_ctx->stream->signal)) 10711a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets( 10721a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc); 10731a05873fSAnthony Koo 10741a05873fSAnthony Koo dc->hwss.disable_audio_stream(pipe_ctx, option); 1075904623eeSYongqiang Sun 10764562236bSHarry Wentland link->link_enc->funcs->connect_dig_be_to_fe( 10774562236bSHarry Wentland link->link_enc, 10788e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->id, 10794562236bSHarry Wentland false); 10804562236bSHarry Wentland 10814562236bSHarry Wentland } 10824562236bSHarry Wentland 10834562236bSHarry Wentland void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, 10844562236bSHarry Wentland struct dc_link_settings *link_settings) 10854562236bSHarry Wentland { 10864562236bSHarry Wentland struct encoder_unblank_param params = { { 0 } }; 108741b49742SCharlene Liu struct dc_stream_state *stream = pipe_ctx->stream; 1088ceb3dbb4SJun Lei struct dc_link *link = stream->link; 10894562236bSHarry Wentland 10904562236bSHarry Wentland /* only 3 items below are used by unblank */ 10917fe538a4SCharlene Liu params.timing = pipe_ctx->stream->timing; 10924562236bSHarry Wentland params.link_settings.link_rate = link_settings->link_rate; 109341b49742SCharlene Liu 109441b49742SCharlene Liu if (dc_is_dp_signal(pipe_ctx->stream->signal)) 10958e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms); 109641b49742SCharlene Liu 109714d6f644SYongqiang Sun if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { 109841b49742SCharlene Liu link->dc->hwss.edp_backlight_control(link, true); 109914d6f644SYongqiang Sun } 110041b49742SCharlene Liu } 11012c850b7bSDmytro Laktyushkin 110241b49742SCharlene Liu void dce110_blank_stream(struct pipe_ctx *pipe_ctx) 110341b49742SCharlene Liu { 110441b49742SCharlene Liu struct dc_stream_state *stream = pipe_ctx->stream; 1105ceb3dbb4SJun Lei struct dc_link *link = stream->link; 110641b49742SCharlene Liu 1107ab892598SRoman Li if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { 110841b49742SCharlene Liu link->dc->hwss.edp_backlight_control(link, false); 1109ab892598SRoman Li dc_link_set_abm_disable(link); 1110ab892598SRoman Li } 111141b49742SCharlene Liu 111241b49742SCharlene Liu if (dc_is_dp_signal(pipe_ctx->stream->signal)) 111341b49742SCharlene Liu pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); 11144562236bSHarry Wentland } 11154562236bSHarry Wentland 111615e17335SCharlene Liu 111715e17335SCharlene Liu void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) 111815e17335SCharlene Liu { 11198e9c4c8cSHarry Wentland if (pipe_ctx != NULL && pipe_ctx->stream_res.stream_enc != NULL) 11208e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->set_avmute(pipe_ctx->stream_res.stream_enc, enable); 112115e17335SCharlene Liu } 112215e17335SCharlene Liu 11234562236bSHarry Wentland static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id) 11244562236bSHarry Wentland { 11254562236bSHarry Wentland switch (crtc_id) { 11264562236bSHarry Wentland case CONTROLLER_ID_D0: 11274562236bSHarry Wentland return DTO_SOURCE_ID0; 11284562236bSHarry Wentland case CONTROLLER_ID_D1: 11294562236bSHarry Wentland return DTO_SOURCE_ID1; 11304562236bSHarry Wentland case CONTROLLER_ID_D2: 11314562236bSHarry Wentland return DTO_SOURCE_ID2; 11324562236bSHarry Wentland case CONTROLLER_ID_D3: 11334562236bSHarry Wentland return DTO_SOURCE_ID3; 11344562236bSHarry Wentland case CONTROLLER_ID_D4: 11354562236bSHarry Wentland return DTO_SOURCE_ID4; 11364562236bSHarry Wentland case CONTROLLER_ID_D5: 11374562236bSHarry Wentland return DTO_SOURCE_ID5; 11384562236bSHarry Wentland default: 11394562236bSHarry Wentland return DTO_SOURCE_UNKNOWN; 11404562236bSHarry Wentland } 11414562236bSHarry Wentland } 11424562236bSHarry Wentland 11434562236bSHarry Wentland static void build_audio_output( 1144ab8db3e1SAndrey Grodzovsky struct dc_state *state, 11454562236bSHarry Wentland const struct pipe_ctx *pipe_ctx, 11464562236bSHarry Wentland struct audio_output *audio_output) 11474562236bSHarry Wentland { 11480971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 11498e9c4c8cSHarry Wentland audio_output->engine_id = pipe_ctx->stream_res.stream_enc->id; 11504562236bSHarry Wentland 11514562236bSHarry Wentland audio_output->signal = pipe_ctx->stream->signal; 11524562236bSHarry Wentland 11534562236bSHarry Wentland /* audio_crtc_info */ 11544562236bSHarry Wentland 11554562236bSHarry Wentland audio_output->crtc_info.h_total = 11564fa086b9SLeo (Sunpeng) Li stream->timing.h_total; 11574562236bSHarry Wentland 11584562236bSHarry Wentland /* 11594562236bSHarry Wentland * Audio packets are sent during actual CRTC blank physical signal, we 11604562236bSHarry Wentland * need to specify actual active signal portion 11614562236bSHarry Wentland */ 11624562236bSHarry Wentland audio_output->crtc_info.h_active = 11634fa086b9SLeo (Sunpeng) Li stream->timing.h_addressable 11644fa086b9SLeo (Sunpeng) Li + stream->timing.h_border_left 11654fa086b9SLeo (Sunpeng) Li + stream->timing.h_border_right; 11664562236bSHarry Wentland 11674562236bSHarry Wentland audio_output->crtc_info.v_active = 11684fa086b9SLeo (Sunpeng) Li stream->timing.v_addressable 11694fa086b9SLeo (Sunpeng) Li + stream->timing.v_border_top 11704fa086b9SLeo (Sunpeng) Li + stream->timing.v_border_bottom; 11714562236bSHarry Wentland 11724562236bSHarry Wentland audio_output->crtc_info.pixel_repetition = 1; 11734562236bSHarry Wentland 11744562236bSHarry Wentland audio_output->crtc_info.interlaced = 11754fa086b9SLeo (Sunpeng) Li stream->timing.flags.INTERLACE; 11764562236bSHarry Wentland 11774562236bSHarry Wentland audio_output->crtc_info.refresh_rate = 1178380604e2SKen Chalmers (stream->timing.pix_clk_100hz*10000)/ 11794fa086b9SLeo (Sunpeng) Li (stream->timing.h_total*stream->timing.v_total); 11804562236bSHarry Wentland 11814562236bSHarry Wentland audio_output->crtc_info.color_depth = 11824fa086b9SLeo (Sunpeng) Li stream->timing.display_color_depth; 11834562236bSHarry Wentland 11844562236bSHarry Wentland audio_output->crtc_info.requested_pixel_clock = 1185380604e2SKen Chalmers pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10; 11864562236bSHarry Wentland 11874562236bSHarry Wentland audio_output->crtc_info.calculated_pixel_clock = 1188380604e2SKen Chalmers pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10; 11894562236bSHarry Wentland 119087b58768SCharlene Liu /*for HDMI, audio ACR is with deep color ratio factor*/ 119187b58768SCharlene Liu if (dc_is_hdmi_signal(pipe_ctx->stream->signal) && 119287b58768SCharlene Liu audio_output->crtc_info.requested_pixel_clock == 1193380604e2SKen Chalmers (stream->timing.pix_clk_100hz / 10)) { 119410688217SHarry Wentland if (pipe_ctx->stream_res.pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) { 119587b58768SCharlene Liu audio_output->crtc_info.requested_pixel_clock = 119687b58768SCharlene Liu audio_output->crtc_info.requested_pixel_clock/2; 119787b58768SCharlene Liu audio_output->crtc_info.calculated_pixel_clock = 1198380604e2SKen Chalmers pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz/20; 119987b58768SCharlene Liu 120087b58768SCharlene Liu } 120187b58768SCharlene Liu } 120287b58768SCharlene Liu 12034562236bSHarry Wentland if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT || 12044562236bSHarry Wentland pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { 12054562236bSHarry Wentland audio_output->pll_info.dp_dto_source_clock_in_khz = 12060de34efcSDmytro Laktyushkin state->clk_mgr->funcs->get_dp_ref_clk_frequency( 12070de34efcSDmytro Laktyushkin state->clk_mgr); 12084562236bSHarry Wentland } 12094562236bSHarry Wentland 12104562236bSHarry Wentland audio_output->pll_info.feed_back_divider = 12114562236bSHarry Wentland pipe_ctx->pll_settings.feedback_divider; 12124562236bSHarry Wentland 12134562236bSHarry Wentland audio_output->pll_info.dto_source = 12144562236bSHarry Wentland translate_to_dto_source( 1215e07f541fSYongqiang Sun pipe_ctx->stream_res.tg->inst + 1); 12164562236bSHarry Wentland 12174562236bSHarry Wentland /* TODO hard code to enable for now. Need get from stream */ 12184562236bSHarry Wentland audio_output->pll_info.ss_enabled = true; 12194562236bSHarry Wentland 12204562236bSHarry Wentland audio_output->pll_info.ss_percentage = 12214562236bSHarry Wentland pipe_ctx->pll_settings.ss_percentage; 12224562236bSHarry Wentland } 12234562236bSHarry Wentland 12244562236bSHarry Wentland static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx, 12254562236bSHarry Wentland struct tg_color *color) 12264562236bSHarry Wentland { 12272a54bd6eSJerry (Fangzhi) Zuo uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->stream_res.tg->inst) / 4; 12284562236bSHarry Wentland 12296702a9acSHarry Wentland switch (pipe_ctx->plane_res.scl_data.format) { 12304562236bSHarry Wentland case PIXEL_FORMAT_ARGB8888: 12314562236bSHarry Wentland /* set boarder color to red */ 12324562236bSHarry Wentland color->color_r_cr = color_value; 12334562236bSHarry Wentland break; 12344562236bSHarry Wentland 12354562236bSHarry Wentland case PIXEL_FORMAT_ARGB2101010: 12364562236bSHarry Wentland /* set boarder color to blue */ 12374562236bSHarry Wentland color->color_b_cb = color_value; 12384562236bSHarry Wentland break; 123987449a90SAnthony Koo case PIXEL_FORMAT_420BPP8: 12404562236bSHarry Wentland /* set boarder color to green */ 12414562236bSHarry Wentland color->color_g_y = color_value; 12424562236bSHarry Wentland break; 124387449a90SAnthony Koo case PIXEL_FORMAT_420BPP10: 124487449a90SAnthony Koo /* set boarder color to yellow */ 124587449a90SAnthony Koo color->color_g_y = color_value; 124687449a90SAnthony Koo color->color_r_cr = color_value; 124787449a90SAnthony Koo break; 12484562236bSHarry Wentland case PIXEL_FORMAT_FP16: 12494562236bSHarry Wentland /* set boarder color to white */ 12504562236bSHarry Wentland color->color_r_cr = color_value; 12514562236bSHarry Wentland color->color_b_cb = color_value; 12524562236bSHarry Wentland color->color_g_y = color_value; 12534562236bSHarry Wentland break; 12544562236bSHarry Wentland default: 12554562236bSHarry Wentland break; 12564562236bSHarry Wentland } 12574562236bSHarry Wentland } 12584562236bSHarry Wentland 1259fb3466a4SBhawanpreet Lakha static void program_scaler(const struct dc *dc, 12604562236bSHarry Wentland const struct pipe_ctx *pipe_ctx) 12614562236bSHarry Wentland { 12624562236bSHarry Wentland struct tg_color color = {0}; 12634562236bSHarry Wentland 1264dc37a9a0SLeo (Sunpeng) Li #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 1265ff5ef992SAlex Deucher /* TOFPGA */ 126686a66c4eSHarry Wentland if (pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth == NULL) 1267ff5ef992SAlex Deucher return; 1268ff5ef992SAlex Deucher #endif 1269ff5ef992SAlex Deucher 1270bf53769dSGloria Li if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) 12714562236bSHarry Wentland get_surface_visual_confirm_color(pipe_ctx, &color); 12724562236bSHarry Wentland else 12734562236bSHarry Wentland color_space_to_black_color(dc, 12744fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->output_color_space, 12754562236bSHarry Wentland &color); 12764562236bSHarry Wentland 127786a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth( 127886a66c4eSHarry Wentland pipe_ctx->plane_res.xfm, 12796702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth, 12804562236bSHarry Wentland &pipe_ctx->stream->bit_depth_params); 12814562236bSHarry Wentland 128212750d16SEric Yang if (pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color) { 128312750d16SEric Yang /* 128412750d16SEric Yang * The way 420 is packed, 2 channels carry Y component, 1 channel 128512750d16SEric Yang * alternate between Cb and Cr, so both channels need the pixel 128612750d16SEric Yang * value for Y 128712750d16SEric Yang */ 128812750d16SEric Yang if (pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) 128912750d16SEric Yang color.color_r_cr = color.color_g_y; 129012750d16SEric Yang 12916b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color( 12926b670fa9SHarry Wentland pipe_ctx->stream_res.tg, 12934562236bSHarry Wentland &color); 129412750d16SEric Yang } 12954562236bSHarry Wentland 129686a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm, 12976702a9acSHarry Wentland &pipe_ctx->plane_res.scl_data); 12984562236bSHarry Wentland } 12994562236bSHarry Wentland 13003158223eSEric Bernstein static enum dc_status dce110_enable_stream_timing( 13014562236bSHarry Wentland struct pipe_ctx *pipe_ctx, 1302608ac7bbSJerry Zuo struct dc_state *context, 1303fb3466a4SBhawanpreet Lakha struct dc *dc) 13044562236bSHarry Wentland { 13050971c40eSHarry Wentland struct dc_stream_state *stream = pipe_ctx->stream; 1306608ac7bbSJerry Zuo struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx. 13074562236bSHarry Wentland pipe_ctx[pipe_ctx->pipe_idx]; 13084562236bSHarry Wentland struct tg_color black_color = {0}; 13094562236bSHarry Wentland 13104562236bSHarry Wentland if (!pipe_ctx_old->stream) { 13114562236bSHarry Wentland 13124562236bSHarry Wentland /* program blank color */ 13134562236bSHarry Wentland color_space_to_black_color(dc, 13144fa086b9SLeo (Sunpeng) Li stream->output_color_space, &black_color); 13156b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->set_blank_color( 13166b670fa9SHarry Wentland pipe_ctx->stream_res.tg, 13174562236bSHarry Wentland &black_color); 13184b5e7d62SHersen Wu 13194562236bSHarry Wentland /* 13204562236bSHarry Wentland * Must blank CRTC after disabling power gating and before any 13214562236bSHarry Wentland * programming, otherwise CRTC will be hung in bad state 13224562236bSHarry Wentland */ 13236b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true); 13244562236bSHarry Wentland 13254562236bSHarry Wentland if (false == pipe_ctx->clock_source->funcs->program_pix_clk( 13264562236bSHarry Wentland pipe_ctx->clock_source, 132710688217SHarry Wentland &pipe_ctx->stream_res.pix_clk_params, 13284562236bSHarry Wentland &pipe_ctx->pll_settings)) { 13294562236bSHarry Wentland BREAK_TO_DEBUGGER(); 13304562236bSHarry Wentland return DC_ERROR_UNEXPECTED; 13314562236bSHarry Wentland } 13324562236bSHarry Wentland 13336b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->program_timing( 13346b670fa9SHarry Wentland pipe_ctx->stream_res.tg, 13354fa086b9SLeo (Sunpeng) Li &stream->timing, 1336e7e10c46SDmytro Laktyushkin 0, 1337e7e10c46SDmytro Laktyushkin 0, 1338e7e10c46SDmytro Laktyushkin 0, 1339e7e10c46SDmytro Laktyushkin 0, 1340e7e10c46SDmytro Laktyushkin pipe_ctx->stream->signal, 13414562236bSHarry Wentland true); 13424562236bSHarry Wentland } 13434562236bSHarry Wentland 13444562236bSHarry Wentland if (!pipe_ctx_old->stream) { 13456b670fa9SHarry Wentland if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc( 13466b670fa9SHarry Wentland pipe_ctx->stream_res.tg)) { 13474562236bSHarry Wentland BREAK_TO_DEBUGGER(); 13484562236bSHarry Wentland return DC_ERROR_UNEXPECTED; 13494562236bSHarry Wentland } 13504562236bSHarry Wentland } 13514562236bSHarry Wentland 13524562236bSHarry Wentland return DC_OK; 13534562236bSHarry Wentland } 13544562236bSHarry Wentland 13554562236bSHarry Wentland static enum dc_status apply_single_controller_ctx_to_hw( 13564562236bSHarry Wentland struct pipe_ctx *pipe_ctx, 1357608ac7bbSJerry Zuo struct dc_state *context, 1358fb3466a4SBhawanpreet Lakha struct dc *dc) 13594562236bSHarry Wentland { 13600971c40eSHarry Wentland struct dc_stream_state *stream = pipe_ctx->stream; 13619c0fb8d4SAnthony Koo struct drr_params params = {0}; 13629c0fb8d4SAnthony Koo unsigned int event_triggers = 0; 13637ed4e635SHarry Wentland #if defined(CONFIG_DRM_AMD_DC_DCN2_0) 13647ed4e635SHarry Wentland struct pipe_ctx *odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx); 13657ed4e635SHarry Wentland #endif 13664562236bSHarry Wentland 1367240d09d0SGary Kattan if (dc->hwss.disable_stream_gating) { 1368240d09d0SGary Kattan dc->hwss.disable_stream_gating(dc, pipe_ctx); 1369240d09d0SGary Kattan } 1370240d09d0SGary Kattan 13711a05873fSAnthony Koo if (pipe_ctx->stream_res.audio != NULL) { 13721a05873fSAnthony Koo struct audio_output audio_output; 13731a05873fSAnthony Koo 13741a05873fSAnthony Koo build_audio_output(context, pipe_ctx, &audio_output); 13751a05873fSAnthony Koo 13761a05873fSAnthony Koo if (dc_is_dp_signal(pipe_ctx->stream->signal)) 13771a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( 13781a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc, 13791a05873fSAnthony Koo pipe_ctx->stream_res.audio->inst, 13801a05873fSAnthony Koo &pipe_ctx->stream->audio_info); 13811a05873fSAnthony Koo else 13821a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup( 13831a05873fSAnthony Koo pipe_ctx->stream_res.stream_enc, 13841a05873fSAnthony Koo pipe_ctx->stream_res.audio->inst, 13851a05873fSAnthony Koo &pipe_ctx->stream->audio_info, 13861a05873fSAnthony Koo &audio_output.crtc_info); 13871a05873fSAnthony Koo 13881a05873fSAnthony Koo pipe_ctx->stream_res.audio->funcs->az_configure( 13891a05873fSAnthony Koo pipe_ctx->stream_res.audio, 13901a05873fSAnthony Koo pipe_ctx->stream->signal, 13911a05873fSAnthony Koo &audio_output.crtc_info, 13921a05873fSAnthony Koo &pipe_ctx->stream->audio_info); 13931a05873fSAnthony Koo } 13941a05873fSAnthony Koo 13954562236bSHarry Wentland /* */ 1396d2d7885fSAnthony Koo /* Do not touch stream timing on seamless boot optimization. */ 1397d2d7885fSAnthony Koo if (!pipe_ctx->stream->apply_seamless_boot_optimization) 13983158223eSEric Bernstein dc->hwss.enable_stream_timing(pipe_ctx, context, dc); 13994562236bSHarry Wentland 1400d6001aedSYongqiang Sun if (dc->hwss.setup_vupdate_interrupt) 1401d6001aedSYongqiang Sun dc->hwss.setup_vupdate_interrupt(pipe_ctx); 1402a122b62dSAnthony Koo 14039c0fb8d4SAnthony Koo params.vertical_total_min = stream->adjust.v_total_min; 14049c0fb8d4SAnthony Koo params.vertical_total_max = stream->adjust.v_total_max; 14059c0fb8d4SAnthony Koo if (pipe_ctx->stream_res.tg->funcs->set_drr) 14069c0fb8d4SAnthony Koo pipe_ctx->stream_res.tg->funcs->set_drr( 14079c0fb8d4SAnthony Koo pipe_ctx->stream_res.tg, ¶ms); 14089c0fb8d4SAnthony Koo 14099c0fb8d4SAnthony Koo // DRR should set trigger event to monitor surface update event 14109c0fb8d4SAnthony Koo if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0) 14119c0fb8d4SAnthony Koo event_triggers = 0x80; 14129c0fb8d4SAnthony Koo if (pipe_ctx->stream_res.tg->funcs->set_static_screen_control) 14139c0fb8d4SAnthony Koo pipe_ctx->stream_res.tg->funcs->set_static_screen_control( 14149c0fb8d4SAnthony Koo pipe_ctx->stream_res.tg, event_triggers); 14159c0fb8d4SAnthony Koo 1416248cbed6SEric Bernstein if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) 1417d2c460e7Shersen wu pipe_ctx->stream_res.stream_enc->funcs->dig_connect_to_otg( 1418d2c460e7Shersen wu pipe_ctx->stream_res.stream_enc, 1419d2c460e7Shersen wu pipe_ctx->stream_res.tg->inst); 1420aa9c4abeSNikola Cornij 1421f0c4d997SCorbin McElhanney pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion( 1422f0c4d997SCorbin McElhanney pipe_ctx->stream_res.opp, 1423f0c4d997SCorbin McElhanney COLOR_SPACE_YCBCR601, 1424f0c4d997SCorbin McElhanney stream->timing.display_color_depth, 1425661a8cd9SDmytro Laktyushkin stream->signal); 14264562236bSHarry Wentland 1427a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp->funcs->opp_program_fmt( 1428a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp, 1429181a888fSCharlene Liu &stream->bit_depth_params, 1430181a888fSCharlene Liu &stream->clamping); 14317ed4e635SHarry Wentland #if defined(CONFIG_DRM_AMD_DC_DCN2_0) 14327ed4e635SHarry Wentland if (odm_pipe) { 14337ed4e635SHarry Wentland odm_pipe->stream_res.opp->funcs->opp_set_dyn_expansion( 14347ed4e635SHarry Wentland odm_pipe->stream_res.opp, 14357ed4e635SHarry Wentland COLOR_SPACE_YCBCR601, 14367ed4e635SHarry Wentland stream->timing.display_color_depth, 14377ed4e635SHarry Wentland stream->signal); 14387ed4e635SHarry Wentland 14397ed4e635SHarry Wentland odm_pipe->stream_res.opp->funcs->opp_program_fmt( 14407ed4e635SHarry Wentland odm_pipe->stream_res.opp, 14417ed4e635SHarry Wentland &stream->bit_depth_params, 14427ed4e635SHarry Wentland &stream->clamping); 14437ed4e635SHarry Wentland } 14447ed4e635SHarry Wentland #endif 1445603767f9STony Cheng 14461e7e86c4SSamson Tam if (!stream->dpms_off) 1447ab8db3e1SAndrey Grodzovsky core_link_enable_stream(context, pipe_ctx); 14484562236bSHarry Wentland 14496702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; 14504562236bSHarry Wentland 1451ceb3dbb4SJun Lei pipe_ctx->stream->link->psr_enabled = false; 145294267b3dSSylvia Tsai 14534562236bSHarry Wentland return DC_OK; 14544562236bSHarry Wentland } 14554562236bSHarry Wentland 14564562236bSHarry Wentland /******************************************************************************/ 14574562236bSHarry Wentland 1458fb3466a4SBhawanpreet Lakha static void power_down_encoders(struct dc *dc) 14594562236bSHarry Wentland { 14604562236bSHarry Wentland int i; 1461a0c38ebaSCharlene Liu enum connector_id connector_id; 146268d77dd8SAndrew Jiang enum signal_type signal = SIGNAL_TYPE_NONE; 1463b9b171ffSHersen Wu 1464b9b171ffSHersen Wu /* do not know BIOS back-front mapping, simply blank all. It will not 1465b9b171ffSHersen Wu * hurt for non-DP 1466b9b171ffSHersen Wu */ 1467b9b171ffSHersen Wu for (i = 0; i < dc->res_pool->stream_enc_count; i++) { 1468b9b171ffSHersen Wu dc->res_pool->stream_enc[i]->funcs->dp_blank( 1469b9b171ffSHersen Wu dc->res_pool->stream_enc[i]); 1470b9b171ffSHersen Wu } 1471b9b171ffSHersen Wu 14724562236bSHarry Wentland for (i = 0; i < dc->link_count; i++) { 1473a0c38ebaSCharlene Liu connector_id = dal_graphics_object_id_get_connector_id(dc->links[i]->link_id); 1474a0c38ebaSCharlene Liu if ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || 1475a0c38ebaSCharlene Liu (connector_id == CONNECTOR_ID_EDP)) { 1476a0c38ebaSCharlene Liu 1477a0c38ebaSCharlene Liu if (!dc->links[i]->wa_flags.dp_keep_receiver_powered) 1478a0c38ebaSCharlene Liu dp_receiver_power_ctrl(dc->links[i], false); 1479904623eeSYongqiang Sun if (connector_id == CONNECTOR_ID_EDP) 148068d77dd8SAndrew Jiang signal = SIGNAL_TYPE_EDP; 1481a0c38ebaSCharlene Liu } 1482a0c38ebaSCharlene Liu 14834562236bSHarry Wentland dc->links[i]->link_enc->funcs->disable_output( 1484069d418fSAndrew Jiang dc->links[i]->link_enc, signal); 14854562236bSHarry Wentland } 14864562236bSHarry Wentland } 14874562236bSHarry Wentland 1488fb3466a4SBhawanpreet Lakha static void power_down_controllers(struct dc *dc) 14894562236bSHarry Wentland { 14904562236bSHarry Wentland int i; 14914562236bSHarry Wentland 14927f93c1deSCharlene Liu for (i = 0; i < dc->res_pool->timing_generator_count; i++) { 14934562236bSHarry Wentland dc->res_pool->timing_generators[i]->funcs->disable_crtc( 14944562236bSHarry Wentland dc->res_pool->timing_generators[i]); 14954562236bSHarry Wentland } 14964562236bSHarry Wentland } 14974562236bSHarry Wentland 1498fb3466a4SBhawanpreet Lakha static void power_down_clock_sources(struct dc *dc) 14994562236bSHarry Wentland { 15004562236bSHarry Wentland int i; 15014562236bSHarry Wentland 15024562236bSHarry Wentland if (dc->res_pool->dp_clock_source->funcs->cs_power_down( 15034562236bSHarry Wentland dc->res_pool->dp_clock_source) == false) 15044562236bSHarry Wentland dm_error("Failed to power down pll! (dp clk src)\n"); 15054562236bSHarry Wentland 15064562236bSHarry Wentland for (i = 0; i < dc->res_pool->clk_src_count; i++) { 15074562236bSHarry Wentland if (dc->res_pool->clock_sources[i]->funcs->cs_power_down( 15084562236bSHarry Wentland dc->res_pool->clock_sources[i]) == false) 15094562236bSHarry Wentland dm_error("Failed to power down pll! (clk src index=%d)\n", i); 15104562236bSHarry Wentland } 15114562236bSHarry Wentland } 15124562236bSHarry Wentland 1513fb3466a4SBhawanpreet Lakha static void power_down_all_hw_blocks(struct dc *dc) 15144562236bSHarry Wentland { 15154562236bSHarry Wentland power_down_encoders(dc); 15164562236bSHarry Wentland 15174562236bSHarry Wentland power_down_controllers(dc); 15184562236bSHarry Wentland 15194562236bSHarry Wentland power_down_clock_sources(dc); 15201663ae1cSBhawanpreet Lakha 15212f3bfb27SRoman Li if (dc->fbc_compressor) 15221663ae1cSBhawanpreet Lakha dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); 15234562236bSHarry Wentland } 15244562236bSHarry Wentland 15254562236bSHarry Wentland static void disable_vga_and_power_gate_all_controllers( 1526fb3466a4SBhawanpreet Lakha struct dc *dc) 15274562236bSHarry Wentland { 15284562236bSHarry Wentland int i; 15294562236bSHarry Wentland struct timing_generator *tg; 15304562236bSHarry Wentland struct dc_context *ctx = dc->ctx; 15314562236bSHarry Wentland 15327f93c1deSCharlene Liu for (i = 0; i < dc->res_pool->timing_generator_count; i++) { 15334562236bSHarry Wentland tg = dc->res_pool->timing_generators[i]; 15344562236bSHarry Wentland 15350a87425aSTony Cheng if (tg->funcs->disable_vga) 15364562236bSHarry Wentland tg->funcs->disable_vga(tg); 15377f93c1deSCharlene Liu } 15387f93c1deSCharlene Liu for (i = 0; i < dc->res_pool->pipe_count; i++) { 15394562236bSHarry Wentland /* Enable CLOCK gating for each pipe BEFORE controller 15404562236bSHarry Wentland * powergating. */ 15414562236bSHarry Wentland enable_display_pipe_clock_gating(ctx, 15424562236bSHarry Wentland true); 15434562236bSHarry Wentland 1544e6c258cbSYongqiang Sun dc->current_state->res_ctx.pipe_ctx[i].pipe_idx = i; 15457f914a62SYongqiang Sun dc->hwss.disable_plane(dc, 1546e6c258cbSYongqiang Sun &dc->current_state->res_ctx.pipe_ctx[i]); 15474562236bSHarry Wentland } 15484562236bSHarry Wentland } 15494562236bSHarry Wentland 15503de5aa81SSivapiriyanKumarasamy 15513de5aa81SSivapiriyanKumarasamy static struct dc_stream_state *get_edp_stream(struct dc_state *context) 15523de5aa81SSivapiriyanKumarasamy { 15533de5aa81SSivapiriyanKumarasamy int i; 15543de5aa81SSivapiriyanKumarasamy 15553de5aa81SSivapiriyanKumarasamy for (i = 0; i < context->stream_count; i++) { 15563de5aa81SSivapiriyanKumarasamy if (context->streams[i]->signal == SIGNAL_TYPE_EDP) 15573de5aa81SSivapiriyanKumarasamy return context->streams[i]; 15583de5aa81SSivapiriyanKumarasamy } 15593de5aa81SSivapiriyanKumarasamy return NULL; 15603de5aa81SSivapiriyanKumarasamy } 15613de5aa81SSivapiriyanKumarasamy 1562be4b289fSSivapiriyanKumarasamy static struct dc_link *get_edp_link(struct dc *dc) 1563339cc82aSYongqiang Sun { 1564339cc82aSYongqiang Sun int i; 1565339cc82aSYongqiang Sun 1566be4b289fSSivapiriyanKumarasamy // report any eDP links, even unconnected DDI's 1567f0c0761bSYongqiang Sun for (i = 0; i < dc->link_count; i++) { 1568f0c0761bSYongqiang Sun if (dc->links[i]->connector_signal == SIGNAL_TYPE_EDP) 1569f0c0761bSYongqiang Sun return dc->links[i]; 1570339cc82aSYongqiang Sun } 1571f0c0761bSYongqiang Sun return NULL; 1572339cc82aSYongqiang Sun } 1573339cc82aSYongqiang Sun 1574be4b289fSSivapiriyanKumarasamy static struct dc_link *get_edp_link_with_sink( 157525292028SYongqiang Sun struct dc *dc, 157625292028SYongqiang Sun struct dc_state *context) 157725292028SYongqiang Sun { 157825292028SYongqiang Sun int i; 157925292028SYongqiang Sun struct dc_link *link = NULL; 158025292028SYongqiang Sun 158125292028SYongqiang Sun /* check if there is an eDP panel not in use */ 158225292028SYongqiang Sun for (i = 0; i < dc->link_count; i++) { 158325292028SYongqiang Sun if (dc->links[i]->local_sink && 158425292028SYongqiang Sun dc->links[i]->local_sink->sink_signal == SIGNAL_TYPE_EDP) { 158525292028SYongqiang Sun link = dc->links[i]; 158625292028SYongqiang Sun break; 158725292028SYongqiang Sun } 158825292028SYongqiang Sun } 158925292028SYongqiang Sun 159025292028SYongqiang Sun return link; 159125292028SYongqiang Sun } 159225292028SYongqiang Sun 15934562236bSHarry Wentland /** 15944562236bSHarry Wentland * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need: 15954562236bSHarry Wentland * 1. Power down all DC HW blocks 15964562236bSHarry Wentland * 2. Disable VGA engine on all controllers 15974562236bSHarry Wentland * 3. Enable power gating for controller 15984562236bSHarry Wentland * 4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS) 15994562236bSHarry Wentland */ 160025292028SYongqiang Sun void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) 16014562236bSHarry Wentland { 1602d82f9942SAnthony Koo int i; 1603be4b289fSSivapiriyanKumarasamy struct dc_link *edp_link_with_sink = get_edp_link_with_sink(dc, context); 1604be4b289fSSivapiriyanKumarasamy struct dc_link *edp_link = get_edp_link(dc); 16053de5aa81SSivapiriyanKumarasamy struct dc_stream_state *edp_stream = NULL; 1606be4b289fSSivapiriyanKumarasamy bool can_apply_edp_fast_boot = false; 1607ce72741bSAnthony Koo bool can_apply_seamless_boot = false; 16083de5aa81SSivapiriyanKumarasamy bool keep_edp_vdd_on = false; 1609ce72741bSAnthony Koo 1610be4b289fSSivapiriyanKumarasamy if (dc->hwss.init_pipes) 1611be4b289fSSivapiriyanKumarasamy dc->hwss.init_pipes(dc, context); 1612be4b289fSSivapiriyanKumarasamy 16133de5aa81SSivapiriyanKumarasamy edp_stream = get_edp_stream(context); 16143de5aa81SSivapiriyanKumarasamy 1615be4b289fSSivapiriyanKumarasamy // Check fastboot support, disable on DCE8 because of blank screens 1616be4b289fSSivapiriyanKumarasamy if (edp_link && dc->ctx->dce_version != DCE_VERSION_8_0 && 1617be4b289fSSivapiriyanKumarasamy dc->ctx->dce_version != DCE_VERSION_8_1 && 1618be4b289fSSivapiriyanKumarasamy dc->ctx->dce_version != DCE_VERSION_8_3) { 1619be4b289fSSivapiriyanKumarasamy 1620be4b289fSSivapiriyanKumarasamy // enable fastboot if backend is enabled on eDP 1621be4b289fSSivapiriyanKumarasamy if (edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc)) { 16223de5aa81SSivapiriyanKumarasamy /* Set optimization flag on eDP stream*/ 16233de5aa81SSivapiriyanKumarasamy if (edp_stream) { 16243de5aa81SSivapiriyanKumarasamy edp_stream->apply_edp_fast_boot_optimization = true; 1625be4b289fSSivapiriyanKumarasamy can_apply_edp_fast_boot = true; 1626be4b289fSSivapiriyanKumarasamy } 1627be4b289fSSivapiriyanKumarasamy } 16283de5aa81SSivapiriyanKumarasamy 16293de5aa81SSivapiriyanKumarasamy // We are trying to enable eDP, don't power down VDD 16303de5aa81SSivapiriyanKumarasamy if (edp_stream) 16313de5aa81SSivapiriyanKumarasamy keep_edp_vdd_on = true; 1632be4b289fSSivapiriyanKumarasamy } 1633be4b289fSSivapiriyanKumarasamy 1634be4b289fSSivapiriyanKumarasamy // Check seamless boot support 1635ce72741bSAnthony Koo for (i = 0; i < context->stream_count; i++) { 1636ce72741bSAnthony Koo if (context->streams[i]->apply_seamless_boot_optimization) { 1637ce72741bSAnthony Koo can_apply_seamless_boot = true; 1638ce72741bSAnthony Koo break; 1639ce72741bSAnthony Koo } 1640ce72741bSAnthony Koo } 16414cac1e6dSYongqiang Sun 1642be4b289fSSivapiriyanKumarasamy /* eDP should not have stream in resume from S4 and so even with VBios post 1643be4b289fSSivapiriyanKumarasamy * it should get turned off 16442c37e49aSYongqiang Sun */ 1645be4b289fSSivapiriyanKumarasamy if (!can_apply_edp_fast_boot && !can_apply_seamless_boot) { 16463de5aa81SSivapiriyanKumarasamy if (edp_link_with_sink && !keep_edp_vdd_on) { 16474cac1e6dSYongqiang Sun /*turn off backlight before DP_blank and encoder powered down*/ 1648be4b289fSSivapiriyanKumarasamy dc->hwss.edp_backlight_control(edp_link_with_sink, false); 1649c5fc7f59SCharlene Liu } 1650c5fc7f59SCharlene Liu /*resume from S3, no vbios posting, no need to power down again*/ 165125292028SYongqiang Sun power_down_all_hw_blocks(dc); 16524562236bSHarry Wentland disable_vga_and_power_gate_all_controllers(dc); 16533de5aa81SSivapiriyanKumarasamy if (edp_link_with_sink && !keep_edp_vdd_on) 1654be4b289fSSivapiriyanKumarasamy dc->hwss.edp_power_control(edp_link_with_sink, false); 1655c5fc7f59SCharlene Liu } 16564562236bSHarry Wentland bios_set_scratch_acc_mode_change(dc->ctx->dc_bios); 16574562236bSHarry Wentland } 16584562236bSHarry Wentland 16594562236bSHarry Wentland static uint32_t compute_pstate_blackout_duration( 16604562236bSHarry Wentland struct bw_fixed blackout_duration, 16610971c40eSHarry Wentland const struct dc_stream_state *stream) 16624562236bSHarry Wentland { 16634562236bSHarry Wentland uint32_t total_dest_line_time_ns; 16644562236bSHarry Wentland uint32_t pstate_blackout_duration_ns; 16654562236bSHarry Wentland 16664562236bSHarry Wentland pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24; 16674562236bSHarry Wentland 16684562236bSHarry Wentland total_dest_line_time_ns = 1000000UL * 1669380604e2SKen Chalmers (stream->timing.h_total * 10) / 1670380604e2SKen Chalmers stream->timing.pix_clk_100hz + 16714562236bSHarry Wentland pstate_blackout_duration_ns; 16724562236bSHarry Wentland 16734562236bSHarry Wentland return total_dest_line_time_ns; 16744562236bSHarry Wentland } 16754562236bSHarry Wentland 1676f774b339SEric Yang static void dce110_set_displaymarks( 1677fb3466a4SBhawanpreet Lakha const struct dc *dc, 1678608ac7bbSJerry Zuo struct dc_state *context) 16794562236bSHarry Wentland { 16804562236bSHarry Wentland uint8_t i, num_pipes; 16814562236bSHarry Wentland unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; 16824562236bSHarry Wentland 16834562236bSHarry Wentland for (i = 0, num_pipes = 0; i < MAX_PIPES; i++) { 16844562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 16854562236bSHarry Wentland uint32_t total_dest_line_time_ns; 16864562236bSHarry Wentland 16874562236bSHarry Wentland if (pipe_ctx->stream == NULL) 16884562236bSHarry Wentland continue; 16894562236bSHarry Wentland 16904562236bSHarry Wentland total_dest_line_time_ns = compute_pstate_blackout_duration( 169177a4ea53SBhawanpreet Lakha dc->bw_vbios->blackout_duration, pipe_ctx->stream); 169286a66c4eSHarry Wentland pipe_ctx->plane_res.mi->funcs->mem_input_program_display_marks( 169386a66c4eSHarry Wentland pipe_ctx->plane_res.mi, 1694813d20dcSAidan Wood context->bw_ctx.bw.dce.nbp_state_change_wm_ns[num_pipes], 1695813d20dcSAidan Wood context->bw_ctx.bw.dce.stutter_exit_wm_ns[num_pipes], 1696813d20dcSAidan Wood context->bw_ctx.bw.dce.stutter_entry_wm_ns[num_pipes], 1697813d20dcSAidan Wood context->bw_ctx.bw.dce.urgent_wm_ns[num_pipes], 16984562236bSHarry Wentland total_dest_line_time_ns); 16994562236bSHarry Wentland if (i == underlay_idx) { 17004562236bSHarry Wentland num_pipes++; 170186a66c4eSHarry Wentland pipe_ctx->plane_res.mi->funcs->mem_input_program_chroma_display_marks( 170286a66c4eSHarry Wentland pipe_ctx->plane_res.mi, 1703813d20dcSAidan Wood context->bw_ctx.bw.dce.nbp_state_change_wm_ns[num_pipes], 1704813d20dcSAidan Wood context->bw_ctx.bw.dce.stutter_exit_wm_ns[num_pipes], 1705813d20dcSAidan Wood context->bw_ctx.bw.dce.urgent_wm_ns[num_pipes], 17064562236bSHarry Wentland total_dest_line_time_ns); 17074562236bSHarry Wentland } 17084562236bSHarry Wentland num_pipes++; 17094562236bSHarry Wentland } 17104562236bSHarry Wentland } 17114562236bSHarry Wentland 1712fab55d61SDmytro Laktyushkin void dce110_set_safe_displaymarks( 1713a2b8659dSTony Cheng struct resource_context *res_ctx, 1714a2b8659dSTony Cheng const struct resource_pool *pool) 17154562236bSHarry Wentland { 17164562236bSHarry Wentland int i; 1717a2b8659dSTony Cheng int underlay_idx = pool->underlay_pipe_index; 17189037d802SDmytro Laktyushkin struct dce_watermarks max_marks = { 17194562236bSHarry Wentland MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK }; 17209037d802SDmytro Laktyushkin struct dce_watermarks nbp_marks = { 17214562236bSHarry Wentland SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK }; 17223722c794SMikita Lipski struct dce_watermarks min_marks = { 0, 0, 0, 0}; 17234562236bSHarry Wentland 17244562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 17258feabd03SYue Hin Lau if (res_ctx->pipe_ctx[i].stream == NULL || res_ctx->pipe_ctx[i].plane_res.mi == NULL) 17264562236bSHarry Wentland continue; 17274562236bSHarry Wentland 172886a66c4eSHarry Wentland res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_display_marks( 172986a66c4eSHarry Wentland res_ctx->pipe_ctx[i].plane_res.mi, 17304562236bSHarry Wentland nbp_marks, 17314562236bSHarry Wentland max_marks, 17323722c794SMikita Lipski min_marks, 17334562236bSHarry Wentland max_marks, 17344562236bSHarry Wentland MAX_WATERMARK); 17358feabd03SYue Hin Lau 17364562236bSHarry Wentland if (i == underlay_idx) 173786a66c4eSHarry Wentland res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_chroma_display_marks( 173886a66c4eSHarry Wentland res_ctx->pipe_ctx[i].plane_res.mi, 17394562236bSHarry Wentland nbp_marks, 17404562236bSHarry Wentland max_marks, 17414562236bSHarry Wentland max_marks, 17424562236bSHarry Wentland MAX_WATERMARK); 17438feabd03SYue Hin Lau 17444562236bSHarry Wentland } 17454562236bSHarry Wentland } 17464562236bSHarry Wentland 17474562236bSHarry Wentland /******************************************************************************* 17484562236bSHarry Wentland * Public functions 17494562236bSHarry Wentland ******************************************************************************/ 17504562236bSHarry Wentland 17514562236bSHarry Wentland static void set_drr(struct pipe_ctx **pipe_ctx, 17524562236bSHarry Wentland int num_pipes, int vmin, int vmax) 17534562236bSHarry Wentland { 17544562236bSHarry Wentland int i = 0; 17554562236bSHarry Wentland struct drr_params params = {0}; 175698e6436dSAnthony Koo // DRR should set trigger event to monitor surface update event 175798e6436dSAnthony Koo unsigned int event_triggers = 0x80; 17584562236bSHarry Wentland 17594562236bSHarry Wentland params.vertical_total_max = vmax; 17604562236bSHarry Wentland params.vertical_total_min = vmin; 17614562236bSHarry Wentland 17624562236bSHarry Wentland /* TODO: If multiple pipes are to be supported, you need 176398e6436dSAnthony Koo * some GSL stuff. Static screen triggers may be programmed differently 176498e6436dSAnthony Koo * as well. 17654562236bSHarry Wentland */ 17664562236bSHarry Wentland for (i = 0; i < num_pipes; i++) { 176798e6436dSAnthony Koo pipe_ctx[i]->stream_res.tg->funcs->set_drr( 176898e6436dSAnthony Koo pipe_ctx[i]->stream_res.tg, ¶ms); 176998e6436dSAnthony Koo 177098e6436dSAnthony Koo if (vmax != 0 && vmin != 0) 177198e6436dSAnthony Koo pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control( 177298e6436dSAnthony Koo pipe_ctx[i]->stream_res.tg, 177398e6436dSAnthony Koo event_triggers); 17744562236bSHarry Wentland } 17754562236bSHarry Wentland } 17764562236bSHarry Wentland 177772ada5f7SEric Cook static void get_position(struct pipe_ctx **pipe_ctx, 177872ada5f7SEric Cook int num_pipes, 177972ada5f7SEric Cook struct crtc_position *position) 178072ada5f7SEric Cook { 178172ada5f7SEric Cook int i = 0; 178272ada5f7SEric Cook 178372ada5f7SEric Cook /* TODO: handle pipes > 1 178472ada5f7SEric Cook */ 178572ada5f7SEric Cook for (i = 0; i < num_pipes; i++) 17866b670fa9SHarry Wentland pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position); 178772ada5f7SEric Cook } 178872ada5f7SEric Cook 17894562236bSHarry Wentland static void set_static_screen_control(struct pipe_ctx **pipe_ctx, 179094267b3dSSylvia Tsai int num_pipes, const struct dc_static_screen_events *events) 17914562236bSHarry Wentland { 17924562236bSHarry Wentland unsigned int i; 179394267b3dSSylvia Tsai unsigned int value = 0; 179494267b3dSSylvia Tsai 179594267b3dSSylvia Tsai if (events->overlay_update) 179694267b3dSSylvia Tsai value |= 0x100; 179794267b3dSSylvia Tsai if (events->surface_update) 179894267b3dSSylvia Tsai value |= 0x80; 179994267b3dSSylvia Tsai if (events->cursor_update) 180094267b3dSSylvia Tsai value |= 0x2; 1801ed8462acSCharlene Liu if (events->force_trigger) 1802ed8462acSCharlene Liu value |= 0x1; 18034562236bSHarry Wentland 1804593f79a2SAlex Deucher if (num_pipes) { 1805593f79a2SAlex Deucher struct dc *dc = pipe_ctx[0]->stream->ctx->dc; 1806593f79a2SAlex Deucher 1807593f79a2SAlex Deucher if (dc->fbc_compressor) 1808c3aa1d67SBhawanpreet Lakha value |= 0x84; 1809593f79a2SAlex Deucher } 1810c3aa1d67SBhawanpreet Lakha 18114562236bSHarry Wentland for (i = 0; i < num_pipes; i++) 18126b670fa9SHarry Wentland pipe_ctx[i]->stream_res.tg->funcs-> 18136b670fa9SHarry Wentland set_static_screen_control(pipe_ctx[i]->stream_res.tg, value); 18144562236bSHarry Wentland } 18154562236bSHarry Wentland 1816f6baff4dSHarry Wentland /* 1817690b5e39SRoman Li * Check if FBC can be enabled 1818690b5e39SRoman Li */ 18199c6569deSHarry Wentland static bool should_enable_fbc(struct dc *dc, 18203bc4aaa9SRoman Li struct dc_state *context, 18213bc4aaa9SRoman Li uint32_t *pipe_idx) 1822690b5e39SRoman Li { 18233bc4aaa9SRoman Li uint32_t i; 18243bc4aaa9SRoman Li struct pipe_ctx *pipe_ctx = NULL; 18253bc4aaa9SRoman Li struct resource_context *res_ctx = &context->res_ctx; 182665d38262Shersen wu unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; 18273bc4aaa9SRoman Li 1828690b5e39SRoman Li 1829690b5e39SRoman Li ASSERT(dc->fbc_compressor); 1830690b5e39SRoman Li 1831690b5e39SRoman Li /* FBC memory should be allocated */ 1832690b5e39SRoman Li if (!dc->ctx->fbc_gpu_addr) 18339c6569deSHarry Wentland return false; 1834690b5e39SRoman Li 1835690b5e39SRoman Li /* Only supports single display */ 1836690b5e39SRoman Li if (context->stream_count != 1) 18379c6569deSHarry Wentland return false; 1838690b5e39SRoman Li 18393bc4aaa9SRoman Li for (i = 0; i < dc->res_pool->pipe_count; i++) { 18403bc4aaa9SRoman Li if (res_ctx->pipe_ctx[i].stream) { 184165d38262Shersen wu 18423bc4aaa9SRoman Li pipe_ctx = &res_ctx->pipe_ctx[i]; 184365d38262Shersen wu 184465d38262Shersen wu if (!pipe_ctx) 184565d38262Shersen wu continue; 184665d38262Shersen wu 184765d38262Shersen wu /* fbc not applicable on underlay pipe */ 184865d38262Shersen wu if (pipe_ctx->pipe_idx != underlay_idx) { 18493bc4aaa9SRoman Li *pipe_idx = i; 18503bc4aaa9SRoman Li break; 18513bc4aaa9SRoman Li } 18523bc4aaa9SRoman Li } 185365d38262Shersen wu } 18543bc4aaa9SRoman Li 185565d38262Shersen wu if (i == dc->res_pool->pipe_count) 185665d38262Shersen wu return false; 185765d38262Shersen wu 1858ceb3dbb4SJun Lei if (!pipe_ctx->stream->link) 185965d38262Shersen wu return false; 18607a840773SRoman Li 1861690b5e39SRoman Li /* Only supports eDP */ 1862ceb3dbb4SJun Lei if (pipe_ctx->stream->link->connector_signal != SIGNAL_TYPE_EDP) 18639c6569deSHarry Wentland return false; 1864690b5e39SRoman Li 1865690b5e39SRoman Li /* PSR should not be enabled */ 1866ceb3dbb4SJun Lei if (pipe_ctx->stream->link->psr_enabled) 18679c6569deSHarry Wentland return false; 1868690b5e39SRoman Li 186993984bbcSShirish S /* Nothing to compress */ 187093984bbcSShirish S if (!pipe_ctx->plane_state) 18719c6569deSHarry Wentland return false; 187293984bbcSShirish S 187305230fa9SRoman Li /* Only for non-linear tiling */ 187405230fa9SRoman Li if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) 18759c6569deSHarry Wentland return false; 187605230fa9SRoman Li 18779c6569deSHarry Wentland return true; 1878690b5e39SRoman Li } 1879690b5e39SRoman Li 1880690b5e39SRoman Li /* 1881690b5e39SRoman Li * Enable FBC 1882690b5e39SRoman Li */ 188365d38262Shersen wu static void enable_fbc( 188465d38262Shersen wu struct dc *dc, 1885608ac7bbSJerry Zuo struct dc_state *context) 1886690b5e39SRoman Li { 18873bc4aaa9SRoman Li uint32_t pipe_idx = 0; 18883bc4aaa9SRoman Li 18893bc4aaa9SRoman Li if (should_enable_fbc(dc, context, &pipe_idx)) { 1890690b5e39SRoman Li /* Program GRPH COMPRESSED ADDRESS and PITCH */ 1891690b5e39SRoman Li struct compr_addr_and_pitch_params params = {0, 0, 0}; 1892690b5e39SRoman Li struct compressor *compr = dc->fbc_compressor; 18933bc4aaa9SRoman Li struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; 18943bc4aaa9SRoman Li 18959c6569deSHarry Wentland params.source_view_width = pipe_ctx->stream->timing.h_addressable; 18969c6569deSHarry Wentland params.source_view_height = pipe_ctx->stream->timing.v_addressable; 189765d38262Shersen wu params.inst = pipe_ctx->stream_res.tg->inst; 1898690b5e39SRoman Li compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr; 1899690b5e39SRoman Li 1900690b5e39SRoman Li compr->funcs->surface_address_and_pitch(compr, ¶ms); 1901690b5e39SRoman Li compr->funcs->set_fbc_invalidation_triggers(compr, 1); 1902690b5e39SRoman Li 1903690b5e39SRoman Li compr->funcs->enable_fbc(compr, ¶ms); 1904690b5e39SRoman Li } 1905690b5e39SRoman Li } 1906690b5e39SRoman Li 190754e8695eSDmytro Laktyushkin static void dce110_reset_hw_ctx_wrap( 1908fb3466a4SBhawanpreet Lakha struct dc *dc, 1909608ac7bbSJerry Zuo struct dc_state *context) 19104562236bSHarry Wentland { 19114562236bSHarry Wentland int i; 19124562236bSHarry Wentland 19134562236bSHarry Wentland /* Reset old context */ 19144562236bSHarry Wentland /* look up the targets that have been removed since last commit */ 1915a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 19164562236bSHarry Wentland struct pipe_ctx *pipe_ctx_old = 1917608ac7bbSJerry Zuo &dc->current_state->res_ctx.pipe_ctx[i]; 19184562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 19194562236bSHarry Wentland 19204562236bSHarry Wentland /* Note: We need to disable output if clock sources change, 19214562236bSHarry Wentland * since bios does optimization and doesn't apply if changing 19224562236bSHarry Wentland * PHY when not already disabled. 19234562236bSHarry Wentland */ 19244562236bSHarry Wentland 19254562236bSHarry Wentland /* Skip underlay pipe since it will be handled in commit surface*/ 19264562236bSHarry Wentland if (!pipe_ctx_old->stream || pipe_ctx_old->top_pipe) 19274562236bSHarry Wentland continue; 19284562236bSHarry Wentland 19294562236bSHarry Wentland if (!pipe_ctx->stream || 193054e8695eSDmytro Laktyushkin pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { 193121e67d4dSHarry Wentland struct clock_source *old_clk = pipe_ctx_old->clock_source; 193221e67d4dSHarry Wentland 1933827f11e9SLeo (Sunpeng) Li /* Disable if new stream is null. O/w, if stream is 1934827f11e9SLeo (Sunpeng) Li * disabled already, no need to disable again. 1935827f11e9SLeo (Sunpeng) Li */ 1936827f11e9SLeo (Sunpeng) Li if (!pipe_ctx->stream || !pipe_ctx->stream->dpms_off) 19374176664bSCharlene Liu core_link_disable_stream(pipe_ctx_old, FREE_ACQUIRED_RESOURCE); 1938d050f8edSHersen Wu 19396b670fa9SHarry Wentland pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true); 19406b670fa9SHarry Wentland if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) { 194154e8695eSDmytro Laktyushkin dm_error("DC: failed to blank crtc!\n"); 194254e8695eSDmytro Laktyushkin BREAK_TO_DEBUGGER(); 194354e8695eSDmytro Laktyushkin } 19446b670fa9SHarry Wentland pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg); 194586a66c4eSHarry Wentland pipe_ctx_old->plane_res.mi->funcs->free_mem_input( 1946608ac7bbSJerry Zuo pipe_ctx_old->plane_res.mi, dc->current_state->stream_count); 194754e8695eSDmytro Laktyushkin 1948ad8960a6SMikita Lipski if (old_clk && 0 == resource_get_clock_source_reference(&context->res_ctx, 1949ad8960a6SMikita Lipski dc->res_pool, 1950ad8960a6SMikita Lipski old_clk)) 195121e67d4dSHarry Wentland old_clk->funcs->cs_power_down(old_clk); 195221e67d4dSHarry Wentland 19537f914a62SYongqiang Sun dc->hwss.disable_plane(dc, pipe_ctx_old); 195454e8695eSDmytro Laktyushkin 195554e8695eSDmytro Laktyushkin pipe_ctx_old->stream = NULL; 195654e8695eSDmytro Laktyushkin } 19574562236bSHarry Wentland } 19584562236bSHarry Wentland } 19594562236bSHarry Wentland 19601a05873fSAnthony Koo static void dce110_setup_audio_dto( 19611a05873fSAnthony Koo struct dc *dc, 19621a05873fSAnthony Koo struct dc_state *context) 19631a05873fSAnthony Koo { 19641a05873fSAnthony Koo int i; 19651a05873fSAnthony Koo 19661a05873fSAnthony Koo /* program audio wall clock. use HDMI as clock source if HDMI 19671a05873fSAnthony Koo * audio active. Otherwise, use DP as clock source 19681a05873fSAnthony Koo * first, loop to find any HDMI audio, if not, loop find DP audio 19691a05873fSAnthony Koo */ 19701a05873fSAnthony Koo /* Setup audio rate clock source */ 19711a05873fSAnthony Koo /* Issue: 19721a05873fSAnthony Koo * Audio lag happened on DP monitor when unplug a HDMI monitor 19731a05873fSAnthony Koo * 19741a05873fSAnthony Koo * Cause: 19751a05873fSAnthony Koo * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL 19761a05873fSAnthony Koo * is set to either dto0 or dto1, audio should work fine. 19771a05873fSAnthony Koo * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1, 19781a05873fSAnthony Koo * set to dto0 will cause audio lag. 19791a05873fSAnthony Koo * 19801a05873fSAnthony Koo * Solution: 19811a05873fSAnthony Koo * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx, 19821a05873fSAnthony Koo * find first available pipe with audio, setup audio wall DTO per topology 19831a05873fSAnthony Koo * instead of per pipe. 19841a05873fSAnthony Koo */ 19851a05873fSAnthony Koo for (i = 0; i < dc->res_pool->pipe_count; i++) { 19861a05873fSAnthony Koo struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 19871a05873fSAnthony Koo 19881a05873fSAnthony Koo if (pipe_ctx->stream == NULL) 19891a05873fSAnthony Koo continue; 19901a05873fSAnthony Koo 19911a05873fSAnthony Koo if (pipe_ctx->top_pipe) 19921a05873fSAnthony Koo continue; 19931a05873fSAnthony Koo 19941a05873fSAnthony Koo if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) 19951a05873fSAnthony Koo continue; 19961a05873fSAnthony Koo 19971a05873fSAnthony Koo if (pipe_ctx->stream_res.audio != NULL) { 19981a05873fSAnthony Koo struct audio_output audio_output; 19991a05873fSAnthony Koo 20001a05873fSAnthony Koo build_audio_output(context, pipe_ctx, &audio_output); 20011a05873fSAnthony Koo 20021a05873fSAnthony Koo pipe_ctx->stream_res.audio->funcs->wall_dto_setup( 20031a05873fSAnthony Koo pipe_ctx->stream_res.audio, 20041a05873fSAnthony Koo pipe_ctx->stream->signal, 20051a05873fSAnthony Koo &audio_output.crtc_info, 20061a05873fSAnthony Koo &audio_output.pll_info); 20071a05873fSAnthony Koo break; 20081a05873fSAnthony Koo } 20091a05873fSAnthony Koo } 20101a05873fSAnthony Koo 20111a05873fSAnthony Koo /* no HDMI audio is found, try DP audio */ 20121a05873fSAnthony Koo if (i == dc->res_pool->pipe_count) { 20131a05873fSAnthony Koo for (i = 0; i < dc->res_pool->pipe_count; i++) { 20141a05873fSAnthony Koo struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 20151a05873fSAnthony Koo 20161a05873fSAnthony Koo if (pipe_ctx->stream == NULL) 20171a05873fSAnthony Koo continue; 20181a05873fSAnthony Koo 20191a05873fSAnthony Koo if (pipe_ctx->top_pipe) 20201a05873fSAnthony Koo continue; 20211a05873fSAnthony Koo 20221a05873fSAnthony Koo if (!dc_is_dp_signal(pipe_ctx->stream->signal)) 20231a05873fSAnthony Koo continue; 20241a05873fSAnthony Koo 20251a05873fSAnthony Koo if (pipe_ctx->stream_res.audio != NULL) { 20261a05873fSAnthony Koo struct audio_output audio_output; 20271a05873fSAnthony Koo 20281a05873fSAnthony Koo build_audio_output(context, pipe_ctx, &audio_output); 20291a05873fSAnthony Koo 20301a05873fSAnthony Koo pipe_ctx->stream_res.audio->funcs->wall_dto_setup( 20311a05873fSAnthony Koo pipe_ctx->stream_res.audio, 20321a05873fSAnthony Koo pipe_ctx->stream->signal, 20331a05873fSAnthony Koo &audio_output.crtc_info, 20341a05873fSAnthony Koo &audio_output.pll_info); 20351a05873fSAnthony Koo break; 20361a05873fSAnthony Koo } 20371a05873fSAnthony Koo } 20381a05873fSAnthony Koo } 20391a05873fSAnthony Koo } 2040cf437593SDmytro Laktyushkin 20414562236bSHarry Wentland enum dc_status dce110_apply_ctx_to_hw( 2042fb3466a4SBhawanpreet Lakha struct dc *dc, 2043608ac7bbSJerry Zuo struct dc_state *context) 20444562236bSHarry Wentland { 20454562236bSHarry Wentland struct dc_bios *dcb = dc->ctx->dc_bios; 20464562236bSHarry Wentland enum dc_status status; 20474562236bSHarry Wentland int i; 20484562236bSHarry Wentland 20494562236bSHarry Wentland /* Reset old context */ 20504562236bSHarry Wentland /* look up the targets that have been removed since last commit */ 20514562236bSHarry Wentland dc->hwss.reset_hw_ctx_wrap(dc, context); 20524562236bSHarry Wentland 20534562236bSHarry Wentland /* Skip applying if no targets */ 2054ab2541b6SAric Cyr if (context->stream_count <= 0) 20554562236bSHarry Wentland return DC_OK; 20564562236bSHarry Wentland 20574562236bSHarry Wentland /* Apply new context */ 20584562236bSHarry Wentland dcb->funcs->set_scratch_critical_state(dcb, true); 20594562236bSHarry Wentland 20604562236bSHarry Wentland /* below is for real asic only */ 2061a2b8659dSTony Cheng for (i = 0; i < dc->res_pool->pipe_count; i++) { 20624562236bSHarry Wentland struct pipe_ctx *pipe_ctx_old = 2063608ac7bbSJerry Zuo &dc->current_state->res_ctx.pipe_ctx[i]; 20644562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 20654562236bSHarry Wentland 20664562236bSHarry Wentland if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe) 20674562236bSHarry Wentland continue; 20684562236bSHarry Wentland 20694562236bSHarry Wentland if (pipe_ctx->stream == pipe_ctx_old->stream) { 20704562236bSHarry Wentland if (pipe_ctx_old->clock_source != pipe_ctx->clock_source) 20714562236bSHarry Wentland dce_crtc_switch_to_clk_src(dc->hwseq, 20724562236bSHarry Wentland pipe_ctx->clock_source, i); 20734562236bSHarry Wentland continue; 20744562236bSHarry Wentland } 20754562236bSHarry Wentland 20764562236bSHarry Wentland dc->hwss.enable_display_power_gating( 20774562236bSHarry Wentland dc, i, dc->ctx->dc_bios, 20784562236bSHarry Wentland PIPE_GATING_CONTROL_DISABLE); 20794562236bSHarry Wentland } 20804562236bSHarry Wentland 20812f3bfb27SRoman Li if (dc->fbc_compressor) 20821663ae1cSBhawanpreet Lakha dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); 20835099114bSAlex Deucher 20841a05873fSAnthony Koo dce110_setup_audio_dto(dc, context); 2085ab8812a3SHersen Wu 2086a2b8659dSTony Cheng for (i = 0; i < dc->res_pool->pipe_count; i++) { 2087ab8812a3SHersen Wu struct pipe_ctx *pipe_ctx_old = 2088608ac7bbSJerry Zuo &dc->current_state->res_ctx.pipe_ctx[i]; 2089ab8812a3SHersen Wu struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 2090ab8812a3SHersen Wu 2091ab8812a3SHersen Wu if (pipe_ctx->stream == NULL) 2092ab8812a3SHersen Wu continue; 2093ab8812a3SHersen Wu 2094eed928dcSCharlene Liu if (pipe_ctx->stream == pipe_ctx_old->stream && 2095eed928dcSCharlene Liu pipe_ctx->stream->link->link_state_valid) { 2096ab8812a3SHersen Wu continue; 2097eed928dcSCharlene Liu } 2098ab8812a3SHersen Wu 20995b92d9d4SHarry Wentland if (pipe_ctx_old->stream && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) 2100313bf4ffSYongqiang Sun continue; 2101313bf4ffSYongqiang Sun 2102ab8812a3SHersen Wu if (pipe_ctx->top_pipe) 2103ab8812a3SHersen Wu continue; 2104ab8812a3SHersen Wu 21054562236bSHarry Wentland status = apply_single_controller_ctx_to_hw( 21064562236bSHarry Wentland pipe_ctx, 21074562236bSHarry Wentland context, 21084562236bSHarry Wentland dc); 21094562236bSHarry Wentland 21104562236bSHarry Wentland if (DC_OK != status) 21114562236bSHarry Wentland return status; 21124562236bSHarry Wentland } 21134562236bSHarry Wentland 2114690b5e39SRoman Li if (dc->fbc_compressor) 211565d38262Shersen wu enable_fbc(dc, dc->current_state); 211665d38262Shersen wu 211765d38262Shersen wu dcb->funcs->set_scratch_critical_state(dcb, false); 2118690b5e39SRoman Li 21194562236bSHarry Wentland return DC_OK; 21204562236bSHarry Wentland } 21214562236bSHarry Wentland 21224562236bSHarry Wentland /******************************************************************************* 21234562236bSHarry Wentland * Front End programming 21244562236bSHarry Wentland ******************************************************************************/ 21254562236bSHarry Wentland static void set_default_colors(struct pipe_ctx *pipe_ctx) 21264562236bSHarry Wentland { 21274562236bSHarry Wentland struct default_adjustment default_adjust = { 0 }; 21284562236bSHarry Wentland 21294562236bSHarry Wentland default_adjust.force_hw_default = false; 213034996173SHarry Wentland default_adjust.in_color_space = pipe_ctx->plane_state->color_space; 213134996173SHarry Wentland default_adjust.out_color_space = pipe_ctx->stream->output_color_space; 21324562236bSHarry Wentland default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW; 21336702a9acSHarry Wentland default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format; 21344562236bSHarry Wentland 21354562236bSHarry Wentland /* display color depth */ 21364562236bSHarry Wentland default_adjust.color_depth = 21374fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->timing.display_color_depth; 21384562236bSHarry Wentland 21394562236bSHarry Wentland /* Lb color depth */ 21406702a9acSHarry Wentland default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth; 21414562236bSHarry Wentland 214286a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default( 214386a66c4eSHarry Wentland pipe_ctx->plane_res.xfm, &default_adjust); 21444562236bSHarry Wentland } 21454562236bSHarry Wentland 2146b06b7680SLeon Elazar 2147b06b7680SLeon Elazar /******************************************************************************* 2148b06b7680SLeon Elazar * In order to turn on/off specific surface we will program 2149b06b7680SLeon Elazar * Blender + CRTC 2150b06b7680SLeon Elazar * 2151b06b7680SLeon Elazar * In case that we have two surfaces and they have a different visibility 2152b06b7680SLeon Elazar * we can't turn off the CRTC since it will turn off the entire display 2153b06b7680SLeon Elazar * 2154b06b7680SLeon Elazar * |----------------------------------------------- | 2155b06b7680SLeon Elazar * |bottom pipe|curr pipe | | | 2156b06b7680SLeon Elazar * |Surface |Surface | Blender | CRCT | 2157b06b7680SLeon Elazar * |visibility |visibility | Configuration| | 2158b06b7680SLeon Elazar * |------------------------------------------------| 2159b06b7680SLeon Elazar * | off | off | CURRENT_PIPE | blank | 2160b06b7680SLeon Elazar * | off | on | CURRENT_PIPE | unblank | 2161b06b7680SLeon Elazar * | on | off | OTHER_PIPE | unblank | 2162b06b7680SLeon Elazar * | on | on | BLENDING | unblank | 2163b06b7680SLeon Elazar * -------------------------------------------------| 2164b06b7680SLeon Elazar * 2165b06b7680SLeon Elazar ******************************************************************************/ 2166fb3466a4SBhawanpreet Lakha static void program_surface_visibility(const struct dc *dc, 21674562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 21684562236bSHarry Wentland { 21694562236bSHarry Wentland enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE; 2170b06b7680SLeon Elazar bool blank_target = false; 21714562236bSHarry Wentland 21724562236bSHarry Wentland if (pipe_ctx->bottom_pipe) { 2173b06b7680SLeon Elazar 2174b06b7680SLeon Elazar /* For now we are supporting only two pipes */ 2175b06b7680SLeon Elazar ASSERT(pipe_ctx->bottom_pipe->bottom_pipe == NULL); 2176b06b7680SLeon Elazar 21773be5262eSHarry Wentland if (pipe_ctx->bottom_pipe->plane_state->visible) { 21783be5262eSHarry Wentland if (pipe_ctx->plane_state->visible) 21794562236bSHarry Wentland blender_mode = BLND_MODE_BLENDING; 21804562236bSHarry Wentland else 21814562236bSHarry Wentland blender_mode = BLND_MODE_OTHER_PIPE; 2182b06b7680SLeon Elazar 21833be5262eSHarry Wentland } else if (!pipe_ctx->plane_state->visible) 2184b06b7680SLeon Elazar blank_target = true; 2185b06b7680SLeon Elazar 21863be5262eSHarry Wentland } else if (!pipe_ctx->plane_state->visible) 2187b06b7680SLeon Elazar blank_target = true; 2188b06b7680SLeon Elazar 2189e07f541fSYongqiang Sun dce_set_blender_mode(dc->hwseq, pipe_ctx->stream_res.tg->inst, blender_mode); 21906b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, blank_target); 2191b06b7680SLeon Elazar 21924562236bSHarry Wentland } 21934562236bSHarry Wentland 21941bf56e62SZeyu Fan static void program_gamut_remap(struct pipe_ctx *pipe_ctx) 21951bf56e62SZeyu Fan { 2196146a9f63SKrunoslav Kovac int i = 0; 21971bf56e62SZeyu Fan struct xfm_grph_csc_adjustment adjust; 21981bf56e62SZeyu Fan memset(&adjust, 0, sizeof(adjust)); 21991bf56e62SZeyu Fan adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; 22001bf56e62SZeyu Fan 22011bf56e62SZeyu Fan 22024fa086b9SLeo (Sunpeng) Li if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { 22031bf56e62SZeyu Fan adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; 2204146a9f63SKrunoslav Kovac 2205146a9f63SKrunoslav Kovac for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++) 2206146a9f63SKrunoslav Kovac adjust.temperature_matrix[i] = 2207146a9f63SKrunoslav Kovac pipe_ctx->stream->gamut_remap_matrix.matrix[i]; 22081bf56e62SZeyu Fan } 22091bf56e62SZeyu Fan 221086a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); 22111bf56e62SZeyu Fan } 2212fb3466a4SBhawanpreet Lakha static void update_plane_addr(const struct dc *dc, 22134562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 22144562236bSHarry Wentland { 22153be5262eSHarry Wentland struct dc_plane_state *plane_state = pipe_ctx->plane_state; 22164562236bSHarry Wentland 22173be5262eSHarry Wentland if (plane_state == NULL) 22184562236bSHarry Wentland return; 22194562236bSHarry Wentland 222086a66c4eSHarry Wentland pipe_ctx->plane_res.mi->funcs->mem_input_program_surface_flip_and_addr( 222186a66c4eSHarry Wentland pipe_ctx->plane_res.mi, 22223be5262eSHarry Wentland &plane_state->address, 22233be5262eSHarry Wentland plane_state->flip_immediate); 22244562236bSHarry Wentland 22253be5262eSHarry Wentland plane_state->status.requested_address = plane_state->address; 22264562236bSHarry Wentland } 22274562236bSHarry Wentland 2228f774b339SEric Yang static void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) 22294562236bSHarry Wentland { 22303be5262eSHarry Wentland struct dc_plane_state *plane_state = pipe_ctx->plane_state; 22314562236bSHarry Wentland 22323be5262eSHarry Wentland if (plane_state == NULL) 22334562236bSHarry Wentland return; 22344562236bSHarry Wentland 22353be5262eSHarry Wentland plane_state->status.is_flip_pending = 223686a66c4eSHarry Wentland pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending( 223786a66c4eSHarry Wentland pipe_ctx->plane_res.mi); 22384562236bSHarry Wentland 22393be5262eSHarry Wentland if (plane_state->status.is_flip_pending && !plane_state->visible) 224086a66c4eSHarry Wentland pipe_ctx->plane_res.mi->current_address = pipe_ctx->plane_res.mi->request_address; 22414562236bSHarry Wentland 224286a66c4eSHarry Wentland plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address; 224386a66c4eSHarry Wentland if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && 22446b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye) { 22453be5262eSHarry Wentland plane_state->status.is_right_eye =\ 22466b670fa9SHarry Wentland !pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg); 22477f5c22d1SVitaly Prosyak } 22484562236bSHarry Wentland } 22494562236bSHarry Wentland 2250fb3466a4SBhawanpreet Lakha void dce110_power_down(struct dc *dc) 22514562236bSHarry Wentland { 22524562236bSHarry Wentland power_down_all_hw_blocks(dc); 22534562236bSHarry Wentland disable_vga_and_power_gate_all_controllers(dc); 22544562236bSHarry Wentland } 22554562236bSHarry Wentland 22564562236bSHarry Wentland static bool wait_for_reset_trigger_to_occur( 22574562236bSHarry Wentland struct dc_context *dc_ctx, 22584562236bSHarry Wentland struct timing_generator *tg) 22594562236bSHarry Wentland { 22604562236bSHarry Wentland bool rc = false; 22614562236bSHarry Wentland 22624562236bSHarry Wentland /* To avoid endless loop we wait at most 22634562236bSHarry Wentland * frames_to_wait_on_triggered_reset frames for the reset to occur. */ 22644562236bSHarry Wentland const uint32_t frames_to_wait_on_triggered_reset = 10; 22654562236bSHarry Wentland uint32_t i; 22664562236bSHarry Wentland 22674562236bSHarry Wentland for (i = 0; i < frames_to_wait_on_triggered_reset; i++) { 22684562236bSHarry Wentland 22694562236bSHarry Wentland if (!tg->funcs->is_counter_moving(tg)) { 22704562236bSHarry Wentland DC_ERROR("TG counter is not moving!\n"); 22714562236bSHarry Wentland break; 22724562236bSHarry Wentland } 22734562236bSHarry Wentland 22744562236bSHarry Wentland if (tg->funcs->did_triggered_reset_occur(tg)) { 22754562236bSHarry Wentland rc = true; 22764562236bSHarry Wentland /* usually occurs at i=1 */ 22774562236bSHarry Wentland DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n", 22784562236bSHarry Wentland i); 22794562236bSHarry Wentland break; 22804562236bSHarry Wentland } 22814562236bSHarry Wentland 22824562236bSHarry Wentland /* Wait for one frame. */ 22834562236bSHarry Wentland tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE); 22844562236bSHarry Wentland tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK); 22854562236bSHarry Wentland } 22864562236bSHarry Wentland 22874562236bSHarry Wentland if (false == rc) 22884562236bSHarry Wentland DC_ERROR("GSL: Timeout on reset trigger!\n"); 22894562236bSHarry Wentland 22904562236bSHarry Wentland return rc; 22914562236bSHarry Wentland } 22924562236bSHarry Wentland 22934562236bSHarry Wentland /* Enable timing synchronization for a group of Timing Generators. */ 22944562236bSHarry Wentland static void dce110_enable_timing_synchronization( 2295fb3466a4SBhawanpreet Lakha struct dc *dc, 22964562236bSHarry Wentland int group_index, 22974562236bSHarry Wentland int group_size, 22984562236bSHarry Wentland struct pipe_ctx *grouped_pipes[]) 22994562236bSHarry Wentland { 23004562236bSHarry Wentland struct dc_context *dc_ctx = dc->ctx; 23014562236bSHarry Wentland struct dcp_gsl_params gsl_params = { 0 }; 23024562236bSHarry Wentland int i; 23034562236bSHarry Wentland 23044562236bSHarry Wentland DC_SYNC_INFO("GSL: Setting-up...\n"); 23054562236bSHarry Wentland 23064562236bSHarry Wentland /* Designate a single TG in the group as a master. 23074562236bSHarry Wentland * Since HW doesn't care which one, we always assign 23084562236bSHarry Wentland * the 1st one in the group. */ 23094562236bSHarry Wentland gsl_params.gsl_group = 0; 23106b670fa9SHarry Wentland gsl_params.gsl_master = grouped_pipes[0]->stream_res.tg->inst; 23114562236bSHarry Wentland 23124562236bSHarry Wentland for (i = 0; i < group_size; i++) 23136b670fa9SHarry Wentland grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock( 23146b670fa9SHarry Wentland grouped_pipes[i]->stream_res.tg, &gsl_params); 23154562236bSHarry Wentland 23164562236bSHarry Wentland /* Reset slave controllers on master VSync */ 23174562236bSHarry Wentland DC_SYNC_INFO("GSL: enabling trigger-reset\n"); 23184562236bSHarry Wentland 23194562236bSHarry Wentland for (i = 1 /* skip the master */; i < group_size; i++) 23206b670fa9SHarry Wentland grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger( 2321fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg, 2322fa2123dbSMikita Lipski gsl_params.gsl_group); 23234562236bSHarry Wentland 23244562236bSHarry Wentland for (i = 1 /* skip the master */; i < group_size; i++) { 23254562236bSHarry Wentland DC_SYNC_INFO("GSL: waiting for reset to occur.\n"); 23266b670fa9SHarry Wentland wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg); 2327fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger( 2328fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg); 23294562236bSHarry Wentland } 23304562236bSHarry Wentland 23314562236bSHarry Wentland /* GSL Vblank synchronization is a one time sync mechanism, assumption 23324562236bSHarry Wentland * is that the sync'ed displays will not drift out of sync over time*/ 23334562236bSHarry Wentland DC_SYNC_INFO("GSL: Restoring register states.\n"); 23344562236bSHarry Wentland for (i = 0; i < group_size; i++) 23356b670fa9SHarry Wentland grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg); 23364562236bSHarry Wentland 23374562236bSHarry Wentland DC_SYNC_INFO("GSL: Set-up complete.\n"); 23384562236bSHarry Wentland } 23394562236bSHarry Wentland 2340fa2123dbSMikita Lipski static void dce110_enable_per_frame_crtc_position_reset( 2341fa2123dbSMikita Lipski struct dc *dc, 2342fa2123dbSMikita Lipski int group_size, 2343fa2123dbSMikita Lipski struct pipe_ctx *grouped_pipes[]) 2344fa2123dbSMikita Lipski { 2345fa2123dbSMikita Lipski struct dc_context *dc_ctx = dc->ctx; 2346fa2123dbSMikita Lipski struct dcp_gsl_params gsl_params = { 0 }; 2347fa2123dbSMikita Lipski int i; 2348fa2123dbSMikita Lipski 2349fa2123dbSMikita Lipski gsl_params.gsl_group = 0; 235037cd85ceSDavid Francis gsl_params.gsl_master = 0; 2351fa2123dbSMikita Lipski 2352fa2123dbSMikita Lipski for (i = 0; i < group_size; i++) 2353fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock( 2354fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg, &gsl_params); 2355fa2123dbSMikita Lipski 2356fa2123dbSMikita Lipski DC_SYNC_INFO("GSL: enabling trigger-reset\n"); 2357fa2123dbSMikita Lipski 2358fa2123dbSMikita Lipski for (i = 1; i < group_size; i++) 2359fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset( 2360fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg, 2361fa2123dbSMikita Lipski gsl_params.gsl_master, 2362fa2123dbSMikita Lipski &grouped_pipes[i]->stream->triggered_crtc_reset); 2363fa2123dbSMikita Lipski 2364fa2123dbSMikita Lipski DC_SYNC_INFO("GSL: waiting for reset to occur.\n"); 2365fa2123dbSMikita Lipski for (i = 1; i < group_size; i++) 2366fa2123dbSMikita Lipski wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg); 2367fa2123dbSMikita Lipski 2368fa2123dbSMikita Lipski for (i = 0; i < group_size; i++) 2369fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg); 2370fa2123dbSMikita Lipski 2371fa2123dbSMikita Lipski } 2372fa2123dbSMikita Lipski 2373fb55546eSAnthony Koo static void init_pipes(struct dc *dc, struct dc_state *context) 2374fb55546eSAnthony Koo { 2375fb55546eSAnthony Koo // Do nothing 2376fb55546eSAnthony Koo } 2377fb55546eSAnthony Koo 2378fb3466a4SBhawanpreet Lakha static void init_hw(struct dc *dc) 23794562236bSHarry Wentland { 23804562236bSHarry Wentland int i; 23814562236bSHarry Wentland struct dc_bios *bp; 23824562236bSHarry Wentland struct transform *xfm; 23835e7773a2SAnthony Koo struct abm *abm; 238470d9e8cbSPaul Hsieh struct dmcu *dmcu; 23854562236bSHarry Wentland 23864562236bSHarry Wentland bp = dc->ctx->dc_bios; 23874562236bSHarry Wentland for (i = 0; i < dc->res_pool->pipe_count; i++) { 23884562236bSHarry Wentland xfm = dc->res_pool->transforms[i]; 23894562236bSHarry Wentland xfm->funcs->transform_reset(xfm); 23904562236bSHarry Wentland 23914562236bSHarry Wentland dc->hwss.enable_display_power_gating( 23924562236bSHarry Wentland dc, i, bp, 23934562236bSHarry Wentland PIPE_GATING_CONTROL_INIT); 23944562236bSHarry Wentland dc->hwss.enable_display_power_gating( 23954562236bSHarry Wentland dc, i, bp, 23964562236bSHarry Wentland PIPE_GATING_CONTROL_DISABLE); 23974562236bSHarry Wentland dc->hwss.enable_display_pipe_clock_gating( 23984562236bSHarry Wentland dc->ctx, 23994562236bSHarry Wentland true); 24004562236bSHarry Wentland } 24014562236bSHarry Wentland 2402e166ad43SJulia Lawall dce_clock_gating_power_up(dc->hwseq, false); 24034562236bSHarry Wentland /***************************************/ 24044562236bSHarry Wentland 24054562236bSHarry Wentland for (i = 0; i < dc->link_count; i++) { 24064562236bSHarry Wentland /****************************************/ 24074562236bSHarry Wentland /* Power up AND update implementation according to the 24084562236bSHarry Wentland * required signal (which may be different from the 24094562236bSHarry Wentland * default signal on connector). */ 2410d0778ebfSHarry Wentland struct dc_link *link = dc->links[i]; 2411069d418fSAndrew Jiang 24124562236bSHarry Wentland link->link_enc->funcs->hw_init(link->link_enc); 24134562236bSHarry Wentland } 24144562236bSHarry Wentland 24154562236bSHarry Wentland for (i = 0; i < dc->res_pool->pipe_count; i++) { 24164562236bSHarry Wentland struct timing_generator *tg = dc->res_pool->timing_generators[i]; 24174562236bSHarry Wentland 24184562236bSHarry Wentland tg->funcs->disable_vga(tg); 24194562236bSHarry Wentland 24204562236bSHarry Wentland /* Blank controller using driver code instead of 24214562236bSHarry Wentland * command table. */ 24224562236bSHarry Wentland tg->funcs->set_blank(tg, true); 24234b5e7d62SHersen Wu hwss_wait_for_blank_complete(tg); 24244562236bSHarry Wentland } 24254562236bSHarry Wentland 24264562236bSHarry Wentland for (i = 0; i < dc->res_pool->audio_count; i++) { 24274562236bSHarry Wentland struct audio *audio = dc->res_pool->audios[i]; 24284562236bSHarry Wentland audio->funcs->hw_init(audio); 24294562236bSHarry Wentland } 24305e7773a2SAnthony Koo 24315e7773a2SAnthony Koo abm = dc->res_pool->abm; 24326728b30cSAnthony Koo if (abm != NULL) { 24336728b30cSAnthony Koo abm->funcs->init_backlight(abm); 24345e7773a2SAnthony Koo abm->funcs->abm_init(abm); 24354562236bSHarry Wentland } 24365099114bSAlex Deucher 243770d9e8cbSPaul Hsieh dmcu = dc->res_pool->dmcu; 243870d9e8cbSPaul Hsieh if (dmcu != NULL && abm != NULL) 243970d9e8cbSPaul Hsieh abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu); 244070d9e8cbSPaul Hsieh 24412f3bfb27SRoman Li if (dc->fbc_compressor) 24421663ae1cSBhawanpreet Lakha dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor); 2443690b5e39SRoman Li 24446728b30cSAnthony Koo } 24454562236bSHarry Wentland 24469566b675SDmytro Laktyushkin 24479566b675SDmytro Laktyushkin void dce110_prepare_bandwidth( 2448fb3466a4SBhawanpreet Lakha struct dc *dc, 24499566b675SDmytro Laktyushkin struct dc_state *context) 2450cf437593SDmytro Laktyushkin { 2451dc88b4a6SEric Yang struct clk_mgr *dccg = dc->clk_mgr; 2452fab55d61SDmytro Laktyushkin 2453fab55d61SDmytro Laktyushkin dce110_set_safe_displaymarks(&context->res_ctx, dc->res_pool); 2454cf437593SDmytro Laktyushkin 24555a83c932SNicholas Kazlauskas dccg->funcs->update_clocks( 24565a83c932SNicholas Kazlauskas dccg, 245724f7dd7eSDmytro Laktyushkin context, 24589566b675SDmytro Laktyushkin false); 24599566b675SDmytro Laktyushkin } 24609566b675SDmytro Laktyushkin 24619566b675SDmytro Laktyushkin void dce110_optimize_bandwidth( 24629566b675SDmytro Laktyushkin struct dc *dc, 24639566b675SDmytro Laktyushkin struct dc_state *context) 24649566b675SDmytro Laktyushkin { 2465dc88b4a6SEric Yang struct clk_mgr *dccg = dc->clk_mgr; 24669566b675SDmytro Laktyushkin 24679566b675SDmytro Laktyushkin dce110_set_displaymarks(dc, context); 24689566b675SDmytro Laktyushkin 24699566b675SDmytro Laktyushkin dccg->funcs->update_clocks( 24709566b675SDmytro Laktyushkin dccg, 24719566b675SDmytro Laktyushkin context, 24729566b675SDmytro Laktyushkin true); 24734562236bSHarry Wentland } 24744562236bSHarry Wentland 24754562236bSHarry Wentland static void dce110_program_front_end_for_pipe( 2476fb3466a4SBhawanpreet Lakha struct dc *dc, struct pipe_ctx *pipe_ctx) 24774562236bSHarry Wentland { 247886a66c4eSHarry Wentland struct mem_input *mi = pipe_ctx->plane_res.mi; 24794562236bSHarry Wentland struct pipe_ctx *old_pipe = NULL; 24803be5262eSHarry Wentland struct dc_plane_state *plane_state = pipe_ctx->plane_state; 24814562236bSHarry Wentland struct xfm_grph_csc_adjustment adjust; 24824562236bSHarry Wentland struct out_csc_color_matrix tbl_entry; 24834562236bSHarry Wentland unsigned int i; 24845d4b05ddSBhawanpreet Lakha DC_LOGGER_INIT(); 24854562236bSHarry Wentland memset(&tbl_entry, 0, sizeof(tbl_entry)); 24864562236bSHarry Wentland 2487608ac7bbSJerry Zuo if (dc->current_state) 2488608ac7bbSJerry Zuo old_pipe = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; 24894562236bSHarry Wentland 24904562236bSHarry Wentland memset(&adjust, 0, sizeof(adjust)); 24914562236bSHarry Wentland adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; 24924562236bSHarry Wentland 2493e07f541fSYongqiang Sun dce_enable_fe_clock(dc->hwseq, mi->inst, true); 24944562236bSHarry Wentland 24954562236bSHarry Wentland set_default_colors(pipe_ctx); 24964fa086b9SLeo (Sunpeng) Li if (pipe_ctx->stream->csc_color_matrix.enable_adjustment 24974562236bSHarry Wentland == true) { 24984562236bSHarry Wentland tbl_entry.color_space = 24994fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->output_color_space; 25004562236bSHarry Wentland 25014562236bSHarry Wentland for (i = 0; i < 12; i++) 25024562236bSHarry Wentland tbl_entry.regval[i] = 25034fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->csc_color_matrix.matrix[i]; 25044562236bSHarry Wentland 250586a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment 250686a66c4eSHarry Wentland (pipe_ctx->plane_res.xfm, &tbl_entry); 25074562236bSHarry Wentland } 25084562236bSHarry Wentland 25094fa086b9SLeo (Sunpeng) Li if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { 25104562236bSHarry Wentland adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; 2511146a9f63SKrunoslav Kovac 2512146a9f63SKrunoslav Kovac for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++) 2513146a9f63SKrunoslav Kovac adjust.temperature_matrix[i] = 2514146a9f63SKrunoslav Kovac pipe_ctx->stream->gamut_remap_matrix.matrix[i]; 25154562236bSHarry Wentland } 25164562236bSHarry Wentland 251786a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); 25184562236bSHarry Wentland 25196702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; 2520c1473558SAndrey Grodzovsky 25214562236bSHarry Wentland program_scaler(dc, pipe_ctx); 25224562236bSHarry Wentland 25234562236bSHarry Wentland mi->funcs->mem_input_program_surface_config( 25244562236bSHarry Wentland mi, 25253be5262eSHarry Wentland plane_state->format, 25263be5262eSHarry Wentland &plane_state->tiling_info, 25273be5262eSHarry Wentland &plane_state->plane_size, 25283be5262eSHarry Wentland plane_state->rotation, 2529624d7c47SYongqiang Sun NULL, 25304b28b76bSDmytro Laktyushkin false); 25314b28b76bSDmytro Laktyushkin if (mi->funcs->set_blank) 25323be5262eSHarry Wentland mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible); 25334562236bSHarry Wentland 2534fb3466a4SBhawanpreet Lakha if (dc->config.gpu_vm_support) 25354562236bSHarry Wentland mi->funcs->mem_input_program_pte_vm( 253686a66c4eSHarry Wentland pipe_ctx->plane_res.mi, 25373be5262eSHarry Wentland plane_state->format, 25383be5262eSHarry Wentland &plane_state->tiling_info, 25393be5262eSHarry Wentland plane_state->rotation); 25404562236bSHarry Wentland 2541067c878aSYongqiang Sun /* Moved programming gamma from dc to hwss */ 2542405c50a0SAndrew Jiang if (pipe_ctx->plane_state->update_flags.bits.full_update || 2543405c50a0SAndrew Jiang pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change || 2544405c50a0SAndrew Jiang pipe_ctx->plane_state->update_flags.bits.gamma_change) 2545a6114e85SHarry Wentland dc->hwss.set_input_transfer_func(pipe_ctx, pipe_ctx->plane_state); 2546405c50a0SAndrew Jiang 2547405c50a0SAndrew Jiang if (pipe_ctx->plane_state->update_flags.bits.full_update) 2548a6114e85SHarry Wentland dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream); 2549067c878aSYongqiang Sun 25501296423bSBhawanpreet Lakha DC_LOG_SURFACE( 25513032deb5SBhawanpreet Lakha "Pipe:%d %p: addr hi:0x%x, " 25524562236bSHarry Wentland "addr low:0x%x, " 25534562236bSHarry Wentland "src: %d, %d, %d," 25544562236bSHarry Wentland " %d; dst: %d, %d, %d, %d;" 25554562236bSHarry Wentland "clip: %d, %d, %d, %d\n", 25564562236bSHarry Wentland pipe_ctx->pipe_idx, 25573032deb5SBhawanpreet Lakha (void *) pipe_ctx->plane_state, 25583be5262eSHarry Wentland pipe_ctx->plane_state->address.grph.addr.high_part, 25593be5262eSHarry Wentland pipe_ctx->plane_state->address.grph.addr.low_part, 25603be5262eSHarry Wentland pipe_ctx->plane_state->src_rect.x, 25613be5262eSHarry Wentland pipe_ctx->plane_state->src_rect.y, 25623be5262eSHarry Wentland pipe_ctx->plane_state->src_rect.width, 25633be5262eSHarry Wentland pipe_ctx->plane_state->src_rect.height, 25643be5262eSHarry Wentland pipe_ctx->plane_state->dst_rect.x, 25653be5262eSHarry Wentland pipe_ctx->plane_state->dst_rect.y, 25663be5262eSHarry Wentland pipe_ctx->plane_state->dst_rect.width, 25673be5262eSHarry Wentland pipe_ctx->plane_state->dst_rect.height, 25683be5262eSHarry Wentland pipe_ctx->plane_state->clip_rect.x, 25693be5262eSHarry Wentland pipe_ctx->plane_state->clip_rect.y, 25703be5262eSHarry Wentland pipe_ctx->plane_state->clip_rect.width, 25713be5262eSHarry Wentland pipe_ctx->plane_state->clip_rect.height); 25724562236bSHarry Wentland 25731296423bSBhawanpreet Lakha DC_LOG_SURFACE( 25744562236bSHarry Wentland "Pipe %d: width, height, x, y\n" 25754562236bSHarry Wentland "viewport:%d, %d, %d, %d\n" 25764562236bSHarry Wentland "recout: %d, %d, %d, %d\n", 25774562236bSHarry Wentland pipe_ctx->pipe_idx, 25786702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.width, 25796702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.height, 25806702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.x, 25816702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.y, 25826702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.width, 25836702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.height, 25846702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.x, 25856702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.y); 25864562236bSHarry Wentland } 25874562236bSHarry Wentland 25884562236bSHarry Wentland static void dce110_apply_ctx_for_surface( 2589fb3466a4SBhawanpreet Lakha struct dc *dc, 25903e9ad616SEric Yang const struct dc_stream_state *stream, 25913e9ad616SEric Yang int num_planes, 2592608ac7bbSJerry Zuo struct dc_state *context) 25934562236bSHarry Wentland { 25942194e3aeSRoman Li int i; 25954562236bSHarry Wentland 25963e9ad616SEric Yang if (num_planes == 0) 25974562236bSHarry Wentland return; 25984562236bSHarry Wentland 259965d38262Shersen wu if (dc->fbc_compressor) 260065d38262Shersen wu dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); 260165d38262Shersen wu 26023e9ad616SEric Yang for (i = 0; i < dc->res_pool->pipe_count; i++) { 26033dc780ecSYongqiang Sun struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 26043dc780ecSYongqiang Sun struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; 26053dc780ecSYongqiang Sun 26062194e3aeSRoman Li if (stream == pipe_ctx->stream) { 26073dc780ecSYongqiang Sun if (!pipe_ctx->top_pipe && 26083dc780ecSYongqiang Sun (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) 26093dc780ecSYongqiang Sun dc->hwss.pipe_control_lock(dc, pipe_ctx, true); 26103e9ad616SEric Yang } 26113e9ad616SEric Yang } 26123e9ad616SEric Yang 2613a2b8659dSTony Cheng for (i = 0; i < dc->res_pool->pipe_count; i++) { 26144562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 26154562236bSHarry Wentland 2616a2607aefSHarry Wentland if (pipe_ctx->stream != stream) 26174562236bSHarry Wentland continue; 26184562236bSHarry Wentland 26193b21b6d2SJerry Zuo /* Need to allocate mem before program front end for Fiji */ 26203b21b6d2SJerry Zuo pipe_ctx->plane_res.mi->funcs->allocate_mem_input( 26213b21b6d2SJerry Zuo pipe_ctx->plane_res.mi, 26223b21b6d2SJerry Zuo pipe_ctx->stream->timing.h_total, 26233b21b6d2SJerry Zuo pipe_ctx->stream->timing.v_total, 2624380604e2SKen Chalmers pipe_ctx->stream->timing.pix_clk_100hz / 10, 26253b21b6d2SJerry Zuo context->stream_count); 26263b21b6d2SJerry Zuo 26274562236bSHarry Wentland dce110_program_front_end_for_pipe(dc, pipe_ctx); 26284f804817SYongqiang Sun 26294f804817SYongqiang Sun dc->hwss.update_plane_addr(dc, pipe_ctx); 26304f804817SYongqiang Sun 2631b06b7680SLeon Elazar program_surface_visibility(dc, pipe_ctx); 26324562236bSHarry Wentland 26334562236bSHarry Wentland } 26343dc780ecSYongqiang Sun 26353dc780ecSYongqiang Sun for (i = 0; i < dc->res_pool->pipe_count; i++) { 26363dc780ecSYongqiang Sun struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 26373dc780ecSYongqiang Sun struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; 26383dc780ecSYongqiang Sun 26393dc780ecSYongqiang Sun if ((stream == pipe_ctx->stream) && 26403dc780ecSYongqiang Sun (!pipe_ctx->top_pipe) && 26413dc780ecSYongqiang Sun (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) 26423dc780ecSYongqiang Sun dc->hwss.pipe_control_lock(dc, pipe_ctx, false); 26433dc780ecSYongqiang Sun } 264465d38262Shersen wu 264565d38262Shersen wu if (dc->fbc_compressor) 264612a8bd88SShirish S enable_fbc(dc, context); 26474562236bSHarry Wentland } 26484562236bSHarry Wentland 2649e6c258cbSYongqiang Sun static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx) 26504562236bSHarry Wentland { 2651bc373a89SRoman Li int fe_idx = pipe_ctx->plane_res.mi ? 2652bc373a89SRoman Li pipe_ctx->plane_res.mi->inst : pipe_ctx->pipe_idx; 2653e6c258cbSYongqiang Sun 26547950f0f9SDmytro Laktyushkin /* Do not power down fe when stream is active on dce*/ 2655608ac7bbSJerry Zuo if (dc->current_state->res_ctx.pipe_ctx[fe_idx].stream) 26564562236bSHarry Wentland return; 26574562236bSHarry Wentland 26584562236bSHarry Wentland dc->hwss.enable_display_power_gating( 2659cfe4645eSDmytro Laktyushkin dc, fe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE); 2660cfe4645eSDmytro Laktyushkin 2661cfe4645eSDmytro Laktyushkin dc->res_pool->transforms[fe_idx]->funcs->transform_reset( 2662cfe4645eSDmytro Laktyushkin dc->res_pool->transforms[fe_idx]); 26634562236bSHarry Wentland } 26644562236bSHarry Wentland 26656be425f3SEric Yang static void dce110_wait_for_mpcc_disconnect( 2666fb3466a4SBhawanpreet Lakha struct dc *dc, 26676be425f3SEric Yang struct resource_pool *res_pool, 26686be425f3SEric Yang struct pipe_ctx *pipe_ctx) 2669b6762f0cSEric Yang { 2670b6762f0cSEric Yang /* do nothing*/ 2671b6762f0cSEric Yang } 2672b6762f0cSEric Yang 26734bd0dc68SJoshua Aberback static void program_output_csc(struct dc *dc, 26744bd0dc68SJoshua Aberback struct pipe_ctx *pipe_ctx, 26754bd0dc68SJoshua Aberback enum dc_color_space colorspace, 26764bd0dc68SJoshua Aberback uint16_t *matrix, 26774bd0dc68SJoshua Aberback int opp_id) 26784bd0dc68SJoshua Aberback { 26794bd0dc68SJoshua Aberback int i; 26804bd0dc68SJoshua Aberback struct out_csc_color_matrix tbl_entry; 26814bd0dc68SJoshua Aberback 26824bd0dc68SJoshua Aberback if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { 26834bd0dc68SJoshua Aberback enum dc_color_space color_space = pipe_ctx->stream->output_color_space; 26844bd0dc68SJoshua Aberback 26854bd0dc68SJoshua Aberback for (i = 0; i < 12; i++) 26864bd0dc68SJoshua Aberback tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; 26874bd0dc68SJoshua Aberback 26884bd0dc68SJoshua Aberback tbl_entry.color_space = color_space; 26894bd0dc68SJoshua Aberback 26904bd0dc68SJoshua Aberback pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment( 26914bd0dc68SJoshua Aberback pipe_ctx->plane_res.xfm, &tbl_entry); 26924bd0dc68SJoshua Aberback } 26934bd0dc68SJoshua Aberback } 26944bd0dc68SJoshua Aberback 269533fd17d9SEric Yang void dce110_set_cursor_position(struct pipe_ctx *pipe_ctx) 269633fd17d9SEric Yang { 269733fd17d9SEric Yang struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position; 269833fd17d9SEric Yang struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; 269933fd17d9SEric Yang struct mem_input *mi = pipe_ctx->plane_res.mi; 270033fd17d9SEric Yang struct dc_cursor_mi_param param = { 2701380604e2SKen Chalmers .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10, 270233d7598dSJun Lei .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clocks.xtalin_clock_inKhz, 270339a9f4d8SDmytro Laktyushkin .viewport = pipe_ctx->plane_res.scl_data.viewport, 270439a9f4d8SDmytro Laktyushkin .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz, 270539a9f4d8SDmytro Laktyushkin .v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert, 270608ed681cSDmytro Laktyushkin .rotation = pipe_ctx->plane_state->rotation, 270708ed681cSDmytro Laktyushkin .mirror = pipe_ctx->plane_state->horizontal_mirror 270833fd17d9SEric Yang }; 270933fd17d9SEric Yang 271033fd17d9SEric Yang if (pipe_ctx->plane_state->address.type 271133fd17d9SEric Yang == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) 271233fd17d9SEric Yang pos_cpy.enable = false; 271333fd17d9SEric Yang 271433fd17d9SEric Yang if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) 271533fd17d9SEric Yang pos_cpy.enable = false; 271633fd17d9SEric Yang 2717dc75dd70SRoman Li if (ipp->funcs->ipp_cursor_set_position) 271833fd17d9SEric Yang ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); 2719dc75dd70SRoman Li if (mi->funcs->set_cursor_position) 272033fd17d9SEric Yang mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m); 272133fd17d9SEric Yang } 272233fd17d9SEric Yang 272333fd17d9SEric Yang void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx) 272433fd17d9SEric Yang { 272533fd17d9SEric Yang struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes; 272633fd17d9SEric Yang 2727d1aaad05SHarry Wentland if (pipe_ctx->plane_res.ipp && 2728d1aaad05SHarry Wentland pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes) 272933fd17d9SEric Yang pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( 273033fd17d9SEric Yang pipe_ctx->plane_res.ipp, attributes); 273133fd17d9SEric Yang 2732d1aaad05SHarry Wentland if (pipe_ctx->plane_res.mi && 2733d1aaad05SHarry Wentland pipe_ctx->plane_res.mi->funcs->set_cursor_attributes) 273433fd17d9SEric Yang pipe_ctx->plane_res.mi->funcs->set_cursor_attributes( 273533fd17d9SEric Yang pipe_ctx->plane_res.mi, attributes); 273633fd17d9SEric Yang 2737d1aaad05SHarry Wentland if (pipe_ctx->plane_res.xfm && 2738d1aaad05SHarry Wentland pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes) 273933fd17d9SEric Yang pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes( 274033fd17d9SEric Yang pipe_ctx->plane_res.xfm, attributes); 274133fd17d9SEric Yang } 274233fd17d9SEric Yang 27434562236bSHarry Wentland static const struct hw_sequencer_funcs dce110_funcs = { 27441bf56e62SZeyu Fan .program_gamut_remap = program_gamut_remap, 27454bd0dc68SJoshua Aberback .program_output_csc = program_output_csc, 27464562236bSHarry Wentland .init_hw = init_hw, 2747fb55546eSAnthony Koo .init_pipes = init_pipes, 27484562236bSHarry Wentland .apply_ctx_to_hw = dce110_apply_ctx_to_hw, 27494562236bSHarry Wentland .apply_ctx_for_surface = dce110_apply_ctx_for_surface, 27504562236bSHarry Wentland .update_plane_addr = update_plane_addr, 27514562236bSHarry Wentland .update_pending_status = dce110_update_pending_status, 2752d7194cf6SAric Cyr .set_input_transfer_func = dce110_set_input_transfer_func, 275390e508baSAnthony Koo .set_output_transfer_func = dce110_set_output_transfer_func, 27544562236bSHarry Wentland .power_down = dce110_power_down, 27554562236bSHarry Wentland .enable_accelerated_mode = dce110_enable_accelerated_mode, 27564562236bSHarry Wentland .enable_timing_synchronization = dce110_enable_timing_synchronization, 2757fa2123dbSMikita Lipski .enable_per_frame_crtc_position_reset = dce110_enable_per_frame_crtc_position_reset, 27584562236bSHarry Wentland .update_info_frame = dce110_update_info_frame, 27594562236bSHarry Wentland .enable_stream = dce110_enable_stream, 27604562236bSHarry Wentland .disable_stream = dce110_disable_stream, 27614562236bSHarry Wentland .unblank_stream = dce110_unblank_stream, 276241b49742SCharlene Liu .blank_stream = dce110_blank_stream, 27631a05873fSAnthony Koo .enable_audio_stream = dce110_enable_audio_stream, 27641a05873fSAnthony Koo .disable_audio_stream = dce110_disable_audio_stream, 27654562236bSHarry Wentland .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating, 27664562236bSHarry Wentland .enable_display_power_gating = dce110_enable_display_power_gating, 27677f914a62SYongqiang Sun .disable_plane = dce110_power_down_fe, 27684562236bSHarry Wentland .pipe_control_lock = dce_pipe_control_lock, 27699566b675SDmytro Laktyushkin .prepare_bandwidth = dce110_prepare_bandwidth, 27709566b675SDmytro Laktyushkin .optimize_bandwidth = dce110_optimize_bandwidth, 27714562236bSHarry Wentland .set_drr = set_drr, 277272ada5f7SEric Cook .get_position = get_position, 27734562236bSHarry Wentland .set_static_screen_control = set_static_screen_control, 277454e8695eSDmytro Laktyushkin .reset_hw_ctx_wrap = dce110_reset_hw_ctx_wrap, 27753158223eSEric Bernstein .enable_stream_timing = dce110_enable_stream_timing, 2776240d09d0SGary Kattan .disable_stream_gating = NULL, 2777240d09d0SGary Kattan .enable_stream_gating = NULL, 277815e17335SCharlene Liu .setup_stereo = NULL, 277915e17335SCharlene Liu .set_avmute = dce110_set_avmute, 278041f97c07SHersen Wu .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect, 278187401969SAndrew Jiang .edp_backlight_control = hwss_edp_backlight_control, 278287401969SAndrew Jiang .edp_power_control = hwss_edp_power_control, 2783904623eeSYongqiang Sun .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready, 278433fd17d9SEric Yang .set_cursor_position = dce110_set_cursor_position, 278533fd17d9SEric Yang .set_cursor_attribute = dce110_set_cursor_attribute 27864562236bSHarry Wentland }; 27874562236bSHarry Wentland 2788c13b408bSDave Airlie void dce110_hw_sequencer_construct(struct dc *dc) 27894562236bSHarry Wentland { 27904562236bSHarry Wentland dc->hwss = dce110_funcs; 27914562236bSHarry Wentland } 27924562236bSHarry Wentland 2793