[PATCH v11 0/5] Fix degradation problem of alpha blending series
Some SoCs do not support the ignore_pixl_alpha flag, which breaks the XRGB format. Some SoCs do not support pre-multiplied pixel formats and extending configuration of OVL pre-multiplied color formats, such as MT8173. Fix the SoC degradation problem by this series. Tested-by: Chen-Yu Tsai --- Change in v11: Fix typo in commit message. Change in v10: 1. Fix the commit message and comment for OVL_CON_AEN Change in v9: 1. Add the fix patch for the XRGB downgrade issue of MT8173 2. Add the refine patch for ignore_pixel_alpha statement Change in v8: Remove blend_modes for not supported pre-multiplied SoCs to fix the return error from drm_plane_create_blend_mode_property(). Change in v7: 1. Add the remove color format comment patch for OVL 2. Fix warning: 'const' type qualifier on return type has no effect Chnage in v6: 1. Use blend_modes instead of function pointer in OVL 2. Use ethdr instead of mdp_rdma to get blend_modes 3. Add 0 checking for adding blend_mode property for mtk_plane Change in v5: Add fix patch for mtk_plane Change in v4: Add lost cases of mtk_ovl_fmt_convert_with_blend Change in v3: Change MACRO approach to function pointer in driver data Change in v2: Fix build error and typo Change in v1: Add fix patch for OVL unsupport color format settings by driver data --- Jason-JH.Lin (5): drm/mediatek: ovl: Fix XRGB format breakage for blend_modes unsupported SoCs drm/mediatek: ovl: Refine ignore_pixel_alpha comment and placement drm/mediatek: ovl: Remove the color format comment for ovl_fmt_convert() drm/mediatek: ovl: Add blend_modes to driver data drm/mediatek: Add blend_modes to mtk_plane_init() for different SoCs drivers/gpu/drm/mediatek/mtk_crtc.c | 1 + drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 2 + drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 10 +++ drivers/gpu/drm/mediatek/mtk_disp_drv.h | 2 + drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 70 ++- .../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 7 ++ drivers/gpu/drm/mediatek/mtk_ethdr.c | 7 ++ drivers/gpu/drm/mediatek/mtk_ethdr.h | 1 + drivers/gpu/drm/mediatek/mtk_plane.c | 15 ++-- drivers/gpu/drm/mediatek/mtk_plane.h | 4 +- 10 files changed, 92 insertions(+), 27 deletions(-) -- 2.43.0
[PATCH v11 2/5] drm/mediatek: ovl: Refine ignore_pixel_alpha comment and placement
Refine the comment for ignore_pixel_alpha flag and move it to if(state->fb) statement to make it less conditional. Signed-off-by: Jason-JH.Lin Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 047cd1796a51..0d3a9c5e8d26 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -481,16 +481,16 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, */ if (blend_mode || state->base.fb->format->has_alpha) con |= OVL_CON_AEN; - } - /* CONST_BLD must be enabled for XRGB formats although the alpha channel -* can be ignored, or OVL will still read the value from memory. -* For RGB888 related formats, whether CONST_BLD is enabled or not won't -* affect the result. Therefore we use !has_alpha as the condition. -*/ - if ((state->base.fb && !state->base.fb->format->has_alpha) || - blend_mode == DRM_MODE_BLEND_PIXEL_NONE) - ignore_pixel_alpha = OVL_CONST_BLEND; + /* +* Although the alpha channel can be ignored, CONST_BLD must be enabled +* for XRGB format, otherwise OVL will still read the value from memory. +* For RGB888 related formats, whether CONST_BLD is enabled or not won't +* affect the result. Therefore we use !has_alpha as the condition. +*/ + if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE || !state->base.fb->format->has_alpha) + ignore_pixel_alpha = OVL_CONST_BLEND; + } if (pending->rotation & DRM_MODE_REFLECT_Y) { con |= OVL_CON_VIRT_FLIP; -- 2.43.0
[PATCH v11 5/5] drm/mediatek: Add blend_modes to mtk_plane_init() for different SoCs
Since some SoCs support premultiplied pixel formats but some do not, the blend_modes parameter is added to mtk_plane_init(), which is obtained from the mtk_ddp_comp_get_blend_modes function implemented in different blending supported components. The blending supported components can use driver data to set the blend mode capabilities for different SoCs. Signed-off-by: Jason-JH.Lin Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_crtc.c | 1 + drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 2 ++ drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 10 ++ drivers/gpu/drm/mediatek/mtk_disp_drv.h | 2 ++ drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 7 +++ drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 7 +++ drivers/gpu/drm/mediatek/mtk_ethdr.c| 7 +++ drivers/gpu/drm/mediatek/mtk_ethdr.h| 1 + drivers/gpu/drm/mediatek/mtk_plane.c| 15 +++ drivers/gpu/drm/mediatek/mtk_plane.h| 4 ++-- 10 files changed, 46 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c index 175b00e5a253..b65f196f2015 100644 --- a/drivers/gpu/drm/mediatek/mtk_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_crtc.c @@ -913,6 +913,7 @@ static int mtk_crtc_init_comp_planes(struct drm_device *drm_dev, BIT(pipe), mtk_crtc_plane_type(mtk_crtc->layer_nr, num_planes), mtk_ddp_comp_supported_rotations(comp), + mtk_ddp_comp_get_blend_modes(comp), mtk_ddp_comp_get_formats(comp), mtk_ddp_comp_get_num_formats(comp), i); if (ret) diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c index be66d94be361..edc6417639e6 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c @@ -363,6 +363,7 @@ static const struct mtk_ddp_comp_funcs ddp_ovl = { .layer_config = mtk_ovl_layer_config, .bgclr_in_on = mtk_ovl_bgclr_in_on, .bgclr_in_off = mtk_ovl_bgclr_in_off, + .get_blend_modes = mtk_ovl_get_blend_modes, .get_formats = mtk_ovl_get_formats, .get_num_formats = mtk_ovl_get_num_formats, }; @@ -416,6 +417,7 @@ static const struct mtk_ddp_comp_funcs ddp_ovl_adaptor = { .disconnect = mtk_ovl_adaptor_disconnect, .add = mtk_ovl_adaptor_add_comp, .remove = mtk_ovl_adaptor_remove_comp, + .get_blend_modes = mtk_ovl_adaptor_get_blend_modes, .get_formats = mtk_ovl_adaptor_get_formats, .get_num_formats = mtk_ovl_adaptor_get_num_formats, .mode_valid = mtk_ovl_adaptor_mode_valid, diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h index ecf6dc283cd7..39720b27f4e9 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h @@ -80,6 +80,7 @@ struct mtk_ddp_comp_funcs { void (*ctm_set)(struct device *dev, struct drm_crtc_state *state); struct device * (*dma_dev_get)(struct device *dev); + u32 (*get_blend_modes)(struct device *dev); const u32 *(*get_formats)(struct device *dev); size_t (*get_num_formats)(struct device *dev); void (*connect)(struct device *dev, struct device *mmsys_dev, unsigned int next); @@ -266,6 +267,15 @@ static inline struct device *mtk_ddp_comp_dma_dev_get(struct mtk_ddp_comp *comp) return comp->dev; } +static inline +u32 mtk_ddp_comp_get_blend_modes(struct mtk_ddp_comp *comp) +{ + if (comp->funcs && comp->funcs->get_blend_modes) + return comp->funcs->get_blend_modes(comp->dev); + + return 0; +} + static inline const u32 *mtk_ddp_comp_get_formats(struct mtk_ddp_comp *comp) { diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h index 082ac18fe04a..04154db9085c 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h @@ -103,6 +103,7 @@ void mtk_ovl_register_vblank_cb(struct device *dev, void mtk_ovl_unregister_vblank_cb(struct device *dev); void mtk_ovl_enable_vblank(struct device *dev); void mtk_ovl_disable_vblank(struct device *dev); +u32 mtk_ovl_get_blend_modes(struct device *dev); const u32 *mtk_ovl_get_formats(struct device *dev); size_t mtk_ovl_get_num_formats(struct device *dev); @@ -131,6 +132,7 @@ void mtk_ovl_adaptor_start(struct device *dev); void mtk_ovl_adaptor_stop(struct device *dev); unsigned int mtk_ovl_adaptor_layer_nr(struct device *dev); struct device *mtk_ovl_adaptor_dma_dev_get(struct device *dev); +u32 mtk_ovl_adaptor_get_blend_modes(struct device *dev); const u32 *mtk_ovl_adaptor_get_formats(struct device *dev); size_t mtk_ovl_adaptor_get_num_f
[PATCH v11 4/5] drm/mediatek: ovl: Add blend_modes to driver data
OVL_CON_CLRFMT_MAN is a configuration for extending color format settings of DISP_REG_OVL_CON(n). It will change some of the original color format settings. Take the settings of (3 << 12) for example. - If OVL_CON_CLRFMT_MAN = 0 means OVL_CON_CLRFMT_RGBA. - If OVL_CON_CLRFMT_MAN = 1 means OVL_CON_CLRFMT_PARGB. Since previous SoCs did not support OVL_CON_CLRFMT_MAN, this means that the SoC does not support the premultiplied color format. It will break the original color format setting of MT8173. Therefore, the blend_modes is added to the driver data and then mtk_ovl_fmt_convert() will check the blend_modes to see if pre-multiplied is supported in the current platform. If it is not supported, use coverage mode to set it to the supported color formats to solve the degradation problem. Fixes: a3f7f7ef4bfe ("drm/mediatek: Support "Pre-multiplied" blending in OVL") Signed-off-by: Jason-JH.Lin Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 34 ++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 1ccb700858cf..fab23b1904bd 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -146,6 +146,7 @@ struct mtk_disp_ovl_data { bool fmt_rgb565_is_0; bool smi_id_en; bool supports_afbc; + const u32 blend_modes; const u32 *formats; size_t num_formats; bool supports_clrfmt_ext; @@ -386,9 +387,27 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx, DISP_REG_OVL_RDMA_CTRL(idx)); } -static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt, - unsigned int blend_mode) +static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl, + struct mtk_plane_state *state) { + unsigned int fmt = state->pending.format; + unsigned int blend_mode = DRM_MODE_BLEND_COVERAGE; + + /* +* For the platforms where OVL_CON_CLRFMT_MAN is defined in the hardware data sheet +* and supports premultiplied color formats, such as OVL_CON_CLRFMT_PARGB. +* +* Check blend_modes in the driver data to see if premultiplied mode is supported. +* If not, use coverage mode instead to set it to the supported color formats. +* +* Current DRM assumption is that alpha is default premultiplied, so the bitmask of +* blend_modes must include BIT(DRM_MODE_BLEND_PREMULTI). Otherwise, mtk_plane_init() +* will get an error return from drm_plane_create_blend_mode_property() and +* state->base.pixel_blend_mode should not be used. +*/ + if (ovl->data->blend_modes & BIT(DRM_MODE_BLEND_PREMULTI)) + blend_mode = state->base.pixel_blend_mode; + switch (fmt) { default: case DRM_FORMAT_RGB565: @@ -466,7 +485,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, return; } - con = ovl_fmt_convert(ovl, fmt, blend_mode); + con = mtk_ovl_fmt_convert(ovl, state); if (state->base.fb) { con |= state->base.alpha & OVL_CON_ALPHA; @@ -664,6 +683,9 @@ static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = { .layer_nr = 4, .fmt_rgb565_is_0 = true, .smi_id_en = true, + .blend_modes = BIT(DRM_MODE_BLEND_PREMULTI) | + BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), }; @@ -674,6 +696,9 @@ static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = { .layer_nr = 2, .fmt_rgb565_is_0 = true, .smi_id_en = true, + .blend_modes = BIT(DRM_MODE_BLEND_PREMULTI) | + BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), }; @@ -685,6 +710,9 @@ static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = { .fmt_rgb565_is_0 = true, .smi_id_en = true, .supports_afbc = true, + .blend_modes = BIT(DRM_MODE_BLEND_PREMULTI) | + BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8195_formats, .num_formats = ARRAY_SIZE(mt8195_formats), .supports_clrfmt_ext = true, -- 2.43.0
[PATCH v11 3/5] drm/mediatek: ovl: Remove the color format comment for ovl_fmt_convert()
Since we changed MACROs to be consistent with DRM input color format naming, the comment for ovl_fmt_conver() is no longer needed. Fixes: 9f428b95ac89 ("drm/mediatek: Add new color format MACROs in OVL") Signed-off-by: Jason-JH.Lin Reviewed-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 5 - 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 0d3a9c5e8d26..1ccb700858cf 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -389,11 +389,6 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx, static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt, unsigned int blend_mode) { - /* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX" -* is defined in mediatek HW data sheet. -* The alphabet order in XXX is no relation to data -* arrangement in memory. -*/ switch (fmt) { default: case DRM_FORMAT_RGB565: -- 2.43.0
[PATCH v11 1/5] drm/mediatek: ovl: Fix XRGB format breakage for blend_modes unsupported SoCs
OVL_CON_AEN is for alpha blending enable. For the SoC that is supported the blend_modes, OVL_CON_AEN will always enabled to use constant alpha and then use the ignore_pixel_alpha bit to do the alpha blending for XRGB format. Note that ignore pixel alpha bit is not supported if the SoC is not supported the blend_modes. So it will break the original setting of XRGB format for the blend_modes unsupported SoCs, such as MT8173. To fix the downgrade issue, enable alpha blending only when a valid blend_mode or has_alpha is set. Fixes: bc46eb5d5d77 ("drm/mediatek: Support DRM plane alpha in OVL") Signed-off-by: Jason-JH.Lin Reviewed-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 89b439dcf3a6..047cd1796a51 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -473,8 +473,14 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, con = ovl_fmt_convert(ovl, fmt, blend_mode); if (state->base.fb) { - con |= OVL_CON_AEN; con |= state->base.alpha & OVL_CON_ALPHA; + + /* +* For blend_modes supported SoCs, always enable alpha blending. +* For blend_modes unsupported SoCs, enable alpha blending when has_alpha is set. +*/ + if (blend_mode || state->base.fb->format->has_alpha) + con |= OVL_CON_AEN; } /* CONST_BLD must be enabled for XRGB formats although the alpha channel -- 2.43.0
[PATCH v10 0/5] Fix degradation problem of alpha blending series
Some SoCs do not support the ignore_pixl_alpha flag, which breaks the XRGB format. Some SoCs do not support pre-multiplied pixel formats and extending configuration of OVL pre-multiplied color formats, such as MT8173. Fix the SoC degradation problem by this sreies. --- Change in v10: 1. Fix the commit message and comment for OVL_CON_AEN Change in v9: 1. Add the fix patch for the XRGB downgrade issue of MT8173 2. Add the refine patch for ignore_pixel_alpha statement Change in v8: Remove blend_modes for not supported pre-multiplied SoCs to fix the return error from drm_plane_create_blend_mode_property(). Change in v7: 1. Add the remove color format comment patch for OVL 2. Fix warning: 'const' type qualifier on return type has no effect Chnage in v6: 1. Use blend_modes instead of function pointer in OVL 2. Use ethdr instead of mdp_rdma to get blend_modes 3. Add 0 checking for adding blend_mode property for mtk_plane Change in v5: Add fix patch for mtk_plane Change in v4: Add lost cases of mtk_ovl_fmt_convert_with_blend Change in v3: Change MACRO approach to function pointer in driver data Change in v2: Fix build error and typo Change in v1: Add fix patch for OVL unsupport color format settings by driver data --- Jason-JH.Lin (5): drm/mediatek: ovl: Fix XRGB format breakage for blend_modes unsupported SoCs drm/mediatek: ovl: Refine ignore_pixel_alpha comment and placement drm/mediatek: ovl: Remove the color format comment for ovl_fmt_convert() drm/mediatek: ovl: Add blend_modes to driver data drm/mediatek: Add blend_modes to mtk_plane_init() for different SoCs drivers/gpu/drm/mediatek/mtk_crtc.c | 1 + drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 2 + drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 10 +++ drivers/gpu/drm/mediatek/mtk_disp_drv.h | 2 + drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 70 ++- .../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 7 ++ drivers/gpu/drm/mediatek/mtk_ethdr.c | 7 ++ drivers/gpu/drm/mediatek/mtk_ethdr.h | 1 + drivers/gpu/drm/mediatek/mtk_plane.c | 15 ++-- drivers/gpu/drm/mediatek/mtk_plane.h | 4 +- 10 files changed, 92 insertions(+), 27 deletions(-) -- 2.43.0
[PATCH v10 5/5] drm/mediatek: Add blend_modes to mtk_plane_init() for different SoCs
Since some SoCs support premultiplied pixel formats but some do not, the blend_modes parameter is added to mtk_plane_init(), which is obtained from the mtk_ddp_comp_get_blend_modes function implemented in different blending supported components. The blending supported components can use driver data to set the blend mode capabilities for different SoCs. Signed-off-by: Jason-JH.Lin Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_crtc.c | 1 + drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 2 ++ drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 10 ++ drivers/gpu/drm/mediatek/mtk_disp_drv.h | 2 ++ drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 7 +++ drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 7 +++ drivers/gpu/drm/mediatek/mtk_ethdr.c| 7 +++ drivers/gpu/drm/mediatek/mtk_ethdr.h| 1 + drivers/gpu/drm/mediatek/mtk_plane.c| 15 +++ drivers/gpu/drm/mediatek/mtk_plane.h| 4 ++-- 10 files changed, 46 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c index 175b00e5a253..b65f196f2015 100644 --- a/drivers/gpu/drm/mediatek/mtk_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_crtc.c @@ -913,6 +913,7 @@ static int mtk_crtc_init_comp_planes(struct drm_device *drm_dev, BIT(pipe), mtk_crtc_plane_type(mtk_crtc->layer_nr, num_planes), mtk_ddp_comp_supported_rotations(comp), + mtk_ddp_comp_get_blend_modes(comp), mtk_ddp_comp_get_formats(comp), mtk_ddp_comp_get_num_formats(comp), i); if (ret) diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c index be66d94be361..edc6417639e6 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c @@ -363,6 +363,7 @@ static const struct mtk_ddp_comp_funcs ddp_ovl = { .layer_config = mtk_ovl_layer_config, .bgclr_in_on = mtk_ovl_bgclr_in_on, .bgclr_in_off = mtk_ovl_bgclr_in_off, + .get_blend_modes = mtk_ovl_get_blend_modes, .get_formats = mtk_ovl_get_formats, .get_num_formats = mtk_ovl_get_num_formats, }; @@ -416,6 +417,7 @@ static const struct mtk_ddp_comp_funcs ddp_ovl_adaptor = { .disconnect = mtk_ovl_adaptor_disconnect, .add = mtk_ovl_adaptor_add_comp, .remove = mtk_ovl_adaptor_remove_comp, + .get_blend_modes = mtk_ovl_adaptor_get_blend_modes, .get_formats = mtk_ovl_adaptor_get_formats, .get_num_formats = mtk_ovl_adaptor_get_num_formats, .mode_valid = mtk_ovl_adaptor_mode_valid, diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h index ecf6dc283cd7..39720b27f4e9 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h @@ -80,6 +80,7 @@ struct mtk_ddp_comp_funcs { void (*ctm_set)(struct device *dev, struct drm_crtc_state *state); struct device * (*dma_dev_get)(struct device *dev); + u32 (*get_blend_modes)(struct device *dev); const u32 *(*get_formats)(struct device *dev); size_t (*get_num_formats)(struct device *dev); void (*connect)(struct device *dev, struct device *mmsys_dev, unsigned int next); @@ -266,6 +267,15 @@ static inline struct device *mtk_ddp_comp_dma_dev_get(struct mtk_ddp_comp *comp) return comp->dev; } +static inline +u32 mtk_ddp_comp_get_blend_modes(struct mtk_ddp_comp *comp) +{ + if (comp->funcs && comp->funcs->get_blend_modes) + return comp->funcs->get_blend_modes(comp->dev); + + return 0; +} + static inline const u32 *mtk_ddp_comp_get_formats(struct mtk_ddp_comp *comp) { diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h index 082ac18fe04a..04154db9085c 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h @@ -103,6 +103,7 @@ void mtk_ovl_register_vblank_cb(struct device *dev, void mtk_ovl_unregister_vblank_cb(struct device *dev); void mtk_ovl_enable_vblank(struct device *dev); void mtk_ovl_disable_vblank(struct device *dev); +u32 mtk_ovl_get_blend_modes(struct device *dev); const u32 *mtk_ovl_get_formats(struct device *dev); size_t mtk_ovl_get_num_formats(struct device *dev); @@ -131,6 +132,7 @@ void mtk_ovl_adaptor_start(struct device *dev); void mtk_ovl_adaptor_stop(struct device *dev); unsigned int mtk_ovl_adaptor_layer_nr(struct device *dev); struct device *mtk_ovl_adaptor_dma_dev_get(struct device *dev); +u32 mtk_ovl_adaptor_get_blend_modes(struct device *dev); const u32 *mtk_ovl_adaptor_get_formats(struct device *dev); size_t mtk_ovl_adaptor_get_num_f
[PATCH v10 4/5] drm/mediatek: ovl: Add blend_modes to driver data
OVL_CON_CLRFMT_MAN is a configuration for extending color format settings of DISP_REG_OVL_CON(n). It will change some of the original color format settings. Take the settings of (3 << 12) for example. - If OVL_CON_CLRFMT_MAN = 0 means OVL_CON_CLRFMT_RGBA. - If OVL_CON_CLRFMT_MAN = 1 means OVL_CON_CLRFMT_PARGB. Since previous SoCs did not support OVL_CON_CLRFMT_MAN, this means that the SoC does not support the premultiplied color format. It will break the original color format setting of MT8173. Therefore, the blend_modes is added to the driver data and then mtk_ovl_fmt_convert() will check the blend_modes to see if pre-multiplied is supported in the current platform. If it is not supported, use coverage mode to set it to the supported color formats to solve the degradation problem. Fixes: a3f7f7ef4bfe ("drm/mediatek: Support "Pre-multiplied" blending in OVL") Signed-off-by: Jason-JH.Lin Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 34 ++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 1ccb700858cf..fab23b1904bd 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -146,6 +146,7 @@ struct mtk_disp_ovl_data { bool fmt_rgb565_is_0; bool smi_id_en; bool supports_afbc; + const u32 blend_modes; const u32 *formats; size_t num_formats; bool supports_clrfmt_ext; @@ -386,9 +387,27 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx, DISP_REG_OVL_RDMA_CTRL(idx)); } -static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt, - unsigned int blend_mode) +static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl, + struct mtk_plane_state *state) { + unsigned int fmt = state->pending.format; + unsigned int blend_mode = DRM_MODE_BLEND_COVERAGE; + + /* +* For the platforms where OVL_CON_CLRFMT_MAN is defined in the hardware data sheet +* and supports premultiplied color formats, such as OVL_CON_CLRFMT_PARGB. +* +* Check blend_modes in the driver data to see if premultiplied mode is supported. +* If not, use coverage mode instead to set it to the supported color formats. +* +* Current DRM assumption is that alpha is default premultiplied, so the bitmask of +* blend_modes must include BIT(DRM_MODE_BLEND_PREMULTI). Otherwise, mtk_plane_init() +* will get an error return from drm_plane_create_blend_mode_property() and +* state->base.pixel_blend_mode should not be used. +*/ + if (ovl->data->blend_modes & BIT(DRM_MODE_BLEND_PREMULTI)) + blend_mode = state->base.pixel_blend_mode; + switch (fmt) { default: case DRM_FORMAT_RGB565: @@ -466,7 +485,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, return; } - con = ovl_fmt_convert(ovl, fmt, blend_mode); + con = mtk_ovl_fmt_convert(ovl, state); if (state->base.fb) { con |= state->base.alpha & OVL_CON_ALPHA; @@ -664,6 +683,9 @@ static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = { .layer_nr = 4, .fmt_rgb565_is_0 = true, .smi_id_en = true, + .blend_modes = BIT(DRM_MODE_BLEND_PREMULTI) | + BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), }; @@ -674,6 +696,9 @@ static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = { .layer_nr = 2, .fmt_rgb565_is_0 = true, .smi_id_en = true, + .blend_modes = BIT(DRM_MODE_BLEND_PREMULTI) | + BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), }; @@ -685,6 +710,9 @@ static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = { .fmt_rgb565_is_0 = true, .smi_id_en = true, .supports_afbc = true, + .blend_modes = BIT(DRM_MODE_BLEND_PREMULTI) | + BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8195_formats, .num_formats = ARRAY_SIZE(mt8195_formats), .supports_clrfmt_ext = true, -- 2.43.0
[PATCH v10 1/5] drm/mediatek: ovl: Fix XRGB format breakage for blend_modes unsupported SoCs
OVL_CON_AEN is for alpha blending enable. For the SoC that is supported the blend_modes, OVL_CON_AEN will always enabled to use constant alpha and then use the ignore_pixel_alpha bit to do the alpha blending for XRGB format. Note that ignore pixel alpha bit is not supported if the SoC is not supported the blend_modes. So it will break the original setting of XRGB foramt for the blend_modes unsupported SoCs, such as MT8173. To fix the downgrade issue, enable alpha blending only when a valid blend_mode or has_alpha is set. Fixes: bc46eb5d5d77 ("drm/mediatek: Support DRM plane alpha in OVL") Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 89b439dcf3a6..047cd1796a51 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -473,8 +473,14 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, con = ovl_fmt_convert(ovl, fmt, blend_mode); if (state->base.fb) { - con |= OVL_CON_AEN; con |= state->base.alpha & OVL_CON_ALPHA; + + /* +* For blend_modes supported SoCs, always enable alpha blending. +* For blend_modes unsupported SoCs, enable alpha blending when has_alpha is set. +*/ + if (blend_mode || state->base.fb->format->has_alpha) + con |= OVL_CON_AEN; } /* CONST_BLD must be enabled for XRGB formats although the alpha channel -- 2.43.0
[PATCH v10 3/5] drm/mediatek: ovl: Remove the color format comment for ovl_fmt_convert()
Since we changed MACROs to be consistent with DRM input color format naming, the comment for ovl_fmt_conver() is no longer needed. Fixes: 9f428b95ac89 ("drm/mediatek: Add new color format MACROs in OVL") Signed-off-by: Jason-JH.Lin Reviewed-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 5 - 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 0d3a9c5e8d26..1ccb700858cf 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -389,11 +389,6 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx, static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt, unsigned int blend_mode) { - /* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX" -* is defined in mediatek HW data sheet. -* The alphabet order in XXX is no relation to data -* arrangement in memory. -*/ switch (fmt) { default: case DRM_FORMAT_RGB565: -- 2.43.0
[PATCH v10 2/5] drm/mediatek: ovl: Refine ignore_pixel_alpha comment and placement
Refine the comment for ignore_pixel_alpha flag and move it to if(state->fb) statement to make it less conditional. Signed-off-by: Jason-JH.Lin Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 047cd1796a51..0d3a9c5e8d26 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -481,16 +481,16 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, */ if (blend_mode || state->base.fb->format->has_alpha) con |= OVL_CON_AEN; - } - /* CONST_BLD must be enabled for XRGB formats although the alpha channel -* can be ignored, or OVL will still read the value from memory. -* For RGB888 related formats, whether CONST_BLD is enabled or not won't -* affect the result. Therefore we use !has_alpha as the condition. -*/ - if ((state->base.fb && !state->base.fb->format->has_alpha) || - blend_mode == DRM_MODE_BLEND_PIXEL_NONE) - ignore_pixel_alpha = OVL_CONST_BLEND; + /* +* Although the alpha channel can be ignored, CONST_BLD must be enabled +* for XRGB format, otherwise OVL will still read the value from memory. +* For RGB888 related formats, whether CONST_BLD is enabled or not won't +* affect the result. Therefore we use !has_alpha as the condition. +*/ + if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE || !state->base.fb->format->has_alpha) + ignore_pixel_alpha = OVL_CONST_BLEND; + } if (pending->rotation & DRM_MODE_REFLECT_Y) { con |= OVL_CON_VIRT_FLIP; -- 2.43.0
[PATCH v9 3/5] drm/mediatek: ovl: Remove the color format comment for ovl_fmt_convert()
Since we changed MACROs to be consistent with DRM input color format naming, the comment for ovl_fmt_conver() is no longer needed. Fixes: 9f428b95ac89 ("drm/mediatek: Add new color format MACROs in OVL") Signed-off-by: Jason-JH.Lin Reviewed-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 5 - 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index ddc826c42653..22f17ebfd8b3 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -389,11 +389,6 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx, static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt, unsigned int blend_mode) { - /* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX" -* is defined in mediatek HW data sheet. -* The alphabet order in XXX is no relation to data -* arrangement in memory. -*/ switch (fmt) { default: case DRM_FORMAT_RGB565: -- 2.43.0
[PATCH v9 2/5] drm/mediatek: ovl: Refine ignore_pixel_alpha comment and placement
Refine the comment for ignore_pixel_alpha flag and move it to if (state->fb) statement to make it less conditional. Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 8453a72f9e59..ddc826c42653 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -481,16 +481,16 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, */ if (blend_mode || state->base.fb->format->has_alpha) con |= OVL_CON_AEN; - } - /* CONST_BLD must be enabled for XRGB formats although the alpha channel -* can be ignored, or OVL will still read the value from memory. -* For RGB888 related formats, whether CONST_BLD is enabled or not won't -* affect the result. Therefore we use !has_alpha as the condition. -*/ - if ((state->base.fb && !state->base.fb->format->has_alpha) || - blend_mode == DRM_MODE_BLEND_PIXEL_NONE) - ignore_pixel_alpha = OVL_CONST_BLEND; + /* +* Although the alpha channel can be ignored, CONST_BLD must be enabled +* for XRGB format, otherwise OVL will still read the value from memory. +* For RGB888 related formats, whether CONST_BLD is enabled or not won't +* affect the result. Therefore we use !has_alpha as the condition. +*/ + if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE || !state->base.fb->format->has_alpha) + ignore_pixel_alpha = OVL_CONST_BLEND; + } if (pending->rotation & DRM_MODE_REFLECT_Y) { con |= OVL_CON_VIRT_FLIP; -- 2.43.0
[PATCH v9 1/5] drm/mediatek: ovl: Fix XRGB format breakage for blend_modes unsupported SoCs
If the constant alpha always enable, the SoCs that is not supported the ignore pixel alpha bit will still use constant alpha. That will break the original constant alpha setting of XRGB foramt for blend_modes unsupported SoCs, such as MT8173. Note that ignore pixel alpha bit is suppored if the SoC support the blend_modes. Make the constatnt alpha only enable when having a vliad blend_mode or setting the has_alpha to fix the downgrade issue. Fixes: bc46eb5d5d77 ("drm/mediatek: Support DRM plane alpha in OVL") Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 89b439dcf3a6..8453a72f9e59 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -473,8 +473,14 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, con = ovl_fmt_convert(ovl, fmt, blend_mode); if (state->base.fb) { - con |= OVL_CON_AEN; con |= state->base.alpha & OVL_CON_ALPHA; + + /* +* For blend_modes supported SoCs, always enable constant alpha. +* For blend_modes unsupported SoCs, enable constant alpha when has_alpha is set. +*/ + if (blend_mode || state->base.fb->format->has_alpha) + con |= OVL_CON_AEN; } /* CONST_BLD must be enabled for XRGB formats although the alpha channel -- 2.43.0
[PATCH v9 0/5] Fix degradation problem of alpha blending series
Some SoCs do not support the ignore_pixl_alpha flag, which breaks the XRGB format. Some SoCs do not support pre-multiplied pixel formats and extending configuration of OVL pre-multiplied color formats, such as MT8173. Fix the SoC degradation problem by this sreies. --- Change in v9: 1. Add the fix patch for the XRGB downgrade issue of MT8173 2. Add the refine patch for ignore_pixel_alpha statement Change in v8: Remove blend_modes for not supported pre-multiplied SoCs to fix the return error from drm_plane_create_blend_mode_property(). Change in v7: 1. Add the remove color format comment patch for OVL 2. Fix warning: 'const' type qualifier on return type has no effect Chnage in v6: 1. Use blend_modes instead of function pointer in OVL 2. Use ethdr instead of mdp_rdma to get blend_modes 3. Add 0 checking for adding blend_mode property for mtk_plane Change in v5: Add fix patch for mtk_plane Change in v4: Add lost cases of mtk_ovl_fmt_convert_with_blend Change in v3: Change MACRO approach to function pointer in driver data Change in v2: Fix build error and typo Change in v1: Add fix patch for OVL unsupport color format settings by driver data --- Jason-JH.Lin (5): drm/mediatek: ovl: Fix XRGB format breakage for blend_modes unsupported SoCs drm/mediatek: ovl: Refine ignore_pixel_alpha comment and placement drm/mediatek: ovl: Remove the color format comment for ovl_fmt_convert() drm/mediatek: ovl: Add blend_modes to driver data drm/mediatek: Add blend_modes to mtk_plane_init() for different SoCs drivers/gpu/drm/mediatek/mtk_crtc.c | 1 + drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 2 + drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 10 +++ drivers/gpu/drm/mediatek/mtk_disp_drv.h | 2 + drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 70 ++- .../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 7 ++ drivers/gpu/drm/mediatek/mtk_ethdr.c | 7 ++ drivers/gpu/drm/mediatek/mtk_ethdr.h | 1 + drivers/gpu/drm/mediatek/mtk_plane.c | 15 ++-- drivers/gpu/drm/mediatek/mtk_plane.h | 4 +- 10 files changed, 92 insertions(+), 27 deletions(-) -- 2.43.0
[PATCH v9 5/5] drm/mediatek: Add blend_modes to mtk_plane_init() for different SoCs
Since some SoCs support premultiplied pixel formats but some do not, the blend_modes parameter is added to mtk_plane_init(), which is obtained from the mtk_ddp_comp_get_blend_modes function implemented in different blending supported components. The blending supported components can use driver data to set the blend mode capabilities for different SoCs. Signed-off-by: Jason-JH.Lin Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_crtc.c | 1 + drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 2 ++ drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 10 ++ drivers/gpu/drm/mediatek/mtk_disp_drv.h | 2 ++ drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 7 +++ drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 7 +++ drivers/gpu/drm/mediatek/mtk_ethdr.c| 7 +++ drivers/gpu/drm/mediatek/mtk_ethdr.h| 1 + drivers/gpu/drm/mediatek/mtk_plane.c| 15 +++ drivers/gpu/drm/mediatek/mtk_plane.h| 4 ++-- 10 files changed, 46 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c index 175b00e5a253..b65f196f2015 100644 --- a/drivers/gpu/drm/mediatek/mtk_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_crtc.c @@ -913,6 +913,7 @@ static int mtk_crtc_init_comp_planes(struct drm_device *drm_dev, BIT(pipe), mtk_crtc_plane_type(mtk_crtc->layer_nr, num_planes), mtk_ddp_comp_supported_rotations(comp), + mtk_ddp_comp_get_blend_modes(comp), mtk_ddp_comp_get_formats(comp), mtk_ddp_comp_get_num_formats(comp), i); if (ret) diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c index be66d94be361..edc6417639e6 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c @@ -363,6 +363,7 @@ static const struct mtk_ddp_comp_funcs ddp_ovl = { .layer_config = mtk_ovl_layer_config, .bgclr_in_on = mtk_ovl_bgclr_in_on, .bgclr_in_off = mtk_ovl_bgclr_in_off, + .get_blend_modes = mtk_ovl_get_blend_modes, .get_formats = mtk_ovl_get_formats, .get_num_formats = mtk_ovl_get_num_formats, }; @@ -416,6 +417,7 @@ static const struct mtk_ddp_comp_funcs ddp_ovl_adaptor = { .disconnect = mtk_ovl_adaptor_disconnect, .add = mtk_ovl_adaptor_add_comp, .remove = mtk_ovl_adaptor_remove_comp, + .get_blend_modes = mtk_ovl_adaptor_get_blend_modes, .get_formats = mtk_ovl_adaptor_get_formats, .get_num_formats = mtk_ovl_adaptor_get_num_formats, .mode_valid = mtk_ovl_adaptor_mode_valid, diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h index ecf6dc283cd7..39720b27f4e9 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h @@ -80,6 +80,7 @@ struct mtk_ddp_comp_funcs { void (*ctm_set)(struct device *dev, struct drm_crtc_state *state); struct device * (*dma_dev_get)(struct device *dev); + u32 (*get_blend_modes)(struct device *dev); const u32 *(*get_formats)(struct device *dev); size_t (*get_num_formats)(struct device *dev); void (*connect)(struct device *dev, struct device *mmsys_dev, unsigned int next); @@ -266,6 +267,15 @@ static inline struct device *mtk_ddp_comp_dma_dev_get(struct mtk_ddp_comp *comp) return comp->dev; } +static inline +u32 mtk_ddp_comp_get_blend_modes(struct mtk_ddp_comp *comp) +{ + if (comp->funcs && comp->funcs->get_blend_modes) + return comp->funcs->get_blend_modes(comp->dev); + + return 0; +} + static inline const u32 *mtk_ddp_comp_get_formats(struct mtk_ddp_comp *comp) { diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h index 082ac18fe04a..04154db9085c 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h @@ -103,6 +103,7 @@ void mtk_ovl_register_vblank_cb(struct device *dev, void mtk_ovl_unregister_vblank_cb(struct device *dev); void mtk_ovl_enable_vblank(struct device *dev); void mtk_ovl_disable_vblank(struct device *dev); +u32 mtk_ovl_get_blend_modes(struct device *dev); const u32 *mtk_ovl_get_formats(struct device *dev); size_t mtk_ovl_get_num_formats(struct device *dev); @@ -131,6 +132,7 @@ void mtk_ovl_adaptor_start(struct device *dev); void mtk_ovl_adaptor_stop(struct device *dev); unsigned int mtk_ovl_adaptor_layer_nr(struct device *dev); struct device *mtk_ovl_adaptor_dma_dev_get(struct device *dev); +u32 mtk_ovl_adaptor_get_blend_modes(struct device *dev); const u32 *mtk_ovl_adaptor_get_formats(struct device *dev); size_t mtk_ovl_adaptor_get_num_f
[PATCH v9 4/5] drm/mediatek: ovl: Add blend_modes to driver data
OVL_CON_CLRFMT_MAN is a configuration for extending color format settings of DISP_REG_OVL_CON(n). It will change some of the original color format settings. Take the settings of (3 << 12) for example. - If OVL_CON_CLRFMT_MAN = 0 means OVL_CON_CLRFMT_RGBA. - If OVL_CON_CLRFMT_MAN = 1 means OVL_CON_CLRFMT_PARGB. Since previous SoCs did not support OVL_CON_CLRFMT_MAN, this means that the SoC does not support the premultiplied color format. It will break the original color format setting of MT8173. Therefore, the blend_modes is added to the driver data and then mtk_ovl_fmt_convert() will check the blend_modes to see if premultiplied supported in current platform. If it is not supported, use coverage mode to set it to the supported color formats to solve the degradation problem. Fixes: a3f7f7ef4bfe ("drm/mediatek: Support "Pre-multiplied" blending in OVL") Signed-off-by: Jason-JH.Lin Reviewed-by: AngeloGioacchino Del Regno --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 34 ++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 22f17ebfd8b3..41874dc9d933 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -146,6 +146,7 @@ struct mtk_disp_ovl_data { bool fmt_rgb565_is_0; bool smi_id_en; bool supports_afbc; + const u32 blend_modes; const u32 *formats; size_t num_formats; bool supports_clrfmt_ext; @@ -386,9 +387,27 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx, DISP_REG_OVL_RDMA_CTRL(idx)); } -static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt, - unsigned int blend_mode) +static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl, + struct mtk_plane_state *state) { + unsigned int fmt = state->pending.format; + unsigned int blend_mode = DRM_MODE_BLEND_COVERAGE; + + /* +* For the platforms where OVL_CON_CLRFMT_MAN is defined in the hardware data sheet +* and supports premultiplied color formats, such as OVL_CON_CLRFMT_PARGB. +* +* Check blend_modes in the driver data to see if premultiplied mode is supported. +* If not, use coverage mode instead to set it to the supported color formats. +* +* Current DRM assumption is that alpha is default premultiplied, so the bitmask of +* blend_modes must include BIT(DRM_MODE_BLEND_PREMULTI). Otherwise, mtk_plane_init() +* will get an error return from drm_plane_create_blend_mode_property() and +* state->base.pixel_blend_mode should not be used. +*/ + if (ovl->data->blend_modes & BIT(DRM_MODE_BLEND_PREMULTI)) + blend_mode = state->base.pixel_blend_mode; + switch (fmt) { default: case DRM_FORMAT_RGB565: @@ -466,7 +485,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, return; } - con = ovl_fmt_convert(ovl, fmt, blend_mode); + con = mtk_ovl_fmt_convert(ovl, state); if (state->base.fb) { con |= state->base.alpha & OVL_CON_ALPHA; @@ -664,6 +683,9 @@ static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = { .layer_nr = 4, .fmt_rgb565_is_0 = true, .smi_id_en = true, + .blend_modes = BIT(DRM_MODE_BLEND_PREMULTI) | + BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), }; @@ -674,6 +696,9 @@ static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = { .layer_nr = 2, .fmt_rgb565_is_0 = true, .smi_id_en = true, + .blend_modes = BIT(DRM_MODE_BLEND_PREMULTI) | + BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), }; @@ -685,6 +710,9 @@ static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = { .fmt_rgb565_is_0 = true, .smi_id_en = true, .supports_afbc = true, + .blend_modes = BIT(DRM_MODE_BLEND_PREMULTI) | + BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8195_formats, .num_formats = ARRAY_SIZE(mt8195_formats), .supports_clrfmt_ext = true, -- 2.43.0
[PATCH] drm/mediatek: Fix XRGB format breakage for blend_modes unsupported SoCs
If the constant alpha always set, the SoCs that is not supported the ignore alpha bit will still use constant alpha. That will break the original constant alpha setting of XRGB foramt for blend_modes unsupported SoCs, such as MT8173. Make the constatnt alpha only set when setting has_alpha or supported blend_modes SoC to fix the downgrade issue. Fixes: bc46eb5d5d77 ("drm/mediatek: Support DRM plane alpha in OVL") Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 28 +++-- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 703cd3f6c6d3..de3addd89442 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -494,19 +494,25 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, con = mtk_ovl_fmt_convert(ovl, state); if (state->base.fb) { - con |= OVL_CON_AEN; - con |= state->base.alpha & OVL_CON_ALPHA; + /* +* For blend_modes supported SoCs, always set constant alpha. +* For blend_modes unsupported SoCs, set constant alpha when has_alpha is set. +*/ + if (ovl->data->blend_modes || state->base.fb->format->has_alpha) { + con |= OVL_CON_AEN; + con |= state->base.alpha & OVL_CON_ALPHA; + } + + /* +* Although the alpha channel can be ignored, CONST_BLD must be enabled +* for XRGB format, otherwise OVL will still read the value from memory. +* For RGB888 related formats, whether CONST_BLD is enabled or not won't +* affect the result. Therefore we use !has_alpha as the condition. +*/ + if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE || !state->base.fb->format->has_alpha) + ignore_pixel_alpha = OVL_CONST_BLEND; } - /* CONST_BLD must be enabled for XRGB formats although the alpha channel -* can be ignored, or OVL will still read the value from memory. -* For RGB888 related formats, whether CONST_BLD is enabled or not won't -* affect the result. Therefore we use !has_alpha as the condition. -*/ - if ((state->base.fb && !state->base.fb->format->has_alpha) || - blend_mode == DRM_MODE_BLEND_PIXEL_NONE) - ignore_pixel_alpha = OVL_CONST_BLEND; - if (pending->rotation & DRM_MODE_REFLECT_Y) { con |= OVL_CON_VIRT_FLIP; addr += (pending->height - 1) * pending->pitch; -- 2.43.0
[PATCH v8 2/3] drm/mediatek: ovl: Add blend_modes to driver data
OVL_CON_CLRFMT_MAN is a configuration for extending color format settings of DISP_REG_OVL_CON(n). It will change some of the original color format settings. Take the settings of (3 << 12) for example. - If OVL_CON_CLRFMT_MAN = 0 means OVL_CON_CLRFMT_RGBA. - If OVL_CON_CLRFMT_MAN = 1 means OVL_CON_CLRFMT_PARGB. Since previous SoCs did not support OVL_CON_CLRFMT_MAN, this means that the SoC does not support the premultiplied color format. It will break the original color format setting of MT8173. Therefore, the blend_modes is added to the driver data and then mtk_ovl_fmt_convert() will check the blend_modes to see if premultiplied supported in current platform. If it is not supported, use coverage mode to set it to the supported color formats to solve the degradation problem. Fixes: a3f7f7ef4bfe ("drm/mediatek: Support "Pre-multiplied" blending in OVL") Signed-off-by: Jason-JH.Lin Reviewed-by: AngeloGioacchino Del Regno --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 34 ++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 4a4bc27a67f0..4bfed8a4c14f 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -146,6 +146,7 @@ struct mtk_disp_ovl_data { bool fmt_rgb565_is_0; bool smi_id_en; bool supports_afbc; + const u32 blend_modes; const u32 *formats; size_t num_formats; bool supports_clrfmt_ext; @@ -386,9 +387,27 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx, DISP_REG_OVL_RDMA_CTRL(idx)); } -static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt, - unsigned int blend_mode) +static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl, + struct mtk_plane_state *state) { + unsigned int fmt = state->pending.format; + unsigned int blend_mode = DRM_MODE_BLEND_COVERAGE; + + /* +* For the platforms where OVL_CON_CLRFMT_MAN is defined in the hardware data sheet +* and supports premultiplied color formats, such as OVL_CON_CLRFMT_PARGB. +* +* Check blend_modes in the driver data to see if premultiplied mode is supported. +* If not, use coverage mode instead to set it to the supported color formats. +* +* Current DRM assumption is that alpha is default premultiplied, so the bitmask of +* blend_modes must include BIT(DRM_MODE_BLEND_PREMULTI). Otherwise, mtk_plane_init() +* will get an error return from drm_plane_create_blend_mode_property() and +* state->base.pixel_blend_mode should not be used. +*/ + if (ovl->data->blend_modes & BIT(DRM_MODE_BLEND_PREMULTI)) + blend_mode = state->base.pixel_blend_mode; + switch (fmt) { default: case DRM_FORMAT_RGB565: @@ -466,7 +485,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, return; } - con = ovl_fmt_convert(ovl, fmt, blend_mode); + con = mtk_ovl_fmt_convert(ovl, state); if (state->base.fb) { con |= OVL_CON_AEN; con |= state->base.alpha & OVL_CON_ALPHA; @@ -658,6 +677,9 @@ static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = { .layer_nr = 4, .fmt_rgb565_is_0 = true, .smi_id_en = true, + .blend_modes = BIT(DRM_MODE_BLEND_PREMULTI) | + BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), }; @@ -668,6 +690,9 @@ static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = { .layer_nr = 2, .fmt_rgb565_is_0 = true, .smi_id_en = true, + .blend_modes = BIT(DRM_MODE_BLEND_PREMULTI) | + BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), }; @@ -679,6 +704,9 @@ static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = { .fmt_rgb565_is_0 = true, .smi_id_en = true, .supports_afbc = true, + .blend_modes = BIT(DRM_MODE_BLEND_PREMULTI) | + BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8195_formats, .num_formats = ARRAY_SIZE(mt8195_formats), .supports_clrfmt_ext = true, -- 2.43.0
[PATCH v8 3/3] drm/mediatek: Add blend_modes to mtk_plane_init() for different SoCs
Since some SoCs support premultiplied pixel formats but some do not, the blend_modes parameter is added to mtk_plane_init(), which is obtained from the mtk_ddp_comp_get_blend_modes function implemented in different blending supported components. The blending supported components can use driver data to set the blend mode capabilities for different SoCs. Signed-off-by: Jason-JH.Lin Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_crtc.c | 1 + drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 2 ++ drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 10 ++ drivers/gpu/drm/mediatek/mtk_disp_drv.h | 2 ++ drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 7 +++ drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 7 +++ drivers/gpu/drm/mediatek/mtk_ethdr.c| 7 +++ drivers/gpu/drm/mediatek/mtk_ethdr.h| 1 + drivers/gpu/drm/mediatek/mtk_plane.c| 15 +++ drivers/gpu/drm/mediatek/mtk_plane.h| 4 ++-- 10 files changed, 46 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c index 175b00e5a253..b65f196f2015 100644 --- a/drivers/gpu/drm/mediatek/mtk_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_crtc.c @@ -913,6 +913,7 @@ static int mtk_crtc_init_comp_planes(struct drm_device *drm_dev, BIT(pipe), mtk_crtc_plane_type(mtk_crtc->layer_nr, num_planes), mtk_ddp_comp_supported_rotations(comp), + mtk_ddp_comp_get_blend_modes(comp), mtk_ddp_comp_get_formats(comp), mtk_ddp_comp_get_num_formats(comp), i); if (ret) diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c index be66d94be361..edc6417639e6 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c @@ -363,6 +363,7 @@ static const struct mtk_ddp_comp_funcs ddp_ovl = { .layer_config = mtk_ovl_layer_config, .bgclr_in_on = mtk_ovl_bgclr_in_on, .bgclr_in_off = mtk_ovl_bgclr_in_off, + .get_blend_modes = mtk_ovl_get_blend_modes, .get_formats = mtk_ovl_get_formats, .get_num_formats = mtk_ovl_get_num_formats, }; @@ -416,6 +417,7 @@ static const struct mtk_ddp_comp_funcs ddp_ovl_adaptor = { .disconnect = mtk_ovl_adaptor_disconnect, .add = mtk_ovl_adaptor_add_comp, .remove = mtk_ovl_adaptor_remove_comp, + .get_blend_modes = mtk_ovl_adaptor_get_blend_modes, .get_formats = mtk_ovl_adaptor_get_formats, .get_num_formats = mtk_ovl_adaptor_get_num_formats, .mode_valid = mtk_ovl_adaptor_mode_valid, diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h index ecf6dc283cd7..39720b27f4e9 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h @@ -80,6 +80,7 @@ struct mtk_ddp_comp_funcs { void (*ctm_set)(struct device *dev, struct drm_crtc_state *state); struct device * (*dma_dev_get)(struct device *dev); + u32 (*get_blend_modes)(struct device *dev); const u32 *(*get_formats)(struct device *dev); size_t (*get_num_formats)(struct device *dev); void (*connect)(struct device *dev, struct device *mmsys_dev, unsigned int next); @@ -266,6 +267,15 @@ static inline struct device *mtk_ddp_comp_dma_dev_get(struct mtk_ddp_comp *comp) return comp->dev; } +static inline +u32 mtk_ddp_comp_get_blend_modes(struct mtk_ddp_comp *comp) +{ + if (comp->funcs && comp->funcs->get_blend_modes) + return comp->funcs->get_blend_modes(comp->dev); + + return 0; +} + static inline const u32 *mtk_ddp_comp_get_formats(struct mtk_ddp_comp *comp) { diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h index 082ac18fe04a..04154db9085c 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h @@ -103,6 +103,7 @@ void mtk_ovl_register_vblank_cb(struct device *dev, void mtk_ovl_unregister_vblank_cb(struct device *dev); void mtk_ovl_enable_vblank(struct device *dev); void mtk_ovl_disable_vblank(struct device *dev); +u32 mtk_ovl_get_blend_modes(struct device *dev); const u32 *mtk_ovl_get_formats(struct device *dev); size_t mtk_ovl_get_num_formats(struct device *dev); @@ -131,6 +132,7 @@ void mtk_ovl_adaptor_start(struct device *dev); void mtk_ovl_adaptor_stop(struct device *dev); unsigned int mtk_ovl_adaptor_layer_nr(struct device *dev); struct device *mtk_ovl_adaptor_dma_dev_get(struct device *dev); +u32 mtk_ovl_adaptor_get_blend_modes(struct device *dev); const u32 *mtk_ovl_adaptor_get_formats(struct device *dev); size_t mtk_ovl_adaptor_get_num_f
[PATCH v8 0/3] Fix degradation problem of alpha blending series
From: Jason-jh Lin Some SoCs not support pre-multiplied pixel formats and extending configuration of OVL pre-multiplied color formats, such as MT8173. Fix the SoC degradation problem by this sreies. --- Change in v8: Remove blend_modes for not supported pre-multiplied SoCs to fix the return error from drm_plane_create_blend_mode_property(). Change in v7: 1. Add the remove color format comment patch for OVL 2. Fix warning: 'const' type qualifier on return type has no effect Chnage in v6: 1. Use blend_modes instead of function pointer in OVL 2. Use ethdr instead of mdp_rdma to get blend_modes 3. Add 0 checking for adding blend_mode property for mtk_plane Change in v5: Add fix patch for mtk_plane Change in v4: Add lost cases of mtk_ovl_fmt_convert_with_blend Change in v3: Change MACRO approach to function pointer in driver data Change in v2: Fix build error and typo Change in v1: Add fix patch for OVL unsupport color format settings by driver data --- Jason-JH.Lin (3): drm/mediatek: ovl: Remove the color format comment for ovl_fmt_convert() drm/mediatek: ovl: Add blend_modes to driver data drm/mediatek: Add blend_modes to mtk_plane_init() for different SoCs drivers/gpu/drm/mediatek/mtk_crtc.c | 1 + drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 2 + drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 10 + drivers/gpu/drm/mediatek/mtk_disp_drv.h | 2 + drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 44 --- .../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 7 +++ drivers/gpu/drm/mediatek/mtk_ethdr.c | 7 +++ drivers/gpu/drm/mediatek/mtk_ethdr.h | 1 + drivers/gpu/drm/mediatek/mtk_plane.c | 15 +++ drivers/gpu/drm/mediatek/mtk_plane.h | 4 +- 10 files changed, 76 insertions(+), 17 deletions(-) -- 2.43.0
[PATCH v8 1/3] drm/mediatek: ovl: Remove the color format comment for ovl_fmt_convert()
Since we changed MACROs to be consistent with DRM input color format naming, the comment for ovl_fmt_conver() is no longer needed. Fixes: 9f428b95ac89 ("drm/mediatek: Add new color format MACROs in OVL") Signed-off-by: Jason-JH.Lin Reviewed-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 5 - 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 89b439dcf3a6..4a4bc27a67f0 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -389,11 +389,6 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx, static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt, unsigned int blend_mode) { - /* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX" -* is defined in mediatek HW data sheet. -* The alphabet order in XXX is no relation to data -* arrangement in memory. -*/ switch (fmt) { default: case DRM_FORMAT_RGB565: -- 2.43.0
[PATCH v7 1/3] drm/mediatek: ovl: Remove the color format comment for ovl_fmt_convert()
Since we changed MACROs to be consistent with DRM input color format naming, the comment for ovl_fmt_conver() is no longer needed. Fixes: 9f428b95ac89 ("drm/mediatek: Add new color format MACROs in OVL") Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 5 - 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 89b439dcf3a6..4a4bc27a67f0 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -389,11 +389,6 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx, static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt, unsigned int blend_mode) { - /* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX" -* is defined in mediatek HW data sheet. -* The alphabet order in XXX is no relation to data -* arrangement in memory. -*/ switch (fmt) { default: case DRM_FORMAT_RGB565: -- 2.43.0
[PATCH v7 3/3] drm/mediatek: Add blend_modes to mtk_plane_init() for different SoCs
Since some SoCs support premultiplied pixel formats but some do not, the blend_modes parameter is added to mtk_plane_init(), which is obtained from the mtk_ddp_comp_get_blend_modes function implemented in different blending supported components. The blending supported components can use driver data to set the blend mode capabilities for different SoCs. Signed-off-by: Jason-JH.Lin Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_crtc.c | 1 + drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 2 ++ drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 10 ++ drivers/gpu/drm/mediatek/mtk_disp_drv.h | 2 ++ drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 7 +++ drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 7 +++ drivers/gpu/drm/mediatek/mtk_ethdr.c| 7 +++ drivers/gpu/drm/mediatek/mtk_ethdr.h| 1 + drivers/gpu/drm/mediatek/mtk_plane.c| 15 +++ drivers/gpu/drm/mediatek/mtk_plane.h| 4 ++-- 10 files changed, 46 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c index 175b00e5a253..b65f196f2015 100644 --- a/drivers/gpu/drm/mediatek/mtk_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_crtc.c @@ -913,6 +913,7 @@ static int mtk_crtc_init_comp_planes(struct drm_device *drm_dev, BIT(pipe), mtk_crtc_plane_type(mtk_crtc->layer_nr, num_planes), mtk_ddp_comp_supported_rotations(comp), + mtk_ddp_comp_get_blend_modes(comp), mtk_ddp_comp_get_formats(comp), mtk_ddp_comp_get_num_formats(comp), i); if (ret) diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c index be66d94be361..edc6417639e6 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c @@ -363,6 +363,7 @@ static const struct mtk_ddp_comp_funcs ddp_ovl = { .layer_config = mtk_ovl_layer_config, .bgclr_in_on = mtk_ovl_bgclr_in_on, .bgclr_in_off = mtk_ovl_bgclr_in_off, + .get_blend_modes = mtk_ovl_get_blend_modes, .get_formats = mtk_ovl_get_formats, .get_num_formats = mtk_ovl_get_num_formats, }; @@ -416,6 +417,7 @@ static const struct mtk_ddp_comp_funcs ddp_ovl_adaptor = { .disconnect = mtk_ovl_adaptor_disconnect, .add = mtk_ovl_adaptor_add_comp, .remove = mtk_ovl_adaptor_remove_comp, + .get_blend_modes = mtk_ovl_adaptor_get_blend_modes, .get_formats = mtk_ovl_adaptor_get_formats, .get_num_formats = mtk_ovl_adaptor_get_num_formats, .mode_valid = mtk_ovl_adaptor_mode_valid, diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h index ecf6dc283cd7..39720b27f4e9 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h @@ -80,6 +80,7 @@ struct mtk_ddp_comp_funcs { void (*ctm_set)(struct device *dev, struct drm_crtc_state *state); struct device * (*dma_dev_get)(struct device *dev); + u32 (*get_blend_modes)(struct device *dev); const u32 *(*get_formats)(struct device *dev); size_t (*get_num_formats)(struct device *dev); void (*connect)(struct device *dev, struct device *mmsys_dev, unsigned int next); @@ -266,6 +267,15 @@ static inline struct device *mtk_ddp_comp_dma_dev_get(struct mtk_ddp_comp *comp) return comp->dev; } +static inline +u32 mtk_ddp_comp_get_blend_modes(struct mtk_ddp_comp *comp) +{ + if (comp->funcs && comp->funcs->get_blend_modes) + return comp->funcs->get_blend_modes(comp->dev); + + return 0; +} + static inline const u32 *mtk_ddp_comp_get_formats(struct mtk_ddp_comp *comp) { diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h index 082ac18fe04a..04154db9085c 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h @@ -103,6 +103,7 @@ void mtk_ovl_register_vblank_cb(struct device *dev, void mtk_ovl_unregister_vblank_cb(struct device *dev); void mtk_ovl_enable_vblank(struct device *dev); void mtk_ovl_disable_vblank(struct device *dev); +u32 mtk_ovl_get_blend_modes(struct device *dev); const u32 *mtk_ovl_get_formats(struct device *dev); size_t mtk_ovl_get_num_formats(struct device *dev); @@ -131,6 +132,7 @@ void mtk_ovl_adaptor_start(struct device *dev); void mtk_ovl_adaptor_stop(struct device *dev); unsigned int mtk_ovl_adaptor_layer_nr(struct device *dev); struct device *mtk_ovl_adaptor_dma_dev_get(struct device *dev); +u32 mtk_ovl_adaptor_get_blend_modes(struct device *dev); const u32 *mtk_ovl_adaptor_get_formats(struct device *dev); size_t mtk_ovl_adaptor_get_num_f
[PATCH v7 0/3] Fix degradation problem of alpha blending series
Some SoCs not support pre-multiplied pixel formats and extending configuration of OVL pre-multiplied color formats, such as MT8173. Fix the SoC degradation problem by this sreies. --- Change in v7: 1. Add the remove color format comment patch for OVL 2. Fix warning: 'const' type qualifier on return type has no effect Chnage in v6: 1. Use blend_modes instead of function pointer in OVL 2. Use ethdr instead of mdp_rdma to get blend_modes 3. Add 0 checking for adding blend_mode property for mtk_plane Change in v5: Add fix patch for mtk_plane Change in v4: Add lost cases of mtk_ovl_fmt_convert_with_blend Change in v3: Change MACRO approach to function pointer in driver data Change in v2: Fix build error and typo Change in v1: Add fix patch for OVL unsupport color format settings by driver data --- Jason-JH.Lin (3): drm/mediatek: ovl: Remove the color format comment for ovl_fmt_convert() drm/mediatek: ovl: Add blend_modes to driver data drm/mediatek: Add blend_modes to mtk_plane_init() for different SoCs drivers/gpu/drm/mediatek/mtk_crtc.c | 1 + drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 2 + drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 10 drivers/gpu/drm/mediatek/mtk_disp_drv.h | 2 + drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 48 --- .../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 7 +++ drivers/gpu/drm/mediatek/mtk_ethdr.c | 7 +++ drivers/gpu/drm/mediatek/mtk_ethdr.h | 1 + drivers/gpu/drm/mediatek/mtk_plane.c | 15 +++--- drivers/gpu/drm/mediatek/mtk_plane.h | 4 +- 10 files changed, 80 insertions(+), 17 deletions(-) -- 2.43.0
[PATCH v7 2/3] drm/mediatek: ovl: Add blend_modes to driver data
OVL_CON_CLRFMT_MAN is a configuration for extending color format settings of DISP_REG_OVL_CON(n). It will change some of the original color format settings. Take the settings of (3 << 12) for example. - If OVL_CON_CLRFMT_MAN = 0 means OVL_CON_CLRFMT_RGBA. - If OVL_CON_CLRFMT_MAN = 1 means OVL_CON_CLRFMT_PARGB. Since previous SoCs did not support OVL_CON_CLRFMT_MAN, this means that the SoC does not support the premultiplied color format. It will break the original color format setting of MT8173. Therefore, the blend_modes is added to the driver data and then mtk_ovl_fmt_convert() will check the blend_modes to see if premultiplied supported in current platform. If it is not supported, use coverage mode to set it to the supported color formats to solve the degradation problem. Fixes: a3f7f7ef4bfe ("drm/mediatek: Support "Pre-multiplied" blending in OVL") Signed-off-by: Jason-JH.Lin Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 38 +++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 4a4bc27a67f0..0cf7b80f612e 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -146,6 +146,7 @@ struct mtk_disp_ovl_data { bool fmt_rgb565_is_0; bool smi_id_en; bool supports_afbc; + const u32 blend_modes; const u32 *formats; size_t num_formats; bool supports_clrfmt_ext; @@ -386,9 +387,23 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx, DISP_REG_OVL_RDMA_CTRL(idx)); } -static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt, - unsigned int blend_mode) +static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl, + struct mtk_plane_state *state) { + unsigned int fmt = state->pending.format; + unsigned int blend_mode = state->base.pixel_blend_mode; + + /* +* For the platforms where OVL_CON_CLRFMT_MAN is defined in the hardware data sheet +* and supports premultiplied color formats, such as OVL_CON_CLRFMT_PARGB. +* +* Check blend_modes in the driver data to see if premultiplied mode is supported. +* If not, use coverage mode instead to set it to the supported color formats. +*/ + if (!(ovl->data->blend_modes & BIT(DRM_MODE_BLEND_PREMULTI)) && + blend_mode == DRM_MODE_BLEND_PREMULTI) + blend_mode = DRM_MODE_BLEND_COVERAGE; + switch (fmt) { default: case DRM_FORMAT_RGB565: @@ -466,7 +481,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, return; } - con = ovl_fmt_convert(ovl, fmt, blend_mode); + con = mtk_ovl_fmt_convert(ovl, state); if (state->base.fb) { con |= OVL_CON_AEN; con |= state->base.alpha & OVL_CON_ALPHA; @@ -621,6 +636,8 @@ static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = { .gmc_bits = 8, .layer_nr = 4, .fmt_rgb565_is_0 = false, + .blend_modes = BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), }; @@ -630,6 +647,8 @@ static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = { .gmc_bits = 8, .layer_nr = 4, .fmt_rgb565_is_0 = true, + .blend_modes = BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), }; @@ -639,6 +658,8 @@ static const struct mtk_disp_ovl_data mt8183_ovl_driver_data = { .gmc_bits = 10, .layer_nr = 4, .fmt_rgb565_is_0 = true, + .blend_modes = BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), }; @@ -648,6 +669,8 @@ static const struct mtk_disp_ovl_data mt8183_ovl_2l_driver_data = { .gmc_bits = 10, .layer_nr = 2, .fmt_rgb565_is_0 = true, + .blend_modes = BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), }; @@ -658,6 +681,9 @@ static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = { .layer_nr = 4, .fmt_rgb565_is_0 = true, .smi_id_en = true, + .blend_modes = BIT(DRM_MODE_BLEND_PREMULTI) | + BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), }; @@ -668,6 +69
[PATCH v6 2/2] drm/mediatek: Add blend_modes to mtk_plane_init() for different SoCs
Since some SoCs support premultiplied pixel formats but some do not, the blend_modes parameter is added to mtk_plane_init(), which is obtained from the mtk_ddp_comp_get_blend_modes function implemented in different blending supported components. The blending supported components can use driver data to set the blend mode capabilities for different SoCs. Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_crtc.c | 1 + drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 2 ++ drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 10 ++ drivers/gpu/drm/mediatek/mtk_disp_drv.h | 2 ++ drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 7 +++ drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 7 +++ drivers/gpu/drm/mediatek/mtk_ethdr.c| 7 +++ drivers/gpu/drm/mediatek/mtk_ethdr.h| 1 + drivers/gpu/drm/mediatek/mtk_plane.c| 15 +++ drivers/gpu/drm/mediatek/mtk_plane.h| 4 ++-- 10 files changed, 46 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c index 175b00e5a253..b65f196f2015 100644 --- a/drivers/gpu/drm/mediatek/mtk_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_crtc.c @@ -913,6 +913,7 @@ static int mtk_crtc_init_comp_planes(struct drm_device *drm_dev, BIT(pipe), mtk_crtc_plane_type(mtk_crtc->layer_nr, num_planes), mtk_ddp_comp_supported_rotations(comp), + mtk_ddp_comp_get_blend_modes(comp), mtk_ddp_comp_get_formats(comp), mtk_ddp_comp_get_num_formats(comp), i); if (ret) diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c index be66d94be361..edc6417639e6 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c @@ -363,6 +363,7 @@ static const struct mtk_ddp_comp_funcs ddp_ovl = { .layer_config = mtk_ovl_layer_config, .bgclr_in_on = mtk_ovl_bgclr_in_on, .bgclr_in_off = mtk_ovl_bgclr_in_off, + .get_blend_modes = mtk_ovl_get_blend_modes, .get_formats = mtk_ovl_get_formats, .get_num_formats = mtk_ovl_get_num_formats, }; @@ -416,6 +417,7 @@ static const struct mtk_ddp_comp_funcs ddp_ovl_adaptor = { .disconnect = mtk_ovl_adaptor_disconnect, .add = mtk_ovl_adaptor_add_comp, .remove = mtk_ovl_adaptor_remove_comp, + .get_blend_modes = mtk_ovl_adaptor_get_blend_modes, .get_formats = mtk_ovl_adaptor_get_formats, .get_num_formats = mtk_ovl_adaptor_get_num_formats, .mode_valid = mtk_ovl_adaptor_mode_valid, diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h index ecf6dc283cd7..79562af1180f 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h @@ -80,6 +80,7 @@ struct mtk_ddp_comp_funcs { void (*ctm_set)(struct device *dev, struct drm_crtc_state *state); struct device * (*dma_dev_get)(struct device *dev); + const u32 (*get_blend_modes)(struct device *dev); const u32 *(*get_formats)(struct device *dev); size_t (*get_num_formats)(struct device *dev); void (*connect)(struct device *dev, struct device *mmsys_dev, unsigned int next); @@ -266,6 +267,15 @@ static inline struct device *mtk_ddp_comp_dma_dev_get(struct mtk_ddp_comp *comp) return comp->dev; } +static inline +const u32 mtk_ddp_comp_get_blend_modes(struct mtk_ddp_comp *comp) +{ + if (comp->funcs && comp->funcs->get_blend_modes) + return comp->funcs->get_blend_modes(comp->dev); + + return 0; +} + static inline const u32 *mtk_ddp_comp_get_formats(struct mtk_ddp_comp *comp) { diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h index 082ac18fe04a..defa500cd64f 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h @@ -103,6 +103,7 @@ void mtk_ovl_register_vblank_cb(struct device *dev, void mtk_ovl_unregister_vblank_cb(struct device *dev); void mtk_ovl_enable_vblank(struct device *dev); void mtk_ovl_disable_vblank(struct device *dev); +const u32 mtk_ovl_get_blend_modes(struct device *dev); const u32 *mtk_ovl_get_formats(struct device *dev); size_t mtk_ovl_get_num_formats(struct device *dev); @@ -131,6 +132,7 @@ void mtk_ovl_adaptor_start(struct device *dev); void mtk_ovl_adaptor_stop(struct device *dev); unsigned int mtk_ovl_adaptor_layer_nr(struct device *dev); struct device *mtk_ovl_adaptor_dma_dev_get(struct device *dev); +const u32 mtk_ovl_adaptor_get_blend_modes(struct device *dev); const u32 *mtk_ovl_adaptor_get_formats(struct device *dev); size_t mtk_ovl_adaptor_get_num_formats(struct device *dev); enum drm_
[PATCH v6 0/2] Fix degradation problem of alpha blending series
Some SoCs not support pre-multiplied pixel formats and extending configuration of OVL pre-multiplied color formats, such as MT8173. Fix the SoC degradation problem by this sreies. --- Chnage in v6: 1. Use blend_modes instead of function pointer in OVL 2. Use ethdr instead of mdp_rdma to get blend_modes 3. Add 0 checking for adding blend_mode property for mtk_plane Change in v5: Add fix patch for mtk_plane Change in v4: Add lost cases of mtk_ovl_fmt_convert_with_blend Change in v3: Change MACRO approach to function pointer in driver data Change in v2: Fix build error and typo Change in v1: Add fix patch for OVL unsupport color format settings by driver data --- Jason-JH.Lin (2): drm/mediatek: ovl: Add blend_modes to driver data drm/mediatek: Add blend_modes to mtk_plane_init() for different SoCs drivers/gpu/drm/mediatek/mtk_crtc.c | 1 + drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 2 + drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 10 drivers/gpu/drm/mediatek/mtk_disp_drv.h | 2 + drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 48 --- .../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 7 +++ drivers/gpu/drm/mediatek/mtk_ethdr.c | 7 +++ drivers/gpu/drm/mediatek/mtk_ethdr.h | 1 + drivers/gpu/drm/mediatek/mtk_plane.c | 15 +++--- drivers/gpu/drm/mediatek/mtk_plane.h | 4 +- 10 files changed, 80 insertions(+), 17 deletions(-) -- 2.43.0
[PATCH v6 1/2] drm/mediatek: ovl: Add blend_modes to driver data
OVL_CON_CLRFMT_MAN is a configuration for extending color format settings of DISP_REG_OVL_CON(n). It will change some of the original color format settings. Take the settings of (3 << 12) for example. - If OVL_CON_CLRFMT_MAN = 0 means OVL_CON_CLRFMT_RGBA. - If OVL_CON_CLRFMT_MAN = 1 means OVL_CON_CLRFMT_PARGB. Since previous SoCs did not support OVL_CON_CLRFMT_MAN, this means that the SoC does not support the premultiplied color format. It will break the original color format setting of MT8173. Therefore, the blend_modes is added to the driver data and then mtk_ovl_fmt_convert() will check the blend_modes to see if premultiplied supported in current platform. If it is not supported, use coverage mode to set it to the supported color formats to solve the degradation problem. Fixes: a3f7f7ef4bfe ("drm/mediatek: Support "Pre-multiplied" blending in OVL") Signed-off-by: Jason-JH.Lin Tested-by: Alper Nebi Yasak Reviewed-by: AngeloGioacchino Del Regno --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 41 - 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 89b439dcf3a6..0cf7b80f612e 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -146,6 +146,7 @@ struct mtk_disp_ovl_data { bool fmt_rgb565_is_0; bool smi_id_en; bool supports_afbc; + const u32 blend_modes; const u32 *formats; size_t num_formats; bool supports_clrfmt_ext; @@ -386,14 +387,23 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx, DISP_REG_OVL_RDMA_CTRL(idx)); } -static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt, - unsigned int blend_mode) +static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl, + struct mtk_plane_state *state) { - /* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX" -* is defined in mediatek HW data sheet. -* The alphabet order in XXX is no relation to data -* arrangement in memory. + unsigned int fmt = state->pending.format; + unsigned int blend_mode = state->base.pixel_blend_mode; + + /* +* For the platforms where OVL_CON_CLRFMT_MAN is defined in the hardware data sheet +* and supports premultiplied color formats, such as OVL_CON_CLRFMT_PARGB. +* +* Check blend_modes in the driver data to see if premultiplied mode is supported. +* If not, use coverage mode instead to set it to the supported color formats. */ + if (!(ovl->data->blend_modes & BIT(DRM_MODE_BLEND_PREMULTI)) && + blend_mode == DRM_MODE_BLEND_PREMULTI) + blend_mode = DRM_MODE_BLEND_COVERAGE; + switch (fmt) { default: case DRM_FORMAT_RGB565: @@ -471,7 +481,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, return; } - con = ovl_fmt_convert(ovl, fmt, blend_mode); + con = mtk_ovl_fmt_convert(ovl, state); if (state->base.fb) { con |= OVL_CON_AEN; con |= state->base.alpha & OVL_CON_ALPHA; @@ -626,6 +636,8 @@ static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = { .gmc_bits = 8, .layer_nr = 4, .fmt_rgb565_is_0 = false, + .blend_modes = BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), }; @@ -635,6 +647,8 @@ static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = { .gmc_bits = 8, .layer_nr = 4, .fmt_rgb565_is_0 = true, + .blend_modes = BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), }; @@ -644,6 +658,8 @@ static const struct mtk_disp_ovl_data mt8183_ovl_driver_data = { .gmc_bits = 10, .layer_nr = 4, .fmt_rgb565_is_0 = true, + .blend_modes = BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), }; @@ -653,6 +669,8 @@ static const struct mtk_disp_ovl_data mt8183_ovl_2l_driver_data = { .gmc_bits = 10, .layer_nr = 2, .fmt_rgb565_is_0 = true, + .blend_modes = BIT(DRM_MODE_BLEND_COVERAGE) | + BIT(DRM_MODE_BLEND_PIXEL_NONE), .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), }; @@ -663,6 +681,9 @@ static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = { .layer_nr = 4, .fmt_rgb565_is_0 = true, .smi_id_en = true, + .blend_modes = BIT(DRM_MODE_BLEND_PREMU
[PATCH v5 2/2] drm/mediatek: Add blend_modes to mtk_plane_init() for different SoCs
Since some SoCs support premultiplied pixel formats but some do not, the blend_modes parameter is added to mtk_plane_init(), which is obtained from the mtk_ddp_comp_get_blend_modes function implemented in different OVL components. The OVL component can use driver data to set the blend mode capabilities for different SoCs. Fixes: 4225d5d5e779 ("drm/mediatek: Support alpha blending in display driver") Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_crtc.c | 1 + drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 2 ++ drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 10 drivers/gpu/drm/mediatek/mtk_disp_drv.h | 3 +++ drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 25 +++ .../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 7 ++ drivers/gpu/drm/mediatek/mtk_mdp_rdma.c | 8 ++ drivers/gpu/drm/mediatek/mtk_plane.c | 9 +++ drivers/gpu/drm/mediatek/mtk_plane.h | 4 +-- 9 files changed, 61 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c index 175b00e5a253..b65f196f2015 100644 --- a/drivers/gpu/drm/mediatek/mtk_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_crtc.c @@ -913,6 +913,7 @@ static int mtk_crtc_init_comp_planes(struct drm_device *drm_dev, BIT(pipe), mtk_crtc_plane_type(mtk_crtc->layer_nr, num_planes), mtk_ddp_comp_supported_rotations(comp), + mtk_ddp_comp_get_blend_modes(comp), mtk_ddp_comp_get_formats(comp), mtk_ddp_comp_get_num_formats(comp), i); if (ret) diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c index be66d94be361..edc6417639e6 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c @@ -363,6 +363,7 @@ static const struct mtk_ddp_comp_funcs ddp_ovl = { .layer_config = mtk_ovl_layer_config, .bgclr_in_on = mtk_ovl_bgclr_in_on, .bgclr_in_off = mtk_ovl_bgclr_in_off, + .get_blend_modes = mtk_ovl_get_blend_modes, .get_formats = mtk_ovl_get_formats, .get_num_formats = mtk_ovl_get_num_formats, }; @@ -416,6 +417,7 @@ static const struct mtk_ddp_comp_funcs ddp_ovl_adaptor = { .disconnect = mtk_ovl_adaptor_disconnect, .add = mtk_ovl_adaptor_add_comp, .remove = mtk_ovl_adaptor_remove_comp, + .get_blend_modes = mtk_ovl_adaptor_get_blend_modes, .get_formats = mtk_ovl_adaptor_get_formats, .get_num_formats = mtk_ovl_adaptor_get_num_formats, .mode_valid = mtk_ovl_adaptor_mode_valid, diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h index ecf6dc283cd7..79562af1180f 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h @@ -80,6 +80,7 @@ struct mtk_ddp_comp_funcs { void (*ctm_set)(struct device *dev, struct drm_crtc_state *state); struct device * (*dma_dev_get)(struct device *dev); + const u32 (*get_blend_modes)(struct device *dev); const u32 *(*get_formats)(struct device *dev); size_t (*get_num_formats)(struct device *dev); void (*connect)(struct device *dev, struct device *mmsys_dev, unsigned int next); @@ -266,6 +267,15 @@ static inline struct device *mtk_ddp_comp_dma_dev_get(struct mtk_ddp_comp *comp) return comp->dev; } +static inline +const u32 mtk_ddp_comp_get_blend_modes(struct mtk_ddp_comp *comp) +{ + if (comp->funcs && comp->funcs->get_blend_modes) + return comp->funcs->get_blend_modes(comp->dev); + + return 0; +} + static inline const u32 *mtk_ddp_comp_get_formats(struct mtk_ddp_comp *comp) { diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h index 082ac18fe04a..ea07b3b55b1c 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h @@ -103,6 +103,7 @@ void mtk_ovl_register_vblank_cb(struct device *dev, void mtk_ovl_unregister_vblank_cb(struct device *dev); void mtk_ovl_enable_vblank(struct device *dev); void mtk_ovl_disable_vblank(struct device *dev); +const u32 mtk_ovl_get_blend_modes(struct device *dev); const u32 *mtk_ovl_get_formats(struct device *dev); size_t mtk_ovl_get_num_formats(struct device *dev); @@ -131,6 +132,7 @@ void mtk_ovl_adaptor_start(struct device *dev); void mtk_ovl_adaptor_stop(struct device *dev); unsigned int mtk_ovl_adaptor_layer_nr(struct device *dev); struct device *mtk_ovl_adaptor_dma_dev_get(struct device *dev); +const u32 mtk_ovl_adaptor_get_blend_modes(struct device *dev); const u32 *mtk_ovl_adaptor_get_formats(struct device *dev); size_t mtk_ovl_adaptor_get_num_formats(struct device *dev); enum drm_mode_status mtk_ovl_adaptor_
[PATCH v5 1/2] drm/mediatek: ovl: Add fmt_convert function pointer to driver data
OVL_CON_CLRFMT_MAN is a configuration for extending color format settings of DISP_REG_OVL_CON(n). It will change some of the original color format settings. Take the settings of (3 << 12) for example. - If OVL_CON_CLRFMT_MAN = 0 means OVL_CON_CLRFMT_RGBA. - If OVL_CON_CLRFMT_MAN = 1 means OVL_CON_CLRFMT_PARGB. Since OVL_CON_CLRFMT_MAN is not supported on previous SoCs, It breaks the OVL color format setting of MT8173. Therefore, the fmt_convert function pointer is added to the driver data and mtk_ovl_fmt_convert_with_blend is implemented for MT8192 and MT8195 that support OVL_CON_CLRFMT_MAN, and mtk_ovl_fmt_convert is implemented for other SoCs that do not support it to solve the degradation problem. Fixes: a3f7f7ef4bfe ("drm/mediatek: Support "Pre-multiplied" blending in OVL") Signed-off-by: Jason-JH.Lin Tested-by: Alper Nebi Yasak Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 68 ++--- 1 file changed, 61 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 89b439dcf3a6..8f7b7e07aeb1 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -143,6 +143,7 @@ struct mtk_disp_ovl_data { unsigned int addr; unsigned int gmc_bits; unsigned int layer_nr; + unsigned int (*fmt_convert)(struct device *dev, struct mtk_plane_state *state); bool fmt_rgb565_is_0; bool smi_id_en; bool supports_afbc; @@ -386,13 +387,59 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx, DISP_REG_OVL_RDMA_CTRL(idx)); } -static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt, - unsigned int blend_mode) +static unsigned int mtk_ovl_fmt_convert(struct device *dev, struct mtk_plane_state *state) { - /* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX" -* is defined in mediatek HW data sheet. -* The alphabet order in XXX is no relation to data -* arrangement in memory. + struct mtk_disp_ovl *ovl = dev_get_drvdata(dev); + unsigned int fmt = state->pending.format; + + switch (fmt) { + default: + case DRM_FORMAT_RGB565: + return OVL_CON_CLRFMT_RGB565(ovl); + case DRM_FORMAT_BGR565: + return OVL_CON_CLRFMT_RGB565(ovl) | OVL_CON_BYTE_SWAP; + case DRM_FORMAT_RGB888: + return OVL_CON_CLRFMT_RGB888(ovl); + case DRM_FORMAT_BGR888: + return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP; + case DRM_FORMAT_RGBX: + case DRM_FORMAT_RGBA: + case DRM_FORMAT_RGBX1010102: + case DRM_FORMAT_RGBA1010102: + return OVL_CON_CLRFMT_RGBA; + case DRM_FORMAT_BGRX: + case DRM_FORMAT_BGRA: + case DRM_FORMAT_BGRX1010102: + case DRM_FORMAT_BGRA1010102: + return OVL_CON_CLRFMT_BGRA; + case DRM_FORMAT_XRGB: + case DRM_FORMAT_ARGB: + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_ARGB2101010: + return OVL_CON_CLRFMT_ARGB; + case DRM_FORMAT_XBGR: + case DRM_FORMAT_ABGR: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_ABGR2101010: + return OVL_CON_CLRFMT_ABGR; + case DRM_FORMAT_UYVY: + return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB; + case DRM_FORMAT_YUYV: + return OVL_CON_CLRFMT_YUYV | OVL_CON_MTX_YUV_TO_RGB; + } +} + +static unsigned int mtk_ovl_fmt_convert_with_blend(struct device *dev, + struct mtk_plane_state *state) +{ + struct mtk_disp_ovl *ovl = dev_get_drvdata(dev); + unsigned int fmt = state->pending.format; + unsigned int blend_mode = state->base.pixel_blend_mode; + + /* +* For the platforms where OVL_CON_CLRFMT_MAN is defined in the +* hardware data sheet and supports premultiplied color formats +* such as OVL_CON_CLRFMT_PARGB. */ switch (fmt) { default: @@ -471,7 +518,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, return; } - con = ovl_fmt_convert(ovl, fmt, blend_mode); + con = ovl->data->fmt_convert(dev, state); if (state->base.fb) { con |= OVL_CON_AEN; con |= state->base.alpha & OVL_CON_ALPHA; @@ -625,6 +672,7 @@ static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = { .addr = DISP_REG_OVL_ADDR_MT2701, .gmc_bits = 8, .layer_nr = 4, + .fmt_convert = mtk_ovl_fmt_convert, .fmt_rgb565_is_0 = false, .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), @@ -634,6 +682,7 @@ static const struct mtk_disp_ovl_data mt8173
[PATCH v5 0/2] Fix degradation problem of alpha blending series
From: Jason-jh Lin Some SoCs not support pre-multiplied pixel formats and extending configuration of OVL pre-multiplied color formats, such as MT8173. Fix the SoC degradation problem by this sreies. --- Change in v5: Add fix patch for mtk_plane Change in v4: Add lost cases of mtk_ovl_fmt_convert_with_blend Change in v3: Change MACRO approach to function pointer in driver data Change in v2: Fix build error and typo Change in v1: Add fix patch for OVL unsupport color format settings by driver data --- Jason-JH.Lin (2): drm/mediatek: ovl: Add fmt_convert function pointer to driver data drm/mediatek: Add blend_modes to mtk_plane_init() for different SoCs drivers/gpu/drm/mediatek/mtk_crtc.c | 1 + drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 2 + drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 10 ++ drivers/gpu/drm/mediatek/mtk_disp_drv.h | 3 + drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 93 +-- .../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 7 ++ drivers/gpu/drm/mediatek/mtk_mdp_rdma.c | 8 ++ drivers/gpu/drm/mediatek/mtk_plane.c | 9 +- drivers/gpu/drm/mediatek/mtk_plane.h | 4 +- 9 files changed, 122 insertions(+), 15 deletions(-) -- 2.43.0
[PATCH v4] drm/mediatek: ovl: Add fmt_convert function pointer to driver data
OVL_CON_CLRFMT_MAN is a configuration for extending color format settings of DISP_REG_OVL_CON(n). It will change some of the original color format settings. Take the settings of (3 << 12) for example. - If OVL_CON_CLRFMT_MAN = 0 means OVL_CON_CLRFMT_RGBA. - If OVL_CON_CLRFMT_MAN = 1 means OVL_CON_CLRFMT_PARGB. Since OVL_CON_CLRFMT_MAN is not supported on previous SoCs, It breaks the OVL color format setting of MT8173. Therefore, the fmt_convert function pointer is added to the driver data and mtk_ovl_fmt_convert_with_blend is implemented for MT8192 and MT8195 that support OVL_CON_CLRFMT_MAN, and mtk_ovl_fmt_convert is implemented for other SoCs that do not support it to solve the degradation problem. Fixes: a3f7f7ef4bfe ("drm/mediatek: Support "Pre-multiplied" blending in OVL") Signed-off-by: Jason-JH.Lin Tested-by: Alper Nebi Yasak Reviewed-by: AngeloGioacchino Del Regno --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 68 ++--- 1 file changed, 61 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 89b439dcf3a6..8f7b7e07aeb1 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -143,6 +143,7 @@ struct mtk_disp_ovl_data { unsigned int addr; unsigned int gmc_bits; unsigned int layer_nr; + unsigned int (*fmt_convert)(struct device *dev, struct mtk_plane_state *state); bool fmt_rgb565_is_0; bool smi_id_en; bool supports_afbc; @@ -386,13 +387,59 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx, DISP_REG_OVL_RDMA_CTRL(idx)); } -static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt, - unsigned int blend_mode) +static unsigned int mtk_ovl_fmt_convert(struct device *dev, struct mtk_plane_state *state) { - /* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX" -* is defined in mediatek HW data sheet. -* The alphabet order in XXX is no relation to data -* arrangement in memory. + struct mtk_disp_ovl *ovl = dev_get_drvdata(dev); + unsigned int fmt = state->pending.format; + + switch (fmt) { + default: + case DRM_FORMAT_RGB565: + return OVL_CON_CLRFMT_RGB565(ovl); + case DRM_FORMAT_BGR565: + return OVL_CON_CLRFMT_RGB565(ovl) | OVL_CON_BYTE_SWAP; + case DRM_FORMAT_RGB888: + return OVL_CON_CLRFMT_RGB888(ovl); + case DRM_FORMAT_BGR888: + return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP; + case DRM_FORMAT_RGBX: + case DRM_FORMAT_RGBA: + case DRM_FORMAT_RGBX1010102: + case DRM_FORMAT_RGBA1010102: + return OVL_CON_CLRFMT_RGBA; + case DRM_FORMAT_BGRX: + case DRM_FORMAT_BGRA: + case DRM_FORMAT_BGRX1010102: + case DRM_FORMAT_BGRA1010102: + return OVL_CON_CLRFMT_BGRA; + case DRM_FORMAT_XRGB: + case DRM_FORMAT_ARGB: + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_ARGB2101010: + return OVL_CON_CLRFMT_ARGB; + case DRM_FORMAT_XBGR: + case DRM_FORMAT_ABGR: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_ABGR2101010: + return OVL_CON_CLRFMT_ABGR; + case DRM_FORMAT_UYVY: + return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB; + case DRM_FORMAT_YUYV: + return OVL_CON_CLRFMT_YUYV | OVL_CON_MTX_YUV_TO_RGB; + } +} + +static unsigned int mtk_ovl_fmt_convert_with_blend(struct device *dev, + struct mtk_plane_state *state) +{ + struct mtk_disp_ovl *ovl = dev_get_drvdata(dev); + unsigned int fmt = state->pending.format; + unsigned int blend_mode = state->base.pixel_blend_mode; + + /* +* For the platforms where OVL_CON_CLRFMT_MAN is defined in the +* hardware data sheet and supports premultiplied color formats +* such as OVL_CON_CLRFMT_PARGB. */ switch (fmt) { default: @@ -471,7 +518,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, return; } - con = ovl_fmt_convert(ovl, fmt, blend_mode); + con = ovl->data->fmt_convert(dev, state); if (state->base.fb) { con |= OVL_CON_AEN; con |= state->base.alpha & OVL_CON_ALPHA; @@ -625,6 +672,7 @@ static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = { .addr = DISP_REG_OVL_ADDR_MT2701, .gmc_bits = 8, .layer_nr = 4, + .fmt_convert = mtk_ovl_fmt_convert, .fmt_rgb565_is_0 = false, .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), @@ -634,6 +682,7 @@ static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
[PATCH v3] drm/mediatek: ovl: Add fmt_convert function pointer to driver data
OVL_CON_CLRFMT_MAN is a configuration for extending color format settings of DISP_REG_OVL_CON(n). It will change some of the original color format settings. Take the settings of (3 << 12) for example. - If OVL_CON_CLRFMT_MAN = 0 means OVL_CON_CLRFMT_RGBA. - If OVL_CON_CLRFMT_MAN = 1 means OVL_CON_CLRFMT_PARGB. Since OVL_CON_CLRFMT_MAN is not supported on previous SoCs, It breaks the OVL color format setting of MT8173. Therefore, the fmt_convert function pointer is added to the driver data and mtk_ovl_fmt_convert_with_blend is implemented for MT8192 and MT8195 that support OVL_CON_CLRFMT_MAN, and mtk_ovl_fmt_convert is implemented for other SoCs that do not support it to solve the degradation problem. Fixes: a3f7f7ef4bfe ("drm/mediatek: Support "Pre-multiplied" blending in OVL") Signed-off-by: Jason-JH.Lin Tested-by: Alper Nebi Yasak --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 63 ++--- 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 89b439dcf3a6..4948f269fb81 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -143,6 +143,7 @@ struct mtk_disp_ovl_data { unsigned int addr; unsigned int gmc_bits; unsigned int layer_nr; + unsigned int (*fmt_convert)(struct device *dev, struct mtk_plane_state *state); bool fmt_rgb565_is_0; bool smi_id_en; bool supports_afbc; @@ -386,13 +387,54 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx, DISP_REG_OVL_RDMA_CTRL(idx)); } -static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt, - unsigned int blend_mode) +static unsigned int mtk_ovl_fmt_convert(struct device *dev, struct mtk_plane_state *state) { - /* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX" -* is defined in mediatek HW data sheet. -* The alphabet order in XXX is no relation to data -* arrangement in memory. + struct mtk_disp_ovl *ovl = dev_get_drvdata(dev); + unsigned int fmt = state->pending.format; + + switch (fmt) { + default: + case DRM_FORMAT_RGB565: + return OVL_CON_CLRFMT_RGB565(ovl); + case DRM_FORMAT_BGR565: + return OVL_CON_CLRFMT_RGB565(ovl) | OVL_CON_BYTE_SWAP; + case DRM_FORMAT_RGB888: + return OVL_CON_CLRFMT_RGB888(ovl); + case DRM_FORMAT_BGR888: + return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP; + case DRM_FORMAT_RGBX: + case DRM_FORMAT_RGBA: + case DRM_FORMAT_RGBX1010102: + case DRM_FORMAT_RGBA1010102: + return OVL_CON_CLRFMT_RGBA; + case DRM_FORMAT_XRGB: + case DRM_FORMAT_ARGB: + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_ARGB2101010: + return OVL_CON_CLRFMT_ARGB; + case DRM_FORMAT_XBGR: + case DRM_FORMAT_ABGR: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_ABGR2101010: + return OVL_CON_CLRFMT_ABGR; + case DRM_FORMAT_UYVY: + return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB; + case DRM_FORMAT_YUYV: + return OVL_CON_CLRFMT_YUYV | OVL_CON_MTX_YUV_TO_RGB; + } +} + +static unsigned int mtk_ovl_fmt_convert_with_blend(struct device *dev, + struct mtk_plane_state *state) +{ + struct mtk_disp_ovl *ovl = dev_get_drvdata(dev); + unsigned int fmt = state->pending.format; + unsigned int blend_mode = state->base.pixel_blend_mode; + + /* +* For the platforms where OVL_CON_CLRFMT_MAN is defined in the +* hardware data sheet and supports premultiplied color formats +* such as OVL_CON_CLRFMT_PRGB. */ switch (fmt) { default: @@ -471,7 +513,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, return; } - con = ovl_fmt_convert(ovl, fmt, blend_mode); + con = ovl->data->fmt_convert(dev, state); if (state->base.fb) { con |= OVL_CON_AEN; con |= state->base.alpha & OVL_CON_ALPHA; @@ -625,6 +667,7 @@ static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = { .addr = DISP_REG_OVL_ADDR_MT2701, .gmc_bits = 8, .layer_nr = 4, + .fmt_convert = mtk_ovl_fmt_convert, .fmt_rgb565_is_0 = false, .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), @@ -634,6 +677,7 @@ static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = { .addr = DISP_REG_OVL_ADDR_MT8173, .gmc_bits = 8, .layer_nr = 4, + .fmt_convert = mtk_ovl_fmt_convert, .fmt_rgb565_is_0 = true, .formats = mt8173_formats, .num_formats = ARRAY_SIZ
[PATCH v2] drm/mediatek: ovl: Add fmt_support_man for MT8192 and MT8195
OVL_CON_CLRFMT_MAN is an configuration for extending color format settings of DISP_REG_OVL_CON(n). It will change some of the original color format settings. Take the settings of (3 << 12) for example. - If OVL_CON_CLRFMT_MAN = 0 means OVL_CON_CLRFMT_RGBA. - If OVL_CON_CLRFMT_MAN = 1 means OVL_CON_CLRFMT_PARGB. Since OVL_CON_CLRFMT_MAN is not supported on previous SoCs, It breaks the OVL color format setting of MT8173. So add fmt_support_man to the driver data of MT8192 and MT8195 to solve the downgrade problem. Fixes: a3f7f7ef4bfe ("drm/mediatek: Support "Pre-multiplied" blending in OVL") Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 43 - 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 89b439dcf3a6..7b053ca25b10 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -70,10 +70,33 @@ #define OVL_CON_CLRFMT_UYVY(4 << 12) #define OVL_CON_CLRFMT_YUYV(5 << 12) #define OVL_CON_MTX_YUV_TO_RGB (6 << 16) -#define OVL_CON_CLRFMT_PARGB ((3 << 12) | OVL_CON_CLRFMT_MAN) -#define OVL_CON_CLRFMT_PABGR (OVL_CON_CLRFMT_PARGB | OVL_CON_RGB_SWAP) -#define OVL_CON_CLRFMT_PBGRA (OVL_CON_CLRFMT_PARGB | OVL_CON_BYTE_SWAP) -#define OVL_CON_CLRFMT_PRGBA (OVL_CON_CLRFMT_PABGR | OVL_CON_BYTE_SWAP) + +#define OVL_CON_CLRFMT_PARGB(ovl) ({ \ + struct mtk_disp_ovl *_ovl = (ovl); \ + (_ovl->data->fmt_support_man ? \ + ((3 << 12) | OVL_CON_CLRFMT_MAN) : OVL_CON_CLRFMT_ARGB); \ +}) + +#define OVL_CON_CLRFMT_PABGR(ovl) ({ \ + struct mtk_disp_ovl *_ovl = (ovl); \ + (_ovl->data->fmt_support_man ? \ + (OVL_CON_CLRFMT_PARGB(_ovl) | OVL_CON_RGB_SWAP) : OVL_CON_CLRFMT_ABGR); \ +}) + +#define OVL_CON_CLRFMT_PBGRA(ovl) ({ \ + struct mtk_disp_ovl *_ovl = (ovl); \ + (_ovl->data->fmt_support_man ? \ + (OVL_CON_CLRFMT_PARGB(_ovl) | OVL_CON_BYTE_SWAP) : \ +OVL_CON_CLRFMT_BGRA); \ +}) + +#define OVL_CON_CLRFMT_PRGBA(ovl) ({ \ + struct mtk_disp_ovl *_ovl = (ovl); \ + (_ovl->data->fmt_support_man ? \ + (OVL_CON_CLRFMT_PABGR(_ovl) | OVL_CON_BYTE_SWAP) : \ + OVL_CON_CLRFMT_RGBA); \ +}) + #define OVL_CON_CLRFMT_RGB565(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \ 0 : OVL_CON_CLRFMT_RGB) #define OVL_CON_CLRFMT_RGB888(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \ @@ -144,6 +167,7 @@ struct mtk_disp_ovl_data { unsigned int gmc_bits; unsigned int layer_nr; bool fmt_rgb565_is_0; + bool fmt_support_man; bool smi_id_en; bool supports_afbc; const u32 *formats; @@ -410,28 +434,28 @@ static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt, case DRM_FORMAT_RGBA1010102: return blend_mode == DRM_MODE_BLEND_COVERAGE ? OVL_CON_CLRFMT_RGBA : - OVL_CON_CLRFMT_PRGBA; + OVL_CON_CLRFMT_PRGBA(ovl); case DRM_FORMAT_BGRX: case DRM_FORMAT_BGRA: case DRM_FORMAT_BGRX1010102: case DRM_FORMAT_BGRA1010102: return blend_mode == DRM_MODE_BLEND_COVERAGE ? OVL_CON_CLRFMT_BGRA : - OVL_CON_CLRFMT_PBGRA; + OVL_CON_CLRFMT_PBGRA(ovl); case DRM_FORMAT_XRGB: case DRM_FORMAT_ARGB: case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_ARGB2101010: return blend_mode == DRM_MODE_BLEND_COVERAGE ? OVL_CON_CLRFMT_ARGB : - OVL_CON_CLRFMT_PARGB; + OVL_CON_CLRFMT_PARGB(ovl); case DRM_FORMAT_XBGR: case DRM_FORMAT_ABGR: case DRM_FORMAT_XBGR2101010: case DRM_FORMAT_ABGR2101010: return blend_mode == DRM_MODE_BLEND_COVERAGE ? OVL_CON_CLRFMT_ABGR : - OVL_CON_CLRFMT_PABGR; + OVL_CON_CLRFMT_PABGR(ovl); case DRM_FORMAT_UYVY: return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB; case DRM_FORMAT_YUYV: @@ -662,6 +686,7 @@ static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = { .gmc_bits = 10, .layer_nr = 4, .fmt_rgb565_is_0 = true, + .fmt_support_man = true, .smi_id_en = true, .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), @@ -672,6 +697,7 @@ static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = { .gmc_bits = 10, .layer_nr = 2, .fmt_rgb565_is_0 = true, + .fmt_support_man = true, .smi_id_en = true, .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_form
[PATCH] drm/mediatek: ovl: Add fmt_support_man for MT8192 and MT8195
OVL_CON_CLRFMT_MAN is an configuration for extending color format settings of DISP_REG_OVL_CON(n). It will change some of the original color format settings. Take the settings of (3 << 12) for example. - If OVL_CON_CLRFMT_MAN = 0 means OVL_CON_CLRFMT_RGBA. - If OVL_CON_CLRFMT_MAN = 1 means OVL_CON_CLRFMT_PARGB. Since OVL_CON_CLRFMT_MAN is not supported on previous SoCs, It breaks the OVL color format setting of MT8173. So add fmt_support_man to the driver data of MT8192 and MT8195 to solve the downgrade problem. Fixes: a3f7f7ef4bfe ("drm/mediatek: Support "Pre-multiplied" blending in OVL") Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 28 ++--- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 89b439dcf3a6..aa575569f996 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -70,10 +70,18 @@ #define OVL_CON_CLRFMT_UYVY(4 << 12) #define OVL_CON_CLRFMT_YUYV(5 << 12) #define OVL_CON_MTX_YUV_TO_RGB (6 << 16) -#define OVL_CON_CLRFMT_PARGB ((3 << 12) | OVL_CON_CLRFMT_MAN) -#define OVL_CON_CLRFMT_PABGR (OVL_CON_CLRFMT_PARGB | OVL_CON_RGB_SWAP) -#define OVL_CON_CLRFMT_PBGRA (OVL_CON_CLRFMT_PARGB | OVL_CON_BYTE_SWAP) -#define OVL_CON_CLRFMT_PRGBA (OVL_CON_CLRFMT_PABGR | OVL_CON_BYTE_SWAP) +#define OVL_CON_CLRFMT_PARGB(ovl) ((ovl)->data->fmt_support_man ? \ + ((3 << 12) | OVL_CON_CLRFMT_MAN) : \ + OVL_CON_CLRFMT_ABGR) +#define OVL_CON_CLRFMT_PABGR(ovl) ((ovl)->data->fmt_support_man ? \ + (OVL_CON_CLRFMT_PARGB | OVL_CON_RGB_SWAP) : \ + OVL_CON_CLRFMT_ABGR) +#define OVL_CON_CLRFMT_PBGRA(ovl) ((ovl)->data->fmt_support_man ? \ + (OVL_CON_CLRFMT_PARGB | OVL_CON_BYTE_SWAP) : \ + OVL_CON_CLRFMT_BGRA) +#define OVL_CON_CLRFMT_PRGBA(ovl) ((ovl)->data->fmt_support_man ? \ + (OVL_CON_CLRFMT_PABGR | OVL_CON_BYTE_SWAP) : \ + OVL_CON_CLRFMT_RGBA) #define OVL_CON_CLRFMT_RGB565(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \ 0 : OVL_CON_CLRFMT_RGB) #define OVL_CON_CLRFMT_RGB888(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \ @@ -144,6 +152,7 @@ struct mtk_disp_ovl_data { unsigned int gmc_bits; unsigned int layer_nr; bool fmt_rgb565_is_0; + bool fmt_support_man; bool smi_id_en; bool supports_afbc; const u32 *formats; @@ -410,28 +419,28 @@ static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt, case DRM_FORMAT_RGBA1010102: return blend_mode == DRM_MODE_BLEND_COVERAGE ? OVL_CON_CLRFMT_RGBA : - OVL_CON_CLRFMT_PRGBA; + OVL_CON_CLRFMT_PRGBA(ovl); case DRM_FORMAT_BGRX: case DRM_FORMAT_BGRA: case DRM_FORMAT_BGRX1010102: case DRM_FORMAT_BGRA1010102: return blend_mode == DRM_MODE_BLEND_COVERAGE ? OVL_CON_CLRFMT_BGRA : - OVL_CON_CLRFMT_PBGRA; + OVL_CON_CLRFMT_PBGRA(ovl); case DRM_FORMAT_XRGB: case DRM_FORMAT_ARGB: case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_ARGB2101010: return blend_mode == DRM_MODE_BLEND_COVERAGE ? OVL_CON_CLRFMT_ARGB : - OVL_CON_CLRFMT_PARGB; + OVL_CON_CLRFMT_PARGB(ovl); case DRM_FORMAT_XBGR: case DRM_FORMAT_ABGR: case DRM_FORMAT_XBGR2101010: case DRM_FORMAT_ABGR2101010: return blend_mode == DRM_MODE_BLEND_COVERAGE ? OVL_CON_CLRFMT_ABGR : - OVL_CON_CLRFMT_PABGR; + OVL_CON_CLRFMT_PABGR(ovl); case DRM_FORMAT_UYVY: return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB; case DRM_FORMAT_YUYV: @@ -662,6 +671,7 @@ static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = { .gmc_bits = 10, .layer_nr = 4, .fmt_rgb565_is_0 = true, + .fmt_support_man = true, .smi_id_en = true, .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), @@ -672,6 +682,7 @@ static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = { .gmc_bits = 10, .layer_nr = 2, .fmt_rgb565_is_0 = true, + .fmt_support_man = true, .smi_id_en = true, .formats = mt8173_formats, .num_formats = ARRAY_SIZE(mt8173_formats), @
[PATCH] drm/mediatek: Fix missing configuration flags in mtk_crtc_ddp_config()
In mtk_crtc_ddp_config(), mtk_crtc will use some configuration flags to generate instructions to cmdq_handle, such as: state->pending_config mtk_crtc->pending_planes plane_state->pending.config mtk_crtc->pending_async_planes plane_state->pending.async_config These configuration flags may be set to false when a GCE IRQ comes calling ddp_cmdq_cb(). This may result in missing prepare instructions, especially if mtk_crtc_update_config() with the flase need_vblank (no need to wait for vblank) cases. Therefore, use the mtk_crtc->config_updating flag set at the beginning of mtk_crtc_update_config() to ensure that these configuration flags won't be changed when the mtk_crtc_ddp_config() is preparing instructions. Fixes: 7f82d9c43879 ("drm/mediatek: Clear pending flag when cmdq packet is done") Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_crtc.c | 34 +++-- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c index 6f34f573e127..bc3bf0c3edd9 100644 --- a/drivers/gpu/drm/mediatek/mtk_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_crtc.c @@ -314,30 +314,32 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg) state = to_mtk_crtc_state(mtk_crtc->base.state); - state->pending_config = false; + if (!mtk_crtc->config_updating) { + state->pending_config = false; - if (mtk_crtc->pending_planes) { - for (i = 0; i < mtk_crtc->layer_nr; i++) { - struct drm_plane *plane = &mtk_crtc->planes[i]; - struct mtk_plane_state *plane_state; + if (mtk_crtc->pending_planes) { + for (i = 0; i < mtk_crtc->layer_nr; i++) { + struct drm_plane *plane = &mtk_crtc->planes[i]; + struct mtk_plane_state *plane_state; - plane_state = to_mtk_plane_state(plane->state); + plane_state = to_mtk_plane_state(plane->state); - plane_state->pending.config = false; + plane_state->pending.config = false; + } + mtk_crtc->pending_planes = false; } - mtk_crtc->pending_planes = false; - } - if (mtk_crtc->pending_async_planes) { - for (i = 0; i < mtk_crtc->layer_nr; i++) { - struct drm_plane *plane = &mtk_crtc->planes[i]; - struct mtk_plane_state *plane_state; + if (mtk_crtc->pending_async_planes) { + for (i = 0; i < mtk_crtc->layer_nr; i++) { + struct drm_plane *plane = &mtk_crtc->planes[i]; + struct mtk_plane_state *plane_state; - plane_state = to_mtk_plane_state(plane->state); + plane_state = to_mtk_plane_state(plane->state); - plane_state->pending.async_config = false; + plane_state->pending.async_config = false; + } + mtk_crtc->pending_async_planes = false; } - mtk_crtc->pending_async_planes = false; } mtk_crtc->cmdq_vblank_cnt = 0; -- 2.18.0
[PATCH] drm/mediatek: Fix bit depth overwritten for mtk_ovl_set bit_depth()
Refine the value and mask define of bit depth for mtk_ovl_set bit_depth(). Use cmdq_pkt_write_mask() instead of cmdq_pkt_write() to avoid bit depth settings being overwritten. Fixes: fb36c5020c9c ("drm/mediatek: Add support for AR30 and BA30 overlays") Signed-off-by: Jason-JH.Lin --- Based on: https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 21 - 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 4b370bc0746d..d35f5b4b22c2 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -42,7 +42,11 @@ #define DISP_REG_OVL_RDMA_CTRL(n) (0x00c0 + 0x20 * (n)) #define DISP_REG_OVL_RDMA_GMC(n) (0x00c8 + 0x20 * (n)) #define DISP_REG_OVL_ADDR_MT2701 0x0040 -#define DISP_REG_OVL_CLRFMT_EXT0x02D0 +#define DISP_REG_OVL_CLRFMT_EXT0x02d0 +#define OVL_CON_CLRFMT_BIT_DEPTH_MASK(n) (GENMASK(1, 0) << (4 * (n))) +#define OVL_CON_CLRFMT_BIT_DEPTH(depth, n) ((depth) << (4 * (n))) +#define OVL_CON_CLRFMT_8_BIT (0) +#define OVL_CON_CLRFMT_10_BIT (1) #define DISP_REG_OVL_ADDR_MT8173 0x0f40 #define DISP_REG_OVL_ADDR(ovl, n) ((ovl)->data->addr + 0x20 * (n)) #define DISP_REG_OVL_HDR_ADDR(ovl, n) ((ovl)->data->addr + 0x20 * (n) + 0x04) @@ -65,10 +69,6 @@ 0 : OVL_CON_CLRFMT_RGB) #define OVL_CON_CLRFMT_RGB888(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \ OVL_CON_CLRFMT_RGB : 0) -#define OVL_CON_CLRFMT_BIT_DEPTH_MASK(ovl) (0xFF << 4 * (ovl)) -#define OVL_CON_CLRFMT_BIT_DEPTH(depth, ovl) (depth << 4 * (ovl)) -#define OVL_CON_CLRFMT_8_BIT 0x00 -#define OVL_CON_CLRFMT_10_BIT 0x01 #defineOVL_CON_AEN BIT(8) #defineOVL_CON_ALPHA 0xff #defineOVL_CON_VIRT_FLIP BIT(9) @@ -273,22 +273,17 @@ static void mtk_ovl_set_bit_depth(struct device *dev, int idx, u32 format, struct cmdq_pkt *cmdq_pkt) { struct mtk_disp_ovl *ovl = dev_get_drvdata(dev); - unsigned int reg; unsigned int bit_depth = OVL_CON_CLRFMT_8_BIT; if (!ovl->data->supports_clrfmt_ext) return; - reg = readl(ovl->regs + DISP_REG_OVL_CLRFMT_EXT); - reg &= ~OVL_CON_CLRFMT_BIT_DEPTH_MASK(idx); - if (is_10bit_rgb(format)) bit_depth = OVL_CON_CLRFMT_10_BIT; - reg |= OVL_CON_CLRFMT_BIT_DEPTH(bit_depth, idx); - - mtk_ddp_write(cmdq_pkt, reg, &ovl->cmdq_reg, - ovl->regs, DISP_REG_OVL_CLRFMT_EXT); + mtk_ddp_write_mask(cmdq_pkt, OVL_CON_CLRFMT_BIT_DEPTH(bit_depth, idx), + &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_CLRFMT_EXT, + OVL_CON_CLRFMT_BIT_DEPTH_MASK(idx)); } void mtk_ovl_config(struct device *dev, unsigned int w, -- 2.18.0
[PATCH RESEND, v6 4/8] mailbox: mtk-cmdq: Support GCE loop packets in interrupt handler
1. Add a loop flag for CMDQ packet struct. CMDQ helper will use a loop flag to mark CMDQ packet as lopping command and make current command buffer jumps to the beginning when GCE executes to the end of command buffer. 2. Add a looping task handle flow in irq handler. GCE irq occurs when GCE executes to the end of command(EOC) instruction. If the CMDQ packet is a loopping command, GCE irq handler can not delete the CMDQ task and disable the GCE thread. Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- drivers/mailbox/mtk-cmdq-mailbox.c | 11 +++ include/linux/mailbox/mtk-cmdq-mailbox.h | 1 + 2 files changed, 12 insertions(+) diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c index 4aa394e91109..618023011d31 100644 --- a/drivers/mailbox/mtk-cmdq-mailbox.c +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -267,6 +267,17 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq, curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) << cmdq->pdata->shift; + task = list_first_entry_or_null(&thread->task_busy_list, + struct cmdq_task, list_entry); + if (task && task->pkt->loop) { + struct cmdq_cb_data data; + + data.sta = err; + data.pkt = task->pkt; + mbox_chan_received_data(task->thread->chan, &data); + return; + } + list_for_each_entry_safe(task, tmp, &thread->task_busy_list, list_entry) { task_end_pa = task->pa_base + task->pkt->cmd_buf_size; diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h index a8f0070c7aa9..f78a08e7c6ed 100644 --- a/include/linux/mailbox/mtk-cmdq-mailbox.h +++ b/include/linux/mailbox/mtk-cmdq-mailbox.h @@ -76,6 +76,7 @@ struct cmdq_pkt { size_t cmd_buf_size; /* command occupied size */ size_t buf_size; /* real buffer size */ void*cl; + boolloop; }; u8 cmdq_get_shift_pa(struct mbox_chan *chan); -- 2.18.0
[PATCH RESEND, v6 8/8] soc: mediatek: mtk-cmdq: Add secure cmdq_pkt APIs
Open secure cmdq_pkt APIs to support executing commands in secure world. 1. Add cmdq_sec_pkt_alloc_sec_data(), cmdq_sec_pkt_free_sec_data() and cmdq_sec_pkt_set_data() to prepare the sec_data in cmdq_pkt that will be referenced in the secure world. 2. Add cmdq_sec_insert_backup_cookie() and cmdq_sec_pkt_write() to generate commands that need to be executed in the secure world. In cmdq_sec_pkt_write(), we need to prepare the metadata to store buffer offset of the secure buffer handle because secure world can only translate the start address of secure buffer by secure handle. Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- drivers/soc/mediatek/mtk-cmdq-helper.c | 155 + include/linux/soc/mediatek/mtk-cmdq.h | 71 +++ 2 files changed, 226 insertions(+) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index 42fae05f61a8..de6557f3ca2f 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -562,4 +562,159 @@ int cmdq_pkt_finalize(struct cmdq_pkt *pkt) } EXPORT_SYMBOL(cmdq_pkt_finalize); +int cmdq_sec_insert_backup_cookie(struct cmdq_pkt *pkt) +{ + struct cmdq_client *cl = (struct cmdq_client *)pkt->cl; + struct cmdq_operand left, right; + dma_addr_t addr; + + addr = cmdq_sec_get_exec_cnt_addr(cl->chan); + cmdq_pkt_assign(pkt, CMDQ_THR_SPR_IDX1, CMDQ_ADDR_HIGH(addr)); + cmdq_pkt_read_s(pkt, CMDQ_THR_SPR_IDX1, CMDQ_ADDR_LOW(addr), CMDQ_THR_SPR_IDX1); + + left.reg = true; + left.idx = CMDQ_THR_SPR_IDX1; + right.reg = false; + right.value = 1; + cmdq_pkt_logic_command(pkt, CMDQ_THR_SPR_IDX1, &left, CMDQ_LOGIC_ADD, &right); + + addr = cmdq_sec_get_cookie_addr(cl->chan); + cmdq_pkt_assign(pkt, CMDQ_THR_SPR_IDX2, CMDQ_ADDR_HIGH(addr)); + cmdq_pkt_write_s(pkt, CMDQ_THR_SPR_IDX2, CMDQ_ADDR_LOW(addr), CMDQ_THR_SPR_IDX1); + cmdq_pkt_set_event(pkt, cmdq_sec_get_eof_event_id(cl->chan)); + + return 0; +} +EXPORT_SYMBOL_GPL(cmdq_sec_insert_backup_cookie); + +static int cmdq_sec_realloc_addr_list(struct cmdq_pkt *pkt, const u32 count) +{ + struct cmdq_sec_data *sec_data = (struct cmdq_sec_data *)pkt->sec_data; + void *prev = (void *)(unsigned long)sec_data->addr_metadatas, *curr; + + if (count <= sec_data->addr_metadata_max_cnt) + return 0; + + curr = kcalloc(count, sizeof(*sec_data), GFP_KERNEL); + if (!curr) + return -ENOMEM; + + if (count && sec_data->addr_metadatas) + memcpy(curr, prev, sizeof(*sec_data) * sec_data->addr_metadata_max_cnt); + + kfree(prev); + + sec_data->addr_metadatas = (uintptr_t)curr; + sec_data->addr_metadata_max_cnt = count; + return 0; +} + +void cmdq_sec_pkt_free_sec_data(struct cmdq_pkt *pkt) +{ + kfree(pkt->sec_data); +} +EXPORT_SYMBOL_GPL(cmdq_sec_pkt_free_sec_data); + +int cmdq_sec_pkt_alloc_sec_data(struct cmdq_pkt *pkt) +{ + struct cmdq_sec_data *sec_data; + + if (pkt->sec_data) + return 0; + + sec_data = kzalloc(sizeof(*sec_data), GFP_KERNEL); + if (!sec_data) + return -ENOMEM; + + pkt->sec_data = (void *)sec_data; + + return 0; +} +EXPORT_SYMBOL_GPL(cmdq_sec_pkt_alloc_sec_data); + +static int cmdq_sec_append_metadata(struct cmdq_pkt *pkt, + const enum cmdq_iwc_addr_metadata_type type, + const u32 base, const u32 offset) +{ + struct cmdq_sec_data *sec_data; + struct iwc_cmdq_addr_metadata_t *meta; + int idx, max, ret; + + pr_debug("[%s %d] pkt:%p type:%u base:%#x offset:%#x", +__func__, __LINE__, pkt, type, base, offset); + + ret = cmdq_sec_pkt_alloc_sec_data(pkt); + if (ret < 0) + return ret; + + sec_data = (struct cmdq_sec_data *)pkt->sec_data; + idx = sec_data->addr_metadata_cnt; + if (idx >= CMDQ_IWC_MAX_ADDR_LIST_LENGTH) { + pr_err("idx:%u reach over:%u", idx, CMDQ_IWC_MAX_ADDR_LIST_LENGTH); + return -EFAULT; + } + + if (!sec_data->addr_metadata_max_cnt) + max = ADDR_METADATA_MAX_COUNT_ORIGIN; + else if (idx >= sec_data->addr_metadata_max_cnt) + max = sec_data->addr_metadata_max_cnt * 2; + else + max = sec_data->addr_metadata_max_cnt; + + ret = cmdq_sec_realloc_addr_list(pkt, max); + if (ret) + return ret; + + if (!sec_data->addr_metadatas) { + pr_info("addr_metadatas is missing"); + + meta = kzalloc(sizeof(*meta), GFP_KERNEL); + if (!meta) + return -ENOMEM; + + sec_data->addr_metadatas = (uintptr_t)(void *)meta; + } + meta = (struct iwc_cmdq_addr_metadata_t *)(uintptr_t)sec_data->addr_metadata
[PATCH RESEND, v6 7/8] mailbox: mediatek: Add secure CMDQ driver support for CMDQ driver
CMDQ driver will probe a secure CMDQ driver when has_sec flag in platform data is true and its device node in dts has defined a event id of CMDQ_SYNC_TOKEN_SEC_EOF. Secure CMDQ driver support on mt8188 and mt8195 currently. So add a has_secure flag to their driver data to probe it. Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- drivers/mailbox/mtk-cmdq-mailbox.c | 76 ++ 1 file changed, 76 insertions(+) diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c index 025e53549a45..5c606684b07b 100644 --- a/drivers/mailbox/mtk-cmdq-mailbox.c +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #define CMDQ_MBOX_AUTOSUSPEND_DELAY_MS 100 @@ -55,11 +56,22 @@ #define CMDQ_JUMP_BY_OFFSET0x1000 #define CMDQ_JUMP_BY_PA0x1001 +#define CMDQ_THR_IDX(thread, cmdq) (((thread)->base - (cmdq)->base - CMDQ_THR_BASE) \ +/ CMDQ_THR_SIZE) + +#define CMDQ_IS_SECURE_THREAD(idx, cmdq) ((cmdq)->pdata->has_secure && \ + (idx) >= (cmdq)->pdata->secure_thread_min && \ + (idx) < (cmdq)->pdata->secure_thread_min + \ + (cmdq)->pdata->secure_thread_nr) + struct gce_plat { u32 thread_nr; u8 shift; bool control_by_sw; bool sw_ddr_en; + bool has_secure; + u32 secure_thread_nr; + u32 secure_thread_min; u32 gce_num; }; @@ -368,6 +380,7 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev); struct cmdq_task *task; unsigned long curr_pa, end_pa; + u32 idx = CMDQ_THR_IDX(thread, cmdq); int ret; /* Client should not flush new tasks if suspended. */ @@ -377,6 +390,13 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) if (ret < 0) return ret; + if (CMDQ_IS_SECURE_THREAD(idx, cmdq)) { + ret = cmdq_sec_mbox.ops->send_data(chan, data); + pm_runtime_mark_last_busy(cmdq->mbox.dev); + pm_runtime_put_autosuspend(cmdq->mbox.dev); + return ret; + } + task = kzalloc(sizeof(*task), GFP_ATOMIC); if (!task) { pm_runtime_put_autosuspend(cmdq->mbox.dev); @@ -436,6 +456,13 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) static int cmdq_mbox_startup(struct mbox_chan *chan) { + struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev); + struct cmdq_thread *thread = (struct cmdq_thread *)chan->con_priv; + u32 idx = CMDQ_THR_IDX(thread, cmdq); + + if (CMDQ_IS_SECURE_THREAD(idx, cmdq)) + cmdq_sec_mbox.ops->startup(chan); + return 0; } @@ -445,9 +472,17 @@ static void cmdq_mbox_shutdown(struct mbox_chan *chan) struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev); struct cmdq_task *task, *tmp; unsigned long flags; + u32 idx = CMDQ_THR_IDX(thread, cmdq); WARN_ON(pm_runtime_get_sync(cmdq->mbox.dev) < 0); + if (CMDQ_IS_SECURE_THREAD(idx, cmdq)) { + cmdq_sec_mbox.ops->shutdown(chan); + pm_runtime_mark_last_busy(cmdq->mbox.dev); + pm_runtime_put_autosuspend(cmdq->mbox.dev); + return; + } + spin_lock_irqsave(&thread->chan->lock, flags); if (list_empty(&thread->task_busy_list)) goto done; @@ -488,12 +523,20 @@ static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout) struct cmdq_task *task, *tmp; unsigned long flags; u32 enable; + u32 idx = CMDQ_THR_IDX(thread, cmdq); int ret; ret = pm_runtime_get_sync(cmdq->mbox.dev); if (ret < 0) return ret; + if (CMDQ_IS_SECURE_THREAD(idx, cmdq)) { + cmdq_sec_mbox.ops->flush(chan, timeout); + pm_runtime_mark_last_busy(cmdq->mbox.dev); + pm_runtime_put_autosuspend(cmdq->mbox.dev); + return 0; + } + spin_lock_irqsave(&thread->chan->lock, flags); if (list_empty(&thread->task_busy_list)) goto out; @@ -569,6 +612,7 @@ static int cmdq_probe(struct platform_device *pdev) int alias_id = 0; static const char * const clk_name = "gce"; static const char * const clk_names[] = { "gce0", "gce1" }; + u32 hwid = 0; cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL); if (!cmdq) @@ -594,6 +638,8 @@ static int cmdq_probe(struct platform_device *pdev) dev, cmdq->base, cmdq->irq); if (cmdq->pdata->gce_num > 1) { + hwid = of_alias_get_id(dev->of_node, clk_name); + for_each_child_of_node(phan
[PATCH RESEND, v6 2/8] dt-bindings: mailbox: Add property for CMDQ secure driver
1. Add mboxes property to define a GCE loopping thread as a secure IRQ handler. The CMDQ secure driver requests a mbox channel and sends a looping command to the GCE thread. The looping command will wait for a secure packet done event signal from secure world and then jump back to the first instuction. Each time it waits for an event, it notifies the CMDQ driver to perform the same action as the IRQ handler. 2. Add gce-events property from gce-props.yaml to define a secure packet done signal in secure world. There are 1024 events IDs for GCE to use to execute instructions in the specific event happened. These events could be signaled by HW or SW and their value would be different in different SoC because of HW event IDs distribution range from 0 to 1023. If we set a static event ID: 855 for mt8188, it might be conflict the event ID original set in mt8195. So we define an event ID that will be set when GCE runs to the end of secure cmdq packet in the secure world. This can reduce the latency of software communication between normal world and secure world. In addition, we can also remove the complex logic after the secure packet done in the secure world. Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- .../devicetree/bindings/mailbox/mediatek,gce-mailbox.yaml | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mailbox/mediatek,gce-mailbox.yaml b/Documentation/devicetree/bindings/mailbox/mediatek,gce-mailbox.yaml index cef9d7601398..6e5e848d61d9 100644 --- a/Documentation/devicetree/bindings/mailbox/mediatek,gce-mailbox.yaml +++ b/Documentation/devicetree/bindings/mailbox/mediatek,gce-mailbox.yaml @@ -49,6 +49,10 @@ properties: items: - const: gce + mboxes: +items: + - description: GCE looping thread as a secure IRQ handler + required: - compatible - "#mbox-cells" @@ -57,6 +61,8 @@ required: - clocks allOf: + - $ref: /schemas/mailbox/mediatek,gce-props.yaml# + - if: not: properties: @@ -67,7 +73,7 @@ allOf: required: - clock-names -additionalProperties: false +unevaluatedProperties: false examples: - | -- 2.18.0
[PATCH RESEND, v6 6/8] mailbox: mediatek: Add CMDQ secure mailbox driver
To support secure video path feature, GCE have to read/write registgers in the secure world. GCE will enable the secure access permission to the HW who wants to access the secure content buffer. Add CMDQ secure mailbox driver to make CMDQ client user is able to sending their HW settings to the secure world. So that GCE can execute all instructions to configure HW in the secure world. TODO: 1. Squash cmdq_sec_task_exec_work() into cmdq_sec_mbox_send_data(). 2. Call into TEE to query cookie instead of using shared memory in cmdq_sec_get_cookie(). 3. Register shared memory as command buffer instead of copying normal command buffer to IWC shared memory. 4. Use SOFTDEP to make cmdq_sec_probe later than OPTEE loaded and then move cmdq_sec_session_init into cmdq_sec_probe(). 5. Remove timeout detection in cmdq_sec_session_send(). Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- drivers/mailbox/Makefile | 2 +- drivers/mailbox/mtk-cmdq-sec-mailbox.c| 931 ++ drivers/mailbox/mtk-cmdq-sec-tee.c| 195 include/linux/mailbox/mtk-cmdq-mailbox.h | 1 + .../linux/mailbox/mtk-cmdq-sec-iwc-common.h | 342 +++ include/linux/mailbox/mtk-cmdq-sec-mailbox.h | 106 ++ include/linux/mailbox/mtk-cmdq-sec-tee.h | 105 ++ 7 files changed, 1681 insertions(+), 1 deletion(-) create mode 100644 drivers/mailbox/mtk-cmdq-sec-mailbox.c create mode 100644 drivers/mailbox/mtk-cmdq-sec-tee.c create mode 100644 include/linux/mailbox/mtk-cmdq-sec-iwc-common.h create mode 100644 include/linux/mailbox/mtk-cmdq-sec-mailbox.h create mode 100644 include/linux/mailbox/mtk-cmdq-sec-tee.h diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 5cf2f54debaf..f4c304b50328 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -53,7 +53,7 @@ obj-$(CONFIG_STM32_IPCC) += stm32-ipcc.o obj-$(CONFIG_MTK_ADSP_MBOX)+= mtk-adsp-mailbox.o -obj-$(CONFIG_MTK_CMDQ_MBOX)+= mtk-cmdq-mailbox.o +obj-$(CONFIG_MTK_CMDQ_MBOX)+= mtk-cmdq-mailbox.o mtk-cmdq-sec-mailbox.o mtk-cmdq-sec-tee.o obj-$(CONFIG_ZYNQMP_IPI_MBOX) += zynqmp-ipi-mailbox.o diff --git a/drivers/mailbox/mtk-cmdq-sec-mailbox.c b/drivers/mailbox/mtk-cmdq-sec-mailbox.c new file mode 100644 index ..f1ba827bf3a1 --- /dev/null +++ b/drivers/mailbox/mtk-cmdq-sec-mailbox.c @@ -0,0 +1,931 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define CMDQ_THR_EXEC_CNT_PA (0x28) + +#define CMDQ_TIMEOUT_DEFAULT (1000) + +#define CMDQ_WFE_CMD(event)(0x200080008001ULL | ((u64)(event) << 32)) +#define CMDQ_EOC_CMD (0x4001ULL) +#define CMDQ_JUMP_CMD(addr, shift) (0x1001ULL | ((addr) >> (shift))) + +struct cmdq_sec_task { + struct cmdq_tasktask; + + /* secure CMDQ */ + boolreset_exec; + u32 wait_cookie; + s32 scenario; + u64 trigger; + u64 exec_time; + struct work_struct exec_work; +}; + +struct cmdq_sec_thread { + struct cmdq_thread thread; + + /* secure CMDQ */ + struct device *dev; + u32 idx; + struct timer_list timeout; + u32 timeout_ms; + struct work_struct timeout_work; + u32 wait_cookie; + u32 next_cookie; + u32 task_cnt; + struct workqueue_struct *task_exec_wq; +}; + +/** + * struct cmdq_sec_context - CMDQ secure context structure. + * @tgid: tgid of process context. + * @state: state of inter-world communicatiom. + * @iwc_msg: buffer for inter-world communicatiom message. + * @tee_ctx: context structure for tee vendor. + * + * Note it is not global data, each process has its own cmdq_sec_context. + */ +struct cmdq_sec_context { + u32 tgid; + enum cmdq_iwc_state_enumstate; + void*iwc_msg; + struct cmdq_sec_tee_context tee_ctx; +}; + +/** + * struct cmdq_sec_shared_mem - shared memory between normal and secure world + * @va: virtual address of share memory. + * @pa: physical address of share memory. + * @size: size of share memory. + * + */ +struct cmdq_sec_shared_mem { + void*va; + dma_addr_t pa; + u32 size; +}; + +struct cmdq_sec { + struct device dev; + const struct gce_sec_plat *pdata; + void
[PATCH RESEND, v6 5/8] mailbox: mediatek: Move reuseable definition to header for secure driver
To support CMDQ secure driver, move some reuseable definition to header. - define: e.g. CMDQ_GCE_NUM_MAX, CMDQ_THR_BASE, CMDQ_THR_SIZE. - struct: e.g. cmdq_thread, cmdq, cmdq_task. - include: e.g. . Add "#include " for the function that takes "struct mbox_chan * chan" as a parameter. That may occur a build error if secure driver header includes the mtk-cmdq-mailbox.h. - function: e.g. cmdq_get_shift_pa(struct mbox_chan *chan). Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- drivers/mailbox/mtk-cmdq-mailbox.c | 30 - include/linux/mailbox/mtk-cmdq-mailbox.h | 33 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c index 618023011d31..025e53549a45 100644 --- a/drivers/mailbox/mtk-cmdq-mailbox.c +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -3,7 +3,6 @@ // Copyright (c) 2018 MediaTek Inc. #include -#include #include #include #include @@ -22,13 +21,10 @@ #define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT) #define CMDQ_NUM_CMD(t)(t->cmd_buf_size / CMDQ_INST_SIZE) -#define CMDQ_GCE_NUM_MAX (2) #define CMDQ_CURR_IRQ_STATUS 0x10 #define CMDQ_SYNC_TOKEN_UPDATE 0x68 #define CMDQ_THR_SLOT_CYCLES 0x30 -#define CMDQ_THR_BASE 0x100 -#define CMDQ_THR_SIZE 0x80 #define CMDQ_THR_WARM_RESET0x00 #define CMDQ_THR_ENABLE_TASK 0x04 #define CMDQ_THR_SUSPEND_TASK 0x08 @@ -59,32 +55,6 @@ #define CMDQ_JUMP_BY_OFFSET0x1000 #define CMDQ_JUMP_BY_PA0x1001 -struct cmdq_thread { - struct mbox_chan*chan; - void __iomem*base; - struct list_headtask_busy_list; - u32 priority; -}; - -struct cmdq_task { - struct cmdq *cmdq; - struct list_headlist_entry; - dma_addr_t pa_base; - struct cmdq_thread *thread; - struct cmdq_pkt *pkt; /* the packet sent from mailbox client */ -}; - -struct cmdq { - struct mbox_controller mbox; - void __iomem*base; - int irq; - u32 irq_mask; - const struct gce_plat *pdata; - struct cmdq_thread *thread; - struct clk_bulk_dataclocks[CMDQ_GCE_NUM_MAX]; - boolsuspended; -}; - struct gce_plat { u32 thread_nr; u8 shift; diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h index f78a08e7c6ed..43eae45a08c9 100644 --- a/include/linux/mailbox/mtk-cmdq-mailbox.h +++ b/include/linux/mailbox/mtk-cmdq-mailbox.h @@ -7,10 +7,17 @@ #ifndef __MTK_CMDQ_MAILBOX_H__ #define __MTK_CMDQ_MAILBOX_H__ +#include +#include #include #include #include +#define CMDQ_GCE_NUM_MAX 2 + +#define CMDQ_THR_BASE 0x100 +#define CMDQ_THR_SIZE 0x80 + #define CMDQ_INST_SIZE 8 /* instruction is 64-bit */ #define CMDQ_SUBSYS_SHIFT 16 #define CMDQ_OP_CODE_SHIFT 24 @@ -79,6 +86,32 @@ struct cmdq_pkt { boolloop; }; +struct cmdq_thread { + struct mbox_chan*chan; + void __iomem*base; + struct list_headtask_busy_list; + u32 priority; +}; + +struct cmdq { + struct mbox_controller mbox; + void __iomem*base; + int irq; + u32 irq_mask; + const struct gce_plat *pdata; + struct cmdq_thread *thread; + struct clk_bulk_dataclocks[CMDQ_GCE_NUM_MAX]; + boolsuspended; +}; + +struct cmdq_task { + struct cmdq *cmdq; + struct list_headlist_entry; + dma_addr_t pa_base; + struct cmdq_thread *thread; + struct cmdq_pkt *pkt; /* the packet sent from mailbox client */ +}; + u8 cmdq_get_shift_pa(struct mbox_chan *chan); #endif /* __MTK_CMDQ_MAILBOX_H__ */ -- 2.18.0
[PATCH RESEND, v6 1/8] dt-bindings: gce: mt8195: Add CMDQ_SYNC_TOKEN_SECURE_THR_EOF event id
There are 2 kind of GCE event signal: - The SW token means: a GCE event signal triggered by SW drivers. e.g. SW driver append a GCE command to set a GCE event after a specific GCE command. Or SW driver use CPU to write a event id to GCE register to trigger the GCE event corresponding to that event id. - The HW event means: a GCE event signal triggered by HW engines. e.g. When HW OVL fetches all the data in frame buffer, HW OVL will send a frame done irq and also send a frame done GCE event via HW bus directly. CMDQ_SYNC_TOKEN_SECURE_THR_EOF is a SW token event that is set in the end of each cmdq secure pkt. It is used as a secure irq to notify CMDQ driver in the normal world that GCE secure thread has completed a secure cmd buffer in thee secure world. Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- include/dt-bindings/gce/mt8195-gce.h | 6 ++ 1 file changed, 6 insertions(+) diff --git a/include/dt-bindings/gce/mt8195-gce.h b/include/dt-bindings/gce/mt8195-gce.h index dcfb302b8a5b..b6b3db82c381 100644 --- a/include/dt-bindings/gce/mt8195-gce.h +++ b/include/dt-bindings/gce/mt8195-gce.h @@ -800,6 +800,12 @@ #define CMDQ_EVENT_WPE_VPP1_WPE_GCE_FRAME_DONE 969 #define CMDQ_EVENT_WPE_VPP1_WPE_DONE_SYNC_OUT 970 +/* + * Notify normal CMDQ there are some secure task done, + * this token sync with secure world. + */ +#define CMDQ_SYNC_TOKEN_SECURE_THR_EOF 980 + #define CMDQ_EVENT_DP_TX_VBLANK_FALLING994 #define CMDQ_EVENT_DP_TX_VSC_FINISH995 -- 2.18.0
[PATCH RESEND, v6 3/8] soc: mediatek: cmdq: Add cmdq_pkt_logic_command to support math operation
Add cmdq_pkt_logic_command to support math operation. cmdq_pkt_logic_command can append logic command to the CMDQ packet, ask GCE to execute a arithmetic calculate instruction, such as add, subtract, multiply, AND, OR and NOT, etc. Note that all arithmetic instructions are unsigned calculations. If there are any overflows, GCE will sent the invalid IRQ to notify CMDQ driver. Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- drivers/soc/mediatek/mtk-cmdq-helper.c | 36 ++ include/linux/soc/mediatek/mtk-cmdq.h | 42 ++ 2 files changed, 78 insertions(+) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index 046522664dc1..42fae05f61a8 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -15,10 +15,19 @@ /* dedicate the last GPR_R15 to assign the register address to be poll */ #define CMDQ_POLL_ADDR_GPR (15) #define CMDQ_EOC_IRQ_ENBIT(0) +#define CMDQ_IMMEDIATE_VALUE 0 #define CMDQ_REG_TYPE 1 #define CMDQ_JUMP_RELATIVE 0 #define CMDQ_JUMP_ABSOLUTE 1 +#define CMDQ_OPERAND_GET_IDX_VALUE(operand) \ + ({ \ + struct cmdq_operand *op = operand; \ + op->reg ? op->idx : op->value; \ + }) +#define CMDQ_OPERAND_TYPE(operand) \ + ((operand)->reg ? CMDQ_REG_TYPE : CMDQ_IMMEDIATE_VALUE) + struct cmdq_instruction { union { u32 value; @@ -461,6 +470,33 @@ int cmdq_pkt_poll_addr(struct cmdq_pkt *pkt, dma_addr_t addr, u32 value, u32 mas } EXPORT_SYMBOL(cmdq_pkt_poll_addr); +int cmdq_pkt_logic_command(struct cmdq_pkt *pkt, u16 result_reg_idx, + struct cmdq_operand *left_operand, + enum cmdq_logic_op s_op, + struct cmdq_operand *right_operand) +{ + struct cmdq_instruction inst = { {0} }; + u32 left_idx_value; + u32 right_idx_value; + + if (!left_operand || !right_operand || s_op >= CMDQ_LOGIC_MAX) + return -EINVAL; + + left_idx_value = CMDQ_OPERAND_GET_IDX_VALUE(left_operand); + right_idx_value = CMDQ_OPERAND_GET_IDX_VALUE(right_operand); + inst.op = CMDQ_CODE_LOGIC; + inst.dst_t = CMDQ_REG_TYPE; + inst.src_t = CMDQ_OPERAND_TYPE(left_operand); + inst.arg_c_t = CMDQ_OPERAND_TYPE(right_operand); + inst.sop = s_op; + inst.reg_dst = result_reg_idx; + inst.src_reg = left_idx_value; + inst.arg_c = right_idx_value; + + return cmdq_pkt_append_command(pkt, inst); +} +EXPORT_SYMBOL(cmdq_pkt_logic_command); + int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value) { struct cmdq_instruction inst = {}; diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index d4a8e34505e6..5bee6f7fc400 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -25,6 +25,31 @@ struct cmdq_pkt; +enum cmdq_logic_op { + CMDQ_LOGIC_ASSIGN = 0, + CMDQ_LOGIC_ADD = 1, + CMDQ_LOGIC_SUBTRACT = 2, + CMDQ_LOGIC_MULTIPLY = 3, + CMDQ_LOGIC_XOR = 8, + CMDQ_LOGIC_NOT = 9, + CMDQ_LOGIC_OR = 10, + CMDQ_LOGIC_AND = 11, + CMDQ_LOGIC_LEFT_SHIFT = 12, + CMDQ_LOGIC_RIGHT_SHIFT = 13, + CMDQ_LOGIC_MAX, +}; + +struct cmdq_operand { + /* register type */ + bool reg; + union { + /* index */ + u16 idx; + /* value */ + u16 value; + }; +}; + struct cmdq_client_reg { u8 subsys; u16 offset; @@ -272,6 +297,23 @@ int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys, int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value, u32 mask); +/** + * cmdq_pkt_logic_command() - Append logic command to the CMDQ packet, ask GCE to + * execute an instruction that store the result of logic operation + * with left and right operand into result_reg_idx. + * @pkt: the CMDQ packet + * @result_reg_idx:SPR index that store operation result of left_operand and right_operand + * @left_operand: left operand + * @s_op: the logic operator enum + * @right_operand: right operand + * + * Return: 0 for success; else the error code is returned + */ +int cmdq_pkt_logic_command(struct cmdq_pkt *pkt, u16 result_reg_idx, + struct cmdq_operand *left_operand, + enum cmdq_logic_op s_op, + struct cmdq_operand *right_operand); + /** * cmdq_pkt_assign() - Append logic assign command to the CMDQ packet, ask GCE *to execute an instruction that set a constant value into -- 2.18.0
[PATCH RESEND,v6 0/8] Add CMDQ secure driver for SVP
From: Jason-jh Lin For the Secure Video Path (SVP) feature, inculding the memory stored secure video content, the registers of display HW pipeline and the HW configure operations are required to execute in the secure world. So using a CMDQ secure driver to make all display HW registers configuration secure DRAM access permision settings execute by GCE secure thread in the secure world. We are landing this feature on mt8188 and mt8195 currently. --- TODO: 1) Squash cmdq_sec_task_exec_work() into cmdq_sec_mbox_send_data() 2) Call into TEE to query cookie instead of using shared memory in cmdq_sec_get_cookie() 3) Register shared memory as command buffer instead of copying normal command buffer to IWC shared memory 4) Use SOFTDEP to make cmdq_sec_probe later than OPTEE loaded and then move cmdq_sec_session_init into cmdq_sec_probe() 5) Remove timeout detection in cmdq_sec_session_send() --- Resend v6: 1. Rebase on [1] Add mediatek,gce-props.yaml for other bindings reference to fix yaml check error - [1] https://patchwork.kernel.org/project/linux-mediatek/list/?series=819298 2. Fix unused varibale build error Changes in v6: 1. Rebase to linux-next 2. Change the way to add gce-events prop into dt-binding and add more commit message 3. Remove unused parameters in secure mailbox driver 4. Move cmdq_sec_XXX APIs from secure mailbox driver to helper to fix the build cycle dependency error 5. Remove finalize loop API and write_s_reg API patch 6. Add cmdq secure helper API patch Changes in v5: 1. Sync the local changes Changes in v4: 1. Rebase on mediatek-drm-next(278640d4d74cd) and fix the conflicts 2. This series is based on 20240307013458.23550-1-jason-jh@mediatek.com Changes in v3: 1. separate mt8188 driver porting patches to another series 2. separate adding 'mediatek,gce-events' event prop to another series 3. sepatate mailbox helper and controller driver modification to a single patch for adding looping thread 4. add kerneldoc for secure mailbox related definition 5. add moving reuseable definition patch before adding secure mailbox driver patch 6. adjust redundant logic in mtk-cmdq-sec-mailbox Changes in v2: 1. adjust dt-binding SW event define patch before the dt-binding patch using it 2. adjust dt-binding patch for secure cmdq driver 3. remove the redundant patches or merge the patches of modification for the same API --- Jason-JH.Lin (8): dt-bindings: gce: mt8195: Add CMDQ_SYNC_TOKEN_SECURE_THR_EOF event id dt-bindings: mailbox: Add property for CMDQ secure driver soc: mediatek: cmdq: Add cmdq_pkt_logic_command to support math operation mailbox: mtk-cmdq: Support GCE loop packets in interrupt handler mailbox: mediatek: Move reuseable definition to header for secure driver mailbox: mediatek: Add CMDQ secure mailbox driver mailbox: mediatek: Add secure CMDQ driver support for CMDQ driver soc: mediatek: mtk-cmdq: Add secure cmdq_pkt APIs .../mailbox/mediatek,gce-mailbox.yaml | 8 +- drivers/mailbox/Makefile | 2 +- drivers/mailbox/mtk-cmdq-mailbox.c| 113 ++- drivers/mailbox/mtk-cmdq-sec-mailbox.c| 931 ++ drivers/mailbox/mtk-cmdq-sec-tee.c| 195 drivers/soc/mediatek/mtk-cmdq-helper.c| 191 include/dt-bindings/gce/mt8195-gce.h | 6 + include/linux/mailbox/mtk-cmdq-mailbox.h | 35 + .../linux/mailbox/mtk-cmdq-sec-iwc-common.h | 342 +++ include/linux/mailbox/mtk-cmdq-sec-mailbox.h | 106 ++ include/linux/mailbox/mtk-cmdq-sec-tee.h | 105 ++ include/linux/soc/mediatek/mtk-cmdq.h | 113 +++ 12 files changed, 2117 insertions(+), 30 deletions(-) create mode 100644 drivers/mailbox/mtk-cmdq-sec-mailbox.c create mode 100644 drivers/mailbox/mtk-cmdq-sec-tee.c create mode 100644 include/linux/mailbox/mtk-cmdq-sec-iwc-common.h create mode 100644 include/linux/mailbox/mtk-cmdq-sec-mailbox.h create mode 100644 include/linux/mailbox/mtk-cmdq-sec-tee.h -- 2.18.0
[PATCH v6 0/7] Add mediate-drm secure flow for SVP
From: Jason-jh Lin Memory Definitions: secure memory - Memory allocated in the TEE (Trusted Execution Environment) which is inaccessible in the REE (Rich Execution Environment, i.e. linux kernel/userspace). secure handle - Integer value which acts as reference to 'secure memory'. Used in communication between TEE and REE to reference 'secure memory'. secure buffer - 'secure memory' that is used to store decrypted, compressed video or for other general purposes in the TEE. secure surface - 'secure memory' that is used to store graphic buffers. Memory Usage in SVP: The overall flow of SVP starts with encrypted video coming in from an outside source into the REE. The REE will then allocate a 'secure buffer' and send the corresponding 'secure handle' along with the encrypted, compressed video data to the TEE. The TEE will then decrypt the video and store the result in the 'secure buffer'. The REE will then allocate a 'secure surface'. The REE will pass the 'secure handles' for both the 'secure buffer' and 'secure surface' into the TEE for video decoding. The video decoder HW will then decode the contents of the 'secure buffer' and place the result in the 'secure surface'. The REE will then attach the 'secure surface' to the overlay plane for rendering of the video. Everything relating to ensuring security of the actual contents of the 'secure buffer' and 'secure surface' is out of scope for the REE and is the responsibility of the TEE. DRM driver handles allocation of gem objects that are backed by a 'secure surface' and for displaying a 'secure surface' on the overlay plane. This introduces a new flag for object creation called DRM_MTK_GEM_CREATE_RESTRICTED which indicates it should be a 'secure surface'. All changes here are in MediaTek specific code. --- TODO: 1) Drop MTK_DRM_IOCTL_GEM_CREATE and use DMA_HEAP_IOCTL_ALLOC in userspace 2) DRM driver use secure mailbox channel to handle normal and secure flow 3) Implement setting mmsys routing table in the secure world series --- Based on 3 series: [1] v3 dma-buf: heaps: Add MediaTek secure heap - https://patchwork.kernel.org/project/linux-mediatek/list/?series=809023 [2] v6 media: mediatek: add driver to support secure video decoder - https://patchwork.kernel.org/project/linux-mediatek/list/?series=853689 [3] v6 Add CMDQ secure driver for SVP - https://patchwork.kernel.org/project/linux-mediatek/list/?series=855884 --- Change in v6: 1. Rebase to linux-next then rebased on 3 series [1][2][3] 2. Remove some parameter and security settings in normal world 3. Drop secure port related patches 4. Fix some build error and warning Changes in v5: 1. Sync the local changes Changes in v4: 1. Rebase on mediatek-drm-next(278640d4d74cd) and fix the conflicts 2. This series is based on 20240129063025.29251-1-yunfei.d...@mediatek.com 3. This series is based on 20240322052829.9893-1-shawn.s...@mediatek.com 4. This series is based on 20240403065603.21920-1-shawn.s...@mediatek.com Changes in v3: 1. fix kerneldoc problems 2. fix typo in title and commit message 3. adjust naming for secure variable 4. add the missing part for is_suecure plane implementation 5. use BIT_ULL macro to replace bit shifting 6. move modification of ovl_adaptor part to the correct patch 7. add TODO list in commit message 8. add commit message for using share memory to store execute count Changes in v2: 1. remove the DRIVER_RDNDER flag for mtk_drm_ioctl 2. move cmdq_insert_backup_cookie into client driver 3. move secure gce node define from mt8195-cherry.dtsi to mt8195.dtsi --- CK Hu (1): drm/mediatek: Add interface to allocate MediaTek GEM buffer Jason-JH.Lin (6): drm/mediatek/uapi: Add DRM_MTK_GEM_CREATE_RESTRICTED flag drm/mediatek: Add secure buffer control flow to mtk_drm_gem drm/mediatek: Add secure identify flag and funcution to mtk_drm_plane drm/mediatek: Add mtk_ddp_sec_write() to config secure buffer info drm/mediatek: Add secure flow support to mediatek-drm drm/mediatek: Add cmdq_insert_backup_cookie before secure pkt finalize drivers/gpu/drm/mediatek/mtk_crtc.c | 263 +- drivers/gpu/drm/mediatek/mtk_crtc.h | 1 + drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 14 + drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 5 + drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 9 +- .../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 1 + drivers/gpu/drm/mediatek/mtk_drm_drv.c| 13 +- drivers/gpu/drm/mediatek/mtk_gem.c| 114 drivers/gpu/drm/mediatek/mtk_gem.h| 12 + drivers/gpu/drm/mediatek/mtk_mdp_rdma.c | 8 +- drivers/gpu/drm/mediatek/mtk_mdp_rdma.h | 1 + drivers/gpu/drm/mediatek/mtk_plane.c | 25 ++ drivers/gpu/drm/mediatek/mtk_plane.h | 2 + include/uapi/drm/mediatek_drm.h | 47 14 files changed, 500 insertions(+), 15 deletions(-) create mode 100644 include/uapi/drm/mediatek_drm.h -- 2.18.0
[PATCH v6 3/7] drm/mediatek: Add secure buffer control flow to mtk_drm_gem
Add secure buffer control flow to mtk_drm_gem. When user space takes DRM_MTK_GEM_CREATE_RESTRICTED flag and size to create a mtk_drm_gem object, mtk_drm_gem will find a matched size dma buffer from secure dma-heap and bind it to mtk_drm_gem object. TODO: 1. Drop the mtk_gem_create_from_heap() after we change the ioctl to DMA_HEAP_IOCTL_ALLOC. 2. Checking the private data of dmabuf instead of strncmp the exp_name. Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 +- drivers/gpu/drm/mediatek/mtk_gem.c | 85 +- drivers/gpu/drm/mediatek/mtk_gem.h | 4 ++ 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 11e1555e9aa4..ff40ca5dd2a0 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -573,7 +573,7 @@ static void mtk_drm_kms_deinit(struct drm_device *drm) static const struct drm_ioctl_desc mtk_ioctls[] = { DRM_IOCTL_DEF_DRV(MTK_GEM_CREATE, mtk_gem_create_ioctl, - DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW), + DRM_AUTH | DRM_RENDER_ALLOW), }; DEFINE_DRM_GEM_FOPS(mtk_drm_fops); diff --git a/drivers/gpu/drm/mediatek/mtk_gem.c b/drivers/gpu/drm/mediatek/mtk_gem.c index 91f6cfa3f1b7..118ea7f0a71c 100644 --- a/drivers/gpu/drm/mediatek/mtk_gem.c +++ b/drivers/gpu/drm/mediatek/mtk_gem.c @@ -5,6 +5,8 @@ #include #include +#include +#include #include #include @@ -103,6 +105,81 @@ struct mtk_gem_obj *mtk_gem_create(struct drm_device *dev, return ERR_PTR(ret); } +struct mtk_gem_obj *mtk_gem_create_from_heap(struct drm_device *dev, +const char *heap, size_t size) +{ + struct mtk_drm_private *priv = dev->dev_private; + struct mtk_gem_obj *mtk_gem; + struct drm_gem_object *obj; + struct dma_heap *dma_heap; + struct dma_buf *dma_buf; + struct dma_buf_attachment *attach; + struct sg_table *sgt; + struct iosys_map map = {}; + int ret; + + mtk_gem = mtk_gem_init(dev, size); + if (IS_ERR(mtk_gem)) + return ERR_CAST(mtk_gem); + + obj = &mtk_gem->base; + + dma_heap = dma_heap_find(heap); + if (!dma_heap) { + DRM_ERROR("heap find fail\n"); + goto err_gem_free; + } + dma_buf = dma_heap_buffer_alloc(dma_heap, size, + O_RDWR | O_CLOEXEC, DMA_HEAP_VALID_HEAP_FLAGS); + if (IS_ERR(dma_buf)) { + DRM_ERROR("buffer alloc fail\n"); + dma_heap_put(dma_heap); + goto err_gem_free; + } + dma_heap_put(dma_heap); + + attach = dma_buf_attach(dma_buf, priv->dma_dev); + if (IS_ERR(attach)) { + DRM_ERROR("attach fail, return\n"); + dma_buf_put(dma_buf); + goto err_gem_free; + } + + sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); + if (IS_ERR(sgt)) { + DRM_ERROR("map failed, detach and return\n"); + dma_buf_detach(dma_buf, attach); + dma_buf_put(dma_buf); + goto err_gem_free; + } + obj->import_attach = attach; + mtk_gem->dma_addr = sg_dma_address(sgt->sgl); + mtk_gem->sg = sgt; + mtk_gem->size = dma_buf->size; + + if (!strcmp(heap, "restricted_mtk_cm") || !strcmp(heap, "restricted_mtk_cma")) { + /* secure buffer can not be mapped */ + mtk_gem->secure = true; + } else { + ret = dma_buf_vmap(dma_buf, &map); + mtk_gem->kvaddr = map.vaddr; + if (ret) { + DRM_ERROR("map failed, ret=%d\n", ret); + dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); + dma_buf_detach(dma_buf, attach); + dma_buf_put(dma_buf); + mtk_gem->kvaddr = NULL; + } + } + + return mtk_gem; + +err_gem_free: + drm_gem_object_release(obj); + kfree(mtk_gem); + return ERR_PTR(-ENOMEM); +} + void mtk_gem_free_object(struct drm_gem_object *obj) { struct mtk_gem_obj *mtk_gem = to_mtk_gem_obj(obj); @@ -230,7 +307,9 @@ struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev, if (IS_ERR(mtk_gem)) return ERR_CAST(mtk_gem); + mtk_gem->secure = (!strncmp(attach->dmabuf->exp_name, "restricted", 10)); mtk_gem->dma_addr = sg_dma_address(sg->sgl); + mtk_gem->size = attach->dmabuf->size; mtk_gem->sg = sg; return &mtk_gem->base; @@ -296,7 +375,11 @@ int mtk_gem_create_ioctl(struct drm_device *dev, void *data, struct drm_mtk_gem_create *args = data; int ret; - mtk_gem = mtk_gem_create
[PATCH v6 7/7] drm/mediatek: Add cmdq_insert_backup_cookie before secure pkt finalize
Add cmdq_insert_backup_cookie to append some commands before EOC: 1. Get GCE HW thread execute count from the GCE HW register. 2. Add 1 to the execute count and then store into a shared memory. 3. Set a software event siganl as secure irq to GCE HW. Since the value of execute count + 1 is stored in a shared memory, CMDQ driver in the normal world can use it to handle task done in irq handler and CMDQ driver in the secure world will use it to schedule the task slot for each secure thread. Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- drivers/gpu/drm/mediatek/mtk_crtc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c index 59f6263ae806..0df9bf695f65 100644 --- a/drivers/gpu/drm/mediatek/mtk_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_crtc.c @@ -178,6 +178,7 @@ void mtk_crtc_disable_secure_state(struct drm_crtc *crtc) cmdq_sec_pkt_set_data(&mtk_crtc->sec_cmdq_handle, sec_scn); + cmdq_sec_insert_backup_cookie(&mtk_crtc->sec_cmdq_handle); cmdq_pkt_finalize(&mtk_crtc->sec_cmdq_handle); dma_sync_single_for_device(mtk_crtc->sec_cmdq_client.chan->mbox->dev, mtk_crtc->sec_cmdq_handle.pa_base, @@ -795,6 +796,8 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank) cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event); cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, false); mtk_crtc_ddp_config(crtc, cmdq_handle); + if (cmdq_handle->sec_data) + cmdq_sec_insert_backup_cookie(cmdq_handle); cmdq_pkt_finalize(cmdq_handle); dma_sync_single_for_device(cmdq_client.chan->mbox->dev, cmdq_handle->pa_base, -- 2.18.0
[PATCH v6 2/7] drm/mediatek/uapi: Add DRM_MTK_GEM_CREATE_RESTRICTED flag
Add DRM_MTK_GEM_CREATE_RESTRICTED flag for the user space to tell the kernel space this dma buffer is restricted. The user space can store this flag into the private data of the dma buffer after allocating. A restricted buffer is used to store the secure video content to support secure video path feature. Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- include/uapi/drm/mediatek_drm.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/uapi/drm/mediatek_drm.h b/include/uapi/drm/mediatek_drm.h index 821f7a732365..dee581718d70 100644 --- a/include/uapi/drm/mediatek_drm.h +++ b/include/uapi/drm/mediatek_drm.h @@ -39,6 +39,7 @@ struct drm_mtk_gem_create { }; #define DRM_MTK_GEM_CREATE 0x00 +#define DRM_MTK_GEM_CREATE_RESTRICTED 0x01 #define DRM_IOCTL_MTK_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \ DRM_MTK_GEM_CREATE, struct drm_mtk_gem_create) -- 2.18.0
[PATCH v6 5/7] drm/mediatek: Add mtk_ddp_sec_write() to config secure buffer info
Add mtk_ddp_sec_write() to configure secure buffer information to cmdq secure packet data and send to the secure world. OVL and OVL_ADAPTOR need to use mtk_ddp_sec_write() instead of original mtk_ddp_write() because the address in plane is secure handle not the real buffer address. The secure buffer information will be used to translate the secure handle to the curresponding secure buffer address and then the secure handle in instruction generated by OVL or OVL_ADPATOR will be replaced to the real address in secure world. Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 14 ++ drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 5 + drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 9 +++-- drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 1 + drivers/gpu/drm/mediatek/mtk_mdp_rdma.c | 8 ++-- drivers/gpu/drm/mediatek/mtk_mdp_rdma.h | 1 + 6 files changed, 34 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c index 17b036411292..dc2b36a8bdd6 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c @@ -111,6 +111,20 @@ void mtk_ddp_write_mask(struct cmdq_pkt *cmdq_pkt, unsigned int value, #endif } +void mtk_ddp_sec_write(struct cmdq_pkt *cmdq_pkt, + enum cmdq_iwc_addr_metadata_type type, + unsigned int base, unsigned int base_offset, + struct cmdq_client_reg *cmdq_reg, unsigned int offset) +{ +#if IS_REACHABLE(CONFIG_MTK_CMDQ) + if (!cmdq_pkt) + return; + + cmdq_sec_pkt_write(cmdq_pkt, cmdq_reg->subsys, cmdq_reg->offset + offset, + type, base, base_offset); +#endif +} + static int mtk_ddp_clk_enable(struct device *dev) { struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev); diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h index 26236691ce4c..792fd1b004ee 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h @@ -7,6 +7,7 @@ #define MTK_DDP_COMP_H #include +#include #include #include #include @@ -339,4 +340,8 @@ void mtk_ddp_write_relaxed(struct cmdq_pkt *cmdq_pkt, unsigned int value, void mtk_ddp_write_mask(struct cmdq_pkt *cmdq_pkt, unsigned int value, struct cmdq_client_reg *cmdq_reg, void __iomem *regs, unsigned int offset, unsigned int mask); +void mtk_ddp_sec_write(struct cmdq_pkt *cmdq_pkt, + enum cmdq_iwc_addr_metadata_type type, + unsigned int base, unsigned int base_offset, + struct cmdq_client_reg *cmdq_reg, unsigned int offset); #endif /* MTK_DDP_COMP_H */ diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index b552a02d7eae..5f518c9c63dc 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -449,8 +449,13 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, DISP_REG_OVL_SRC_SIZE(idx)); mtk_ddp_write_relaxed(cmdq_pkt, offset, &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_OFFSET(idx)); - mtk_ddp_write_relaxed(cmdq_pkt, addr, &ovl->cmdq_reg, ovl->regs, - DISP_REG_OVL_ADDR(ovl, idx)); + + if (pending->is_secure) + mtk_ddp_sec_write(cmdq_pkt, CMDQ_IWC_H_2_MVA, pending->addr, 0, + &ovl->cmdq_reg, DISP_REG_OVL_ADDR(ovl, idx)); + else + mtk_ddp_write_relaxed(cmdq_pkt, addr, &ovl->cmdq_reg, ovl->regs, + DISP_REG_OVL_ADDR(ovl, idx)); if (is_afbc) { mtk_ddp_write_relaxed(cmdq_pkt, hdr_addr, &ovl->cmdq_reg, ovl->regs, diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c index 02dd7dcdfedb..5db8711f21c2 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c @@ -188,6 +188,7 @@ void mtk_ovl_adaptor_layer_config(struct device *dev, unsigned int idx, rdma_config.pitch = pending->pitch; rdma_config.fmt = pending->format; rdma_config.color_encoding = pending->color_encoding; + rdma_config.is_secure = state->pending.is_secure; mtk_mdp_rdma_config(rdma_l, &rdma_config, cmdq_pkt); if (use_dual_pipe) { diff --git a/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c b/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c index 925cbb7471ec..961189e16aab 100644 --- a/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c +++ b/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c @@ -199,8 +199,12 @@ void mtk_mdp_rdma_config(struct device *dev, struct mtk_mdp_rdma_cfg *cfg, mtk_ddp_write_m
[PATCH v6 4/7] drm/mediatek: Add secure identify flag and funcution to mtk_drm_plane
Add is_sec flag to identify current mtk_drm_plane is secure. Add mtk_plane_is_sec_fb() to check current drm_framebuffer is secure. Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- drivers/gpu/drm/mediatek/mtk_plane.c | 18 ++ drivers/gpu/drm/mediatek/mtk_plane.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_plane.c b/drivers/gpu/drm/mediatek/mtk_plane.c index 4625deb21d40..478206f21fd0 100644 --- a/drivers/gpu/drm/mediatek/mtk_plane.c +++ b/drivers/gpu/drm/mediatek/mtk_plane.c @@ -210,6 +210,7 @@ static void mtk_plane_update_new_state(struct drm_plane_state *new_state, mtk_plane_state->pending.height = drm_rect_height(&new_state->dst); mtk_plane_state->pending.rotation = new_state->rotation; mtk_plane_state->pending.color_encoding = new_state->color_encoding; + mtk_plane_state->pending.is_secure = mtk_plane_fb_is_secure(fb); } static void mtk_plane_atomic_async_update(struct drm_plane *plane, @@ -348,3 +349,20 @@ int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane, return 0; } + +bool mtk_plane_fb_is_secure(struct drm_framebuffer *fb) +{ + struct drm_gem_object *gem = NULL; + struct mtk_gem_obj *mtk_gem = NULL; + + if (!fb) + return false; + + gem = fb->obj[0]; + if (!gem) + return false; + + mtk_gem = to_mtk_gem_obj(gem); + + return mtk_gem->secure; +} diff --git a/drivers/gpu/drm/mediatek/mtk_plane.h b/drivers/gpu/drm/mediatek/mtk_plane.h index 231bb7aac947..a7779a91f0a2 100644 --- a/drivers/gpu/drm/mediatek/mtk_plane.h +++ b/drivers/gpu/drm/mediatek/mtk_plane.h @@ -33,6 +33,7 @@ struct mtk_plane_pending_state { boolasync_dirty; boolasync_config; enum drm_color_encoding color_encoding; + boolis_secure; }; struct mtk_plane_state { @@ -46,6 +47,7 @@ to_mtk_plane_state(struct drm_plane_state *state) return container_of(state, struct mtk_plane_state, base); } +bool mtk_plane_fb_is_secure(struct drm_framebuffer *fb); int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane, unsigned long possible_crtcs, enum drm_plane_type type, unsigned int supported_rotations, const u32 *formats, -- 2.18.0
[PATCH v6 6/7] drm/mediatek: Add secure flow support to mediatek-drm
To add secure flow support for mediatek-drm, each crtc have to create a secure cmdq mailbox channel. Then cmdq packets with display HW configuration will be sent to secure cmdq mailbox channel and configured in the secure world. Each crtc have to use secure cmdq interface to configure some secure settings for display HW before sending cmdq packets to secure cmdq mailbox channel. If any of plane fbs get from current drm_atomic_state is secure, then crtc will switch to the secure flow to configure display HW. If all plane fbs are not secure in current drm_atomic_state, then crtc will switch to the normal flow. TODO: 1. Try to use secure mailbox channel to handle normal and secure flow. Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- drivers/gpu/drm/mediatek/mtk_crtc.c | 260 +-- drivers/gpu/drm/mediatek/mtk_crtc.h | 1 + drivers/gpu/drm/mediatek/mtk_plane.c | 7 + 3 files changed, 258 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c index 6f34f573e127..59f6263ae806 100644 --- a/drivers/gpu/drm/mediatek/mtk_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_crtc.c @@ -56,6 +56,11 @@ struct mtk_crtc { u32 cmdq_event; u32 cmdq_vblank_cnt; wait_queue_head_t cb_blocking_queue; + + struct cmdq_client sec_cmdq_client; + struct cmdq_pkt sec_cmdq_handle; + boolsec_cmdq_working; + wait_queue_head_t sec_cb_blocking_queue; #endif struct device *mmsys_dev; @@ -69,6 +74,7 @@ struct mtk_crtc { /* lock for display hardware access */ struct mutexhw_lock; boolconfig_updating; + boolsec_on; }; struct mtk_crtc_state { @@ -113,6 +119,144 @@ static void mtk_drm_finish_page_flip(struct mtk_crtc *mtk_crtc) } } +void mtk_crtc_disable_secure_state(struct drm_crtc *crtc) +{ +#if IS_REACHABLE(CONFIG_MTK_CMDQ) + enum cmdq_sec_scenario sec_scn = CMDQ_SEC_SCNR_MAX; + int i; + struct mtk_ddp_comp *ddp_first_comp; + struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc); + + mutex_lock(&mtk_crtc->hw_lock); + + if (!mtk_crtc->sec_cmdq_client.chan) { + pr_err("crtc-%d secure mbox channel is NULL\n", drm_crtc_index(crtc)); + goto err; + } + + if (!mtk_crtc->sec_on) { + pr_debug("crtc-%d is already disabled!\n", drm_crtc_index(crtc)); + goto err; + } + + mbox_flush(mtk_crtc->sec_cmdq_client.chan, 0); + mtk_crtc->sec_cmdq_handle.cmd_buf_size = 0; + + if (mtk_crtc->sec_cmdq_handle.sec_data) { + struct cmdq_sec_data *sec_data; + + sec_data = mtk_crtc->sec_cmdq_handle.sec_data; + sec_data->addr_metadata_cnt = 0; + sec_data->addr_metadatas = (uintptr_t)NULL; + } + + /* +* Secure path only support DL mode, so we just wait +* the first path frame done here +*/ + cmdq_pkt_wfe(&mtk_crtc->sec_cmdq_handle, mtk_crtc->cmdq_event, false); + + ddp_first_comp = mtk_crtc->ddp_comp[0]; + for (i = 0; i < mtk_crtc->layer_nr; i++) { + struct drm_plane *plane = &mtk_crtc->planes[i]; + + /* make sure secure layer off before switching secure state */ + if (!mtk_plane_fb_is_secure(plane->state->fb)) { + struct mtk_plane_state *plane_state = to_mtk_plane_state(plane->state); + + plane_state->pending.enable = false; + mtk_ddp_comp_layer_config(ddp_first_comp, i, plane_state, + &mtk_crtc->sec_cmdq_handle); + } + } + + /* Disable secure path */ + if (drm_crtc_index(crtc) == 0) + sec_scn = CMDQ_SEC_SCNR_PRIMARY_DISP_DISABLE; + else if (drm_crtc_index(crtc) == 1) + sec_scn = CMDQ_SEC_SCNR_SUB_DISP_DISABLE; + + cmdq_sec_pkt_set_data(&mtk_crtc->sec_cmdq_handle, sec_scn); + + cmdq_pkt_finalize(&mtk_crtc->sec_cmdq_handle); + dma_sync_single_for_device(mtk_crtc->sec_cmdq_client.chan->mbox->dev, + mtk_crtc->sec_cmdq_handle.pa_base, + mtk_crtc->sec_cmdq_handle.cmd_buf_size, + DMA_TO_DEVICE); + + mtk_crtc->sec_cmdq_working = true; + mbox_send_message(mtk_crtc->sec_cmdq_client.chan, &mtk_crtc->sec_cmdq_handle); + mbox_client_txdone(mtk_crtc->sec_cmdq_client.chan, 0); + + // Wait for sec state to be disabled by cmdq + wait_event_timeout(mtk_crtc->sec_cb_blocking_queue, + !mtk_crtc->sec_cmdq_working, +
[PATCH v6 1/7] drm/mediatek: Add interface to allocate MediaTek GEM buffer
From: CK Hu Add an interface to allocate MediaTek GEM buffers, allow the IOCTLs to be used by render nodes. This patch also sets the RENDER driver feature. TODO: Drop this path after we change all the usages of this ioctl to DMA_HEAP_IOCTL_ALLOC in the user sapce. Signed-off-by: CK Hu Signed-off-by: Hsiao Chien Sung --- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 13 +++- drivers/gpu/drm/mediatek/mtk_gem.c | 31 + drivers/gpu/drm/mediatek/mtk_gem.h | 8 + include/uapi/drm/mediatek_drm.h| 46 ++ 4 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 include/uapi/drm/mediatek_drm.h diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index b5f605751b0a..11e1555e9aa4 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "mtk_crtc.h" #include "mtk_ddp_comp.h" @@ -570,6 +571,11 @@ static void mtk_drm_kms_deinit(struct drm_device *drm) component_unbind_all(drm->dev, drm); } +static const struct drm_ioctl_desc mtk_ioctls[] = { + DRM_IOCTL_DEF_DRV(MTK_GEM_CREATE, mtk_gem_create_ioctl, + DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW), +}; + DEFINE_DRM_GEM_FOPS(mtk_drm_fops); /* @@ -585,12 +591,17 @@ static struct drm_gem_object *mtk_gem_prime_import(struct drm_device *dev, } static const struct drm_driver mtk_drm_driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC | + DRIVER_RENDER, .dumb_create = mtk_gem_dumb_create, .gem_prime_import = mtk_gem_prime_import, .gem_prime_import_sg_table = mtk_gem_prime_import_sg_table, + + .ioctls = mtk_ioctls, + .num_ioctls = ARRAY_SIZE(mtk_ioctls), + .fops = &mtk_drm_fops, .name = DRIVER_NAME, diff --git a/drivers/gpu/drm/mediatek/mtk_gem.c b/drivers/gpu/drm/mediatek/mtk_gem.c index a172456d1d7b..91f6cfa3f1b7 100644 --- a/drivers/gpu/drm/mediatek/mtk_gem.c +++ b/drivers/gpu/drm/mediatek/mtk_gem.c @@ -5,9 +5,11 @@ #include #include +#include #include #include +#include #include #include #include @@ -286,3 +288,32 @@ void mtk_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map) mtk_gem->kvaddr = NULL; kfree(mtk_gem->pages); } + +int mtk_gem_create_ioctl(struct drm_device *dev, void *data, +struct drm_file *file_priv) +{ + struct mtk_gem_obj *mtk_gem; + struct drm_mtk_gem_create *args = data; + int ret; + + mtk_gem = mtk_gem_create(dev, args->size, false); + if (IS_ERR(mtk_gem)) + return PTR_ERR(mtk_gem); + + /* +* allocate a id of idr table where the obj is registered +* and handle has the id what user can see. +*/ + ret = drm_gem_handle_create(file_priv, &mtk_gem->base, &args->handle); + if (ret) + goto err_handle_create; + + /* drop reference from allocate - handle holds it now. */ + drm_gem_object_put(&mtk_gem->base); + + return 0; + +err_handle_create: + mtk_gem_free_object(&mtk_gem->base); + return ret; +} diff --git a/drivers/gpu/drm/mediatek/mtk_gem.h b/drivers/gpu/drm/mediatek/mtk_gem.h index 66e5f154f698..b71a7e7b405a 100644 --- a/drivers/gpu/drm/mediatek/mtk_gem.h +++ b/drivers/gpu/drm/mediatek/mtk_gem.h @@ -45,4 +45,12 @@ struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev, int mtk_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map); void mtk_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map); +/* + * request gem object creation and buffer allocation as the size + * that it is calculated with framebuffer information such as width, + * height and bpp. + */ +int mtk_gem_create_ioctl(struct drm_device *dev, void *data, +struct drm_file *file_priv); + #endif diff --git a/include/uapi/drm/mediatek_drm.h b/include/uapi/drm/mediatek_drm.h new file mode 100644 index ..821f7a732365 --- /dev/null +++ b/include/uapi/drm/mediatek_drm.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * Copyright (c) 2015 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _UAPI_MEDIATEK_DRM_H +#define _UAPI_MEDIATEK_DRM_H + +#include + +#ifdef __KERNEL__ +#include +#else +#inc
[PATCH v6 7/8] mailbox: mediatek: Add secure CMDQ driver support for CMDQ driver
CMDQ driver will probe a secure CMDQ driver when has_sec flag in platform data is true and its device node in dts has defined a event id of CMDQ_SYNC_TOKEN_SEC_EOF. Secure CMDQ driver support on mt8188 and mt8195 currently. So add a has_secure flag to their driver data to probe it. Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- drivers/mailbox/mtk-cmdq-mailbox.c | 76 ++ 1 file changed, 76 insertions(+) diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c index 025e53549a45..5c606684b07b 100644 --- a/drivers/mailbox/mtk-cmdq-mailbox.c +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #define CMDQ_MBOX_AUTOSUSPEND_DELAY_MS 100 @@ -55,11 +56,22 @@ #define CMDQ_JUMP_BY_OFFSET0x1000 #define CMDQ_JUMP_BY_PA0x1001 +#define CMDQ_THR_IDX(thread, cmdq) (((thread)->base - (cmdq)->base - CMDQ_THR_BASE) \ +/ CMDQ_THR_SIZE) + +#define CMDQ_IS_SECURE_THREAD(idx, cmdq) ((cmdq)->pdata->has_secure && \ + (idx) >= (cmdq)->pdata->secure_thread_min && \ + (idx) < (cmdq)->pdata->secure_thread_min + \ + (cmdq)->pdata->secure_thread_nr) + struct gce_plat { u32 thread_nr; u8 shift; bool control_by_sw; bool sw_ddr_en; + bool has_secure; + u32 secure_thread_nr; + u32 secure_thread_min; u32 gce_num; }; @@ -368,6 +380,7 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev); struct cmdq_task *task; unsigned long curr_pa, end_pa; + u32 idx = CMDQ_THR_IDX(thread, cmdq); int ret; /* Client should not flush new tasks if suspended. */ @@ -377,6 +390,13 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) if (ret < 0) return ret; + if (CMDQ_IS_SECURE_THREAD(idx, cmdq)) { + ret = cmdq_sec_mbox.ops->send_data(chan, data); + pm_runtime_mark_last_busy(cmdq->mbox.dev); + pm_runtime_put_autosuspend(cmdq->mbox.dev); + return ret; + } + task = kzalloc(sizeof(*task), GFP_ATOMIC); if (!task) { pm_runtime_put_autosuspend(cmdq->mbox.dev); @@ -436,6 +456,13 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) static int cmdq_mbox_startup(struct mbox_chan *chan) { + struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev); + struct cmdq_thread *thread = (struct cmdq_thread *)chan->con_priv; + u32 idx = CMDQ_THR_IDX(thread, cmdq); + + if (CMDQ_IS_SECURE_THREAD(idx, cmdq)) + cmdq_sec_mbox.ops->startup(chan); + return 0; } @@ -445,9 +472,17 @@ static void cmdq_mbox_shutdown(struct mbox_chan *chan) struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev); struct cmdq_task *task, *tmp; unsigned long flags; + u32 idx = CMDQ_THR_IDX(thread, cmdq); WARN_ON(pm_runtime_get_sync(cmdq->mbox.dev) < 0); + if (CMDQ_IS_SECURE_THREAD(idx, cmdq)) { + cmdq_sec_mbox.ops->shutdown(chan); + pm_runtime_mark_last_busy(cmdq->mbox.dev); + pm_runtime_put_autosuspend(cmdq->mbox.dev); + return; + } + spin_lock_irqsave(&thread->chan->lock, flags); if (list_empty(&thread->task_busy_list)) goto done; @@ -488,12 +523,20 @@ static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout) struct cmdq_task *task, *tmp; unsigned long flags; u32 enable; + u32 idx = CMDQ_THR_IDX(thread, cmdq); int ret; ret = pm_runtime_get_sync(cmdq->mbox.dev); if (ret < 0) return ret; + if (CMDQ_IS_SECURE_THREAD(idx, cmdq)) { + cmdq_sec_mbox.ops->flush(chan, timeout); + pm_runtime_mark_last_busy(cmdq->mbox.dev); + pm_runtime_put_autosuspend(cmdq->mbox.dev); + return 0; + } + spin_lock_irqsave(&thread->chan->lock, flags); if (list_empty(&thread->task_busy_list)) goto out; @@ -569,6 +612,7 @@ static int cmdq_probe(struct platform_device *pdev) int alias_id = 0; static const char * const clk_name = "gce"; static const char * const clk_names[] = { "gce0", "gce1" }; + u32 hwid = 0; cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL); if (!cmdq) @@ -594,6 +638,8 @@ static int cmdq_probe(struct platform_device *pdev) dev, cmdq->base, cmdq->irq); if (cmdq->pdata->gce_num > 1) { + hwid = of_alias_get_id(dev->of_node, clk_name); + for_each_child_of_node(phan
[PATCH v6 1/8] dt-bindings: gce: mt8195: Add CMDQ_SYNC_TOKEN_SECURE_THR_EOF event id
There are 2 kind of GCE event signal: - The SW token means: a GCE event signal triggered by SW drivers. e.g. SW driver append a GCE command to set a GCE event after a specific GCE command. Or SW driver use CPU to write a event id to GCE register to trigger the GCE event corresponding to that event id. - The HW event means: a GCE event signal triggered by HW engines. e.g. When HW OVL fetches all the data in frame buffer, HW OVL will send a frame done irq and also send a frame done GCE event via HW bus directly. CMDQ_SYNC_TOKEN_SECURE_THR_EOF is a SW token event that is set in the end of each cmdq secure pkt. It is used as a secure irq to notify CMDQ driver in the normal world that GCE secure thread has completed a secure cmd buffer in thee secure world. Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- include/dt-bindings/gce/mt8195-gce.h | 6 ++ 1 file changed, 6 insertions(+) diff --git a/include/dt-bindings/gce/mt8195-gce.h b/include/dt-bindings/gce/mt8195-gce.h index dcfb302b8a5b..b6b3db82c381 100644 --- a/include/dt-bindings/gce/mt8195-gce.h +++ b/include/dt-bindings/gce/mt8195-gce.h @@ -800,6 +800,12 @@ #define CMDQ_EVENT_WPE_VPP1_WPE_GCE_FRAME_DONE 969 #define CMDQ_EVENT_WPE_VPP1_WPE_DONE_SYNC_OUT 970 +/* + * Notify normal CMDQ there are some secure task done, + * this token sync with secure world. + */ +#define CMDQ_SYNC_TOKEN_SECURE_THR_EOF 980 + #define CMDQ_EVENT_DP_TX_VBLANK_FALLING994 #define CMDQ_EVENT_DP_TX_VSC_FINISH995 -- 2.18.0
[PATCH v6 5/8] mailbox: mediatek: Move reuseable definition to header for secure driver
To support CMDQ secure driver, move some reuseable definition to header. - define: e.g. CMDQ_GCE_NUM_MAX, CMDQ_THR_BASE, CMDQ_THR_SIZE. - struct: e.g. cmdq_thread, cmdq, cmdq_task. - include: e.g. . Add "#include " for the function that takes "struct mbox_chan * chan" as a parameter. That may occur a build error if secure driver header includes the mtk-cmdq-mailbox.h. - function: e.g. cmdq_get_shift_pa(struct mbox_chan *chan). Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- drivers/mailbox/mtk-cmdq-mailbox.c | 30 - include/linux/mailbox/mtk-cmdq-mailbox.h | 33 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c index 618023011d31..025e53549a45 100644 --- a/drivers/mailbox/mtk-cmdq-mailbox.c +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -3,7 +3,6 @@ // Copyright (c) 2018 MediaTek Inc. #include -#include #include #include #include @@ -22,13 +21,10 @@ #define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT) #define CMDQ_NUM_CMD(t)(t->cmd_buf_size / CMDQ_INST_SIZE) -#define CMDQ_GCE_NUM_MAX (2) #define CMDQ_CURR_IRQ_STATUS 0x10 #define CMDQ_SYNC_TOKEN_UPDATE 0x68 #define CMDQ_THR_SLOT_CYCLES 0x30 -#define CMDQ_THR_BASE 0x100 -#define CMDQ_THR_SIZE 0x80 #define CMDQ_THR_WARM_RESET0x00 #define CMDQ_THR_ENABLE_TASK 0x04 #define CMDQ_THR_SUSPEND_TASK 0x08 @@ -59,32 +55,6 @@ #define CMDQ_JUMP_BY_OFFSET0x1000 #define CMDQ_JUMP_BY_PA0x1001 -struct cmdq_thread { - struct mbox_chan*chan; - void __iomem*base; - struct list_headtask_busy_list; - u32 priority; -}; - -struct cmdq_task { - struct cmdq *cmdq; - struct list_headlist_entry; - dma_addr_t pa_base; - struct cmdq_thread *thread; - struct cmdq_pkt *pkt; /* the packet sent from mailbox client */ -}; - -struct cmdq { - struct mbox_controller mbox; - void __iomem*base; - int irq; - u32 irq_mask; - const struct gce_plat *pdata; - struct cmdq_thread *thread; - struct clk_bulk_dataclocks[CMDQ_GCE_NUM_MAX]; - boolsuspended; -}; - struct gce_plat { u32 thread_nr; u8 shift; diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h index f78a08e7c6ed..43eae45a08c9 100644 --- a/include/linux/mailbox/mtk-cmdq-mailbox.h +++ b/include/linux/mailbox/mtk-cmdq-mailbox.h @@ -7,10 +7,17 @@ #ifndef __MTK_CMDQ_MAILBOX_H__ #define __MTK_CMDQ_MAILBOX_H__ +#include +#include #include #include #include +#define CMDQ_GCE_NUM_MAX 2 + +#define CMDQ_THR_BASE 0x100 +#define CMDQ_THR_SIZE 0x80 + #define CMDQ_INST_SIZE 8 /* instruction is 64-bit */ #define CMDQ_SUBSYS_SHIFT 16 #define CMDQ_OP_CODE_SHIFT 24 @@ -79,6 +86,32 @@ struct cmdq_pkt { boolloop; }; +struct cmdq_thread { + struct mbox_chan*chan; + void __iomem*base; + struct list_headtask_busy_list; + u32 priority; +}; + +struct cmdq { + struct mbox_controller mbox; + void __iomem*base; + int irq; + u32 irq_mask; + const struct gce_plat *pdata; + struct cmdq_thread *thread; + struct clk_bulk_dataclocks[CMDQ_GCE_NUM_MAX]; + boolsuspended; +}; + +struct cmdq_task { + struct cmdq *cmdq; + struct list_headlist_entry; + dma_addr_t pa_base; + struct cmdq_thread *thread; + struct cmdq_pkt *pkt; /* the packet sent from mailbox client */ +}; + u8 cmdq_get_shift_pa(struct mbox_chan *chan); #endif /* __MTK_CMDQ_MAILBOX_H__ */ -- 2.18.0
[PATCH v6 3/8] soc: mediatek: cmdq: Add cmdq_pkt_logic_command to support math operation
Add cmdq_pkt_logic_command to support math operation. cmdq_pkt_logic_command can append logic command to the CMDQ packet, ask GCE to execute a arithmetic calculate instruction, such as add, subtract, multiply, AND, OR and NOT, etc. Note that all arithmetic instructions are unsigned calculations. If there are any overflows, GCE will sent the invalid IRQ to notify CMDQ driver. Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- drivers/soc/mediatek/mtk-cmdq-helper.c | 36 ++ include/linux/soc/mediatek/mtk-cmdq.h | 42 ++ 2 files changed, 78 insertions(+) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index 046522664dc1..42fae05f61a8 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -15,10 +15,19 @@ /* dedicate the last GPR_R15 to assign the register address to be poll */ #define CMDQ_POLL_ADDR_GPR (15) #define CMDQ_EOC_IRQ_ENBIT(0) +#define CMDQ_IMMEDIATE_VALUE 0 #define CMDQ_REG_TYPE 1 #define CMDQ_JUMP_RELATIVE 0 #define CMDQ_JUMP_ABSOLUTE 1 +#define CMDQ_OPERAND_GET_IDX_VALUE(operand) \ + ({ \ + struct cmdq_operand *op = operand; \ + op->reg ? op->idx : op->value; \ + }) +#define CMDQ_OPERAND_TYPE(operand) \ + ((operand)->reg ? CMDQ_REG_TYPE : CMDQ_IMMEDIATE_VALUE) + struct cmdq_instruction { union { u32 value; @@ -461,6 +470,33 @@ int cmdq_pkt_poll_addr(struct cmdq_pkt *pkt, dma_addr_t addr, u32 value, u32 mas } EXPORT_SYMBOL(cmdq_pkt_poll_addr); +int cmdq_pkt_logic_command(struct cmdq_pkt *pkt, u16 result_reg_idx, + struct cmdq_operand *left_operand, + enum cmdq_logic_op s_op, + struct cmdq_operand *right_operand) +{ + struct cmdq_instruction inst = { {0} }; + u32 left_idx_value; + u32 right_idx_value; + + if (!left_operand || !right_operand || s_op >= CMDQ_LOGIC_MAX) + return -EINVAL; + + left_idx_value = CMDQ_OPERAND_GET_IDX_VALUE(left_operand); + right_idx_value = CMDQ_OPERAND_GET_IDX_VALUE(right_operand); + inst.op = CMDQ_CODE_LOGIC; + inst.dst_t = CMDQ_REG_TYPE; + inst.src_t = CMDQ_OPERAND_TYPE(left_operand); + inst.arg_c_t = CMDQ_OPERAND_TYPE(right_operand); + inst.sop = s_op; + inst.reg_dst = result_reg_idx; + inst.src_reg = left_idx_value; + inst.arg_c = right_idx_value; + + return cmdq_pkt_append_command(pkt, inst); +} +EXPORT_SYMBOL(cmdq_pkt_logic_command); + int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value) { struct cmdq_instruction inst = {}; diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index d4a8e34505e6..5bee6f7fc400 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -25,6 +25,31 @@ struct cmdq_pkt; +enum cmdq_logic_op { + CMDQ_LOGIC_ASSIGN = 0, + CMDQ_LOGIC_ADD = 1, + CMDQ_LOGIC_SUBTRACT = 2, + CMDQ_LOGIC_MULTIPLY = 3, + CMDQ_LOGIC_XOR = 8, + CMDQ_LOGIC_NOT = 9, + CMDQ_LOGIC_OR = 10, + CMDQ_LOGIC_AND = 11, + CMDQ_LOGIC_LEFT_SHIFT = 12, + CMDQ_LOGIC_RIGHT_SHIFT = 13, + CMDQ_LOGIC_MAX, +}; + +struct cmdq_operand { + /* register type */ + bool reg; + union { + /* index */ + u16 idx; + /* value */ + u16 value; + }; +}; + struct cmdq_client_reg { u8 subsys; u16 offset; @@ -272,6 +297,23 @@ int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys, int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value, u32 mask); +/** + * cmdq_pkt_logic_command() - Append logic command to the CMDQ packet, ask GCE to + * execute an instruction that store the result of logic operation + * with left and right operand into result_reg_idx. + * @pkt: the CMDQ packet + * @result_reg_idx:SPR index that store operation result of left_operand and right_operand + * @left_operand: left operand + * @s_op: the logic operator enum + * @right_operand: right operand + * + * Return: 0 for success; else the error code is returned + */ +int cmdq_pkt_logic_command(struct cmdq_pkt *pkt, u16 result_reg_idx, + struct cmdq_operand *left_operand, + enum cmdq_logic_op s_op, + struct cmdq_operand *right_operand); + /** * cmdq_pkt_assign() - Append logic assign command to the CMDQ packet, ask GCE *to execute an instruction that set a constant value into -- 2.18.0
[PATCH v6 4/8] mailbox: mtk-cmdq: Support GCE loop packets in interrupt handler
1. Add a loop flag for CMDQ packet struct. CMDQ helper will use a loop flag to mark CMDQ packet as lopping command and make current command buffer jumps to the beginning when GCE executes to the end of command buffer. 2. Add a looping task handle flow in irq handler. GCE irq occurs when GCE executes to the end of command(EOC) instruction. If the CMDQ packet is a loopping command, GCE irq handler can not delete the CMDQ task and disable the GCE thread. Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- drivers/mailbox/mtk-cmdq-mailbox.c | 11 +++ include/linux/mailbox/mtk-cmdq-mailbox.h | 1 + 2 files changed, 12 insertions(+) diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c index 4aa394e91109..618023011d31 100644 --- a/drivers/mailbox/mtk-cmdq-mailbox.c +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -267,6 +267,17 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq, curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) << cmdq->pdata->shift; + task = list_first_entry_or_null(&thread->task_busy_list, + struct cmdq_task, list_entry); + if (task && task->pkt->loop) { + struct cmdq_cb_data data; + + data.sta = err; + data.pkt = task->pkt; + mbox_chan_received_data(task->thread->chan, &data); + return; + } + list_for_each_entry_safe(task, tmp, &thread->task_busy_list, list_entry) { task_end_pa = task->pa_base + task->pkt->cmd_buf_size; diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h index a8f0070c7aa9..f78a08e7c6ed 100644 --- a/include/linux/mailbox/mtk-cmdq-mailbox.h +++ b/include/linux/mailbox/mtk-cmdq-mailbox.h @@ -76,6 +76,7 @@ struct cmdq_pkt { size_t cmd_buf_size; /* command occupied size */ size_t buf_size; /* real buffer size */ void*cl; + boolloop; }; u8 cmdq_get_shift_pa(struct mbox_chan *chan); -- 2.18.0
[PATCH v6 0/8] Add CMDQ secure driver for SVP
From: Jason-jh Lin For the Secure Video Path (SVP) feature, inculding the memory stored secure video content, the registers of display HW pipeline and the HW configure operations are required to execute in the secure world. So using a CMDQ secure driver to make all display HW registers configuration secure DRAM access permision settings execute by GCE secure thread in the secure world. We are landing this feature on mt8188 and mt8195 currently. --- TODO: 1) Squash cmdq_sec_task_exec_work() into cmdq_sec_mbox_send_data() 2) Call into TEE to query cookie instead of using shared memory in cmdq_sec_get_cookie() 3) Register shared memory as command buffer instead of copying normal command buffer to IWC shared memory 4) Use SOFTDEP to make cmdq_sec_probe later than OPTEE loaded and then move cmdq_sec_session_init into cmdq_sec_probe() 5) Remove timeout detection in cmdq_sec_session_send() --- Changes in v6: 1. Rebase to linux-next 2. Change the way to add gce-events prop into dt-binding and add more commit message 3. Remove unused parameters in secure mailbox driver 4. Move cmdq_sec_XXX APIs from secure mailbox driver to helper to fix the build cycle dependency error 5. Remove finalize loop API and write_s_reg API patch 6. Add cmdq secure helper API patch Changes in v5: 1. Sync the local changes Changes in v4: 1. Rebase on mediatek-drm-next(278640d4d74cd) and fix the conflicts 2. This series is based on 20240307013458.23550-1-jason-jh@mediatek.com Changes in v3: 1. separate mt8188 driver porting patches to another series 2. separate adding 'mediatek,gce-events' event prop to another series 3. sepatate mailbox helper and controller driver modification to a single patch for adding looping thread 4. add kerneldoc for secure mailbox related definition 5. add moving reuseable definition patch before adding secure mailbox driver patch 6. adjust redundant logic in mtk-cmdq-sec-mailbox Changes in v2: 1. adjust dt-binding SW event define patch before the dt-binding patch using it 2. adjust dt-binding patch for secure cmdq driver 3. remove the redundant patches or merge the patches of modification for the same API --- Jason-JH.Lin (8): dt-bindings: gce: mt8195: Add CMDQ_SYNC_TOKEN_SECURE_THR_EOF event id dt-bindings: mailbox: Add property for CMDQ secure driver soc: mediatek: cmdq: Add cmdq_pkt_logic_command to support math operation mailbox: mtk-cmdq: Support GCE loop packets in interrupt handler mailbox: mediatek: Move reuseable definition to header for secure driver mailbox: mediatek: Add CMDQ secure mailbox driver mailbox: mediatek: Add secure CMDQ driver support for CMDQ driver soc: mediatek: mtk-cmdq: Add secure cmdq_pkt APIs .../mailbox/mediatek,gce-mailbox.yaml | 8 +- drivers/mailbox/Makefile | 2 +- drivers/mailbox/mtk-cmdq-mailbox.c| 113 ++- drivers/mailbox/mtk-cmdq-sec-mailbox.c| 932 ++ drivers/mailbox/mtk-cmdq-sec-tee.c| 195 drivers/soc/mediatek/mtk-cmdq-helper.c| 191 include/dt-bindings/gce/mt8195-gce.h | 6 + include/linux/mailbox/mtk-cmdq-mailbox.h | 35 + .../linux/mailbox/mtk-cmdq-sec-iwc-common.h | 342 +++ include/linux/mailbox/mtk-cmdq-sec-mailbox.h | 106 ++ include/linux/mailbox/mtk-cmdq-sec-tee.h | 105 ++ include/linux/soc/mediatek/mtk-cmdq.h | 113 +++ 12 files changed, 2118 insertions(+), 30 deletions(-) create mode 100644 drivers/mailbox/mtk-cmdq-sec-mailbox.c create mode 100644 drivers/mailbox/mtk-cmdq-sec-tee.c create mode 100644 include/linux/mailbox/mtk-cmdq-sec-iwc-common.h create mode 100644 include/linux/mailbox/mtk-cmdq-sec-mailbox.h create mode 100644 include/linux/mailbox/mtk-cmdq-sec-tee.h -- 2.18.0
[PATCH v6 6/8] mailbox: mediatek: Add CMDQ secure mailbox driver
To support secure video path feature, GCE have to read/write registgers in the secure world. GCE will enable the secure access permission to the HW who wants to access the secure content buffer. Add CMDQ secure mailbox driver to make CMDQ client user is able to sending their HW settings to the secure world. So that GCE can execute all instructions to configure HW in the secure world. TODO: 1. Squash cmdq_sec_task_exec_work() into cmdq_sec_mbox_send_data(). 2. Call into TEE to query cookie instead of using shared memory in cmdq_sec_get_cookie(). 3. Register shared memory as command buffer instead of copying normal command buffer to IWC shared memory. 4. Use SOFTDEP to make cmdq_sec_probe later than OPTEE loaded and then move cmdq_sec_session_init into cmdq_sec_probe(). 5. Remove timeout detection in cmdq_sec_session_send(). Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- drivers/mailbox/Makefile | 2 +- drivers/mailbox/mtk-cmdq-sec-mailbox.c| 932 ++ drivers/mailbox/mtk-cmdq-sec-tee.c| 195 include/linux/mailbox/mtk-cmdq-mailbox.h | 1 + .../linux/mailbox/mtk-cmdq-sec-iwc-common.h | 342 +++ include/linux/mailbox/mtk-cmdq-sec-mailbox.h | 106 ++ include/linux/mailbox/mtk-cmdq-sec-tee.h | 105 ++ 7 files changed, 1682 insertions(+), 1 deletion(-) create mode 100644 drivers/mailbox/mtk-cmdq-sec-mailbox.c create mode 100644 drivers/mailbox/mtk-cmdq-sec-tee.c create mode 100644 include/linux/mailbox/mtk-cmdq-sec-iwc-common.h create mode 100644 include/linux/mailbox/mtk-cmdq-sec-mailbox.h create mode 100644 include/linux/mailbox/mtk-cmdq-sec-tee.h diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 5cf2f54debaf..f4c304b50328 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -53,7 +53,7 @@ obj-$(CONFIG_STM32_IPCC) += stm32-ipcc.o obj-$(CONFIG_MTK_ADSP_MBOX)+= mtk-adsp-mailbox.o -obj-$(CONFIG_MTK_CMDQ_MBOX)+= mtk-cmdq-mailbox.o +obj-$(CONFIG_MTK_CMDQ_MBOX)+= mtk-cmdq-mailbox.o mtk-cmdq-sec-mailbox.o mtk-cmdq-sec-tee.o obj-$(CONFIG_ZYNQMP_IPI_MBOX) += zynqmp-ipi-mailbox.o diff --git a/drivers/mailbox/mtk-cmdq-sec-mailbox.c b/drivers/mailbox/mtk-cmdq-sec-mailbox.c new file mode 100644 index ..763d65034cc6 --- /dev/null +++ b/drivers/mailbox/mtk-cmdq-sec-mailbox.c @@ -0,0 +1,932 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define CMDQ_THR_EXEC_CNT_PA (0x28) + +#define CMDQ_TIMEOUT_DEFAULT (1000) + +#define CMDQ_WFE_CMD(event)(0x200080008001ULL | ((u64)(event) << 32)) +#define CMDQ_EOC_CMD (0x4001ULL) +#define CMDQ_JUMP_CMD(addr, shift) (0x1001ULL | ((addr) >> (shift))) + +struct cmdq_sec_task { + struct cmdq_tasktask; + + /* secure CMDQ */ + boolreset_exec; + u32 wait_cookie; + s32 scenario; + u64 trigger; + u64 exec_time; + struct work_struct exec_work; +}; + +struct cmdq_sec_thread { + struct cmdq_thread thread; + + /* secure CMDQ */ + struct device *dev; + u32 idx; + struct timer_list timeout; + u32 timeout_ms; + struct work_struct timeout_work; + u32 wait_cookie; + u32 next_cookie; + u32 task_cnt; + struct workqueue_struct *task_exec_wq; +}; + +/** + * struct cmdq_sec_context - CMDQ secure context structure. + * @tgid: tgid of process context. + * @state: state of inter-world communicatiom. + * @iwc_msg: buffer for inter-world communicatiom message. + * @tee_ctx: context structure for tee vendor. + * + * Note it is not global data, each process has its own cmdq_sec_context. + */ +struct cmdq_sec_context { + u32 tgid; + enum cmdq_iwc_state_enumstate; + void*iwc_msg; + struct cmdq_sec_tee_context tee_ctx; +}; + +/** + * struct cmdq_sec_shared_mem - shared memory between normal and secure world + * @va: virtual address of share memory. + * @pa: physical address of share memory. + * @size: size of share memory. + * + */ +struct cmdq_sec_shared_mem { + void*va; + dma_addr_t pa; + u32 size; +}; + +struct cmdq_sec { + struct device dev; + const struct gce_sec_plat *pdata; + void
[PATCH v6 8/8] soc: mediatek: mtk-cmdq: Add secure cmdq_pkt APIs
Open secure cmdq_pkt APIs to support executing commands in secure world. 1. Add cmdq_sec_pkt_alloc_sec_data(), cmdq_sec_pkt_free_sec_data() and cmdq_sec_pkt_set_data() to prepare the sec_data in cmdq_pkt that will be referenced in the secure world. 2. Add cmdq_sec_insert_backup_cookie() and cmdq_sec_pkt_write() to generate commands that need to be executed in the secure world. In cmdq_sec_pkt_write(), we need to prepare the metadata to store buffer offset of the secure buffer handle because secure world can only translate the start address of secure buffer by secure handle. Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- drivers/soc/mediatek/mtk-cmdq-helper.c | 155 + include/linux/soc/mediatek/mtk-cmdq.h | 71 +++ 2 files changed, 226 insertions(+) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index 42fae05f61a8..de6557f3ca2f 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -562,4 +562,159 @@ int cmdq_pkt_finalize(struct cmdq_pkt *pkt) } EXPORT_SYMBOL(cmdq_pkt_finalize); +int cmdq_sec_insert_backup_cookie(struct cmdq_pkt *pkt) +{ + struct cmdq_client *cl = (struct cmdq_client *)pkt->cl; + struct cmdq_operand left, right; + dma_addr_t addr; + + addr = cmdq_sec_get_exec_cnt_addr(cl->chan); + cmdq_pkt_assign(pkt, CMDQ_THR_SPR_IDX1, CMDQ_ADDR_HIGH(addr)); + cmdq_pkt_read_s(pkt, CMDQ_THR_SPR_IDX1, CMDQ_ADDR_LOW(addr), CMDQ_THR_SPR_IDX1); + + left.reg = true; + left.idx = CMDQ_THR_SPR_IDX1; + right.reg = false; + right.value = 1; + cmdq_pkt_logic_command(pkt, CMDQ_THR_SPR_IDX1, &left, CMDQ_LOGIC_ADD, &right); + + addr = cmdq_sec_get_cookie_addr(cl->chan); + cmdq_pkt_assign(pkt, CMDQ_THR_SPR_IDX2, CMDQ_ADDR_HIGH(addr)); + cmdq_pkt_write_s(pkt, CMDQ_THR_SPR_IDX2, CMDQ_ADDR_LOW(addr), CMDQ_THR_SPR_IDX1); + cmdq_pkt_set_event(pkt, cmdq_sec_get_eof_event_id(cl->chan)); + + return 0; +} +EXPORT_SYMBOL_GPL(cmdq_sec_insert_backup_cookie); + +static int cmdq_sec_realloc_addr_list(struct cmdq_pkt *pkt, const u32 count) +{ + struct cmdq_sec_data *sec_data = (struct cmdq_sec_data *)pkt->sec_data; + void *prev = (void *)(unsigned long)sec_data->addr_metadatas, *curr; + + if (count <= sec_data->addr_metadata_max_cnt) + return 0; + + curr = kcalloc(count, sizeof(*sec_data), GFP_KERNEL); + if (!curr) + return -ENOMEM; + + if (count && sec_data->addr_metadatas) + memcpy(curr, prev, sizeof(*sec_data) * sec_data->addr_metadata_max_cnt); + + kfree(prev); + + sec_data->addr_metadatas = (uintptr_t)curr; + sec_data->addr_metadata_max_cnt = count; + return 0; +} + +void cmdq_sec_pkt_free_sec_data(struct cmdq_pkt *pkt) +{ + kfree(pkt->sec_data); +} +EXPORT_SYMBOL_GPL(cmdq_sec_pkt_free_sec_data); + +int cmdq_sec_pkt_alloc_sec_data(struct cmdq_pkt *pkt) +{ + struct cmdq_sec_data *sec_data; + + if (pkt->sec_data) + return 0; + + sec_data = kzalloc(sizeof(*sec_data), GFP_KERNEL); + if (!sec_data) + return -ENOMEM; + + pkt->sec_data = (void *)sec_data; + + return 0; +} +EXPORT_SYMBOL_GPL(cmdq_sec_pkt_alloc_sec_data); + +static int cmdq_sec_append_metadata(struct cmdq_pkt *pkt, + const enum cmdq_iwc_addr_metadata_type type, + const u32 base, const u32 offset) +{ + struct cmdq_sec_data *sec_data; + struct iwc_cmdq_addr_metadata_t *meta; + int idx, max, ret; + + pr_debug("[%s %d] pkt:%p type:%u base:%#x offset:%#x", +__func__, __LINE__, pkt, type, base, offset); + + ret = cmdq_sec_pkt_alloc_sec_data(pkt); + if (ret < 0) + return ret; + + sec_data = (struct cmdq_sec_data *)pkt->sec_data; + idx = sec_data->addr_metadata_cnt; + if (idx >= CMDQ_IWC_MAX_ADDR_LIST_LENGTH) { + pr_err("idx:%u reach over:%u", idx, CMDQ_IWC_MAX_ADDR_LIST_LENGTH); + return -EFAULT; + } + + if (!sec_data->addr_metadata_max_cnt) + max = ADDR_METADATA_MAX_COUNT_ORIGIN; + else if (idx >= sec_data->addr_metadata_max_cnt) + max = sec_data->addr_metadata_max_cnt * 2; + else + max = sec_data->addr_metadata_max_cnt; + + ret = cmdq_sec_realloc_addr_list(pkt, max); + if (ret) + return ret; + + if (!sec_data->addr_metadatas) { + pr_info("addr_metadatas is missing"); + + meta = kzalloc(sizeof(*meta), GFP_KERNEL); + if (!meta) + return -ENOMEM; + + sec_data->addr_metadatas = (uintptr_t)(void *)meta; + } + meta = (struct iwc_cmdq_addr_metadata_t *)(uintptr_t)sec_data->addr_metadata
[PATCH v6 2/8] dt-bindings: mailbox: Add property for CMDQ secure driver
1. Add mboxes property to define a GCE loopping thread as a secure IRQ handler. The CMDQ secure driver requests a mbox channel and sends a looping command to the GCE thread. The looping command will wait for a secure packet done event signal from secure world and then jump back to the first instuction. Each time it waits for an event, it notifies the CMDQ driver to perform the same action as the IRQ handler. 2. Add gce-events property from gce-props.yaml to define a secure packet done signal in secure world. There are 1024 events IDs for GCE to use to execute instructions in the specific event happened. These events could be signaled by HW or SW and their value would be different in different SoC because of HW event IDs distribution range from 0 to 1023. If we set a static event ID: 855 for mt8188, it might be conflict the event ID original set in mt8195. So we define an event ID that will be set when GCE runs to the end of secure cmdq packet in the secure world. This can reduce the latency of software communication between normal world and secure world. In addition, we can also remove the complex logic after the secure packet done in the secure world. Signed-off-by: Jason-JH.Lin Signed-off-by: Hsiao Chien Sung --- .../devicetree/bindings/mailbox/mediatek,gce-mailbox.yaml | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mailbox/mediatek,gce-mailbox.yaml b/Documentation/devicetree/bindings/mailbox/mediatek,gce-mailbox.yaml index cef9d7601398..6e5e848d61d9 100644 --- a/Documentation/devicetree/bindings/mailbox/mediatek,gce-mailbox.yaml +++ b/Documentation/devicetree/bindings/mailbox/mediatek,gce-mailbox.yaml @@ -49,6 +49,10 @@ properties: items: - const: gce + mboxes: +items: + - description: GCE looping thread as a secure IRQ handler + required: - compatible - "#mbox-cells" @@ -57,6 +61,8 @@ required: - clocks allOf: + - $ref: /schemas/mailbox/mediatek,gce-props.yaml# + - if: not: properties: @@ -67,7 +73,7 @@ allOf: required: - clock-names -additionalProperties: false +unevaluatedProperties: false examples: - | -- 2.18.0
[PATCH v2] mailbox: mtk-cmdq: Fix sleeping function called from invalid context
When we run kernel with lockdebug option, we will get the BUG below: [ 106.692124] BUG: sleeping function called from invalid context at drivers/base/power/runtime.c:1164 [ 106.692190] in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 3616, name: kworker/u17:3 [ 106.692226] preempt_count: 1, expected: 0 [ 106.692254] RCU nest depth: 0, expected: 0 [ 106.692282] INFO: lockdep is turned off. [ 106.692306] irq event stamp: 0 [ 106.692331] hardirqs last enabled at (0): [<>] 0x0 [ 106.692376] hardirqs last disabled at (0): [] copy_process+0xc90/0x2ac0 [ 106.692429] softirqs last enabled at (0): [] copy_process+0xcb4/0x2ac0 [ 106.692473] softirqs last disabled at (0): [<>] 0x0 [ 106.692513] CPU: 1 PID: 3616 Comm: kworker/u17:3 Not tainted 6.1.87-lockdep-14133-g26e933aca785 #1 6839942e1cf34914b0a366137843dd2366f52aa9 [ 106.692556] Hardware name: Google Ciri sku0/unprovisioned board (DT) [ 106.692586] Workqueue: imgsys_runner imgsys_runner_func [ 106.692638] Call trace: [ 106.692662] dump_backtrace+0x100/0x120 [ 106.692702] show_stack+0x20/0x2c [ 106.692737] dump_stack_lvl+0x84/0xb4 [ 106.692775] dump_stack+0x18/0x48 [ 106.692809] __might_resched+0x354/0x4c0 [ 106.692847] __might_sleep+0x98/0xe4 [ 106.692883] __pm_runtime_resume+0x70/0x124 [ 106.692921] cmdq_mbox_send_data+0xe4/0xb1c [ 106.692964] msg_submit+0x194/0x2dc [ 106.693003] mbox_send_message+0x190/0x330 [ 106.693043] imgsys_cmdq_sendtask+0x1618/0x2224 [ 106.693082] imgsys_runner_func+0xac/0x11c [ 106.693118] process_one_work+0x638/0xf84 [ 106.693158] worker_thread+0x808/0xcd0 [ 106.693196] kthread+0x24c/0x324 [ 106.693231] ret_from_fork+0x10/0x20 We found that there is a spin_lock_irqsave protection in msg_submit() of mailbox.c and it is in the atomic context. So when cmdq driver calls pm_runtime_get_sync() in cmdq_mbox_send_data(), it will get this BUG report. 1. Change pm_runtime_get_sync() to pm_runtime_get() to avoid using sleep in atomic context. 2. Move clk_bulk_enable() outside cmdq_runtime_resume() to ensure GCE clocks are enabled before configuring GCE register. 3. Add used_count to avoid cmdq_runtime_suspend() being called before calling cmdq_runtime_resume(). Fixes: 8afe816b0c99 ("mailbox: mtk-cmdq-mailbox: Implement Runtime PM with autosuspend") Signed-off-by: Jason-JH.Lin --- drivers/mailbox/mtk-cmdq-mailbox.c | 24 +++- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c index 033aff11f87c..b50f42e69aab 100644 --- a/drivers/mailbox/mtk-cmdq-mailbox.c +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -82,6 +82,7 @@ struct cmdq { const struct gce_plat *pdata; struct cmdq_thread *thread; struct clk_bulk_dataclocks[CMDQ_GCE_NUM_MAX]; + atomic_tused_count; boolsuspended; }; @@ -317,14 +318,21 @@ static int cmdq_runtime_resume(struct device *dev) { struct cmdq *cmdq = dev_get_drvdata(dev); - return clk_bulk_enable(cmdq->pdata->gce_num, cmdq->clocks); + atomic_inc(&cmdq->used_count); + return 0; } static int cmdq_runtime_suspend(struct device *dev) { struct cmdq *cmdq = dev_get_drvdata(dev); + if (atomic_read(&cmdq->used_count) == 0) { + dev_warn(dev, "%s when used_count is 0!", __func__); + return -EINVAL; + } + clk_bulk_disable(cmdq->pdata->gce_num, cmdq->clocks); + atomic_dec(&cmdq->used_count); return 0; } @@ -392,9 +400,8 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) /* Client should not flush new tasks if suspended. */ WARN_ON(cmdq->suspended); - ret = pm_runtime_get_sync(cmdq->mbox.dev); - if (ret < 0) - return ret; + WARN_ON(pm_runtime_get(cmdq->mbox.dev) < 0); + WARN_ON(clk_bulk_enable(cmdq->pdata->gce_num, cmdq->clocks)); task = kzalloc(sizeof(*task), GFP_ATOMIC); if (!task) { @@ -465,7 +472,8 @@ static void cmdq_mbox_shutdown(struct mbox_chan *chan) struct cmdq_task *task, *tmp; unsigned long flags; - WARN_ON(pm_runtime_get_sync(cmdq->mbox.dev) < 0); + WARN_ON(pm_runtime_get(cmdq->mbox.dev) < 0); + WARN_ON(clk_bulk_enable(cmdq->pdata->gce_num, cmdq->clocks)); spin_lock_irqsave(&thread->chan->lock, flags); if (list_empty(&thread->task_busy_list)) @@ -507,11 +515,9 @@ static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout) struct cmdq_task *task, *tmp; unsigned long flags; u32 enable; - int ret; - ret = pm_runtime_get_sync(cmdq->mbox.dev); - if (ret < 0) - return ret; + WARN_ON(pm_runtime_get(cmdq->mbox.dev) < 0); + WARN_ON(clk_bulk_enable(cmdq->pdata->gce_num, cmdq->clocks)); spin_lock_irqsave(&t
[PATCH v2 1/3] dt-bindings: display: mediatek: gamma: Change MT8195 to single enum group
Since MT8195 gamma has multiple bank for 12 bits LUT and it is different from any other SoC LUT setting. So we add MT8195 compatible to the single enum group to make its driver data settings can be reused by other SoC. Signed-off-by: Jason-JH.Lin Acked-by: Krzysztof Kozlowski --- .../devicetree/bindings/display/mediatek/mediatek,gamma.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml index c6641acd75d6..ef1f575757f6 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml @@ -24,6 +24,7 @@ properties: - enum: - mediatek,mt8173-disp-gamma - mediatek,mt8183-disp-gamma + - mediatek,mt8195-disp-gamma - items: - enum: - mediatek,mt6795-disp-gamma -- 2.18.0
[PATCH v2 3/3] drm/mediatek: Add gamma support for MT8195
Since MT8195 compatible is in the single enum group, we have to add its compatible into mediatek-drm component binding table to ensure that it can be bound as a ddp_comp. Signed-off-by: Jason-JH.Lin Reviewed-by: AngeloGioacchino Del Regno --- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 14a1e0157cc4..93303bff8f34 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -707,6 +707,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = { .data = (void *)MTK_DISP_GAMMA, }, { .compatible = "mediatek,mt8183-disp-gamma", .data = (void *)MTK_DISP_GAMMA, }, + { .compatible = "mediatek,mt8195-disp-gamma", + .data = (void *)MTK_DISP_GAMMA, }, { .compatible = "mediatek,mt8195-disp-merge", .data = (void *)MTK_DISP_MERGE }, { .compatible = "mediatek,mt2701-disp-mutex", -- 2.18.0
[PATCH v2 0/3] Add GAMMA 12-bit LUT support for MT8188
From: Jason-jh Lin Since MT8195 supports GAMMA 12-bit LUT after the landing of [1] series, we can now add support for MT8188. [1] MediaTek DDP GAMMA - 12-bit LUT support - https://patchwork.kernel.org/project/linux-mediatek/list/?series=792516 Change in v2: 1. Keep MT8195 compatible in the group of MT8183. 2. Move MT8195 compatible group to the end of items list. Jason-JH.Lin (3): dt-bindings: display: mediatek: gamma: Change MT8195 to single enum group dt-bindings: display: mediatek: gamma: Add support for MT8188 drm/mediatek: Add gamma support for MT8195 .../devicetree/bindings/display/mediatek/mediatek,gamma.yaml | 5 + drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 ++ 2 files changed, 7 insertions(+) -- 2.18.0
[PATCH v2 2/3] dt-bindings: display: mediatek: gamma: Add support for MT8188
The gamma LUT setting of MT8188 and MT8195 are the same, so we create a one of items for MT8188 to reuse the driver data settings of MT8195. Signed-off-by: Jason-JH.Lin Reviewed-by: AngeloGioacchino Del Regno --- .../devicetree/bindings/display/mediatek/mediatek,gamma.yaml | 4 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml index ef1f575757f6..b8b8e83ebc3f 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml @@ -36,6 +36,10 @@ properties: - mediatek,mt8192-disp-gamma - mediatek,mt8195-disp-gamma - const: mediatek,mt8183-disp-gamma + - items: + - enum: + - mediatek,mt8188-disp-gamma + - const: mediatek,mt8195-disp-gamma reg: maxItems: 1 -- 2.18.0
[PATCH 1/3] dt-bindings: display: mediatek: gamma: Change MT8195 to single enum group
Since MT8195 gamma has multiple bank for 12 bits LUT and it is different from any other SoC LUT setting. So we move MT8195 compatible from the one of items to the single enum group. Signed-off-by: Jason-JH.Lin --- .../devicetree/bindings/display/mediatek/mediatek,gamma.yaml| 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml index c6641acd75d6..3e6cb8f48bcc 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml @@ -24,6 +24,7 @@ properties: - enum: - mediatek,mt8173-disp-gamma - mediatek,mt8183-disp-gamma + - mediatek,mt8195-disp-gamma - items: - enum: - mediatek,mt6795-disp-gamma @@ -33,7 +34,6 @@ properties: - mediatek,mt8186-disp-gamma - mediatek,mt8188-disp-gamma - mediatek,mt8192-disp-gamma - - mediatek,mt8195-disp-gamma - const: mediatek,mt8183-disp-gamma reg: -- 2.18.0
[PATCH 2/3] dt-bindings: display: mediatek: gamma: Add support for MT8188
The gamma LUT setting of MT8188 and MT8195 are the same, so we create a one of items for MT8188 to reuse the driver data settings of MT8195. Signed-off-by: Jason-JH.Lin --- .../devicetree/bindings/display/mediatek/mediatek,gamma.yaml | 4 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml index 3e6cb8f48bcc..90c454eea06f 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml @@ -29,6 +29,10 @@ properties: - enum: - mediatek,mt6795-disp-gamma - const: mediatek,mt8173-disp-gamma + - items: + - enum: + - mediatek,mt8188-disp-gamma + - const: mediatek,mt8195-disp-gamma - items: - enum: - mediatek,mt8186-disp-gamma -- 2.18.0
[PATCH 3/3] drm/mediatek: Add gamma support for MT8195
Since MT8195 compatible is in the single enum group, we have to add its compatible into mediatek-drm component binding table to ensure that it can be bound as a ddp_comp. Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 14a1e0157cc4..93303bff8f34 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -707,6 +707,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = { .data = (void *)MTK_DISP_GAMMA, }, { .compatible = "mediatek,mt8183-disp-gamma", .data = (void *)MTK_DISP_GAMMA, }, + { .compatible = "mediatek,mt8195-disp-gamma", + .data = (void *)MTK_DISP_GAMMA, }, { .compatible = "mediatek,mt8195-disp-merge", .data = (void *)MTK_DISP_MERGE }, { .compatible = "mediatek,mt2701-disp-mutex", -- 2.18.0
[PATCH 0/3] Add GAMMA 12-bit LUT support for MT8188
From: Jason-jh Lin Since MT8195 supports GAMMA 12-bit LUT after the landing of [1] series, we can now add support for MT8188. [1] MediaTek DDP GAMMA - 12-bit LUT support - https://patchwork.kernel.org/project/linux-mediatek/list/?series=792516 Jason-JH.Lin (3): dt-bindings: display: mediatek: gamma: Change MT8195 to single enum group dt-bindings: display: mediatek: gamma: Add support for MT8188 drm/mediatek: Add gamma support for MT8195 .../bindings/display/mediatek/mediatek,gamma.yaml | 6 +- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) -- 2.18.0
[PATCH v4 3/3] dt-bindings: soc: mediatek: Change mediatek, gce-events to refernece
Change mediatek,gce-events property to reference mediatek,gce-props.yaml instead of defining itself. Signed-off-by: Jason-JH.Lin Reviewed-by: Conor Dooley --- .../bindings/soc/mediatek/mediatek,ccorr.yaml| 12 .../bindings/soc/mediatek/mediatek,mutex.yaml| 11 +++ .../bindings/soc/mediatek/mediatek,wdma.yaml | 12 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,ccorr.yaml b/Documentation/devicetree/bindings/soc/mediatek/mediatek,ccorr.yaml index 4380b98b0dfe..305f2cd9f865 100644 --- a/Documentation/devicetree/bindings/soc/mediatek/mediatek,ccorr.yaml +++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,ccorr.yaml @@ -34,13 +34,6 @@ properties: 4 arguments defined in this property. Each GCE subsys id is mapping to a client defined in the header include/dt-bindings/gce/-gce.h. - mediatek,gce-events: -description: - The event id which is mapping to the specific hardware event signal - to gce. The event id is defined in the gce header - include/dt-bindings/gce/-gce.h of each chips. -$ref: /schemas/types.yaml#/definitions/uint32-array - clocks: minItems: 1 @@ -51,7 +44,10 @@ required: - mediatek,gce-events - clocks -additionalProperties: false +allOf: + - $ref: /schemas/mailbox/mediatek,gce-props.yaml# + +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml index ba2014a8725c..61cf16ce8b0b 100644 --- a/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml +++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml @@ -53,13 +53,6 @@ properties: items: - description: MUTEX Clock - mediatek,gce-events: -description: - The event id which is mapping to the specific hardware event signal - to gce. The event id is defined in the gce header - include/dt-bindings/gce/-gce.h of each chips. -$ref: /schemas/types.yaml#/definitions/uint32-array - mediatek,gce-client-reg: $ref: /schemas/types.yaml#/definitions/phandle-array items: @@ -73,6 +66,8 @@ properties: a client defined in the header include/dt-bindings/gce/-gce.h. allOf: + - $ref: /schemas/mailbox/mediatek,gce-props.yaml# + - if: properties: compatible: @@ -97,7 +92,7 @@ required: - interrupts - power-domains -additionalProperties: false +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,wdma.yaml b/Documentation/devicetree/bindings/soc/mediatek/mediatek,wdma.yaml index 69afb329e5f4..d9dd4428c036 100644 --- a/Documentation/devicetree/bindings/soc/mediatek/mediatek,wdma.yaml +++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,wdma.yaml @@ -35,13 +35,6 @@ properties: 4 arguments defined in this property. Each GCE subsys id is mapping to a client defined in the header include/dt-bindings/gce/-gce.h. - mediatek,gce-events: -description: - The event id which is mapping to the specific hardware event signal - to gce. The event id is defined in the gce header - include/dt-bindings/gce/-gce.h of each chips. -$ref: /schemas/types.yaml#/definitions/uint32-array - power-domains: maxItems: 1 @@ -60,7 +53,10 @@ required: - clocks - iommus -additionalProperties: false +allOf: + - $ref: /schemas/mailbox/mediatek,gce-props.yaml# + +unevaluatedProperties: false examples: - | -- 2.18.0
[PATCH v4 2/3] dt-bindings: media: mediatek: mdp: Change mediatek, gce-events to reference
Change mediatek,gce-events property to reference mediatek,gce-props.yaml instead of defining itself. Signed-off-by: Jason-JH.Lin Reviewed-by: Conor Dooley --- .../bindings/media/mediatek,mdp3-rdma.yaml | 11 +++ .../devicetree/bindings/media/mediatek,mdp3-rsz.yaml | 12 .../bindings/media/mediatek,mdp3-wrot.yaml | 12 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/Documentation/devicetree/bindings/media/mediatek,mdp3-rdma.yaml b/Documentation/devicetree/bindings/media/mediatek,mdp3-rdma.yaml index 59db8306485b..4a286d46c8ee 100644 --- a/Documentation/devicetree/bindings/media/mediatek,mdp3-rdma.yaml +++ b/Documentation/devicetree/bindings/media/mediatek,mdp3-rdma.yaml @@ -44,13 +44,6 @@ properties: 4 arguments defined in this property. Each GCE subsys id is mapping to a client defined in the header include/dt-bindings/gce/-gce.h. - mediatek,gce-events: -description: - The event id which is mapping to the specific hardware event signal - to gce. The event id is defined in the gce header - include/dt-bindings/gce/-gce.h of each chips. -$ref: /schemas/types.yaml#/definitions/uint32-array - mediatek,scp: $ref: /schemas/types.yaml#/definitions/phandle description: @@ -96,6 +89,8 @@ required: - '#dma-cells' allOf: + - $ref: /schemas/mailbox/mediatek,gce-props.yaml + - if: properties: compatible: @@ -142,7 +137,7 @@ allOf: clocks: maxItems: 1 -additionalProperties: false +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/media/mediatek,mdp3-rsz.yaml b/Documentation/devicetree/bindings/media/mediatek,mdp3-rsz.yaml index f5676bec4326..4774fdde1a1b 100644 --- a/Documentation/devicetree/bindings/media/mediatek,mdp3-rsz.yaml +++ b/Documentation/devicetree/bindings/media/mediatek,mdp3-rsz.yaml @@ -38,13 +38,6 @@ properties: 4 arguments defined in this property. Each GCE subsys id is mapping to a client defined in the header include/dt-bindings/gce/-gce.h. - mediatek,gce-events: -description: - The event id which is mapping to the specific hardware event signal - to gce. The event id is defined in the gce header - include/dt-bindings/gce/-gce.h of each chips. -$ref: /schemas/types.yaml#/definitions/uint32-array - clocks: minItems: 1 @@ -55,7 +48,10 @@ required: - mediatek,gce-events - clocks -additionalProperties: false +allOf: + - $ref: /schemas/mailbox/mediatek,gce-props.yaml + +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/media/mediatek,mdp3-wrot.yaml b/Documentation/devicetree/bindings/media/mediatek,mdp3-wrot.yaml index 53a679338402..a31f3f5aea96 100644 --- a/Documentation/devicetree/bindings/media/mediatek,mdp3-wrot.yaml +++ b/Documentation/devicetree/bindings/media/mediatek,mdp3-wrot.yaml @@ -38,13 +38,6 @@ properties: 4 arguments defined in this property. Each GCE subsys id is mapping to a client defined in the header include/dt-bindings/gce/-gce.h. - mediatek,gce-events: -description: - The event id which is mapping to the specific hardware event signal - to gce. The event id is defined in the gce header - include/dt-bindings/gce/-gce.h of each chips. -$ref: /schemas/types.yaml#/definitions/uint32-array - power-domains: maxItems: 1 @@ -67,7 +60,10 @@ required: - iommus - '#dma-cells' -additionalProperties: false +allOf: + - $ref: /schemas/mailbox/mediatek,gce-props.yaml + +unevaluatedProperties: false examples: - | -- 2.18.0
[PATCH v4 0/3] Add mediatek, gce-props.yaml for other bindings reference
From: Jason-jh Lin The property "mediatek,gce-events" is used for GCE event ID corresponding to a hardware event signal sent by the hardware or a software driver. If the mailbox providers or consumers want to manipulate the value of the event ID, they need to know the specific event ID. Since mediatek,gce-events property is used for both mailbox producers and consumers, we add a mediatek,gce-props.yaml to place the common GCE properties like mediatek,gce-events. Change in v4: 1. Fix some typo. 2. Change maxItems of gce-events from 1024 to 32. Change in v3: 1. Add more description and fix typo and grammar. 2. Fix $ref as full path. Change in v2: 1. Add mediatek,gce-props.yaml for other binding reference. Jason-JH.Lin (3): dt-bindings: mailbox: Add mediatek,gce-props.yaml dt-bindings: media: mediatek: mdp: Change mediatek,gce-events to reference dt-bindings: soc: mediatek: Change mediatek,gce-events to refernece .../bindings/mailbox/mediatek,gce-props.yaml | 52 +++ .../bindings/media/mediatek,mdp3-rdma.yaml| 11 ++-- .../bindings/media/mediatek,mdp3-rsz.yaml | 12 ++--- .../bindings/media/mediatek,mdp3-wrot.yaml| 12 ++--- .../bindings/soc/mediatek/mediatek,ccorr.yaml | 12 ++--- .../bindings/soc/mediatek/mediatek,mutex.yaml | 11 ++-- .../bindings/soc/mediatek/mediatek,wdma.yaml | 12 ++--- 7 files changed, 74 insertions(+), 48 deletions(-) create mode 100644 Documentation/devicetree/bindings/mailbox/mediatek,gce-props.yaml -- 2.18.0
[PATCH v4 1/3] dt-bindings: mailbox: Add mediatek,gce-props.yaml
Add mediatek,gce-props.yaml for common GCE properties that is used for both mailbox providers and consumers. We place the common property "mediatek,gce-events" in this binding currently. The property "mediatek,gce-events" is used for GCE event ID corresponding to a hardware event signal sent by the hardware or a software driver. If the mailbox providers or consumers want to manipulate the value of the event ID, they need to know the specific event ID. Signed-off-by: Jason-JH.Lin Reviewed-by: Conor Dooley --- .../bindings/mailbox/mediatek,gce-props.yaml | 52 +++ 1 file changed, 52 insertions(+) create mode 100644 Documentation/devicetree/bindings/mailbox/mediatek,gce-props.yaml diff --git a/Documentation/devicetree/bindings/mailbox/mediatek,gce-props.yaml b/Documentation/devicetree/bindings/mailbox/mediatek,gce-props.yaml new file mode 100644 index ..c25eed4606fe --- /dev/null +++ b/Documentation/devicetree/bindings/mailbox/mediatek,gce-props.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mailbox/mediatek,gce-props.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek Global Command Engine Common Properties + +maintainers: + - Houlong Wei + +description: + The Global Command Engine (GCE) is an instruction based, multi-threaded, + single-core command dispatcher for MediaTek hardware. The Command Queue + (CMDQ) mailbox driver is a driver for GCE, implemented using the Linux + mailbox framework. It is used to receive messages from mailbox consumers + and configure GCE to execute the specified instruction set in the message. + We use mediatek,gce-mailbox.yaml to define the properties for CMDQ mailbox + driver. A device driver that uses the CMDQ driver to configure its hardware + registers is a mailbox consumer. The mailbox consumer can request a mailbox + channel corresponding to a GCE hardware thread to send a message, specifying + that the GCE thread to configure its hardware. The mailbox provider can also + reserve a mailbox channel to configure GCE hardware register by the specific + GCE thread. This binding defines the common GCE properties for both mailbox + provider and consumers. + +properties: + mediatek,gce-events: +description: + GCE has an event table in SRAM, consisting of 1024 event IDs (0~1023). + Each event ID has a boolean event value with the default value 0. + The property mediatek,gce-events is used to obtain the event IDs. + Some gce-events are hardware-bound and cannot be changed by software. + For instance, in MT8195, when VDO0_MUTEX is stream done, VDO_MUTEX will + send an event signal to GCE, setting the value of event ID 597 to 1. + Similarly, in MT8188, the value of event ID 574 will be set to 1 when + VOD0_MUTEX is stream done. + On the other hand, some gce-events are not hardware-bound and can be + changed by software. For example, in MT8188, we can set the value of + event ID 855, which is not bound to any hardware, to 1 when the driver + in the secure world completes a task. However, in MT8195, event ID 855 + is already bound to VDEC_LAT1, so we need to select another event ID to + achieve the same purpose. This event ID can be any ID that is not bound + to any hardware and is not yet used in any software driver. + To determine if the event ID is bound to the hardware or used by a + software driver, refer to the GCE header + include/dt-bindings/gce/-gce.h of each chip. +$ref: /schemas/types.yaml#/definitions/uint32-array +minItems: 1 +maxItems: 32 + +additionalProperties: true -- 2.18.0
[PATCH v3 3/3] dt-bindings: soc: mediatek: Change mediatek, gce-events to refernece
Change mediatek,gce-events property to reference mediatek,gce-props.yaml instead of defining itself. Signed-off-by: Jason-JH.Lin --- .../bindings/soc/mediatek/mediatek,ccorr.yaml| 12 .../bindings/soc/mediatek/mediatek,mutex.yaml| 11 +++ .../bindings/soc/mediatek/mediatek,wdma.yaml | 12 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,ccorr.yaml b/Documentation/devicetree/bindings/soc/mediatek/mediatek,ccorr.yaml index 4380b98b0dfe..305f2cd9f865 100644 --- a/Documentation/devicetree/bindings/soc/mediatek/mediatek,ccorr.yaml +++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,ccorr.yaml @@ -34,13 +34,6 @@ properties: 4 arguments defined in this property. Each GCE subsys id is mapping to a client defined in the header include/dt-bindings/gce/-gce.h. - mediatek,gce-events: -description: - The event id which is mapping to the specific hardware event signal - to gce. The event id is defined in the gce header - include/dt-bindings/gce/-gce.h of each chips. -$ref: /schemas/types.yaml#/definitions/uint32-array - clocks: minItems: 1 @@ -51,7 +44,10 @@ required: - mediatek,gce-events - clocks -additionalProperties: false +allOf: + - $ref: /schemas/mailbox/mediatek,gce-props.yaml# + +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml index ba2014a8725c..61cf16ce8b0b 100644 --- a/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml +++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml @@ -53,13 +53,6 @@ properties: items: - description: MUTEX Clock - mediatek,gce-events: -description: - The event id which is mapping to the specific hardware event signal - to gce. The event id is defined in the gce header - include/dt-bindings/gce/-gce.h of each chips. -$ref: /schemas/types.yaml#/definitions/uint32-array - mediatek,gce-client-reg: $ref: /schemas/types.yaml#/definitions/phandle-array items: @@ -73,6 +66,8 @@ properties: a client defined in the header include/dt-bindings/gce/-gce.h. allOf: + - $ref: /schemas/mailbox/mediatek,gce-props.yaml# + - if: properties: compatible: @@ -97,7 +92,7 @@ required: - interrupts - power-domains -additionalProperties: false +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,wdma.yaml b/Documentation/devicetree/bindings/soc/mediatek/mediatek,wdma.yaml index 69afb329e5f4..d9dd4428c036 100644 --- a/Documentation/devicetree/bindings/soc/mediatek/mediatek,wdma.yaml +++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,wdma.yaml @@ -35,13 +35,6 @@ properties: 4 arguments defined in this property. Each GCE subsys id is mapping to a client defined in the header include/dt-bindings/gce/-gce.h. - mediatek,gce-events: -description: - The event id which is mapping to the specific hardware event signal - to gce. The event id is defined in the gce header - include/dt-bindings/gce/-gce.h of each chips. -$ref: /schemas/types.yaml#/definitions/uint32-array - power-domains: maxItems: 1 @@ -60,7 +53,10 @@ required: - clocks - iommus -additionalProperties: false +allOf: + - $ref: /schemas/mailbox/mediatek,gce-props.yaml# + +unevaluatedProperties: false examples: - | -- 2.18.0
[PATCH v3 1/3] dt-bindings: mailbox: Add mediatek,gce-props.yaml
Add mediatek,gce-props.yaml for common GCE properties that is used for both mailbox providers and consumers. We place the common property "mediatek,gce-events" in this binding currently. The property "mediatek,gce-events" is used for GCE event ID corresponding to a hardware event signal sent by the hardware or a sofware driver. If the mailbox providers or consumers want to manipulate the value of the event ID, they need to know the specific event ID. Signed-off-by: Jason-JH.Lin --- .../bindings/mailbox/mediatek,gce-props.yaml | 52 +++ 1 file changed, 52 insertions(+) create mode 100644 Documentation/devicetree/bindings/mailbox/mediatek,gce-props.yaml diff --git a/Documentation/devicetree/bindings/mailbox/mediatek,gce-props.yaml b/Documentation/devicetree/bindings/mailbox/mediatek,gce-props.yaml new file mode 100644 index ..68b519ff089f --- /dev/null +++ b/Documentation/devicetree/bindings/mailbox/mediatek,gce-props.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mailbox/mediatek,gce-props.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek Global Command Engine Common Propertes + +maintainers: + - Houlong Wei + +description: + The Global Command Engine (GCE) is an instruction based, multi-threaded, + single-core command dispatcher for MediaTek hardware. The Command Queue + (CMDQ) mailbox driver is a driver for GCE, implemented using the Linux + mailbox framework. It is used to receive messages from mailbox consumers + and configure GCE to execute the specified instruction set in the message. + We use mediatek,gce-mailbox.yaml to define the properties for CMDQ mailbox + driver. A device driver that uses the CMDQ driver to configure its hardware + registers is a mailbox consumer. The mailbox consumer can request a mailbox + channel corresponding to a GCE hardware thread to send a message, specifying + that the GCE thread to configure its hardware. The mailbox provider can also + reserved a mailbox channel to configure GCE hardware register by the spcific + GCE thread. This binding defines the common GCE properties for both mailbox + provider and consumers. + +properties: + mediatek,gce-events: +description: + GCE has an event table in SRAM, consisting of 1024 event IDs (0~1023). + Each event ID has a boolean event value with the default value 0. + The property mediatek,gce-events is used to obtain the event IDs. + Some gce-events are hardware-bound and cannot be changed by software. + For instance, in MT8195, when VDO0_MUTEX is stream done, VDO_MUTEX will + send an event signal to GCE, setting the value of event ID 597 to 1. + Similarly, in MT8188, the value of event ID 574 will be set to 1 when + VOD0_MUTEX is stream done. + On the other hand, some gce-events are not hardware-bound and can be + changed by software. For example, in MT8188, we can set the value of + event ID 855, which is not bound to any hardware, to 1 when the driver + in the secure world completes a task. However, in MT8195, event ID 855 + is already bound to VDEC_LAT1, so we need to select another event ID to + achieve the same purpose. This event ID can be any ID that is not bound + to any hardware and is not yet used in any software driver. + To determine if the event ID is bound to the hardware or used by a + software driver, refer to the GCE header + include/dt-bindings/gce/-gce.h of each chip. +$ref: /schemas/types.yaml#/definitions/uint32-array +minItems: 1 +maxItems: 1024 + +additionalProperties: true -- 2.18.0
[PATCH v3 2/3] dt-bindings: media: mediatek: mdp: Change mediatek, gce-events to reference
Change mediatek,gce-events property to reference mediatek,gce-props.yaml instead of defining itself. Signed-off-by: Jason-JH.Lin --- .../bindings/media/mediatek,mdp3-rdma.yaml | 11 +++ .../devicetree/bindings/media/mediatek,mdp3-rsz.yaml | 12 .../bindings/media/mediatek,mdp3-wrot.yaml | 12 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/Documentation/devicetree/bindings/media/mediatek,mdp3-rdma.yaml b/Documentation/devicetree/bindings/media/mediatek,mdp3-rdma.yaml index 59db8306485b..4a286d46c8ee 100644 --- a/Documentation/devicetree/bindings/media/mediatek,mdp3-rdma.yaml +++ b/Documentation/devicetree/bindings/media/mediatek,mdp3-rdma.yaml @@ -44,13 +44,6 @@ properties: 4 arguments defined in this property. Each GCE subsys id is mapping to a client defined in the header include/dt-bindings/gce/-gce.h. - mediatek,gce-events: -description: - The event id which is mapping to the specific hardware event signal - to gce. The event id is defined in the gce header - include/dt-bindings/gce/-gce.h of each chips. -$ref: /schemas/types.yaml#/definitions/uint32-array - mediatek,scp: $ref: /schemas/types.yaml#/definitions/phandle description: @@ -96,6 +89,8 @@ required: - '#dma-cells' allOf: + - $ref: /schemas/mailbox/mediatek,gce-props.yaml + - if: properties: compatible: @@ -142,7 +137,7 @@ allOf: clocks: maxItems: 1 -additionalProperties: false +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/media/mediatek,mdp3-rsz.yaml b/Documentation/devicetree/bindings/media/mediatek,mdp3-rsz.yaml index f5676bec4326..4774fdde1a1b 100644 --- a/Documentation/devicetree/bindings/media/mediatek,mdp3-rsz.yaml +++ b/Documentation/devicetree/bindings/media/mediatek,mdp3-rsz.yaml @@ -38,13 +38,6 @@ properties: 4 arguments defined in this property. Each GCE subsys id is mapping to a client defined in the header include/dt-bindings/gce/-gce.h. - mediatek,gce-events: -description: - The event id which is mapping to the specific hardware event signal - to gce. The event id is defined in the gce header - include/dt-bindings/gce/-gce.h of each chips. -$ref: /schemas/types.yaml#/definitions/uint32-array - clocks: minItems: 1 @@ -55,7 +48,10 @@ required: - mediatek,gce-events - clocks -additionalProperties: false +allOf: + - $ref: /schemas/mailbox/mediatek,gce-props.yaml + +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/media/mediatek,mdp3-wrot.yaml b/Documentation/devicetree/bindings/media/mediatek,mdp3-wrot.yaml index 53a679338402..a31f3f5aea96 100644 --- a/Documentation/devicetree/bindings/media/mediatek,mdp3-wrot.yaml +++ b/Documentation/devicetree/bindings/media/mediatek,mdp3-wrot.yaml @@ -38,13 +38,6 @@ properties: 4 arguments defined in this property. Each GCE subsys id is mapping to a client defined in the header include/dt-bindings/gce/-gce.h. - mediatek,gce-events: -description: - The event id which is mapping to the specific hardware event signal - to gce. The event id is defined in the gce header - include/dt-bindings/gce/-gce.h of each chips. -$ref: /schemas/types.yaml#/definitions/uint32-array - power-domains: maxItems: 1 @@ -67,7 +60,10 @@ required: - iommus - '#dma-cells' -additionalProperties: false +allOf: + - $ref: /schemas/mailbox/mediatek,gce-props.yaml + +unevaluatedProperties: false examples: - | -- 2.18.0
[PATCH v3 0/3] Add mediatek, gce-props.yaml for other bindings reference
From: Jason-jh Lin The property "mediatek,gce-events" is used for GCE event ID corresponding to a hardware event signal sent by the hardware or a sofware driver. If the mailbox providers or consumers want to manipulate the value of the event ID, they need to know the specific event ID. Since mediatek,gce-events property is used for both mailbox producers and consumers, we add a mediatek,gce-props.yaml to place the common GCE properties like mediatek,gce-events. Change in v3: 1. Add more description and fix typo and grammar. 2. Fix $ref as full path. Change in v2: 1. Add mediatek,gce-props.yaml for other binding reference. Jason-JH.Lin (3): dt-bindings: mailbox: Add mediatek,gce-props.yaml dt-bindings: media: mediatek: mdp: Change mediatek,gce-events to reference dt-bindings: soc: mediatek: Change mediatek,gce-events to refernece .../bindings/mailbox/mediatek,gce-props.yaml | 52 +++ .../bindings/media/mediatek,mdp3-rdma.yaml| 11 ++-- .../bindings/media/mediatek,mdp3-rsz.yaml | 12 ++--- .../bindings/media/mediatek,mdp3-wrot.yaml| 12 ++--- .../bindings/soc/mediatek/mediatek,ccorr.yaml | 12 ++--- .../bindings/soc/mediatek/mediatek,mutex.yaml | 11 ++-- .../bindings/soc/mediatek/mediatek,wdma.yaml | 12 ++--- 7 files changed, 74 insertions(+), 48 deletions(-) create mode 100644 Documentation/devicetree/bindings/mailbox/mediatek,gce-props.yaml -- 2.18.0
[PATCH v3 00/11] Add mediate-drm secure flow for SVP
From: Jason-jh Lin Memory Definitions: secure memory - Memory allocated in the TEE (Trusted Execution Environment) which is inaccessible in the REE (Rich Execution Environment, i.e. linux kernel/userspace). secure handle - Integer value which acts as reference to 'secure memory'. Used in communication between TEE and REE to reference 'secure memory'. secure buffer - 'secure memory' that is used to store decrypted, compressed video or for other general purposes in the TEE. secure surface - 'secure memory' that is used to store graphic buffers. Memory Usage in SVP: The overall flow of SVP starts with encrypted video coming in from an outside source into the REE. The REE will then allocate a 'secure buffer' and send the corresponding 'secure handle' along with the encrypted, compressed video data to the TEE. The TEE will then decrypt the video and store the result in the 'secure buffer'. The REE will then allocate a 'secure surface'. The REE will pass the 'secure handles' for both the 'secure buffer' and 'secure surface' into the TEE for video decoding. The video decoder HW will then decode the contents of the 'secure buffer' and place the result in the 'secure surface'. The REE will then attach the 'secure surface' to the overlay plane for rendering of the video. Everything relating to ensuring security of the actual contents of the 'secure buffer' and 'secure surface' is out of scope for the REE and is the responsibility of the TEE. DRM driver handles allocation of gem objects that are backed by a 'secure surface' and for displaying a 'secure surface' on the overlay plane. This introduces a new flag for object creation called DRM_MTK_GEM_CREATE_ENCRYPTED which indicates it should be a 'secure surface'. All changes here are in MediaTek specific code. --- TODO: 1) Remove get sec larb port interface in ddp_comp, ovl and ovl_adaptor. 2) Verify instruction for enabling/disabling dapc and larb port in TEE drop the sec_engine flags in normal world and. 3) Move DISP_REG_OVL_SECURE setting to secure world for mtk_disp_ovl.c. 4) Change the parameter register address in mtk_ddp_sec_write() from "u32 addr" to "struct cmdq_client_reg *cmdq_reg". 5) Implement setting mmsys routing table in the secure world series. --- Based on 5 series and 1 patch: [1] v3 dma-buf: heaps: Add MediaTek secure heap - https://patchwork.kernel.org/project/linux-mediatek/list/?series=809023 [2] v3 add driver to support secure video decoder - https://patchwork.kernel.org/project/linux-mediatek/list/?series=807308 [3] v4 soc: mediatek: Add register definitions for GCE - https://patchwork.kernel.org/project/linux-mediatek/patch/20231212121957.19231-2-shawn.s...@mediatek.com/ [4] v2 Add CMDQ driver support for mt8188 - https://patchwork.kernel.org/project/linux-mediatek/list/?series=810302 [5] Add mediatek,gce-events definition to mediatek,gce-mailbox bindings - https://patchwork.kernel.org/project/linux-mediatek/list/?series=810938 [6] v3 Add CMDQ secure driver for SVP - https://patchwork.kernel.org/project/linux-mediatek/list/?series=812379 --- Change in v3: 1. fix kerneldoc problems 2. fix typo in title and commit message 3. adjust naming for secure variable 4. add the missing part for is_suecure plane implementation 5. use BIT_ULL macro to replace bit shifting 6. move modification of ovl_adaptor part to the correct patch 7. add TODO list in commit message 8. add commit message for using share memory to store execute count Change in v2: 1. remove the DRIVER_RDNDER flag for mtk_drm_ioctl 2. move cmdq_insert_backup_cookie into client driver 3. move secure gce node define from mt8195-cherry.dtsi to mt8195.dtsi --- CK Hu (1): drm/mediatek: Add interface to allocate MediaTek GEM buffer. Jason-JH.Lin (10): drm/mediatek/uapi: Add DRM_MTK_GEM_CREATE_ENCRYPTED flag drm/mediatek: Add secure buffer control flow to mtk_drm_gem drm/mediatek: Add secure identify flag and funcution to mtk_drm_plane drm/mediatek: Add mtk_ddp_sec_write to config secure buffer info drm/mediatek: Add get_sec_port interface to mtk_ddp_comp drm/mediatek: Add secure layer config support for ovl drm/mediatek: Add secure layer config support for ovl_adaptor drm/mediatek: Add secure flow support to mediatek-drm drm/mediatek: Add cmdq_insert_backup_cookie before secure pkt finalize arm64: dts: mt8195: Add secure mbox settings for vdosys arch/arm64/boot/dts/mediatek/mt8195.dtsi | 6 +- drivers/gpu/drm/mediatek/mtk_disp_drv.h | 3 + drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 31 +- .../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 15 + drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 274 +- drivers/gpu/drm/mediatek/mtk_drm_crtc.h | 1 + drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 30 ++
[PATCH v3 08/11] drm/mediatek: Add secure layer config support for ovl_adaptor
Add secure layer config support for ovl_adaptor and sub driver mdp_rdma. Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_disp_drv.h | 1 + drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 15 +++ drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 1 + drivers/gpu/drm/mediatek/mtk_mdp_rdma.c | 11 --- drivers/gpu/drm/mediatek/mtk_mdp_rdma.h | 2 ++ 5 files changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h index 77054adcd9cf..ec9746767468 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h @@ -117,6 +117,7 @@ void mtk_ovl_adaptor_clk_disable(struct device *dev); void mtk_ovl_adaptor_config(struct device *dev, unsigned int w, unsigned int h, unsigned int vrefresh, unsigned int bpc, struct cmdq_pkt *cmdq_pkt); +u64 mtk_ovl_adaptor_get_sec_port(struct mtk_ddp_comp *comp, unsigned int idx); void mtk_ovl_adaptor_layer_config(struct device *dev, unsigned int idx, struct mtk_plane_state *state, struct cmdq_pkt *cmdq_pkt); diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c index 6bf6367853fb..f419c2e70ba3 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c @@ -83,6 +83,18 @@ static const struct ovl_adaptor_comp_match comp_matches[OVL_ADAPTOR_ID_MAX] = { [OVL_ADAPTOR_ETHDR0]= { OVL_ADAPTOR_TYPE_ETHDR, 0 }, }; +static const u64 ovl_adaptor_sec_port[] = { + BIT_ULL(CMDQ_SEC_VDO1_DISP_RDMA_L0), + BIT_ULL(CMDQ_SEC_VDO1_DISP_RDMA_L1), + BIT_ULL(CMDQ_SEC_VDO1_DISP_RDMA_L2), + BIT_ULL(CMDQ_SEC_VDO1_DISP_RDMA_L3), +}; + +u64 mtk_ovl_adaptor_get_sec_port(struct mtk_ddp_comp *comp, unsigned int idx) +{ + return ovl_adaptor_sec_port[idx]; +} + void mtk_ovl_adaptor_layer_config(struct device *dev, unsigned int idx, struct mtk_plane_state *state, struct cmdq_pkt *cmdq_pkt) @@ -141,6 +153,9 @@ void mtk_ovl_adaptor_layer_config(struct device *dev, unsigned int idx, rdma_config.pitch = pending->pitch; rdma_config.fmt = pending->format; rdma_config.color_encoding = pending->color_encoding; + rdma_config.source_size = (pending->height - 1) * pending->pitch + + pending->width * fmt_info->cpp[0]; + rdma_config.is_secure = state->pending.is_secure; mtk_mdp_rdma_config(rdma_l, &rdma_config, cmdq_pkt); if (use_dual_pipe) { diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c index 6aed7647dfc0..9b7fe34df9a6 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c @@ -445,6 +445,7 @@ static const struct mtk_ddp_comp_funcs ddp_ovl_adaptor = { .remove = mtk_ovl_adaptor_remove_comp, .get_formats = mtk_ovl_adaptor_get_formats, .get_num_formats = mtk_ovl_adaptor_get_num_formats, + .get_sec_port = mtk_ovl_adaptor_get_sec_port, }; static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = { diff --git a/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c b/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c index c3adaeefd551..a164ba82d022 100644 --- a/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c +++ b/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c @@ -94,6 +94,7 @@ struct mtk_mdp_rdma { void __iomem*regs; struct clk *clk; struct cmdq_client_reg cmdq_reg; + resource_size_t regs_pa; }; static unsigned int rdma_fmt_convert(unsigned int fmt) @@ -198,9 +199,12 @@ void mtk_mdp_rdma_config(struct device *dev, struct mtk_mdp_rdma_cfg *cfg, else mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs, MDP_RDMA_SRC_CON, FLD_OUTPUT_ARGB); - - mtk_ddp_write_mask(cmdq_pkt, cfg->addr0, &priv->cmdq_reg, priv->regs, - MDP_RDMA_SRC_BASE_0, FLD_SRC_BASE_0); + if (cfg->is_secure) + mtk_ddp_sec_write(cmdq_pkt, priv->regs_pa + MDP_RDMA_SRC_BASE_0, + cfg->addr0, CMDQ_IWC_H_2_MVA, 0, cfg->source_size, 0); + else + mtk_ddp_write_mask(cmdq_pkt, cfg->addr0, &priv->cmdq_reg, priv->regs, + MDP_RDMA_SRC_BASE_0, FLD_SRC_BASE_0); mtk_ddp_write_mask(cmdq_pkt, src_pitch_y, &priv->cmdq_reg, priv->regs, MDP_RDMA_MF_BKGD_SIZE_IN_BYTE, FLD_MF_BKGD_WB); @@ -285,6 +289,7 @@ static int mtk_mdp_rdma_probe(struct platform_device *pdev) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + pr
[PATCH v3 09/11] drm/mediatek: Add secure flow support to mediatek-drm
To add secure flow support for mediatek-drm, each crtc have to create a secure cmdq mailbox channel. Then cmdq packets with display HW configuration will be sent to secure cmdq mailbox channel and configured in the secure world. Each crtc have to use secure cmdq interface to configure some secure settings for display HW before sending cmdq packets to secure cmdq mailbox channel. If any of fb get from current drm_atomic_state is secure, then crtc will switch to the secure flow to configure display HW. If all fbs are not secure in current drm_atomic_state, then crtc will switch to the normal flow. TODO: 1. Remove get sec larb port interface in ddp_comp, ovl and ovl_adaptor. 2. Verify instruction for enabling/disabling dapc and larb port in TEE drop the sec_engine flags in normal world. Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 272 ++- drivers/gpu/drm/mediatek/mtk_drm_crtc.h | 1 + drivers/gpu/drm/mediatek/mtk_drm_plane.c | 7 + 3 files changed, 269 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index db43f9dff912..79617c0f016d 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -56,6 +56,11 @@ struct mtk_drm_crtc { u32 cmdq_event; u32 cmdq_vblank_cnt; wait_queue_head_t cb_blocking_queue; + + struct cmdq_client sec_cmdq_client; + struct cmdq_pkt sec_cmdq_handle; + boolsec_cmdq_working; + wait_queue_head_t sec_cb_blocking_queue; #endif struct device *mmsys_dev; @@ -69,6 +74,7 @@ struct mtk_drm_crtc { /* lock for display hardware access */ struct mutexhw_lock; boolconfig_updating; + boolsec_on; }; struct mtk_crtc_state { @@ -111,6 +117,154 @@ static void mtk_drm_finish_page_flip(struct mtk_drm_crtc *mtk_crtc) } } +void mtk_crtc_disable_secure_state(struct drm_crtc *crtc) +{ +#if IS_REACHABLE(CONFIG_MTK_CMDQ) + enum cmdq_sec_scenario sec_scn = CMDQ_SEC_SCNR_MAX; + int i; + struct mtk_ddp_comp *ddp_first_comp; + struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); + u64 sec_engine = 0; /* for hw engine write output secure fb */ + u64 sec_port = 0; /* for larb port read input secure fb */ + + mutex_lock(&mtk_crtc->hw_lock); + + if (!mtk_crtc->sec_cmdq_client.chan) { + pr_err("crtc-%d secure mbox channel is NULL\n", drm_crtc_index(crtc)); + goto err; + } + + if (!mtk_crtc->sec_on) { + pr_debug("crtc-%d is already disabled!\n", drm_crtc_index(crtc)); + goto err; + } + + mbox_flush(mtk_crtc->sec_cmdq_client.chan, 0); + mtk_crtc->sec_cmdq_handle.cmd_buf_size = 0; + + if (mtk_crtc->sec_cmdq_handle.sec_data) { + struct cmdq_sec_data *sec_data; + + sec_data = mtk_crtc->sec_cmdq_handle.sec_data; + sec_data->addr_metadata_cnt = 0; + sec_data->addr_metadatas = (uintptr_t)NULL; + } + + /* +* Secure path only support DL mode, so we just wait +* the first path frame done here +*/ + cmdq_pkt_wfe(&mtk_crtc->sec_cmdq_handle, mtk_crtc->cmdq_event, false); + + ddp_first_comp = mtk_crtc->ddp_comp[0]; + for (i = 0; i < mtk_crtc->layer_nr; i++) { + struct drm_plane *plane = &mtk_crtc->planes[i]; + + sec_port |= mtk_ddp_comp_layer_get_sec_port(ddp_first_comp, i); + + /* make sure secure layer off before switching secure state */ + if (!mtk_plane_fb_is_secure(plane->state->fb)) { + struct mtk_plane_state *plane_state = to_mtk_plane_state(plane->state); + + plane_state->pending.enable = false; + mtk_ddp_comp_layer_config(ddp_first_comp, i, plane_state, + &mtk_crtc->sec_cmdq_handle); + } + } + + /* Disable secure path */ + if (drm_crtc_index(crtc) == 0) + sec_scn = CMDQ_SEC_SCNR_PRIMARY_DISP_DISABLE; + else if (drm_crtc_index(crtc) == 1) + sec_scn = CMDQ_SEC_SCNR_SUB_DISP_DISABLE; + + cmdq_sec_pkt_set_data(&mtk_crtc->sec_cmdq_handle, sec_engine, sec_engine, sec_scn); + + cmdq_pkt_finalize(&mtk_crtc->sec_cmdq_handle); + dma_sync_single_for_device(mtk_crtc->sec_cmdq_client.chan->mbox->dev, + mtk_crtc->sec_cmdq_handle.pa_base, + mtk_crtc->sec_cmdq_handle.cmd_buf_size, + DMA_TO_DEVICE); + + mtk_crtc->sec_cmdq_work
[PATCH v3 04/11] drm/mediatek: Add secure identify flag and funcution to mtk_drm_plane
Add is_sec flag to identify current mtk_drm_plane is secure. Add mtk_plane_is_sec_fb() to check current drm_framebuffer is secure. Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_drm_plane.c | 19 +++ drivers/gpu/drm/mediatek/mtk_drm_plane.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c index ddc9355b06d5..d4d515627ca4 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c @@ -210,6 +210,7 @@ static void mtk_plane_update_new_state(struct drm_plane_state *new_state, mtk_plane_state->pending.height = drm_rect_height(&new_state->dst); mtk_plane_state->pending.rotation = new_state->rotation; mtk_plane_state->pending.color_encoding = new_state->color_encoding; + mtk_plane_state->pending.is_secure = mtk_plane_fb_is_secure(fb); } static void mtk_plane_atomic_async_update(struct drm_plane *plane, @@ -348,3 +349,21 @@ int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane, return 0; } + +bool mtk_plane_fb_is_secure(struct drm_framebuffer *fb) +{ + struct drm_gem_object *gem = NULL; + struct mtk_drm_gem_obj *mtk_gem = NULL; + + if (!fb) + return false; + + gem = fb->obj[0]; + if (!gem) + return false; + + mtk_gem = to_mtk_gem_obj(gem); + + return mtk_gem->secure; +} + diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.h b/drivers/gpu/drm/mediatek/mtk_drm_plane.h index 99aff7da0831..5a330797b5db 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_plane.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.h @@ -33,6 +33,7 @@ struct mtk_plane_pending_state { boolasync_dirty; boolasync_config; enum drm_color_encoding color_encoding; + boolis_secure; }; struct mtk_plane_state { @@ -46,6 +47,7 @@ to_mtk_plane_state(struct drm_plane_state *state) return container_of(state, struct mtk_plane_state, base); } +bool mtk_plane_fb_is_secure(struct drm_framebuffer *fb); int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane, unsigned long possible_crtcs, enum drm_plane_type type, unsigned int supported_rotations, const u32 *formats, -- 2.18.0
[PATCH v3 02/11] drm/mediatek/uapi: Add DRM_MTK_GEM_CREATE_ENCRYPTED flag
Add DRM_MTK_GEM_CREATE_ENCRYPTED flag to allow user to allocate a secure buffer to support secure video path feature. Signed-off-by: Jason-JH.Lin --- include/uapi/drm/mediatek_drm.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/uapi/drm/mediatek_drm.h b/include/uapi/drm/mediatek_drm.h index f4d47577c94e..189d20301205 100644 --- a/include/uapi/drm/mediatek_drm.h +++ b/include/uapi/drm/mediatek_drm.h @@ -48,6 +48,7 @@ struct drm_mtk_gem_map_off { #define DRM_MTK_GEM_CREATE 0x00 #define DRM_MTK_GEM_MAP_OFFSET 0x01 +#define DRM_MTK_GEM_CREATE_ENCRYPTED 0x02 #define DRM_IOCTL_MTK_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \ DRM_MTK_GEM_CREATE, struct drm_mtk_gem_create) -- 2.18.0
[PATCH v3 11/11] arm64: dts: mt8195: Add secure mbox settings for vdosys
Add a secure mailbox channel to support secure video path on vdosys0 and vdosys1. Signed-off-by: Jason-JH.Lin --- arch/arm64/boot/dts/mediatek/mt8195.dtsi | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi index e0ac2e9f5b72..416d575be123 100644 --- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi @@ -2621,7 +2621,8 @@ vdosys0: syscon@1c01a000 { compatible = "mediatek,mt8195-vdosys0", "mediatek,mt8195-mmsys", "syscon"; reg = <0 0x1c01a000 0 0x1000>; - mboxes = <&gce0 0 CMDQ_THR_PRIO_4>; + mboxes = <&gce0 0 CMDQ_THR_PRIO_4>, +<&gce0 8 CMDQ_THR_PRIO_4>; /* secure mbox */ #clock-cells = <1>; }; @@ -2806,7 +2807,8 @@ vdosys1: syscon@1c10 { compatible = "mediatek,mt8195-vdosys1", "syscon"; reg = <0 0x1c10 0 0x1000>; - mboxes = <&gce0 1 CMDQ_THR_PRIO_4>; + mboxes = <&gce0 1 CMDQ_THR_PRIO_4>, +<&gce0 9 CMDQ_THR_PRIO_4>; /* secure mbox */; mediatek,gce-client-reg = <&gce0 SUBSYS_1c10 0x 0x1000>; #clock-cells = <1>; #reset-cells = <1>; -- 2.18.0
[PATCH v3 06/11] drm/mediatek: Add get_sec_port interface to mtk_ddp_comp
Add get_sec_port interface to ddp_comp to get the secure port settings from ovl and ovl_adaptor. Then mediatek-drm will use secure cmdq driver to configure DRAM access permission in secure world by their secure port settings. Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 9 + 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h index b5a05ca3a385..1e6a120a103d 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h @@ -84,6 +84,7 @@ struct mtk_ddp_comp_funcs { void (*add)(struct device *dev, struct mtk_mutex *mutex); void (*remove)(struct device *dev, struct mtk_mutex *mutex); unsigned int (*encoder_index)(struct device *dev); + u64 (*get_sec_port)(struct mtk_ddp_comp *comp, unsigned int idx); }; struct mtk_ddp_comp { @@ -199,6 +200,14 @@ static inline unsigned int mtk_ddp_gamma_get_lut_size(struct mtk_ddp_comp *comp) return 0; } +static inline u64 mtk_ddp_comp_layer_get_sec_port(struct mtk_ddp_comp *comp, + unsigned int idx) +{ + if (comp->funcs && comp->funcs->get_sec_port) + return comp->funcs->get_sec_port(comp, idx); + return 0; +} + static inline void mtk_ddp_gamma_set(struct mtk_ddp_comp *comp, struct drm_crtc_state *state) { -- 2.18.0
[PATCH v3 03/11] drm/mediatek: Add secure buffer control flow to mtk_drm_gem
Add secure buffer control flow to mtk_drm_gem. When user space takes DRM_MTK_GEM_CREATE_ENCRYPTED flag and size to create a mtk_drm_gem object, mtk_drm_gem will find a matched size dma buffer from secure dma-heap and bind it to mtk_drm_gem object. Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_drm_gem.c | 85 +- drivers/gpu/drm/mediatek/mtk_drm_gem.h | 4 ++ 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c b/drivers/gpu/drm/mediatek/mtk_drm_gem.c index 30e347adcbe9..858f34a735f8 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c @@ -4,6 +4,8 @@ */ #include +#include +#include #include #include @@ -55,6 +57,81 @@ static struct mtk_drm_gem_obj *mtk_drm_gem_init(struct drm_device *dev, return mtk_gem_obj; } +struct mtk_drm_gem_obj *mtk_drm_gem_create_from_heap(struct drm_device *dev, +const char *heap, size_t size) +{ + struct mtk_drm_private *priv = dev->dev_private; + struct mtk_drm_gem_obj *mtk_gem; + struct drm_gem_object *obj; + struct dma_heap *dma_heap; + struct dma_buf *dma_buf; + struct dma_buf_attachment *attach; + struct sg_table *sgt; + struct iosys_map map = {}; + int ret; + + mtk_gem = mtk_drm_gem_init(dev, size); + if (IS_ERR(mtk_gem)) + return ERR_CAST(mtk_gem); + + obj = &mtk_gem->base; + + dma_heap = dma_heap_find(heap); + if (!dma_heap) { + DRM_ERROR("heap find fail\n"); + goto err_gem_free; + } + dma_buf = dma_heap_buffer_alloc(dma_heap, size, + O_RDWR | O_CLOEXEC, DMA_HEAP_VALID_HEAP_FLAGS); + if (IS_ERR(dma_buf)) { + DRM_ERROR("buffer alloc fail\n"); + dma_heap_put(dma_heap); + goto err_gem_free; + } + dma_heap_put(dma_heap); + + attach = dma_buf_attach(dma_buf, priv->dma_dev); + if (IS_ERR(attach)) { + DRM_ERROR("attach fail, return\n"); + dma_buf_put(dma_buf); + goto err_gem_free; + } + + sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); + if (IS_ERR(sgt)) { + DRM_ERROR("map failed, detach and return\n"); + dma_buf_detach(dma_buf, attach); + dma_buf_put(dma_buf); + goto err_gem_free; + } + obj->import_attach = attach; + mtk_gem->dma_addr = sg_dma_address(sgt->sgl); + mtk_gem->sg = sgt; + mtk_gem->size = dma_buf->size; + + if (!strcmp(heap, "mtk_svp") || !strcmp(heap, "mtk_svp_cma")) { + /* secure buffer can not be mapped */ + mtk_gem->secure = true; + } else { + ret = dma_buf_vmap(dma_buf, &map); + mtk_gem->kvaddr = map.vaddr; + if (ret) { + DRM_ERROR("map failed, ret=%d\n", ret); + dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); + dma_buf_detach(dma_buf, attach); + dma_buf_put(dma_buf); + mtk_gem->kvaddr = NULL; + } + } + + return mtk_gem; + +err_gem_free: + drm_gem_object_release(obj); + kfree(mtk_gem); + return ERR_PTR(-ENOMEM); +} + struct mtk_drm_gem_obj *mtk_drm_gem_create(struct drm_device *dev, size_t size, bool alloc_kmap) { @@ -225,7 +302,9 @@ struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev, if (IS_ERR(mtk_gem)) return ERR_CAST(mtk_gem); + mtk_gem->secure = !sg_page(sg->sgl); mtk_gem->dma_addr = sg_dma_address(sg->sgl); + mtk_gem->size = attach->dmabuf->size; mtk_gem->sg = sg; return &mtk_gem->base; @@ -301,7 +380,11 @@ int mtk_gem_create_ioctl(struct drm_device *dev, void *data, struct drm_mtk_gem_create *args = data; int ret; - mtk_gem = mtk_drm_gem_create(dev, args->size, false); + if (args->flags & DRM_MTK_GEM_CREATE_ENCRYPTED) + mtk_gem = mtk_drm_gem_create_from_heap(dev, "mtk_svp_cma", args->size); + else + mtk_gem = mtk_drm_gem_create(dev, args->size, false); + if (IS_ERR(mtk_gem)) return PTR_ERR(mtk_gem); diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.h b/drivers/gpu/drm/mediatek/mtk_drm_gem.h index 90f3d2916ec5..8fd5ce827d4f 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_gem.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.h @@ -27,9 +27,11 @@ struct mtk_drm_gem_obj { void*cookie; void*kvaddr; dma_addr_t dma_addr; + size_t size; unsigned long dma_attrs; struct sg_t
[PATCH v3 07/11] drm/mediatek: Add secure layer config support for ovl
Add secure layer config support for ovl. TODO: 1. Move DISP_REG_OVL_SECURE setting to secure world. 2. Change the parameter register address in mtk_ddp_sec_write() from "u32 addr" to "struct cmdq_client_reg *cmdq_reg". Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_disp_drv.h | 2 ++ drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 31 +++-- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 29 +++ 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h index 1311562d25cc..77054adcd9cf 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h @@ -9,6 +9,7 @@ #include #include #include +#include "mtk_drm_ddp_comp.h" #include "mtk_drm_plane.h" #include "mtk_mdp_rdma.h" @@ -82,6 +83,7 @@ void mtk_ovl_clk_disable(struct device *dev); void mtk_ovl_config(struct device *dev, unsigned int w, unsigned int h, unsigned int vrefresh, unsigned int bpc, struct cmdq_pkt *cmdq_pkt); +u64 mtk_ovl_get_sec_port(struct mtk_ddp_comp *comp, unsigned int idx); int mtk_ovl_layer_check(struct device *dev, unsigned int idx, struct mtk_plane_state *mtk_state); void mtk_ovl_layer_config(struct device *dev, unsigned int idx, diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 2bffe4245466..c18f76412a2e 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -46,6 +46,7 @@ #define DISP_REG_OVL_ADDR(ovl, n) ((ovl)->data->addr + 0x20 * (n)) #define DISP_REG_OVL_HDR_ADDR(ovl, n) ((ovl)->data->addr + 0x20 * (n) + 0x04) #define DISP_REG_OVL_HDR_PITCH(ovl, n) ((ovl)->data->addr + 0x20 * (n) + 0x08) +#define DISP_REG_OVL_SECURE0x0fc0 #define GMC_THRESHOLD_BITS 16 #define GMC_THRESHOLD_HIGH ((1 << GMC_THRESHOLD_BITS) / 4) @@ -126,8 +127,19 @@ struct mtk_disp_ovl { const struct mtk_disp_ovl_data *data; void(*vblank_cb)(void *data); void*vblank_cb_data; + resource_size_t regs_pa; }; +u64 mtk_ovl_get_sec_port(struct mtk_ddp_comp *comp, unsigned int idx) +{ + if (comp->id == DDP_COMPONENT_OVL0) + return BIT_ULL(CMDQ_SEC_DISP_OVL0); + else if (comp->id == DDP_COMPONENT_OVL1) + return BIT_ULL(CMDQ_SEC_DISP_OVL1); + + return 0; +} + static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id) { struct mtk_disp_ovl *priv = dev_id; @@ -449,8 +461,22 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, DISP_REG_OVL_SRC_SIZE(idx)); mtk_ddp_write_relaxed(cmdq_pkt, offset, &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_OFFSET(idx)); - mtk_ddp_write_relaxed(cmdq_pkt, addr, &ovl->cmdq_reg, ovl->regs, - DISP_REG_OVL_ADDR(ovl, idx)); + + if (state->pending.is_secure) { + const struct drm_format_info *fmt_info = drm_format_info(fmt); + unsigned int buf_size = (pending->height - 1) * pending->pitch + + pending->width * fmt_info->cpp[0]; + + mtk_ddp_write_mask(cmdq_pkt, BIT(idx), &ovl->cmdq_reg, ovl->regs, + DISP_REG_OVL_SECURE, BIT(idx)); + mtk_ddp_sec_write(cmdq_pkt, ovl->regs_pa + DISP_REG_OVL_ADDR(ovl, idx), + pending->addr, CMDQ_IWC_H_2_MVA, 0, buf_size, 0); + } else { + mtk_ddp_write_mask(cmdq_pkt, 0, &ovl->cmdq_reg, ovl->regs, + DISP_REG_OVL_SECURE, BIT(idx)); + mtk_ddp_write_relaxed(cmdq_pkt, addr, &ovl->cmdq_reg, ovl->regs, + DISP_REG_OVL_ADDR(ovl, idx)); + } if (is_afbc) { mtk_ddp_write_relaxed(cmdq_pkt, hdr_addr, &ovl->cmdq_reg, ovl->regs, @@ -529,6 +555,7 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + priv->regs_pa = res->start; priv->regs = devm_ioremap_resource(dev, res); if (IS_ERR(priv->regs)) { dev_err(dev, "failed to ioremap ovl\n"); diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c index 3046c0409353..6aed7647dfc0 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c @@ -111,6 +111,34 @@ void mtk_ddp_write_mask(struct cmdq_pkt *cmdq_pkt, unsigned int value, #endif } +void mtk_ddp_sec_write(struct cmdq_pkt *cmdq_pkt, u32 addr, u64 base, + const enum cmdq_iwc_addr_metadata_type type, +
[PATCH v3 10/11] drm/mediatek: Add cmdq_insert_backup_cookie before secure pkt finalize
Add cmdq_insert_backup_cookie to append some commands before EOC: 1. Get GCE HW thread execute count from the GCE HW register. 2. Add 1 to the execute count and then store into a shared memory. 3. Set a software event siganl as secure irq to GCE HW. Since the value of execute count + 1 is stored in a shared memory, CMDQ driver in the normal world can use it to handle task done in irq handler and CMDQ driver in the secure world will use it to schedule the task slot for each secure thread. The reason why we use shared memory to record execute count here is: 1. normal world can not access the register of secure GCE thread in normal world. 2. calling TEE invoke cmd in the irq handler would be expensive and not stable. I've tested that a single TEE invloke cmd to CMDQ PTA costs 19~53 us. Maybe it would cost more during the scenario that needs more CPU loading. Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 79617c0f016d..856513a14cda 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -179,7 +179,7 @@ void mtk_crtc_disable_secure_state(struct drm_crtc *crtc) sec_scn = CMDQ_SEC_SCNR_SUB_DISP_DISABLE; cmdq_sec_pkt_set_data(&mtk_crtc->sec_cmdq_handle, sec_engine, sec_engine, sec_scn); - + cmdq_sec_insert_backup_cookie(&mtk_crtc->sec_cmdq_handle); cmdq_pkt_finalize(&mtk_crtc->sec_cmdq_handle); dma_sync_single_for_device(mtk_crtc->sec_cmdq_client.chan->mbox->dev, mtk_crtc->sec_cmdq_handle.pa_base, @@ -791,6 +791,8 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc, cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event); cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, false); mtk_crtc_ddp_config(crtc, cmdq_handle); + if (cmdq_handle->sec_data) + cmdq_sec_insert_backup_cookie(cmdq_handle); cmdq_pkt_finalize(cmdq_handle); dma_sync_single_for_device(cmdq_client.chan->mbox->dev, cmdq_handle->pa_base, -- 2.18.0
[PATCH v3 01/11] drm/mediatek: Add interface to allocate MediaTek GEM buffer.
From: CK Hu Add an interface to allocate MediaTek GEM buffers, allow the IOCTLs to be used by render nodes. This patch also sets the RENDER driver feature. Signed-off-by: CK Hu Signed-off-by: Nicolas Boichat Signed-off-by: Philipp Zabel Signed-off-by: Jason-JH.Lin Reviewed-by: Daniel Kurtz Reviewed-by: Nicolas Boichat Tested-by: Daniel Kurtz Tested-by: Pi-Hsun Shih --- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 13 ++ drivers/gpu/drm/mediatek/mtk_drm_gem.c | 39 + drivers/gpu/drm/mediatek/mtk_drm_gem.h | 12 ++ include/uapi/drm/mediatek_drm.h| 58 ++ 4 files changed, 122 insertions(+) create mode 100644 include/uapi/drm/mediatek_drm.h diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 2b0c35cacbc6..5d2a39e491aa 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "mtk_drm_crtc.h" #include "mtk_drm_ddp_comp.h" @@ -569,6 +570,14 @@ static void mtk_drm_kms_deinit(struct drm_device *drm) component_unbind_all(drm->dev, drm); } +static const struct drm_ioctl_desc mtk_ioctls[] = { + DRM_IOCTL_DEF_DRV(MTK_GEM_CREATE, mtk_gem_create_ioctl, + DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MTK_GEM_MAP_OFFSET, + mtk_gem_map_offset_ioctl, + DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW), +}; + DEFINE_DRM_GEM_FOPS(mtk_drm_fops); /* @@ -590,6 +599,10 @@ static const struct drm_driver mtk_drm_driver = { .gem_prime_import = mtk_drm_gem_prime_import, .gem_prime_import_sg_table = mtk_gem_prime_import_sg_table, + + .ioctls = mtk_ioctls, + .num_ioctls = ARRAY_SIZE(mtk_ioctls), + .fops = &mtk_drm_fops, .name = DRIVER_NAME, diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c b/drivers/gpu/drm/mediatek/mtk_drm_gem.c index 4f2e3feabc0f..30e347adcbe9 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c @@ -4,6 +4,7 @@ */ #include +#include #include #include @@ -283,3 +284,41 @@ void mtk_drm_gem_prime_vunmap(struct drm_gem_object *obj, mtk_gem->kvaddr = NULL; kfree(mtk_gem->pages); } + +int mtk_gem_map_offset_ioctl(struct drm_device *drm, void *data, +struct drm_file *file_priv) +{ + struct drm_mtk_gem_map_off *args = data; + + return drm_gem_dumb_map_offset(file_priv, drm, args->handle, + &args->offset); +} + +int mtk_gem_create_ioctl(struct drm_device *dev, void *data, +struct drm_file *file_priv) +{ + struct mtk_drm_gem_obj *mtk_gem; + struct drm_mtk_gem_create *args = data; + int ret; + + mtk_gem = mtk_drm_gem_create(dev, args->size, false); + if (IS_ERR(mtk_gem)) + return PTR_ERR(mtk_gem); + + /* +* allocate a id of idr table where the obj is registered +* and handle has the id what user can see. +*/ + ret = drm_gem_handle_create(file_priv, &mtk_gem->base, &args->handle); + if (ret) + goto err_handle_create; + + /* drop reference from allocate - handle holds it now. */ + drm_gem_object_put(&mtk_gem->base); + + return 0; + +err_handle_create: + mtk_drm_gem_free_object(&mtk_gem->base); + return ret; +} diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.h b/drivers/gpu/drm/mediatek/mtk_drm_gem.h index 78f23b07a02e..90f3d2916ec5 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_gem.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.h @@ -46,4 +46,16 @@ int mtk_drm_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map); void mtk_drm_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map); +/* + * request gem object creation and buffer allocation as the size + * that it is calculated with framebuffer information such as width, + * height and bpp. + */ +int mtk_gem_create_ioctl(struct drm_device *dev, void *data, +struct drm_file *file_priv); + +/* get buffer offset to map to user space. */ +int mtk_gem_map_offset_ioctl(struct drm_device *dev, void *data, +struct drm_file *file_priv); + #endif diff --git a/include/uapi/drm/mediatek_drm.h b/include/uapi/drm/mediatek_drm.h new file mode 100644 index ..f4d47577c94e --- /dev/null +++ b/include/uapi/drm/mediatek_drm.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * Copyright (c) 2015 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will
[PATCH v3 05/11] drm/mediatek: Add mtk_ddp_sec_write to config secure buffer info
Add mtk_ddp_sec_write to configure secure buffer information to cmdq secure packet data. Then secure cmdq driver will use these information to configure curresponding secure DRAM address to HW overlay in secure world. Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h index 4bae55bdb034..b5a05ca3a385 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h @@ -7,6 +7,8 @@ #define MTK_DRM_DDP_COMP_H #include +#include +#include #include #include #include @@ -308,4 +310,7 @@ void mtk_ddp_write_relaxed(struct cmdq_pkt *cmdq_pkt, unsigned int value, void mtk_ddp_write_mask(struct cmdq_pkt *cmdq_pkt, unsigned int value, struct cmdq_client_reg *cmdq_reg, void __iomem *regs, unsigned int offset, unsigned int mask); +void mtk_ddp_sec_write(struct cmdq_pkt *cmdq_pkt, u32 addr, u64 base, + const enum cmdq_iwc_addr_metadata_type type, + const u32 offset, const u32 size, const u32 port); #endif /* MTK_DRM_DDP_COMP_H */ -- 2.18.0
[PATCH v2 05/11] drm/mediatek: Add mtk_ddp_sec_write to config secure buffer info
Add mtk_ddp_sec_write to configure secure buffer information to cmdq secure packet data. Then secure cmdq driver will use these information to configure curresponding secure DRAM address to HW overlay in secure world. Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 12 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 4 2 files changed, 16 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c index 771f4e173353..3dca936b9143 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c @@ -111,6 +111,18 @@ void mtk_ddp_write_mask(struct cmdq_pkt *cmdq_pkt, unsigned int value, #endif } +void mtk_ddp_sec_write(struct cmdq_pkt *cmdq_pkt, u32 addr, u64 base, + const enum cmdq_iwc_addr_metadata_type type, + const u32 offset, const u32 size, const u32 port) +{ +#if IS_REACHABLE(CONFIG_MTK_CMDQ) + /* secure buffer will be 4K alignment */ + if (cmdq_pkt) + cmdq_sec_pkt_write(cmdq_pkt, addr, base, type, + offset, ALIGN(size, PAGE_SIZE), port); +#endif +} + static int mtk_ddp_clk_enable(struct device *dev) { struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev); diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h index febcaeef16a1..239a65140352 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h @@ -7,6 +7,7 @@ #define MTK_DRM_DDP_COMP_H #include +#include #include #include #include @@ -291,4 +292,7 @@ void mtk_ddp_write_relaxed(struct cmdq_pkt *cmdq_pkt, unsigned int value, void mtk_ddp_write_mask(struct cmdq_pkt *cmdq_pkt, unsigned int value, struct cmdq_client_reg *cmdq_reg, void __iomem *regs, unsigned int offset, unsigned int mask); +void mtk_ddp_sec_write(struct cmdq_pkt *cmdq_pkt, u32 addr, u64 base, + const enum cmdq_iwc_addr_metadata_type type, + const u32 offset, const u32 size, const u32 port); #endif /* MTK_DRM_DDP_COMP_H */ -- 2.18.0
[PATCH v2 00/11] Add mediate-drm secure flow for SVP
The patch series provides drm driver support for enabling secure video path (SVP) playback on MediaiTek hardware in the Linux kernel. Memory Definitions: secure memory - Memory allocated in the TEE (Trusted Execution Environment) which is inaccessible in the REE (Rich Execution Environment, i.e. linux kernel/userspace). secure handle - Integer value which acts as reference to 'secure memory'. Used in communication between TEE and REE to reference 'secure memory'. secure buffer - 'secure memory' that is used to store decrypted, compressed video or for other general purposes in the TEE. secure surface - 'secure memory' that is used to store graphic buffers. Memory Usage in SVP: The overall flow of SVP starts with encrypted video coming in from an outside source into the REE. The REE will then allocate a 'secure buffer' and send the corresponding 'secure handle' along with the encrypted, compressed video data to the TEE. The TEE will then decrypt the video and store the result in the 'secure buffer'. The REE will then allocate a 'secure surface'. The REE will pass the 'secure handles' for both the 'secure buffer' and 'secure surface' into the TEE for video decoding. The video decoder HW will then decode the contents of the 'secure buffer' and place the result in the 'secure surface'. The REE will then attach the 'secure surface' to the overlay plane for rendering of the video. Everything relating to ensuring security of the actual contents of the 'secure buffer' and 'secure surface' is out of scope for the REE and is the responsibility of the TEE. DRM driver handles allocation of gem objects that are backed by a 'secure surface' and for displaying a 'secure surface' on the overlay plane. This introduces a new flag for object creation called DRM_MTK_GEM_CREATE_ENCRYPTED which indicates it should be a 'secure surface'. All changes here are in MediaTek specific code. --- Based on 3 series and 1 patch: [1] dma-buf: heaps: Add MediaTek secure heap - https://patchwork.kernel.org/project/linux-mediatek/list/?series=782776 [2] add driver to support secure video decoder - https://patchwork.kernel.org/project/linux-mediatek/list/?series=782922 [3] soc: mediatek: Add register definitions for GCE - https://patchwork.kernel.org/project/linux-mediatek/patch/20231017064717.21616-2-shawn.s...@mediatek.com/ [4] Add CMDQ secure driver for SVP - https://patchwork.kernel.org/project/linux-mediatek/list/?series=795502 --- Change in v2: 1. remove the DRIVER_RDNDER flag for mtk_drm_ioctl 2. move cmdq_insert_backup_cookie into client driver 3. move secure gce node define from mt8195-cherry.dtsi to mt8195.dtsi --- CK Hu (1): drm/mediatek: Add interface to allocate MediaTek GEM buffer. Jason-JH.Lin (10): drm/mediatek/uapi: Add DRM_MTK_GEM_CREATED_ENCRYPTTED flag drm/mediatek: Add secure buffer control flow to mtk_drm_gem drm/mediatek: Add secure identify flag and funcution to mtk_drm_plane drm/mediatek: Add mtk_ddp_sec_write to config secure buffer info drm/mediatek: Add get_sec_port interface to mtk_ddp_comp drm/mediatek: Add secure layer config support for ovl drm/mediatek: Add secure layer config support for ovl_adaptor drm/mediatek: Add secure flow support to mediatek-drm drm/mediatek: Add cmdq_insert_backup_cookie before secure pkt finalize arm64: dts: mt8195: Add secure mbox settings for vdosys arch/arm64/boot/dts/mediatek/mt8195.dtsi | 6 +- drivers/gpu/drm/mediatek/mtk_disp_drv.h | 3 + drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 31 +- .../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 15 + drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 274 +- drivers/gpu/drm/mediatek/mtk_drm_crtc.h | 1 + drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 14 + drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 13 + drivers/gpu/drm/mediatek/mtk_drm_drv.c| 13 + drivers/gpu/drm/mediatek/mtk_drm_gem.c| 121 drivers/gpu/drm/mediatek/mtk_drm_gem.h| 16 + drivers/gpu/drm/mediatek/mtk_drm_plane.c | 7 + drivers/gpu/drm/mediatek/mtk_drm_plane.h | 2 + drivers/gpu/drm/mediatek/mtk_mdp_rdma.c | 11 +- drivers/gpu/drm/mediatek/mtk_mdp_rdma.h | 2 + include/uapi/drm/mediatek_drm.h | 59 16 files changed, 570 insertions(+), 18 deletions(-) create mode 100644 include/uapi/drm/mediatek_drm.h -- 2.18.0
[PATCH v2 02/11] drm/mediatek/uapi: Add DRM_MTK_GEM_CREATED_ENCRYPTTED flag
Add DRM_MTK_GEM_CREATED_ENCRYPTTED flag to allocate a secure buffer to support secure video path feature. Signed-off-by: Jason-JH.Lin --- include/uapi/drm/mediatek_drm.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/uapi/drm/mediatek_drm.h b/include/uapi/drm/mediatek_drm.h index c050de320a84..93f25e0c21d7 100644 --- a/include/uapi/drm/mediatek_drm.h +++ b/include/uapi/drm/mediatek_drm.h @@ -48,6 +48,7 @@ struct drm_mtk_gem_map_off { #define DRM_MTK_GEM_CREATE 0x00 #define DRM_MTK_GEM_MAP_OFFSET 0x01 +#define DRM_MTK_GEM_CREATE_ENCRYPTED 0x02 #define DRM_IOCTL_MTK_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \ DRM_MTK_GEM_CREATE, struct drm_mtk_gem_create) -- 2.18.0
[PATCH v2 11/11] arm64: dts: mt8195: Add secure mbox settings for vdosys
Add a secure mailbox channel to support secure video path on vdosys0 and vdosys1. Signed-off-by: Jason-JH.Lin --- arch/arm64/boot/dts/mediatek/mt8195.dtsi | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi index 42f9fdf696fe..d14113c89a9b 100644 --- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi @@ -2619,7 +2619,8 @@ vdosys0: syscon@1c01a000 { compatible = "mediatek,mt8195-vdosys0", "mediatek,mt8195-mmsys", "syscon"; reg = <0 0x1c01a000 0 0x1000>; - mboxes = <&gce0 0 CMDQ_THR_PRIO_4>; + mboxes = <&gce0 0 CMDQ_THR_PRIO_4>, +<&gce0 8 CMDQ_THR_PRIO_4>; /* secure mbox */ #clock-cells = <1>; }; @@ -2804,7 +2805,8 @@ vdosys1: syscon@1c10 { compatible = "mediatek,mt8195-vdosys1", "syscon"; reg = <0 0x1c10 0 0x1000>; - mboxes = <&gce0 1 CMDQ_THR_PRIO_4>; + mboxes = <&gce0 1 CMDQ_THR_PRIO_4>, +<&gce0 9 CMDQ_THR_PRIO_4>; /* secure mbox */; mediatek,gce-client-reg = <&gce0 SUBSYS_1c10 0x 0x1000>; #clock-cells = <1>; #reset-cells = <1>; -- 2.18.0
[PATCH v2 10/11] drm/mediatek: Add cmdq_insert_backup_cookie before secure pkt finalize
Add cmdq_insert_backup_cookie to append some commands before EOC: 1. Get GCE HW thread execute count from the GCE HW register. 2. Add 1 to the execute count and then store into a shared memory. 3. Set a software event siganl as secure irq to GCE HW. Since the value of execute count + 1 is stored in a shared memory, CMDQ driver in the normal world can use it to handle task done in irq handler and CMDQ driver in the secure world will use it to schedule the task slot for each secure thread. Signed-off-by: Jason-JH.Lin --- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 6c2cf339b923..399aa6bb2f8d 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -177,7 +177,7 @@ void mtk_crtc_disable_secure_state(struct drm_crtc *crtc) sec_scn = CMDQ_SEC_SUB_DISP_DISABLE; cmdq_sec_pkt_set_data(&mtk_crtc->sec_cmdq_handle, sec_engine, sec_engine, sec_scn); - + cmdq_sec_insert_backup_cookie(&mtk_crtc->sec_cmdq_handle); cmdq_pkt_finalize(&mtk_crtc->sec_cmdq_handle); dma_sync_single_for_device(mtk_crtc->sec_cmdq_client.chan->mbox->dev, mtk_crtc->sec_cmdq_handle.pa_base, @@ -786,6 +786,8 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc, cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event); cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, false); mtk_crtc_ddp_config(crtc, cmdq_handle); + if (cmdq_handle->sec_data) + cmdq_sec_insert_backup_cookie(cmdq_handle); cmdq_pkt_finalize(cmdq_handle); dma_sync_single_for_device(cmdq_client.chan->mbox->dev, cmdq_handle->pa_base, -- 2.18.0
[PATCH v2 01/11] drm/mediatek: Add interface to allocate MediaTek GEM buffer.
From: CK Hu Add an interface to allocate MediaTek GEM buffers, allow the IOCTLs to be used by render nodes. This patch also sets the RENDER driver feature. Signed-off-by: CK Hu Signed-off-by: Nicolas Boichat Signed-off-by: Philipp Zabel Signed-off-by: Jason-JH.Lin Reviewed-by: Daniel Kurtz Reviewed-by: Nicolas Boichat Tested-by: Daniel Kurtz Tested-by: Pi-Hsun Shih --- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 13 ++ drivers/gpu/drm/mediatek/mtk_drm_gem.c | 39 + drivers/gpu/drm/mediatek/mtk_drm_gem.h | 12 ++ include/uapi/drm/mediatek_drm.h| 58 ++ 4 files changed, 122 insertions(+) create mode 100644 include/uapi/drm/mediatek_drm.h diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 93552d76b6e7..e3e9dbdf265b 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "mtk_drm_crtc.h" #include "mtk_drm_ddp_comp.h" @@ -541,6 +542,14 @@ static void mtk_drm_kms_deinit(struct drm_device *drm) component_unbind_all(drm->dev, drm); } +static const struct drm_ioctl_desc mtk_ioctls[] = { + DRM_IOCTL_DEF_DRV(MTK_GEM_CREATE, mtk_gem_create_ioctl, + DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MTK_GEM_MAP_OFFSET, + mtk_gem_map_offset_ioctl, + DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW), +}; + DEFINE_DRM_GEM_FOPS(mtk_drm_fops); /* @@ -562,6 +571,10 @@ static const struct drm_driver mtk_drm_driver = { .gem_prime_import = mtk_drm_gem_prime_import, .gem_prime_import_sg_table = mtk_gem_prime_import_sg_table, + + .ioctls = mtk_ioctls, + .num_ioctls = ARRAY_SIZE(mtk_ioctls), + .fops = &mtk_drm_fops, .name = DRIVER_NAME, diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c b/drivers/gpu/drm/mediatek/mtk_drm_gem.c index 9f364df52478..bcce723f257d 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c @@ -4,6 +4,7 @@ */ #include +#include #include #include @@ -272,3 +273,41 @@ void mtk_drm_gem_prime_vunmap(struct drm_gem_object *obj, mtk_gem->kvaddr = NULL; kfree(mtk_gem->pages); } + +int mtk_gem_map_offset_ioctl(struct drm_device *drm, void *data, +struct drm_file *file_priv) +{ + struct drm_mtk_gem_map_off *args = data; + + return drm_gem_dumb_map_offset(file_priv, drm, args->handle, + &args->offset); +} + +int mtk_gem_create_ioctl(struct drm_device *dev, void *data, +struct drm_file *file_priv) +{ + struct mtk_drm_gem_obj *mtk_gem; + struct drm_mtk_gem_create *args = data; + int ret; + + mtk_gem = mtk_drm_gem_create(dev, args->size, false); + if (IS_ERR(mtk_gem)) + return PTR_ERR(mtk_gem); + + /* +* allocate a id of idr table where the obj is registered +* and handle has the id what user can see. +*/ + ret = drm_gem_handle_create(file_priv, &mtk_gem->base, &args->handle); + if (ret) + goto err_handle_create; + + /* drop reference from allocate - handle holds it now. */ + drm_gem_object_put(&mtk_gem->base); + + return 0; + +err_handle_create: + mtk_drm_gem_free_object(&mtk_gem->base); + return ret; +} diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.h b/drivers/gpu/drm/mediatek/mtk_drm_gem.h index 78f23b07a02e..90f3d2916ec5 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_gem.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.h @@ -46,4 +46,16 @@ int mtk_drm_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map); void mtk_drm_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map); +/* + * request gem object creation and buffer allocation as the size + * that it is calculated with framebuffer information such as width, + * height and bpp. + */ +int mtk_gem_create_ioctl(struct drm_device *dev, void *data, +struct drm_file *file_priv); + +/* get buffer offset to map to user space. */ +int mtk_gem_map_offset_ioctl(struct drm_device *dev, void *data, +struct drm_file *file_priv); + #endif diff --git a/include/uapi/drm/mediatek_drm.h b/include/uapi/drm/mediatek_drm.h new file mode 100644 index ..c050de320a84 --- /dev/null +++ b/include/uapi/drm/mediatek_drm.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * Copyright (c) 2015 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will