Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp3683103pxf; Mon, 29 Mar 2021 08:38:48 -0700 (PDT) X-Google-Smtp-Source: ABdhPJx3WJPQzZU1T/tJ0nEG0c/SDl2YwoNTPhX8TMcl31smoOJbgwpcqJt8iwCtDrTCoJmIguBd X-Received: by 2002:a17:907:3f26:: with SMTP id hq38mr29214105ejc.374.1617032328498; Mon, 29 Mar 2021 08:38:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1617032328; cv=none; d=google.com; s=arc-20160816; b=FIbKiGA6ccoxCWJm7+kD7FYsI2ZHbeuX1DwrJbZlK2+SwwG5Ai4cEfh7kyVne1SZTa Dqr8BvaI9W0gm4cz7ajkCqzjkNvGtJ7g7mKIM1aKllh340TGPDRkBbzNeP1/QfTGvuEH fLTa1PCRX0DI+3lOYjDv3f3HvouoAyHajSOHsMMapjjQCY3PVeufAvNG+vw2oHQWthcq 9FmsUIqlX8GMpFzfY+KNX4URDY1WoZ8Vggy4P9HBbQikVa7hnwsP9EtvgMyupyELuXnY PEWvsgbF5zq2k/FwxCOprX2feTNjmDHBBnbfzd1VXgNqFRIARHcM1huBvoTVqEQW4+J9 /+Ew== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from; bh=Z7nuGUK3ALzVA56oO6oCbpDUO9YrWtujzU/KJWGBWs8=; b=WrRbTkLVthf/ReVVI8dy7hhcshk7jFm38Vy+xx6fg9253KXM6rnNrWzJATYKnQwvzd C9U5bISXNtpj/9ZM0e323wSZoQ3H7r60fkepbvnCGTPGmYPKXoJzHXJ8J/qPFk9KY0Mz /Q/xdHivNje7Cct0KctQolteEwqUvq7/7xGq+Ealbm5w7H1dPlg6xn7rbryGW/cl9ubS 7jrPJGuJx7hkliS68Ah0a4SJaetMB2gSwWDk6XnV9k7uX1VZFlQQy57h8kE69TJXtkXh hdavB62ZHXuFu/SmELWHJ23cHfCRDZaiSmzYTTxt3vgfms9b+CBY8llwvp2D0sQ7UClI R81A== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=collabora.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id u6si12685128ejx.73.2021.03.29.08.38.26; Mon, 29 Mar 2021 08:38:48 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=collabora.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231453AbhC2Ph3 (ORCPT + 99 others); Mon, 29 Mar 2021 11:37:29 -0400 Received: from bhuna.collabora.co.uk ([46.235.227.227]:51340 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231424AbhC2Pgz (ORCPT ); Mon, 29 Mar 2021 11:36:55 -0400 Received: from guri.fritz.box (unknown [IPv6:2a02:810a:880:f54:85ba:22ea:8b43:4375]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: dafna) by bhuna.collabora.co.uk (Postfix) with ESMTPSA id 582AD1F45543; Mon, 29 Mar 2021 16:36:53 +0100 (BST) From: Dafna Hirschfeld To: dri-devel@lists.freedesktop.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org Cc: dafna.hirschfeld@collabora.com, kernel@collabora.com, dafna3@gmail.com, chunkuang.hu@kernel.org, p.zabel@pengutronix.de, airlied@linux.ie, daniel@ffwll.ch, enric.balletbo@collabora.com, laurent.pinchart@ideasonboard.com Subject: [PATCH v2 2/3] drm/mediatek: Don't support hdmi connector creation Date: Mon, 29 Mar 2021 17:36:31 +0200 Message-Id: <20210329153632.17559-3-dafna.hirschfeld@collabora.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210329153632.17559-1-dafna.hirschfeld@collabora.com> References: <20210329153632.17559-1-dafna.hirschfeld@collabora.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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. 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 --- drivers/gpu/drm/mediatek/mtk_hdmi.c | 129 ++++++++++------------------ 1 file changed, 44 insertions(+), 85 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index f2c810b767ef..1eeb211b1536 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -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); @@ -1201,48 +1196,30 @@ 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) -{ - 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 struct edid *mtk_hdmi_get_edid(struct mtk_hdmi *hdmi, + struct drm_connector *connector) { - 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); + return NULL; + edid = drm_get_edid(connector, hdmi->ddc_adpt); if (!edid) - return -ENODEV; - + return NULL; hdmi->dvi_mode = !drm_detect_monitor_audio(edid); + return edid; +} - drm_connector_update_edid_property(conn, edid); - - ret = drm_add_edid_modes(conn, edid); - kfree(edid); - return ret; +static enum drm_connector_status mtk_hdmi_detect(struct mtk_hdmi *hdmi) +{ + return mtk_hdmi_update_plugged_status(hdmi); } -static int mtk_hdmi_conn_mode_valid(struct drm_connector *conn, - struct drm_display_mode *mode) +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); + 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 +1244,50 @@ 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); + + return mtk_hdmi_get_edid(hdmi, connector); +} + 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); @@ -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, @@ -1762,6 +1718,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); -- 2.17.1