Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2017 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 "dce_ipp.h"
0027 #include "reg_helper.h"
0028 #include "dm_services.h"
0029 
0030 #define REG(reg) \
0031     (ipp_dce->regs->reg)
0032 
0033 #undef FN
0034 #define FN(reg_name, field_name) \
0035     ipp_dce->ipp_shift->field_name, ipp_dce->ipp_mask->field_name
0036 
0037 #define CTX \
0038     ipp_dce->base.ctx
0039 
0040 
0041 static void dce_ipp_cursor_set_position(
0042     struct input_pixel_processor *ipp,
0043     const struct dc_cursor_position *position,
0044     const struct dc_cursor_mi_param *param)
0045 {
0046     struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp);
0047 
0048     /* lock cursor registers */
0049     REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, true);
0050 
0051     /* Flag passed in structure differentiates cursor enable/disable. */
0052     /* Update if it differs from cached state. */
0053     REG_UPDATE(CUR_CONTROL, CURSOR_EN, position->enable);
0054 
0055     REG_SET_2(CUR_POSITION, 0,
0056         CURSOR_X_POSITION, position->x,
0057         CURSOR_Y_POSITION, position->y);
0058 
0059     REG_SET_2(CUR_HOT_SPOT, 0,
0060         CURSOR_HOT_SPOT_X, position->x_hotspot,
0061         CURSOR_HOT_SPOT_Y, position->y_hotspot);
0062 
0063     /* unlock cursor registers */
0064     REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, false);
0065 }
0066 
0067 static void dce_ipp_cursor_set_attributes(
0068     struct input_pixel_processor *ipp,
0069     const struct dc_cursor_attributes *attributes)
0070 {
0071     struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp);
0072     int mode;
0073 
0074     /* Lock cursor registers */
0075     REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, true);
0076 
0077     /* Program cursor control */
0078     switch (attributes->color_format) {
0079     case CURSOR_MODE_MONO:
0080         mode = 0;
0081         break;
0082     case CURSOR_MODE_COLOR_1BIT_AND:
0083         mode = 1;
0084         break;
0085     case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA:
0086         mode = 2;
0087         break;
0088     case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA:
0089         mode = 3;
0090         break;
0091     default:
0092         BREAK_TO_DEBUGGER(); /* unsupported */
0093         mode = 0;
0094     }
0095 
0096     REG_UPDATE_3(CUR_CONTROL,
0097         CURSOR_MODE, mode,
0098         CURSOR_2X_MAGNIFY, attributes->attribute_flags.bits.ENABLE_MAGNIFICATION,
0099         CUR_INV_TRANS_CLAMP, attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING);
0100 
0101     if (attributes->color_format == CURSOR_MODE_MONO) {
0102         REG_SET_3(CUR_COLOR1, 0,
0103             CUR_COLOR1_BLUE, 0,
0104             CUR_COLOR1_GREEN, 0,
0105             CUR_COLOR1_RED, 0);
0106 
0107         REG_SET_3(CUR_COLOR2, 0,
0108             CUR_COLOR2_BLUE, 0xff,
0109             CUR_COLOR2_GREEN, 0xff,
0110             CUR_COLOR2_RED, 0xff);
0111     }
0112 
0113     /*
0114      * Program cursor size -- NOTE: HW spec specifies that HW register
0115      * stores size as (height - 1, width - 1)
0116      */
0117     REG_SET_2(CUR_SIZE, 0,
0118         CURSOR_WIDTH, attributes->width-1,
0119         CURSOR_HEIGHT, attributes->height-1);
0120 
0121     /* Program cursor surface address */
0122     /* SURFACE_ADDRESS_HIGH: Higher order bits (39:32) of hardware cursor
0123      * surface base address in byte. It is 4K byte aligned.
0124      * The correct way to program cursor surface address is to first write
0125      * to CUR_SURFACE_ADDRESS_HIGH, and then write to CUR_SURFACE_ADDRESS
0126      */
0127     REG_SET(CUR_SURFACE_ADDRESS_HIGH, 0,
0128         CURSOR_SURFACE_ADDRESS_HIGH, attributes->address.high_part);
0129 
0130     REG_SET(CUR_SURFACE_ADDRESS, 0,
0131         CURSOR_SURFACE_ADDRESS, attributes->address.low_part);
0132 
0133     /* Unlock Cursor registers. */
0134     REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, false);
0135 }
0136 
0137 
0138 static void dce_ipp_program_prescale(struct input_pixel_processor *ipp,
0139                      struct ipp_prescale_params *params)
0140 {
0141     struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp);
0142 
0143     /* set to bypass mode first before change */
0144     REG_UPDATE(PRESCALE_GRPH_CONTROL,
0145            GRPH_PRESCALE_BYPASS, 1);
0146 
0147     REG_SET_2(PRESCALE_VALUES_GRPH_R, 0,
0148           GRPH_PRESCALE_SCALE_R, params->scale,
0149           GRPH_PRESCALE_BIAS_R, params->bias);
0150 
0151     REG_SET_2(PRESCALE_VALUES_GRPH_G, 0,
0152           GRPH_PRESCALE_SCALE_G, params->scale,
0153           GRPH_PRESCALE_BIAS_G, params->bias);
0154 
0155     REG_SET_2(PRESCALE_VALUES_GRPH_B, 0,
0156           GRPH_PRESCALE_SCALE_B, params->scale,
0157           GRPH_PRESCALE_BIAS_B, params->bias);
0158 
0159     if (params->mode != IPP_PRESCALE_MODE_BYPASS) {
0160         REG_UPDATE(PRESCALE_GRPH_CONTROL,
0161                GRPH_PRESCALE_BYPASS, 0);
0162 
0163         /* If prescale is in use, then legacy lut should be bypassed */
0164         REG_UPDATE(INPUT_GAMMA_CONTROL,
0165                GRPH_INPUT_GAMMA_MODE, 1);
0166     }
0167 }
0168 
0169 static void dce_ipp_program_input_lut(
0170     struct input_pixel_processor *ipp,
0171     const struct dc_gamma *gamma)
0172 {
0173     int i;
0174     struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp);
0175 
0176     /* power on LUT memory */
0177     if (REG(DCFE_MEM_PWR_CTRL))
0178         REG_SET(DCFE_MEM_PWR_CTRL, 0, DCP_LUT_MEM_PWR_DIS, 1);
0179 
0180     /* enable all */
0181     REG_SET(DC_LUT_WRITE_EN_MASK, 0, DC_LUT_WRITE_EN_MASK, 0x7);
0182 
0183     /* 256 entry mode */
0184     REG_UPDATE(DC_LUT_RW_MODE, DC_LUT_RW_MODE, 0);
0185 
0186     /* LUT-256, unsigned, integer, new u0.12 format */
0187     REG_SET_3(DC_LUT_CONTROL, 0,
0188         DC_LUT_DATA_R_FORMAT, 3,
0189         DC_LUT_DATA_G_FORMAT, 3,
0190         DC_LUT_DATA_B_FORMAT, 3);
0191 
0192     /* start from index 0 */
0193     REG_SET(DC_LUT_RW_INDEX, 0,
0194         DC_LUT_RW_INDEX, 0);
0195 
0196     for (i = 0; i < gamma->num_entries; i++) {
0197         REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR,
0198                 dc_fixpt_round(
0199                     gamma->entries.red[i]));
0200         REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR,
0201                 dc_fixpt_round(
0202                     gamma->entries.green[i]));
0203         REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR,
0204                 dc_fixpt_round(
0205                     gamma->entries.blue[i]));
0206     }
0207 
0208     /* power off LUT memory */
0209     if (REG(DCFE_MEM_PWR_CTRL))
0210         REG_SET(DCFE_MEM_PWR_CTRL, 0, DCP_LUT_MEM_PWR_DIS, 0);
0211 
0212     /* bypass prescale, enable legacy LUT */
0213     REG_UPDATE(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 1);
0214     REG_UPDATE(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, 0);
0215 }
0216 
0217 static void dce_ipp_set_degamma(
0218     struct input_pixel_processor *ipp,
0219     enum ipp_degamma_mode mode)
0220 {
0221     struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp);
0222     uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_HW_sRGB) ? 1 : 0;
0223 
0224     ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || mode == IPP_DEGAMMA_MODE_HW_sRGB);
0225 
0226     REG_SET_3(DEGAMMA_CONTROL, 0,
0227           GRPH_DEGAMMA_MODE, degamma_type,
0228           CURSOR_DEGAMMA_MODE, degamma_type,
0229           CURSOR2_DEGAMMA_MODE, degamma_type);
0230 }
0231 
0232 #if defined(CONFIG_DRM_AMD_DC_SI)
0233 static void dce60_ipp_set_degamma(
0234     struct input_pixel_processor *ipp,
0235     enum ipp_degamma_mode mode)
0236 {
0237     struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp);
0238     uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_HW_sRGB) ? 1 : 0;
0239 
0240     ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || mode == IPP_DEGAMMA_MODE_HW_sRGB);
0241     /* DCE6 does not have CURSOR2_DEGAMMA_MODE bit in DEGAMMA_CONTROL reg */
0242     REG_SET_2(DEGAMMA_CONTROL, 0,
0243           GRPH_DEGAMMA_MODE, degamma_type,
0244           CURSOR_DEGAMMA_MODE, degamma_type);
0245 }
0246 #endif
0247 
0248 static const struct ipp_funcs dce_ipp_funcs = {
0249     .ipp_cursor_set_attributes = dce_ipp_cursor_set_attributes,
0250     .ipp_cursor_set_position = dce_ipp_cursor_set_position,
0251     .ipp_program_prescale = dce_ipp_program_prescale,
0252     .ipp_program_input_lut = dce_ipp_program_input_lut,
0253     .ipp_set_degamma = dce_ipp_set_degamma
0254 };
0255 
0256 #if defined(CONFIG_DRM_AMD_DC_SI)
0257 static const struct ipp_funcs dce60_ipp_funcs = {
0258     .ipp_cursor_set_attributes = dce_ipp_cursor_set_attributes,
0259     .ipp_cursor_set_position = dce_ipp_cursor_set_position,
0260     .ipp_program_prescale = dce_ipp_program_prescale,
0261     .ipp_program_input_lut = dce_ipp_program_input_lut,
0262     .ipp_set_degamma = dce60_ipp_set_degamma
0263 };
0264 #endif
0265 
0266 
0267 /*****************************************/
0268 /* Constructor, Destructor               */
0269 /*****************************************/
0270 
0271 void dce_ipp_construct(
0272     struct dce_ipp *ipp_dce,
0273     struct dc_context *ctx,
0274     int inst,
0275     const struct dce_ipp_registers *regs,
0276     const struct dce_ipp_shift *ipp_shift,
0277     const struct dce_ipp_mask *ipp_mask)
0278 {
0279     ipp_dce->base.ctx = ctx;
0280     ipp_dce->base.inst = inst;
0281     ipp_dce->base.funcs = &dce_ipp_funcs;
0282 
0283     ipp_dce->regs = regs;
0284     ipp_dce->ipp_shift = ipp_shift;
0285     ipp_dce->ipp_mask = ipp_mask;
0286 }
0287 
0288 #if defined(CONFIG_DRM_AMD_DC_SI)
0289 void dce60_ipp_construct(
0290     struct dce_ipp *ipp_dce,
0291     struct dc_context *ctx,
0292     int inst,
0293     const struct dce_ipp_registers *regs,
0294     const struct dce_ipp_shift *ipp_shift,
0295     const struct dce_ipp_mask *ipp_mask)
0296 {
0297     ipp_dce->base.ctx = ctx;
0298     ipp_dce->base.inst = inst;
0299     ipp_dce->base.funcs = &dce60_ipp_funcs;
0300 
0301     ipp_dce->regs = regs;
0302     ipp_dce->ipp_shift = ipp_shift;
0303     ipp_dce->ipp_mask = ipp_mask;
0304 }
0305 #endif
0306 
0307 void dce_ipp_destroy(struct input_pixel_processor **ipp)
0308 {
0309     kfree(TO_DCE_IPP(*ipp));
0310     *ipp = NULL;
0311 }