Mediatek DRM Fixes - 20241028

1. Fix degradation problem of alpha blending
 2. Fix color format MACROs in OVL
 3. Fix get efuse issue for MT8188 DPTX
 4. Fix potential NULL dereference in mtk_crtc_destroy()
 5. Correct dpi power-domains property
 6. Add split subschema property constraints
 -----BEGIN PGP SIGNATURE-----
 
 iQJMBAABCgA2FiEEACwLKSDmq+9RDv5P4cpzo8lZTiQFAmcfllQYHGNodW5rdWFu
 Zy5odUBrZXJuZWwub3JnAAoJEOHKc6PJWU4kS1QP/ju0jufnTZsS6m61yNKTJ/wA
 LjZeGOmtsbPOQc+++fD+5M4gAj9V3tuFPyfmqSRyLWj3PHDg05FY23XkFnKEDNMH
 n0S5i/097ZaS4fqDZcIy2A8+rOO+72aX+noLZaeMNT9V1k6EH08fycQ1CWP/fc0b
 3tS9e9f7lYzO+Bf0h7TophXJ81Dga/o8hj+16qo0eSjz4vS+49W/Ir30gp8UprfK
 i/p5TwoAApDfe5VTOnXgZlWfjVBCoSvWHD9nX8uRw9RXunf+B0GWYe5LcKRLXtFv
 JEuf8+D3lO2CEuLLfxtiXsIKA9uKkHkmrpCQ++2aLFnqav/mA1tkCN38mvtxtlCs
 Aqb2ng19NWNtP7Fhz/N8AELLgoQXcs1KZpYvAJkWeHjQXrxWtFMvSCa8mtQImtwT
 aG7QvONeBHmwIqHZNQYXTE337qcua0Wz06jYv8pgnUrwdqBrwVtq6qHUPk+TR3/G
 GNbM4LQYTEBFoBY1gUjgs4kbrvtTWBoYxcaMdW2wpYELCJ1trbvbzk9CA7RPjRWM
 4SH1OFwICv2wz6OWoywgJLLYTVC3PJf/c1bfew4AZsMHW4TSKnctXdd5ug5WSwp1
 tvRRr36a5gjMxFL4zOx0yPGIIVavlKNdM14ntyH2fo1v+KC+NJtWbYGlMwnsVvMK
 AXzr6lalO2jfvjxy2mg9
 =F/S2
 -----END PGP SIGNATURE-----

Merge tag 'mediatek-drm-fixes-20241028' of https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux into drm-fixes

Mediatek DRM Fixes - 20241028

1. Fix degradation problem of alpha blending
2. Fix color format MACROs in OVL
3. Fix get efuse issue for MT8188 DPTX
4. Fix potential NULL dereference in mtk_crtc_destroy()
5. Correct dpi power-domains property
6. Add split subschema property constraints

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Chun-Kuang Hu <chunkuang.hu@kernel.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20241028135846.3570-1-chunkuang.hu@kernel.org
This commit is contained in:
Dave Airlie 2024-11-01 07:34:14 +10:00
commit 427360718e
13 changed files with 208 additions and 46 deletions

View File

@ -63,6 +63,16 @@ properties:
- const: sleep
power-domains:
description: |
The MediaTek DPI module is typically associated with one of the
following multimedia power domains:
POWER_DOMAIN_DISPLAY
POWER_DOMAIN_VDOSYS
POWER_DOMAIN_MM
The specific power domain used varies depending on the SoC design.
It is recommended to explicitly add the appropriate power domain
property to the DPI node in the device tree.
maxItems: 1
port:
@ -79,20 +89,6 @@ required:
- clock-names
- port
allOf:
- if:
not:
properties:
compatible:
contains:
enum:
- mediatek,mt6795-dpi
- mediatek,mt8173-dpi
- mediatek,mt8186-dpi
then:
properties:
power-domains: false
additionalProperties: false
examples:

View File

@ -38,6 +38,7 @@ properties:
description: A phandle and PM domain specifier as defined by bindings of
the power controller specified by phandle. See
Documentation/devicetree/bindings/power/power-domain.yaml for details.
maxItems: 1
mediatek,gce-client-reg:
description:
@ -57,6 +58,9 @@ properties:
clocks:
items:
- description: SPLIT Clock
- description: Used for interfacing with the HDMI RX signal source.
- description: Paired with receiving HDMI RX metadata.
minItems: 1
required:
- compatible
@ -72,9 +76,24 @@ allOf:
const: mediatek,mt8195-mdp3-split
then:
properties:
clocks:
minItems: 3
required:
- mediatek,gce-client-reg
- if:
properties:
compatible:
contains:
const: mediatek,mt8173-disp-split
then:
properties:
clocks:
maxItems: 1
additionalProperties: false
examples:

