aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2506-drm-amd-display-moving-cursor-functions-from-ipp-to-.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2506-drm-amd-display-moving-cursor-functions-from-ipp-to-.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2506-drm-amd-display-moving-cursor-functions-from-ipp-to-.patch762
1 files changed, 762 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2506-drm-amd-display-moving-cursor-functions-from-ipp-to-.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2506-drm-amd-display-moving-cursor-functions-from-ipp-to-.patch
new file mode 100644
index 00000000..9c0d69c3
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2506-drm-amd-display-moving-cursor-functions-from-ipp-to-.patch
@@ -0,0 +1,762 @@
+From cb8f7d1a867881f80ef1128274fd05221b2ca09c Mon Sep 17 00:00:00 2001
+From: Yue Hin Lau <Yuehin.Lau@amd.com>
+Date: Tue, 19 Sep 2017 17:29:28 -0400
+Subject: [PATCH 2506/4131] drm/amd/display: moving cursor functions from ipp
+ to mem_input
+
+Signed-off-by: Yue Hin Lau <Yuehin.Lau@amd.com>
+Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
+Acked-by: Harry Wentland <Harry.Wentland@amd.com>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 32 +++-
+ drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c | 2 +
+ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 51 ++++++
+ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 15 +-
+ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 189 ---------------------
+ .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 163 ++++++++++++++++++
+ .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 57 ++++++-
+ drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 10 ++
+ drivers/gpu/drm/amd/display/dc/inc/hw/transform.h | 11 ++
+ 9 files changed, 329 insertions(+), 201 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+index 23df7bc..c19b478 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+@@ -195,13 +195,23 @@ bool dc_stream_set_cursor_attributes(
+ for (i = 0; i < MAX_PIPES; i++) {
+ struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
+
+- if (pipe_ctx->stream != stream || !pipe_ctx->plane_res.ipp)
++ if (pipe_ctx->stream != stream || !pipe_ctx->plane_res.mi || !pipe_ctx->plane_res.xfm)
+ continue;
+ if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
+ continue;
+
+- pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes(
+- pipe_ctx->plane_res.ipp, attributes);
++
++ if (pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes != NULL)
++ pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes(
++ pipe_ctx->plane_res.ipp, attributes);
++
++ if (pipe_ctx->plane_res.mi->funcs->set_cursor_attributes != NULL)
++ pipe_ctx->plane_res.mi->funcs->set_cursor_attributes(
++ pipe_ctx->plane_res.mi, attributes);
++
++ if (pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes != NULL)
++ pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes(
++ pipe_ctx->plane_res.xfm, attributes);
+ }
+
+ return true;
+@@ -231,6 +241,8 @@ bool dc_stream_set_cursor_position(
+ for (i = 0; i < MAX_PIPES; i++) {
+ struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
+ struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
++ struct mem_input *mi = pipe_ctx->plane_res.mi;
++ struct transform *xfm = pipe_ctx->plane_res.xfm;
+ struct dc_cursor_position pos_cpy = *position;
+ struct dc_cursor_mi_param param = {
+ .pixel_clk_khz = stream->timing.pix_clk_khz,
+@@ -241,7 +253,9 @@ bool dc_stream_set_cursor_position(
+ };
+
+ if (pipe_ctx->stream != stream ||
+- !pipe_ctx->plane_res.ipp || !pipe_ctx->plane_state)
++ !pipe_ctx->plane_res.mi ||
++ !pipe_ctx->plane_state ||
++ !pipe_ctx->plane_res.xfm)
+ continue;
+
+ if (pipe_ctx->plane_state->address.type
+@@ -251,7 +265,15 @@ bool dc_stream_set_cursor_position(
+ if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
+ pos_cpy.enable = false;
+
+- ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, &param);
++
++ if (ipp->funcs->ipp_cursor_set_position != NULL)
++ ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, &param);
++
++ if (mi->funcs->set_cursor_attributes != NULL)
++ mi->funcs->set_cursor_position(mi, &pos_cpy, &param);
++
++ if (xfm->funcs->set_cursor_attributes != NULL)
++ xfm->funcs->set_cursor_position(xfm, &pos_cpy, &param, mi->curs_attr.width);
+ }
+
+ return true;
+diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c
+index fa481d4..d618fdd 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c
++++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c
+@@ -37,6 +37,7 @@
+ #define CTX \
+ ipp_dce->base.ctx
+
++
+ static void dce_ipp_cursor_set_position(
+ struct input_pixel_processor *ipp,
+ const struct dc_cursor_position *position,
+@@ -133,6 +134,7 @@ static void dce_ipp_cursor_set_attributes(
+ REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, false);
+ }
+
++
+ static void dce_ipp_program_prescale(
+ struct input_pixel_processor *ipp,
+ struct ipp_prescale_params *params)
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c
+index f9e43e6..05df3b2 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c
+@@ -372,6 +372,55 @@ void ippn10_cnv_setup (
+ }
+ }
+
++void dcn10_set_cursor_attributes(
++ struct transform *xfm_base,
++ const struct dc_cursor_attributes *attr)
++{
++ struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
++ enum dc_cursor_color_format color_format = attr->color_format;
++
++ REG_UPDATE_2(CURSOR0_CONTROL,
++ CUR0_MODE, color_format,
++ CUR0_EXPANSION_MODE, 0);
++
++ if (color_format == CURSOR_MODE_MONO) {
++ /* todo: clarify what to program these to */
++ REG_UPDATE(CURSOR0_COLOR0,
++ CUR0_COLOR0, 0x00000000);
++ REG_UPDATE(CURSOR0_COLOR1,
++ CUR0_COLOR1, 0xFFFFFFFF);
++ }
++
++ /* TODO: Fixed vs float */
++
++ REG_UPDATE_3(FORMAT_CONTROL,
++ CNVC_BYPASS, 0,
++ FORMAT_CONTROL__ALPHA_EN, 1,
++ FORMAT_EXPANSION_MODE, 0);
++}
++
++
++void dcn10_set_cursor_position(
++ struct transform *xfm_base,
++ const struct dc_cursor_position *pos,
++ const struct dc_cursor_mi_param *param,
++ uint32_t width)
++{
++ struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
++ int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start;
++ uint32_t cur_en = pos->enable ? 1 : 0;
++
++ if (src_x_offset >= (int)param->viewport_width)
++ cur_en = 0; /* not visible beyond right edge*/
++
++ if (src_x_offset + (int)width < 0)
++ cur_en = 0; /* not visible beyond left edge*/
++
++ REG_UPDATE(CURSOR0_CONTROL,
++ CUR0_ENABLE, cur_en);
++
++}
++
+ static const struct transform_funcs dcn10_dpp_funcs = {
+ .transform_reset = dpp_reset,
+ .transform_set_scaler = dcn10_dpp_dscl_set_scaler_manual_scale,
+@@ -391,6 +440,8 @@ static const struct transform_funcs dcn10_dpp_funcs = {
+ .ipp_program_degamma_pwl = ippn10_set_degamma_pwl,
+ .ipp_setup = ippn10_cnv_setup,
+ .ipp_full_bypass = ippn10_full_bypass,
++ .set_cursor_attributes = dcn10_set_cursor_attributes,
++ .set_cursor_position = dcn10_set_cursor_position,
+ };
+
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h
+index a1f6b01..7fecdb1 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h
+@@ -112,7 +112,10 @@
+ SRI(CM_DGAM_CONTROL, CM, id), \
+ SRI(FORMAT_CONTROL, CNVC_CFG, id), \
+ SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \
+- SRI(CURSOR0_CONTROL, CNVC_CUR, id)
++ SRI(CURSOR0_CONTROL, CNVC_CUR, id), \
++ SRI(CURSOR0_CONTROL, CNVC_CUR, id), \
++ SRI(CURSOR0_COLOR0, CNVC_CUR, id), \
++ SRI(CURSOR0_COLOR1, CNVC_CUR, id)
+
+
+
+@@ -302,7 +305,9 @@
+ TF_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \
+ TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \
+ TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_EXPANSION_MODE, mask_sh), \
+- TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh)
++ TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh), \
++ TF_SF(CNVC_CUR0_CURSOR0_COLOR0, CUR0_COLOR0, mask_sh), \
++ TF_SF(CNVC_CUR0_CURSOR0_COLOR1, CUR0_COLOR1, mask_sh)
+
+ #define TF_REG_LIST_SH_MASK_DCN10(mask_sh)\
+ TF_REG_LIST_SH_MASK_DCN(mask_sh),\
+@@ -989,7 +994,9 @@
+ type CUR0_EXPANSION_MODE; \
+ type CUR0_ENABLE; \
+ type CM_BYPASS; \
+- type FORMAT_CONTROL__ALPHA_EN
++ type FORMAT_CONTROL__ALPHA_EN; \
++ type CUR0_COLOR0; \
++ type CUR0_COLOR1
+
+
+
+@@ -1237,6 +1244,8 @@ struct dcn_dpp_registers {
+ uint32_t CNVC_SURFACE_PIXEL_FORMAT;
+ uint32_t CURSOR_CONTROL;
+ uint32_t CURSOR0_CONTROL;
++ uint32_t CURSOR0_COLOR0;
++ uint32_t CURSOR0_COLOR1;
+ };
+
+ struct dcn10_dpp {
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c
+index 67bd6a7..08db1e6 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c
+@@ -37,188 +37,6 @@
+ #define CTX \
+ ippn10->base.ctx
+
+-static bool ippn10_cursor_program_control(
+- struct dcn10_ipp *ippn10,
+- bool pixel_data_invert,
+- enum dc_cursor_color_format color_format)
+-{
+- if (REG(CURSOR_SETTINS))
+- REG_SET_2(CURSOR_SETTINS, 0,
+- /* no shift of the cursor HDL schedule */
+- CURSOR0_DST_Y_OFFSET, 0,
+- /* used to shift the cursor chunk request deadline */
+- CURSOR0_CHUNK_HDL_ADJUST, 3);
+- else
+- REG_SET_2(CURSOR_SETTINGS, 0,
+- /* no shift of the cursor HDL schedule */
+- CURSOR0_DST_Y_OFFSET, 0,
+- /* used to shift the cursor chunk request deadline */
+- CURSOR0_CHUNK_HDL_ADJUST, 3);
+-
+- REG_UPDATE_2(CURSOR0_CONTROL,
+- CUR0_MODE, color_format,
+- CUR0_EXPANSION_MODE, 0);
+-
+- if (color_format == CURSOR_MODE_MONO) {
+- /* todo: clarify what to program these to */
+- REG_UPDATE(CURSOR0_COLOR0,
+- CUR0_COLOR0, 0x00000000);
+- REG_UPDATE(CURSOR0_COLOR1,
+- CUR0_COLOR1, 0xFFFFFFFF);
+- }
+-
+- /* TODO: Fixed vs float */
+-
+- REG_UPDATE_3(FORMAT_CONTROL,
+- CNVC_BYPASS, 0,
+- ALPHA_EN, 1,
+- FORMAT_EXPANSION_MODE, 0);
+-
+- return true;
+-}
+-
+-enum cursor_pitch {
+- CURSOR_PITCH_64_PIXELS = 0,
+- CURSOR_PITCH_128_PIXELS,
+- CURSOR_PITCH_256_PIXELS
+-};
+-
+-enum cursor_lines_per_chunk {
+- CURSOR_LINE_PER_CHUNK_2 = 1,
+- CURSOR_LINE_PER_CHUNK_4,
+- CURSOR_LINE_PER_CHUNK_8,
+- CURSOR_LINE_PER_CHUNK_16
+-};
+-
+-static enum cursor_pitch ippn10_get_cursor_pitch(
+- unsigned int pitch)
+-{
+- enum cursor_pitch hw_pitch;
+-
+- switch (pitch) {
+- case 64:
+- hw_pitch = CURSOR_PITCH_64_PIXELS;
+- break;
+- case 128:
+- hw_pitch = CURSOR_PITCH_128_PIXELS;
+- break;
+- case 256:
+- hw_pitch = CURSOR_PITCH_256_PIXELS;
+- break;
+- default:
+- DC_ERR("Invalid cursor pitch of %d. "
+- "Only 64/128/256 is supported on DCN.\n", pitch);
+- hw_pitch = CURSOR_PITCH_64_PIXELS;
+- break;
+- }
+- return hw_pitch;
+-}
+-
+-static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk(
+- unsigned int cur_width,
+- enum dc_cursor_color_format format)
+-{
+- enum cursor_lines_per_chunk line_per_chunk;
+-
+- if (format == CURSOR_MODE_MONO)
+- /* impl B. expansion in CUR Buffer reader */
+- line_per_chunk = CURSOR_LINE_PER_CHUNK_16;
+- else if (cur_width <= 32)
+- line_per_chunk = CURSOR_LINE_PER_CHUNK_16;
+- else if (cur_width <= 64)
+- line_per_chunk = CURSOR_LINE_PER_CHUNK_8;
+- else if (cur_width <= 128)
+- line_per_chunk = CURSOR_LINE_PER_CHUNK_4;
+- else
+- line_per_chunk = CURSOR_LINE_PER_CHUNK_2;
+-
+- return line_per_chunk;
+-}
+-
+-static void ippn10_cursor_set_attributes(
+- struct input_pixel_processor *ipp,
+- const struct dc_cursor_attributes *attr)
+-{
+- struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
+- enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch);
+- enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk(
+- attr->width, attr->color_format);
+-
+- ippn10->curs_attr = *attr;
+-
+- REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH,
+- CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part);
+- REG_UPDATE(CURSOR_SURFACE_ADDRESS,
+- CURSOR_SURFACE_ADDRESS, attr->address.low_part);
+-
+- REG_UPDATE_2(CURSOR_SIZE,
+- CURSOR_WIDTH, attr->width,
+- CURSOR_HEIGHT, attr->height);
+- REG_UPDATE_3(CURSOR_CONTROL,
+- CURSOR_MODE, attr->color_format,
+- CURSOR_PITCH, hw_pitch,
+- CURSOR_LINES_PER_CHUNK, lpc);
+- ippn10_cursor_program_control(ippn10,
+- attr->attribute_flags.bits.INVERT_PIXEL_DATA,
+- attr->color_format);
+-}
+-
+-static void ippn10_cursor_set_position(
+- struct input_pixel_processor *ipp,
+- const struct dc_cursor_position *pos,
+- const struct dc_cursor_mi_param *param)
+-{
+- struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
+- int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start;
+- uint32_t cur_en = pos->enable ? 1 : 0;
+- uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0;
+-
+- /*
+- * Guard aganst cursor_set_position() from being called with invalid
+- * attributes
+- *
+- * TODO: Look at combining cursor_set_position() and
+- * cursor_set_attributes() into cursor_update()
+- */
+- if (ippn10->curs_attr.address.quad_part == 0)
+- return;
+-
+- dst_x_offset *= param->ref_clk_khz;
+- dst_x_offset /= param->pixel_clk_khz;
+-
+- ASSERT(param->h_scale_ratio.value);
+-
+- if (param->h_scale_ratio.value)
+- dst_x_offset = dal_fixed31_32_floor(dal_fixed31_32_div(
+- dal_fixed31_32_from_int(dst_x_offset),
+- param->h_scale_ratio));
+-
+- if (src_x_offset >= (int)param->viewport_width)
+- cur_en = 0; /* not visible beyond right edge*/
+-
+- if (src_x_offset + (int)ippn10->curs_attr.width < 0)
+- cur_en = 0; /* not visible beyond left edge*/
+-
+- if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0)
+- ippn10_cursor_set_attributes(ipp, &ippn10->curs_attr);
+- REG_UPDATE(CURSOR_CONTROL,
+- CURSOR_ENABLE, cur_en);
+- REG_UPDATE(CURSOR0_CONTROL,
+- CUR0_ENABLE, cur_en);
+-
+- REG_SET_2(CURSOR_POSITION, 0,
+- CURSOR_X_POSITION, pos->x,
+- CURSOR_Y_POSITION, pos->y);
+-
+- REG_SET_2(CURSOR_HOT_SPOT, 0,
+- CURSOR_HOT_SPOT_X, pos->x_hotspot,
+- CURSOR_HOT_SPOT_Y, pos->y_hotspot);
+-
+- REG_SET(CURSOR_DST_OFFSET, 0,
+- CURSOR_DST_X_OFFSET, dst_x_offset);
+- /* TODO Handle surface pixel formats other than 4:4:4 */
+-}
+-
+ /*****************************************/
+ /* Constructor, Destructor */
+ /*****************************************/
+@@ -230,13 +48,6 @@ static void dcn10_ipp_destroy(struct input_pixel_processor **ipp)
+ }
+
+ static const struct ipp_funcs dcn10_ipp_funcs = {
+- .ipp_cursor_set_attributes = ippn10_cursor_set_attributes,
+- .ipp_cursor_set_position = ippn10_cursor_set_position,
+- .ipp_set_degamma = NULL,
+- .ipp_program_input_lut = NULL,
+- .ipp_full_bypass = NULL,
+- .ipp_setup = NULL,
+- .ipp_program_degamma_pwl = NULL,
+ .ipp_destroy = dcn10_ipp_destroy
+ };
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c
+index a28495d..efa1aca 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c
+@@ -766,6 +766,167 @@ void dcn10_mem_input_read_state(struct dcn10_mem_input *mi,
+ QoS_LEVEL_HIGH_WM, &s->qos_level_high_wm);
+ }
+
++enum cursor_pitch {
++ CURSOR_PITCH_64_PIXELS = 0,
++ CURSOR_PITCH_128_PIXELS,
++ CURSOR_PITCH_256_PIXELS
++};
++
++enum cursor_lines_per_chunk {
++ CURSOR_LINE_PER_CHUNK_2 = 1,
++ CURSOR_LINE_PER_CHUNK_4,
++ CURSOR_LINE_PER_CHUNK_8,
++ CURSOR_LINE_PER_CHUNK_16
++};
++
++static bool ippn10_cursor_program_control(
++ struct dcn10_mem_input *mi,
++ bool pixel_data_invert,
++ enum dc_cursor_color_format color_format)
++{
++ if (REG(CURSOR_SETTINS))
++ REG_SET_2(CURSOR_SETTINS, 0,
++ /* no shift of the cursor HDL schedule */
++ CURSOR0_DST_Y_OFFSET, 0,
++ /* used to shift the cursor chunk request deadline */
++ CURSOR0_CHUNK_HDL_ADJUST, 3);
++ else
++ REG_SET_2(CURSOR_SETTINGS, 0,
++ /* no shift of the cursor HDL schedule */
++ CURSOR0_DST_Y_OFFSET, 0,
++ /* used to shift the cursor chunk request deadline */
++ CURSOR0_CHUNK_HDL_ADJUST, 3);
++
++ return true;
++}
++
++static enum cursor_pitch ippn10_get_cursor_pitch(
++ unsigned int pitch)
++{
++ enum cursor_pitch hw_pitch;
++
++ switch (pitch) {
++ case 64:
++ hw_pitch = CURSOR_PITCH_64_PIXELS;
++ break;
++ case 128:
++ hw_pitch = CURSOR_PITCH_128_PIXELS;
++ break;
++ case 256:
++ hw_pitch = CURSOR_PITCH_256_PIXELS;
++ break;
++ default:
++ DC_ERR("Invalid cursor pitch of %d. "
++ "Only 64/128/256 is supported on DCN.\n", pitch);
++ hw_pitch = CURSOR_PITCH_64_PIXELS;
++ break;
++ }
++ return hw_pitch;
++}
++
++static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk(
++ unsigned int cur_width,
++ enum dc_cursor_color_format format)
++{
++ enum cursor_lines_per_chunk line_per_chunk;
++
++ if (format == CURSOR_MODE_MONO)
++ /* impl B. expansion in CUR Buffer reader */
++ line_per_chunk = CURSOR_LINE_PER_CHUNK_16;
++ else if (cur_width <= 32)
++ line_per_chunk = CURSOR_LINE_PER_CHUNK_16;
++ else if (cur_width <= 64)
++ line_per_chunk = CURSOR_LINE_PER_CHUNK_8;
++ else if (cur_width <= 128)
++ line_per_chunk = CURSOR_LINE_PER_CHUNK_4;
++ else
++ line_per_chunk = CURSOR_LINE_PER_CHUNK_2;
++
++ return line_per_chunk;
++}
++
++static void ippn10_cursor_set_attributes(
++ struct mem_input *mem_input,
++ const struct dc_cursor_attributes *attr)
++{
++ struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input);
++ enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch);
++ enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk(
++ attr->width, attr->color_format);
++
++ mem_input->curs_attr = *attr;
++
++ REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH,
++ CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part);
++ REG_UPDATE(CURSOR_SURFACE_ADDRESS,
++ CURSOR_SURFACE_ADDRESS, attr->address.low_part);
++
++ REG_UPDATE_2(CURSOR_SIZE,
++ CURSOR_WIDTH, attr->width,
++ CURSOR_HEIGHT, attr->height);
++ REG_UPDATE_3(CURSOR_CONTROL,
++ CURSOR_MODE, attr->color_format,
++ CURSOR_PITCH, hw_pitch,
++ CURSOR_LINES_PER_CHUNK, lpc);
++ ippn10_cursor_program_control(mi,
++ attr->attribute_flags.bits.INVERT_PIXEL_DATA,
++ attr->color_format);
++}
++
++static void ippn10_cursor_set_position(
++ struct mem_input *mem_input,
++ const struct dc_cursor_position *pos,
++ const struct dc_cursor_mi_param *param)
++{
++ struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input);
++ int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start;
++ uint32_t cur_en = pos->enable ? 1 : 0;
++ uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0;
++
++ /*
++ * Guard aganst cursor_set_position() from being called with invalid
++ * attributes
++ *
++ * TODO: Look at combining cursor_set_position() and
++ * cursor_set_attributes() into cursor_update()
++ */
++ if (mem_input->curs_attr.address.quad_part == 0)
++ return;
++
++ dst_x_offset *= param->ref_clk_khz;
++ dst_x_offset /= param->pixel_clk_khz;
++
++ ASSERT(param->h_scale_ratio.value);
++
++ if (param->h_scale_ratio.value)
++ dst_x_offset = dal_fixed31_32_floor(dal_fixed31_32_div(
++ dal_fixed31_32_from_int(dst_x_offset),
++ param->h_scale_ratio));
++
++ if (src_x_offset >= (int)param->viewport_width)
++ cur_en = 0; /* not visible beyond right edge*/
++
++ if (src_x_offset + (int)mem_input->curs_attr.width < 0)
++ cur_en = 0; /* not visible beyond left edge*/
++
++ if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0)
++ ippn10_cursor_set_attributes(mem_input, &mem_input->curs_attr);
++ REG_UPDATE(CURSOR_CONTROL,
++ CURSOR_ENABLE, cur_en);
++
++ REG_SET_2(CURSOR_POSITION, 0,
++ CURSOR_X_POSITION, pos->x,
++ CURSOR_Y_POSITION, pos->y);
++
++ REG_SET_2(CURSOR_HOT_SPOT, 0,
++ CURSOR_HOT_SPOT_X, pos->x_hotspot,
++ CURSOR_HOT_SPOT_Y, pos->y_hotspot);
++
++ REG_SET(CURSOR_DST_OFFSET, 0,
++ CURSOR_DST_X_OFFSET, dst_x_offset);
++ /* TODO Handle surface pixel formats other than 4:4:4 */
++}
++
+ static struct mem_input_funcs dcn10_mem_input_funcs = {
+ .mem_input_program_display_marks = min10_program_display_marks,
+ .mem_input_program_surface_flip_and_addr =
+@@ -780,6 +941,8 @@ static struct mem_input_funcs dcn10_mem_input_funcs = {
+ .dcc_control = min10_dcc_control,
+ .mem_program_viewport = min_set_viewport,
+ .set_hubp_blank_en = min10_set_hubp_blank_en,
++ .set_cursor_attributes = ippn10_cursor_set_attributes,
++ .set_cursor_position = ippn10_cursor_set_position,
+ };
+
+ /*****************************************/
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h
+index 0b7d4fa..2c79d7a 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h
+@@ -30,7 +30,6 @@
+ #define TO_DCN10_MEM_INPUT(mi)\
+ container_of(mi, struct dcn10_mem_input, base)
+
+-
+ #define MI_REG_LIST_DCN(id)\
+ SRI(DCHUBP_CNTL, HUBP, id),\
+ SRI(HUBPREQ_DEBUG_DB, HUBP, id),\
+@@ -118,7 +117,15 @@
+ SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, HUBPREQ, id),\
+ SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, HUBPREQ, id),\
+ SR(DCHUBBUB_SDPIF_FB_BASE),\
+- SR(DCHUBBUB_SDPIF_FB_OFFSET)
++ SR(DCHUBBUB_SDPIF_FB_OFFSET),\
++ SRI(CURSOR_SETTINS, HUBPREQ, id), \
++ SRI(CURSOR_SURFACE_ADDRESS_HIGH, CURSOR, id), \
++ SRI(CURSOR_SURFACE_ADDRESS, CURSOR, id), \
++ SRI(CURSOR_SIZE, CURSOR, id), \
++ SRI(CURSOR_CONTROL, CURSOR, id), \
++ SRI(CURSOR_POSITION, CURSOR, id), \
++ SRI(CURSOR_HOT_SPOT, CURSOR, id), \
++ SRI(CURSOR_DST_OFFSET, CURSOR, id)
+
+
+
+@@ -217,6 +224,15 @@ struct dcn_mi_registers {
+ uint32_t DCN_VM_AGP_BASE;
+ uint32_t DCN_VM_AGP_BOT;
+ uint32_t DCN_VM_AGP_TOP;
++ uint32_t CURSOR_SETTINS;
++ uint32_t CURSOR_SETTINGS;
++ uint32_t CURSOR_SURFACE_ADDRESS_HIGH;
++ uint32_t CURSOR_SURFACE_ADDRESS;
++ uint32_t CURSOR_SIZE;
++ uint32_t CURSOR_CONTROL;
++ uint32_t CURSOR_POSITION;
++ uint32_t CURSOR_HOT_SPOT;
++ uint32_t CURSOR_DST_OFFSET;
+ };
+
+ #define MI_SF(reg_name, field_name, post_fix)\
+@@ -362,7 +378,23 @@ struct dcn_mi_registers {
+ MI_SF(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, mask_sh),\
+ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, mask_sh),\
+ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mask_sh),\
+- MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh)
++ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh),\
++ MI_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \
++ MI_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \
++ MI_SF(CURSOR0_CURSOR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \
++ MI_SF(CURSOR0_CURSOR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \
++ MI_SF(CURSOR0_CURSOR_SIZE, CURSOR_WIDTH, mask_sh), \
++ MI_SF(CURSOR0_CURSOR_SIZE, CURSOR_HEIGHT, mask_sh), \
++ MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \
++ MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_2X_MAGNIFY, mask_sh), \
++ MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \
++ MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \
++ MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \
++ MI_SF(CURSOR0_CURSOR_POSITION, CURSOR_X_POSITION, mask_sh), \
++ MI_SF(CURSOR0_CURSOR_POSITION, CURSOR_Y_POSITION, mask_sh), \
++ MI_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \
++ MI_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \
++ MI_SF(CURSOR0_CURSOR_DST_OFFSET, CURSOR_DST_X_OFFSET, mask_sh)
+
+ #define DCN_MI_REG_FIELD_LIST(type) \
+ type HUBP_BLANK_EN;\
+@@ -523,7 +555,24 @@ struct dcn_mi_registers {
+ type PHYSICAL_PAGE_ADDR_LO32;\
+ type PHYSICAL_PAGE_NUMBER_MSB;\
+ type PHYSICAL_PAGE_NUMBER_LSB;\
+- type LOGICAL_ADDR
++ type LOGICAL_ADDR;\
++ type CURSOR0_DST_Y_OFFSET; \
++ type CURSOR0_CHUNK_HDL_ADJUST; \
++ type CURSOR_SURFACE_ADDRESS_HIGH; \
++ type CURSOR_SURFACE_ADDRESS; \
++ type CURSOR_WIDTH; \
++ type CURSOR_HEIGHT; \
++ type CURSOR_MODE; \
++ type CURSOR_2X_MAGNIFY; \
++ type CURSOR_PITCH; \
++ type CURSOR_LINES_PER_CHUNK; \
++ type CURSOR_ENABLE; \
++ type CURSOR_X_POSITION; \
++ type CURSOR_Y_POSITION; \
++ type CURSOR_HOT_SPOT_X; \
++ type CURSOR_HOT_SPOT_Y; \
++ type CURSOR_DST_X_OFFSET; \
++ type OUTPUT_FP
+
+ struct dcn_mi_shift {
+ DCN_MI_REG_FIELD_LIST(uint8_t);
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h
+index 6cef9ad..5c8e45b 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h
+@@ -72,6 +72,7 @@ struct mem_input {
+ int opp_id;
+ int mpcc_id;
+ struct stutter_modes stutter_mode;
++ struct dc_cursor_attributes curs_attr;
+ };
+
+ struct vm_system_aperture_param {
+@@ -163,6 +164,15 @@ struct mem_input_funcs {
+ void (*set_blank)(struct mem_input *mi, bool blank);
+ void (*set_hubp_blank_en)(struct mem_input *mi, bool blank);
+
++ void (*set_cursor_attributes)(
++ struct mem_input *mem_input,
++ const struct dc_cursor_attributes *attr);
++
++ void (*set_cursor_position)(
++ struct mem_input *mem_input,
++ const struct dc_cursor_position *pos,
++ const struct dc_cursor_mi_param *param);
++
+ };
+
+ #endif
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
+index 785d397..f95621df 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
+@@ -238,6 +238,17 @@ struct transform_funcs {
+
+ void (*ipp_full_bypass)(struct transform *xfm_base);
+
++ void (*set_cursor_attributes)(
++ struct transform *xfm_base,
++ const struct dc_cursor_attributes *attr);
++
++ void (*set_cursor_position)(
++ struct transform *xfm_base,
++ const struct dc_cursor_position *pos,
++ const struct dc_cursor_mi_param *param,
++ uint32_t width
++ );
++
+ };
+
+ const uint16_t *get_filter_2tap_16p(void);
+--
+2.7.4
+