1 /* 2 * Copyright 2019 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: AMD 23 * 24 */ 25 26 #include "dmub_abm.h" 27 #include "dmub_abm_lcd.h" 28 #include "dc.h" 29 #include "core_types.h" 30 #include "dmub_cmd.h" 31 32 #define TO_DMUB_ABM(abm)\ 33 container_of(abm, struct dce_abm, base) 34 35 #define ABM_FEATURE_NO_SUPPORT 0 36 #define ABM_LCD_SUPPORT 1 37 38 static unsigned int abm_feature_support(struct abm *abm, unsigned int panel_inst) 39 { 40 struct dc_context *dc = abm->ctx; 41 struct dc_link *edp_links[MAX_NUM_EDP]; 42 int i; 43 int edp_num; 44 unsigned int ret = ABM_FEATURE_NO_SUPPORT; 45 46 dc_get_edp_links(dc->dc, edp_links, &edp_num); 47 48 for (i = 0; i < edp_num; i++) { 49 if (panel_inst == i) 50 break; 51 } 52 53 if (i < edp_num) { 54 ret = ABM_LCD_SUPPORT; 55 } 56 57 return ret; 58 } 59 60 static void dmub_abm_init_ex(struct abm *abm, uint32_t backlight, uint32_t user_level) 61 { 62 dmub_abm_init(abm, backlight, user_level); 63 } 64 65 static unsigned int dmub_abm_get_current_backlight_ex(struct abm *abm) 66 { 67 dc_allow_idle_optimizations(abm->ctx->dc, false); 68 69 return dmub_abm_get_current_backlight(abm); 70 } 71 72 static unsigned int dmub_abm_get_target_backlight_ex(struct abm *abm) 73 { 74 dc_allow_idle_optimizations(abm->ctx->dc, false); 75 76 return dmub_abm_get_target_backlight(abm); 77 } 78 79 static bool dmub_abm_set_level_ex(struct abm *abm, uint32_t level) 80 { 81 bool ret = false; 82 unsigned int feature_support, i; 83 uint8_t panel_mask0 = 0; 84 85 for (i = 0; i < MAX_NUM_EDP; i++) { 86 feature_support = abm_feature_support(abm, i); 87 88 if (feature_support == ABM_LCD_SUPPORT) 89 panel_mask0 |= (0x01 << i); 90 } 91 92 if (panel_mask0) 93 ret = dmub_abm_set_level(abm, level, panel_mask0); 94 95 return ret; 96 } 97 98 static bool dmub_abm_init_config_ex(struct abm *abm, 99 const char *src, 100 unsigned int bytes, 101 unsigned int inst) 102 { 103 unsigned int feature_support; 104 105 feature_support = abm_feature_support(abm, inst); 106 107 if (feature_support == ABM_LCD_SUPPORT) 108 dmub_abm_init_config(abm, src, bytes, inst); 109 110 return true; 111 } 112 113 static bool dmub_abm_set_pause_ex(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int stream_inst) 114 { 115 bool ret = false; 116 unsigned int feature_support; 117 118 feature_support = abm_feature_support(abm, panel_inst); 119 120 if (feature_support == ABM_LCD_SUPPORT) 121 ret = dmub_abm_set_pause(abm, pause, panel_inst, stream_inst); 122 123 return ret; 124 } 125 126 /***************************************************************************** 127 * dmub_abm_save_restore_ex() - calls dmub_abm_save_restore for preserving DMUB's 128 * Varibright states for LCD only. OLED is TBD 129 * @abm: used to check get dc context 130 * @panel_inst: panel instance index 131 * @pData: contains command to pause/un-pause abm and abm parameters 132 * 133 * 134 ***************************************************************************/ 135 static bool dmub_abm_save_restore_ex( 136 struct abm *abm, 137 unsigned int panel_inst, 138 struct abm_save_restore *pData) 139 { 140 bool ret = false; 141 unsigned int feature_support; 142 struct dc_context *dc = abm->ctx; 143 144 feature_support = abm_feature_support(abm, panel_inst); 145 146 if (feature_support == ABM_LCD_SUPPORT) 147 ret = dmub_abm_save_restore(dc, panel_inst, pData); 148 149 return ret; 150 } 151 152 static bool dmub_abm_set_pipe_ex(struct abm *abm, 153 uint32_t otg_inst, 154 uint32_t option, 155 uint32_t panel_inst, 156 uint32_t pwrseq_inst) 157 { 158 bool ret = false; 159 unsigned int feature_support; 160 161 feature_support = abm_feature_support(abm, panel_inst); 162 163 if (feature_support == ABM_LCD_SUPPORT) 164 ret = dmub_abm_set_pipe(abm, otg_inst, option, panel_inst, pwrseq_inst); 165 166 return ret; 167 } 168 169 static bool dmub_abm_set_backlight_level_pwm_ex(struct abm *abm, 170 unsigned int backlight_pwm_u16_16, 171 unsigned int frame_ramp, 172 unsigned int controller_id, 173 unsigned int panel_inst) 174 { 175 bool ret = false; 176 unsigned int feature_support; 177 178 feature_support = abm_feature_support(abm, panel_inst); 179 180 if (feature_support == ABM_LCD_SUPPORT) 181 ret = dmub_abm_set_backlight_level(abm, backlight_pwm_u16_16, frame_ramp, panel_inst); 182 183 return ret; 184 } 185 186 static const struct abm_funcs abm_funcs = { 187 .abm_init = dmub_abm_init_ex, 188 .set_abm_level = dmub_abm_set_level_ex, 189 .get_current_backlight = dmub_abm_get_current_backlight_ex, 190 .get_target_backlight = dmub_abm_get_target_backlight_ex, 191 .init_abm_config = dmub_abm_init_config_ex, 192 .set_abm_pause = dmub_abm_set_pause_ex, 193 .save_restore = dmub_abm_save_restore_ex, 194 .set_pipe_ex = dmub_abm_set_pipe_ex, 195 .set_backlight_level_pwm = dmub_abm_set_backlight_level_pwm_ex, 196 }; 197 198 static void dmub_abm_construct( 199 struct dce_abm *abm_dce, 200 struct dc_context *ctx, 201 const struct dce_abm_registers *regs, 202 const struct dce_abm_shift *abm_shift, 203 const struct dce_abm_mask *abm_mask) 204 { 205 struct abm *base = &abm_dce->base; 206 207 base->ctx = ctx; 208 base->funcs = &abm_funcs; 209 base->dmcu_is_running = false; 210 211 abm_dce->regs = regs; 212 abm_dce->abm_shift = abm_shift; 213 abm_dce->abm_mask = abm_mask; 214 } 215 216 struct abm *dmub_abm_create( 217 struct dc_context *ctx, 218 const struct dce_abm_registers *regs, 219 const struct dce_abm_shift *abm_shift, 220 const struct dce_abm_mask *abm_mask) 221 { 222 if (ctx->dc->caps.dmcub_support) { 223 struct dce_abm *abm_dce = kzalloc(sizeof(*abm_dce), GFP_KERNEL); 224 225 if (abm_dce == NULL) { 226 BREAK_TO_DEBUGGER(); 227 return NULL; 228 } 229 230 dmub_abm_construct(abm_dce, ctx, regs, abm_shift, abm_mask); 231 232 return &abm_dce->base; 233 } 234 return NULL; 235 } 236 237 void dmub_abm_destroy(struct abm **abm) 238 { 239 struct dce_abm *abm_dce = TO_DMUB_ABM(*abm); 240 241 kfree(abm_dce); 242 *abm = NULL; 243 } 244