From patchwork Tue Dec 20 01:33:41 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 9480945 X-Patchwork-Delegate: geert@linux-m68k.org Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id B5664607FF for ; Tue, 20 Dec 2016 01:33:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A44F926AE3 for ; Tue, 20 Dec 2016 01:33:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 98FCD284A9; Tue, 20 Dec 2016 01:33:45 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1148B26AE3 for ; Tue, 20 Dec 2016 01:33:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753954AbcLTBdo (ORCPT ); Mon, 19 Dec 2016 20:33:44 -0500 Received: from galahad.ideasonboard.com ([185.26.127.97]:41469 "EHLO galahad.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754596AbcLTBdo (ORCPT ); Mon, 19 Dec 2016 20:33:44 -0500 Received: from avalon.bb.dnainternet.fi (dfj612ybrt5fhg77mgycy-3.rev.dnainternet.fi [IPv6:2001:14ba:21f5:5b00:2e86:4862:ef6a:2804]) by galahad.ideasonboard.com (Postfix) with ESMTPSA id 3471520AAE; Tue, 20 Dec 2016 02:33:25 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1482197605; bh=/hyqmWXJVTNrGmGTnOLrDg6/dWSSn4dv0seLkKbegnw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=i8dKP40bYKJDT4ynVse2qBpHE19snHafAsHUMlxkX57LT8EaHWftRbOEZJUBenbrm K3f1qb/1uQWFIDUugC4cefWCKmX9TLnhiGWz6lm9lmMuxOQZGzdoPAjjzGfcEUxSX6 waggEWyZ2NCskfcEa3U+VZBs5EXa4pBzlZel6okw= From: Laurent Pinchart To: dri-devel@lists.freedesktop.org Cc: Andy Yan , Fabio Estevam , Jose Abreu , Kieran Bingham , Russell King , Ulrich Hecht , Vladimir Zapolskiy , linux-renesas-soc@vger.kernel.org Subject: [PATCH v2 10/29] drm: bridge: dw-hdmi: Implement DRM bridge registration Date: Tue, 20 Dec 2016 03:33:41 +0200 Message-Id: <20161220013400.28317-11-laurent.pinchart+renesas@ideasonboard.com> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20161220013400.28317-1-laurent.pinchart+renesas@ideasonboard.com> References: <20161220013400.28317-1-laurent.pinchart+renesas@ideasonboard.com> Sender: linux-renesas-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP As an option for drivers not based on the component framework, register the bridge with the DRM core with the DRM bridge API. Existing drivers based on dw_hdmi_bind() and dw_hdmi_unbind() are not affected as those functions are preserved with their current behaviour. Signed-off-by: Laurent Pinchart Reviewed-by: Jose Abreu --- drivers/gpu/drm/bridge/dw-hdmi.c | 112 ++++++++++++++++++++++++++++----------- include/drm/bridge/dw_hdmi.h | 3 ++ 2 files changed, 83 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c index 88cd40adb977..107fea49c4c6 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/dw-hdmi.c @@ -1836,24 +1836,9 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) return IRQ_HANDLED; } -static int dw_hdmi_register(struct drm_encoder *encoder, struct dw_hdmi *hdmi) -{ - struct drm_bridge *bridge = &hdmi->bridge; - int ret; - - bridge->driver_private = hdmi; - bridge->funcs = &dw_hdmi_bridge_funcs; - ret = drm_bridge_attach(encoder, bridge, NULL); - if (ret) { - DRM_ERROR("Failed to initialize bridge with drm\n"); - return -EINVAL; - } - - return 0; -} - -int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, - const struct dw_hdmi_plat_data *plat_data) +static struct dw_hdmi * +__dw_hdmi_probe(struct platform_device *pdev, + const struct dw_hdmi_plat_data *plat_data) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; @@ -1869,7 +1854,7 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); if (!hdmi) - return -ENOMEM; + return ERR_PTR(-ENOMEM); hdmi->plat_data = plat_data; hdmi->dev = dev; @@ -1896,7 +1881,7 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, break; default: dev_err(dev, "reg-io-width must be 1 or 4\n"); - return -EINVAL; + return ERR_PTR(-EINVAL); } ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); @@ -1905,7 +1890,7 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, of_node_put(ddc_node); if (!hdmi->ddc) { dev_dbg(hdmi->dev, "failed to read ddc node\n"); - return -EPROBE_DEFER; + return ERR_PTR(-EPROBE_DEFER); } } else { @@ -1956,8 +1941,10 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, initialize_hdmi_ih_mutes(hdmi); irq = platform_get_irq(pdev, 0); - if (irq < 0) + if (irq < 0) { + ret = irq; goto err_iahb; + } ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq, dw_hdmi_irq, IRQF_SHARED, @@ -1988,11 +1975,11 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE, HDMI_IH_PHY_STAT0); - ret = dw_hdmi_fb_registered(hdmi); - if (ret) - goto err_iahb; + hdmi->bridge.driver_private = hdmi; + hdmi->bridge.funcs = &dw_hdmi_bridge_funcs; + hdmi->bridge.of_node = pdev->dev.of_node; - ret = dw_hdmi_register(encoder, hdmi); + ret = dw_hdmi_fb_registered(hdmi); if (ret) goto err_iahb; @@ -2041,7 +2028,7 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, platform_set_drvdata(pdev, hdmi); - return 0; + return hdmi; err_iahb: if (hdmi->i2c) { @@ -2055,14 +2042,11 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, err_res: i2c_put_adapter(hdmi->ddc); - return ret; + return ERR_PTR(ret); } -EXPORT_SYMBOL_GPL(dw_hdmi_bind); -void dw_hdmi_unbind(struct device *dev) +static void __dw_hdmi_remove(struct dw_hdmi *hdmi) { - struct dw_hdmi *hdmi = dev_get_drvdata(dev); - if (hdmi->audio && !IS_ERR(hdmi->audio)) platform_device_unregister(hdmi->audio); @@ -2077,6 +2061,70 @@ void dw_hdmi_unbind(struct device *dev) else i2c_put_adapter(hdmi->ddc); } + +/* ----------------------------------------------------------------------------- + * Probe/remove API, used from platforms based on the DRM bridge API. + */ +int dw_hdmi_probe(struct platform_device *pdev, + const struct dw_hdmi_plat_data *plat_data) +{ + struct dw_hdmi *hdmi; + int ret; + + hdmi = __dw_hdmi_probe(pdev, plat_data); + if (IS_ERR(hdmi)) + return PTR_ERR(hdmi); + + ret = drm_bridge_add(&hdmi->bridge); + if (ret < 0) { + __dw_hdmi_remove(hdmi); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(dw_hdmi_probe); + +void dw_hdmi_remove(struct platform_device *pdev) +{ + struct dw_hdmi *hdmi = platform_get_drvdata(pdev); + + drm_bridge_remove(&hdmi->bridge); + + __dw_hdmi_remove(hdmi); +} +EXPORT_SYMBOL_GPL(dw_hdmi_remove); + +/* ----------------------------------------------------------------------------- + * Bind/unbind API, used from platforms based on the component framework. + */ +int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, + const struct dw_hdmi_plat_data *plat_data) +{ + struct dw_hdmi *hdmi; + int ret; + + hdmi = __dw_hdmi_probe(pdev, plat_data); + if (IS_ERR(hdmi)) + return PTR_ERR(hdmi); + + ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL); + if (ret) { + dw_hdmi_remove(pdev); + DRM_ERROR("Failed to initialize bridge with drm\n"); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(dw_hdmi_bind); + +void dw_hdmi_unbind(struct device *dev) +{ + struct dw_hdmi *hdmi = dev_get_drvdata(dev); + + __dw_hdmi_remove(hdmi); +} EXPORT_SYMBOL_GPL(dw_hdmi_unbind); MODULE_AUTHOR("Sascha Hauer "); diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index 94ff6edd070b..3bb22a849830 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -56,6 +56,9 @@ struct dw_hdmi_plat_data { struct drm_display_mode *mode); }; +int dw_hdmi_probe(struct platform_device *pdev, + const struct dw_hdmi_plat_data *plat_data); +void dw_hdmi_remove(struct platform_device *pdev); void dw_hdmi_unbind(struct device *dev); int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, const struct dw_hdmi_plat_data *plat_data);