From patchwork Wed Mar 11 15:27:05 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Davor Joja X-Patchwork-Id: 5986751 Return-Path: X-Original-To: patchwork-linux-fbdev@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id E91589F380 for ; Wed, 11 Mar 2015 15:36:36 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3E81A20386 for ; Wed, 11 Mar 2015 15:36:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 50007203B0 for ; Wed, 11 Mar 2015 15:36:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753535AbbCKPdY (ORCPT ); Wed, 11 Mar 2015 11:33:24 -0400 Received: from mail.logicbricks.com ([89.201.165.134]:27597 "EHLO mail.logicbricks.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752770AbbCKPdV (ORCPT ); Wed, 11 Mar 2015 11:33:21 -0400 X-Greylist: delayed 334 seconds by postgrey-1.27 at vger.kernel.org; Wed, 11 Mar 2015 11:33:15 EDT From: Davor Joja To: , , , CC: Davor Joja Subject: [PATCH 04/10] fbdev: xylon: Framebuffer driver pixel clock Date: Wed, 11 Mar 2015 16:27:05 +0100 X-Mailer: git-send-email 1.9.1 In-Reply-To: <1426087631-9952-1-git-send-email-davorjoja@logicbricks.com> References: <1426087631-9952-1-git-send-email-davorjoja@logicbricks.com> MIME-Version: 1.0 X-Originating-IP: [192.168.0.95] Message-ID: Sender: linux-fbdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fbdev@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Driver pixel clock control functionality supporting optional Xylon logiCLK IP core clock generator. Signed-off-by: Davor Joja --- drivers/video/fbdev/xylon/xylonfb_pixclk.c | 119 +++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 drivers/video/fbdev/xylon/xylonfb_pixclk.c diff --git a/drivers/video/fbdev/xylon/xylonfb_pixclk.c b/drivers/video/fbdev/xylon/xylonfb_pixclk.c new file mode 100644 index 0000000..d63dbeb --- /dev/null +++ b/drivers/video/fbdev/xylon/xylonfb_pixclk.c @@ -0,0 +1,119 @@ +/* + * Xylon logiCVC frame buffer driver pixel clock control + * + * Copyright (C) 2015 Xylon d.o.o. + * Author: Davor Joja + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +struct xylonfb_pixclk { + struct device *dev; + struct device_node *dn; + struct clk *clk; +}; + +#if defined(CONFIG_FB_XYLON_PIXCLK_LOGICLK) +static const struct of_device_id logiclk_of_match[] = { + { .compatible = "xylon,logiclk-1.02.b" }, + {/* end of table */} +}; +static struct xylonfb_pixclk logiclk; +#endif + +bool xylonfb_hw_pixclk_supported(struct device *dev, struct device_node *dn); +void xylonfb_hw_pixclk_unload(struct device_node *dn); +int xylonfb_hw_pixclk_set(struct device *dev, struct device_node *dn, + unsigned long pixclk_khz); + +#if defined(CONFIG_FB_XYLON_PIXCLK) +static int xylonfb_hw_pixclk_set_freq(struct device *dev, + struct device_node *dn, + unsigned long freq_khz) +{ + struct clk *clk = NULL; + +#if defined(CONFIG_FB_XYLON_PIXCLK_LOGICLK) + if (dn == logiclk.dn) + clk = logiclk.clk; +#endif + + if (clk && clk_set_rate(clk, (freq_khz * 1000))) { + dev_err(dev, "failed set pixel clock frequency\n"); + return -EINVAL; + } + + return 0; +} +#endif + +bool xylonfb_hw_pixclk_supported(struct device *dev, struct device_node *dn) +{ +#if defined(CONFIG_FB_XYLON_PIXCLK) + struct clk **clk; + bool clk_dev = false; + +#if defined(CONFIG_FB_XYLON_PIXCLK_LOGICLK) + if (of_match_node(logiclk_of_match, of_get_parent(dn))) { + clk = &logiclk.clk; + logiclk.dev = dev; + logiclk.dn = dn; + clk_dev = true; + } +#endif + + if (clk_dev) { + *clk = devm_clk_get(dev, NULL); + if (IS_ERR(*clk)) { + dev_err(dev, "failed get pixel clock\n"); + return false; + } + if (clk_prepare_enable(*clk)) { + dev_err(dev, + "failed prepare/enable pixel clock\n"); + return false; + } + + return true; + } else { + return false; + } +#else + return true; +#endif +} + +void xylonfb_hw_pixclk_unload(struct device_node *dn) +{ + struct clk *clk = NULL; + +#if defined(CONFIG_FB_XYLON_PIXCLK_LOGICLK) + clk = logiclk.clk; +#endif + + if (clk) + clk_disable_unprepare(clk); +} + +int xylonfb_hw_pixclk_set(struct device *dev, struct device_node *dn, + unsigned long pixclk_khz) +{ +#if defined(CONFIG_FB_XYLON_PIXCLK) + return xylonfb_hw_pixclk_set_freq(dev, dn, pixclk_khz); +#else + dev_warn(dev, "pixel clock control not supported\n"); + return -ENODEV; +#endif +}