170ccab60SHarry Wentland /* 270ccab60SHarry Wentland * Copyright 2017 Advanced Micro Devices, Inc. 370ccab60SHarry Wentland * 470ccab60SHarry Wentland * Permission is hereby granted, free of charge, to any person obtaining a 570ccab60SHarry Wentland * copy of this software and associated documentation files (the "Software"), 670ccab60SHarry Wentland * to deal in the Software without restriction, including without limitation 770ccab60SHarry Wentland * the rights to use, copy, modify, merge, publish, distribute, sublicense, 870ccab60SHarry Wentland * and/or sell copies of the Software, and to permit persons to whom the 970ccab60SHarry Wentland * Software is furnished to do so, subject to the following conditions: 1070ccab60SHarry Wentland * 1170ccab60SHarry Wentland * The above copyright notice and this permission notice shall be included in 1270ccab60SHarry Wentland * all copies or substantial portions of the Software. 1370ccab60SHarry Wentland * 1470ccab60SHarry Wentland * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1570ccab60SHarry Wentland * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1670ccab60SHarry Wentland * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1770ccab60SHarry Wentland * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 1870ccab60SHarry Wentland * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 1970ccab60SHarry Wentland * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2070ccab60SHarry Wentland * OTHER DEALINGS IN THE SOFTWARE. 2170ccab60SHarry Wentland * 2270ccab60SHarry Wentland * Authors: AMD 2370ccab60SHarry Wentland * 2470ccab60SHarry Wentland */ 2570ccab60SHarry Wentland 2670ccab60SHarry Wentland #include "dm_services.h" 2770ccab60SHarry Wentland #include "dcn10_ipp.h" 2870ccab60SHarry Wentland #include "reg_helper.h" 2970ccab60SHarry Wentland 3070ccab60SHarry Wentland #define REG(reg) \ 3170ccab60SHarry Wentland (ippn10->regs->reg) 3270ccab60SHarry Wentland 3370ccab60SHarry Wentland #undef FN 3470ccab60SHarry Wentland #define FN(reg_name, field_name) \ 3570ccab60SHarry Wentland ippn10->ipp_shift->field_name, ippn10->ipp_mask->field_name 3670ccab60SHarry Wentland 3770ccab60SHarry Wentland #define CTX \ 3870ccab60SHarry Wentland ippn10->base.ctx 3970ccab60SHarry Wentland 40a3ac9dadSDmytro Laktyushkin static bool ippn10_cursor_program_control( 4170ccab60SHarry Wentland struct dcn10_ipp *ippn10, 4270ccab60SHarry Wentland bool pixel_data_invert, 4370ccab60SHarry Wentland enum dc_cursor_color_format color_format) 4470ccab60SHarry Wentland { 4551666631SDmytro Laktyushkin if (REG(CURSOR_SETTINS)) 4670ccab60SHarry Wentland REG_SET_2(CURSOR_SETTINS, 0, 4770ccab60SHarry Wentland /* no shift of the cursor HDL schedule */ 4870ccab60SHarry Wentland CURSOR0_DST_Y_OFFSET, 0, 4970ccab60SHarry Wentland /* used to shift the cursor chunk request deadline */ 5070ccab60SHarry Wentland CURSOR0_CHUNK_HDL_ADJUST, 3); 5151666631SDmytro Laktyushkin else 5251666631SDmytro Laktyushkin REG_SET_2(CURSOR_SETTINGS, 0, 5351666631SDmytro Laktyushkin /* no shift of the cursor HDL schedule */ 5451666631SDmytro Laktyushkin CURSOR0_DST_Y_OFFSET, 0, 5551666631SDmytro Laktyushkin /* used to shift the cursor chunk request deadline */ 5651666631SDmytro Laktyushkin CURSOR0_CHUNK_HDL_ADJUST, 3); 5770ccab60SHarry Wentland 5870ccab60SHarry Wentland REG_UPDATE_2(CURSOR0_CONTROL, 5970ccab60SHarry Wentland CUR0_MODE, color_format, 6035ce37d6SDmytro Laktyushkin CUR0_EXPANSION_MODE, 0); 6170ccab60SHarry Wentland 6270ccab60SHarry Wentland if (color_format == CURSOR_MODE_MONO) { 6370ccab60SHarry Wentland /* todo: clarify what to program these to */ 6470ccab60SHarry Wentland REG_UPDATE(CURSOR0_COLOR0, 6570ccab60SHarry Wentland CUR0_COLOR0, 0x00000000); 6670ccab60SHarry Wentland REG_UPDATE(CURSOR0_COLOR1, 6770ccab60SHarry Wentland CUR0_COLOR1, 0xFFFFFFFF); 6870ccab60SHarry Wentland } 6970ccab60SHarry Wentland 7070ccab60SHarry Wentland /* TODO: Fixed vs float */ 7170ccab60SHarry Wentland 7270ccab60SHarry Wentland REG_UPDATE_3(FORMAT_CONTROL, 7370ccab60SHarry Wentland CNVC_BYPASS, 0, 7470ccab60SHarry Wentland ALPHA_EN, 1, 7570ccab60SHarry Wentland FORMAT_EXPANSION_MODE, 0); 7670ccab60SHarry Wentland 7770ccab60SHarry Wentland return true; 7870ccab60SHarry Wentland } 7970ccab60SHarry Wentland 8070ccab60SHarry Wentland enum cursor_pitch { 8170ccab60SHarry Wentland CURSOR_PITCH_64_PIXELS = 0, 8270ccab60SHarry Wentland CURSOR_PITCH_128_PIXELS, 8370ccab60SHarry Wentland CURSOR_PITCH_256_PIXELS 8470ccab60SHarry Wentland }; 8570ccab60SHarry Wentland 8670ccab60SHarry Wentland enum cursor_lines_per_chunk { 8770ccab60SHarry Wentland CURSOR_LINE_PER_CHUNK_2 = 1, 8870ccab60SHarry Wentland CURSOR_LINE_PER_CHUNK_4, 8970ccab60SHarry Wentland CURSOR_LINE_PER_CHUNK_8, 9070ccab60SHarry Wentland CURSOR_LINE_PER_CHUNK_16 9170ccab60SHarry Wentland }; 9270ccab60SHarry Wentland 93a3ac9dadSDmytro Laktyushkin static enum cursor_pitch ippn10_get_cursor_pitch( 9470ccab60SHarry Wentland unsigned int pitch) 9570ccab60SHarry Wentland { 9670ccab60SHarry Wentland enum cursor_pitch hw_pitch; 9770ccab60SHarry Wentland 9870ccab60SHarry Wentland switch (pitch) { 9970ccab60SHarry Wentland case 64: 10070ccab60SHarry Wentland hw_pitch = CURSOR_PITCH_64_PIXELS; 10170ccab60SHarry Wentland break; 10270ccab60SHarry Wentland case 128: 10370ccab60SHarry Wentland hw_pitch = CURSOR_PITCH_128_PIXELS; 10470ccab60SHarry Wentland break; 10570ccab60SHarry Wentland case 256: 10670ccab60SHarry Wentland hw_pitch = CURSOR_PITCH_256_PIXELS; 10770ccab60SHarry Wentland break; 10870ccab60SHarry Wentland default: 10970ccab60SHarry Wentland DC_ERR("Invalid cursor pitch of %d. " 11070ccab60SHarry Wentland "Only 64/128/256 is supported on DCN.\n", pitch); 11170ccab60SHarry Wentland hw_pitch = CURSOR_PITCH_64_PIXELS; 11270ccab60SHarry Wentland break; 11370ccab60SHarry Wentland } 11470ccab60SHarry Wentland return hw_pitch; 11570ccab60SHarry Wentland } 11670ccab60SHarry Wentland 117a3ac9dadSDmytro Laktyushkin static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( 11870ccab60SHarry Wentland unsigned int cur_width, 11970ccab60SHarry Wentland enum dc_cursor_color_format format) 12070ccab60SHarry Wentland { 12170ccab60SHarry Wentland enum cursor_lines_per_chunk line_per_chunk; 12270ccab60SHarry Wentland 12370ccab60SHarry Wentland if (format == CURSOR_MODE_MONO) 12470ccab60SHarry Wentland /* impl B. expansion in CUR Buffer reader */ 12570ccab60SHarry Wentland line_per_chunk = CURSOR_LINE_PER_CHUNK_16; 12670ccab60SHarry Wentland else if (cur_width <= 32) 12770ccab60SHarry Wentland line_per_chunk = CURSOR_LINE_PER_CHUNK_16; 12870ccab60SHarry Wentland else if (cur_width <= 64) 12970ccab60SHarry Wentland line_per_chunk = CURSOR_LINE_PER_CHUNK_8; 13070ccab60SHarry Wentland else if (cur_width <= 128) 13170ccab60SHarry Wentland line_per_chunk = CURSOR_LINE_PER_CHUNK_4; 13270ccab60SHarry Wentland else 13370ccab60SHarry Wentland line_per_chunk = CURSOR_LINE_PER_CHUNK_2; 13470ccab60SHarry Wentland 13570ccab60SHarry Wentland return line_per_chunk; 13670ccab60SHarry Wentland } 13770ccab60SHarry Wentland 138a3ac9dadSDmytro Laktyushkin static void ippn10_cursor_set_attributes( 13970ccab60SHarry Wentland struct input_pixel_processor *ipp, 14070ccab60SHarry Wentland const struct dc_cursor_attributes *attr) 14170ccab60SHarry Wentland { 14270ccab60SHarry Wentland struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); 143a3ac9dadSDmytro Laktyushkin enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch); 144a3ac9dadSDmytro Laktyushkin enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk( 14570ccab60SHarry Wentland attr->width, attr->color_format); 14670ccab60SHarry Wentland 14770ccab60SHarry Wentland ippn10->curs_attr = *attr; 14870ccab60SHarry Wentland 14970ccab60SHarry Wentland REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH, 15070ccab60SHarry Wentland CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part); 15170ccab60SHarry Wentland REG_UPDATE(CURSOR_SURFACE_ADDRESS, 15270ccab60SHarry Wentland CURSOR_SURFACE_ADDRESS, attr->address.low_part); 15370ccab60SHarry Wentland 15470ccab60SHarry Wentland REG_UPDATE_2(CURSOR_SIZE, 15570ccab60SHarry Wentland CURSOR_WIDTH, attr->width, 15670ccab60SHarry Wentland CURSOR_HEIGHT, attr->height); 15770ccab60SHarry Wentland REG_UPDATE_3(CURSOR_CONTROL, 15870ccab60SHarry Wentland CURSOR_MODE, attr->color_format, 15970ccab60SHarry Wentland CURSOR_PITCH, hw_pitch, 16070ccab60SHarry Wentland CURSOR_LINES_PER_CHUNK, lpc); 161a3ac9dadSDmytro Laktyushkin ippn10_cursor_program_control(ippn10, 16270ccab60SHarry Wentland attr->attribute_flags.bits.INVERT_PIXEL_DATA, 16370ccab60SHarry Wentland attr->color_format); 16470ccab60SHarry Wentland } 16570ccab60SHarry Wentland 166a3ac9dadSDmytro Laktyushkin static void ippn10_cursor_set_position( 16770ccab60SHarry Wentland struct input_pixel_processor *ipp, 16870ccab60SHarry Wentland const struct dc_cursor_position *pos, 16970ccab60SHarry Wentland const struct dc_cursor_mi_param *param) 17070ccab60SHarry Wentland { 17170ccab60SHarry Wentland struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); 17270ccab60SHarry Wentland int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start; 17370ccab60SHarry Wentland uint32_t cur_en = pos->enable ? 1 : 0; 17470ccab60SHarry Wentland uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; 17570ccab60SHarry Wentland 176d3ec0562SLeo (Sunpeng) Li /* 177d3ec0562SLeo (Sunpeng) Li * Guard aganst cursor_set_position() from being called with invalid 178d3ec0562SLeo (Sunpeng) Li * attributes 179d3ec0562SLeo (Sunpeng) Li * 180d3ec0562SLeo (Sunpeng) Li * TODO: Look at combining cursor_set_position() and 181d3ec0562SLeo (Sunpeng) Li * cursor_set_attributes() into cursor_update() 182d3ec0562SLeo (Sunpeng) Li */ 183d3ec0562SLeo (Sunpeng) Li if (ippn10->curs_attr.address.quad_part == 0) 184d3ec0562SLeo (Sunpeng) Li return; 185d3ec0562SLeo (Sunpeng) Li 18670ccab60SHarry Wentland dst_x_offset *= param->ref_clk_khz; 18770ccab60SHarry Wentland dst_x_offset /= param->pixel_clk_khz; 18870ccab60SHarry Wentland 18970ccab60SHarry Wentland ASSERT(param->h_scale_ratio.value); 19070ccab60SHarry Wentland 19170ccab60SHarry Wentland if (param->h_scale_ratio.value) 19270ccab60SHarry Wentland dst_x_offset = dal_fixed31_32_floor(dal_fixed31_32_div( 19370ccab60SHarry Wentland dal_fixed31_32_from_int(dst_x_offset), 19470ccab60SHarry Wentland param->h_scale_ratio)); 19570ccab60SHarry Wentland 19670ccab60SHarry Wentland if (src_x_offset >= (int)param->viewport_width) 19770ccab60SHarry Wentland cur_en = 0; /* not visible beyond right edge*/ 19870ccab60SHarry Wentland 19970ccab60SHarry Wentland if (src_x_offset + (int)ippn10->curs_attr.width < 0) 20070ccab60SHarry Wentland cur_en = 0; /* not visible beyond left edge*/ 20170ccab60SHarry Wentland 20270ccab60SHarry Wentland if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) 203a3ac9dadSDmytro Laktyushkin ippn10_cursor_set_attributes(ipp, &ippn10->curs_attr); 20470ccab60SHarry Wentland REG_UPDATE(CURSOR_CONTROL, 20570ccab60SHarry Wentland CURSOR_ENABLE, cur_en); 20670ccab60SHarry Wentland REG_UPDATE(CURSOR0_CONTROL, 20770ccab60SHarry Wentland CUR0_ENABLE, cur_en); 20870ccab60SHarry Wentland 20970ccab60SHarry Wentland REG_SET_2(CURSOR_POSITION, 0, 21070ccab60SHarry Wentland CURSOR_X_POSITION, pos->x, 21170ccab60SHarry Wentland CURSOR_Y_POSITION, pos->y); 21270ccab60SHarry Wentland 21370ccab60SHarry Wentland REG_SET_2(CURSOR_HOT_SPOT, 0, 21470ccab60SHarry Wentland CURSOR_HOT_SPOT_X, pos->x_hotspot, 21570ccab60SHarry Wentland CURSOR_HOT_SPOT_Y, pos->y_hotspot); 21670ccab60SHarry Wentland 21770ccab60SHarry Wentland REG_SET(CURSOR_DST_OFFSET, 0, 21870ccab60SHarry Wentland CURSOR_DST_X_OFFSET, dst_x_offset); 21970ccab60SHarry Wentland /* TODO Handle surface pixel formats other than 4:4:4 */ 22070ccab60SHarry Wentland } 22170ccab60SHarry Wentland 22270ccab60SHarry Wentland /*****************************************/ 22370ccab60SHarry Wentland /* Constructor, Destructor */ 22470ccab60SHarry Wentland /*****************************************/ 22570ccab60SHarry Wentland 22670ccab60SHarry Wentland static void dcn10_ipp_destroy(struct input_pixel_processor **ipp) 22770ccab60SHarry Wentland { 2282004f45eSHarry Wentland kfree(TO_DCN10_IPP(*ipp)); 22970ccab60SHarry Wentland *ipp = NULL; 23070ccab60SHarry Wentland } 23170ccab60SHarry Wentland 23270ccab60SHarry Wentland static const struct ipp_funcs dcn10_ipp_funcs = { 233a3ac9dadSDmytro Laktyushkin .ipp_cursor_set_attributes = ippn10_cursor_set_attributes, 234a3ac9dadSDmytro Laktyushkin .ipp_cursor_set_position = ippn10_cursor_set_position, 235b3c340faSYue Hin Lau .ipp_set_degamma = NULL, 236b3c340faSYue Hin Lau .ipp_program_input_lut = NULL, 237b3c340faSYue Hin Lau .ipp_full_bypass = NULL, 238b3c340faSYue Hin Lau .ipp_setup = NULL, 239b3c340faSYue Hin Lau .ipp_program_degamma_pwl = NULL, 24070ccab60SHarry Wentland .ipp_destroy = dcn10_ipp_destroy 24170ccab60SHarry Wentland }; 24270ccab60SHarry Wentland 24370ccab60SHarry Wentland void dcn10_ipp_construct( 24470ccab60SHarry Wentland struct dcn10_ipp *ippn10, 24570ccab60SHarry Wentland struct dc_context *ctx, 24670ccab60SHarry Wentland int inst, 24770ccab60SHarry Wentland const struct dcn10_ipp_registers *regs, 24870ccab60SHarry Wentland const struct dcn10_ipp_shift *ipp_shift, 24970ccab60SHarry Wentland const struct dcn10_ipp_mask *ipp_mask) 25070ccab60SHarry Wentland { 25170ccab60SHarry Wentland ippn10->base.ctx = ctx; 25270ccab60SHarry Wentland ippn10->base.inst = inst; 25370ccab60SHarry Wentland ippn10->base.funcs = &dcn10_ipp_funcs; 25470ccab60SHarry Wentland 25570ccab60SHarry Wentland ippn10->regs = regs; 25670ccab60SHarry Wentland ippn10->ipp_shift = ipp_shift; 25770ccab60SHarry Wentland ippn10->ipp_mask = ipp_mask; 25870ccab60SHarry Wentland } 259a3ac9dadSDmytro Laktyushkin 260