Changes in v7:
- Start/Stop the components in OVL Adaptor with function pointers
- Refine Padding driver
- Fix underrun when the layer is switching off
Changes in v6:
- Separate the commits into smaller ones
- Add DPI input mode setting
- Fix VDOSYS1 power-on issues
Changes in v5:
- Reuse .clk_enable/.clk_disable in struct mtk_ddp_comp_funcs
in mtk_disp_ovl_adaptor.c
- Adjust commits order
Changes in v4:
- Add new functions in mtk_disp_ovl_adaptor.c to enable/disable
components and reuse them when clock enable/disable
- Rename components in mtk_disp_ovl_adaptor.c and sort them in
alphabetical order
Changes in v3:
- Define macro MMSYS_RST_NR in mtk-mmsys.h and update reset table
- Fix typos (ETDHR -> ETHDR, VSNYC -> VSYNC)
- Rebase dt-bindings on linux-next
- Refine description of Padding
- Squash reset bit map commits for VDO0 and VDO1 into one
Changes in v2:
- Remove redundant compatibles of MT8188 because it shares the same
configuration with MT8195
- Separate dt-bindings by modules
- Support reset bit mapping in mmsys driver
Hsiao Chien Sung (23):
dt-bindings: display: mediatek: ethdr: Add compatible for MT8188
dt-bindings: display: mediatek: mdp-rdma: Add compatible for MT8188
dt-bindings: display: mediatek: merge: Add compatible for MT8188
dt-bindings: display: mediatek: padding: Add MT8188
dt-bindings: arm: mediatek: Add compatible for MT8188
dt-bindings: reset: mt8188: Add VDOSYS reset control bits
soc: mediatek: Support MT8188 VDOSYS1 in mtk-mmsys
soc: mediatek: Support MT8188 VDOSYS1 Padding in mtk-mmsys
soc: mediatek: Support reset bit mapping in mmsys driver
soc: mediatek: Add MT8188 VDOSYS reset bit map
drm/mediatek: Rename OVL_ADAPTOR_TYPE_RDMA
drm/mediatek: Refine device table of OVL adaptor
drm/mediatek: Sort OVL adaptor components
drm/mediatek: Add component ID to component match structure
drm/mediatek: Manage component's clock with function pointers
drm/mediatek: Start/Stop components with function pointers
drm/mediatek: Support MT8188 Padding in display driver
drm/mediatek: Add Padding to OVL adaptor
drm/mediatek: Return error if MDP RDMA failed to enable the clock
drm/mediatek: Remove the redundant driver data for DPI
drm/mediatek: Fix underrun in VDO1 when switches off the layer
drm/mediatek: Power on devices in OVL adaptor when atomic enable
drm/mediatek: Support MT8188 VDOSYS1 in display driver
.../bindings/arm/mediatek/mediatek,mmsys.yaml | 1 +
.../display/mediatek/mediatek,ethdr.yaml | 6 +-
.../display/mediatek/mediatek,mdp-rdma.yaml | 6 +-
.../display/mediatek/mediatek,merge.yaml | 3 +
.../display/mediatek/mediatek,padding.yaml | 81 ++++++
drivers/gpu/drm/mediatek/Makefile | 3 +-
drivers/gpu/drm/mediatek/mtk_disp_drv.h | 7 +
drivers/gpu/drm/mediatek/mtk_disp_merge.c | 2 +-
.../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 266 +++++++++++-------
drivers/gpu/drm/mediatek/mtk_dpi.c | 16 +-
drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 9 +
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 1 +
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 9 +
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 4 +
drivers/gpu/drm/mediatek/mtk_drm_drv.h | 2 +-
drivers/gpu/drm/mediatek/mtk_mdp_rdma.c | 3 +-
drivers/gpu/drm/mediatek/mtk_padding.c | 206 ++++++++++++++
drivers/soc/mediatek/mt8188-mmsys.h | 210 ++++++++++++++
drivers/soc/mediatek/mtk-mmsys.c | 27 ++
drivers/soc/mediatek/mtk-mmsys.h | 32 +++
drivers/soc/mediatek/mtk-mutex.c | 51 ++++
include/dt-bindings/reset/mt8188-resets.h | 75 +++++
include/linux/soc/mediatek/mtk-mmsys.h | 8 +
23 files changed, 899 insertions(+), 129 deletions(-)
create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,padding.yaml
create mode 100644 drivers/gpu/drm/mediatek/mtk_padding.c
--
2.18.0
Do not reset Merge while using CMDQ because it doesn't wait for
frame done event as CMDQ does and could lead to underrun when
the layer is switching off.
Fixes: aaf94f7c3ae6 ("drm/mediatek: Add display merge async reset control")
Signed-off-by: Hsiao Chien Sung <[email protected]>
---
drivers/gpu/drm/mediatek/mtk_disp_merge.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_merge.c b/drivers/gpu/drm/mediatek/mtk_disp_merge.c
index e525a6b9e5b0..22f768d923d5 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_merge.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_merge.c
@@ -103,7 +103,7 @@ void mtk_merge_stop_cmdq(struct device *dev, struct cmdq_pkt *cmdq_pkt)
mtk_ddp_write(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
DISP_REG_MERGE_CTRL);
- if (priv->async_clk)
+ if (!cmdq_pkt && priv->async_clk)
reset_control_reset(priv->reset_ctl);
}
--
2.18.0
- The mmsys_dev_num in MT8188 VDOSYS0 was set to 1 since
VDOSYS1 was not available before. Increase it to support
VDOSYS1 in display driver.
- Add compatible name for MT8188 VDOSYS1
(shares the same driver data with MT8195 VDOSYS1)
Reviewed-by: AngeloGioacchino Del Regno <[email protected]>
Reviewed-by: CK Hu <[email protected]>
Signed-off-by: Hsiao Chien Sung <[email protected]>
---
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index cde69f39a066..212475436f47 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -288,6 +288,7 @@ static const struct mtk_mmsys_driver_data mt8186_mmsys_driver_data = {
static const struct mtk_mmsys_driver_data mt8188_vdosys0_driver_data = {
.main_path = mt8188_mtk_ddp_main,
.main_len = ARRAY_SIZE(mt8188_mtk_ddp_main),
+ .mmsys_dev_num = 2,
};
static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = {
@@ -328,6 +329,8 @@ static const struct of_device_id mtk_drm_of_ids[] = {
.data = &mt8186_mmsys_driver_data},
{ .compatible = "mediatek,mt8188-vdosys0",
.data = &mt8188_vdosys0_driver_data},
+ { .compatible = "mediatek,mt8188-vdosys1",
+ .data = &mt8195_vdosys1_driver_data},
{ .compatible = "mediatek,mt8192-mmsys",
.data = &mt8192_mmsys_driver_data},
{ .compatible = "mediatek,mt8195-mmsys",
--
2.18.0
By registering component related functions to the pointers,
we can easily manage them within a for-loop and simplify the
logic of clock control significantly.
Reviewed-by: CK Hu <[email protected]>
Signed-off-by: Hsiao Chien Sung <[email protected]>
---
.../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 111 +++++++-----------
1 file changed, 44 insertions(+), 67 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
index 8a52d1301e04..84133303a6ec 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
@@ -54,6 +54,7 @@ struct ovl_adaptor_comp_match {
enum mtk_ovl_adaptor_comp_type type;
enum mtk_ddp_comp_id comp_id;
int alias_id;
+ const struct mtk_ddp_comp_funcs *funcs;
};
struct mtk_disp_ovl_adaptor {
@@ -68,20 +69,35 @@ static const char * const private_comp_stem[OVL_ADAPTOR_TYPE_NUM] = {
[OVL_ADAPTOR_TYPE_MERGE] = "merge",
};
+static const struct mtk_ddp_comp_funcs _ethdr = {
+ .clk_enable = mtk_ethdr_clk_enable,
+ .clk_disable = mtk_ethdr_clk_disable,
+};
+
+static const struct mtk_ddp_comp_funcs _merge = {
+ .clk_enable = mtk_merge_clk_enable,
+ .clk_disable = mtk_merge_clk_disable,
+};
+
+static const struct mtk_ddp_comp_funcs _rdma = {
+ .clk_enable = mtk_mdp_rdma_clk_enable,
+ .clk_disable = mtk_mdp_rdma_clk_disable,
+};
+
static const struct ovl_adaptor_comp_match comp_matches[OVL_ADAPTOR_ID_MAX] = {
- [OVL_ADAPTOR_ETHDR0] = { OVL_ADAPTOR_TYPE_ETHDR, DDP_COMPONENT_ETHDR_MIXER, 0 },
- [OVL_ADAPTOR_MDP_RDMA0] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA0, 0 },
- [OVL_ADAPTOR_MDP_RDMA1] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA1, 1 },
- [OVL_ADAPTOR_MDP_RDMA2] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA2, 2 },
- [OVL_ADAPTOR_MDP_RDMA3] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA3, 3 },
- [OVL_ADAPTOR_MDP_RDMA4] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA4, 4 },
- [OVL_ADAPTOR_MDP_RDMA5] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA5, 5 },
- [OVL_ADAPTOR_MDP_RDMA6] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA6, 6 },
- [OVL_ADAPTOR_MDP_RDMA7] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA7, 7 },
- [OVL_ADAPTOR_MERGE0] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE1, 1 },
- [OVL_ADAPTOR_MERGE1] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE2, 2 },
- [OVL_ADAPTOR_MERGE2] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE3, 3 },
- [OVL_ADAPTOR_MERGE3] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE4, 4 },
+ [OVL_ADAPTOR_ETHDR0] = { OVL_ADAPTOR_TYPE_ETHDR, DDP_COMPONENT_ETHDR_MIXER, 0, &_ethdr },
+ [OVL_ADAPTOR_MDP_RDMA0] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA0, 0, &_rdma },
+ [OVL_ADAPTOR_MDP_RDMA1] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA1, 1, &_rdma },
+ [OVL_ADAPTOR_MDP_RDMA2] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA2, 2, &_rdma },
+ [OVL_ADAPTOR_MDP_RDMA3] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA3, 3, &_rdma },
+ [OVL_ADAPTOR_MDP_RDMA4] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA4, 4, &_rdma },
+ [OVL_ADAPTOR_MDP_RDMA5] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA5, 5, &_rdma },
+ [OVL_ADAPTOR_MDP_RDMA6] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA6, 6, &_rdma },
+ [OVL_ADAPTOR_MDP_RDMA7] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA7, 7, &_rdma },
+ [OVL_ADAPTOR_MERGE0] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE1, 1, &_merge },
+ [OVL_ADAPTOR_MERGE1] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE2, 2, &_merge },
+ [OVL_ADAPTOR_MERGE2] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE3, 3, &_merge },
+ [OVL_ADAPTOR_MERGE3] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE4, 4, &_merge },
};
void mtk_ovl_adaptor_layer_config(struct device *dev, unsigned int idx,
@@ -187,73 +203,34 @@ void mtk_ovl_adaptor_stop(struct device *dev)
int mtk_ovl_adaptor_clk_enable(struct device *dev)
{
- struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
- struct device *comp;
- int ret;
int i;
-
- for (i = 0; i < OVL_ADAPTOR_MERGE0; i++) {
- comp = ovl_adaptor->ovl_adaptor_comp[i];
- ret = pm_runtime_get_sync(comp);
- if (ret < 0) {
- dev_err(dev, "Failed to enable power domain %d, err %d\n", i, ret);
- goto pwr_err;
- }
- }
+ int ret;
+ struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
for (i = 0; i < OVL_ADAPTOR_ID_MAX; i++) {
- comp = ovl_adaptor->ovl_adaptor_comp[i];
-
- if (i < OVL_ADAPTOR_MERGE0)
- ret = mtk_mdp_rdma_clk_enable(comp);
- else if (i < OVL_ADAPTOR_ETHDR0)
- ret = mtk_merge_clk_enable(comp);
- else
- ret = mtk_ethdr_clk_enable(comp);
+ dev = ovl_adaptor->ovl_adaptor_comp[i];
+ if (!dev)
+ continue;
+ ret = comp_matches[i].funcs->clk_enable(dev);
if (ret) {
- dev_err(dev, "Failed to enable clock %d, err %d\n", i, ret);
- goto clk_err;
+ while (--i >= 0)
+ comp_matches[i].funcs->clk_disable(dev);
+ return ret;
}
}
-
- return ret;
-
-clk_err:
- while (--i >= 0) {
- comp = ovl_adaptor->ovl_adaptor_comp[i];
- if (i < OVL_ADAPTOR_MERGE0)
- mtk_mdp_rdma_clk_disable(comp);
- else if (i < OVL_ADAPTOR_ETHDR0)
- mtk_merge_clk_disable(comp);
- else
- mtk_ethdr_clk_disable(comp);
- }
- i = OVL_ADAPTOR_MERGE0;
-
-pwr_err:
- while (--i >= 0)
- pm_runtime_put(ovl_adaptor->ovl_adaptor_comp[i]);
-
- return ret;
+ return 0;
}
void mtk_ovl_adaptor_clk_disable(struct device *dev)
{
- struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
- struct device *comp;
int i;
+ struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
for (i = 0; i < OVL_ADAPTOR_ID_MAX; i++) {
- comp = ovl_adaptor->ovl_adaptor_comp[i];
-
- if (i < OVL_ADAPTOR_MERGE0) {
- mtk_mdp_rdma_clk_disable(comp);
- pm_runtime_put(comp);
- } else if (i < OVL_ADAPTOR_ETHDR0) {
- mtk_merge_clk_disable(comp);
- } else {
- mtk_ethdr_clk_disable(comp);
- }
+ dev = ovl_adaptor->ovl_adaptor_comp[i];
+ if (!dev)
+ continue;
+ comp_matches[i].funcs->clk_disable(dev);
}
}
--
2.18.0
Different from OVL, OVL adaptor is a pseudo device so we didn't
define it in the device tree, consequently, pm_runtime_resume_and_get()
called by .atomic_enable() powers on no device in OVL adaptor and
leads to power outage in the corresponding IOMMU.
To resolve the issue, we implement a function to power on the RDMAs
in OVL adaptor, and the system will make sure the IOMMU is powered on
as well because of the device link (iommus) in the RDMA nodes in DTS.
Fixes: 5db12f5d843b ("media: drm/mediatek: Add pm runtime support for ovl and rdma")
Signed-off-by: Hsiao Chien Sung <[email protected]>
---
drivers/gpu/drm/mediatek/mtk_disp_drv.h | 1 +
.../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 49 +++++++++++++++++++
drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 9 ++++
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 1 +
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 9 ++++
5 files changed, 69 insertions(+)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index 45b30a2fe11a..971d64261fb9 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -107,6 +107,7 @@ void mtk_ovl_adaptor_connect(struct device *dev, struct device *mmsys_dev,
unsigned int next);
void mtk_ovl_adaptor_disconnect(struct device *dev, struct device *mmsys_dev,
unsigned int next);
+int mtk_ovl_adaptor_power_on(struct device *dev);
int mtk_ovl_adaptor_clk_enable(struct device *dev);
void mtk_ovl_adaptor_clk_disable(struct device *dev);
void mtk_ovl_adaptor_config(struct device *dev, unsigned int w,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
index c326a658dc63..ae3b6ba655b1 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
@@ -242,6 +242,55 @@ void mtk_ovl_adaptor_stop(struct device *dev)
}
}
+/**
+ * mtk_ovl_adaptor_power_on - Power on devices in OVL adaptor
+ * @dev: device to be powered on
+ *
+ * Different from OVL, OVL adaptor is a pseudo device so
+ * we didn't define it in the device tree, pm_runtime_resume_and_get()
+ * called by .atomic_enable() power on no device in OVL adaptor,
+ * we have to implement a function to do the job instead.
+ *
+ * returns:
+ * zero on success, errno on failure.
+ */
+int mtk_ovl_adaptor_power_on(struct device *dev)
+{
+ int i, ret;
+ struct device *comp;
+ struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
+
+ for (i = 0; i < OVL_ADAPTOR_ID_MAX; i++) {
+ comp = ovl_adaptor->ovl_adaptor_comp[i];
+
+ if (!comp)
+ continue;
+
+ if (comp_matches[i].type != OVL_ADAPTOR_TYPE_MDP_RDMA)
+ continue;
+
+ ret = pm_runtime_resume_and_get(comp);
+ if (ret < 0) {
+ dev_err(dev, "Failed to power on comp(%u): %d\n", i, ret);
+ goto error;
+ }
+ }
+ return 0;
+error:
+ while (--i >= 0) {
+ comp = ovl_adaptor->ovl_adaptor_comp[i];
+
+ if (!comp)
+ continue;
+
+ if (comp_matches[i].type != OVL_ADAPTOR_TYPE_MDP_RDMA)
+ continue;
+
+ pm_runtime_put(comp);
+ }
+ return ret;
+}
+
int mtk_ovl_adaptor_clk_enable(struct device *dev)
{
int i;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index b6fa4ad2f94d..5bd62027190b 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -364,6 +364,15 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
return ret;
}
+ for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
+ ret = mtk_ddp_comp_power_on(mtk_crtc->ddp_comp[i]);
+ if (ret) {
+ DRM_ERROR("Failed to power on %s: %d\n",
+ dev_name(mtk_crtc->ddp_comp[i]->dev), ret);
+ return ret;
+ }
+ }
+
ret = mtk_mutex_prepare(mtk_crtc->mutex);
if (ret < 0) {
DRM_ERROR("Failed to enable mutex clock: %d\n", ret);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
index 771f4e173353..e39860f2be78 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
@@ -394,6 +394,7 @@ static const struct mtk_ddp_comp_funcs ddp_ufoe = {
};
static const struct mtk_ddp_comp_funcs ddp_ovl_adaptor = {
+ .power_on = mtk_ovl_adaptor_power_on,
.clk_enable = mtk_ovl_adaptor_clk_enable,
.clk_disable = mtk_ovl_adaptor_clk_disable,
.config = mtk_ovl_adaptor_config,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
index febcaeef16a1..4fef283f17d2 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
@@ -46,6 +46,7 @@ enum mtk_ddp_comp_type {
struct mtk_ddp_comp;
struct cmdq_pkt;
struct mtk_ddp_comp_funcs {
+ int (*power_on)(struct device *dev);
int (*clk_enable)(struct device *dev);
void (*clk_disable)(struct device *dev);
void (*config)(struct device *dev, unsigned int w,
@@ -89,6 +90,14 @@ struct mtk_ddp_comp {
const struct mtk_ddp_comp_funcs *funcs;
};
+static inline int mtk_ddp_comp_power_on(struct mtk_ddp_comp *comp)
+{
+ if (comp->funcs && comp->funcs->power_on)
+ return comp->funcs->power_on(comp->dev);
+
+ return 0;
+}
+
static inline int mtk_ddp_comp_clk_enable(struct mtk_ddp_comp *comp)
{
if (comp->funcs && comp->funcs->clk_enable)
--
2.18.0
Padding is a new display module on MT8188, it provides ability
to add pixels to width and height of a layer with specified colors.
Due to hardware design, Mixer in VDOSYS1 requires width of a layer
to be 2-pixel-align, or 4-pixel-align when ETHDR is enabled,
we need Padding to deal with odd width.
Signed-off-by: Hsiao Chien Sung <[email protected]>
---
drivers/gpu/drm/mediatek/Makefile | 3 +-
drivers/gpu/drm/mediatek/mtk_disp_drv.h | 3 +
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 +
drivers/gpu/drm/mediatek/mtk_drm_drv.h | 2 +-
drivers/gpu/drm/mediatek/mtk_padding.c | 206 ++++++++++++++++++++++++
5 files changed, 213 insertions(+), 2 deletions(-)
create mode 100644 drivers/gpu/drm/mediatek/mtk_padding.c
diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index d4d193f60271..5e4436403b8d 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -16,7 +16,8 @@ mediatek-drm-y := mtk_disp_aal.o \
mtk_dsi.o \
mtk_dpi.o \
mtk_ethdr.o \
- mtk_mdp_rdma.o
+ mtk_mdp_rdma.o \
+ mtk_padding.o
obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index 2254038519e1..f9fdb1268aa5 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -157,4 +157,7 @@ void mtk_mdp_rdma_config(struct device *dev, struct mtk_mdp_rdma_cfg *cfg,
const u32 *mtk_mdp_rdma_get_formats(struct device *dev);
size_t mtk_mdp_rdma_get_num_formats(struct device *dev);
+int mtk_padding_clk_enable(struct device *dev);
+void mtk_padding_clk_disable(struct device *dev);
+void mtk_padding_config(struct device *dev, struct cmdq_pkt *cmdq_pkt);
#endif
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 93552d76b6e7..cde69f39a066 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -973,6 +973,7 @@ static struct platform_driver * const mtk_drm_drivers[] = {
&mtk_dsi_driver,
&mtk_ethdr_driver,
&mtk_mdp_rdma_driver,
+ &mtk_padding_driver,
};
static int __init mtk_drm_init(void)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index eb2fd45941f0..562f2db47add 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -64,5 +64,5 @@ extern struct platform_driver mtk_dpi_driver;
extern struct platform_driver mtk_dsi_driver;
extern struct platform_driver mtk_ethdr_driver;
extern struct platform_driver mtk_mdp_rdma_driver;
-
+extern struct platform_driver mtk_padding_driver;
#endif /* MTK_DRM_DRV_H */
diff --git a/drivers/gpu/drm/mediatek/mtk_padding.c b/drivers/gpu/drm/mediatek/mtk_padding.c
new file mode 100644
index 000000000000..2a29a5fa0a68
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_padding.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/soc/mediatek/mtk-cmdq.h>
+
+#include "mtk_disp_drv.h"
+#include "mtk_drm_crtc.h"
+#include "mtk_drm_ddp_comp.h"
+
+#define PADDING_CONTROL_REG 0x00
+#define PADDING_BYPASS BIT(0)
+#define PADDING_ENABLE BIT(1)
+#define PADDING_PIC_SIZE_REG 0x04
+#define PADDING_H_REG 0x08 /* horizontal */
+#define PADDING_V_REG 0x0c /* vertical */
+#define PADDING_COLOR_REG 0x10
+
+#define PADDING_PIC_SIZE(w, h) ( \
+ ((w) & GENMASK(15, 0)) | \
+ (((h) & GENMASK(15, 0)) >> 16) \
+)
+
+#define PADDING_H(right) (((right) & GENMASK(12, 0)) >> 16)
+
+#define PADDING_V(bottom) (((bottom) & GENMASK(12, 0)) >> 16)
+
+/* 10-bit RGB without alpha */
+#define PADDING_COLOR(r, g, b) ( \
+ ((r) & GENMASK(9, 0)) << 22 | \
+ ((g) & GENMASK(9, 0)) << 12 | \
+ ((b) & GENMASK(9, 0)) << 2 \
+)
+
+/**
+ * struct mtk_padding - basic information of Padding
+ * @clk: Clock of the module
+ * @reg: Virtual address of the Padding for CPU to access
+ * @cmdq_reg: CMDQ setting of the Padding
+ *
+ * Every Padding should have different clock source, register base, and
+ * CMDQ settings, we stored these differences all together.
+ */
+struct mtk_padding {
+ struct clk *clk;
+ void __iomem *reg;
+ struct cmdq_client_reg cmdq_reg;
+};
+
+int mtk_padding_clk_enable(struct device *dev)
+{
+ struct mtk_padding *padding = dev_get_drvdata(dev);
+
+ return clk_prepare_enable(padding->clk);
+}
+
+void mtk_padding_clk_disable(struct device *dev)
+{
+ struct mtk_padding *padding = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(padding->clk);
+}
+
+void mtk_padding_start(struct device *dev)
+{
+ struct mtk_padding *padding = dev_get_drvdata(dev);
+
+ writel(PADDING_ENABLE | PADDING_BYPASS,
+ padding->reg + PADDING_CONTROL_REG);
+
+ /*
+ * notice that even the padding is in bypass mode,
+ * all the settings must be cleared to 0 or
+ * undefined behaviors could happen
+ */
+ writel(0, padding->reg + PADDING_PIC_SIZE_REG);
+ writel(0, padding->reg + PADDING_H_REG);
+ writel(0, padding->reg + PADDING_V_REG);
+ writel(0, padding->reg + PADDING_COLOR_REG);
+}
+
+void mtk_padding_stop(struct device *dev)
+{
+ struct mtk_padding *padding = dev_get_drvdata(dev);
+
+ writel_relaxed(0, padding->reg + PADDING_CONTROL_REG);
+}
+
+void mtk_padding_config(struct device *dev, struct cmdq_pkt *cmdq_pkt,
+ u32 width, u32 height, u32 right, u32 bottom, u32 color)
+{
+ bool bypass = true;
+ struct mtk_padding *padding = dev_get_drvdata(dev);
+
+ if (width | height | right | bottom | color)
+ bypass = false;
+
+ mtk_ddp_write_mask(cmdq_pkt, bypass,
+ &padding->cmdq_reg, padding->reg,
+ PADDING_CONTROL_REG, PADDING_BYPASS);
+
+ mtk_ddp_write_mask(cmdq_pkt, PADDING_PIC_SIZE(width, height),
+ &padding->cmdq_reg, padding->reg,
+ PADDING_PIC_SIZE_REG, GENMASK(31, 0));
+
+ mtk_ddp_write_mask(cmdq_pkt, PADDING_H(right),
+ &padding->cmdq_reg, padding->reg,
+ PADDING_H_REG, GENMASK(31, 0));
+
+ mtk_ddp_write_mask(cmdq_pkt, PADDING_V(bottom),
+ &padding->cmdq_reg, padding->reg,
+ PADDING_V_REG, GENMASK(31, 0));
+
+ mtk_ddp_write_mask(cmdq_pkt, PADDING_V(bottom),
+ &padding->cmdq_reg, padding->reg,
+ PADDING_V_REG, GENMASK(31, 0));
+}
+
+static int mtk_padding_bind(struct device *dev, struct device *master, void *data)
+{
+ return 0;
+}
+
+static void mtk_padding_unbind(struct device *dev, struct device *master, void *data)
+{
+}
+
+static const struct component_ops mtk_padding_component_ops = {
+ .bind = mtk_padding_bind,
+ .unbind = mtk_padding_unbind,
+};
+
+static int mtk_padding_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mtk_padding *priv;
+ struct resource *res;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(priv->clk)) {
+ dev_err(dev, "failed to get clk\n");
+ return PTR_ERR(priv->clk);
+ }
+
+ priv->reg = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(priv->reg)) {
+ dev_err(dev, "failed to do ioremap\n");
+ return PTR_ERR(priv->reg);
+ }
+
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+ ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
+ if (ret) {
+ dev_err(dev, "failed to get gce client reg\n");
+ return ret;
+ }
+#endif
+
+ platform_set_drvdata(pdev, priv);
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return ret;
+
+ ret = component_add(dev, &mtk_padding_component_ops);
+ if (ret) {
+ pm_runtime_disable(dev);
+ return dev_err_probe(dev, ret, "failed to add component\n");
+ }
+
+ return 0;
+}
+
+static int mtk_padding_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &mtk_padding_component_ops);
+ return 0;
+}
+
+static const struct of_device_id mtk_padding_driver_dt_match[] = {
+ { .compatible = "mediatek,mt8188-padding" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mtk_padding_driver_dt_match);
+
+struct platform_driver mtk_padding_driver = {
+ .probe = mtk_padding_probe,
+ .remove = mtk_padding_remove,
+ .driver = {
+ .name = "mediatek-padding",
+ .owner = THIS_MODULE,
+ .of_match_table = mtk_padding_driver_dt_match,
+ },
+};
--
2.18.0
Add component ID to component match structure so we can
configure them with a for-loop.
The main reason we do such code refactoring is that
there is a new hardware component called "Padding" since
MT8188, while MT8195 doesn't have this module, we can't
use the original logic to manage the components.
While MT8195 does not define Padding in the device tree,
the corresponding components will be NULL and being skipped
by the functions.
Reviewed-by: CK Hu <[email protected]>
Signed-off-by: Hsiao Chien Sung <[email protected]>
---
.../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 69 ++++++++-----------
1 file changed, 30 insertions(+), 39 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
index 72758e41b1e6..8a52d1301e04 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
@@ -52,6 +52,7 @@ enum mtk_ovl_adaptor_comp_id {
struct ovl_adaptor_comp_match {
enum mtk_ovl_adaptor_comp_type type;
+ enum mtk_ddp_comp_id comp_id;
int alias_id;
};
@@ -68,19 +69,19 @@ static const char * const private_comp_stem[OVL_ADAPTOR_TYPE_NUM] = {
};
static const struct ovl_adaptor_comp_match comp_matches[OVL_ADAPTOR_ID_MAX] = {
- [OVL_ADAPTOR_ETHDR0] = { OVL_ADAPTOR_TYPE_ETHDR, 0 },
- [OVL_ADAPTOR_MDP_RDMA0] = { OVL_ADAPTOR_TYPE_MDP_RDMA, 0 },
- [OVL_ADAPTOR_MDP_RDMA1] = { OVL_ADAPTOR_TYPE_MDP_RDMA, 1 },
- [OVL_ADAPTOR_MDP_RDMA2] = { OVL_ADAPTOR_TYPE_MDP_RDMA, 2 },
- [OVL_ADAPTOR_MDP_RDMA3] = { OVL_ADAPTOR_TYPE_MDP_RDMA, 3 },
- [OVL_ADAPTOR_MDP_RDMA4] = { OVL_ADAPTOR_TYPE_MDP_RDMA, 4 },
- [OVL_ADAPTOR_MDP_RDMA5] = { OVL_ADAPTOR_TYPE_MDP_RDMA, 5 },
- [OVL_ADAPTOR_MDP_RDMA6] = { OVL_ADAPTOR_TYPE_MDP_RDMA, 6 },
- [OVL_ADAPTOR_MDP_RDMA7] = { OVL_ADAPTOR_TYPE_MDP_RDMA, 7 },
- [OVL_ADAPTOR_MERGE0] = { OVL_ADAPTOR_TYPE_MERGE, 1 },
- [OVL_ADAPTOR_MERGE1] = { OVL_ADAPTOR_TYPE_MERGE, 2 },
- [OVL_ADAPTOR_MERGE2] = { OVL_ADAPTOR_TYPE_MERGE, 3 },
- [OVL_ADAPTOR_MERGE3] = { OVL_ADAPTOR_TYPE_MERGE, 4 },
+ [OVL_ADAPTOR_ETHDR0] = { OVL_ADAPTOR_TYPE_ETHDR, DDP_COMPONENT_ETHDR_MIXER, 0 },
+ [OVL_ADAPTOR_MDP_RDMA0] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA0, 0 },
+ [OVL_ADAPTOR_MDP_RDMA1] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA1, 1 },
+ [OVL_ADAPTOR_MDP_RDMA2] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA2, 2 },
+ [OVL_ADAPTOR_MDP_RDMA3] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA3, 3 },
+ [OVL_ADAPTOR_MDP_RDMA4] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA4, 4 },
+ [OVL_ADAPTOR_MDP_RDMA5] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA5, 5 },
+ [OVL_ADAPTOR_MDP_RDMA6] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA6, 6 },
+ [OVL_ADAPTOR_MDP_RDMA7] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA7, 7 },
+ [OVL_ADAPTOR_MERGE0] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE1, 1 },
+ [OVL_ADAPTOR_MERGE1] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE2, 2 },
+ [OVL_ADAPTOR_MERGE2] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE3, 3 },
+ [OVL_ADAPTOR_MERGE3] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE4, 4 },
};
void mtk_ovl_adaptor_layer_config(struct device *dev, unsigned int idx,
@@ -314,36 +315,26 @@ size_t mtk_ovl_adaptor_get_num_formats(struct device *dev)
void mtk_ovl_adaptor_add_comp(struct device *dev, struct mtk_mutex *mutex)
{
- mtk_mutex_add_comp(mutex, DDP_COMPONENT_ETHDR_MIXER);
- mtk_mutex_add_comp(mutex, DDP_COMPONENT_MDP_RDMA0);
- mtk_mutex_add_comp(mutex, DDP_COMPONENT_MDP_RDMA1);
- mtk_mutex_add_comp(mutex, DDP_COMPONENT_MDP_RDMA2);
- mtk_mutex_add_comp(mutex, DDP_COMPONENT_MDP_RDMA3);
- mtk_mutex_add_comp(mutex, DDP_COMPONENT_MDP_RDMA4);
- mtk_mutex_add_comp(mutex, DDP_COMPONENT_MDP_RDMA5);
- mtk_mutex_add_comp(mutex, DDP_COMPONENT_MDP_RDMA6);
- mtk_mutex_add_comp(mutex, DDP_COMPONENT_MDP_RDMA7);
- mtk_mutex_add_comp(mutex, DDP_COMPONENT_MERGE1);
- mtk_mutex_add_comp(mutex, DDP_COMPONENT_MERGE2);
- mtk_mutex_add_comp(mutex, DDP_COMPONENT_MERGE3);
- mtk_mutex_add_comp(mutex, DDP_COMPONENT_MERGE4);
+ int i;
+ struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
+
+ for (i = 0; i < OVL_ADAPTOR_ID_MAX; i++) {
+ if (!ovl_adaptor->ovl_adaptor_comp[i])
+ continue;
+ mtk_mutex_add_comp(mutex, comp_matches[i].comp_id);
+ }
}
void mtk_ovl_adaptor_remove_comp(struct device *dev, struct mtk_mutex *mutex)
{
- mtk_mutex_remove_comp(mutex, DDP_COMPONENT_ETHDR_MIXER);
- mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MDP_RDMA0);
- mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MDP_RDMA1);
- mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MDP_RDMA2);
- mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MDP_RDMA3);
- mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MDP_RDMA4);
- mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MDP_RDMA5);
- mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MDP_RDMA6);
- mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MDP_RDMA7);
- mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MERGE1);
- mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MERGE2);
- mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MERGE3);
- mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MERGE4);
+ int i;
+ struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
+
+ for (i = 0; i < OVL_ADAPTOR_ID_MAX; i++) {
+ if (!ovl_adaptor->ovl_adaptor_comp[i])
+ continue;
+ mtk_mutex_remove_comp(mutex, comp_matches[i].comp_id);
+ }
}
void mtk_ovl_adaptor_connect(struct device *dev, struct device *mmsys_dev, unsigned int next)
--
2.18.0
Return the result of clk_prepare_enable() instead of
always returns 0.
Fixes: f8946e2b6bb2 ("drm/mediatek: Add display MDP RDMA support for MT8195")
Signed-off-by: Hsiao Chien Sung <[email protected]>
---
drivers/gpu/drm/mediatek/mtk_mdp_rdma.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c b/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c
index c3adaeefd551..c7233d0ac210 100644
--- a/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c
+++ b/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c
@@ -246,8 +246,7 @@ int mtk_mdp_rdma_clk_enable(struct device *dev)
{
struct mtk_mdp_rdma *rdma = dev_get_drvdata(dev);
- clk_prepare_enable(rdma->clk);
- return 0;
+ return clk_prepare_enable(rdma->clk);
}
void mtk_mdp_rdma_clk_disable(struct device *dev)
--
2.18.0
Hi, Hsiao-chien:
On Fri, 2023-10-06 at 15:38 +0800, Hsiao Chien Sung wrote:
> Padding is a new display module on MT8188, it provides ability
> to add pixels to width and height of a layer with specified colors.
>
> Due to hardware design, Mixer in VDOSYS1 requires width of a layer
> to be 2-pixel-align, or 4-pixel-align when ETHDR is enabled,
> we need Padding to deal with odd width.
>
> Signed-off-by: Hsiao Chien Sung <[email protected]>
> ---
> drivers/gpu/drm/mediatek/Makefile | 3 +-
> drivers/gpu/drm/mediatek/mtk_disp_drv.h | 3 +
> drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 +
> drivers/gpu/drm/mediatek/mtk_drm_drv.h | 2 +-
> drivers/gpu/drm/mediatek/mtk_padding.c | 206
> ++++++++++++++++++++++++
> 5 files changed, 213 insertions(+), 2 deletions(-)
> create mode 100644 drivers/gpu/drm/mediatek/mtk_padding.c
>
> diff --git a/drivers/gpu/drm/mediatek/Makefile
> b/drivers/gpu/drm/mediatek/Makefile
> index d4d193f60271..5e4436403b8d 100644
> --- a/drivers/gpu/drm/mediatek/Makefile
> +++ b/drivers/gpu/drm/mediatek/Makefile
> @@ -16,7 +16,8 @@ mediatek-drm-y := mtk_disp_aal.o \
> mtk_dsi.o \
> mtk_dpi.o \
> mtk_ethdr.o \
> - mtk_mdp_rdma.o
> + mtk_mdp_rdma.o \
> + mtk_padding.o
>
> obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> index 2254038519e1..f9fdb1268aa5 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> @@ -157,4 +157,7 @@ void mtk_mdp_rdma_config(struct device *dev,
> struct mtk_mdp_rdma_cfg *cfg,
> const u32 *mtk_mdp_rdma_get_formats(struct device *dev);
> size_t mtk_mdp_rdma_get_num_formats(struct device *dev);
>
> +int mtk_padding_clk_enable(struct device *dev);
> +void mtk_padding_clk_disable(struct device *dev);
> +void mtk_padding_config(struct device *dev, struct cmdq_pkt
> *cmdq_pkt);
> #endif
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index 93552d76b6e7..cde69f39a066 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -973,6 +973,7 @@ static struct platform_driver * const
> mtk_drm_drivers[] = {
> &mtk_dsi_driver,
> &mtk_ethdr_driver,
> &mtk_mdp_rdma_driver,
> + &mtk_padding_driver,
> };
>
> static int __init mtk_drm_init(void)
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> index eb2fd45941f0..562f2db47add 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> @@ -64,5 +64,5 @@ extern struct platform_driver mtk_dpi_driver;
> extern struct platform_driver mtk_dsi_driver;
> extern struct platform_driver mtk_ethdr_driver;
> extern struct platform_driver mtk_mdp_rdma_driver;
> -
> +extern struct platform_driver mtk_padding_driver;
> #endif /* MTK_DRM_DRV_H */
> diff --git a/drivers/gpu/drm/mediatek/mtk_padding.c
> b/drivers/gpu/drm/mediatek/mtk_padding.c
> new file mode 100644
> index 000000000000..2a29a5fa0a68
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_padding.c
> @@ -0,0 +1,206 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2023 MediaTek Inc.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/soc/mediatek/mtk-cmdq.h>
> +
> +#include "mtk_disp_drv.h"
> +#include "mtk_drm_crtc.h"
> +#include "mtk_drm_ddp_comp.h"
> +
> +#define PADDING_CONTROL_REG 0x00
> +#define PADDING_BYPASS BIT(0)
> +#define PADDING_ENABLE BIT(1)
> +#define PADDING_PIC_SIZE_REG 0x04
> +#define PADDING_H_REG 0x08 /* horizontal */
> +#define PADDING_V_REG 0x0c /* vertical */
> +#define PADDING_COLOR_REG 0x10
> +
> +#define PADDING_PIC_SIZE(w, h) ( \
> + ((w) & GENMASK(15, 0)) | \
> + (((h) & GENMASK(15, 0)) >> 16) \
> +)
> +
> +#define PADDING_H(right) (((right) & GENMASK(12, 0)) >> 16)
> +
> +#define PADDING_V(bottom) (((bottom) & GENMASK(12, 0)) >> 16)
> +
> +/* 10-bit RGB without alpha */
> +#define PADDING_COLOR(r, g, b) ( \
> + ((r) & GENMASK(9, 0)) << 22 | \
> + ((g) & GENMASK(9, 0)) << 12 | \
> + ((b) & GENMASK(9, 0)) << 2 \
> +)
> +
> +/**
> + * struct mtk_padding - basic information of Padding
> + * @clk: Clock of the module
> + * @reg: Virtual address of the Padding for CPU to access
> + * @cmdq_reg: CMDQ setting of the Padding
> + *
> + * Every Padding should have different clock source, register base,
> and
> + * CMDQ settings, we stored these differences all together.
> + */
> +struct mtk_padding {
> + struct clk *clk;
> + void __iomem *reg;
> + struct cmdq_client_reg cmdq_reg;
> +};
> +
> +int mtk_padding_clk_enable(struct device *dev)
> +{
> + struct mtk_padding *padding = dev_get_drvdata(dev);
> +
> + return clk_prepare_enable(padding->clk);
> +}
> +
> +void mtk_padding_clk_disable(struct device *dev)
> +{
> + struct mtk_padding *padding = dev_get_drvdata(dev);
> +
> + clk_disable_unprepare(padding->clk);
> +}
> +
> +void mtk_padding_start(struct device *dev)
> +{
> + struct mtk_padding *padding = dev_get_drvdata(dev);
> +
> + writel(PADDING_ENABLE | PADDING_BYPASS,
> + padding->reg + PADDING_CONTROL_REG);
> +
> + /*
> + * notice that even the padding is in bypass mode,
> + * all the settings must be cleared to 0 or
> + * undefined behaviors could happen
> + */
> + writel(0, padding->reg + PADDING_PIC_SIZE_REG);
> + writel(0, padding->reg + PADDING_H_REG);
> + writel(0, padding->reg + PADDING_V_REG);
> + writel(0, padding->reg + PADDING_COLOR_REG);
> +}
> +
> +void mtk_padding_stop(struct device *dev)
> +{
> + struct mtk_padding *padding = dev_get_drvdata(dev);
> +
> + writel_relaxed(0, padding->reg + PADDING_CONTROL_REG);
> +}
> +
> +void mtk_padding_config(struct device *dev, struct cmdq_pkt
> *cmdq_pkt,
> + u32 width, u32 height, u32 right, u32 bottom,
> u32 color)
mtk_padding_config() is useless, so drop it.
Regards,
CK
> +{
> + bool bypass = true;
> + struct mtk_padding *padding = dev_get_drvdata(dev);
> +
> + if (width | height | right | bottom | color)
> + bypass = false;
> +
> + mtk_ddp_write_mask(cmdq_pkt, bypass,
> + &padding->cmdq_reg, padding->reg,
> + PADDING_CONTROL_REG, PADDING_BYPASS);
> +
> + mtk_ddp_write_mask(cmdq_pkt, PADDING_PIC_SIZE(width, height),
> + &padding->cmdq_reg, padding->reg,
> + PADDING_PIC_SIZE_REG, GENMASK(31, 0));
> +
> + mtk_ddp_write_mask(cmdq_pkt, PADDING_H(right),
> + &padding->cmdq_reg, padding->reg,
> + PADDING_H_REG, GENMASK(31, 0));
> +
> + mtk_ddp_write_mask(cmdq_pkt, PADDING_V(bottom),
> + &padding->cmdq_reg, padding->reg,
> + PADDING_V_REG, GENMASK(31, 0));
> +
> + mtk_ddp_write_mask(cmdq_pkt, PADDING_V(bottom),
> + &padding->cmdq_reg, padding->reg,
> + PADDING_V_REG, GENMASK(31, 0));
> +}
> +
> +static int mtk_padding_bind(struct device *dev, struct device
> *master, void *data)
> +{
> + return 0;
> +}
> +
> +static void mtk_padding_unbind(struct device *dev, struct device
> *master, void *data)
> +{
> +}
> +
> +static const struct component_ops mtk_padding_component_ops = {
> + .bind = mtk_padding_bind,
> + .unbind = mtk_padding_unbind,
> +};
> +
> +static int mtk_padding_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct mtk_padding *priv;
> + struct resource *res;
> + int ret;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + priv->clk = devm_clk_get(dev, NULL);
> + if (IS_ERR(priv->clk)) {
> + dev_err(dev, "failed to get clk\n");
> + return PTR_ERR(priv->clk);
> + }
> +
> + priv->reg = devm_platform_get_and_ioremap_resource(pdev, 0,
> &res);
> + if (IS_ERR(priv->reg)) {
> + dev_err(dev, "failed to do ioremap\n");
> + return PTR_ERR(priv->reg);
> + }
> +
> +#if IS_REACHABLE(CONFIG_MTK_CMDQ)
> + ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
> + if (ret) {
> + dev_err(dev, "failed to get gce client reg\n");
> + return ret;
> + }
> +#endif
> +
> + platform_set_drvdata(pdev, priv);
> +
> + ret = devm_pm_runtime_enable(dev);
> + if (ret)
> + return ret;
> +
> + ret = component_add(dev, &mtk_padding_component_ops);
> + if (ret) {
> + pm_runtime_disable(dev);
> + return dev_err_probe(dev, ret, "failed to add
> component\n");
> + }
> +
> + return 0;
> +}
> +
> +static int mtk_padding_remove(struct platform_device *pdev)
> +{
> + component_del(&pdev->dev, &mtk_padding_component_ops);
> + return 0;
> +}
> +
> +static const struct of_device_id mtk_padding_driver_dt_match[] = {
> + { .compatible = "mediatek,mt8188-padding" },
> + { /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, mtk_padding_driver_dt_match);
> +
> +struct platform_driver mtk_padding_driver = {
> + .probe = mtk_padding_probe,
> + .remove = mtk_padding_remove,
> + .driver = {
> + .name = "mediatek-padding",
> + .owner = THIS_MODULE,
> + .of_match_table = mtk_padding_driver_dt_match,
> + },
> +};
Hi, Hsiao-chien:
On Fri, 2023-10-06 at 15:38 +0800, Hsiao Chien Sung wrote:
> Return the result of clk_prepare_enable() instead of
> always returns 0.
Reviewed-by: CK Hu <[email protected]>
>
> Fixes: f8946e2b6bb2 ("drm/mediatek: Add display MDP RDMA support for
> MT8195")
>
> Signed-off-by: Hsiao Chien Sung <[email protected]>
> ---
> drivers/gpu/drm/mediatek/mtk_mdp_rdma.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c
> b/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c
> index c3adaeefd551..c7233d0ac210 100644
> --- a/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c
> +++ b/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c
> @@ -246,8 +246,7 @@ int mtk_mdp_rdma_clk_enable(struct device *dev)
> {
> struct mtk_mdp_rdma *rdma = dev_get_drvdata(dev);
>
> - clk_prepare_enable(rdma->clk);
> - return 0;
> + return clk_prepare_enable(rdma->clk);
> }
>
> void mtk_mdp_rdma_clk_disable(struct device *dev)
Hi, Hsiao-chien:
On Fri, 2023-10-06 at 15:38 +0800, Hsiao Chien Sung wrote:
> Different from OVL, OVL adaptor is a pseudo device so we didn't
> define it in the device tree, consequently,
> pm_runtime_resume_and_get()
> called by .atomic_enable() powers on no device in OVL adaptor and
> leads to power outage in the corresponding IOMMU.
>
> To resolve the issue, we implement a function to power on the RDMAs
> in OVL adaptor, and the system will make sure the IOMMU is powered on
> as well because of the device link (iommus) in the RDMA nodes in DTS.
>
> Fixes: 5db12f5d843b ("media: drm/mediatek: Add pm runtime support for
> ovl and rdma")
>
> Signed-off-by: Hsiao Chien Sung <[email protected]>
> ---
> drivers/gpu/drm/mediatek/mtk_disp_drv.h | 1 +
> .../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 49
> +++++++++++++++++++
> drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 9 ++++
> drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 1 +
> drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 9 ++++
> 5 files changed, 69 insertions(+)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> index 45b30a2fe11a..971d64261fb9 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> @@ -107,6 +107,7 @@ void mtk_ovl_adaptor_connect(struct device *dev,
> struct device *mmsys_dev,
> unsigned int next);
> void mtk_ovl_adaptor_disconnect(struct device *dev, struct device
> *mmsys_dev,
> unsigned int next);
> +int mtk_ovl_adaptor_power_on(struct device *dev);
> int mtk_ovl_adaptor_clk_enable(struct device *dev);
> void mtk_ovl_adaptor_clk_disable(struct device *dev);
> void mtk_ovl_adaptor_config(struct device *dev, unsigned int w,
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
> b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
> index c326a658dc63..ae3b6ba655b1 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
> @@ -242,6 +242,55 @@ void mtk_ovl_adaptor_stop(struct device *dev)
> }
> }
>
> +/**
> + * mtk_ovl_adaptor_power_on - Power on devices in OVL adaptor
> + * @dev: device to be powered on
> + *
> + * Different from OVL, OVL adaptor is a pseudo device so
> + * we didn't define it in the device tree,
> pm_runtime_resume_and_get()
> + * called by .atomic_enable() power on no device in OVL adaptor,
> + * we have to implement a function to do the job instead.
> + *
> + * returns:
> + * zero on success, errno on failure.
> + */
> +int mtk_ovl_adaptor_power_on(struct device *dev)
> +{
> + int i, ret;
> + struct device *comp;
> + struct mtk_disp_ovl_adaptor *ovl_adaptor =
> dev_get_drvdata(dev);
> +
> + for (i = 0; i < OVL_ADAPTOR_ID_MAX; i++) {
> + comp = ovl_adaptor->ovl_adaptor_comp[i];
> +
> + if (!comp)
> + continue;
> +
> + if (comp_matches[i].type != OVL_ADAPTOR_TYPE_MDP_RDMA)
> + continue;
> +
> + ret = pm_runtime_resume_and_get(comp);
> + if (ret < 0) {
> + dev_err(dev, "Failed to power on comp(%u):
> %d\n", i, ret);
> + goto error;
> + }
> + }
> + return 0;
> +error:
> + while (--i >= 0) {
> + comp = ovl_adaptor->ovl_adaptor_comp[i];
> +
> + if (!comp)
> + continue;
> +
> + if (comp_matches[i].type != OVL_ADAPTOR_TYPE_MDP_RDMA)
> + continue;
> +
> + pm_runtime_put(comp);
> + }
> + return ret;
> +}
> +
> int mtk_ovl_adaptor_clk_enable(struct device *dev)
> {
> int i;
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> index b6fa4ad2f94d..5bd62027190b 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> @@ -364,6 +364,15 @@ static int mtk_crtc_ddp_hw_init(struct
> mtk_drm_crtc *mtk_crtc)
> return ret;
> }
>
> + for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
> + ret = mtk_ddp_comp_power_on(mtk_crtc->ddp_comp[i]);
> + if (ret) {
> + DRM_ERROR("Failed to power on %s: %d\n",
> + dev_name(mtk_crtc->ddp_comp[i]->dev),
> ret);
> + return ret;
> + }
> + }
I would like to replace below statement in mtk_drm_crtc_atomic_enable()
ret = pm_runtime_resume_and_get(comp-dev);
with
ret = mtk_ddp_comp_power_on(comp);
And define mtk_ddp_comp_power_on() as
static inline int mtk_ddp_comp_power_on(struct mtk_ddp_comp *comp)
{
if (comp->funcs && comp->funcs->power_on)
return comp->funcs->power_on(comp->dev);
else
return pm_runtime_resume_and_get(comp-dev);
}
And you should also define mtk_ddp_comp_power_off().
Regards,
CK
> +
> ret = mtk_mutex_prepare(mtk_crtc->mutex);
> if (ret < 0) {
> DRM_ERROR("Failed to enable mutex clock: %d\n", ret);
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
> b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
> index 771f4e173353..e39860f2be78 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
> @@ -394,6 +394,7 @@ static const struct mtk_ddp_comp_funcs ddp_ufoe =
> {
> };
>
> static const struct mtk_ddp_comp_funcs ddp_ovl_adaptor = {
> + .power_on = mtk_ovl_adaptor_power_on,
> .clk_enable = mtk_ovl_adaptor_clk_enable,
> .clk_disable = mtk_ovl_adaptor_clk_disable,
> .config = mtk_ovl_adaptor_config,
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
> b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
> index febcaeef16a1..4fef283f17d2 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
> @@ -46,6 +46,7 @@ enum mtk_ddp_comp_type {
> struct mtk_ddp_comp;
> struct cmdq_pkt;
> struct mtk_ddp_comp_funcs {
> + int (*power_on)(struct device *dev);
> int (*clk_enable)(struct device *dev);
> void (*clk_disable)(struct device *dev);
> void (*config)(struct device *dev, unsigned int w,
> @@ -89,6 +90,14 @@ struct mtk_ddp_comp {
> const struct mtk_ddp_comp_funcs *funcs;
> };
>
> +static inline int mtk_ddp_comp_power_on(struct mtk_ddp_comp *comp)
> +{
> + if (comp->funcs && comp->funcs->power_on)
> + return comp->funcs->power_on(comp->dev);
> +
> + return 0;
> +}
> +
> static inline int mtk_ddp_comp_clk_enable(struct mtk_ddp_comp *comp)
> {
> if (comp->funcs && comp->funcs->clk_enable)