116012806SWyatt Wood /* 216012806SWyatt Wood * Copyright 2019 Advanced Micro Devices, Inc. 316012806SWyatt Wood * 416012806SWyatt Wood * Permission is hereby granted, free of charge, to any person obtaining a 516012806SWyatt Wood * copy of this software and associated documentation files (the "Software"), 616012806SWyatt Wood * to deal in the Software without restriction, including without limitation 716012806SWyatt Wood * the rights to use, copy, modify, merge, publish, distribute, sublicense, 816012806SWyatt Wood * and/or sell copies of the Software, and to permit persons to whom the 916012806SWyatt Wood * Software is furnished to do so, subject to the following conditions: 1016012806SWyatt Wood * 1116012806SWyatt Wood * The above copyright notice and this permission notice shall be included in 1216012806SWyatt Wood * all copies or substantial portions of the Software. 1316012806SWyatt Wood * 1416012806SWyatt Wood * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1516012806SWyatt Wood * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1616012806SWyatt Wood * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1716012806SWyatt Wood * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 1816012806SWyatt Wood * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 1916012806SWyatt Wood * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2016012806SWyatt Wood * OTHER DEALINGS IN THE SOFTWARE. 2116012806SWyatt Wood * 2216012806SWyatt Wood * Authors: AMD 2316012806SWyatt Wood * 2416012806SWyatt Wood */ 2516012806SWyatt Wood 2616012806SWyatt Wood #include "dmub_abm.h" 27b8fe5637SLeon Huang #include "dmub_abm_lcd.h" 2816012806SWyatt Wood #include "dc.h" 2916012806SWyatt Wood #include "core_types.h" 30*da915efaSReza Amini #include "dmub_cmd.h" 3116012806SWyatt Wood 3216012806SWyatt Wood #define TO_DMUB_ABM(abm)\ 3316012806SWyatt Wood container_of(abm, struct dce_abm, base) 3416012806SWyatt Wood 35b8fe5637SLeon Huang #define ABM_FEATURE_NO_SUPPORT 0 36b8fe5637SLeon Huang #define ABM_LCD_SUPPORT 1 3716012806SWyatt Wood 38b8fe5637SLeon Huang static unsigned int abm_feature_support(struct abm *abm, unsigned int panel_inst) 39dd5a94ceSWyatt Wood { 4016012806SWyatt Wood struct dc_context *dc = abm->ctx; 4163de4f04SJake Wang struct dc_link *edp_links[MAX_NUM_EDP]; 4263de4f04SJake Wang int i; 4363de4f04SJake Wang int edp_num; 44b8fe5637SLeon Huang unsigned int ret = ABM_FEATURE_NO_SUPPORT; 4563de4f04SJake Wang 467ae1dbe6SWenjing Liu dc_get_edp_links(dc->dc, edp_links, &edp_num); 4763de4f04SJake Wang 4863de4f04SJake Wang for (i = 0; i < edp_num; i++) { 49b8fe5637SLeon Huang if (panel_inst == i) 50b8fe5637SLeon Huang break; 5163de4f04SJake Wang } 5216012806SWyatt Wood 53b8fe5637SLeon Huang if (i < edp_num) { 54b8fe5637SLeon Huang ret = ABM_LCD_SUPPORT; 5516012806SWyatt Wood } 5616012806SWyatt Wood 57b8fe5637SLeon Huang return ret; 58b8fe5637SLeon Huang } 59b8fe5637SLeon Huang 60b8fe5637SLeon Huang static void dmub_abm_init_ex(struct abm *abm, uint32_t backlight) 61b8fe5637SLeon Huang { 62b8fe5637SLeon Huang dmub_abm_init(abm, backlight); 63b8fe5637SLeon Huang } 64b8fe5637SLeon Huang 65b8fe5637SLeon Huang static unsigned int dmub_abm_get_current_backlight_ex(struct abm *abm) 66b8fe5637SLeon Huang { 67b8fe5637SLeon Huang return dmub_abm_get_current_backlight(abm); 68b8fe5637SLeon Huang } 69b8fe5637SLeon Huang 70b8fe5637SLeon Huang static unsigned int dmub_abm_get_target_backlight_ex(struct abm *abm) 71b8fe5637SLeon Huang { 72b8fe5637SLeon Huang return dmub_abm_get_target_backlight(abm); 73b8fe5637SLeon Huang } 74b8fe5637SLeon Huang 75b8fe5637SLeon Huang static bool dmub_abm_set_level_ex(struct abm *abm, uint32_t level) 76b8fe5637SLeon Huang { 77b8fe5637SLeon Huang bool ret = false; 78b8fe5637SLeon Huang unsigned int feature_support, i; 79b8fe5637SLeon Huang uint8_t panel_mask0 = 0; 80b8fe5637SLeon Huang 81b8fe5637SLeon Huang for (i = 0; i < MAX_NUM_EDP; i++) { 82b8fe5637SLeon Huang feature_support = abm_feature_support(abm, i); 83b8fe5637SLeon Huang 84b8fe5637SLeon Huang if (feature_support == ABM_LCD_SUPPORT) 85b8fe5637SLeon Huang panel_mask0 |= (0x01 << i); 86b8fe5637SLeon Huang } 87b8fe5637SLeon Huang 88b8fe5637SLeon Huang if (panel_mask0) 89b8fe5637SLeon Huang ret = dmub_abm_set_level(abm, level, panel_mask0); 90b8fe5637SLeon Huang 91b8fe5637SLeon Huang return ret; 92b8fe5637SLeon Huang } 93b8fe5637SLeon Huang 94b8fe5637SLeon Huang static bool dmub_abm_init_config_ex(struct abm *abm, 9516012806SWyatt Wood const char *src, 966e568e43SJake Wang unsigned int bytes, 976e568e43SJake Wang unsigned int inst) 9816012806SWyatt Wood { 99b8fe5637SLeon Huang unsigned int feature_support; 100c5d5b0ecSWyatt Wood 101b8fe5637SLeon Huang feature_support = abm_feature_support(abm, inst); 102c5d5b0ecSWyatt Wood 103b8fe5637SLeon Huang if (feature_support == ABM_LCD_SUPPORT) 104b8fe5637SLeon Huang dmub_abm_init_config(abm, src, bytes, inst); 105c5d5b0ecSWyatt Wood 10616012806SWyatt Wood return true; 10716012806SWyatt Wood } 10816012806SWyatt Wood 109b8fe5637SLeon Huang static bool dmub_abm_set_pause_ex(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int stream_inst) 110b629a824SEric Yang { 111b8fe5637SLeon Huang bool ret = false; 112b8fe5637SLeon Huang unsigned int feature_support; 113b629a824SEric Yang 114b8fe5637SLeon Huang feature_support = abm_feature_support(abm, panel_inst); 115b629a824SEric Yang 116b8fe5637SLeon Huang if (feature_support == ABM_LCD_SUPPORT) 117b8fe5637SLeon Huang ret = dmub_abm_set_pause(abm, pause, panel_inst, stream_inst); 118b629a824SEric Yang 119b8fe5637SLeon Huang return ret; 120b8fe5637SLeon Huang } 121b8fe5637SLeon Huang 122*da915efaSReza Amini /***************************************************************************** 123*da915efaSReza Amini * dmub_abm_save_restore_ex() - calls dmub_abm_save_restore for preserving DMUB's 124*da915efaSReza Amini * Varibright states for LCD only. OLED is TBD 125*da915efaSReza Amini * @abm: used to check get dc context 126*da915efaSReza Amini * @panel_inst: panel instance index 127*da915efaSReza Amini * @pData: contains command to pause/un-pause abm and abm parameters 128*da915efaSReza Amini * 129*da915efaSReza Amini * 130*da915efaSReza Amini ***************************************************************************/ 131*da915efaSReza Amini static bool dmub_abm_save_restore_ex( 132*da915efaSReza Amini struct abm *abm, 133*da915efaSReza Amini unsigned int panel_inst, 134*da915efaSReza Amini struct abm_save_restore *pData) 135*da915efaSReza Amini { 136*da915efaSReza Amini bool ret = false; 137*da915efaSReza Amini unsigned int feature_support; 138*da915efaSReza Amini struct dc_context *dc = abm->ctx; 139*da915efaSReza Amini 140*da915efaSReza Amini feature_support = abm_feature_support(abm, panel_inst); 141*da915efaSReza Amini 142*da915efaSReza Amini if (feature_support == ABM_LCD_SUPPORT) 143*da915efaSReza Amini ret = dmub_abm_save_restore(dc, panel_inst, pData); 144*da915efaSReza Amini 145*da915efaSReza Amini return ret; 146*da915efaSReza Amini } 147*da915efaSReza Amini 148b8fe5637SLeon Huang static bool dmub_abm_set_pipe_ex(struct abm *abm, uint32_t otg_inst, uint32_t option, uint32_t panel_inst) 149b8fe5637SLeon Huang { 150b8fe5637SLeon Huang bool ret = false; 151b8fe5637SLeon Huang unsigned int feature_support; 152b8fe5637SLeon Huang 153b8fe5637SLeon Huang feature_support = abm_feature_support(abm, panel_inst); 154b8fe5637SLeon Huang 155b8fe5637SLeon Huang if (feature_support == ABM_LCD_SUPPORT) 156b8fe5637SLeon Huang ret = dmub_abm_set_pipe(abm, otg_inst, option, panel_inst); 157b8fe5637SLeon Huang 158b8fe5637SLeon Huang return ret; 159b8fe5637SLeon Huang } 160b8fe5637SLeon Huang 161b8fe5637SLeon Huang static bool dmub_abm_set_backlight_level_pwm_ex(struct abm *abm, 162b8fe5637SLeon Huang unsigned int backlight_pwm_u16_16, 163b8fe5637SLeon Huang unsigned int frame_ramp, 164b8fe5637SLeon Huang unsigned int controller_id, 165b8fe5637SLeon Huang unsigned int panel_inst) 166b8fe5637SLeon Huang { 167b8fe5637SLeon Huang bool ret = false; 168b8fe5637SLeon Huang unsigned int feature_support; 169b8fe5637SLeon Huang 170b8fe5637SLeon Huang feature_support = abm_feature_support(abm, panel_inst); 171b8fe5637SLeon Huang 172b8fe5637SLeon Huang if (feature_support == ABM_LCD_SUPPORT) 173b8fe5637SLeon Huang ret = dmub_abm_set_backlight_level(abm, backlight_pwm_u16_16, frame_ramp, panel_inst); 174b8fe5637SLeon Huang 175b8fe5637SLeon Huang return ret; 176b629a824SEric Yang } 177b629a824SEric Yang 17816012806SWyatt Wood static const struct abm_funcs abm_funcs = { 179b8fe5637SLeon Huang .abm_init = dmub_abm_init_ex, 180b8fe5637SLeon Huang .set_abm_level = dmub_abm_set_level_ex, 181b8fe5637SLeon Huang .get_current_backlight = dmub_abm_get_current_backlight_ex, 182b8fe5637SLeon Huang .get_target_backlight = dmub_abm_get_target_backlight_ex, 183b8fe5637SLeon Huang .init_abm_config = dmub_abm_init_config_ex, 184b8fe5637SLeon Huang .set_abm_pause = dmub_abm_set_pause_ex, 185*da915efaSReza Amini .save_restore = dmub_abm_save_restore_ex, 186b8fe5637SLeon Huang .set_pipe_ex = dmub_abm_set_pipe_ex, 187b8fe5637SLeon Huang .set_backlight_level_pwm = dmub_abm_set_backlight_level_pwm_ex, 18816012806SWyatt Wood }; 18916012806SWyatt Wood 19016012806SWyatt Wood static void dmub_abm_construct( 19116012806SWyatt Wood struct dce_abm *abm_dce, 19216012806SWyatt Wood struct dc_context *ctx, 19316012806SWyatt Wood const struct dce_abm_registers *regs, 19416012806SWyatt Wood const struct dce_abm_shift *abm_shift, 19516012806SWyatt Wood const struct dce_abm_mask *abm_mask) 19616012806SWyatt Wood { 19716012806SWyatt Wood struct abm *base = &abm_dce->base; 19816012806SWyatt Wood 19916012806SWyatt Wood base->ctx = ctx; 20016012806SWyatt Wood base->funcs = &abm_funcs; 20116012806SWyatt Wood base->dmcu_is_running = false; 20216012806SWyatt Wood 20316012806SWyatt Wood abm_dce->regs = regs; 20416012806SWyatt Wood abm_dce->abm_shift = abm_shift; 20516012806SWyatt Wood abm_dce->abm_mask = abm_mask; 20616012806SWyatt Wood } 20716012806SWyatt Wood 20816012806SWyatt Wood struct abm *dmub_abm_create( 20916012806SWyatt Wood struct dc_context *ctx, 21016012806SWyatt Wood const struct dce_abm_registers *regs, 21116012806SWyatt Wood const struct dce_abm_shift *abm_shift, 21216012806SWyatt Wood const struct dce_abm_mask *abm_mask) 21316012806SWyatt Wood { 214b8fe5637SLeon Huang if (ctx->dc->caps.dmcub_support) { 21516012806SWyatt Wood struct dce_abm *abm_dce = kzalloc(sizeof(*abm_dce), GFP_KERNEL); 21616012806SWyatt Wood 21716012806SWyatt Wood if (abm_dce == NULL) { 21816012806SWyatt Wood BREAK_TO_DEBUGGER(); 21916012806SWyatt Wood return NULL; 22016012806SWyatt Wood } 22116012806SWyatt Wood 22216012806SWyatt Wood dmub_abm_construct(abm_dce, ctx, regs, abm_shift, abm_mask); 22316012806SWyatt Wood 22416012806SWyatt Wood return &abm_dce->base; 22516012806SWyatt Wood } 226b8fe5637SLeon Huang return NULL; 227b8fe5637SLeon Huang } 22816012806SWyatt Wood 22916012806SWyatt Wood void dmub_abm_destroy(struct abm **abm) 23016012806SWyatt Wood { 23116012806SWyatt Wood struct dce_abm *abm_dce = TO_DMUB_ABM(*abm); 23216012806SWyatt Wood 23316012806SWyatt Wood kfree(abm_dce); 23416012806SWyatt Wood *abm = NULL; 23516012806SWyatt Wood } 236