From patchwork Wed May 17 16:43:47 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Icenowy Zheng X-Patchwork-Id: 9731647 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 A3A6E6022E for ; Wed, 17 May 2017 17:02:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EEB5425EF7 for ; Wed, 17 May 2017 17:02:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E2695262F2; Wed, 17 May 2017 17:02:25 +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=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 698A925EF7 for ; Wed, 17 May 2017 17:02:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=R2k0wlggZsrlGyzOqwOH18XBFjtR7YWz1xKyTD06TRs=; b=KapADXPaGhNB5LaxR2cNn+NUiG DM2i3D4zqtXtWflhl3Bmn1AgxWgtQ3sMEYUoC+phb2x5eUvklt9tWgUrQQZohoPS7abTuizvHX9BC lJmy4dVn5pTnnyOnrWZVJFFiqM0mRdHjQW/EzqLHPUvVzA0zqppdgIoFi6x6ll6o5wix8TktFjXNw 2mI4+4N3//yqsCrAcL7PrlyC2NzzlwH8VG/3sZUFD2bv4gTFDTOSxT3SUJtVogztCQch6+SuCbX63 u4iflJqdj/0pISi/2zA9N957mjraQC4sJzX4cCd3RBT9zY8HbH4VViPqCbYFJBVK5a63zTFhhFAS9 b7GesuHw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1dB2L5-0005Zg-KS; Wed, 17 May 2017 17:02:19 +0000 Received: from camel.ash.relay.mailchannels.net ([23.83.222.29]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1dB259-0002jK-M3 for linux-arm-kernel@lists.infradead.org; Wed, 17 May 2017 16:46:23 +0000 X-Sender-Id: lmn-tzduiowcrqmw|x-authsender|icenowy@aosc.io Received: from relay.mailchannels.net (localhost [127.0.0.1]) by relay.mailchannels.net (Postfix) with ESMTP id DBD122053F1; Wed, 17 May 2017 16:45:22 +0000 (UTC) Received: from hermes.aosc.io (unknown [100.96.137.69]) (Authenticated sender: lmn-TZDUIOWCRQMW) by relay.mailchannels.net (Postfix) with ESMTPA id 66B122050EF; Wed, 17 May 2017 16:45:19 +0000 (UTC) X-Sender-Id: lmn-tzduiowcrqmw|x-authsender|icenowy@aosc.io Received: from hermes.aosc.io (hermes.aosc.io [172.20.82.168]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384) by 0.0.0.0:2500 (trex/5.9.3); Wed, 17 May 2017 16:45:22 +0000 X-MC-Relay: Neutral X-MailChannels-SenderId: lmn-tzduiowcrqmw|x-authsender|icenowy@aosc.io X-MailChannels-Auth-Id: lmn-TZDUIOWCRQMW X-Interest-Stop: 0c618ba70963cd27_1495039520730_293849787 X-MC-Loop-Signature: 1495039520729:3452631616 X-MC-Ingress-Time: 1495039520729 Received: from localhost (localhost [127.0.0.1]) (Authenticated sender: icenowy@aosc.io) by hermes.aosc.io (Postfix) with ESMTPSA id EF06A4DD14; Wed, 17 May 2017 16:45:10 +0000 (UTC) From: Icenowy Zheng To: Maxime Ripard , Rob Herring , Chen-Yu Tsai Subject: [RFC PATCH 04/11] drm: sun4i: add support for H3's TCON0/1 Date: Thu, 18 May 2017 00:43:47 +0800 Message-Id: <20170517164354.16399-5-icenowy@aosc.io> In-Reply-To: <20170517164354.16399-1-icenowy@aosc.io> References: <20170517164354.16399-1-icenowy@aosc.io> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170517_094552_710479_59FAD1AC X-CRM114-Status: GOOD ( 15.23 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-sunxi@googlegroups.com, Icenowy Zheng , linux-clk@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Icenowy Zheng MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: Icenowy Zheng Allwinner H3 has two special TCONs, both come without channel0. And the TCON1 of H3 has no special clocks even for the channel1. Add support for these kinds of TCON. Signed-off-by: Icenowy Zheng --- drivers/gpu/drm/sun4i/sun4i_tcon.c | 78 ++++++++++++++++++++++++++++---------- drivers/gpu/drm/sun4i/sun4i_tcon.h | 3 ++ 2 files changed, 61 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 89a215ff2370..7009292f99e4 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -57,6 +57,7 @@ void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel) { /* Disable the TCON's channel */ if (channel == 0) { + WARN_ON(!tcon->quirks->has_channel_0); regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, SUN4I_TCON0_CTL_TCON_ENABLE, 0); clk_disable_unprepare(tcon->dclk); @@ -66,7 +67,8 @@ void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel) WARN_ON(!tcon->quirks->has_channel_1); regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG, SUN4I_TCON1_CTL_TCON_ENABLE, 0); - clk_disable_unprepare(tcon->sclk1); + if (tcon->quirks->has_channel_1_clk) + clk_disable_unprepare(tcon->sclk1); } EXPORT_SYMBOL(sun4i_tcon_channel_disable); @@ -74,6 +76,7 @@ void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel) { /* Enable the TCON's channel */ if (channel == 0) { + WARN_ON(!tcon->quirks->has_channel_0); regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, SUN4I_TCON0_CTL_TCON_ENABLE, SUN4I_TCON0_CTL_TCON_ENABLE); @@ -85,7 +88,8 @@ void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel) regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG, SUN4I_TCON1_CTL_TCON_ENABLE, SUN4I_TCON1_CTL_TCON_ENABLE); - clk_prepare_enable(tcon->sclk1); + if (tcon->quirks->has_channel_1_clk) + clk_prepare_enable(tcon->sclk1); } EXPORT_SYMBOL(sun4i_tcon_channel_enable); @@ -132,6 +136,7 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon, /* Configure the dot clock */ clk_set_rate(tcon->dclk, mode->crtc_clock * 1000); + WARN_ON(!tcon->quirks->has_channel_0); /* Adjust clock delay */ clk_delay = sun4i_tcon_get_clk_delay(mode, 0); @@ -209,7 +214,8 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon, WARN_ON(!tcon->quirks->has_channel_1); /* Configure the dot clock */ - clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000); + if (tcon->quirks->has_channel_1_clk) + clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000); /* Adjust clock delay */ clk_delay = sun4i_tcon_get_clk_delay(mode, 1); @@ -327,13 +333,15 @@ static int sun4i_tcon_init_clocks(struct device *dev, } clk_prepare_enable(tcon->clk); - tcon->sclk0 = devm_clk_get(dev, "tcon-ch0"); - if (IS_ERR(tcon->sclk0)) { - dev_err(dev, "Couldn't get the TCON channel 0 clock\n"); - return PTR_ERR(tcon->sclk0); + if (tcon->quirks->has_channel_0) { + tcon->sclk0 = devm_clk_get(dev, "tcon-ch0"); + if (IS_ERR(tcon->sclk0)) { + dev_err(dev, "Couldn't get the TCON channel 0 clock\n"); + return PTR_ERR(tcon->sclk0); + } } - if (tcon->quirks->has_channel_1) { + if (tcon->quirks->has_channel_1 && tcon->quirks->has_channel_1_clk) { tcon->sclk1 = devm_clk_get(dev, "tcon-ch1"); if (IS_ERR(tcon->sclk1)) { dev_err(dev, "Couldn't get the TCON channel 1 clock\n"); @@ -533,10 +541,12 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, goto err_free_clocks; } - ret = sun4i_dclk_create(dev, tcon); - if (ret) { - dev_err(dev, "Couldn't create our TCON dot clock\n"); - goto err_free_clocks; + if (tcon->quirks->has_channel_0) { + ret = sun4i_dclk_create(dev, tcon); + if (ret) { + dev_err(dev, "Couldn't create our TCON dot clock\n"); + goto err_free_clocks; + } } ret = sun4i_tcon_init_irq(dev, tcon); @@ -561,7 +571,8 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, return 0; err_free_dotclock: - sun4i_dclk_free(tcon); + if (tcon->quirks->has_channel_0) + sun4i_dclk_free(tcon); err_free_clocks: sun4i_tcon_free_clocks(tcon); err_assert_reset: @@ -575,7 +586,9 @@ static void sun4i_tcon_unbind(struct device *dev, struct device *master, struct sun4i_tcon *tcon = dev_get_drvdata(dev); list_del(&tcon->list); - sun4i_dclk_free(tcon); + + if (tcon->quirks->has_channel_0) + sun4i_dclk_free(tcon); sun4i_tcon_free_clocks(tcon); } @@ -606,24 +619,41 @@ static int sun4i_tcon_remove(struct platform_device *pdev) } static const struct sun4i_tcon_quirks sun5i_a13_quirks = { - .has_unknown_mux = true, - .has_channel_1 = true, + .has_unknown_mux = true, + .has_channel_0 = true, + .has_channel_1 = true, + .has_channel_1_clk = true, }; static const struct sun4i_tcon_quirks sun6i_a31_quirks = { - .has_channel_1 = true, + .has_channel_0 = true, + .has_channel_1 = true, + .has_channel_1_clk = true, }; static const struct sun4i_tcon_quirks sun6i_a31s_quirks = { - .has_channel_1 = true, + .has_channel_0 = true, + .has_channel_1 = true, + .has_channel_1_clk = true, }; static const struct sun4i_tcon_quirks sun8i_a33_quirks = { - /* nothing is supported */ + .has_channel_0 = true, }; static const struct sun4i_tcon_quirks sun8i_v3s_quirks = { - /* nothing is supported */ + .has_channel_0 = true, +}; + +static const struct sun4i_tcon_quirks sun8i_h3_tcon0_quirks = { + .has_channel_1 = true, + .has_channel_1_clk = true, + .swappable_input = true, +}; + +static const struct sun4i_tcon_quirks sun8i_h3_tcon1_quirks = { + .has_channel_1 = true, + .swappable_input = true, }; static const struct of_device_id sun4i_tcon_of_table[] = { @@ -632,6 +662,14 @@ static const struct of_device_id sun4i_tcon_of_table[] = { { .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks }, { .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks }, { .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks }, + { + .compatible = "allwinner,sun8i-h3-tcon0", + .data = &sun8i_h3_tcon0_quirks + }, + { + .compatible = "allwinner,sun8i-h3-tcon1", + .data = &sun8i_h3_tcon1_quirks + }, { } }; MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table); diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h index 568dc736238a..6aeb2d68b523 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h @@ -145,7 +145,10 @@ struct sun4i_tcon_quirks { bool has_unknown_mux; /* sun5i has undocumented mux */ + bool has_channel_0; /* some A83T+ TCONs don't have channel 0*/ bool has_channel_1; /* a33 does not have channel 1 */ + /* H3 TCON1 doesn't have channel 1 sclk */ + bool has_channel_1_clk; /* Some DE2 can swap the mixer<->TCON connection */ bool swappable_input; };