From be7507bdd705bd28c8e6091e1717b4a53dbd7b8c Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 23 Feb 2021 15:50:57 -0600 Subject: [PATCH 01/13] dt-bindings: display: mediatek, dpi: Convert to use graph schema Update the mediatek,dpi binding to use the graph schema. Missed this one from the mass conversion since it's not part of drm-misc. Cc: Chun-Kuang Hu Cc: Philipp Zabel Cc: Matthias Brugger Cc: CK Hu Cc: Jitao shi Cc: dri-devel@lists.freedesktop.org Cc: linux-mediatek@lists.infradead.org Signed-off-by: Rob Herring Signed-off-by: Chun-Kuang Hu --- .../bindings/display/mediatek/mediatek,dpi.yaml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml index 6cdb734c91a9..eb84b53cabb1 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml @@ -50,15 +50,10 @@ properties: - const: sleep port: - type: object + $ref: /schemas/graph.yaml#/properties/port description: - Output port node with endpoint definitions as described in - Documentation/devicetree/bindings/graph.txt. This port should be connected - to the input port of an attached HDMI or LVDS encoder chip. - - properties: - endpoint: - type: object + Output port node. This port should be connected to the input port of an + attached HDMI or LVDS encoder chip. required: - compatible From c87d1c4b5b9a86454d928e68d6f1a437a95ed41c Mon Sep 17 00:00:00 2001 From: Jitao Shi Date: Mon, 1 Feb 2021 11:36:02 +0800 Subject: [PATCH 02/13] drm/mediatek: dsi: Use symbolized register definition For HSTX_CKLP_EN and DIS_EOT, use symbolized register definition instead of magic number. Signed-off-by: Jitao Shi Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_dsi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index a1ff152ef468..b91d7c3dd9ac 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -401,8 +401,11 @@ static void mtk_dsi_rxtx_control(struct mtk_dsi *dsi) break; } - tmp_reg |= (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) << 6; - tmp_reg |= (dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET) >> 3; + if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) + tmp_reg |= HSTX_CKLP_EN; + + if (!(dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET)) + tmp_reg |= DIS_EOT; writel(tmp_reg, dsi->regs + DSI_TXRX_CTRL); } From 8b2b99fd7931cee3c1fffe4f37bd67583384b505 Mon Sep 17 00:00:00 2001 From: Jitao Shi Date: Mon, 1 Feb 2021 11:36:03 +0800 Subject: [PATCH 03/13] drm/mediatek: dsi: Fine tune the line time caused by EOTp Enabling EoTp will make the line time larger, so the hfp and hbp should be reduced to keep line time. Signed-off-by: Jitao Shi Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_dsi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index b91d7c3dd9ac..1c6e612f7eef 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -481,6 +481,7 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi) timing->da_hs_zero + timing->da_hs_exit + 3; delta = dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST ? 18 : 12; + delta += dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET ? 2 : 0; horizontal_frontporch_byte = vm->hfront_porch * dsi_tmp_buf_bpp; horizontal_front_back_byte = horizontal_frontporch_byte + horizontal_backporch_byte; From 618655131894d14e59cec59481efc6b46ed747c8 Mon Sep 17 00:00:00 2001 From: Jitao Shi Date: Mon, 8 Feb 2021 09:42:21 +0800 Subject: [PATCH 04/13] dt-bindings: mediatek,dpi: add mt8192 to mediatek,dpi Add compatible "mediatek,mt8192-dpi" for the mt8192 dpi. Signed-off-by: Jitao Shi Acked-by: Rob Herring Signed-off-by: Chun-Kuang Hu --- .../devicetree/bindings/display/mediatek/mediatek,dpi.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml index eb84b53cabb1..dd2896a40ff0 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml @@ -22,6 +22,7 @@ properties: - mediatek,mt7623-dpi - mediatek,mt8173-dpi - mediatek,mt8183-dpi + - mediatek,mt8192-dpi reg: maxItems: 1 From 4accca4399cf73e3c97ef0695280afd1729bf60d Mon Sep 17 00:00:00 2001 From: Wang Qing Date: Sat, 13 Mar 2021 15:48:02 +0800 Subject: [PATCH 05/13] drm/mediatek: dpi: Delete redundant printing of return value platform_get_irq() has already checked and printed the return value, the printing here is nothing special, it is not necessary at all. Signed-off-by: Wang Qing Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_dpi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c index b05f900d9322..0ac49624b5dc 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi.c +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -751,10 +751,8 @@ static int mtk_dpi_probe(struct platform_device *pdev) } dpi->irq = platform_get_irq(pdev, 0); - if (dpi->irq <= 0) { - dev_err(dev, "Failed to get irq: %d\n", dpi->irq); + if (dpi->irq <= 0) return -EINVAL; - } ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, NULL, &dpi->next_bridge); From ee5ee188e2c2518c38337361b1d2825cf80fbaa0 Mon Sep 17 00:00:00 2001 From: tangchunyou Date: Wed, 17 Mar 2021 15:24:43 +0800 Subject: [PATCH 06/13] drm/mediatek: cec: Delete redundant printing of return value platform_get_irq() has already checked and printed the return value, the printing here is nothing special, it is not necessary at all. Signed-off-by: tangchunyou Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_cec.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_cec.c b/drivers/gpu/drm/mediatek/mtk_cec.c index cb29b649fcdb..332a4dfbdde7 100644 --- a/drivers/gpu/drm/mediatek/mtk_cec.c +++ b/drivers/gpu/drm/mediatek/mtk_cec.c @@ -208,10 +208,8 @@ static int mtk_cec_probe(struct platform_device *pdev) } cec->irq = platform_get_irq(pdev, 0); - if (cec->irq < 0) { - dev_err(dev, "Failed to get cec irq: %d\n", cec->irq); + if (cec->irq < 0) return cec->irq; - } ret = devm_request_threaded_irq(dev, cec->irq, NULL, mtk_cec_htplg_isr_thread, From 44b07120291c4b7a6722ccb7149f6b9d938cf5a2 Mon Sep 17 00:00:00 2001 From: Rex-BC Chen Date: Thu, 18 Mar 2021 13:40:55 +0800 Subject: [PATCH 07/13] drm/mediatek: dpi: Add check for max clock rate in mode_valid Add per-platform max clock rate check in mtk_dpi_bridge_mode_valid. Signed-off-by: Pi-Hsun Shih Signed-off-by: Rex-BC Chen Signed-off-by: Jitao Shi Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_dpi.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c index 0ac49624b5dc..07afbdd19ab1 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi.c +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -120,6 +120,7 @@ struct mtk_dpi_yc_limit { struct mtk_dpi_conf { unsigned int (*cal_factor)(int clock); u32 reg_h_fre_con; + u32 max_clock_khz; bool edge_sel_en; }; @@ -557,9 +558,23 @@ static void mtk_dpi_bridge_enable(struct drm_bridge *bridge) mtk_dpi_set_display_mode(dpi, &dpi->mode); } +static enum drm_mode_status +mtk_dpi_bridge_mode_valid(struct drm_bridge *bridge, + const struct drm_display_info *info, + const struct drm_display_mode *mode) +{ + struct mtk_dpi *dpi = bridge_to_dpi(bridge); + + if (mode->clock > dpi->conf->max_clock_khz) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + static const struct drm_bridge_funcs mtk_dpi_bridge_funcs = { .attach = mtk_dpi_bridge_attach, .mode_set = mtk_dpi_bridge_mode_set, + .mode_valid = mtk_dpi_bridge_mode_valid, .disable = mtk_dpi_bridge_disable, .enable = mtk_dpi_bridge_enable, }; @@ -668,17 +683,20 @@ static unsigned int mt8183_calculate_factor(int clock) static const struct mtk_dpi_conf mt8173_conf = { .cal_factor = mt8173_calculate_factor, .reg_h_fre_con = 0xe0, + .max_clock_khz = 300000, }; static const struct mtk_dpi_conf mt2701_conf = { .cal_factor = mt2701_calculate_factor, .reg_h_fre_con = 0xb0, .edge_sel_en = true, + .max_clock_khz = 150000, }; static const struct mtk_dpi_conf mt8183_conf = { .cal_factor = mt8183_calculate_factor, .reg_h_fre_con = 0xe0, + .max_clock_khz = 100000, }; static int mtk_dpi_probe(struct platform_device *pdev) From 38eaef2dca4ec8dfb9ea84d9dde0f76da5c8caaa Mon Sep 17 00:00:00 2001 From: Rex-BC Chen Date: Thu, 18 Mar 2021 13:40:56 +0800 Subject: [PATCH 08/13] drm/mediatek: dpi: Add config for mt8192 Add dpi config setting and compatible for MT8192. Signed-off-by: Rex-BC Chen Signed-off-by: Jitao Shi Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_dpi.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c index 07afbdd19ab1..04d60b3d3c5a 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi.c +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -699,6 +699,12 @@ static const struct mtk_dpi_conf mt8183_conf = { .max_clock_khz = 100000, }; +static const struct mtk_dpi_conf mt8192_conf = { + .cal_factor = mt8183_calculate_factor, + .reg_h_fre_con = 0xe0, + .max_clock_khz = 150000, +}; + static int mtk_dpi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -817,6 +823,9 @@ static const struct of_device_id mtk_dpi_of_ids[] = { { .compatible = "mediatek,mt8183-dpi", .data = &mt8183_conf, }, + { .compatible = "mediatek,mt8192-dpi", + .data = &mt8192_conf, + }, { }, }; From 9eda0155e6f134728f3a686101ba3b840051aba3 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Thu, 25 Mar 2021 14:07:28 +0100 Subject: [PATCH 09/13] MAINTAINERS: Add linux-mediatek ML for drm Mediatek drivers Add the linux-mediatek mailing list to drm Mediatek drivers Signed-off-by: Dafna Hirschfeld Signed-off-by: Chun-Kuang Hu --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index d92f85ca831d..9ae8444c96b4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5963,6 +5963,7 @@ DRM DRIVERS FOR MEDIATEK M: Chun-Kuang Hu M: Philipp Zabel L: dri-devel@lists.freedesktop.org +L: linux-mediatek@lists.infradead.org (moderated for non-subscribers) S: Supported F: Documentation/devicetree/bindings/display/mediatek/ F: drivers/gpu/drm/mediatek/ From 368166ec7600ba83587cfcb31d817cf6479cf006 Mon Sep 17 00:00:00 2001 From: Chun-Kuang Hu Date: Sat, 13 Mar 2021 17:22:17 +0800 Subject: [PATCH 10/13] drm/mediatek: crtc: Make config-updating atomic While updating config, the irq would occur and get the partial config, so use variable config_updating to make updating atomic. Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 8b0de90156c6..870f66210848 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -61,6 +61,7 @@ struct mtk_drm_crtc { /* lock for display hardware access */ struct mutex hw_lock; + bool config_updating; }; struct mtk_crtc_state { @@ -97,7 +98,7 @@ static void mtk_drm_crtc_finish_page_flip(struct mtk_drm_crtc *mtk_crtc) static void mtk_drm_finish_page_flip(struct mtk_drm_crtc *mtk_crtc) { drm_crtc_handle_vblank(&mtk_crtc->base); - if (mtk_crtc->pending_needs_vblank) { + if (!mtk_crtc->config_updating && mtk_crtc->pending_needs_vblank) { mtk_drm_crtc_finish_page_flip(mtk_crtc); mtk_crtc->pending_needs_vblank = false; } @@ -425,7 +426,8 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc, } } -static void mtk_drm_crtc_hw_config(struct mtk_drm_crtc *mtk_crtc) +static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc, + bool needs_vblank) { #if IS_REACHABLE(CONFIG_MTK_CMDQ) struct cmdq_pkt *cmdq_handle; @@ -436,6 +438,10 @@ static void mtk_drm_crtc_hw_config(struct mtk_drm_crtc *mtk_crtc) int i; mutex_lock(&mtk_crtc->hw_lock); + mtk_crtc->config_updating = true; + if (needs_vblank) + mtk_crtc->pending_needs_vblank = true; + for (i = 0; i < mtk_crtc->layer_nr; i++) { struct drm_plane *plane = &mtk_crtc->planes[i]; struct mtk_plane_state *plane_state; @@ -472,6 +478,7 @@ static void mtk_drm_crtc_hw_config(struct mtk_drm_crtc *mtk_crtc) cmdq_pkt_flush_async(cmdq_handle, ddp_cmdq_cb, cmdq_handle); } #endif + mtk_crtc->config_updating = false; mutex_unlock(&mtk_crtc->hw_lock); } @@ -532,7 +539,7 @@ void mtk_drm_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane, return; plane_helper_funcs->atomic_update(plane, new_state); - mtk_drm_crtc_hw_config(mtk_crtc); + mtk_drm_crtc_update_config(mtk_crtc, false); } static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc, @@ -582,7 +589,7 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc *crtc, } mtk_crtc->pending_planes = true; - mtk_drm_crtc_hw_config(mtk_crtc); + mtk_drm_crtc_update_config(mtk_crtc, false); /* Wait for planes to be disabled */ drm_crtc_wait_one_vblank(crtc); @@ -618,14 +625,12 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc, struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); int i; - if (mtk_crtc->event) - mtk_crtc->pending_needs_vblank = true; if (crtc->state->color_mgmt_changed) for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) { mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i], crtc->state); mtk_ddp_ctm_set(mtk_crtc->ddp_comp[i], crtc->state); } - mtk_drm_crtc_hw_config(mtk_crtc); + mtk_drm_crtc_update_config(mtk_crtc, !!mtk_crtc->event); } static const struct drm_crtc_funcs mtk_crtc_funcs = { From fdcbe17c6090acdeb766c0383ce101fdf64177e1 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Feb 2021 12:07:17 +0100 Subject: [PATCH 11/13] drm/mediatek: Add missing MODULE_DEVICE_TABLE() This patch adds the missing MODULE_DEVICE_TABLE definitions on different Mediatek drivers which generates correct modalias for automatic loading when these drivers are compiled as an external module. Signed-off-by: Boris Brezillon Signed-off-by: Enric Balletbo i Serra Reviewed-by: Hsin-Yi Wang Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_cec.c | 2 ++ drivers/gpu/drm/mediatek/mtk_dpi.c | 1 + drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 + drivers/gpu/drm/mediatek/mtk_dsi.c | 1 + drivers/gpu/drm/mediatek/mtk_hdmi.c | 1 + drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c | 1 + 6 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_cec.c b/drivers/gpu/drm/mediatek/mtk_cec.c index 332a4dfbdde7..e9cef5c0c8f7 100644 --- a/drivers/gpu/drm/mediatek/mtk_cec.c +++ b/drivers/gpu/drm/mediatek/mtk_cec.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -245,6 +246,7 @@ static const struct of_device_id mtk_cec_of_ids[] = { { .compatible = "mediatek,mt8173-cec", }, {} }; +MODULE_DEVICE_TABLE(of, mtk_cec_of_ids); struct platform_driver mtk_cec_driver = { .probe = mtk_cec_probe, diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c index 04d60b3d3c5a..bea91c81626e 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi.c +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -828,6 +828,7 @@ static const struct of_device_id mtk_dpi_of_ids[] = { }, { }, }; +MODULE_DEVICE_TABLE(of, mtk_dpi_of_ids); struct platform_driver mtk_dpi_driver = { .probe = mtk_dpi_probe, diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index b013d56d2777..b46bdb8985da 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -470,6 +470,7 @@ static const struct of_device_id mtk_drm_of_ids[] = { .data = &mt8183_mmsys_driver_data}, { } }; +MODULE_DEVICE_TABLE(of, mtk_drm_of_ids); static int mtk_drm_probe(struct platform_device *pdev) { diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 1c6e612f7eef..ae403c67cbd9 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -1145,6 +1145,7 @@ static const struct of_device_id mtk_dsi_of_match[] = { .data = &mt8183_dsi_driver_data }, { }, }; +MODULE_DEVICE_TABLE(of, mtk_dsi_of_match); struct platform_driver mtk_dsi_driver = { .probe = mtk_dsi_probe, diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 8ee55f9e2954..b4696a9d73f7 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -1818,6 +1818,7 @@ static const struct of_device_id mtk_drm_hdmi_of_ids[] = { }, {} }; +MODULE_DEVICE_TABLE(of, mtk_drm_hdmi_of_ids); static struct platform_driver mtk_hdmi_driver = { .probe = mtk_drm_hdmi_probe, diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c index 62dbad5675bb..6207eac88550 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c @@ -335,6 +335,7 @@ static const struct of_device_id mtk_hdmi_ddc_match[] = { { .compatible = "mediatek,mt8173-hdmi-ddc", }, {}, }; +MODULE_DEVICE_TABLE(of, mtk_hdmi_ddc_match); struct platform_driver mtk_hdmi_ddc_driver = { .probe = mtk_hdmi_ddc_probe, From 053d231f369ca05cd563ca9738b5a4c73908e697 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Tue, 30 Mar 2021 13:09:01 +0200 Subject: [PATCH 12/13] drm/mediatek: Switch the hdmi bridge ops to the atomic versions The bridge operation '.enable' and the audio cb '.get_eld' access hdmi->conn. In the future we will want to support the flag DRM_BRIDGE_ATTACH_NO_CONNECTOR and then we will not have direct access to the connector. The atomic version '.atomic_enable' allows accessing the current connector from the state. This patch switches the bridge to the atomic version to prepare access to the connector in later patches. Signed-off-by: Dafna Hirschfeld Reviewed-by: Laurent Pinchart Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_hdmi.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index b4696a9d73f7..2d0429e8471a 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -1357,7 +1357,8 @@ static bool mtk_hdmi_bridge_mode_fixup(struct drm_bridge *bridge, return true; } -static void mtk_hdmi_bridge_disable(struct drm_bridge *bridge) +static void mtk_hdmi_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) { struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); @@ -1371,7 +1372,8 @@ static void mtk_hdmi_bridge_disable(struct drm_bridge *bridge) hdmi->enabled = false; } -static void mtk_hdmi_bridge_post_disable(struct drm_bridge *bridge) +static void mtk_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge, + struct drm_bridge_state *old_state) { struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); @@ -1406,7 +1408,8 @@ static void mtk_hdmi_bridge_mode_set(struct drm_bridge *bridge, drm_mode_copy(&hdmi->mode, adjusted_mode); } -static void mtk_hdmi_bridge_pre_enable(struct drm_bridge *bridge) +static void mtk_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_state) { struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); @@ -1426,7 +1429,8 @@ static void mtk_hdmi_send_infoframe(struct mtk_hdmi *hdmi, mtk_hdmi_setup_vendor_specific_infoframe(hdmi, mode); } -static void mtk_hdmi_bridge_enable(struct drm_bridge *bridge) +static void mtk_hdmi_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_state) { struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); @@ -1440,13 +1444,16 @@ static void mtk_hdmi_bridge_enable(struct drm_bridge *bridge) } static const struct drm_bridge_funcs mtk_hdmi_bridge_funcs = { + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_reset = drm_atomic_helper_bridge_reset, .attach = mtk_hdmi_bridge_attach, .mode_fixup = mtk_hdmi_bridge_mode_fixup, - .disable = mtk_hdmi_bridge_disable, - .post_disable = mtk_hdmi_bridge_post_disable, + .atomic_disable = mtk_hdmi_bridge_atomic_disable, + .atomic_post_disable = mtk_hdmi_bridge_atomic_post_disable, .mode_set = mtk_hdmi_bridge_mode_set, - .pre_enable = mtk_hdmi_bridge_pre_enable, - .enable = mtk_hdmi_bridge_enable, + .atomic_pre_enable = mtk_hdmi_bridge_atomic_pre_enable, + .atomic_enable = mtk_hdmi_bridge_atomic_enable, }; static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, From 2e477391522354e763aa62ee3e281c1ad9e8eb1b Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Tue, 30 Mar 2021 13:09:02 +0200 Subject: [PATCH 13/13] drm/mediatek: Don't support hdmi connector creation commit f01195148967 ("drm/mediatek: mtk_dpi: Create connector for bridges") broke the display support for elm device since mtk_dpi calls drm_bridge_attach with the flag DRM_BRIDGE_ATTACH_NO_CONNECTOR while mtk_hdmi does not yet support this flag. Fix this by accepting DRM_BRIDGE_ATTACH_NO_CONNECTOR in bridge attachment. Implement the drm_bridge_funcs .detect() and .get_edid() operations, and call drm_bridge_hpd_notify() to report HPD. This provides the necessary API to support disabling connector creation. In addition, the field 'conn' is removed from the mtk_hdmi struct since mtk_hdmi don't create a connector. It is replaced with a pointer 'curr_conn' that points to the current connector which can be access through the global state. This patch is inspired by a similar patch for bridge/synopsys/dw-hdmi.c: commit ec971aaa6775 ("drm: bridge: dw-hdmi: Make connector creation optional") But with the difference that in mtk-hdmi only the option of not creating a connector is supported. Fixes: f01195148967 ("drm/mediatek: mtk_dpi: Create connector for bridges") Signed-off-by: Dafna Hirschfeld Reviewed-by: Laurent Pinchart Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_hdmi.c | 151 +++++++++++----------------- 1 file changed, 56 insertions(+), 95 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 2d0429e8471a..dea46d66e712 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -153,7 +153,7 @@ struct mtk_hdmi_conf { struct mtk_hdmi { struct drm_bridge bridge; struct drm_bridge *next_bridge; - struct drm_connector conn; + struct drm_connector *curr_conn;/* current connector (only valid when 'enabled') */ struct device *dev; const struct mtk_hdmi_conf *conf; struct phy *phy; @@ -186,11 +186,6 @@ static inline struct mtk_hdmi *hdmi_ctx_from_bridge(struct drm_bridge *b) return container_of(b, struct mtk_hdmi, bridge); } -static inline struct mtk_hdmi *hdmi_ctx_from_conn(struct drm_connector *c) -{ - return container_of(c, struct mtk_hdmi, conn); -} - static u32 mtk_hdmi_read(struct mtk_hdmi *hdmi, u32 offset) { return readl(hdmi->regs + offset); @@ -974,7 +969,7 @@ static int mtk_hdmi_setup_avi_infoframe(struct mtk_hdmi *hdmi, ssize_t err; err = drm_hdmi_avi_infoframe_from_display_mode(&frame, - &hdmi->conn, mode); + hdmi->curr_conn, mode); if (err < 0) { dev_err(hdmi->dev, "Failed to get AVI infoframe from mode: %zd\n", err); @@ -1054,7 +1049,7 @@ static int mtk_hdmi_setup_vendor_specific_infoframe(struct mtk_hdmi *hdmi, ssize_t err; err = drm_hdmi_vendor_infoframe_from_display_mode(&frame, - &hdmi->conn, mode); + hdmi->curr_conn, mode); if (err) { dev_err(hdmi->dev, "Failed to get vendor infoframe from mode: %zd\n", err); @@ -1201,48 +1196,16 @@ mtk_hdmi_update_plugged_status(struct mtk_hdmi *hdmi) connector_status_connected : connector_status_disconnected; } -static enum drm_connector_status hdmi_conn_detect(struct drm_connector *conn, - bool force) +static enum drm_connector_status mtk_hdmi_detect(struct mtk_hdmi *hdmi) { - struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn); return mtk_hdmi_update_plugged_status(hdmi); } -static void hdmi_conn_destroy(struct drm_connector *conn) +static int mtk_hdmi_bridge_mode_valid(struct drm_bridge *bridge, + const struct drm_display_info *info, + const struct drm_display_mode *mode) { - struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn); - - mtk_cec_set_hpd_event(hdmi->cec_dev, NULL, NULL); - - drm_connector_cleanup(conn); -} - -static int mtk_hdmi_conn_get_modes(struct drm_connector *conn) -{ - struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn); - struct edid *edid; - int ret; - - if (!hdmi->ddc_adpt) - return -ENODEV; - - edid = drm_get_edid(conn, hdmi->ddc_adpt); - if (!edid) - return -ENODEV; - - hdmi->dvi_mode = !drm_detect_monitor_audio(edid); - - drm_connector_update_edid_property(conn, edid); - - ret = drm_add_edid_modes(conn, edid); - kfree(edid); - return ret; -} - -static int mtk_hdmi_conn_mode_valid(struct drm_connector *conn, - struct drm_display_mode *mode) -{ - struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn); + struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); struct drm_bridge *next_bridge; dev_dbg(hdmi->dev, "xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n", @@ -1267,74 +1230,57 @@ static int mtk_hdmi_conn_mode_valid(struct drm_connector *conn, return drm_mode_validate_size(mode, 0x1fff, 0x1fff); } -static struct drm_encoder *mtk_hdmi_conn_best_enc(struct drm_connector *conn) -{ - struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn); - - return hdmi->bridge.encoder; -} - -static const struct drm_connector_funcs mtk_hdmi_connector_funcs = { - .detect = hdmi_conn_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = hdmi_conn_destroy, - .reset = drm_atomic_helper_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - -static const struct drm_connector_helper_funcs - mtk_hdmi_connector_helper_funcs = { - .get_modes = mtk_hdmi_conn_get_modes, - .mode_valid = mtk_hdmi_conn_mode_valid, - .best_encoder = mtk_hdmi_conn_best_enc, -}; - static void mtk_hdmi_hpd_event(bool hpd, struct device *dev) { struct mtk_hdmi *hdmi = dev_get_drvdata(dev); - if (hdmi && hdmi->bridge.encoder && hdmi->bridge.encoder->dev) + if (hdmi && hdmi->bridge.encoder && hdmi->bridge.encoder->dev) { + static enum drm_connector_status status; + + status = mtk_hdmi_detect(hdmi); drm_helper_hpd_irq_event(hdmi->bridge.encoder->dev); + drm_bridge_hpd_notify(&hdmi->bridge, status); + } } /* * Bridge callbacks */ +static enum drm_connector_status mtk_hdmi_bridge_detect(struct drm_bridge *bridge) +{ + struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); + + return mtk_hdmi_detect(hdmi); +} + +static struct edid *mtk_hdmi_bridge_get_edid(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); + struct edid *edid; + + if (!hdmi->ddc_adpt) + return NULL; + edid = drm_get_edid(connector, hdmi->ddc_adpt); + if (!edid) + return NULL; + hdmi->dvi_mode = !drm_detect_monitor_audio(edid); + return edid; +} + static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) { struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); int ret; - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { - DRM_ERROR("Fix bridge driver to make connector optional!"); + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { + DRM_ERROR("%s: The flag DRM_BRIDGE_ATTACH_NO_CONNECTOR must be supplied\n", + __func__); return -EINVAL; } - ret = drm_connector_init_with_ddc(bridge->encoder->dev, &hdmi->conn, - &mtk_hdmi_connector_funcs, - DRM_MODE_CONNECTOR_HDMIA, - hdmi->ddc_adpt); - if (ret) { - dev_err(hdmi->dev, "Failed to initialize connector: %d\n", ret); - return ret; - } - drm_connector_helper_add(&hdmi->conn, &mtk_hdmi_connector_helper_funcs); - - hdmi->conn.polled = DRM_CONNECTOR_POLL_HPD; - hdmi->conn.interlace_allowed = true; - hdmi->conn.doublescan_allowed = false; - - ret = drm_connector_attach_encoder(&hdmi->conn, - bridge->encoder); - if (ret) { - dev_err(hdmi->dev, - "Failed to attach connector to encoder: %d\n", ret); - return ret; - } - if (hdmi->next_bridge) { ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge, bridge, flags); @@ -1369,6 +1315,8 @@ static void mtk_hdmi_bridge_atomic_disable(struct drm_bridge *bridge, clk_disable_unprepare(hdmi->clk[MTK_HDMI_CLK_HDMI_PIXEL]); clk_disable_unprepare(hdmi->clk[MTK_HDMI_CLK_HDMI_PLL]); + hdmi->curr_conn = NULL; + hdmi->enabled = false; } @@ -1432,8 +1380,13 @@ static void mtk_hdmi_send_infoframe(struct mtk_hdmi *hdmi, static void mtk_hdmi_bridge_atomic_enable(struct drm_bridge *bridge, struct drm_bridge_state *old_state) { + struct drm_atomic_state *state = old_state->base.state; struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); + /* Retrieve the connector through the atomic state. */ + hdmi->curr_conn = drm_atomic_get_new_connector_for_encoder(state, + bridge->encoder); + mtk_hdmi_output_set_display_mode(hdmi, &hdmi->mode); clk_prepare_enable(hdmi->clk[MTK_HDMI_CLK_HDMI_PLL]); clk_prepare_enable(hdmi->clk[MTK_HDMI_CLK_HDMI_PIXEL]); @@ -1444,6 +1397,7 @@ static void mtk_hdmi_bridge_atomic_enable(struct drm_bridge *bridge, } static const struct drm_bridge_funcs mtk_hdmi_bridge_funcs = { + .mode_valid = mtk_hdmi_bridge_mode_valid, .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, .atomic_reset = drm_atomic_helper_bridge_reset, @@ -1454,6 +1408,8 @@ static const struct drm_bridge_funcs mtk_hdmi_bridge_funcs = { .mode_set = mtk_hdmi_bridge_mode_set, .atomic_pre_enable = mtk_hdmi_bridge_atomic_pre_enable, .atomic_enable = mtk_hdmi_bridge_atomic_enable, + .detect = mtk_hdmi_bridge_detect, + .get_edid = mtk_hdmi_bridge_get_edid, }; static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, @@ -1669,8 +1625,10 @@ static int mtk_hdmi_audio_get_eld(struct device *dev, void *data, uint8_t *buf, { struct mtk_hdmi *hdmi = dev_get_drvdata(dev); - memcpy(buf, hdmi->conn.eld, min(sizeof(hdmi->conn.eld), len)); - + if (hdmi->enabled) + memcpy(buf, hdmi->curr_conn->eld, min(sizeof(hdmi->curr_conn->eld), len)); + else + memset(buf, 0, len); return 0; } @@ -1762,6 +1720,9 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev) hdmi->bridge.funcs = &mtk_hdmi_bridge_funcs; hdmi->bridge.of_node = pdev->dev.of_node; + hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID + | DRM_BRIDGE_OP_HPD; + hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA; drm_bridge_add(&hdmi->bridge); ret = mtk_hdmi_clk_enable_audio(hdmi);