View File

@ -127,9 +127,8 @@ static void mtk_crtc_destroy(struct drm_crtc *crtc)
mtk_mutex_put(mtk_crtc->mutex);
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
cmdq_pkt_destroy(&mtk_crtc->cmdq_client, &mtk_crtc->cmdq_handle);
if (mtk_crtc->cmdq_client.chan) {
cmdq_pkt_destroy(&mtk_crtc->cmdq_client, &mtk_crtc->cmdq_handle);
mbox_free_channel(mtk_crtc->cmdq_client.chan);
mtk_crtc->cmdq_client.chan = NULL;
}
@ -913,6 +912,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)

View File

@ -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,

View File

@ -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)
{

View File

@ -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_formats(struct device *dev);
enum drm_mode_status mtk_ovl_adaptor_mode_valid(struct device *dev,

View File

@ -65,8 +65,8 @@
#define OVL_CON_CLRFMT_RGB (1 << 12)
#define OVL_CON_CLRFMT_ARGB8888 (2 << 12)
#define OVL_CON_CLRFMT_RGBA8888 (3 << 12)
#define OVL_CON_CLRFMT_ABGR8888 (OVL_CON_CLRFMT_RGBA8888 | OVL_CON_BYTE_SWAP)
#define OVL_CON_CLRFMT_BGRA8888 (OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP)
#define OVL_CON_CLRFMT_ABGR8888 (OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP)
#define OVL_CON_CLRFMT_BGRA8888 (OVL_CON_CLRFMT_RGBA8888 | OVL_CON_BYTE_SWAP)
#define OVL_CON_CLRFMT_UYVY (4 << 12)
#define OVL_CON_CLRFMT_YUYV (5 << 12)
#define OVL_CON_MTX_YUV_TO_RGB (6 << 16)
@ -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;
@ -214,6 +215,13 @@ void mtk_ovl_disable_vblank(struct device *dev)
writel_relaxed(0x0, ovl->regs + DISP_REG_OVL_INTEN);
}
u32 mtk_ovl_get_blend_modes(struct device *dev)
{
struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
return ovl->data->blend_modes;
}
const u32 *mtk_ovl_get_formats(struct device *dev)
{
struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
@ -386,14 +394,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)
{
/* 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 = 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_PARGB8888.
*
* 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:
@ -471,20 +492,26 @@ 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;
}
/* 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;
/*
* 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;
/*
* 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;
@ -663,6 +690,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),
};
@ -673,6 +703,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),
};
@ -684,6 +717,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,

View File

@ -400,6 +400,13 @@ void mtk_ovl_adaptor_disable_vblank(struct device *dev)
mtk_ethdr_disable_vblank(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0]);
}
u32 mtk_ovl_adaptor_get_blend_modes(struct device *dev)
{
struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
return mtk_ethdr_get_blend_modes(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0]);
}
const u32 *mtk_ovl_adaptor_get_formats(struct device *dev)
{
struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);

View File

@ -145,6 +145,89 @@ struct mtk_dp_data {
u16 audio_m_div2_bit;
};
static const struct mtk_dp_efuse_fmt mt8188_dp_efuse_fmt[MTK_DP_CAL_MAX] = {
[MTK_DP_CAL_GLB_BIAS_TRIM] = {
.idx = 0,
.shift = 10,
.mask = 0x1f,
.min_val = 1,
.max_val = 0x1e,
.default_val = 0xf,
},
[MTK_DP_CAL_CLKTX_IMPSE] = {
.idx = 0,
.shift = 15,
.mask = 0xf,
.min_val = 1,
.max_val = 0xe,
.default_val = 0x8,
},
[MTK_DP_CAL_LN_TX_IMPSEL_PMOS_0] = {
.idx = 1,
.shift = 0,
.mask = 0xf,
.min_val = 1,
.max_val = 0xe,
.default_val = 0x8,
},
[MTK_DP_CAL_LN_TX_IMPSEL_PMOS_1] = {
.idx = 1,
.shift = 8,
.mask = 0xf,
.min_val = 1,
.max_val = 0xe,
.default_val = 0x8,
},
[MTK_DP_CAL_LN_TX_IMPSEL_PMOS_2] = {
.idx = 1,
.shift = 16,
.mask = 0xf,
.min_val = 1,
.max_val = 0xe,
.default_val = 0x8,
},
[MTK_DP_CAL_LN_TX_IMPSEL_PMOS_3] = {
.idx = 1,
.shift = 24,
.mask = 0xf,
.min_val = 1,
.max_val = 0xe,
.default_val = 0x8,
},
[MTK_DP_CAL_LN_TX_IMPSEL_NMOS_0] = {
.idx = 1,
.shift = 4,
.mask = 0xf,
.min_val = 1,
.max_val = 0xe,
.default_val = 0x8,
},
[MTK_DP_CAL_LN_TX_IMPSEL_NMOS_1] = {
.idx = 1,
.shift = 12,
.mask = 0xf,
.min_val = 1,
.max_val = 0xe,
.default_val = 0x8,
},
[MTK_DP_CAL_LN_TX_IMPSEL_NMOS_2] = {
.idx = 1,
.shift = 20,
.mask = 0xf,
.min_val = 1,
.max_val = 0xe,
.default_val = 0x8,
},
[MTK_DP_CAL_LN_TX_IMPSEL_NMOS_3] = {
.idx = 1,
.shift = 28,
.mask = 0xf,
.min_val = 1,
.max_val = 0xe,
.default_val = 0x8,
},
};
static const struct mtk_dp_efuse_fmt mt8195_edp_efuse_fmt[MTK_DP_CAL_MAX] = {
[MTK_DP_CAL_GLB_BIAS_TRIM] = {
.idx = 3,
@ -2771,7 +2854,7 @@ static SIMPLE_DEV_PM_OPS(mtk_dp_pm_ops, mtk_dp_suspend, mtk_dp_resume);
static const struct mtk_dp_data mt8188_dp_data = {
.bridge_type = DRM_MODE_CONNECTOR_DisplayPort,
.smc_cmd = MTK_DP_SIP_ATF_VIDEO_UNMUTE,
.efuse_fmt = mt8195_dp_efuse_fmt,
.efuse_fmt = mt8188_dp_efuse_fmt,
.audio_supported = true,
.audio_pkt_in_hblank_area = true,
.audio_m_div2_bit = MT8188_AUDIO_M_CODE_MULT_DIV_SEL_DP_ENC0_P0_DIV_2,

View File

@ -145,6 +145,13 @@ static irqreturn_t mtk_ethdr_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
u32 mtk_ethdr_get_blend_modes(struct device *dev)
{
return BIT(DRM_MODE_BLEND_PREMULTI) |
BIT(DRM_MODE_BLEND_COVERAGE) |
BIT(DRM_MODE_BLEND_PIXEL_NONE);
}
void mtk_ethdr_layer_config(struct device *dev, unsigned int idx,
struct mtk_plane_state *state,
struct cmdq_pkt *cmdq_pkt)

View File

@ -13,6 +13,7 @@ void mtk_ethdr_clk_disable(struct device *dev);
void mtk_ethdr_config(struct device *dev, unsigned int w,
unsigned int h, unsigned int vrefresh,
unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
u32 mtk_ethdr_get_blend_modes(struct device *dev);
void mtk_ethdr_layer_config(struct device *dev, unsigned int idx,
struct mtk_plane_state *state,
struct cmdq_pkt *cmdq_pkt);

View File

@ -320,8 +320,8 @@ static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = {
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,
size_t num_formats, unsigned int plane_idx)
unsigned int supported_rotations, const u32 blend_modes,
const u32 *formats, size_t num_formats, unsigned int plane_idx)
{
int err;
@ -366,12 +366,11 @@ int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
if (err)
DRM_ERROR("failed to create property: alpha\n");
err = drm_plane_create_blend_mode_property(plane,
BIT(DRM_MODE_BLEND_PREMULTI) |
BIT(DRM_MODE_BLEND_COVERAGE) |
BIT(DRM_MODE_BLEND_PIXEL_NONE));
if (err)
DRM_ERROR("failed to create property: blend_mode\n");
if (blend_modes) {
err = drm_plane_create_blend_mode_property(plane, blend_modes);
if (err)
DRM_ERROR("failed to create property: blend_mode\n");
}
drm_plane_helper_add(plane, &mtk_plane_helper_funcs);

View File

@ -48,6 +48,6 @@ to_mtk_plane_state(struct drm_plane_state *state)
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,
size_t num_formats, unsigned int plane_idx);
unsigned int supported_rotations, const u32 blend_modes,
const u32 *formats, size_t num_formats, unsigned int plane_idx);
#endif