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 373eab7916SShirish S #if defined(CONFIG_DRM_AMD_DC_FBC) 381663ae1cSBhawanpreet Lakha #include "dce110_compressor.h" 391663ae1cSBhawanpreet Lakha #endif 401663ae1cSBhawanpreet Lakha 414562236bSHarry Wentland #include "bios/bios_parser_helper.h" 424562236bSHarry Wentland #include "timing_generator.h" 434562236bSHarry Wentland #include "mem_input.h" 444562236bSHarry Wentland #include "opp.h" 454562236bSHarry Wentland #include "ipp.h" 464562236bSHarry Wentland #include "transform.h" 474562236bSHarry Wentland #include "stream_encoder.h" 484562236bSHarry Wentland #include "link_encoder.h" 4987401969SAndrew Jiang #include "link_hwss.h" 504562236bSHarry Wentland #include "clock_source.h" 515e7773a2SAnthony Koo #include "abm.h" 524562236bSHarry Wentland #include "audio.h" 5308b16886SZeyu Fan #include "reg_helper.h" 544562236bSHarry Wentland 554562236bSHarry Wentland /* include DCE11 register header files */ 564562236bSHarry Wentland #include "dce/dce_11_0_d.h" 574562236bSHarry Wentland #include "dce/dce_11_0_sh_mask.h" 58e266fdf6SVitaly Prosyak #include "custom_float.h" 594562236bSHarry Wentland 6087401969SAndrew Jiang /* 6187401969SAndrew Jiang * All values are in milliseconds; 6287401969SAndrew Jiang * For eDP, after power-up/power/down, 6387401969SAndrew Jiang * 300/500 msec max. delay from LCDVCC to black video generation 6487401969SAndrew Jiang */ 6587401969SAndrew Jiang #define PANEL_POWER_UP_TIMEOUT 300 6687401969SAndrew Jiang #define PANEL_POWER_DOWN_TIMEOUT 500 6787401969SAndrew Jiang #define HPD_CHECK_INTERVAL 10 6887401969SAndrew Jiang 695eefbc40SYue Hin Lau #define CTX \ 705eefbc40SYue Hin Lau hws->ctx 715eefbc40SYue Hin Lau #define REG(reg)\ 725eefbc40SYue Hin Lau hws->regs->reg 735eefbc40SYue Hin Lau 745eefbc40SYue Hin Lau #undef FN 755eefbc40SYue Hin Lau #define FN(reg_name, field_name) \ 765eefbc40SYue Hin Lau hws->shifts->field_name, hws->masks->field_name 775eefbc40SYue Hin Lau 784562236bSHarry Wentland struct dce110_hw_seq_reg_offsets { 794562236bSHarry Wentland uint32_t crtc; 804562236bSHarry Wentland }; 814562236bSHarry Wentland 824562236bSHarry Wentland static const struct dce110_hw_seq_reg_offsets reg_offsets[] = { 834562236bSHarry Wentland { 844562236bSHarry Wentland .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), 854562236bSHarry Wentland }, 864562236bSHarry Wentland { 874562236bSHarry Wentland .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), 884562236bSHarry Wentland }, 894562236bSHarry Wentland { 904562236bSHarry Wentland .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), 914562236bSHarry Wentland }, 924562236bSHarry Wentland { 934562236bSHarry Wentland .crtc = (mmCRTCV_GSL_CONTROL - mmCRTC_GSL_CONTROL), 944562236bSHarry Wentland } 954562236bSHarry Wentland }; 964562236bSHarry Wentland 974562236bSHarry Wentland #define HW_REG_BLND(reg, id)\ 984562236bSHarry Wentland (reg + reg_offsets[id].blnd) 994562236bSHarry Wentland 1004562236bSHarry Wentland #define HW_REG_CRTC(reg, id)\ 1014562236bSHarry Wentland (reg + reg_offsets[id].crtc) 1024562236bSHarry Wentland 1034562236bSHarry Wentland #define MAX_WATERMARK 0xFFFF 1044562236bSHarry Wentland #define SAFE_NBP_MARK 0x7FFF 1054562236bSHarry Wentland 1064562236bSHarry Wentland /******************************************************************************* 1074562236bSHarry Wentland * Private definitions 1084562236bSHarry Wentland ******************************************************************************/ 1094562236bSHarry Wentland /***************************PIPE_CONTROL***********************************/ 1104562236bSHarry Wentland static void dce110_init_pte(struct dc_context *ctx) 1114562236bSHarry Wentland { 1124562236bSHarry Wentland uint32_t addr; 1134562236bSHarry Wentland uint32_t value = 0; 1144562236bSHarry Wentland uint32_t chunk_int = 0; 1154562236bSHarry Wentland uint32_t chunk_mul = 0; 1164562236bSHarry Wentland 1174562236bSHarry Wentland addr = mmUNP_DVMM_PTE_CONTROL; 1184562236bSHarry Wentland value = dm_read_reg(ctx, addr); 1194562236bSHarry Wentland 1204562236bSHarry Wentland set_reg_field_value( 1214562236bSHarry Wentland value, 1224562236bSHarry Wentland 0, 1234562236bSHarry Wentland DVMM_PTE_CONTROL, 1244562236bSHarry Wentland DVMM_USE_SINGLE_PTE); 1254562236bSHarry Wentland 1264562236bSHarry Wentland set_reg_field_value( 1274562236bSHarry Wentland value, 1284562236bSHarry Wentland 1, 1294562236bSHarry Wentland DVMM_PTE_CONTROL, 1304562236bSHarry Wentland DVMM_PTE_BUFFER_MODE0); 1314562236bSHarry Wentland 1324562236bSHarry Wentland set_reg_field_value( 1334562236bSHarry Wentland value, 1344562236bSHarry Wentland 1, 1354562236bSHarry Wentland DVMM_PTE_CONTROL, 1364562236bSHarry Wentland DVMM_PTE_BUFFER_MODE1); 1374562236bSHarry Wentland 1384562236bSHarry Wentland dm_write_reg(ctx, addr, value); 1394562236bSHarry Wentland 1404562236bSHarry Wentland addr = mmDVMM_PTE_REQ; 1414562236bSHarry Wentland value = dm_read_reg(ctx, addr); 1424562236bSHarry Wentland 1434562236bSHarry Wentland chunk_int = get_reg_field_value( 1444562236bSHarry Wentland value, 1454562236bSHarry Wentland DVMM_PTE_REQ, 1464562236bSHarry Wentland HFLIP_PTEREQ_PER_CHUNK_INT); 1474562236bSHarry Wentland 1484562236bSHarry Wentland chunk_mul = get_reg_field_value( 1494562236bSHarry Wentland value, 1504562236bSHarry Wentland DVMM_PTE_REQ, 1514562236bSHarry Wentland HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); 1524562236bSHarry Wentland 1534562236bSHarry Wentland if (chunk_int != 0x4 || chunk_mul != 0x4) { 1544562236bSHarry Wentland 1554562236bSHarry Wentland set_reg_field_value( 1564562236bSHarry Wentland value, 1574562236bSHarry Wentland 255, 1584562236bSHarry Wentland DVMM_PTE_REQ, 1594562236bSHarry Wentland MAX_PTEREQ_TO_ISSUE); 1604562236bSHarry Wentland 1614562236bSHarry Wentland set_reg_field_value( 1624562236bSHarry Wentland value, 1634562236bSHarry Wentland 4, 1644562236bSHarry Wentland DVMM_PTE_REQ, 1654562236bSHarry Wentland HFLIP_PTEREQ_PER_CHUNK_INT); 1664562236bSHarry Wentland 1674562236bSHarry Wentland set_reg_field_value( 1684562236bSHarry Wentland value, 1694562236bSHarry Wentland 4, 1704562236bSHarry Wentland DVMM_PTE_REQ, 1714562236bSHarry Wentland HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); 1724562236bSHarry Wentland 1734562236bSHarry Wentland dm_write_reg(ctx, addr, value); 1744562236bSHarry Wentland } 1754562236bSHarry Wentland } 1764562236bSHarry Wentland /**************************************************************************/ 1774562236bSHarry Wentland 1784562236bSHarry Wentland static void enable_display_pipe_clock_gating( 1794562236bSHarry Wentland struct dc_context *ctx, 1804562236bSHarry Wentland bool clock_gating) 1814562236bSHarry Wentland { 1824562236bSHarry Wentland /*TODO*/ 1834562236bSHarry Wentland } 1844562236bSHarry Wentland 1854562236bSHarry Wentland static bool dce110_enable_display_power_gating( 186fb3466a4SBhawanpreet Lakha struct dc *dc, 1874562236bSHarry Wentland uint8_t controller_id, 1884562236bSHarry Wentland struct dc_bios *dcb, 1894562236bSHarry Wentland enum pipe_gating_control power_gating) 1904562236bSHarry Wentland { 1914562236bSHarry Wentland enum bp_result bp_result = BP_RESULT_OK; 1924562236bSHarry Wentland enum bp_pipe_control_action cntl; 1934562236bSHarry Wentland struct dc_context *ctx = dc->ctx; 1944562236bSHarry Wentland unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; 1954562236bSHarry Wentland 1964562236bSHarry Wentland if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) 1974562236bSHarry Wentland return true; 1984562236bSHarry Wentland 1994562236bSHarry Wentland if (power_gating == PIPE_GATING_CONTROL_INIT) 2004562236bSHarry Wentland cntl = ASIC_PIPE_INIT; 2014562236bSHarry Wentland else if (power_gating == PIPE_GATING_CONTROL_ENABLE) 2024562236bSHarry Wentland cntl = ASIC_PIPE_ENABLE; 2034562236bSHarry Wentland else 2044562236bSHarry Wentland cntl = ASIC_PIPE_DISABLE; 2054562236bSHarry Wentland 2064562236bSHarry Wentland if (controller_id == underlay_idx) 2074562236bSHarry Wentland controller_id = CONTROLLER_ID_UNDERLAY0 - 1; 2084562236bSHarry Wentland 2094562236bSHarry Wentland if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0){ 2104562236bSHarry Wentland 2114562236bSHarry Wentland bp_result = dcb->funcs->enable_disp_power_gating( 2124562236bSHarry Wentland dcb, controller_id + 1, cntl); 2134562236bSHarry Wentland 2144562236bSHarry Wentland /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2 2154562236bSHarry Wentland * by default when command table is called 2164562236bSHarry Wentland * 2174562236bSHarry Wentland * Bios parser accepts controller_id = 6 as indicative of 2184562236bSHarry Wentland * underlay pipe in dce110. But we do not support more 2194562236bSHarry Wentland * than 3. 2204562236bSHarry Wentland */ 2214562236bSHarry Wentland if (controller_id < CONTROLLER_ID_MAX - 1) 2224562236bSHarry Wentland dm_write_reg(ctx, 2234562236bSHarry Wentland HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE, controller_id), 2244562236bSHarry Wentland 0); 2254562236bSHarry Wentland } 2264562236bSHarry Wentland 2274562236bSHarry Wentland if (power_gating != PIPE_GATING_CONTROL_ENABLE) 2284562236bSHarry Wentland dce110_init_pte(ctx); 2294562236bSHarry Wentland 2304562236bSHarry Wentland if (bp_result == BP_RESULT_OK) 2314562236bSHarry Wentland return true; 2324562236bSHarry Wentland else 2334562236bSHarry Wentland return false; 2344562236bSHarry Wentland } 2354562236bSHarry Wentland 2364562236bSHarry Wentland static void build_prescale_params(struct ipp_prescale_params *prescale_params, 2373be5262eSHarry Wentland const struct dc_plane_state *plane_state) 2384562236bSHarry Wentland { 2394562236bSHarry Wentland prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED; 2404562236bSHarry Wentland 2413be5262eSHarry Wentland switch (plane_state->format) { 2424562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 2438693049aSTony Cheng case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 2444562236bSHarry Wentland prescale_params->scale = 0x2020; 2454562236bSHarry Wentland break; 2464562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 2474562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 2484562236bSHarry Wentland prescale_params->scale = 0x2008; 2494562236bSHarry Wentland break; 2504562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 2514562236bSHarry Wentland case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 2524562236bSHarry Wentland prescale_params->scale = 0x2000; 2534562236bSHarry Wentland break; 2544562236bSHarry Wentland default: 2554562236bSHarry Wentland ASSERT(false); 256d7194cf6SAric Cyr break; 2574562236bSHarry Wentland } 2584562236bSHarry Wentland } 2594562236bSHarry Wentland 260d7194cf6SAric Cyr static bool dce110_set_input_transfer_func( 261fb735a9fSAnthony Koo struct pipe_ctx *pipe_ctx, 2623be5262eSHarry Wentland const struct dc_plane_state *plane_state) 2634562236bSHarry Wentland { 26486a66c4eSHarry Wentland struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; 2657b0c470fSLeo (Sunpeng) Li const struct dc_transfer_func *tf = NULL; 26690e508baSAnthony Koo struct ipp_prescale_params prescale_params = { 0 }; 26790e508baSAnthony Koo bool result = true; 26890e508baSAnthony Koo 26990e508baSAnthony Koo if (ipp == NULL) 27090e508baSAnthony Koo return false; 27190e508baSAnthony Koo 2723be5262eSHarry Wentland if (plane_state->in_transfer_func) 2733be5262eSHarry Wentland tf = plane_state->in_transfer_func; 27490e508baSAnthony Koo 2753be5262eSHarry Wentland build_prescale_params(&prescale_params, plane_state); 27690e508baSAnthony Koo ipp->funcs->ipp_program_prescale(ipp, &prescale_params); 27790e508baSAnthony Koo 2783be5262eSHarry Wentland if (plane_state->gamma_correction && dce_use_lut(plane_state)) 2793be5262eSHarry Wentland ipp->funcs->ipp_program_input_lut(ipp, plane_state->gamma_correction); 280d7194cf6SAric Cyr 28190e508baSAnthony Koo if (tf == NULL) { 28290e508baSAnthony Koo /* Default case if no input transfer function specified */ 28390e508baSAnthony Koo ipp->funcs->ipp_set_degamma(ipp, 284306dadf0SAmy Zhang IPP_DEGAMMA_MODE_HW_sRGB); 2857b0c470fSLeo (Sunpeng) Li } else if (tf->type == TF_TYPE_PREDEFINED) { 2867b0c470fSLeo (Sunpeng) Li switch (tf->tf) { 28790e508baSAnthony Koo case TRANSFER_FUNCTION_SRGB: 28890e508baSAnthony Koo ipp->funcs->ipp_set_degamma(ipp, 28990e508baSAnthony Koo IPP_DEGAMMA_MODE_HW_sRGB); 29090e508baSAnthony Koo break; 29190e508baSAnthony Koo case TRANSFER_FUNCTION_BT709: 29290e508baSAnthony Koo ipp->funcs->ipp_set_degamma(ipp, 29390e508baSAnthony Koo IPP_DEGAMMA_MODE_HW_xvYCC); 29490e508baSAnthony Koo break; 29590e508baSAnthony Koo case TRANSFER_FUNCTION_LINEAR: 29690e508baSAnthony Koo ipp->funcs->ipp_set_degamma(ipp, 29790e508baSAnthony Koo IPP_DEGAMMA_MODE_BYPASS); 29890e508baSAnthony Koo break; 29990e508baSAnthony Koo case TRANSFER_FUNCTION_PQ: 30090e508baSAnthony Koo result = false; 30190e508baSAnthony Koo break; 30290e508baSAnthony Koo default: 30390e508baSAnthony Koo result = false; 304d7194cf6SAric Cyr break; 30590e508baSAnthony Koo } 3067b0c470fSLeo (Sunpeng) Li } else if (tf->type == TF_TYPE_BYPASS) { 30770063a59SAmy Zhang ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); 30890e508baSAnthony Koo } else { 30990e508baSAnthony Koo /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/ 31090e508baSAnthony Koo result = false; 31190e508baSAnthony Koo } 31290e508baSAnthony Koo 31390e508baSAnthony Koo return result; 31490e508baSAnthony Koo } 31590e508baSAnthony Koo 316fcd2f4bfSAmy Zhang static bool convert_to_custom_float( 317fcd2f4bfSAmy Zhang struct pwl_result_data *rgb_resulted, 318fcd2f4bfSAmy Zhang struct curve_points *arr_points, 319fcd2f4bfSAmy Zhang uint32_t hw_points_num) 320fcd2f4bfSAmy Zhang { 321fcd2f4bfSAmy Zhang struct custom_float_format fmt; 322fcd2f4bfSAmy Zhang 323fcd2f4bfSAmy Zhang struct pwl_result_data *rgb = rgb_resulted; 324fcd2f4bfSAmy Zhang 325fcd2f4bfSAmy Zhang uint32_t i = 0; 326fcd2f4bfSAmy Zhang 327fcd2f4bfSAmy Zhang fmt.exponenta_bits = 6; 328fcd2f4bfSAmy Zhang fmt.mantissa_bits = 12; 329fcd2f4bfSAmy Zhang fmt.sign = true; 330fcd2f4bfSAmy Zhang 331fcd2f4bfSAmy Zhang if (!convert_to_custom_float_format( 332fcd2f4bfSAmy Zhang arr_points[0].x, 333fcd2f4bfSAmy Zhang &fmt, 334fcd2f4bfSAmy Zhang &arr_points[0].custom_float_x)) { 335fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 336fcd2f4bfSAmy Zhang return false; 337fcd2f4bfSAmy Zhang } 338fcd2f4bfSAmy Zhang 339fcd2f4bfSAmy Zhang if (!convert_to_custom_float_format( 340fcd2f4bfSAmy Zhang arr_points[0].offset, 341fcd2f4bfSAmy Zhang &fmt, 342fcd2f4bfSAmy Zhang &arr_points[0].custom_float_offset)) { 343fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 344fcd2f4bfSAmy Zhang return false; 345fcd2f4bfSAmy Zhang } 346fcd2f4bfSAmy Zhang 347fcd2f4bfSAmy Zhang if (!convert_to_custom_float_format( 348fcd2f4bfSAmy Zhang arr_points[0].slope, 349fcd2f4bfSAmy Zhang &fmt, 350fcd2f4bfSAmy Zhang &arr_points[0].custom_float_slope)) { 351fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 352fcd2f4bfSAmy Zhang return false; 353fcd2f4bfSAmy Zhang } 354fcd2f4bfSAmy Zhang 355fcd2f4bfSAmy Zhang fmt.mantissa_bits = 10; 356fcd2f4bfSAmy Zhang fmt.sign = false; 357fcd2f4bfSAmy Zhang 358fcd2f4bfSAmy Zhang if (!convert_to_custom_float_format( 359fcd2f4bfSAmy Zhang arr_points[1].x, 360fcd2f4bfSAmy Zhang &fmt, 361fcd2f4bfSAmy Zhang &arr_points[1].custom_float_x)) { 362fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 363fcd2f4bfSAmy Zhang return false; 364fcd2f4bfSAmy Zhang } 365fcd2f4bfSAmy Zhang 366fcd2f4bfSAmy Zhang if (!convert_to_custom_float_format( 367fcd2f4bfSAmy Zhang arr_points[1].y, 368fcd2f4bfSAmy Zhang &fmt, 369fcd2f4bfSAmy Zhang &arr_points[1].custom_float_y)) { 370fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 371fcd2f4bfSAmy Zhang return false; 372fcd2f4bfSAmy Zhang } 373fcd2f4bfSAmy Zhang 374fcd2f4bfSAmy Zhang if (!convert_to_custom_float_format( 375fcd2f4bfSAmy Zhang arr_points[2].slope, 376fcd2f4bfSAmy Zhang &fmt, 377fcd2f4bfSAmy Zhang &arr_points[2].custom_float_slope)) { 378fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 379fcd2f4bfSAmy Zhang return false; 380fcd2f4bfSAmy Zhang } 381fcd2f4bfSAmy Zhang 382fcd2f4bfSAmy Zhang fmt.mantissa_bits = 12; 383fcd2f4bfSAmy Zhang fmt.sign = true; 384fcd2f4bfSAmy Zhang 385fcd2f4bfSAmy Zhang while (i != hw_points_num) { 386fcd2f4bfSAmy Zhang if (!convert_to_custom_float_format( 387fcd2f4bfSAmy Zhang rgb->red, 388fcd2f4bfSAmy Zhang &fmt, 389fcd2f4bfSAmy Zhang &rgb->red_reg)) { 390fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 391fcd2f4bfSAmy Zhang return false; 392fcd2f4bfSAmy Zhang } 393fcd2f4bfSAmy Zhang 394fcd2f4bfSAmy Zhang if (!convert_to_custom_float_format( 395fcd2f4bfSAmy Zhang rgb->green, 396fcd2f4bfSAmy Zhang &fmt, 397fcd2f4bfSAmy Zhang &rgb->green_reg)) { 398fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 399fcd2f4bfSAmy Zhang return false; 400fcd2f4bfSAmy Zhang } 401fcd2f4bfSAmy Zhang 402fcd2f4bfSAmy Zhang if (!convert_to_custom_float_format( 403fcd2f4bfSAmy Zhang rgb->blue, 404fcd2f4bfSAmy Zhang &fmt, 405fcd2f4bfSAmy Zhang &rgb->blue_reg)) { 406fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 407fcd2f4bfSAmy Zhang return false; 408fcd2f4bfSAmy Zhang } 409fcd2f4bfSAmy Zhang 410fcd2f4bfSAmy Zhang if (!convert_to_custom_float_format( 411fcd2f4bfSAmy Zhang rgb->delta_red, 412fcd2f4bfSAmy Zhang &fmt, 413fcd2f4bfSAmy Zhang &rgb->delta_red_reg)) { 414fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 415fcd2f4bfSAmy Zhang return false; 416fcd2f4bfSAmy Zhang } 417fcd2f4bfSAmy Zhang 418fcd2f4bfSAmy Zhang if (!convert_to_custom_float_format( 419fcd2f4bfSAmy Zhang rgb->delta_green, 420fcd2f4bfSAmy Zhang &fmt, 421fcd2f4bfSAmy Zhang &rgb->delta_green_reg)) { 422fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 423fcd2f4bfSAmy Zhang return false; 424fcd2f4bfSAmy Zhang } 425fcd2f4bfSAmy Zhang 426fcd2f4bfSAmy Zhang if (!convert_to_custom_float_format( 427fcd2f4bfSAmy Zhang rgb->delta_blue, 428fcd2f4bfSAmy Zhang &fmt, 429fcd2f4bfSAmy Zhang &rgb->delta_blue_reg)) { 430fcd2f4bfSAmy Zhang BREAK_TO_DEBUGGER(); 431fcd2f4bfSAmy Zhang return false; 432fcd2f4bfSAmy Zhang } 433fcd2f4bfSAmy Zhang 434fcd2f4bfSAmy Zhang ++rgb; 435fcd2f4bfSAmy Zhang ++i; 436fcd2f4bfSAmy Zhang } 437fcd2f4bfSAmy Zhang 438fcd2f4bfSAmy Zhang return true; 439fcd2f4bfSAmy Zhang } 440fcd2f4bfSAmy Zhang 441e266fdf6SVitaly Prosyak static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func 442fcd2f4bfSAmy Zhang *output_tf, struct pwl_params *regamma_params) 443fcd2f4bfSAmy Zhang { 44423ae4f8eSAmy Zhang struct curve_points *arr_points; 44523ae4f8eSAmy Zhang struct pwl_result_data *rgb_resulted; 44623ae4f8eSAmy Zhang struct pwl_result_data *rgb; 44723ae4f8eSAmy Zhang struct pwl_result_data *rgb_plus_1; 448fcd2f4bfSAmy Zhang struct fixed31_32 y_r; 449fcd2f4bfSAmy Zhang struct fixed31_32 y_g; 450fcd2f4bfSAmy Zhang struct fixed31_32 y_b; 451fcd2f4bfSAmy Zhang struct fixed31_32 y1_min; 452fcd2f4bfSAmy Zhang struct fixed31_32 y3_max; 453fcd2f4bfSAmy Zhang 454fcd2f4bfSAmy Zhang int32_t segment_start, segment_end; 45523ae4f8eSAmy Zhang uint32_t i, j, k, seg_distr[16], increment, start_index, hw_points; 45623ae4f8eSAmy Zhang 45770063a59SAmy Zhang if (output_tf == NULL || regamma_params == NULL || 45870063a59SAmy Zhang output_tf->type == TF_TYPE_BYPASS) 45923ae4f8eSAmy Zhang return false; 46023ae4f8eSAmy Zhang 46123ae4f8eSAmy Zhang arr_points = regamma_params->arr_points; 46223ae4f8eSAmy Zhang rgb_resulted = regamma_params->rgb_resulted; 46323ae4f8eSAmy Zhang hw_points = 0; 464fcd2f4bfSAmy Zhang 465fcd2f4bfSAmy Zhang memset(regamma_params, 0, sizeof(struct pwl_params)); 466fcd2f4bfSAmy Zhang 467fcd2f4bfSAmy Zhang if (output_tf->tf == TRANSFER_FUNCTION_PQ) { 468534db198SAmy Zhang /* 16 segments 469fcd2f4bfSAmy Zhang * segments are from 2^-11 to 2^5 470fcd2f4bfSAmy Zhang */ 471fcd2f4bfSAmy Zhang segment_start = -11; 472fcd2f4bfSAmy Zhang segment_end = 5; 473fcd2f4bfSAmy Zhang 474534db198SAmy Zhang seg_distr[0] = 2; 475534db198SAmy Zhang seg_distr[1] = 2; 476534db198SAmy Zhang seg_distr[2] = 2; 477534db198SAmy Zhang seg_distr[3] = 2; 478534db198SAmy Zhang seg_distr[4] = 2; 479534db198SAmy Zhang seg_distr[5] = 2; 480534db198SAmy Zhang seg_distr[6] = 3; 481534db198SAmy Zhang seg_distr[7] = 4; 482534db198SAmy Zhang seg_distr[8] = 4; 483534db198SAmy Zhang seg_distr[9] = 4; 484534db198SAmy Zhang seg_distr[10] = 4; 485534db198SAmy Zhang seg_distr[11] = 5; 486534db198SAmy Zhang seg_distr[12] = 5; 487534db198SAmy Zhang seg_distr[13] = 5; 488534db198SAmy Zhang seg_distr[14] = 5; 489534db198SAmy Zhang seg_distr[15] = 5; 490534db198SAmy Zhang 491fcd2f4bfSAmy Zhang } else { 492534db198SAmy Zhang /* 10 segments 493fcd2f4bfSAmy Zhang * segment is from 2^-10 to 2^0 494fcd2f4bfSAmy Zhang */ 495fcd2f4bfSAmy Zhang segment_start = -10; 496fcd2f4bfSAmy Zhang segment_end = 0; 497534db198SAmy Zhang 498534db198SAmy Zhang seg_distr[0] = 3; 499534db198SAmy Zhang seg_distr[1] = 4; 500534db198SAmy Zhang seg_distr[2] = 4; 501534db198SAmy Zhang seg_distr[3] = 4; 502534db198SAmy Zhang seg_distr[4] = 4; 503534db198SAmy Zhang seg_distr[5] = 4; 504534db198SAmy Zhang seg_distr[6] = 4; 505534db198SAmy Zhang seg_distr[7] = 4; 506534db198SAmy Zhang seg_distr[8] = 5; 507534db198SAmy Zhang seg_distr[9] = 5; 508534db198SAmy Zhang seg_distr[10] = -1; 509534db198SAmy Zhang seg_distr[11] = -1; 510534db198SAmy Zhang seg_distr[12] = -1; 511534db198SAmy Zhang seg_distr[13] = -1; 512534db198SAmy Zhang seg_distr[14] = -1; 513534db198SAmy Zhang seg_distr[15] = -1; 514fcd2f4bfSAmy Zhang } 515fcd2f4bfSAmy Zhang 516534db198SAmy Zhang for (k = 0; k < 16; k++) { 517534db198SAmy Zhang if (seg_distr[k] != -1) 518534db198SAmy Zhang hw_points += (1 << seg_distr[k]); 519534db198SAmy Zhang } 520534db198SAmy Zhang 521fcd2f4bfSAmy Zhang j = 0; 522534db198SAmy Zhang for (k = 0; k < (segment_end - segment_start); k++) { 523534db198SAmy Zhang increment = 32 / (1 << seg_distr[k]); 524534db198SAmy Zhang start_index = (segment_start + k + 25) * 32; 525534db198SAmy Zhang for (i = start_index; i < start_index + 32; i += increment) { 526534db198SAmy Zhang if (j == hw_points - 1) 527fcd2f4bfSAmy Zhang break; 528fcd2f4bfSAmy Zhang rgb_resulted[j].red = output_tf->tf_pts.red[i]; 529fcd2f4bfSAmy Zhang rgb_resulted[j].green = output_tf->tf_pts.green[i]; 530fcd2f4bfSAmy Zhang rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; 531fcd2f4bfSAmy Zhang j++; 532fcd2f4bfSAmy Zhang } 533534db198SAmy Zhang } 534534db198SAmy Zhang 535534db198SAmy Zhang /* last point */ 536534db198SAmy Zhang start_index = (segment_end + 25) * 32; 537534db198SAmy Zhang rgb_resulted[hw_points - 1].red = 538534db198SAmy Zhang output_tf->tf_pts.red[start_index]; 539534db198SAmy Zhang rgb_resulted[hw_points - 1].green = 540534db198SAmy Zhang output_tf->tf_pts.green[start_index]; 541534db198SAmy Zhang rgb_resulted[hw_points - 1].blue = 542534db198SAmy Zhang output_tf->tf_pts.blue[start_index]; 543fcd2f4bfSAmy Zhang 544fcd2f4bfSAmy Zhang arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), 545fcd2f4bfSAmy Zhang dal_fixed31_32_from_int(segment_start)); 546fcd2f4bfSAmy Zhang arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), 547fcd2f4bfSAmy Zhang dal_fixed31_32_from_int(segment_end)); 548fcd2f4bfSAmy Zhang arr_points[2].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), 549fcd2f4bfSAmy Zhang dal_fixed31_32_from_int(segment_end)); 550fcd2f4bfSAmy Zhang 551fcd2f4bfSAmy Zhang y_r = rgb_resulted[0].red; 552fcd2f4bfSAmy Zhang y_g = rgb_resulted[0].green; 553fcd2f4bfSAmy Zhang y_b = rgb_resulted[0].blue; 554fcd2f4bfSAmy Zhang 555fcd2f4bfSAmy Zhang y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b)); 556fcd2f4bfSAmy Zhang 557fcd2f4bfSAmy Zhang arr_points[0].y = y1_min; 558fcd2f4bfSAmy Zhang arr_points[0].slope = dal_fixed31_32_div( 559fcd2f4bfSAmy Zhang arr_points[0].y, 560fcd2f4bfSAmy Zhang arr_points[0].x); 561fcd2f4bfSAmy Zhang 562fcd2f4bfSAmy Zhang y_r = rgb_resulted[hw_points - 1].red; 563fcd2f4bfSAmy Zhang y_g = rgb_resulted[hw_points - 1].green; 564fcd2f4bfSAmy Zhang y_b = rgb_resulted[hw_points - 1].blue; 565fcd2f4bfSAmy Zhang 566fcd2f4bfSAmy Zhang /* see comment above, m_arrPoints[1].y should be the Y value for the 567fcd2f4bfSAmy Zhang * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) 568fcd2f4bfSAmy Zhang */ 569fcd2f4bfSAmy Zhang y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); 570fcd2f4bfSAmy Zhang 571fcd2f4bfSAmy Zhang arr_points[1].y = y3_max; 572fcd2f4bfSAmy Zhang arr_points[2].y = y3_max; 573fcd2f4bfSAmy Zhang 574fcd2f4bfSAmy Zhang arr_points[1].slope = dal_fixed31_32_zero; 575fcd2f4bfSAmy Zhang arr_points[2].slope = dal_fixed31_32_zero; 576fcd2f4bfSAmy Zhang 577fcd2f4bfSAmy Zhang if (output_tf->tf == TRANSFER_FUNCTION_PQ) { 578fcd2f4bfSAmy Zhang /* for PQ, we want to have a straight line from last HW X point, 579fcd2f4bfSAmy Zhang * and the slope to be such that we hit 1.0 at 10000 nits. 580fcd2f4bfSAmy Zhang */ 581fcd2f4bfSAmy Zhang const struct fixed31_32 end_value = 582fcd2f4bfSAmy Zhang dal_fixed31_32_from_int(125); 583fcd2f4bfSAmy Zhang 584fcd2f4bfSAmy Zhang arr_points[1].slope = dal_fixed31_32_div( 585fcd2f4bfSAmy Zhang dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), 586fcd2f4bfSAmy Zhang dal_fixed31_32_sub(end_value, arr_points[1].x)); 587fcd2f4bfSAmy Zhang arr_points[2].slope = dal_fixed31_32_div( 588fcd2f4bfSAmy Zhang dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), 589fcd2f4bfSAmy Zhang dal_fixed31_32_sub(end_value, arr_points[1].x)); 590fcd2f4bfSAmy Zhang } 591fcd2f4bfSAmy Zhang 592fcd2f4bfSAmy Zhang regamma_params->hw_points_num = hw_points; 593fcd2f4bfSAmy Zhang 594534db198SAmy Zhang i = 1; 595534db198SAmy Zhang for (k = 0; k < 16 && i < 16; k++) { 596534db198SAmy Zhang if (seg_distr[k] != -1) { 597534db198SAmy Zhang regamma_params->arr_curve_points[k].segments_num = 598534db198SAmy Zhang seg_distr[k]; 599534db198SAmy Zhang regamma_params->arr_curve_points[i].offset = 600534db198SAmy Zhang regamma_params->arr_curve_points[k]. 601534db198SAmy Zhang offset + (1 << seg_distr[k]); 602fcd2f4bfSAmy Zhang } 603534db198SAmy Zhang i++; 604534db198SAmy Zhang } 605534db198SAmy Zhang 606534db198SAmy Zhang if (seg_distr[k] != -1) 607534db198SAmy Zhang regamma_params->arr_curve_points[k].segments_num = 608534db198SAmy Zhang seg_distr[k]; 609fcd2f4bfSAmy Zhang 61023ae4f8eSAmy Zhang rgb = rgb_resulted; 61123ae4f8eSAmy Zhang rgb_plus_1 = rgb_resulted + 1; 612fcd2f4bfSAmy Zhang 613fcd2f4bfSAmy Zhang i = 1; 614fcd2f4bfSAmy Zhang 615fcd2f4bfSAmy Zhang while (i != hw_points + 1) { 616fcd2f4bfSAmy Zhang if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red)) 617fcd2f4bfSAmy Zhang rgb_plus_1->red = rgb->red; 618fcd2f4bfSAmy Zhang if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green)) 619fcd2f4bfSAmy Zhang rgb_plus_1->green = rgb->green; 620fcd2f4bfSAmy Zhang if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue)) 621fcd2f4bfSAmy Zhang rgb_plus_1->blue = rgb->blue; 622fcd2f4bfSAmy Zhang 623fcd2f4bfSAmy Zhang rgb->delta_red = dal_fixed31_32_sub( 624fcd2f4bfSAmy Zhang rgb_plus_1->red, 625fcd2f4bfSAmy Zhang rgb->red); 626fcd2f4bfSAmy Zhang rgb->delta_green = dal_fixed31_32_sub( 627fcd2f4bfSAmy Zhang rgb_plus_1->green, 628fcd2f4bfSAmy Zhang rgb->green); 629fcd2f4bfSAmy Zhang rgb->delta_blue = dal_fixed31_32_sub( 630fcd2f4bfSAmy Zhang rgb_plus_1->blue, 631fcd2f4bfSAmy Zhang rgb->blue); 632fcd2f4bfSAmy Zhang 633fcd2f4bfSAmy Zhang ++rgb_plus_1; 634fcd2f4bfSAmy Zhang ++rgb; 635fcd2f4bfSAmy Zhang ++i; 636fcd2f4bfSAmy Zhang } 637fcd2f4bfSAmy Zhang 638fcd2f4bfSAmy Zhang convert_to_custom_float(rgb_resulted, arr_points, hw_points); 639fcd2f4bfSAmy Zhang 640fcd2f4bfSAmy Zhang return true; 641fcd2f4bfSAmy Zhang } 642fcd2f4bfSAmy Zhang 64390e508baSAnthony Koo static bool dce110_set_output_transfer_func( 64490e508baSAnthony Koo struct pipe_ctx *pipe_ctx, 6450971c40eSHarry Wentland const struct dc_stream_state *stream) 64690e508baSAnthony Koo { 64786a66c4eSHarry Wentland struct transform *xfm = pipe_ctx->plane_res.xfm; 6484562236bSHarry Wentland 6497a09f5beSYue Hin Lau xfm->funcs->opp_power_on_regamma_lut(xfm, true); 6507a09f5beSYue Hin Lau xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; 6514562236bSHarry Wentland 6524fa086b9SLeo (Sunpeng) Li if (stream->out_transfer_func && 6534fa086b9SLeo (Sunpeng) Li stream->out_transfer_func->type == 654fcd2f4bfSAmy Zhang TF_TYPE_PREDEFINED && 6554fa086b9SLeo (Sunpeng) Li stream->out_transfer_func->tf == 656fcd2f4bfSAmy Zhang TRANSFER_FUNCTION_SRGB) { 6577a09f5beSYue Hin Lau xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB); 658fcd2f4bfSAmy Zhang } else if (dce110_translate_regamma_to_hw_format( 6597a09f5beSYue Hin Lau stream->out_transfer_func, &xfm->regamma_params)) { 6607a09f5beSYue Hin Lau xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params); 6617a09f5beSYue Hin Lau xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER); 6624562236bSHarry Wentland } else { 6637a09f5beSYue Hin Lau xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_BYPASS); 6644562236bSHarry Wentland } 6654562236bSHarry Wentland 6667a09f5beSYue Hin Lau xfm->funcs->opp_power_on_regamma_lut(xfm, false); 6674562236bSHarry Wentland 668cc0cb445SLeon Elazar return true; 6694562236bSHarry Wentland } 6704562236bSHarry Wentland 6714562236bSHarry Wentland static enum dc_status bios_parser_crtc_source_select( 6724562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 6734562236bSHarry Wentland { 6744562236bSHarry Wentland struct dc_bios *dcb; 6754562236bSHarry Wentland /* call VBIOS table to set CRTC source for the HW 6764562236bSHarry Wentland * encoder block 6774562236bSHarry Wentland * note: video bios clears all FMT setting here. */ 6784562236bSHarry Wentland struct bp_crtc_source_select crtc_source_select = {0}; 679b73a22d3SHarry Wentland const struct dc_sink *sink = pipe_ctx->stream->sink; 6804562236bSHarry Wentland 6818e9c4c8cSHarry Wentland crtc_source_select.engine_id = pipe_ctx->stream_res.stream_enc->id; 6824562236bSHarry Wentland crtc_source_select.controller_id = pipe_ctx->pipe_idx + 1; 6834562236bSHarry Wentland /*TODO: Need to un-hardcode color depth, dp_audio and account for 6844562236bSHarry Wentland * the case where signal and sink signal is different (translator 6854562236bSHarry Wentland * encoder)*/ 6864562236bSHarry Wentland crtc_source_select.signal = pipe_ctx->stream->signal; 6874562236bSHarry Wentland crtc_source_select.enable_dp_audio = false; 6884562236bSHarry Wentland crtc_source_select.sink_signal = pipe_ctx->stream->signal; 6891b7441b0SCharlene Liu 6901b7441b0SCharlene Liu switch (pipe_ctx->stream->timing.display_color_depth) { 6911b7441b0SCharlene Liu case COLOR_DEPTH_666: 6921b7441b0SCharlene Liu crtc_source_select.display_output_bit_depth = PANEL_6BIT_COLOR; 6931b7441b0SCharlene Liu break; 6941b7441b0SCharlene Liu case COLOR_DEPTH_888: 6954562236bSHarry Wentland crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR; 6961b7441b0SCharlene Liu break; 6971b7441b0SCharlene Liu case COLOR_DEPTH_101010: 6981b7441b0SCharlene Liu crtc_source_select.display_output_bit_depth = PANEL_10BIT_COLOR; 6991b7441b0SCharlene Liu break; 7001b7441b0SCharlene Liu case COLOR_DEPTH_121212: 7011b7441b0SCharlene Liu crtc_source_select.display_output_bit_depth = PANEL_12BIT_COLOR; 7021b7441b0SCharlene Liu break; 7031b7441b0SCharlene Liu default: 7041b7441b0SCharlene Liu BREAK_TO_DEBUGGER(); 7051b7441b0SCharlene Liu crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR; 7061b7441b0SCharlene Liu break; 7071b7441b0SCharlene Liu } 7084562236bSHarry Wentland 7094562236bSHarry Wentland dcb = sink->ctx->dc_bios; 7104562236bSHarry Wentland 7114562236bSHarry Wentland if (BP_RESULT_OK != dcb->funcs->crtc_source_select( 7124562236bSHarry Wentland dcb, 7134562236bSHarry Wentland &crtc_source_select)) { 7144562236bSHarry Wentland return DC_ERROR_UNEXPECTED; 7154562236bSHarry Wentland } 7164562236bSHarry Wentland 7174562236bSHarry Wentland return DC_OK; 7184562236bSHarry Wentland } 7194562236bSHarry Wentland 7204562236bSHarry Wentland void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) 7214562236bSHarry Wentland { 72286e2e1beSHersen Wu ASSERT(pipe_ctx->stream); 72386e2e1beSHersen Wu 7248e9c4c8cSHarry Wentland if (pipe_ctx->stream_res.stream_enc == NULL) 72586e2e1beSHersen Wu return; /* this is not root pipe */ 72686e2e1beSHersen Wu 7274562236bSHarry Wentland if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) 7288e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets( 7298e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc, 73096c50c0dSHarry Wentland &pipe_ctx->stream_res.encoder_info_frame); 7314562236bSHarry Wentland else if (dc_is_dp_signal(pipe_ctx->stream->signal)) 7328e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets( 7338e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc, 73496c50c0dSHarry Wentland &pipe_ctx->stream_res.encoder_info_frame); 7354562236bSHarry Wentland } 7364562236bSHarry Wentland 7374562236bSHarry Wentland void dce110_enable_stream(struct pipe_ctx *pipe_ctx) 7384562236bSHarry Wentland { 7394562236bSHarry Wentland enum dc_lane_count lane_count = 740d0778ebfSHarry Wentland pipe_ctx->stream->sink->link->cur_link_settings.lane_count; 7414562236bSHarry Wentland 7424fa086b9SLeo (Sunpeng) Li struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 743d0778ebfSHarry Wentland struct dc_link *link = pipe_ctx->stream->sink->link; 7444562236bSHarry Wentland 7454562236bSHarry Wentland /* 1. update AVI info frame (HDMI, DP) 7464562236bSHarry Wentland * we always need to update info frame 7474562236bSHarry Wentland */ 7484562236bSHarry Wentland uint32_t active_total_with_borders; 7494562236bSHarry Wentland uint32_t early_control = 0; 7506b670fa9SHarry Wentland struct timing_generator *tg = pipe_ctx->stream_res.tg; 7514562236bSHarry Wentland 7524562236bSHarry Wentland /* TODOFPGA may change to hwss.update_info_frame */ 7534562236bSHarry Wentland dce110_update_info_frame(pipe_ctx); 7544562236bSHarry Wentland /* enable early control to avoid corruption on DP monitor*/ 7554562236bSHarry Wentland active_total_with_borders = 7564562236bSHarry Wentland timing->h_addressable 7574562236bSHarry Wentland + timing->h_border_left 7584562236bSHarry Wentland + timing->h_border_right; 7594562236bSHarry Wentland 7604562236bSHarry Wentland if (lane_count != 0) 7614562236bSHarry Wentland early_control = active_total_with_borders % lane_count; 7624562236bSHarry Wentland 7634562236bSHarry Wentland if (early_control == 0) 7644562236bSHarry Wentland early_control = lane_count; 7654562236bSHarry Wentland 7664562236bSHarry Wentland tg->funcs->set_early_control(tg, early_control); 7674562236bSHarry Wentland 7684562236bSHarry Wentland /* enable audio only within mode set */ 769afaacef4SHarry Wentland if (pipe_ctx->stream_res.audio != NULL) { 7704562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal)) 7718e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc); 7724562236bSHarry Wentland } 7734562236bSHarry Wentland 7744562236bSHarry Wentland /* For MST, there are multiply stream go to only one link. 7754562236bSHarry Wentland * connect DIG back_end to front_end while enable_stream and 7764562236bSHarry Wentland * disconnect them during disable_stream 7774562236bSHarry Wentland * BY this, it is logic clean to separate stream and link */ 7784562236bSHarry Wentland link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, 7798e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->id, true); 7804562236bSHarry Wentland 7814562236bSHarry Wentland } 7824562236bSHarry Wentland 7835eefbc40SYue Hin Lau /*todo: cloned in stream enc, fix*/ 7845eefbc40SYue Hin Lau static bool is_panel_backlight_on(struct dce_hwseq *hws) 7855eefbc40SYue Hin Lau { 7865eefbc40SYue Hin Lau uint32_t value; 7875eefbc40SYue Hin Lau 7885eefbc40SYue Hin Lau REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value); 7895eefbc40SYue Hin Lau 7905eefbc40SYue Hin Lau return value; 7915eefbc40SYue Hin Lau } 7925eefbc40SYue Hin Lau 79387401969SAndrew Jiang static bool is_panel_powered_on(struct dce_hwseq *hws) 79487401969SAndrew Jiang { 79587401969SAndrew Jiang uint32_t value; 79687401969SAndrew Jiang 79787401969SAndrew Jiang REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &value); 79887401969SAndrew Jiang return value == 1; 79987401969SAndrew Jiang } 80087401969SAndrew Jiang 8015eefbc40SYue Hin Lau static enum bp_result link_transmitter_control( 80287401969SAndrew Jiang struct dc_bios *bios, 8035eefbc40SYue Hin Lau struct bp_transmitter_control *cntl) 8045eefbc40SYue Hin Lau { 8055eefbc40SYue Hin Lau enum bp_result result; 8065eefbc40SYue Hin Lau 80787401969SAndrew Jiang result = bios->funcs->transmitter_control(bios, cntl); 8085eefbc40SYue Hin Lau 8095eefbc40SYue Hin Lau return result; 8105eefbc40SYue Hin Lau } 8115eefbc40SYue Hin Lau 81287401969SAndrew Jiang /* 81387401969SAndrew Jiang * @brief 81487401969SAndrew Jiang * eDP only. 81587401969SAndrew Jiang */ 81687401969SAndrew Jiang void hwss_edp_wait_for_hpd_ready( 817069d418fSAndrew Jiang struct dc_link *link, 81887401969SAndrew Jiang bool power_up) 81987401969SAndrew Jiang { 820069d418fSAndrew Jiang struct dc_context *ctx = link->ctx; 821069d418fSAndrew Jiang struct graphics_object_id connector = link->link_enc->connector; 82287401969SAndrew Jiang struct gpio *hpd; 82387401969SAndrew Jiang bool edp_hpd_high = false; 82487401969SAndrew Jiang uint32_t time_elapsed = 0; 82587401969SAndrew Jiang uint32_t timeout = power_up ? 82687401969SAndrew Jiang PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT; 82787401969SAndrew Jiang 82887401969SAndrew Jiang if (dal_graphics_object_id_get_connector_id(connector) 82987401969SAndrew Jiang != CONNECTOR_ID_EDP) { 83087401969SAndrew Jiang BREAK_TO_DEBUGGER(); 83187401969SAndrew Jiang return; 83287401969SAndrew Jiang } 83387401969SAndrew Jiang 83487401969SAndrew Jiang if (!power_up) 83587401969SAndrew Jiang /* 83687401969SAndrew Jiang * From KV, we will not HPD low after turning off VCC - 83787401969SAndrew Jiang * instead, we will check the SW timer in power_up(). 83887401969SAndrew Jiang */ 83987401969SAndrew Jiang return; 84087401969SAndrew Jiang 84187401969SAndrew Jiang /* 84287401969SAndrew Jiang * When we power on/off the eDP panel, 84387401969SAndrew Jiang * we need to wait until SENSE bit is high/low. 84487401969SAndrew Jiang */ 84587401969SAndrew Jiang 84687401969SAndrew Jiang /* obtain HPD */ 84787401969SAndrew Jiang /* TODO what to do with this? */ 84887401969SAndrew Jiang hpd = get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service); 84987401969SAndrew Jiang 85087401969SAndrew Jiang if (!hpd) { 85187401969SAndrew Jiang BREAK_TO_DEBUGGER(); 85287401969SAndrew Jiang return; 85387401969SAndrew Jiang } 85487401969SAndrew Jiang 85587401969SAndrew Jiang dal_gpio_open(hpd, GPIO_MODE_INTERRUPT); 85687401969SAndrew Jiang 85787401969SAndrew Jiang /* wait until timeout or panel detected */ 85887401969SAndrew Jiang 85987401969SAndrew Jiang do { 86087401969SAndrew Jiang uint32_t detected = 0; 86187401969SAndrew Jiang 86287401969SAndrew Jiang dal_gpio_get_value(hpd, &detected); 86387401969SAndrew Jiang 86487401969SAndrew Jiang if (!(detected ^ power_up)) { 86587401969SAndrew Jiang edp_hpd_high = true; 86687401969SAndrew Jiang break; 86787401969SAndrew Jiang } 86887401969SAndrew Jiang 86987401969SAndrew Jiang msleep(HPD_CHECK_INTERVAL); 87087401969SAndrew Jiang 87187401969SAndrew Jiang time_elapsed += HPD_CHECK_INTERVAL; 87287401969SAndrew Jiang } while (time_elapsed < timeout); 87387401969SAndrew Jiang 87487401969SAndrew Jiang dal_gpio_close(hpd); 87587401969SAndrew Jiang 87687401969SAndrew Jiang dal_gpio_destroy_irq(&hpd); 87787401969SAndrew Jiang 87887401969SAndrew Jiang if (false == edp_hpd_high) { 87987401969SAndrew Jiang dm_logger_write(ctx->logger, LOG_ERROR, 88087401969SAndrew Jiang "%s: wait timed out!\n", __func__); 88187401969SAndrew Jiang } 88287401969SAndrew Jiang } 88387401969SAndrew Jiang 88487401969SAndrew Jiang void hwss_edp_power_control( 885069d418fSAndrew Jiang struct dc_link *link, 88687401969SAndrew Jiang bool power_up) 88787401969SAndrew Jiang { 888069d418fSAndrew Jiang struct dc_context *ctx = link->ctx; 88987401969SAndrew Jiang struct dce_hwseq *hwseq = ctx->dc->hwseq; 89087401969SAndrew Jiang struct bp_transmitter_control cntl = { 0 }; 89187401969SAndrew Jiang enum bp_result bp_result; 89287401969SAndrew Jiang 89387401969SAndrew Jiang 894069d418fSAndrew Jiang if (dal_graphics_object_id_get_connector_id(link->link_enc->connector) 89587401969SAndrew Jiang != CONNECTOR_ID_EDP) { 89687401969SAndrew Jiang BREAK_TO_DEBUGGER(); 89787401969SAndrew Jiang return; 89887401969SAndrew Jiang } 89987401969SAndrew Jiang 90087401969SAndrew Jiang if (power_up != is_panel_powered_on(hwseq)) { 90187401969SAndrew Jiang /* Send VBIOS command to prompt eDP panel power */ 90287401969SAndrew Jiang 90387401969SAndrew Jiang dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, 90487401969SAndrew Jiang "%s: Panel Power action: %s\n", 90587401969SAndrew Jiang __func__, (power_up ? "On":"Off")); 90687401969SAndrew Jiang 90787401969SAndrew Jiang cntl.action = power_up ? 90887401969SAndrew Jiang TRANSMITTER_CONTROL_POWER_ON : 90987401969SAndrew Jiang TRANSMITTER_CONTROL_POWER_OFF; 910069d418fSAndrew Jiang cntl.transmitter = link->link_enc->transmitter; 911069d418fSAndrew Jiang cntl.connector_obj_id = link->link_enc->connector; 91287401969SAndrew Jiang cntl.coherent = false; 91387401969SAndrew Jiang cntl.lanes_number = LANE_COUNT_FOUR; 914069d418fSAndrew Jiang cntl.hpd_sel = link->link_enc->hpd_source; 91587401969SAndrew Jiang 91687401969SAndrew Jiang bp_result = link_transmitter_control(ctx->dc_bios, &cntl); 91787401969SAndrew Jiang 91887401969SAndrew Jiang if (bp_result != BP_RESULT_OK) 91987401969SAndrew Jiang dm_logger_write(ctx->logger, LOG_ERROR, 92087401969SAndrew Jiang "%s: Panel Power bp_result: %d\n", 92187401969SAndrew Jiang __func__, bp_result); 92287401969SAndrew Jiang } else { 92387401969SAndrew Jiang dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, 92487401969SAndrew Jiang "%s: Skipping Panel Power action: %s\n", 92587401969SAndrew Jiang __func__, (power_up ? "On":"Off")); 92687401969SAndrew Jiang } 92787401969SAndrew Jiang 928069d418fSAndrew Jiang hwss_edp_wait_for_hpd_ready(link, true); 92987401969SAndrew Jiang } 9305eefbc40SYue Hin Lau 9315eefbc40SYue Hin Lau /*todo: cloned in stream enc, fix*/ 9325eefbc40SYue Hin Lau /* 9335eefbc40SYue Hin Lau * @brief 9345eefbc40SYue Hin Lau * eDP only. Control the backlight of the eDP panel 9355eefbc40SYue Hin Lau */ 93687401969SAndrew Jiang void hwss_edp_backlight_control( 9375eefbc40SYue Hin Lau struct dc_link *link, 9385eefbc40SYue Hin Lau bool enable) 9395eefbc40SYue Hin Lau { 940069d418fSAndrew Jiang struct dc_context *ctx = link->ctx; 941069d418fSAndrew Jiang struct dce_hwseq *hws = ctx->dc->hwseq; 9425eefbc40SYue Hin Lau struct bp_transmitter_control cntl = { 0 }; 9435eefbc40SYue Hin Lau 944069d418fSAndrew Jiang if (dal_graphics_object_id_get_connector_id(link->link_enc->connector) 9455eefbc40SYue Hin Lau != CONNECTOR_ID_EDP) { 9465eefbc40SYue Hin Lau BREAK_TO_DEBUGGER(); 9475eefbc40SYue Hin Lau return; 9485eefbc40SYue Hin Lau } 9495eefbc40SYue Hin Lau 9505eefbc40SYue Hin Lau if (enable && is_panel_backlight_on(hws)) { 9515eefbc40SYue Hin Lau dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, 9525eefbc40SYue Hin Lau "%s: panel already powered up. Do nothing.\n", 9535eefbc40SYue Hin Lau __func__); 9545eefbc40SYue Hin Lau return; 9555eefbc40SYue Hin Lau } 9565eefbc40SYue Hin Lau 9575eefbc40SYue Hin Lau /* Send VBIOS command to control eDP panel backlight */ 9585eefbc40SYue Hin Lau 9595eefbc40SYue Hin Lau dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, 9605eefbc40SYue Hin Lau "%s: backlight action: %s\n", 9615eefbc40SYue Hin Lau __func__, (enable ? "On":"Off")); 9625eefbc40SYue Hin Lau 9635eefbc40SYue Hin Lau cntl.action = enable ? 9645eefbc40SYue Hin Lau TRANSMITTER_CONTROL_BACKLIGHT_ON : 9655eefbc40SYue Hin Lau TRANSMITTER_CONTROL_BACKLIGHT_OFF; 96687401969SAndrew Jiang 9675eefbc40SYue Hin Lau /*cntl.engine_id = ctx->engine;*/ 9685eefbc40SYue Hin Lau cntl.transmitter = link->link_enc->transmitter; 9695eefbc40SYue Hin Lau cntl.connector_obj_id = link->link_enc->connector; 9705eefbc40SYue Hin Lau /*todo: unhardcode*/ 9715eefbc40SYue Hin Lau cntl.lanes_number = LANE_COUNT_FOUR; 9725eefbc40SYue Hin Lau cntl.hpd_sel = link->link_enc->hpd_source; 9735eefbc40SYue Hin Lau 9745eefbc40SYue Hin Lau /* For eDP, the following delays might need to be considered 9755eefbc40SYue Hin Lau * after link training completed: 9765eefbc40SYue Hin Lau * idle period - min. accounts for required BS-Idle pattern, 9775eefbc40SYue Hin Lau * max. allows for source frame synchronization); 9785eefbc40SYue Hin Lau * 50 msec max. delay from valid video data from source 9795eefbc40SYue Hin Lau * to video on dislpay or backlight enable. 9805eefbc40SYue Hin Lau * 9815eefbc40SYue Hin Lau * Disable the delay for now. 9825eefbc40SYue Hin Lau * Enable it in the future if necessary. 9835eefbc40SYue Hin Lau */ 9845eefbc40SYue Hin Lau /* dc_service_sleep_in_milliseconds(50); */ 985069d418fSAndrew Jiang link_transmitter_control(ctx->dc_bios, &cntl); 9865eefbc40SYue Hin Lau } 9875eefbc40SYue Hin Lau 9884176664bSCharlene Liu void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) 9894562236bSHarry Wentland { 9900971c40eSHarry Wentland struct dc_stream_state *stream = pipe_ctx->stream; 991d0778ebfSHarry Wentland struct dc_link *link = stream->sink->link; 9924176664bSCharlene Liu struct dc *dc = pipe_ctx->stream->ctx->dc; 9934562236bSHarry Wentland 9942b7c97d6SCharlene Liu if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) 9952b7c97d6SCharlene Liu pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets( 9962b7c97d6SCharlene Liu pipe_ctx->stream_res.stream_enc); 9972b7c97d6SCharlene Liu 9982b7c97d6SCharlene Liu if (dc_is_dp_signal(pipe_ctx->stream->signal)) 9992b7c97d6SCharlene Liu pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets( 10002b7c97d6SCharlene Liu pipe_ctx->stream_res.stream_enc); 10012b7c97d6SCharlene Liu 10022b7c97d6SCharlene Liu pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( 10032b7c97d6SCharlene Liu pipe_ctx->stream_res.stream_enc, true); 1004afaacef4SHarry Wentland if (pipe_ctx->stream_res.audio) { 1005afaacef4SHarry Wentland pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); 10064562236bSHarry Wentland 10074562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal)) 10088e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( 10098e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc); 10104562236bSHarry Wentland else 10118e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( 10128e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc); 10134176664bSCharlene Liu /*don't free audio if it is from retrain or internal disable stream*/ 10144176664bSCharlene Liu if (option == FREE_ACQUIRED_RESOURCE && dc->caps.dynamic_audio == true) { 10154176664bSCharlene Liu /*we have to dynamic arbitrate the audio endpoints*/ 10164176664bSCharlene Liu pipe_ctx->stream_res.audio = NULL; 10174176664bSCharlene Liu /*we free the resource, need reset is_audio_acquired*/ 10184176664bSCharlene Liu update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false); 10194176664bSCharlene Liu } 10204562236bSHarry Wentland 10214562236bSHarry Wentland /* TODO: notify audio driver for if audio modes list changed 10224562236bSHarry Wentland * add audio mode list change flag */ 10234562236bSHarry Wentland /* dal_audio_disable_azalia_audio_jack_presence(stream->audio, 10244562236bSHarry Wentland * stream->stream_engine_id); 10254562236bSHarry Wentland */ 10264562236bSHarry Wentland } 10274562236bSHarry Wentland 10284562236bSHarry Wentland /* blank at encoder level */ 10291e4cee77SCharlene Liu if (dc_is_dp_signal(pipe_ctx->stream->signal)) { 10301e4cee77SCharlene Liu if (pipe_ctx->stream->sink->link->connector_signal == SIGNAL_TYPE_EDP) 103187401969SAndrew Jiang hwss_edp_backlight_control(link, false); 10328e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); 10331e4cee77SCharlene Liu } 10344562236bSHarry Wentland link->link_enc->funcs->connect_dig_be_to_fe( 10354562236bSHarry Wentland link->link_enc, 10368e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->id, 10374562236bSHarry Wentland false); 10384562236bSHarry Wentland 10394562236bSHarry Wentland } 10404562236bSHarry Wentland 10414562236bSHarry Wentland void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, 10424562236bSHarry Wentland struct dc_link_settings *link_settings) 10434562236bSHarry Wentland { 10444562236bSHarry Wentland struct encoder_unblank_param params = { { 0 } }; 10451e4cee77SCharlene Liu struct dc_link *link = pipe_ctx->stream->sink->link; 10464562236bSHarry Wentland 10474562236bSHarry Wentland /* only 3 items below are used by unblank */ 10486235b23cSTony Cheng params.pixel_clk_khz = 10494fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->timing.pix_clk_khz; 10504562236bSHarry Wentland params.link_settings.link_rate = link_settings->link_rate; 10518e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms); 10521e4cee77SCharlene Liu if (link->connector_signal == SIGNAL_TYPE_EDP) 105387401969SAndrew Jiang hwss_edp_backlight_control(link, true); 10544562236bSHarry Wentland } 10554562236bSHarry Wentland 105615e17335SCharlene Liu 105715e17335SCharlene Liu void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) 105815e17335SCharlene Liu { 10598e9c4c8cSHarry Wentland if (pipe_ctx != NULL && pipe_ctx->stream_res.stream_enc != NULL) 10608e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->set_avmute(pipe_ctx->stream_res.stream_enc, enable); 106115e17335SCharlene Liu } 106215e17335SCharlene Liu 10634562236bSHarry Wentland static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id) 10644562236bSHarry Wentland { 10654562236bSHarry Wentland switch (crtc_id) { 10664562236bSHarry Wentland case CONTROLLER_ID_D0: 10674562236bSHarry Wentland return DTO_SOURCE_ID0; 10684562236bSHarry Wentland case CONTROLLER_ID_D1: 10694562236bSHarry Wentland return DTO_SOURCE_ID1; 10704562236bSHarry Wentland case CONTROLLER_ID_D2: 10714562236bSHarry Wentland return DTO_SOURCE_ID2; 10724562236bSHarry Wentland case CONTROLLER_ID_D3: 10734562236bSHarry Wentland return DTO_SOURCE_ID3; 10744562236bSHarry Wentland case CONTROLLER_ID_D4: 10754562236bSHarry Wentland return DTO_SOURCE_ID4; 10764562236bSHarry Wentland case CONTROLLER_ID_D5: 10774562236bSHarry Wentland return DTO_SOURCE_ID5; 10784562236bSHarry Wentland default: 10794562236bSHarry Wentland return DTO_SOURCE_UNKNOWN; 10804562236bSHarry Wentland } 10814562236bSHarry Wentland } 10824562236bSHarry Wentland 10834562236bSHarry Wentland static void build_audio_output( 1084ab8db3e1SAndrey Grodzovsky struct dc_state *state, 10854562236bSHarry Wentland const struct pipe_ctx *pipe_ctx, 10864562236bSHarry Wentland struct audio_output *audio_output) 10874562236bSHarry Wentland { 10880971c40eSHarry Wentland const struct dc_stream_state *stream = pipe_ctx->stream; 10898e9c4c8cSHarry Wentland audio_output->engine_id = pipe_ctx->stream_res.stream_enc->id; 10904562236bSHarry Wentland 10914562236bSHarry Wentland audio_output->signal = pipe_ctx->stream->signal; 10924562236bSHarry Wentland 10934562236bSHarry Wentland /* audio_crtc_info */ 10944562236bSHarry Wentland 10954562236bSHarry Wentland audio_output->crtc_info.h_total = 10964fa086b9SLeo (Sunpeng) Li stream->timing.h_total; 10974562236bSHarry Wentland 10984562236bSHarry Wentland /* 10994562236bSHarry Wentland * Audio packets are sent during actual CRTC blank physical signal, we 11004562236bSHarry Wentland * need to specify actual active signal portion 11014562236bSHarry Wentland */ 11024562236bSHarry Wentland audio_output->crtc_info.h_active = 11034fa086b9SLeo (Sunpeng) Li stream->timing.h_addressable 11044fa086b9SLeo (Sunpeng) Li + stream->timing.h_border_left 11054fa086b9SLeo (Sunpeng) Li + stream->timing.h_border_right; 11064562236bSHarry Wentland 11074562236bSHarry Wentland audio_output->crtc_info.v_active = 11084fa086b9SLeo (Sunpeng) Li stream->timing.v_addressable 11094fa086b9SLeo (Sunpeng) Li + stream->timing.v_border_top 11104fa086b9SLeo (Sunpeng) Li + stream->timing.v_border_bottom; 11114562236bSHarry Wentland 11124562236bSHarry Wentland audio_output->crtc_info.pixel_repetition = 1; 11134562236bSHarry Wentland 11144562236bSHarry Wentland audio_output->crtc_info.interlaced = 11154fa086b9SLeo (Sunpeng) Li stream->timing.flags.INTERLACE; 11164562236bSHarry Wentland 11174562236bSHarry Wentland audio_output->crtc_info.refresh_rate = 11184fa086b9SLeo (Sunpeng) Li (stream->timing.pix_clk_khz*1000)/ 11194fa086b9SLeo (Sunpeng) Li (stream->timing.h_total*stream->timing.v_total); 11204562236bSHarry Wentland 11214562236bSHarry Wentland audio_output->crtc_info.color_depth = 11224fa086b9SLeo (Sunpeng) Li stream->timing.display_color_depth; 11234562236bSHarry Wentland 11244562236bSHarry Wentland audio_output->crtc_info.requested_pixel_clock = 112510688217SHarry Wentland pipe_ctx->stream_res.pix_clk_params.requested_pix_clk; 11264562236bSHarry Wentland 11274562236bSHarry Wentland audio_output->crtc_info.calculated_pixel_clock = 112810688217SHarry Wentland pipe_ctx->stream_res.pix_clk_params.requested_pix_clk; 11294562236bSHarry Wentland 113087b58768SCharlene Liu /*for HDMI, audio ACR is with deep color ratio factor*/ 113187b58768SCharlene Liu if (dc_is_hdmi_signal(pipe_ctx->stream->signal) && 113287b58768SCharlene Liu audio_output->crtc_info.requested_pixel_clock == 11334fa086b9SLeo (Sunpeng) Li stream->timing.pix_clk_khz) { 113410688217SHarry Wentland if (pipe_ctx->stream_res.pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) { 113587b58768SCharlene Liu audio_output->crtc_info.requested_pixel_clock = 113687b58768SCharlene Liu audio_output->crtc_info.requested_pixel_clock/2; 113787b58768SCharlene Liu audio_output->crtc_info.calculated_pixel_clock = 113810688217SHarry Wentland pipe_ctx->stream_res.pix_clk_params.requested_pix_clk/2; 113987b58768SCharlene Liu 114087b58768SCharlene Liu } 114187b58768SCharlene Liu } 114287b58768SCharlene Liu 11434562236bSHarry Wentland if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT || 11444562236bSHarry Wentland pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { 11454562236bSHarry Wentland audio_output->pll_info.dp_dto_source_clock_in_khz = 1146ab8db3e1SAndrey Grodzovsky state->dis_clk->funcs->get_dp_ref_clk_frequency( 1147ab8db3e1SAndrey Grodzovsky state->dis_clk); 11484562236bSHarry Wentland } 11494562236bSHarry Wentland 11504562236bSHarry Wentland audio_output->pll_info.feed_back_divider = 11514562236bSHarry Wentland pipe_ctx->pll_settings.feedback_divider; 11524562236bSHarry Wentland 11534562236bSHarry Wentland audio_output->pll_info.dto_source = 11544562236bSHarry Wentland translate_to_dto_source( 11554562236bSHarry Wentland pipe_ctx->pipe_idx + 1); 11564562236bSHarry Wentland 11574562236bSHarry Wentland /* TODO hard code to enable for now. Need get from stream */ 11584562236bSHarry Wentland audio_output->pll_info.ss_enabled = true; 11594562236bSHarry Wentland 11604562236bSHarry Wentland audio_output->pll_info.ss_percentage = 11614562236bSHarry Wentland pipe_ctx->pll_settings.ss_percentage; 11624562236bSHarry Wentland } 11634562236bSHarry Wentland 11644562236bSHarry Wentland static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx, 11654562236bSHarry Wentland struct tg_color *color) 11664562236bSHarry Wentland { 11674562236bSHarry Wentland uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->pipe_idx) / 4; 11684562236bSHarry Wentland 11696702a9acSHarry Wentland switch (pipe_ctx->plane_res.scl_data.format) { 11704562236bSHarry Wentland case PIXEL_FORMAT_ARGB8888: 11714562236bSHarry Wentland /* set boarder color to red */ 11724562236bSHarry Wentland color->color_r_cr = color_value; 11734562236bSHarry Wentland break; 11744562236bSHarry Wentland 11754562236bSHarry Wentland case PIXEL_FORMAT_ARGB2101010: 11764562236bSHarry Wentland /* set boarder color to blue */ 11774562236bSHarry Wentland color->color_b_cb = color_value; 11784562236bSHarry Wentland break; 117987449a90SAnthony Koo case PIXEL_FORMAT_420BPP8: 11804562236bSHarry Wentland /* set boarder color to green */ 11814562236bSHarry Wentland color->color_g_y = color_value; 11824562236bSHarry Wentland break; 118387449a90SAnthony Koo case PIXEL_FORMAT_420BPP10: 118487449a90SAnthony Koo /* set boarder color to yellow */ 118587449a90SAnthony Koo color->color_g_y = color_value; 118687449a90SAnthony Koo color->color_r_cr = color_value; 118787449a90SAnthony Koo break; 11884562236bSHarry Wentland case PIXEL_FORMAT_FP16: 11894562236bSHarry Wentland /* set boarder color to white */ 11904562236bSHarry Wentland color->color_r_cr = color_value; 11914562236bSHarry Wentland color->color_b_cb = color_value; 11924562236bSHarry Wentland color->color_g_y = color_value; 11934562236bSHarry Wentland break; 11944562236bSHarry Wentland default: 11954562236bSHarry Wentland break; 11964562236bSHarry Wentland } 11974562236bSHarry Wentland } 11984562236bSHarry Wentland 1199fb3466a4SBhawanpreet Lakha static void program_scaler(const struct dc *dc, 12004562236bSHarry Wentland const struct pipe_ctx *pipe_ctx) 12014562236bSHarry Wentland { 12024562236bSHarry Wentland struct tg_color color = {0}; 12034562236bSHarry Wentland 1204ff5ef992SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 1205ff5ef992SAlex Deucher /* TOFPGA */ 120686a66c4eSHarry Wentland if (pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth == NULL) 1207ff5ef992SAlex Deucher return; 1208ff5ef992SAlex Deucher #endif 1209ff5ef992SAlex Deucher 1210fb3466a4SBhawanpreet Lakha if (dc->debug.surface_visual_confirm) 12114562236bSHarry Wentland get_surface_visual_confirm_color(pipe_ctx, &color); 12124562236bSHarry Wentland else 12134562236bSHarry Wentland color_space_to_black_color(dc, 12144fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->output_color_space, 12154562236bSHarry Wentland &color); 12164562236bSHarry Wentland 121786a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth( 121886a66c4eSHarry Wentland pipe_ctx->plane_res.xfm, 12196702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.depth, 12204562236bSHarry Wentland &pipe_ctx->stream->bit_depth_params); 12214562236bSHarry Wentland 12226b670fa9SHarry Wentland if (pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color) 12236b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color( 12246b670fa9SHarry Wentland pipe_ctx->stream_res.tg, 12254562236bSHarry Wentland &color); 12264562236bSHarry Wentland 122786a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm, 12286702a9acSHarry Wentland &pipe_ctx->plane_res.scl_data); 12294562236bSHarry Wentland } 12304562236bSHarry Wentland 12314b5e7d62SHersen Wu static enum dc_status dce110_prog_pixclk_crtc_otg( 12324562236bSHarry Wentland struct pipe_ctx *pipe_ctx, 1233608ac7bbSJerry Zuo struct dc_state *context, 1234fb3466a4SBhawanpreet Lakha struct dc *dc) 12354562236bSHarry Wentland { 12360971c40eSHarry Wentland struct dc_stream_state *stream = pipe_ctx->stream; 1237608ac7bbSJerry Zuo struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx. 12384562236bSHarry Wentland pipe_ctx[pipe_ctx->pipe_idx]; 12394562236bSHarry Wentland struct tg_color black_color = {0}; 12404562236bSHarry Wentland 12414562236bSHarry Wentland if (!pipe_ctx_old->stream) { 12424562236bSHarry Wentland 12434562236bSHarry Wentland /* program blank color */ 12444562236bSHarry Wentland color_space_to_black_color(dc, 12454fa086b9SLeo (Sunpeng) Li stream->output_color_space, &black_color); 12466b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->set_blank_color( 12476b670fa9SHarry Wentland pipe_ctx->stream_res.tg, 12484562236bSHarry Wentland &black_color); 12494b5e7d62SHersen Wu 12504562236bSHarry Wentland /* 12514562236bSHarry Wentland * Must blank CRTC after disabling power gating and before any 12524562236bSHarry Wentland * programming, otherwise CRTC will be hung in bad state 12534562236bSHarry Wentland */ 12546b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true); 12554562236bSHarry Wentland 12564562236bSHarry Wentland if (false == pipe_ctx->clock_source->funcs->program_pix_clk( 12574562236bSHarry Wentland pipe_ctx->clock_source, 125810688217SHarry Wentland &pipe_ctx->stream_res.pix_clk_params, 12594562236bSHarry Wentland &pipe_ctx->pll_settings)) { 12604562236bSHarry Wentland BREAK_TO_DEBUGGER(); 12614562236bSHarry Wentland return DC_ERROR_UNEXPECTED; 12624562236bSHarry Wentland } 12634562236bSHarry Wentland 12646b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->program_timing( 12656b670fa9SHarry Wentland pipe_ctx->stream_res.tg, 12664fa086b9SLeo (Sunpeng) Li &stream->timing, 12674562236bSHarry Wentland true); 126894267b3dSSylvia Tsai 12696b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->set_static_screen_control( 12706b670fa9SHarry Wentland pipe_ctx->stream_res.tg, 127194267b3dSSylvia Tsai 0x182); 12724562236bSHarry Wentland } 12734562236bSHarry Wentland 12744562236bSHarry Wentland if (!pipe_ctx_old->stream) { 12756b670fa9SHarry Wentland if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc( 12766b670fa9SHarry Wentland pipe_ctx->stream_res.tg)) { 12774562236bSHarry Wentland BREAK_TO_DEBUGGER(); 12784562236bSHarry Wentland return DC_ERROR_UNEXPECTED; 12794562236bSHarry Wentland } 12804562236bSHarry Wentland } 12814562236bSHarry Wentland 128294267b3dSSylvia Tsai 128394267b3dSSylvia Tsai 12844562236bSHarry Wentland return DC_OK; 12854562236bSHarry Wentland } 12864562236bSHarry Wentland 12874562236bSHarry Wentland static enum dc_status apply_single_controller_ctx_to_hw( 12884562236bSHarry Wentland struct pipe_ctx *pipe_ctx, 1289608ac7bbSJerry Zuo struct dc_state *context, 1290fb3466a4SBhawanpreet Lakha struct dc *dc) 12914562236bSHarry Wentland { 12920971c40eSHarry Wentland struct dc_stream_state *stream = pipe_ctx->stream; 1293608ac7bbSJerry Zuo struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx. 12944562236bSHarry Wentland pipe_ctx[pipe_ctx->pipe_idx]; 12954562236bSHarry Wentland 12964562236bSHarry Wentland /* */ 12974562236bSHarry Wentland dc->hwss.prog_pixclk_crtc_otg(pipe_ctx, context, dc); 12984562236bSHarry Wentland 1299f0c4d997SCorbin McElhanney /* FPGA does not program backend */ 1300f0c4d997SCorbin McElhanney if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { 1301a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion( 1302a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp, 13034562236bSHarry Wentland COLOR_SPACE_YCBCR601, 13044fa086b9SLeo (Sunpeng) Li stream->timing.display_color_depth, 13054562236bSHarry Wentland pipe_ctx->stream->signal); 13064562236bSHarry Wentland 1307a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp->funcs->opp_program_fmt( 1308a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp, 13094562236bSHarry Wentland &stream->bit_depth_params, 13104562236bSHarry Wentland &stream->clamping); 13114562236bSHarry Wentland return DC_OK; 1312181a888fSCharlene Liu } 13134562236bSHarry Wentland /* TODO: move to stream encoder */ 13144562236bSHarry Wentland if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) 13154562236bSHarry Wentland if (DC_OK != bios_parser_crtc_source_select(pipe_ctx)) { 13164562236bSHarry Wentland BREAK_TO_DEBUGGER(); 13174562236bSHarry Wentland return DC_ERROR_UNEXPECTED; 13184562236bSHarry Wentland } 1319f0c4d997SCorbin McElhanney pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion( 1320f0c4d997SCorbin McElhanney pipe_ctx->stream_res.opp, 1321f0c4d997SCorbin McElhanney COLOR_SPACE_YCBCR601, 1322f0c4d997SCorbin McElhanney stream->timing.display_color_depth, 1323f0c4d997SCorbin McElhanney pipe_ctx->stream->signal); 13244562236bSHarry Wentland 13254562236bSHarry Wentland if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) 13264562236bSHarry Wentland stream->sink->link->link_enc->funcs->setup( 13274562236bSHarry Wentland stream->sink->link->link_enc, 13284562236bSHarry Wentland pipe_ctx->stream->signal); 13294562236bSHarry Wentland 1330ab3c1798SVitaly Prosyak if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) 13318e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->setup_stereo_sync( 13328e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc, 13336b670fa9SHarry Wentland pipe_ctx->stream_res.tg->inst, 13344fa086b9SLeo (Sunpeng) Li stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE); 1335ab3c1798SVitaly Prosyak 1336ab3c1798SVitaly Prosyak 1337a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp->funcs->opp_program_fmt( 1338a6a6cb34SHarry Wentland pipe_ctx->stream_res.opp, 1339181a888fSCharlene Liu &stream->bit_depth_params, 1340181a888fSCharlene Liu &stream->clamping); 1341603767f9STony Cheng 13424562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal)) 13438e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute( 13448e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc, 13454fa086b9SLeo (Sunpeng) Li &stream->timing, 13464fa086b9SLeo (Sunpeng) Li stream->output_color_space); 13474562236bSHarry Wentland 13484562236bSHarry Wentland if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) 13498e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->hdmi_set_stream_attribute( 13508e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc, 13514fa086b9SLeo (Sunpeng) Li &stream->timing, 13524562236bSHarry Wentland stream->phy_pix_clk, 1353afaacef4SHarry Wentland pipe_ctx->stream_res.audio != NULL); 13544562236bSHarry Wentland 13554562236bSHarry Wentland if (dc_is_dvi_signal(pipe_ctx->stream->signal)) 13568e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->dvi_set_stream_attribute( 13578e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc, 13584fa086b9SLeo (Sunpeng) Li &stream->timing, 13594562236bSHarry Wentland (pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ? 13604562236bSHarry Wentland true : false); 13614562236bSHarry Wentland 136215e17335SCharlene Liu resource_build_info_frame(pipe_ctx); 13633639fa68SZeyu Fan dce110_update_info_frame(pipe_ctx); 13644562236bSHarry Wentland if (!pipe_ctx_old->stream) { 1365d050f8edSHersen Wu if (!pipe_ctx->stream->dpms_off) 1366ab8db3e1SAndrey Grodzovsky core_link_enable_stream(context, pipe_ctx); 13674562236bSHarry Wentland } 13684562236bSHarry Wentland 13696702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; 13704562236bSHarry Wentland 137194267b3dSSylvia Tsai pipe_ctx->stream->sink->link->psr_enabled = false; 137294267b3dSSylvia Tsai 13734562236bSHarry Wentland return DC_OK; 13744562236bSHarry Wentland } 13754562236bSHarry Wentland 13764562236bSHarry Wentland /******************************************************************************/ 13774562236bSHarry Wentland 1378fb3466a4SBhawanpreet Lakha static void power_down_encoders(struct dc *dc) 13794562236bSHarry Wentland { 13804562236bSHarry Wentland int i; 1381a0c38ebaSCharlene Liu enum connector_id connector_id; 138268d77dd8SAndrew Jiang enum signal_type signal = SIGNAL_TYPE_NONE; 1383b9b171ffSHersen Wu 1384b9b171ffSHersen Wu /* do not know BIOS back-front mapping, simply blank all. It will not 1385b9b171ffSHersen Wu * hurt for non-DP 1386b9b171ffSHersen Wu */ 1387b9b171ffSHersen Wu for (i = 0; i < dc->res_pool->stream_enc_count; i++) { 1388b9b171ffSHersen Wu dc->res_pool->stream_enc[i]->funcs->dp_blank( 1389b9b171ffSHersen Wu dc->res_pool->stream_enc[i]); 1390b9b171ffSHersen Wu } 1391b9b171ffSHersen Wu 13924562236bSHarry Wentland for (i = 0; i < dc->link_count; i++) { 1393a0c38ebaSCharlene Liu connector_id = dal_graphics_object_id_get_connector_id(dc->links[i]->link_id); 1394a0c38ebaSCharlene Liu if ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || 1395a0c38ebaSCharlene Liu (connector_id == CONNECTOR_ID_EDP)) { 1396a0c38ebaSCharlene Liu 1397a0c38ebaSCharlene Liu if (!dc->links[i]->wa_flags.dp_keep_receiver_powered) 1398a0c38ebaSCharlene Liu dp_receiver_power_ctrl(dc->links[i], false); 1399069d418fSAndrew Jiang if (connector_id == CONNECTOR_ID_EDP) { 140068d77dd8SAndrew Jiang signal = SIGNAL_TYPE_EDP; 1401069d418fSAndrew Jiang hwss_edp_backlight_control(dc->links[i], false); 1402069d418fSAndrew Jiang } 1403a0c38ebaSCharlene Liu } 1404a0c38ebaSCharlene Liu 14054562236bSHarry Wentland dc->links[i]->link_enc->funcs->disable_output( 1406069d418fSAndrew Jiang dc->links[i]->link_enc, signal); 14074562236bSHarry Wentland } 14084562236bSHarry Wentland } 14094562236bSHarry Wentland 1410fb3466a4SBhawanpreet Lakha static void power_down_controllers(struct dc *dc) 14114562236bSHarry Wentland { 14124562236bSHarry Wentland int i; 14134562236bSHarry Wentland 14144562236bSHarry Wentland for (i = 0; i < dc->res_pool->pipe_count; i++) { 14154562236bSHarry Wentland dc->res_pool->timing_generators[i]->funcs->disable_crtc( 14164562236bSHarry Wentland dc->res_pool->timing_generators[i]); 14174562236bSHarry Wentland } 14184562236bSHarry Wentland } 14194562236bSHarry Wentland 1420fb3466a4SBhawanpreet Lakha static void power_down_clock_sources(struct dc *dc) 14214562236bSHarry Wentland { 14224562236bSHarry Wentland int i; 14234562236bSHarry Wentland 14244562236bSHarry Wentland if (dc->res_pool->dp_clock_source->funcs->cs_power_down( 14254562236bSHarry Wentland dc->res_pool->dp_clock_source) == false) 14264562236bSHarry Wentland dm_error("Failed to power down pll! (dp clk src)\n"); 14274562236bSHarry Wentland 14284562236bSHarry Wentland for (i = 0; i < dc->res_pool->clk_src_count; i++) { 14294562236bSHarry Wentland if (dc->res_pool->clock_sources[i]->funcs->cs_power_down( 14304562236bSHarry Wentland dc->res_pool->clock_sources[i]) == false) 14314562236bSHarry Wentland dm_error("Failed to power down pll! (clk src index=%d)\n", i); 14324562236bSHarry Wentland } 14334562236bSHarry Wentland } 14344562236bSHarry Wentland 1435fb3466a4SBhawanpreet Lakha static void power_down_all_hw_blocks(struct dc *dc) 14364562236bSHarry Wentland { 14374562236bSHarry Wentland power_down_encoders(dc); 14384562236bSHarry Wentland 14394562236bSHarry Wentland power_down_controllers(dc); 14404562236bSHarry Wentland 14414562236bSHarry Wentland power_down_clock_sources(dc); 14421663ae1cSBhawanpreet Lakha 14433eab7916SShirish S #if defined(CONFIG_DRM_AMD_DC_FBC) 14442f3bfb27SRoman Li if (dc->fbc_compressor) 14451663ae1cSBhawanpreet Lakha dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); 14461663ae1cSBhawanpreet Lakha #endif 14474562236bSHarry Wentland } 14484562236bSHarry Wentland 14494562236bSHarry Wentland static void disable_vga_and_power_gate_all_controllers( 1450fb3466a4SBhawanpreet Lakha struct dc *dc) 14514562236bSHarry Wentland { 14524562236bSHarry Wentland int i; 14534562236bSHarry Wentland struct timing_generator *tg; 14544562236bSHarry Wentland struct dc_context *ctx = dc->ctx; 14554562236bSHarry Wentland 14564562236bSHarry Wentland for (i = 0; i < dc->res_pool->pipe_count; i++) { 14574562236bSHarry Wentland tg = dc->res_pool->timing_generators[i]; 14584562236bSHarry Wentland 14590a87425aSTony Cheng if (tg->funcs->disable_vga) 14604562236bSHarry Wentland tg->funcs->disable_vga(tg); 14614562236bSHarry Wentland 14624562236bSHarry Wentland /* Enable CLOCK gating for each pipe BEFORE controller 14634562236bSHarry Wentland * powergating. */ 14644562236bSHarry Wentland enable_display_pipe_clock_gating(ctx, 14654562236bSHarry Wentland true); 14664562236bSHarry Wentland 1467e6c258cbSYongqiang Sun dc->current_state->res_ctx.pipe_ctx[i].pipe_idx = i; 1468e6c258cbSYongqiang Sun dc->hwss.power_down_front_end(dc, 1469e6c258cbSYongqiang Sun &dc->current_state->res_ctx.pipe_ctx[i]); 14704562236bSHarry Wentland } 14714562236bSHarry Wentland } 14724562236bSHarry Wentland 14734562236bSHarry Wentland /** 14744562236bSHarry Wentland * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need: 14754562236bSHarry Wentland * 1. Power down all DC HW blocks 14764562236bSHarry Wentland * 2. Disable VGA engine on all controllers 14774562236bSHarry Wentland * 3. Enable power gating for controller 14784562236bSHarry Wentland * 4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS) 14794562236bSHarry Wentland */ 1480fb3466a4SBhawanpreet Lakha void dce110_enable_accelerated_mode(struct dc *dc) 14814562236bSHarry Wentland { 14824562236bSHarry Wentland power_down_all_hw_blocks(dc); 14834562236bSHarry Wentland 14844562236bSHarry Wentland disable_vga_and_power_gate_all_controllers(dc); 14854562236bSHarry Wentland bios_set_scratch_acc_mode_change(dc->ctx->dc_bios); 14864562236bSHarry Wentland } 14874562236bSHarry Wentland 14884562236bSHarry Wentland static uint32_t compute_pstate_blackout_duration( 14894562236bSHarry Wentland struct bw_fixed blackout_duration, 14900971c40eSHarry Wentland const struct dc_stream_state *stream) 14914562236bSHarry Wentland { 14924562236bSHarry Wentland uint32_t total_dest_line_time_ns; 14934562236bSHarry Wentland uint32_t pstate_blackout_duration_ns; 14944562236bSHarry Wentland 14954562236bSHarry Wentland pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24; 14964562236bSHarry Wentland 14974562236bSHarry Wentland total_dest_line_time_ns = 1000000UL * 14984fa086b9SLeo (Sunpeng) Li stream->timing.h_total / 14994fa086b9SLeo (Sunpeng) Li stream->timing.pix_clk_khz + 15004562236bSHarry Wentland pstate_blackout_duration_ns; 15014562236bSHarry Wentland 15024562236bSHarry Wentland return total_dest_line_time_ns; 15034562236bSHarry Wentland } 15044562236bSHarry Wentland 15054562236bSHarry Wentland void dce110_set_displaymarks( 1506fb3466a4SBhawanpreet Lakha const struct dc *dc, 1507608ac7bbSJerry Zuo struct dc_state *context) 15084562236bSHarry Wentland { 15094562236bSHarry Wentland uint8_t i, num_pipes; 15104562236bSHarry Wentland unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; 15114562236bSHarry Wentland 15124562236bSHarry Wentland for (i = 0, num_pipes = 0; i < MAX_PIPES; i++) { 15134562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 15144562236bSHarry Wentland uint32_t total_dest_line_time_ns; 15154562236bSHarry Wentland 15164562236bSHarry Wentland if (pipe_ctx->stream == NULL) 15174562236bSHarry Wentland continue; 15184562236bSHarry Wentland 15194562236bSHarry Wentland total_dest_line_time_ns = compute_pstate_blackout_duration( 152077a4ea53SBhawanpreet Lakha dc->bw_vbios->blackout_duration, pipe_ctx->stream); 152186a66c4eSHarry Wentland pipe_ctx->plane_res.mi->funcs->mem_input_program_display_marks( 152286a66c4eSHarry Wentland pipe_ctx->plane_res.mi, 15239037d802SDmytro Laktyushkin context->bw.dce.nbp_state_change_wm_ns[num_pipes], 15249037d802SDmytro Laktyushkin context->bw.dce.stutter_exit_wm_ns[num_pipes], 15259037d802SDmytro Laktyushkin context->bw.dce.urgent_wm_ns[num_pipes], 15264562236bSHarry Wentland total_dest_line_time_ns); 15274562236bSHarry Wentland if (i == underlay_idx) { 15284562236bSHarry Wentland num_pipes++; 152986a66c4eSHarry Wentland pipe_ctx->plane_res.mi->funcs->mem_input_program_chroma_display_marks( 153086a66c4eSHarry Wentland pipe_ctx->plane_res.mi, 15319037d802SDmytro Laktyushkin context->bw.dce.nbp_state_change_wm_ns[num_pipes], 15329037d802SDmytro Laktyushkin context->bw.dce.stutter_exit_wm_ns[num_pipes], 15339037d802SDmytro Laktyushkin context->bw.dce.urgent_wm_ns[num_pipes], 15344562236bSHarry Wentland total_dest_line_time_ns); 15354562236bSHarry Wentland } 15364562236bSHarry Wentland num_pipes++; 15374562236bSHarry Wentland } 15384562236bSHarry Wentland } 15394562236bSHarry Wentland 1540a2b8659dSTony Cheng static void set_safe_displaymarks( 1541a2b8659dSTony Cheng struct resource_context *res_ctx, 1542a2b8659dSTony Cheng const struct resource_pool *pool) 15434562236bSHarry Wentland { 15444562236bSHarry Wentland int i; 1545a2b8659dSTony Cheng int underlay_idx = pool->underlay_pipe_index; 15469037d802SDmytro Laktyushkin struct dce_watermarks max_marks = { 15474562236bSHarry Wentland MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK }; 15489037d802SDmytro Laktyushkin struct dce_watermarks nbp_marks = { 15494562236bSHarry Wentland SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK }; 15504562236bSHarry Wentland 15514562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 15528feabd03SYue Hin Lau if (res_ctx->pipe_ctx[i].stream == NULL || res_ctx->pipe_ctx[i].plane_res.mi == NULL) 15534562236bSHarry Wentland continue; 15544562236bSHarry Wentland 155586a66c4eSHarry Wentland res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_display_marks( 155686a66c4eSHarry Wentland res_ctx->pipe_ctx[i].plane_res.mi, 15574562236bSHarry Wentland nbp_marks, 15584562236bSHarry Wentland max_marks, 15594562236bSHarry Wentland max_marks, 15604562236bSHarry Wentland MAX_WATERMARK); 15618feabd03SYue Hin Lau 15624562236bSHarry Wentland if (i == underlay_idx) 156386a66c4eSHarry Wentland res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_chroma_display_marks( 156486a66c4eSHarry Wentland res_ctx->pipe_ctx[i].plane_res.mi, 15654562236bSHarry Wentland nbp_marks, 15664562236bSHarry Wentland max_marks, 15674562236bSHarry Wentland max_marks, 15684562236bSHarry Wentland MAX_WATERMARK); 15698feabd03SYue Hin Lau 15704562236bSHarry Wentland } 15714562236bSHarry Wentland } 15724562236bSHarry Wentland 15734562236bSHarry Wentland /******************************************************************************* 15744562236bSHarry Wentland * Public functions 15754562236bSHarry Wentland ******************************************************************************/ 15764562236bSHarry Wentland 15774562236bSHarry Wentland static void set_drr(struct pipe_ctx **pipe_ctx, 15784562236bSHarry Wentland int num_pipes, int vmin, int vmax) 15794562236bSHarry Wentland { 15804562236bSHarry Wentland int i = 0; 15814562236bSHarry Wentland struct drr_params params = {0}; 15824562236bSHarry Wentland 15834562236bSHarry Wentland params.vertical_total_max = vmax; 15844562236bSHarry Wentland params.vertical_total_min = vmin; 15854562236bSHarry Wentland 15864562236bSHarry Wentland /* TODO: If multiple pipes are to be supported, you need 15874562236bSHarry Wentland * some GSL stuff 15884562236bSHarry Wentland */ 15894562236bSHarry Wentland 15904562236bSHarry Wentland for (i = 0; i < num_pipes; i++) { 15916b670fa9SHarry Wentland pipe_ctx[i]->stream_res.tg->funcs->set_drr(pipe_ctx[i]->stream_res.tg, ¶ms); 15924562236bSHarry Wentland } 15934562236bSHarry Wentland } 15944562236bSHarry Wentland 159572ada5f7SEric Cook static void get_position(struct pipe_ctx **pipe_ctx, 159672ada5f7SEric Cook int num_pipes, 159772ada5f7SEric Cook struct crtc_position *position) 159872ada5f7SEric Cook { 159972ada5f7SEric Cook int i = 0; 160072ada5f7SEric Cook 160172ada5f7SEric Cook /* TODO: handle pipes > 1 160272ada5f7SEric Cook */ 160372ada5f7SEric Cook for (i = 0; i < num_pipes; i++) 16046b670fa9SHarry Wentland pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position); 160572ada5f7SEric Cook } 160672ada5f7SEric Cook 16074562236bSHarry Wentland static void set_static_screen_control(struct pipe_ctx **pipe_ctx, 160894267b3dSSylvia Tsai int num_pipes, const struct dc_static_screen_events *events) 16094562236bSHarry Wentland { 16104562236bSHarry Wentland unsigned int i; 161194267b3dSSylvia Tsai unsigned int value = 0; 161294267b3dSSylvia Tsai 161394267b3dSSylvia Tsai if (events->overlay_update) 161494267b3dSSylvia Tsai value |= 0x100; 161594267b3dSSylvia Tsai if (events->surface_update) 161694267b3dSSylvia Tsai value |= 0x80; 161794267b3dSSylvia Tsai if (events->cursor_update) 161894267b3dSSylvia Tsai value |= 0x2; 16194562236bSHarry Wentland 16203eab7916SShirish S #if defined(CONFIG_DRM_AMD_DC_FBC) 1621c3aa1d67SBhawanpreet Lakha value |= 0x84; 1622c3aa1d67SBhawanpreet Lakha #endif 1623c3aa1d67SBhawanpreet Lakha 16244562236bSHarry Wentland for (i = 0; i < num_pipes; i++) 16256b670fa9SHarry Wentland pipe_ctx[i]->stream_res.tg->funcs-> 16266b670fa9SHarry Wentland set_static_screen_control(pipe_ctx[i]->stream_res.tg, value); 16274562236bSHarry Wentland } 16284562236bSHarry Wentland 16294562236bSHarry Wentland /* unit: in_khz before mode set, get pixel clock from context. ASIC register 16304562236bSHarry Wentland * may not be programmed yet. 16314562236bSHarry Wentland * TODO: after mode set, pre_mode_set = false, 16324562236bSHarry Wentland * may read PLL register to get pixel clock 16334562236bSHarry Wentland */ 16344562236bSHarry Wentland static uint32_t get_max_pixel_clock_for_all_paths( 1635fb3466a4SBhawanpreet Lakha struct dc *dc, 1636608ac7bbSJerry Zuo struct dc_state *context, 16374562236bSHarry Wentland bool pre_mode_set) 16384562236bSHarry Wentland { 16394562236bSHarry Wentland uint32_t max_pix_clk = 0; 16404562236bSHarry Wentland int i; 16414562236bSHarry Wentland 16424562236bSHarry Wentland if (!pre_mode_set) { 16434562236bSHarry Wentland /* TODO: read ASIC register to get pixel clock */ 16444562236bSHarry Wentland ASSERT(0); 16454562236bSHarry Wentland } 16464562236bSHarry Wentland 16474562236bSHarry Wentland for (i = 0; i < MAX_PIPES; i++) { 16484562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 16494562236bSHarry Wentland 16504562236bSHarry Wentland if (pipe_ctx->stream == NULL) 16514562236bSHarry Wentland continue; 16524562236bSHarry Wentland 16534562236bSHarry Wentland /* do not check under lay */ 16544562236bSHarry Wentland if (pipe_ctx->top_pipe) 16554562236bSHarry Wentland continue; 16564562236bSHarry Wentland 165710688217SHarry Wentland if (pipe_ctx->stream_res.pix_clk_params.requested_pix_clk > max_pix_clk) 16584562236bSHarry Wentland max_pix_clk = 165910688217SHarry Wentland pipe_ctx->stream_res.pix_clk_params.requested_pix_clk; 16604562236bSHarry Wentland } 16614562236bSHarry Wentland 16624562236bSHarry Wentland if (max_pix_clk == 0) 16634562236bSHarry Wentland ASSERT(0); 16644562236bSHarry Wentland 16654562236bSHarry Wentland return max_pix_clk; 16664562236bSHarry Wentland } 16674562236bSHarry Wentland 1668f6baff4dSHarry Wentland /* 1669f6baff4dSHarry Wentland * Find clock state based on clock requested. if clock value is 0, simply 16704562236bSHarry Wentland * set clock state as requested without finding clock state by clock value 16714562236bSHarry Wentland */ 1672f6baff4dSHarry Wentland 16734562236bSHarry Wentland static void apply_min_clocks( 1674fb3466a4SBhawanpreet Lakha struct dc *dc, 1675608ac7bbSJerry Zuo struct dc_state *context, 1676e9c58bb4SDmytro Laktyushkin enum dm_pp_clocks_state *clocks_state, 16774562236bSHarry Wentland bool pre_mode_set) 16784562236bSHarry Wentland { 16794562236bSHarry Wentland struct state_dependent_clocks req_clocks = {0}; 16804562236bSHarry Wentland 16814562236bSHarry Wentland if (!pre_mode_set) { 16824562236bSHarry Wentland /* set clock_state without verification */ 1683ab8db3e1SAndrey Grodzovsky if (context->dis_clk->funcs->set_min_clocks_state) { 1684ab8db3e1SAndrey Grodzovsky context->dis_clk->funcs->set_min_clocks_state( 1685ab8db3e1SAndrey Grodzovsky context->dis_clk, *clocks_state); 16864562236bSHarry Wentland return; 16875d6d185fSDmytro Laktyushkin } 16884562236bSHarry Wentland 16892c8ad2d5SAlex Deucher /* TODO: This is incorrect. Figure out how to fix. */ 1690ab8db3e1SAndrey Grodzovsky context->dis_clk->funcs->apply_clock_voltage_request( 1691ab8db3e1SAndrey Grodzovsky context->dis_clk, 16922c8ad2d5SAlex Deucher DM_PP_CLOCK_TYPE_DISPLAY_CLK, 1693ab8db3e1SAndrey Grodzovsky context->dis_clk->cur_clocks_value.dispclk_in_khz, 16942c8ad2d5SAlex Deucher pre_mode_set, 16952c8ad2d5SAlex Deucher false); 16962c8ad2d5SAlex Deucher 1697ab8db3e1SAndrey Grodzovsky context->dis_clk->funcs->apply_clock_voltage_request( 1698ab8db3e1SAndrey Grodzovsky context->dis_clk, 16992c8ad2d5SAlex Deucher DM_PP_CLOCK_TYPE_PIXELCLK, 1700ab8db3e1SAndrey Grodzovsky context->dis_clk->cur_clocks_value.max_pixelclk_in_khz, 17012c8ad2d5SAlex Deucher pre_mode_set, 17022c8ad2d5SAlex Deucher false); 17032c8ad2d5SAlex Deucher 1704ab8db3e1SAndrey Grodzovsky context->dis_clk->funcs->apply_clock_voltage_request( 1705ab8db3e1SAndrey Grodzovsky context->dis_clk, 17062c8ad2d5SAlex Deucher DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, 1707ab8db3e1SAndrey Grodzovsky context->dis_clk->cur_clocks_value.max_non_dp_phyclk_in_khz, 17082c8ad2d5SAlex Deucher pre_mode_set, 17092c8ad2d5SAlex Deucher false); 17102c8ad2d5SAlex Deucher return; 17114562236bSHarry Wentland } 17124562236bSHarry Wentland 17134562236bSHarry Wentland /* get the required state based on state dependent clocks: 17144562236bSHarry Wentland * display clock and pixel clock 17154562236bSHarry Wentland */ 17169037d802SDmytro Laktyushkin req_clocks.display_clk_khz = context->bw.dce.dispclk_khz; 17174562236bSHarry Wentland 17184562236bSHarry Wentland req_clocks.pixel_clk_khz = get_max_pixel_clock_for_all_paths( 17194562236bSHarry Wentland dc, context, true); 17204562236bSHarry Wentland 1721ab8db3e1SAndrey Grodzovsky if (context->dis_clk->funcs->get_required_clocks_state) { 1722ab8db3e1SAndrey Grodzovsky *clocks_state = context->dis_clk->funcs->get_required_clocks_state( 1723ab8db3e1SAndrey Grodzovsky context->dis_clk, &req_clocks); 1724ab8db3e1SAndrey Grodzovsky context->dis_clk->funcs->set_min_clocks_state( 1725ab8db3e1SAndrey Grodzovsky context->dis_clk, *clocks_state); 17264562236bSHarry Wentland } else { 1727ab8db3e1SAndrey Grodzovsky context->dis_clk->funcs->apply_clock_voltage_request( 1728ab8db3e1SAndrey Grodzovsky context->dis_clk, 17292c8ad2d5SAlex Deucher DM_PP_CLOCK_TYPE_DISPLAY_CLK, 17302c8ad2d5SAlex Deucher req_clocks.display_clk_khz, 17312c8ad2d5SAlex Deucher pre_mode_set, 17322c8ad2d5SAlex Deucher false); 17332c8ad2d5SAlex Deucher 1734ab8db3e1SAndrey Grodzovsky context->dis_clk->funcs->apply_clock_voltage_request( 1735ab8db3e1SAndrey Grodzovsky context->dis_clk, 17362c8ad2d5SAlex Deucher DM_PP_CLOCK_TYPE_PIXELCLK, 17372c8ad2d5SAlex Deucher req_clocks.pixel_clk_khz, 17382c8ad2d5SAlex Deucher pre_mode_set, 17392c8ad2d5SAlex Deucher false); 17402c8ad2d5SAlex Deucher 1741ab8db3e1SAndrey Grodzovsky context->dis_clk->funcs->apply_clock_voltage_request( 1742ab8db3e1SAndrey Grodzovsky context->dis_clk, 17432c8ad2d5SAlex Deucher DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, 17442c8ad2d5SAlex Deucher req_clocks.pixel_clk_khz, 17452c8ad2d5SAlex Deucher pre_mode_set, 17462c8ad2d5SAlex Deucher false); 17474562236bSHarry Wentland } 17484562236bSHarry Wentland } 17494562236bSHarry Wentland 17503eab7916SShirish S #if defined(CONFIG_DRM_AMD_DC_FBC) 1751690b5e39SRoman Li 1752690b5e39SRoman Li /* 1753690b5e39SRoman Li * Check if FBC can be enabled 1754690b5e39SRoman Li */ 1755fb3466a4SBhawanpreet Lakha static enum dc_status validate_fbc(struct dc *dc, 1756608ac7bbSJerry Zuo struct dc_state *context) 1757690b5e39SRoman Li { 1758690b5e39SRoman Li struct pipe_ctx *pipe_ctx = 1759690b5e39SRoman Li &context->res_ctx.pipe_ctx[0]; 1760690b5e39SRoman Li 1761690b5e39SRoman Li ASSERT(dc->fbc_compressor); 1762690b5e39SRoman Li 1763690b5e39SRoman Li /* FBC memory should be allocated */ 1764690b5e39SRoman Li if (!dc->ctx->fbc_gpu_addr) 1765690b5e39SRoman Li return DC_ERROR_UNEXPECTED; 1766690b5e39SRoman Li 1767690b5e39SRoman Li /* Only supports single display */ 1768690b5e39SRoman Li if (context->stream_count != 1) 1769690b5e39SRoman Li return DC_ERROR_UNEXPECTED; 1770690b5e39SRoman Li 1771690b5e39SRoman Li /* Only supports eDP */ 1772690b5e39SRoman Li if (pipe_ctx->stream->sink->link->connector_signal != SIGNAL_TYPE_EDP) 1773690b5e39SRoman Li return DC_ERROR_UNEXPECTED; 1774690b5e39SRoman Li 1775690b5e39SRoman Li /* PSR should not be enabled */ 1776690b5e39SRoman Li if (pipe_ctx->stream->sink->link->psr_enabled) 1777690b5e39SRoman Li return DC_ERROR_UNEXPECTED; 1778690b5e39SRoman Li 177993984bbcSShirish S /* Nothing to compress */ 178093984bbcSShirish S if (!pipe_ctx->plane_state) 178193984bbcSShirish S return DC_ERROR_UNEXPECTED; 178293984bbcSShirish S 178305230fa9SRoman Li /* Only for non-linear tiling */ 178405230fa9SRoman Li if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) 178505230fa9SRoman Li return DC_ERROR_UNEXPECTED; 178605230fa9SRoman Li 1787690b5e39SRoman Li return DC_OK; 1788690b5e39SRoman Li } 1789690b5e39SRoman Li 1790690b5e39SRoman Li /* 1791690b5e39SRoman Li * Enable FBC 1792690b5e39SRoman Li */ 1793fb3466a4SBhawanpreet Lakha static enum dc_status enable_fbc(struct dc *dc, 1794608ac7bbSJerry Zuo struct dc_state *context) 1795690b5e39SRoman Li { 1796690b5e39SRoman Li enum dc_status status = validate_fbc(dc, context); 1797690b5e39SRoman Li 1798690b5e39SRoman Li if (status == DC_OK) { 1799690b5e39SRoman Li /* Program GRPH COMPRESSED ADDRESS and PITCH */ 1800690b5e39SRoman Li struct compr_addr_and_pitch_params params = {0, 0, 0}; 1801690b5e39SRoman Li struct compressor *compr = dc->fbc_compressor; 1802690b5e39SRoman Li struct pipe_ctx *pipe_ctx = 1803690b5e39SRoman Li &context->res_ctx.pipe_ctx[0]; 1804690b5e39SRoman Li 1805690b5e39SRoman Li params.source_view_width = 1806690b5e39SRoman Li pipe_ctx->stream->timing.h_addressable; 1807690b5e39SRoman Li params.source_view_height = 1808690b5e39SRoman Li pipe_ctx->stream->timing.v_addressable; 1809690b5e39SRoman Li 1810690b5e39SRoman Li compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr; 1811690b5e39SRoman Li 1812690b5e39SRoman Li compr->funcs->surface_address_and_pitch(compr, ¶ms); 1813690b5e39SRoman Li compr->funcs->set_fbc_invalidation_triggers(compr, 1); 1814690b5e39SRoman Li 1815690b5e39SRoman Li compr->funcs->enable_fbc(compr, ¶ms); 1816690b5e39SRoman Li } 1817690b5e39SRoman Li return status; 1818690b5e39SRoman Li } 1819690b5e39SRoman Li #endif 1820690b5e39SRoman Li 18214562236bSHarry Wentland static enum dc_status apply_ctx_to_hw_fpga( 1822fb3466a4SBhawanpreet Lakha struct dc *dc, 1823608ac7bbSJerry Zuo struct dc_state *context) 18244562236bSHarry Wentland { 18254562236bSHarry Wentland enum dc_status status = DC_ERROR_UNEXPECTED; 18264562236bSHarry Wentland int i; 18274562236bSHarry Wentland 1828a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 18294562236bSHarry Wentland struct pipe_ctx *pipe_ctx_old = 1830608ac7bbSJerry Zuo &dc->current_state->res_ctx.pipe_ctx[i]; 18314562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 18324562236bSHarry Wentland 18334562236bSHarry Wentland if (pipe_ctx->stream == NULL) 18344562236bSHarry Wentland continue; 18354562236bSHarry Wentland 18364562236bSHarry Wentland if (pipe_ctx->stream == pipe_ctx_old->stream) 18374562236bSHarry Wentland continue; 18384562236bSHarry Wentland 18394562236bSHarry Wentland status = apply_single_controller_ctx_to_hw( 18404562236bSHarry Wentland pipe_ctx, 18414562236bSHarry Wentland context, 18424562236bSHarry Wentland dc); 18434562236bSHarry Wentland 18444562236bSHarry Wentland if (status != DC_OK) 18454562236bSHarry Wentland return status; 18464562236bSHarry Wentland } 18474562236bSHarry Wentland 18484562236bSHarry Wentland return DC_OK; 18494562236bSHarry Wentland } 18504562236bSHarry Wentland 185154e8695eSDmytro Laktyushkin static void dce110_reset_hw_ctx_wrap( 1852fb3466a4SBhawanpreet Lakha struct dc *dc, 1853608ac7bbSJerry Zuo struct dc_state *context) 18544562236bSHarry Wentland { 18554562236bSHarry Wentland int i; 18564562236bSHarry Wentland 18574562236bSHarry Wentland /* Reset old context */ 18584562236bSHarry Wentland /* look up the targets that have been removed since last commit */ 1859a2b8659dSTony Cheng for (i = 0; i < MAX_PIPES; i++) { 18604562236bSHarry Wentland struct pipe_ctx *pipe_ctx_old = 1861608ac7bbSJerry Zuo &dc->current_state->res_ctx.pipe_ctx[i]; 18624562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 18634562236bSHarry Wentland 18644562236bSHarry Wentland /* Note: We need to disable output if clock sources change, 18654562236bSHarry Wentland * since bios does optimization and doesn't apply if changing 18664562236bSHarry Wentland * PHY when not already disabled. 18674562236bSHarry Wentland */ 18684562236bSHarry Wentland 18694562236bSHarry Wentland /* Skip underlay pipe since it will be handled in commit surface*/ 18704562236bSHarry Wentland if (!pipe_ctx_old->stream || pipe_ctx_old->top_pipe) 18714562236bSHarry Wentland continue; 18724562236bSHarry Wentland 18734562236bSHarry Wentland if (!pipe_ctx->stream || 187454e8695eSDmytro Laktyushkin pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { 187521e67d4dSHarry Wentland struct clock_source *old_clk = pipe_ctx_old->clock_source; 187621e67d4dSHarry Wentland 1877827f11e9SLeo (Sunpeng) Li /* Disable if new stream is null. O/w, if stream is 1878827f11e9SLeo (Sunpeng) Li * disabled already, no need to disable again. 1879827f11e9SLeo (Sunpeng) Li */ 1880827f11e9SLeo (Sunpeng) Li if (!pipe_ctx->stream || !pipe_ctx->stream->dpms_off) 18814176664bSCharlene Liu core_link_disable_stream(pipe_ctx_old, FREE_ACQUIRED_RESOURCE); 1882d050f8edSHersen Wu 18836b670fa9SHarry Wentland pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true); 18846b670fa9SHarry Wentland if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) { 188554e8695eSDmytro Laktyushkin dm_error("DC: failed to blank crtc!\n"); 188654e8695eSDmytro Laktyushkin BREAK_TO_DEBUGGER(); 188754e8695eSDmytro Laktyushkin } 18886b670fa9SHarry Wentland pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg); 188986a66c4eSHarry Wentland pipe_ctx_old->plane_res.mi->funcs->free_mem_input( 1890608ac7bbSJerry Zuo pipe_ctx_old->plane_res.mi, dc->current_state->stream_count); 189154e8695eSDmytro Laktyushkin 189221e67d4dSHarry Wentland if (old_clk) 189321e67d4dSHarry Wentland old_clk->funcs->cs_power_down(old_clk); 189421e67d4dSHarry Wentland 1895e6c258cbSYongqiang Sun dc->hwss.power_down_front_end(dc, pipe_ctx_old); 189654e8695eSDmytro Laktyushkin 189754e8695eSDmytro Laktyushkin pipe_ctx_old->stream = NULL; 189854e8695eSDmytro Laktyushkin } 18994562236bSHarry Wentland } 19004562236bSHarry Wentland } 19014562236bSHarry Wentland 1902cf437593SDmytro Laktyushkin 19034562236bSHarry Wentland enum dc_status dce110_apply_ctx_to_hw( 1904fb3466a4SBhawanpreet Lakha struct dc *dc, 1905608ac7bbSJerry Zuo struct dc_state *context) 19064562236bSHarry Wentland { 19074562236bSHarry Wentland struct dc_bios *dcb = dc->ctx->dc_bios; 19084562236bSHarry Wentland enum dc_status status; 19094562236bSHarry Wentland int i; 1910e9c58bb4SDmytro Laktyushkin enum dm_pp_clocks_state clocks_state = DM_PP_CLOCKS_STATE_INVALID; 19114562236bSHarry Wentland 19124562236bSHarry Wentland /* Reset old context */ 19134562236bSHarry Wentland /* look up the targets that have been removed since last commit */ 19144562236bSHarry Wentland dc->hwss.reset_hw_ctx_wrap(dc, context); 19154562236bSHarry Wentland 19164562236bSHarry Wentland /* Skip applying if no targets */ 1917ab2541b6SAric Cyr if (context->stream_count <= 0) 19184562236bSHarry Wentland return DC_OK; 19194562236bSHarry Wentland 19204562236bSHarry Wentland if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { 19214562236bSHarry Wentland apply_ctx_to_hw_fpga(dc, context); 19224562236bSHarry Wentland return DC_OK; 19234562236bSHarry Wentland } 19244562236bSHarry Wentland 19254562236bSHarry Wentland /* Apply new context */ 19264562236bSHarry Wentland dcb->funcs->set_scratch_critical_state(dcb, true); 19274562236bSHarry Wentland 19284562236bSHarry Wentland /* below is for real asic only */ 1929a2b8659dSTony Cheng for (i = 0; i < dc->res_pool->pipe_count; i++) { 19304562236bSHarry Wentland struct pipe_ctx *pipe_ctx_old = 1931608ac7bbSJerry Zuo &dc->current_state->res_ctx.pipe_ctx[i]; 19324562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 19334562236bSHarry Wentland 19344562236bSHarry Wentland if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe) 19354562236bSHarry Wentland continue; 19364562236bSHarry Wentland 19374562236bSHarry Wentland if (pipe_ctx->stream == pipe_ctx_old->stream) { 19384562236bSHarry Wentland if (pipe_ctx_old->clock_source != pipe_ctx->clock_source) 19394562236bSHarry Wentland dce_crtc_switch_to_clk_src(dc->hwseq, 19404562236bSHarry Wentland pipe_ctx->clock_source, i); 19414562236bSHarry Wentland continue; 19424562236bSHarry Wentland } 19434562236bSHarry Wentland 19444562236bSHarry Wentland dc->hwss.enable_display_power_gating( 19454562236bSHarry Wentland dc, i, dc->ctx->dc_bios, 19464562236bSHarry Wentland PIPE_GATING_CONTROL_DISABLE); 19474562236bSHarry Wentland } 19484562236bSHarry Wentland 1949a2b8659dSTony Cheng set_safe_displaymarks(&context->res_ctx, dc->res_pool); 19501663ae1cSBhawanpreet Lakha 19513eab7916SShirish S #if defined(CONFIG_DRM_AMD_DC_FBC) 19522f3bfb27SRoman Li if (dc->fbc_compressor) 19531663ae1cSBhawanpreet Lakha dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); 19541663ae1cSBhawanpreet Lakha #endif 19554562236bSHarry Wentland /*TODO: when pplib works*/ 19564562236bSHarry Wentland apply_min_clocks(dc, context, &clocks_state, true); 19574562236bSHarry Wentland 1958ff5ef992SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 19593639fa68SZeyu Fan if (dc->ctx->dce_version >= DCN_VERSION_1_0) { 19609037d802SDmytro Laktyushkin if (context->bw.dcn.calc_clk.fclk_khz 1961608ac7bbSJerry Zuo > dc->current_state->bw.dcn.cur_clk.fclk_khz) { 1962ff5ef992SAlex Deucher struct dm_pp_clock_for_voltage_req clock; 1963ff5ef992SAlex Deucher 1964ff5ef992SAlex Deucher clock.clk_type = DM_PP_CLOCK_TYPE_FCLK; 19659037d802SDmytro Laktyushkin clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz; 1966ff5ef992SAlex Deucher dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); 1967608ac7bbSJerry Zuo dc->current_state->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz; 1968c66a54dcSDmytro Laktyushkin context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz; 1969ff5ef992SAlex Deucher } 19709037d802SDmytro Laktyushkin if (context->bw.dcn.calc_clk.dcfclk_khz 1971608ac7bbSJerry Zuo > dc->current_state->bw.dcn.cur_clk.dcfclk_khz) { 1972ff5ef992SAlex Deucher struct dm_pp_clock_for_voltage_req clock; 1973ff5ef992SAlex Deucher 1974ff5ef992SAlex Deucher clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; 19759037d802SDmytro Laktyushkin clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz; 1976ff5ef992SAlex Deucher dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); 1977608ac7bbSJerry Zuo dc->current_state->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; 1978c66a54dcSDmytro Laktyushkin context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; 1979ff5ef992SAlex Deucher } 1980c66a54dcSDmytro Laktyushkin if (context->bw.dcn.calc_clk.dispclk_khz 1981608ac7bbSJerry Zuo > dc->current_state->bw.dcn.cur_clk.dispclk_khz) { 1982c66a54dcSDmytro Laktyushkin dc->res_pool->display_clock->funcs->set_clock( 1983c66a54dcSDmytro Laktyushkin dc->res_pool->display_clock, 1984c66a54dcSDmytro Laktyushkin context->bw.dcn.calc_clk.dispclk_khz); 1985608ac7bbSJerry Zuo dc->current_state->bw.dcn.cur_clk.dispclk_khz = 1986c66a54dcSDmytro Laktyushkin context->bw.dcn.calc_clk.dispclk_khz; 1987c66a54dcSDmytro Laktyushkin context->bw.dcn.cur_clk.dispclk_khz = 1988c66a54dcSDmytro Laktyushkin context->bw.dcn.calc_clk.dispclk_khz; 1989c66a54dcSDmytro Laktyushkin } 1990c66a54dcSDmytro Laktyushkin } else 1991ff5ef992SAlex Deucher #endif 19929037d802SDmytro Laktyushkin if (context->bw.dce.dispclk_khz 1993608ac7bbSJerry Zuo > dc->current_state->bw.dce.dispclk_khz) { 1994a2b8659dSTony Cheng dc->res_pool->display_clock->funcs->set_clock( 1995a2b8659dSTony Cheng dc->res_pool->display_clock, 19969037d802SDmytro Laktyushkin context->bw.dce.dispclk_khz * 115 / 100); 19971ce71fcdSCharlene Liu } 1998ab8812a3SHersen Wu /* program audio wall clock. use HDMI as clock source if HDMI 1999ab8812a3SHersen Wu * audio active. Otherwise, use DP as clock source 2000ab8812a3SHersen Wu * first, loop to find any HDMI audio, if not, loop find DP audio 2001ab8812a3SHersen Wu */ 20024562236bSHarry Wentland /* Setup audio rate clock source */ 20034562236bSHarry Wentland /* Issue: 20044562236bSHarry Wentland * Audio lag happened on DP monitor when unplug a HDMI monitor 20054562236bSHarry Wentland * 20064562236bSHarry Wentland * Cause: 20074562236bSHarry Wentland * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL 20084562236bSHarry Wentland * is set to either dto0 or dto1, audio should work fine. 20094562236bSHarry Wentland * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1, 20104562236bSHarry Wentland * set to dto0 will cause audio lag. 20114562236bSHarry Wentland * 20124562236bSHarry Wentland * Solution: 20134562236bSHarry Wentland * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx, 20144562236bSHarry Wentland * find first available pipe with audio, setup audio wall DTO per topology 20154562236bSHarry Wentland * instead of per pipe. 20164562236bSHarry Wentland */ 2017a2b8659dSTony Cheng for (i = 0; i < dc->res_pool->pipe_count; i++) { 2018ab8812a3SHersen Wu struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 2019ab8812a3SHersen Wu 2020ab8812a3SHersen Wu if (pipe_ctx->stream == NULL) 2021ab8812a3SHersen Wu continue; 2022ab8812a3SHersen Wu 2023ab8812a3SHersen Wu if (pipe_ctx->top_pipe) 2024ab8812a3SHersen Wu continue; 2025ab8812a3SHersen Wu 2026ab8812a3SHersen Wu if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) 2027ab8812a3SHersen Wu continue; 2028ab8812a3SHersen Wu 2029afaacef4SHarry Wentland if (pipe_ctx->stream_res.audio != NULL) { 2030ab8812a3SHersen Wu struct audio_output audio_output; 2031ab8812a3SHersen Wu 2032ab8db3e1SAndrey Grodzovsky build_audio_output(context, pipe_ctx, &audio_output); 2033ab8812a3SHersen Wu 2034afaacef4SHarry Wentland pipe_ctx->stream_res.audio->funcs->wall_dto_setup( 2035afaacef4SHarry Wentland pipe_ctx->stream_res.audio, 2036ab8812a3SHersen Wu pipe_ctx->stream->signal, 2037ab8812a3SHersen Wu &audio_output.crtc_info, 2038ab8812a3SHersen Wu &audio_output.pll_info); 2039ab8812a3SHersen Wu break; 2040ab8812a3SHersen Wu } 2041ab8812a3SHersen Wu } 2042ab8812a3SHersen Wu 2043ab8812a3SHersen Wu /* no HDMI audio is found, try DP audio */ 2044a2b8659dSTony Cheng if (i == dc->res_pool->pipe_count) { 2045a2b8659dSTony Cheng for (i = 0; i < dc->res_pool->pipe_count; i++) { 2046ab8812a3SHersen Wu struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 2047ab8812a3SHersen Wu 2048ab8812a3SHersen Wu if (pipe_ctx->stream == NULL) 2049ab8812a3SHersen Wu continue; 2050ab8812a3SHersen Wu 2051ab8812a3SHersen Wu if (pipe_ctx->top_pipe) 2052ab8812a3SHersen Wu continue; 2053ab8812a3SHersen Wu 2054ab8812a3SHersen Wu if (!dc_is_dp_signal(pipe_ctx->stream->signal)) 2055ab8812a3SHersen Wu continue; 2056ab8812a3SHersen Wu 2057afaacef4SHarry Wentland if (pipe_ctx->stream_res.audio != NULL) { 2058ab8812a3SHersen Wu struct audio_output audio_output; 2059ab8812a3SHersen Wu 2060ab8db3e1SAndrey Grodzovsky build_audio_output(context, pipe_ctx, &audio_output); 2061ab8812a3SHersen Wu 2062afaacef4SHarry Wentland pipe_ctx->stream_res.audio->funcs->wall_dto_setup( 2063afaacef4SHarry Wentland pipe_ctx->stream_res.audio, 2064ab8812a3SHersen Wu pipe_ctx->stream->signal, 2065ab8812a3SHersen Wu &audio_output.crtc_info, 2066ab8812a3SHersen Wu &audio_output.pll_info); 2067ab8812a3SHersen Wu break; 2068ab8812a3SHersen Wu } 2069ab8812a3SHersen Wu } 2070ab8812a3SHersen Wu } 2071ab8812a3SHersen Wu 2072a2b8659dSTony Cheng for (i = 0; i < dc->res_pool->pipe_count; i++) { 2073ab8812a3SHersen Wu struct pipe_ctx *pipe_ctx_old = 2074608ac7bbSJerry Zuo &dc->current_state->res_ctx.pipe_ctx[i]; 2075ab8812a3SHersen Wu struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 2076ab8812a3SHersen Wu 2077ab8812a3SHersen Wu if (pipe_ctx->stream == NULL) 2078ab8812a3SHersen Wu continue; 2079ab8812a3SHersen Wu 2080ab8812a3SHersen Wu if (pipe_ctx->stream == pipe_ctx_old->stream) 2081ab8812a3SHersen Wu continue; 2082ab8812a3SHersen Wu 2083313bf4ffSYongqiang Sun if (pipe_ctx->stream && pipe_ctx_old->stream 2084313bf4ffSYongqiang Sun && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) 2085313bf4ffSYongqiang Sun continue; 2086313bf4ffSYongqiang Sun 2087ab8812a3SHersen Wu if (pipe_ctx->top_pipe) 2088ab8812a3SHersen Wu continue; 2089ab8812a3SHersen Wu 2090afaacef4SHarry Wentland if (context->res_ctx.pipe_ctx[i].stream_res.audio != NULL) { 2091ab8812a3SHersen Wu 20924562236bSHarry Wentland struct audio_output audio_output; 20934562236bSHarry Wentland 2094ab8db3e1SAndrey Grodzovsky build_audio_output(context, pipe_ctx, &audio_output); 20954562236bSHarry Wentland 20964562236bSHarry Wentland if (dc_is_dp_signal(pipe_ctx->stream->signal)) 20978e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( 20988e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc, 2099afaacef4SHarry Wentland pipe_ctx->stream_res.audio->inst, 21004fa086b9SLeo (Sunpeng) Li &pipe_ctx->stream->audio_info); 21014562236bSHarry Wentland else 21028e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup( 21038e9c4c8cSHarry Wentland pipe_ctx->stream_res.stream_enc, 2104afaacef4SHarry Wentland pipe_ctx->stream_res.audio->inst, 21054fa086b9SLeo (Sunpeng) Li &pipe_ctx->stream->audio_info, 21064562236bSHarry Wentland &audio_output.crtc_info); 21074562236bSHarry Wentland 2108afaacef4SHarry Wentland pipe_ctx->stream_res.audio->funcs->az_configure( 2109afaacef4SHarry Wentland pipe_ctx->stream_res.audio, 21104562236bSHarry Wentland pipe_ctx->stream->signal, 21114562236bSHarry Wentland &audio_output.crtc_info, 21124fa086b9SLeo (Sunpeng) Li &pipe_ctx->stream->audio_info); 21134562236bSHarry Wentland } 21144562236bSHarry Wentland 21154562236bSHarry Wentland status = apply_single_controller_ctx_to_hw( 21164562236bSHarry Wentland pipe_ctx, 21174562236bSHarry Wentland context, 21184562236bSHarry Wentland dc); 21194562236bSHarry Wentland 212018f7a1e4SYongqiang Sun if (dc->hwss.power_on_front_end) 212118f7a1e4SYongqiang Sun dc->hwss.power_on_front_end(dc, pipe_ctx, context); 212218f7a1e4SYongqiang Sun 21234562236bSHarry Wentland if (DC_OK != status) 21244562236bSHarry Wentland return status; 21254562236bSHarry Wentland } 21264562236bSHarry Wentland 21276bf52028SHersen Wu /* pplib is notified if disp_num changed */ 2128cf437593SDmytro Laktyushkin dc->hwss.set_bandwidth(dc, context, true); 21294562236bSHarry Wentland 21304562236bSHarry Wentland /* to save power */ 21314562236bSHarry Wentland apply_min_clocks(dc, context, &clocks_state, false); 21324562236bSHarry Wentland 21334562236bSHarry Wentland dcb->funcs->set_scratch_critical_state(dcb, false); 21344562236bSHarry Wentland 21353eab7916SShirish S #if defined(CONFIG_DRM_AMD_DC_FBC) 2136690b5e39SRoman Li if (dc->fbc_compressor) 2137690b5e39SRoman Li enable_fbc(dc, context); 2138690b5e39SRoman Li 2139690b5e39SRoman Li #endif 2140cf437593SDmytro Laktyushkin 21414562236bSHarry Wentland return DC_OK; 21424562236bSHarry Wentland } 21434562236bSHarry Wentland 21444562236bSHarry Wentland /******************************************************************************* 21454562236bSHarry Wentland * Front End programming 21464562236bSHarry Wentland ******************************************************************************/ 21474562236bSHarry Wentland static void set_default_colors(struct pipe_ctx *pipe_ctx) 21484562236bSHarry Wentland { 21494562236bSHarry Wentland struct default_adjustment default_adjust = { 0 }; 21504562236bSHarry Wentland 21514562236bSHarry Wentland default_adjust.force_hw_default = false; 21523be5262eSHarry Wentland if (pipe_ctx->plane_state == NULL) 21534562236bSHarry Wentland default_adjust.in_color_space = COLOR_SPACE_SRGB; 21544562236bSHarry Wentland else 21554562236bSHarry Wentland default_adjust.in_color_space = 21563be5262eSHarry Wentland pipe_ctx->plane_state->color_space; 21574562236bSHarry Wentland if (pipe_ctx->stream == NULL) 21584562236bSHarry Wentland default_adjust.out_color_space = COLOR_SPACE_SRGB; 21594562236bSHarry Wentland else 21604562236bSHarry Wentland default_adjust.out_color_space = 21614fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->output_color_space; 21624562236bSHarry Wentland default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW; 21636702a9acSHarry Wentland default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format; 21644562236bSHarry Wentland 21654562236bSHarry Wentland /* display color depth */ 21664562236bSHarry Wentland default_adjust.color_depth = 21674fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->timing.display_color_depth; 21684562236bSHarry Wentland 21694562236bSHarry Wentland /* Lb color depth */ 21706702a9acSHarry Wentland default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth; 21714562236bSHarry Wentland 217286a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default( 217386a66c4eSHarry Wentland pipe_ctx->plane_res.xfm, &default_adjust); 21744562236bSHarry Wentland } 21754562236bSHarry Wentland 2176b06b7680SLeon Elazar 2177b06b7680SLeon Elazar /******************************************************************************* 2178b06b7680SLeon Elazar * In order to turn on/off specific surface we will program 2179b06b7680SLeon Elazar * Blender + CRTC 2180b06b7680SLeon Elazar * 2181b06b7680SLeon Elazar * In case that we have two surfaces and they have a different visibility 2182b06b7680SLeon Elazar * we can't turn off the CRTC since it will turn off the entire display 2183b06b7680SLeon Elazar * 2184b06b7680SLeon Elazar * |----------------------------------------------- | 2185b06b7680SLeon Elazar * |bottom pipe|curr pipe | | | 2186b06b7680SLeon Elazar * |Surface |Surface | Blender | CRCT | 2187b06b7680SLeon Elazar * |visibility |visibility | Configuration| | 2188b06b7680SLeon Elazar * |------------------------------------------------| 2189b06b7680SLeon Elazar * | off | off | CURRENT_PIPE | blank | 2190b06b7680SLeon Elazar * | off | on | CURRENT_PIPE | unblank | 2191b06b7680SLeon Elazar * | on | off | OTHER_PIPE | unblank | 2192b06b7680SLeon Elazar * | on | on | BLENDING | unblank | 2193b06b7680SLeon Elazar * -------------------------------------------------| 2194b06b7680SLeon Elazar * 2195b06b7680SLeon Elazar ******************************************************************************/ 2196fb3466a4SBhawanpreet Lakha static void program_surface_visibility(const struct dc *dc, 21974562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 21984562236bSHarry Wentland { 21994562236bSHarry Wentland enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE; 2200b06b7680SLeon Elazar bool blank_target = false; 22014562236bSHarry Wentland 22024562236bSHarry Wentland if (pipe_ctx->bottom_pipe) { 2203b06b7680SLeon Elazar 2204b06b7680SLeon Elazar /* For now we are supporting only two pipes */ 2205b06b7680SLeon Elazar ASSERT(pipe_ctx->bottom_pipe->bottom_pipe == NULL); 2206b06b7680SLeon Elazar 22073be5262eSHarry Wentland if (pipe_ctx->bottom_pipe->plane_state->visible) { 22083be5262eSHarry Wentland if (pipe_ctx->plane_state->visible) 22094562236bSHarry Wentland blender_mode = BLND_MODE_BLENDING; 22104562236bSHarry Wentland else 22114562236bSHarry Wentland blender_mode = BLND_MODE_OTHER_PIPE; 2212b06b7680SLeon Elazar 22133be5262eSHarry Wentland } else if (!pipe_ctx->plane_state->visible) 2214b06b7680SLeon Elazar blank_target = true; 2215b06b7680SLeon Elazar 22163be5262eSHarry Wentland } else if (!pipe_ctx->plane_state->visible) 2217b06b7680SLeon Elazar blank_target = true; 2218b06b7680SLeon Elazar 22194562236bSHarry Wentland dce_set_blender_mode(dc->hwseq, pipe_ctx->pipe_idx, blender_mode); 22206b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, blank_target); 2221b06b7680SLeon Elazar 22224562236bSHarry Wentland } 22234562236bSHarry Wentland 22241bf56e62SZeyu Fan static void program_gamut_remap(struct pipe_ctx *pipe_ctx) 22251bf56e62SZeyu Fan { 22261bf56e62SZeyu Fan struct xfm_grph_csc_adjustment adjust; 22271bf56e62SZeyu Fan memset(&adjust, 0, sizeof(adjust)); 22281bf56e62SZeyu Fan adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; 22291bf56e62SZeyu Fan 22301bf56e62SZeyu Fan 22314fa086b9SLeo (Sunpeng) Li if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { 22321bf56e62SZeyu Fan adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; 22331bf56e62SZeyu Fan adjust.temperature_matrix[0] = 22341bf56e62SZeyu Fan pipe_ctx->stream-> 22354fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[0]; 22361bf56e62SZeyu Fan adjust.temperature_matrix[1] = 22371bf56e62SZeyu Fan pipe_ctx->stream-> 22384fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[1]; 22391bf56e62SZeyu Fan adjust.temperature_matrix[2] = 22401bf56e62SZeyu Fan pipe_ctx->stream-> 22414fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[2]; 22421bf56e62SZeyu Fan adjust.temperature_matrix[3] = 22431bf56e62SZeyu Fan pipe_ctx->stream-> 22444fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[4]; 22451bf56e62SZeyu Fan adjust.temperature_matrix[4] = 22461bf56e62SZeyu Fan pipe_ctx->stream-> 22474fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[5]; 22481bf56e62SZeyu Fan adjust.temperature_matrix[5] = 22491bf56e62SZeyu Fan pipe_ctx->stream-> 22504fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[6]; 22511bf56e62SZeyu Fan adjust.temperature_matrix[6] = 22521bf56e62SZeyu Fan pipe_ctx->stream-> 22534fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[8]; 22541bf56e62SZeyu Fan adjust.temperature_matrix[7] = 22551bf56e62SZeyu Fan pipe_ctx->stream-> 22564fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[9]; 22571bf56e62SZeyu Fan adjust.temperature_matrix[8] = 22581bf56e62SZeyu Fan pipe_ctx->stream-> 22594fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[10]; 22601bf56e62SZeyu Fan } 22611bf56e62SZeyu Fan 226286a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); 22631bf56e62SZeyu Fan } 22641bf56e62SZeyu Fan 22654562236bSHarry Wentland /** 22664562236bSHarry Wentland * TODO REMOVE, USE UPDATE INSTEAD 22674562236bSHarry Wentland */ 22684562236bSHarry Wentland static void set_plane_config( 2269fb3466a4SBhawanpreet Lakha const struct dc *dc, 22704562236bSHarry Wentland struct pipe_ctx *pipe_ctx, 22714562236bSHarry Wentland struct resource_context *res_ctx) 22724562236bSHarry Wentland { 227386a66c4eSHarry Wentland struct mem_input *mi = pipe_ctx->plane_res.mi; 22743be5262eSHarry Wentland struct dc_plane_state *plane_state = pipe_ctx->plane_state; 22754562236bSHarry Wentland struct xfm_grph_csc_adjustment adjust; 22764562236bSHarry Wentland struct out_csc_color_matrix tbl_entry; 22774562236bSHarry Wentland unsigned int i; 22784562236bSHarry Wentland 22794562236bSHarry Wentland memset(&adjust, 0, sizeof(adjust)); 22804562236bSHarry Wentland memset(&tbl_entry, 0, sizeof(tbl_entry)); 22814562236bSHarry Wentland adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; 22824562236bSHarry Wentland 22834562236bSHarry Wentland dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true); 22844562236bSHarry Wentland 22854562236bSHarry Wentland set_default_colors(pipe_ctx); 228656ef6ed9SAnthony Koo if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { 22874562236bSHarry Wentland tbl_entry.color_space = 22884fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->output_color_space; 22894562236bSHarry Wentland 22904562236bSHarry Wentland for (i = 0; i < 12; i++) 22914562236bSHarry Wentland tbl_entry.regval[i] = 22924fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->csc_color_matrix.matrix[i]; 22934562236bSHarry Wentland 229486a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment 229586a66c4eSHarry Wentland (pipe_ctx->plane_res.xfm, &tbl_entry); 22964562236bSHarry Wentland } 22974562236bSHarry Wentland 22984fa086b9SLeo (Sunpeng) Li if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { 22994562236bSHarry Wentland adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; 23004562236bSHarry Wentland adjust.temperature_matrix[0] = 23014562236bSHarry Wentland pipe_ctx->stream-> 23024fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[0]; 23034562236bSHarry Wentland adjust.temperature_matrix[1] = 23044562236bSHarry Wentland pipe_ctx->stream-> 23054fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[1]; 23064562236bSHarry Wentland adjust.temperature_matrix[2] = 23074562236bSHarry Wentland pipe_ctx->stream-> 23084fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[2]; 23094562236bSHarry Wentland adjust.temperature_matrix[3] = 23104562236bSHarry Wentland pipe_ctx->stream-> 23114fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[4]; 23124562236bSHarry Wentland adjust.temperature_matrix[4] = 23134562236bSHarry Wentland pipe_ctx->stream-> 23144fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[5]; 23154562236bSHarry Wentland adjust.temperature_matrix[5] = 23164562236bSHarry Wentland pipe_ctx->stream-> 23174fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[6]; 23184562236bSHarry Wentland adjust.temperature_matrix[6] = 23194562236bSHarry Wentland pipe_ctx->stream-> 23204fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[8]; 23214562236bSHarry Wentland adjust.temperature_matrix[7] = 23224562236bSHarry Wentland pipe_ctx->stream-> 23234fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[9]; 23244562236bSHarry Wentland adjust.temperature_matrix[8] = 23254562236bSHarry Wentland pipe_ctx->stream-> 23264fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[10]; 23274562236bSHarry Wentland } 23284562236bSHarry Wentland 232986a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); 23304562236bSHarry Wentland 23316702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; 23324562236bSHarry Wentland program_scaler(dc, pipe_ctx); 23334562236bSHarry Wentland 2334b06b7680SLeon Elazar program_surface_visibility(dc, pipe_ctx); 23354562236bSHarry Wentland 23364562236bSHarry Wentland mi->funcs->mem_input_program_surface_config( 23374562236bSHarry Wentland mi, 23383be5262eSHarry Wentland plane_state->format, 23393be5262eSHarry Wentland &plane_state->tiling_info, 23403be5262eSHarry Wentland &plane_state->plane_size, 23413be5262eSHarry Wentland plane_state->rotation, 23424562236bSHarry Wentland NULL, 23434b28b76bSDmytro Laktyushkin false); 23444b28b76bSDmytro Laktyushkin if (mi->funcs->set_blank) 23453be5262eSHarry Wentland mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible); 23464562236bSHarry Wentland 2347fb3466a4SBhawanpreet Lakha if (dc->config.gpu_vm_support) 23484562236bSHarry Wentland mi->funcs->mem_input_program_pte_vm( 234986a66c4eSHarry Wentland pipe_ctx->plane_res.mi, 23503be5262eSHarry Wentland plane_state->format, 23513be5262eSHarry Wentland &plane_state->tiling_info, 23523be5262eSHarry Wentland plane_state->rotation); 23534562236bSHarry Wentland } 23544562236bSHarry Wentland 2355fb3466a4SBhawanpreet Lakha static void update_plane_addr(const struct dc *dc, 23564562236bSHarry Wentland struct pipe_ctx *pipe_ctx) 23574562236bSHarry Wentland { 23583be5262eSHarry Wentland struct dc_plane_state *plane_state = pipe_ctx->plane_state; 23594562236bSHarry Wentland 23603be5262eSHarry Wentland if (plane_state == NULL) 23614562236bSHarry Wentland return; 23624562236bSHarry Wentland 236386a66c4eSHarry Wentland pipe_ctx->plane_res.mi->funcs->mem_input_program_surface_flip_and_addr( 236486a66c4eSHarry Wentland pipe_ctx->plane_res.mi, 23653be5262eSHarry Wentland &plane_state->address, 23663be5262eSHarry Wentland plane_state->flip_immediate); 23674562236bSHarry Wentland 23683be5262eSHarry Wentland plane_state->status.requested_address = plane_state->address; 23694562236bSHarry Wentland } 23704562236bSHarry Wentland 23714562236bSHarry Wentland void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) 23724562236bSHarry Wentland { 23733be5262eSHarry Wentland struct dc_plane_state *plane_state = pipe_ctx->plane_state; 23744562236bSHarry Wentland 23753be5262eSHarry Wentland if (plane_state == NULL) 23764562236bSHarry Wentland return; 23774562236bSHarry Wentland 23783be5262eSHarry Wentland plane_state->status.is_flip_pending = 237986a66c4eSHarry Wentland pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending( 238086a66c4eSHarry Wentland pipe_ctx->plane_res.mi); 23814562236bSHarry Wentland 23823be5262eSHarry Wentland if (plane_state->status.is_flip_pending && !plane_state->visible) 238386a66c4eSHarry Wentland pipe_ctx->plane_res.mi->current_address = pipe_ctx->plane_res.mi->request_address; 23844562236bSHarry Wentland 238586a66c4eSHarry Wentland plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address; 238686a66c4eSHarry Wentland if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && 23876b670fa9SHarry Wentland pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye) { 23883be5262eSHarry Wentland plane_state->status.is_right_eye =\ 23896b670fa9SHarry Wentland !pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg); 23907f5c22d1SVitaly Prosyak } 23914562236bSHarry Wentland } 23924562236bSHarry Wentland 2393fb3466a4SBhawanpreet Lakha void dce110_power_down(struct dc *dc) 23944562236bSHarry Wentland { 23954562236bSHarry Wentland power_down_all_hw_blocks(dc); 23964562236bSHarry Wentland disable_vga_and_power_gate_all_controllers(dc); 23974562236bSHarry Wentland } 23984562236bSHarry Wentland 23994562236bSHarry Wentland static bool wait_for_reset_trigger_to_occur( 24004562236bSHarry Wentland struct dc_context *dc_ctx, 24014562236bSHarry Wentland struct timing_generator *tg) 24024562236bSHarry Wentland { 24034562236bSHarry Wentland bool rc = false; 24044562236bSHarry Wentland 24054562236bSHarry Wentland /* To avoid endless loop we wait at most 24064562236bSHarry Wentland * frames_to_wait_on_triggered_reset frames for the reset to occur. */ 24074562236bSHarry Wentland const uint32_t frames_to_wait_on_triggered_reset = 10; 24084562236bSHarry Wentland uint32_t i; 24094562236bSHarry Wentland 24104562236bSHarry Wentland for (i = 0; i < frames_to_wait_on_triggered_reset; i++) { 24114562236bSHarry Wentland 24124562236bSHarry Wentland if (!tg->funcs->is_counter_moving(tg)) { 24134562236bSHarry Wentland DC_ERROR("TG counter is not moving!\n"); 24144562236bSHarry Wentland break; 24154562236bSHarry Wentland } 24164562236bSHarry Wentland 24174562236bSHarry Wentland if (tg->funcs->did_triggered_reset_occur(tg)) { 24184562236bSHarry Wentland rc = true; 24194562236bSHarry Wentland /* usually occurs at i=1 */ 24204562236bSHarry Wentland DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n", 24214562236bSHarry Wentland i); 24224562236bSHarry Wentland break; 24234562236bSHarry Wentland } 24244562236bSHarry Wentland 24254562236bSHarry Wentland /* Wait for one frame. */ 24264562236bSHarry Wentland tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE); 24274562236bSHarry Wentland tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK); 24284562236bSHarry Wentland } 24294562236bSHarry Wentland 24304562236bSHarry Wentland if (false == rc) 24314562236bSHarry Wentland DC_ERROR("GSL: Timeout on reset trigger!\n"); 24324562236bSHarry Wentland 24334562236bSHarry Wentland return rc; 24344562236bSHarry Wentland } 24354562236bSHarry Wentland 24364562236bSHarry Wentland /* Enable timing synchronization for a group of Timing Generators. */ 24374562236bSHarry Wentland static void dce110_enable_timing_synchronization( 2438fb3466a4SBhawanpreet Lakha struct dc *dc, 24394562236bSHarry Wentland int group_index, 24404562236bSHarry Wentland int group_size, 24414562236bSHarry Wentland struct pipe_ctx *grouped_pipes[]) 24424562236bSHarry Wentland { 24434562236bSHarry Wentland struct dc_context *dc_ctx = dc->ctx; 24444562236bSHarry Wentland struct dcp_gsl_params gsl_params = { 0 }; 24454562236bSHarry Wentland int i; 24464562236bSHarry Wentland 24474562236bSHarry Wentland DC_SYNC_INFO("GSL: Setting-up...\n"); 24484562236bSHarry Wentland 24494562236bSHarry Wentland /* Designate a single TG in the group as a master. 24504562236bSHarry Wentland * Since HW doesn't care which one, we always assign 24514562236bSHarry Wentland * the 1st one in the group. */ 24524562236bSHarry Wentland gsl_params.gsl_group = 0; 24536b670fa9SHarry Wentland gsl_params.gsl_master = grouped_pipes[0]->stream_res.tg->inst; 24544562236bSHarry Wentland 24554562236bSHarry Wentland for (i = 0; i < group_size; i++) 24566b670fa9SHarry Wentland grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock( 24576b670fa9SHarry Wentland grouped_pipes[i]->stream_res.tg, &gsl_params); 24584562236bSHarry Wentland 24594562236bSHarry Wentland /* Reset slave controllers on master VSync */ 24604562236bSHarry Wentland DC_SYNC_INFO("GSL: enabling trigger-reset\n"); 24614562236bSHarry Wentland 24624562236bSHarry Wentland for (i = 1 /* skip the master */; i < group_size; i++) 24636b670fa9SHarry Wentland grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger( 2464fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg, 2465fa2123dbSMikita Lipski gsl_params.gsl_group); 24664562236bSHarry Wentland 24674562236bSHarry Wentland for (i = 1 /* skip the master */; i < group_size; i++) { 24684562236bSHarry Wentland DC_SYNC_INFO("GSL: waiting for reset to occur.\n"); 24696b670fa9SHarry Wentland wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg); 2470fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger( 2471fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg); 24724562236bSHarry Wentland } 24734562236bSHarry Wentland 24744562236bSHarry Wentland /* GSL Vblank synchronization is a one time sync mechanism, assumption 24754562236bSHarry Wentland * is that the sync'ed displays will not drift out of sync over time*/ 24764562236bSHarry Wentland DC_SYNC_INFO("GSL: Restoring register states.\n"); 24774562236bSHarry Wentland for (i = 0; i < group_size; i++) 24786b670fa9SHarry Wentland grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg); 24794562236bSHarry Wentland 24804562236bSHarry Wentland DC_SYNC_INFO("GSL: Set-up complete.\n"); 24814562236bSHarry Wentland } 24824562236bSHarry Wentland 2483fa2123dbSMikita Lipski static void dce110_enable_per_frame_crtc_position_reset( 2484fa2123dbSMikita Lipski struct dc *dc, 2485fa2123dbSMikita Lipski int group_size, 2486fa2123dbSMikita Lipski struct pipe_ctx *grouped_pipes[]) 2487fa2123dbSMikita Lipski { 2488fa2123dbSMikita Lipski struct dc_context *dc_ctx = dc->ctx; 2489fa2123dbSMikita Lipski struct dcp_gsl_params gsl_params = { 0 }; 2490fa2123dbSMikita Lipski int i; 2491fa2123dbSMikita Lipski 2492fa2123dbSMikita Lipski gsl_params.gsl_group = 0; 2493fa2123dbSMikita Lipski gsl_params.gsl_master = grouped_pipes[0]->stream->triggered_crtc_reset.event_source->status.primary_otg_inst; 2494fa2123dbSMikita Lipski 2495fa2123dbSMikita Lipski for (i = 0; i < group_size; i++) 2496fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock( 2497fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg, &gsl_params); 2498fa2123dbSMikita Lipski 2499fa2123dbSMikita Lipski DC_SYNC_INFO("GSL: enabling trigger-reset\n"); 2500fa2123dbSMikita Lipski 2501fa2123dbSMikita Lipski for (i = 1; i < group_size; i++) 2502fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset( 2503fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg, 2504fa2123dbSMikita Lipski gsl_params.gsl_master, 2505fa2123dbSMikita Lipski &grouped_pipes[i]->stream->triggered_crtc_reset); 2506fa2123dbSMikita Lipski 2507fa2123dbSMikita Lipski DC_SYNC_INFO("GSL: waiting for reset to occur.\n"); 2508fa2123dbSMikita Lipski for (i = 1; i < group_size; i++) 2509fa2123dbSMikita Lipski wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg); 2510fa2123dbSMikita Lipski 2511fa2123dbSMikita Lipski for (i = 0; i < group_size; i++) 2512fa2123dbSMikita Lipski grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg); 2513fa2123dbSMikita Lipski 2514fa2123dbSMikita Lipski } 2515fa2123dbSMikita Lipski 2516fb3466a4SBhawanpreet Lakha static void init_hw(struct dc *dc) 25174562236bSHarry Wentland { 25184562236bSHarry Wentland int i; 25194562236bSHarry Wentland struct dc_bios *bp; 25204562236bSHarry Wentland struct transform *xfm; 25215e7773a2SAnthony Koo struct abm *abm; 25224562236bSHarry Wentland 25234562236bSHarry Wentland bp = dc->ctx->dc_bios; 25244562236bSHarry Wentland for (i = 0; i < dc->res_pool->pipe_count; i++) { 25254562236bSHarry Wentland xfm = dc->res_pool->transforms[i]; 25264562236bSHarry Wentland xfm->funcs->transform_reset(xfm); 25274562236bSHarry Wentland 25284562236bSHarry Wentland dc->hwss.enable_display_power_gating( 25294562236bSHarry Wentland dc, i, bp, 25304562236bSHarry Wentland PIPE_GATING_CONTROL_INIT); 25314562236bSHarry Wentland dc->hwss.enable_display_power_gating( 25324562236bSHarry Wentland dc, i, bp, 25334562236bSHarry Wentland PIPE_GATING_CONTROL_DISABLE); 25344562236bSHarry Wentland dc->hwss.enable_display_pipe_clock_gating( 25354562236bSHarry Wentland dc->ctx, 25364562236bSHarry Wentland true); 25374562236bSHarry Wentland } 25384562236bSHarry Wentland 2539e166ad43SJulia Lawall dce_clock_gating_power_up(dc->hwseq, false); 25404562236bSHarry Wentland /***************************************/ 25414562236bSHarry Wentland 25424562236bSHarry Wentland for (i = 0; i < dc->link_count; i++) { 25434562236bSHarry Wentland /****************************************/ 25444562236bSHarry Wentland /* Power up AND update implementation according to the 25454562236bSHarry Wentland * required signal (which may be different from the 25464562236bSHarry Wentland * default signal on connector). */ 2547d0778ebfSHarry Wentland struct dc_link *link = dc->links[i]; 2548069d418fSAndrew Jiang 2549069d418fSAndrew Jiang if (link->link_enc->connector.id == CONNECTOR_ID_EDP) 2550069d418fSAndrew Jiang dc->hwss.edp_power_control(link, true); 2551069d418fSAndrew Jiang 25524562236bSHarry Wentland link->link_enc->funcs->hw_init(link->link_enc); 25534562236bSHarry Wentland } 25544562236bSHarry Wentland 25554562236bSHarry Wentland for (i = 0; i < dc->res_pool->pipe_count; i++) { 25564562236bSHarry Wentland struct timing_generator *tg = dc->res_pool->timing_generators[i]; 25574562236bSHarry Wentland 25584562236bSHarry Wentland tg->funcs->disable_vga(tg); 25594562236bSHarry Wentland 25604562236bSHarry Wentland /* Blank controller using driver code instead of 25614562236bSHarry Wentland * command table. */ 25624562236bSHarry Wentland tg->funcs->set_blank(tg, true); 25634b5e7d62SHersen Wu hwss_wait_for_blank_complete(tg); 25644562236bSHarry Wentland } 25654562236bSHarry Wentland 25664562236bSHarry Wentland for (i = 0; i < dc->res_pool->audio_count; i++) { 25674562236bSHarry Wentland struct audio *audio = dc->res_pool->audios[i]; 25684562236bSHarry Wentland audio->funcs->hw_init(audio); 25694562236bSHarry Wentland } 25705e7773a2SAnthony Koo 25715e7773a2SAnthony Koo abm = dc->res_pool->abm; 25726728b30cSAnthony Koo if (abm != NULL) { 25736728b30cSAnthony Koo abm->funcs->init_backlight(abm); 25745e7773a2SAnthony Koo abm->funcs->abm_init(abm); 25754562236bSHarry Wentland } 25763eab7916SShirish S #if defined(CONFIG_DRM_AMD_DC_FBC) 25772f3bfb27SRoman Li if (dc->fbc_compressor) 25781663ae1cSBhawanpreet Lakha dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor); 25791663ae1cSBhawanpreet Lakha #endif 2580690b5e39SRoman Li 25816728b30cSAnthony Koo } 25824562236bSHarry Wentland 258328f72454SJordan Lazare void dce110_fill_display_configs( 2584608ac7bbSJerry Zuo const struct dc_state *context, 2585cf437593SDmytro Laktyushkin struct dm_pp_display_configuration *pp_display_cfg) 25864562236bSHarry Wentland { 2587cf437593SDmytro Laktyushkin int j; 2588cf437593SDmytro Laktyushkin int num_cfgs = 0; 2589cf437593SDmytro Laktyushkin 2590cf437593SDmytro Laktyushkin for (j = 0; j < context->stream_count; j++) { 2591cf437593SDmytro Laktyushkin int k; 2592cf437593SDmytro Laktyushkin 25930971c40eSHarry Wentland const struct dc_stream_state *stream = context->streams[j]; 2594cf437593SDmytro Laktyushkin struct dm_pp_single_disp_config *cfg = 2595cf437593SDmytro Laktyushkin &pp_display_cfg->disp_configs[num_cfgs]; 2596cf437593SDmytro Laktyushkin const struct pipe_ctx *pipe_ctx = NULL; 2597cf437593SDmytro Laktyushkin 2598cf437593SDmytro Laktyushkin for (k = 0; k < MAX_PIPES; k++) 2599cf437593SDmytro Laktyushkin if (stream == context->res_ctx.pipe_ctx[k].stream) { 2600cf437593SDmytro Laktyushkin pipe_ctx = &context->res_ctx.pipe_ctx[k]; 2601cf437593SDmytro Laktyushkin break; 26024562236bSHarry Wentland } 26034562236bSHarry Wentland 2604cf437593SDmytro Laktyushkin ASSERT(pipe_ctx != NULL); 2605cf437593SDmytro Laktyushkin 2606cf437593SDmytro Laktyushkin num_cfgs++; 2607cf437593SDmytro Laktyushkin cfg->signal = pipe_ctx->stream->signal; 2608cf437593SDmytro Laktyushkin cfg->pipe_idx = pipe_ctx->pipe_idx; 26094fa086b9SLeo (Sunpeng) Li cfg->src_height = stream->src.height; 26104fa086b9SLeo (Sunpeng) Li cfg->src_width = stream->src.width; 2611cf437593SDmytro Laktyushkin cfg->ddi_channel_mapping = 2612cf437593SDmytro Laktyushkin stream->sink->link->ddi_channel_mapping.raw; 2613cf437593SDmytro Laktyushkin cfg->transmitter = 2614cf437593SDmytro Laktyushkin stream->sink->link->link_enc->transmitter; 2615cf437593SDmytro Laktyushkin cfg->link_settings.lane_count = 2616d0778ebfSHarry Wentland stream->sink->link->cur_link_settings.lane_count; 2617cf437593SDmytro Laktyushkin cfg->link_settings.link_rate = 2618d0778ebfSHarry Wentland stream->sink->link->cur_link_settings.link_rate; 2619cf437593SDmytro Laktyushkin cfg->link_settings.link_spread = 2620d0778ebfSHarry Wentland stream->sink->link->cur_link_settings.link_spread; 2621cf437593SDmytro Laktyushkin cfg->sym_clock = stream->phy_pix_clk; 2622cf437593SDmytro Laktyushkin /* Round v_refresh*/ 26234fa086b9SLeo (Sunpeng) Li cfg->v_refresh = stream->timing.pix_clk_khz * 1000; 26244fa086b9SLeo (Sunpeng) Li cfg->v_refresh /= stream->timing.h_total; 26254fa086b9SLeo (Sunpeng) Li cfg->v_refresh = (cfg->v_refresh + stream->timing.v_total / 2) 26264fa086b9SLeo (Sunpeng) Li / stream->timing.v_total; 2627cf437593SDmytro Laktyushkin } 2628cf437593SDmytro Laktyushkin 2629cf437593SDmytro Laktyushkin pp_display_cfg->display_count = num_cfgs; 2630cf437593SDmytro Laktyushkin } 2631cf437593SDmytro Laktyushkin 2632608ac7bbSJerry Zuo uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context) 2633cf437593SDmytro Laktyushkin { 2634cf437593SDmytro Laktyushkin uint8_t j; 2635cf437593SDmytro Laktyushkin uint32_t min_vertical_blank_time = -1; 2636cf437593SDmytro Laktyushkin 2637cf437593SDmytro Laktyushkin for (j = 0; j < context->stream_count; j++) { 26380971c40eSHarry Wentland struct dc_stream_state *stream = context->streams[j]; 2639cf437593SDmytro Laktyushkin uint32_t vertical_blank_in_pixels = 0; 2640cf437593SDmytro Laktyushkin uint32_t vertical_blank_time = 0; 2641cf437593SDmytro Laktyushkin 2642cf437593SDmytro Laktyushkin vertical_blank_in_pixels = stream->timing.h_total * 2643cf437593SDmytro Laktyushkin (stream->timing.v_total 2644cf437593SDmytro Laktyushkin - stream->timing.v_addressable); 2645cf437593SDmytro Laktyushkin 2646cf437593SDmytro Laktyushkin vertical_blank_time = vertical_blank_in_pixels 2647cf437593SDmytro Laktyushkin * 1000 / stream->timing.pix_clk_khz; 2648cf437593SDmytro Laktyushkin 2649cf437593SDmytro Laktyushkin if (min_vertical_blank_time > vertical_blank_time) 2650cf437593SDmytro Laktyushkin min_vertical_blank_time = vertical_blank_time; 2651cf437593SDmytro Laktyushkin } 2652cf437593SDmytro Laktyushkin 2653cf437593SDmytro Laktyushkin return min_vertical_blank_time; 2654cf437593SDmytro Laktyushkin } 2655cf437593SDmytro Laktyushkin 2656cf437593SDmytro Laktyushkin static int determine_sclk_from_bounding_box( 2657fb3466a4SBhawanpreet Lakha const struct dc *dc, 2658cf437593SDmytro Laktyushkin int required_sclk) 26594562236bSHarry Wentland { 26604562236bSHarry Wentland int i; 26614562236bSHarry Wentland 2662cf437593SDmytro Laktyushkin /* 2663cf437593SDmytro Laktyushkin * Some asics do not give us sclk levels, so we just report the actual 2664cf437593SDmytro Laktyushkin * required sclk 2665cf437593SDmytro Laktyushkin */ 2666cf437593SDmytro Laktyushkin if (dc->sclk_lvls.num_levels == 0) 2667cf437593SDmytro Laktyushkin return required_sclk; 26684562236bSHarry Wentland 2669cf437593SDmytro Laktyushkin for (i = 0; i < dc->sclk_lvls.num_levels; i++) { 2670cf437593SDmytro Laktyushkin if (dc->sclk_lvls.clocks_in_khz[i] >= required_sclk) 2671cf437593SDmytro Laktyushkin return dc->sclk_lvls.clocks_in_khz[i]; 2672cf437593SDmytro Laktyushkin } 2673cf437593SDmytro Laktyushkin /* 2674cf437593SDmytro Laktyushkin * even maximum level could not satisfy requirement, this 2675cf437593SDmytro Laktyushkin * is unexpected at this stage, should have been caught at 2676cf437593SDmytro Laktyushkin * validation time 2677cf437593SDmytro Laktyushkin */ 2678cf437593SDmytro Laktyushkin ASSERT(0); 2679cf437593SDmytro Laktyushkin return dc->sclk_lvls.clocks_in_khz[dc->sclk_lvls.num_levels - 1]; 26804562236bSHarry Wentland } 26814562236bSHarry Wentland 2682cf437593SDmytro Laktyushkin static void pplib_apply_display_requirements( 2683fb3466a4SBhawanpreet Lakha struct dc *dc, 2684608ac7bbSJerry Zuo struct dc_state *context) 2685cf437593SDmytro Laktyushkin { 2686cf437593SDmytro Laktyushkin struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; 2687cf437593SDmytro Laktyushkin 2688cf437593SDmytro Laktyushkin pp_display_cfg->all_displays_in_sync = 26899037d802SDmytro Laktyushkin context->bw.dce.all_displays_in_sync; 2690cf437593SDmytro Laktyushkin pp_display_cfg->nb_pstate_switch_disable = 26919037d802SDmytro Laktyushkin context->bw.dce.nbp_state_change_enable == false; 2692cf437593SDmytro Laktyushkin pp_display_cfg->cpu_cc6_disable = 26939037d802SDmytro Laktyushkin context->bw.dce.cpuc_state_change_enable == false; 2694cf437593SDmytro Laktyushkin pp_display_cfg->cpu_pstate_disable = 26959037d802SDmytro Laktyushkin context->bw.dce.cpup_state_change_enable == false; 2696cf437593SDmytro Laktyushkin pp_display_cfg->cpu_pstate_separation_time = 26979037d802SDmytro Laktyushkin context->bw.dce.blackout_recovery_time_us; 2698cf437593SDmytro Laktyushkin 26999037d802SDmytro Laktyushkin pp_display_cfg->min_memory_clock_khz = context->bw.dce.yclk_khz 2700cf437593SDmytro Laktyushkin / MEMORY_TYPE_MULTIPLIER; 2701cf437593SDmytro Laktyushkin 2702cf437593SDmytro Laktyushkin pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box( 2703cf437593SDmytro Laktyushkin dc, 27049037d802SDmytro Laktyushkin context->bw.dce.sclk_khz); 2705cf437593SDmytro Laktyushkin 2706cf437593SDmytro Laktyushkin pp_display_cfg->min_engine_clock_deep_sleep_khz 27079037d802SDmytro Laktyushkin = context->bw.dce.sclk_deep_sleep_khz; 2708cf437593SDmytro Laktyushkin 2709cf437593SDmytro Laktyushkin pp_display_cfg->avail_mclk_switch_time_us = 271028f72454SJordan Lazare dce110_get_min_vblank_time_us(context); 2711cf437593SDmytro Laktyushkin /* TODO: dce11.2*/ 2712cf437593SDmytro Laktyushkin pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; 2713cf437593SDmytro Laktyushkin 27149037d802SDmytro Laktyushkin pp_display_cfg->disp_clk_khz = context->bw.dce.dispclk_khz; 2715cf437593SDmytro Laktyushkin 271628f72454SJordan Lazare dce110_fill_display_configs(context, pp_display_cfg); 2717cf437593SDmytro Laktyushkin 2718cf437593SDmytro Laktyushkin /* TODO: is this still applicable?*/ 2719cf437593SDmytro Laktyushkin if (pp_display_cfg->display_count == 1) { 2720cf437593SDmytro Laktyushkin const struct dc_crtc_timing *timing = 27214fa086b9SLeo (Sunpeng) Li &context->streams[0]->timing; 2722cf437593SDmytro Laktyushkin 2723cf437593SDmytro Laktyushkin pp_display_cfg->crtc_index = 2724cf437593SDmytro Laktyushkin pp_display_cfg->disp_configs[0].pipe_idx; 2725cf437593SDmytro Laktyushkin pp_display_cfg->line_time_in_us = timing->h_total * 1000 2726cf437593SDmytro Laktyushkin / timing->pix_clk_khz; 2727cf437593SDmytro Laktyushkin } 2728cf437593SDmytro Laktyushkin 2729cf437593SDmytro Laktyushkin if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof( 2730cf437593SDmytro Laktyushkin struct dm_pp_display_configuration)) != 0) 2731cf437593SDmytro Laktyushkin dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); 2732cf437593SDmytro Laktyushkin 2733cf437593SDmytro Laktyushkin dc->prev_display_config = *pp_display_cfg; 2734cf437593SDmytro Laktyushkin } 2735cf437593SDmytro Laktyushkin 2736cf437593SDmytro Laktyushkin static void dce110_set_bandwidth( 2737fb3466a4SBhawanpreet Lakha struct dc *dc, 2738608ac7bbSJerry Zuo struct dc_state *context, 2739cf437593SDmytro Laktyushkin bool decrease_allowed) 2740cf437593SDmytro Laktyushkin { 27412180e7ccSDmytro Laktyushkin dce110_set_displaymarks(dc, context); 2742cf437593SDmytro Laktyushkin 2743608ac7bbSJerry Zuo if (decrease_allowed || context->bw.dce.dispclk_khz > dc->current_state->bw.dce.dispclk_khz) { 2744a2b8659dSTony Cheng dc->res_pool->display_clock->funcs->set_clock( 2745a2b8659dSTony Cheng dc->res_pool->display_clock, 27469037d802SDmytro Laktyushkin context->bw.dce.dispclk_khz * 115 / 100); 2747608ac7bbSJerry Zuo dc->current_state->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz; 2748cf437593SDmytro Laktyushkin } 2749cf437593SDmytro Laktyushkin 2750cf437593SDmytro Laktyushkin pplib_apply_display_requirements(dc, context); 27514562236bSHarry Wentland } 27524562236bSHarry Wentland 27534562236bSHarry Wentland static void dce110_program_front_end_for_pipe( 2754fb3466a4SBhawanpreet Lakha struct dc *dc, struct pipe_ctx *pipe_ctx) 27554562236bSHarry Wentland { 275686a66c4eSHarry Wentland struct mem_input *mi = pipe_ctx->plane_res.mi; 27574562236bSHarry Wentland struct pipe_ctx *old_pipe = NULL; 27583be5262eSHarry Wentland struct dc_plane_state *plane_state = pipe_ctx->plane_state; 27594562236bSHarry Wentland struct xfm_grph_csc_adjustment adjust; 27604562236bSHarry Wentland struct out_csc_color_matrix tbl_entry; 2761067c878aSYongqiang Sun struct pipe_ctx *cur_pipe_ctx = 2762067c878aSYongqiang Sun &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; 27634562236bSHarry Wentland unsigned int i; 27644562236bSHarry Wentland 27654562236bSHarry Wentland memset(&tbl_entry, 0, sizeof(tbl_entry)); 27664562236bSHarry Wentland 2767608ac7bbSJerry Zuo if (dc->current_state) 2768608ac7bbSJerry Zuo old_pipe = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; 27694562236bSHarry Wentland 27704562236bSHarry Wentland memset(&adjust, 0, sizeof(adjust)); 27714562236bSHarry Wentland adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; 27724562236bSHarry Wentland 27734562236bSHarry Wentland dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true); 27744562236bSHarry Wentland 27754562236bSHarry Wentland set_default_colors(pipe_ctx); 27764fa086b9SLeo (Sunpeng) Li if (pipe_ctx->stream->csc_color_matrix.enable_adjustment 27774562236bSHarry Wentland == true) { 27784562236bSHarry Wentland tbl_entry.color_space = 27794fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->output_color_space; 27804562236bSHarry Wentland 27814562236bSHarry Wentland for (i = 0; i < 12; i++) 27824562236bSHarry Wentland tbl_entry.regval[i] = 27834fa086b9SLeo (Sunpeng) Li pipe_ctx->stream->csc_color_matrix.matrix[i]; 27844562236bSHarry Wentland 278586a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment 278686a66c4eSHarry Wentland (pipe_ctx->plane_res.xfm, &tbl_entry); 27874562236bSHarry Wentland } 27884562236bSHarry Wentland 27894fa086b9SLeo (Sunpeng) Li if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { 27904562236bSHarry Wentland adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; 27914562236bSHarry Wentland adjust.temperature_matrix[0] = 27924562236bSHarry Wentland pipe_ctx->stream-> 27934fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[0]; 27944562236bSHarry Wentland adjust.temperature_matrix[1] = 27954562236bSHarry Wentland pipe_ctx->stream-> 27964fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[1]; 27974562236bSHarry Wentland adjust.temperature_matrix[2] = 27984562236bSHarry Wentland pipe_ctx->stream-> 27994fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[2]; 28004562236bSHarry Wentland adjust.temperature_matrix[3] = 28014562236bSHarry Wentland pipe_ctx->stream-> 28024fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[4]; 28034562236bSHarry Wentland adjust.temperature_matrix[4] = 28044562236bSHarry Wentland pipe_ctx->stream-> 28054fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[5]; 28064562236bSHarry Wentland adjust.temperature_matrix[5] = 28074562236bSHarry Wentland pipe_ctx->stream-> 28084fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[6]; 28094562236bSHarry Wentland adjust.temperature_matrix[6] = 28104562236bSHarry Wentland pipe_ctx->stream-> 28114fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[8]; 28124562236bSHarry Wentland adjust.temperature_matrix[7] = 28134562236bSHarry Wentland pipe_ctx->stream-> 28144fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[9]; 28154562236bSHarry Wentland adjust.temperature_matrix[8] = 28164562236bSHarry Wentland pipe_ctx->stream-> 28174fa086b9SLeo (Sunpeng) Li gamut_remap_matrix.matrix[10]; 28184562236bSHarry Wentland } 28194562236bSHarry Wentland 282086a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); 28214562236bSHarry Wentland 28226702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; 2823c1473558SAndrey Grodzovsky 28244562236bSHarry Wentland program_scaler(dc, pipe_ctx); 28254562236bSHarry Wentland 28263eab7916SShirish S #if defined(CONFIG_DRM_AMD_DC_FBC) 2827e008b0bcSRoman Li if (dc->fbc_compressor && old_pipe->stream) { 2828e008b0bcSRoman Li if (plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) 2829e008b0bcSRoman Li dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); 2830e008b0bcSRoman Li else 2831e008b0bcSRoman Li enable_fbc(dc, dc->current_state); 2832e008b0bcSRoman Li } 2833e008b0bcSRoman Li #endif 2834e008b0bcSRoman Li 28354562236bSHarry Wentland mi->funcs->mem_input_program_surface_config( 28364562236bSHarry Wentland mi, 28373be5262eSHarry Wentland plane_state->format, 28383be5262eSHarry Wentland &plane_state->tiling_info, 28393be5262eSHarry Wentland &plane_state->plane_size, 28403be5262eSHarry Wentland plane_state->rotation, 2841624d7c47SYongqiang Sun NULL, 28424b28b76bSDmytro Laktyushkin false); 28434b28b76bSDmytro Laktyushkin if (mi->funcs->set_blank) 28443be5262eSHarry Wentland mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible); 28454562236bSHarry Wentland 2846fb3466a4SBhawanpreet Lakha if (dc->config.gpu_vm_support) 28474562236bSHarry Wentland mi->funcs->mem_input_program_pte_vm( 284886a66c4eSHarry Wentland pipe_ctx->plane_res.mi, 28493be5262eSHarry Wentland plane_state->format, 28503be5262eSHarry Wentland &plane_state->tiling_info, 28513be5262eSHarry Wentland plane_state->rotation); 28524562236bSHarry Wentland 2853067c878aSYongqiang Sun /* Moved programming gamma from dc to hwss */ 2854067c878aSYongqiang Sun if (cur_pipe_ctx->plane_state != pipe_ctx->plane_state) { 2855067c878aSYongqiang Sun dc->hwss.set_input_transfer_func( 2856067c878aSYongqiang Sun pipe_ctx, pipe_ctx->plane_state); 2857067c878aSYongqiang Sun dc->hwss.set_output_transfer_func( 2858067c878aSYongqiang Sun pipe_ctx, pipe_ctx->stream); 2859067c878aSYongqiang Sun } 2860067c878aSYongqiang Sun 28614562236bSHarry Wentland dm_logger_write(dc->ctx->logger, LOG_SURFACE, 28624562236bSHarry Wentland "Pipe:%d 0x%x: addr hi:0x%x, " 28634562236bSHarry Wentland "addr low:0x%x, " 28644562236bSHarry Wentland "src: %d, %d, %d," 28654562236bSHarry Wentland " %d; dst: %d, %d, %d, %d;" 28664562236bSHarry Wentland "clip: %d, %d, %d, %d\n", 28674562236bSHarry Wentland pipe_ctx->pipe_idx, 28683be5262eSHarry Wentland pipe_ctx->plane_state, 28693be5262eSHarry Wentland pipe_ctx->plane_state->address.grph.addr.high_part, 28703be5262eSHarry Wentland pipe_ctx->plane_state->address.grph.addr.low_part, 28713be5262eSHarry Wentland pipe_ctx->plane_state->src_rect.x, 28723be5262eSHarry Wentland pipe_ctx->plane_state->src_rect.y, 28733be5262eSHarry Wentland pipe_ctx->plane_state->src_rect.width, 28743be5262eSHarry Wentland pipe_ctx->plane_state->src_rect.height, 28753be5262eSHarry Wentland pipe_ctx->plane_state->dst_rect.x, 28763be5262eSHarry Wentland pipe_ctx->plane_state->dst_rect.y, 28773be5262eSHarry Wentland pipe_ctx->plane_state->dst_rect.width, 28783be5262eSHarry Wentland pipe_ctx->plane_state->dst_rect.height, 28793be5262eSHarry Wentland pipe_ctx->plane_state->clip_rect.x, 28803be5262eSHarry Wentland pipe_ctx->plane_state->clip_rect.y, 28813be5262eSHarry Wentland pipe_ctx->plane_state->clip_rect.width, 28823be5262eSHarry Wentland pipe_ctx->plane_state->clip_rect.height); 28834562236bSHarry Wentland 28844562236bSHarry Wentland dm_logger_write(dc->ctx->logger, LOG_SURFACE, 28854562236bSHarry Wentland "Pipe %d: width, height, x, y\n" 28864562236bSHarry Wentland "viewport:%d, %d, %d, %d\n" 28874562236bSHarry Wentland "recout: %d, %d, %d, %d\n", 28884562236bSHarry Wentland pipe_ctx->pipe_idx, 28896702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.width, 28906702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.height, 28916702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.x, 28926702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.viewport.y, 28936702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.width, 28946702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.height, 28956702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.x, 28966702a9acSHarry Wentland pipe_ctx->plane_res.scl_data.recout.y); 28974562236bSHarry Wentland } 28984562236bSHarry Wentland 28994562236bSHarry Wentland static void dce110_apply_ctx_for_surface( 2900fb3466a4SBhawanpreet Lakha struct dc *dc, 29013e9ad616SEric Yang const struct dc_stream_state *stream, 29023e9ad616SEric Yang int num_planes, 2903608ac7bbSJerry Zuo struct dc_state *context) 29044562236bSHarry Wentland { 29053e9ad616SEric Yang int i, be_idx; 29064562236bSHarry Wentland 29073e9ad616SEric Yang if (num_planes == 0) 29084562236bSHarry Wentland return; 29094562236bSHarry Wentland 29103e9ad616SEric Yang be_idx = -1; 29113e9ad616SEric Yang for (i = 0; i < dc->res_pool->pipe_count; i++) { 29123dc780ecSYongqiang Sun struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 29133dc780ecSYongqiang Sun struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; 29143dc780ecSYongqiang Sun 29153e9ad616SEric Yang if (stream == context->res_ctx.pipe_ctx[i].stream) { 29163e9ad616SEric Yang be_idx = context->res_ctx.pipe_ctx[i].stream_res.tg->inst; 29173dc780ecSYongqiang Sun if (!pipe_ctx->top_pipe && 29183dc780ecSYongqiang Sun (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) 29193dc780ecSYongqiang Sun dc->hwss.pipe_control_lock(dc, pipe_ctx, true); 29203e9ad616SEric Yang break; 29213e9ad616SEric Yang } 29223e9ad616SEric Yang } 29233e9ad616SEric Yang 2924a2b8659dSTony Cheng for (i = 0; i < dc->res_pool->pipe_count; i++) { 29254562236bSHarry Wentland struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 29264562236bSHarry Wentland 2927a2607aefSHarry Wentland if (pipe_ctx->stream != stream) 29284562236bSHarry Wentland continue; 29294562236bSHarry Wentland 29303b21b6d2SJerry Zuo /* Need to allocate mem before program front end for Fiji */ 29313b21b6d2SJerry Zuo if (pipe_ctx->plane_res.mi != NULL) 29323b21b6d2SJerry Zuo pipe_ctx->plane_res.mi->funcs->allocate_mem_input( 29333b21b6d2SJerry Zuo pipe_ctx->plane_res.mi, 29343b21b6d2SJerry Zuo pipe_ctx->stream->timing.h_total, 29353b21b6d2SJerry Zuo pipe_ctx->stream->timing.v_total, 29363b21b6d2SJerry Zuo pipe_ctx->stream->timing.pix_clk_khz, 29373b21b6d2SJerry Zuo context->stream_count); 29383b21b6d2SJerry Zuo 29394562236bSHarry Wentland dce110_program_front_end_for_pipe(dc, pipe_ctx); 2940b06b7680SLeon Elazar program_surface_visibility(dc, pipe_ctx); 29414562236bSHarry Wentland 29424562236bSHarry Wentland } 29433dc780ecSYongqiang Sun 29443dc780ecSYongqiang Sun for (i = 0; i < dc->res_pool->pipe_count; i++) { 29453dc780ecSYongqiang Sun struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 29463dc780ecSYongqiang Sun struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; 29473dc780ecSYongqiang Sun 29483dc780ecSYongqiang Sun if ((stream == pipe_ctx->stream) && 29493dc780ecSYongqiang Sun (!pipe_ctx->top_pipe) && 29503dc780ecSYongqiang Sun (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) 29513dc780ecSYongqiang Sun dc->hwss.pipe_control_lock(dc, pipe_ctx, false); 29523dc780ecSYongqiang Sun } 29534562236bSHarry Wentland } 29544562236bSHarry Wentland 2955e6c258cbSYongqiang Sun static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx) 29564562236bSHarry Wentland { 2957e6c258cbSYongqiang Sun int fe_idx = pipe_ctx->pipe_idx; 2958e6c258cbSYongqiang Sun 29597950f0f9SDmytro Laktyushkin /* Do not power down fe when stream is active on dce*/ 2960608ac7bbSJerry Zuo if (dc->current_state->res_ctx.pipe_ctx[fe_idx].stream) 29614562236bSHarry Wentland return; 29624562236bSHarry Wentland 29634562236bSHarry Wentland dc->hwss.enable_display_power_gating( 2964cfe4645eSDmytro Laktyushkin dc, fe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE); 2965cfe4645eSDmytro Laktyushkin 2966cfe4645eSDmytro Laktyushkin dc->res_pool->transforms[fe_idx]->funcs->transform_reset( 2967cfe4645eSDmytro Laktyushkin dc->res_pool->transforms[fe_idx]); 29684562236bSHarry Wentland } 29694562236bSHarry Wentland 29706be425f3SEric Yang static void dce110_wait_for_mpcc_disconnect( 2971fb3466a4SBhawanpreet Lakha struct dc *dc, 29726be425f3SEric Yang struct resource_pool *res_pool, 29736be425f3SEric Yang struct pipe_ctx *pipe_ctx) 2974b6762f0cSEric Yang { 2975b6762f0cSEric Yang /* do nothing*/ 2976b6762f0cSEric Yang } 2977b6762f0cSEric Yang 2978bdf9a1a0SYue Hin Lau static void program_csc_matrix(struct pipe_ctx *pipe_ctx, 2979bdf9a1a0SYue Hin Lau enum dc_color_space colorspace, 2980bdf9a1a0SYue Hin Lau uint16_t *matrix) 2981bdf9a1a0SYue Hin Lau { 2982bdf9a1a0SYue Hin Lau int i; 2983bdf9a1a0SYue Hin Lau struct out_csc_color_matrix tbl_entry; 2984bdf9a1a0SYue Hin Lau 2985bdf9a1a0SYue Hin Lau if (pipe_ctx->stream->csc_color_matrix.enable_adjustment 2986bdf9a1a0SYue Hin Lau == true) { 2987bdf9a1a0SYue Hin Lau enum dc_color_space color_space = 2988bdf9a1a0SYue Hin Lau pipe_ctx->stream->output_color_space; 2989bdf9a1a0SYue Hin Lau 2990bdf9a1a0SYue Hin Lau //uint16_t matrix[12]; 2991bdf9a1a0SYue Hin Lau for (i = 0; i < 12; i++) 2992bdf9a1a0SYue Hin Lau tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; 2993bdf9a1a0SYue Hin Lau 2994bdf9a1a0SYue Hin Lau tbl_entry.color_space = color_space; 2995bdf9a1a0SYue Hin Lau //tbl_entry.regval = matrix; 299686a66c4eSHarry Wentland pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment(pipe_ctx->plane_res.xfm, &tbl_entry); 2997bdf9a1a0SYue Hin Lau } 2998bdf9a1a0SYue Hin Lau } 2999bdf9a1a0SYue Hin Lau 30006bf52028SHersen Wu static void ready_shared_resources(struct dc *dc, struct dc_state *context) {} 300141f97c07SHersen Wu 300241f97c07SHersen Wu static void optimize_shared_resources(struct dc *dc) {} 300341f97c07SHersen Wu 30044562236bSHarry Wentland static const struct hw_sequencer_funcs dce110_funcs = { 30051bf56e62SZeyu Fan .program_gamut_remap = program_gamut_remap, 3006bdf9a1a0SYue Hin Lau .program_csc_matrix = program_csc_matrix, 30074562236bSHarry Wentland .init_hw = init_hw, 30084562236bSHarry Wentland .apply_ctx_to_hw = dce110_apply_ctx_to_hw, 30094562236bSHarry Wentland .apply_ctx_for_surface = dce110_apply_ctx_for_surface, 30104562236bSHarry Wentland .set_plane_config = set_plane_config, 30114562236bSHarry Wentland .update_plane_addr = update_plane_addr, 30124562236bSHarry Wentland .update_pending_status = dce110_update_pending_status, 3013d7194cf6SAric Cyr .set_input_transfer_func = dce110_set_input_transfer_func, 301490e508baSAnthony Koo .set_output_transfer_func = dce110_set_output_transfer_func, 30154562236bSHarry Wentland .power_down = dce110_power_down, 30164562236bSHarry Wentland .enable_accelerated_mode = dce110_enable_accelerated_mode, 30174562236bSHarry Wentland .enable_timing_synchronization = dce110_enable_timing_synchronization, 3018fa2123dbSMikita Lipski .enable_per_frame_crtc_position_reset = dce110_enable_per_frame_crtc_position_reset, 30194562236bSHarry Wentland .update_info_frame = dce110_update_info_frame, 30204562236bSHarry Wentland .enable_stream = dce110_enable_stream, 30214562236bSHarry Wentland .disable_stream = dce110_disable_stream, 30224562236bSHarry Wentland .unblank_stream = dce110_unblank_stream, 30234562236bSHarry Wentland .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating, 30244562236bSHarry Wentland .enable_display_power_gating = dce110_enable_display_power_gating, 30254562236bSHarry Wentland .power_down_front_end = dce110_power_down_fe, 30264562236bSHarry Wentland .pipe_control_lock = dce_pipe_control_lock, 30274562236bSHarry Wentland .set_bandwidth = dce110_set_bandwidth, 30284562236bSHarry Wentland .set_drr = set_drr, 302972ada5f7SEric Cook .get_position = get_position, 30304562236bSHarry Wentland .set_static_screen_control = set_static_screen_control, 303154e8695eSDmytro Laktyushkin .reset_hw_ctx_wrap = dce110_reset_hw_ctx_wrap, 30324b5e7d62SHersen Wu .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg, 303315e17335SCharlene Liu .setup_stereo = NULL, 303415e17335SCharlene Liu .set_avmute = dce110_set_avmute, 303541f97c07SHersen Wu .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect, 303641f97c07SHersen Wu .ready_shared_resources = ready_shared_resources, 303741f97c07SHersen Wu .optimize_shared_resources = optimize_shared_resources, 303887401969SAndrew Jiang .edp_backlight_control = hwss_edp_backlight_control, 303987401969SAndrew Jiang .edp_power_control = hwss_edp_power_control, 30404562236bSHarry Wentland }; 30414562236bSHarry Wentland 3042c13b408bSDave Airlie void dce110_hw_sequencer_construct(struct dc *dc) 30434562236bSHarry Wentland { 30444562236bSHarry Wentland dc->hwss = dce110_funcs; 30454562236bSHarry Wentland } 30464562236bSHarry Wentland 3047