Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012-16 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 #include <linux/slab.h>
0027 
0028 #include "dce_abm.h"
0029 #include "dm_services.h"
0030 #include "reg_helper.h"
0031 #include "fixed31_32.h"
0032 #include "dc.h"
0033 
0034 #include "atom.h"
0035 
0036 
0037 #define TO_DCE_ABM(abm)\
0038     container_of(abm, struct dce_abm, base)
0039 
0040 #define REG(reg) \
0041     (abm_dce->regs->reg)
0042 
0043 #undef FN
0044 #define FN(reg_name, field_name) \
0045     abm_dce->abm_shift->field_name, abm_dce->abm_mask->field_name
0046 
0047 #define DC_LOGGER \
0048     abm->ctx->logger
0049 #define CTX \
0050     abm_dce->base.ctx
0051 
0052 #define MCP_ABM_LEVEL_SET 0x65
0053 #define MCP_ABM_PIPE_SET 0x66
0054 #define MCP_BL_SET 0x67
0055 
0056 #define MCP_DISABLE_ABM_IMMEDIATELY 255
0057 
0058 static bool dce_abm_set_pipe(struct abm *abm, uint32_t controller_id, uint32_t panel_inst)
0059 {
0060     struct dce_abm *abm_dce = TO_DCE_ABM(abm);
0061     uint32_t rampingBoundary = 0xFFFF;
0062 
0063     if (abm->dmcu_is_running == false)
0064         return true;
0065 
0066     REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0,
0067             1, 80000);
0068 
0069     /* set ramping boundary */
0070     REG_WRITE(MASTER_COMM_DATA_REG1, rampingBoundary);
0071 
0072     /* setDMCUParam_Pipe */
0073     REG_UPDATE_2(MASTER_COMM_CMD_REG,
0074             MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_PIPE_SET,
0075             MASTER_COMM_CMD_REG_BYTE1, controller_id);
0076 
0077     /* notifyDMCUMsg */
0078     REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
0079 
0080     REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0,
0081             1, 80000);
0082 
0083     return true;
0084 }
0085 
0086 static void dmcu_set_backlight_level(
0087     struct dce_abm *abm_dce,
0088     uint32_t backlight_pwm_u16_16,
0089     uint32_t frame_ramp,
0090     uint32_t controller_id,
0091     uint32_t panel_id)
0092 {
0093     unsigned int backlight_8_bit = 0;
0094     uint32_t s2;
0095 
0096     if (backlight_pwm_u16_16 & 0x10000)
0097         // Check for max backlight condition
0098         backlight_8_bit = 0xFF;
0099     else
0100         // Take MSB of fractional part since backlight is not max
0101         backlight_8_bit = (backlight_pwm_u16_16 >> 8) & 0xFF;
0102 
0103     dce_abm_set_pipe(&abm_dce->base, controller_id, panel_id);
0104 
0105     /* waitDMCUReadyForCmd */
0106     REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT,
0107             0, 1, 80000);
0108 
0109     /* setDMCUParam_BL */
0110     REG_UPDATE(BL1_PWM_USER_LEVEL, BL1_PWM_USER_LEVEL, backlight_pwm_u16_16);
0111 
0112     /* write ramp */
0113     if (controller_id == 0)
0114         frame_ramp = 0;
0115     REG_WRITE(MASTER_COMM_DATA_REG1, frame_ramp);
0116 
0117     /* setDMCUParam_Cmd */
0118     REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, MCP_BL_SET);
0119 
0120     /* notifyDMCUMsg */
0121     REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
0122 
0123     /* UpdateRequestedBacklightLevel */
0124     s2 = REG_READ(BIOS_SCRATCH_2);
0125 
0126     s2 &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK;
0127     backlight_8_bit &= (ATOM_S2_CURRENT_BL_LEVEL_MASK >>
0128                 ATOM_S2_CURRENT_BL_LEVEL_SHIFT);
0129     s2 |= (backlight_8_bit << ATOM_S2_CURRENT_BL_LEVEL_SHIFT);
0130 
0131     REG_WRITE(BIOS_SCRATCH_2, s2);
0132 
0133     /* waitDMCUReadyForCmd */
0134     REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT,
0135             0, 1, 80000);
0136 }
0137 
0138 static void dce_abm_init(struct abm *abm, uint32_t backlight)
0139 {
0140     struct dce_abm *abm_dce = TO_DCE_ABM(abm);
0141 
0142     REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x103);
0143     REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x101);
0144     REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x103);
0145     REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x101);
0146     REG_WRITE(BL1_PWM_BL_UPDATE_SAMPLE_RATE, 0x101);
0147 
0148     REG_SET_3(DC_ABM1_HG_MISC_CTRL, 0,
0149             ABM1_HG_NUM_OF_BINS_SEL, 0,
0150             ABM1_HG_VMAX_SEL, 1,
0151             ABM1_HG_BIN_BITWIDTH_SIZE_SEL, 0);
0152 
0153     REG_SET_3(DC_ABM1_IPCSC_COEFF_SEL, 0,
0154             ABM1_IPCSC_COEFF_SEL_R, 2,
0155             ABM1_IPCSC_COEFF_SEL_G, 4,
0156             ABM1_IPCSC_COEFF_SEL_B, 2);
0157 
0158     REG_UPDATE(BL1_PWM_CURRENT_ABM_LEVEL,
0159             BL1_PWM_CURRENT_ABM_LEVEL, backlight);
0160 
0161     REG_UPDATE(BL1_PWM_TARGET_ABM_LEVEL,
0162             BL1_PWM_TARGET_ABM_LEVEL, backlight);
0163 
0164     REG_UPDATE(BL1_PWM_USER_LEVEL,
0165             BL1_PWM_USER_LEVEL, backlight);
0166 
0167     REG_UPDATE_2(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES,
0168             ABM1_LS_MIN_PIXEL_VALUE_THRES, 0,
0169             ABM1_LS_MAX_PIXEL_VALUE_THRES, 1000);
0170 
0171     REG_SET_3(DC_ABM1_HGLS_REG_READ_PROGRESS, 0,
0172             ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, 1,
0173             ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, 1,
0174             ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, 1);
0175 }
0176 
0177 static unsigned int dce_abm_get_current_backlight(struct abm *abm)
0178 {
0179     struct dce_abm *abm_dce = TO_DCE_ABM(abm);
0180     unsigned int backlight = REG_READ(BL1_PWM_CURRENT_ABM_LEVEL);
0181 
0182     /* return backlight in hardware format which is unsigned 17 bits, with
0183      * 1 bit integer and 16 bit fractional
0184      */
0185     return backlight;
0186 }
0187 
0188 static unsigned int dce_abm_get_target_backlight(struct abm *abm)
0189 {
0190     struct dce_abm *abm_dce = TO_DCE_ABM(abm);
0191     unsigned int backlight = REG_READ(BL1_PWM_TARGET_ABM_LEVEL);
0192 
0193     /* return backlight in hardware format which is unsigned 17 bits, with
0194      * 1 bit integer and 16 bit fractional
0195      */
0196     return backlight;
0197 }
0198 
0199 static bool dce_abm_set_level(struct abm *abm, uint32_t level)
0200 {
0201     struct dce_abm *abm_dce = TO_DCE_ABM(abm);
0202 
0203     if (abm->dmcu_is_running == false)
0204         return true;
0205 
0206     REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0,
0207             1, 80000);
0208 
0209     /* setDMCUParam_ABMLevel */
0210     REG_UPDATE_2(MASTER_COMM_CMD_REG,
0211             MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_LEVEL_SET,
0212             MASTER_COMM_CMD_REG_BYTE2, level);
0213 
0214     /* notifyDMCUMsg */
0215     REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
0216 
0217     return true;
0218 }
0219 
0220 static bool dce_abm_immediate_disable(struct abm *abm, uint32_t panel_inst)
0221 {
0222     if (abm->dmcu_is_running == false)
0223         return true;
0224 
0225     dce_abm_set_pipe(abm, MCP_DISABLE_ABM_IMMEDIATELY, panel_inst);
0226 
0227     return true;
0228 }
0229 
0230 static bool dce_abm_set_backlight_level_pwm(
0231         struct abm *abm,
0232         unsigned int backlight_pwm_u16_16,
0233         unsigned int frame_ramp,
0234         unsigned int controller_id,
0235         unsigned int panel_inst)
0236 {
0237     struct dce_abm *abm_dce = TO_DCE_ABM(abm);
0238 
0239     DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n",
0240             backlight_pwm_u16_16, backlight_pwm_u16_16);
0241 
0242     dmcu_set_backlight_level(abm_dce,
0243             backlight_pwm_u16_16,
0244             frame_ramp,
0245             controller_id,
0246             panel_inst);
0247 
0248     return true;
0249 }
0250 
0251 static const struct abm_funcs dce_funcs = {
0252     .abm_init = dce_abm_init,
0253     .set_abm_level = dce_abm_set_level,
0254     .set_pipe = dce_abm_set_pipe,
0255     .set_backlight_level_pwm = dce_abm_set_backlight_level_pwm,
0256     .get_current_backlight = dce_abm_get_current_backlight,
0257     .get_target_backlight = dce_abm_get_target_backlight,
0258     .init_abm_config = NULL,
0259     .set_abm_immediate_disable = dce_abm_immediate_disable,
0260 };
0261 
0262 static void dce_abm_construct(
0263     struct dce_abm *abm_dce,
0264     struct dc_context *ctx,
0265     const struct dce_abm_registers *regs,
0266     const struct dce_abm_shift *abm_shift,
0267     const struct dce_abm_mask *abm_mask)
0268 {
0269     struct abm *base = &abm_dce->base;
0270 
0271     base->ctx = ctx;
0272     base->funcs = &dce_funcs;
0273     base->dmcu_is_running = false;
0274 
0275     abm_dce->regs = regs;
0276     abm_dce->abm_shift = abm_shift;
0277     abm_dce->abm_mask = abm_mask;
0278 }
0279 
0280 struct abm *dce_abm_create(
0281     struct dc_context *ctx,
0282     const struct dce_abm_registers *regs,
0283     const struct dce_abm_shift *abm_shift,
0284     const struct dce_abm_mask *abm_mask)
0285 {
0286     struct dce_abm *abm_dce = kzalloc(sizeof(*abm_dce), GFP_ATOMIC);
0287 
0288     if (abm_dce == NULL) {
0289         BREAK_TO_DEBUGGER();
0290         return NULL;
0291     }
0292 
0293     dce_abm_construct(abm_dce, ctx, regs, abm_shift, abm_mask);
0294 
0295     abm_dce->base.funcs = &dce_funcs;
0296 
0297     return &abm_dce->base;
0298 }
0299 
0300 void dce_abm_destroy(struct abm **abm)
0301 {
0302     struct dce_abm *abm_dce = TO_DCE_ABM(*abm);
0303 
0304     kfree(abm_dce);
0305     *abm = NULL;
0306 }