From patchwork Fri May 9 14:53:01 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ajay Kumar X-Patchwork-Id: 4150121 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 40BC5C0ACD for ; Sun, 11 May 2014 11:04:19 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 151EC2028D for ; Sun, 11 May 2014 11:04:18 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id C72E9202F8 for ; Sun, 11 May 2014 11:04:16 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E14D56E89A; Sun, 11 May 2014 04:04:10 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mailout1.samsung.com (mailout1.samsung.com [203.254.224.24]) by gabe.freedesktop.org (Postfix) with ESMTP id D94046E05A for ; Fri, 9 May 2014 07:54:38 -0700 (PDT) Received: from epcpsbgr1.samsung.com (u141.gpu120.samsung.co.kr [203.254.230.141]) by mailout1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0N5B003R6AR21D10@mailout1.samsung.com> for dri-devel@lists.freedesktop.org; Fri, 09 May 2014 23:54:38 +0900 (KST) Received: from epcpsbgm2.samsung.com ( [172.20.52.122]) by epcpsbgr1.samsung.com (EPCPMTA) with SMTP id F0.C0.18501.E2CEC635; Fri, 09 May 2014 23:54:38 +0900 (KST) X-AuditID: cbfee68d-b7f4e6d000004845-6b-536cec2ef9db Received: from epmmp2 ( [203.254.227.17]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 40.5E.25708.D2CEC635; Fri, 09 May 2014 23:54:37 +0900 (KST) Received: from chromebld-server.sisodomain.com ([107.108.73.106]) by mmp2.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0N5B00MULAPV2020@mmp2.samsung.com>; Fri, 09 May 2014 23:54:37 +0900 (KST) From: Ajay Kumar To: dri-devel@lists.freedesktop.org, linux-samsung-soc@vger.kernel.org Subject: [RFC V3 2/3] drm/bridge: add a dummy panel driver to support lvds bridges Date: Fri, 09 May 2014 20:23:01 +0530 Message-id: <1399647182-20951-3-git-send-email-ajaykumar.rs@samsung.com> X-Mailer: git-send-email 1.7.9.5 In-reply-to: <1399647182-20951-1-git-send-email-ajaykumar.rs@samsung.com> References: <1399647182-20951-1-git-send-email-ajaykumar.rs@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprAIsWRmVeSWpSXmKPExsWyRsSkSlfvTU6wwdTvHBa31p1jtTjw/iCL xYY3C5ktFj68y2xx5et7NotJ9yewWHzf9YXdYsb5fUwWqw5vYLd4vvAHs8XdDWcZHbg9Zjdc ZPHY+20Bi8fOWXfZPe53H2fy6NuyitHj8ya5ALYoLpuU1JzMstQifbsEroxH848yFmwMr1i1 bT1bA2OrRxcjJ4eEgInErUPf2SFsMYkL99azdTFycQgJLGWU+HeoiwmmaM/NVVCJ6YwSD/5s YYJwJjBJtE06xwxSxSagLbFt+k0WEFtEwE2i6fBMVpAiZoF7jBIdk+axgiSEBUIk+hvawIpY BFQlPq36DWbzCnhILD82EegODqB1ChJzJtmAhDkFPCU+tG0Hu0IIqGT9ts+MIDMlBI6xS8z+ cZMdYo6AxLfJh1ggemUlNh1ghrhaUuLgihssExiFFzAyrGIUTS1ILihOSi8y1CtOzC0uzUvX S87P3cQIjI3T/5717mC8fcD6EGMy0LiJzFKiyfnA2MoriTc0NjOyMDUxNTYytzQjTVhJnDfp YVKQkEB6YklqdmpqQWpRfFFpTmrxIUYmDk6pBsa+6mNv71teyv957VP14Wt/I1X0tIuLJHiv z/8Z6iL/ZKveyh0JrooGjq0Wim0nI6fzm2ewXY4o/599SnTS/ITH95WOO0SnsUTbNexf+vaH 6t+7vf4ZKqfnhemyt4hNyk3yZlss8zW9bOn9TYmx4imL+XYm8BRdPdLutHuldt+U12L31vEw 7FBiKc5INNRiLipOBAC3R8KHowIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrLIsWRmVeSWpSXmKPExsVy+t9jQV3dNznBBudXWVvcWneO1eLA+4Ms FhveLGS2WPjwLrPFla/v2Swm3Z/AYvF91xd2ixnn9zFZrDq8gd3i+cIfzBZ3N5xldOD2mN1w kcVj77cFLB47Z91l97jffZzJo2/LKkaPz5vkAtiiGhhtMlITU1KLFFLzkvNTMvPSbZW8g+Od 403NDAx1DS0tzJUU8hJzU22VXHwCdN0yc4AOVFIoS8wpBQoFJBYXK+nbYZoQGuKmawHTGKHr GxIE12NkgAYS1jBmPJp/lLFgY3jFqm3r2RoYWz26GDk5JARMJPbcXMUGYYtJXLi3Hsjm4hAS mM4o8eDPFiYIZwKTRNukc8wgVWwC2hLbpt9kAbFFBNwkmg7PZAUpYha4xyjRMWkeK0hCWCBE or+hDayIRUBV4tOq32A2r4CHxPJjE9m7GDmA1ilIzJlkAxLmFPCU+NC2nQnEFgIqWb/tM+ME Rt4FjAyrGEVTC5ILipPSc430ihNzi0vz0vWS83M3MYIj75n0DsZVDRaHGAU4GJV4eF9MyQ4W Yk0sK67MPcQowcGsJMKreTgnWIg3JbGyKrUoP76oNCe1+BBjMtBRE5mlRJPzgUkhryTe0NjE 3NTY1NLEwsTMkjRhJXHeg63WgUIC6YklqdmpqQWpRTBbmDg4pRoYIxxach51pLJffMTVnMpX d0b9MevjNxohzh+F1+em1Nw5vrRj/b1+u3lbKtimVTvufWjq/u7O9p97Fxnd6GO+apDRny1r 8X6KZf9Sa6E9k7SXfJj/b+XVdyGXhdV8r1y/1ZXWL+N6QfSun/qzO3dnGs3Y/JD9IeM1S3+x gDVr7V8tMJ7PsZ9LVYmlOCPRUIu5qDgRADqaVBwAAwAA DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected X-Mailman-Approved-At: Sun, 11 May 2014 04:04:08 -0700 Cc: daniel.vetter@ffwll.ch, joshi@samsung.com, a.hajda@samsung.com, ajaynumb@gmail.com, prashanth.g@samsung.com, Ajay Kumar X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Spam-Status: No, score=-4.8 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable 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 implement basic panel controls as a drm_bridge so that the existing bridges can make use of it. The driver assumes that it is the last entity in the bridge chain. Signed-off-by: Ajay Kumar --- .../bindings/drm/bridge/bridge_panel.txt | 45 ++++ drivers/gpu/drm/bridge/Kconfig | 6 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/bridge_panel.c | 217 ++++++++++++++++++++ include/drm/bridge/bridge_panel.h | 40 ++++ 5 files changed, 309 insertions(+) create mode 100644 Documentation/devicetree/bindings/drm/bridge/bridge_panel.txt create mode 100644 drivers/gpu/drm/bridge/bridge_panel.c create mode 100644 include/drm/bridge/bridge_panel.h diff --git a/Documentation/devicetree/bindings/drm/bridge/bridge_panel.txt b/Documentation/devicetree/bindings/drm/bridge/bridge_panel.txt new file mode 100644 index 0000000..0f916b0 --- /dev/null +++ b/Documentation/devicetree/bindings/drm/bridge/bridge_panel.txt @@ -0,0 +1,45 @@ +Simple panel interface for chaining along with bridges + +Required properties: + - compatible: "drm-bridge,panel" + +Optional properties: + -lcd-en-gpio: + eDP panel LCD poweron GPIO. + Indicates which GPIO needs to be powered up as output + to powerup/enable the switch to the LCD panel. + -led-en-gpio: + eDP panel LED enable GPIO. + Indicates which GPIO needs to be powered up as output + to enable the backlight. + -panel-pre-enable-delay: + delay value in ms required for panel_pre_enable process + Delay in ms needed for the eDP panel LCD unit to + powerup, and delay needed between panel_VCC and + video_enable. + -panel-enable-delay: + delay value in ms required for panel_enable process + Delay in ms needed for the eDP panel backlight/LED unit + to powerup, and delay needed between video_enable and + BL_EN. + -panel-disable-delay: + delay value in ms required for panel_disable process + Delay in ms needed for the eDP panel backlight/LED unit + powerdown, and delay needed between BL_DISABLE and + video_disable. + -panel-post-disable-delay: + delay value in ms required for panel_post_disable process + Delay in ms needed for the eDP panel LCD unit to + to powerdown, and delay between video_disable and + panel_VCC going down. + +Example: + + bridge-panel { + compatible = "drm-bridge,panel"; + led-en-gpio = <&gpx3 0 1>; + panel-pre-enable-delay = <40>; + panel-enable-delay = <20>; + panel-disable-delay = <20>; + panel-post-disable-delay = <30>; + }; diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 884923f..654c5ea 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -3,3 +3,9 @@ config DRM_PTN3460 depends on DRM select DRM_KMS_HELPER ---help--- + +config DRM_BRIDGE_PANEL + tristate "dummy bridge panel" + depends on DRM + select DRM_KMS_HELPER + ---help--- diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index b4733e1..bf433cf 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -1,3 +1,4 @@ ccflags-y := -Iinclude/drm obj-$(CONFIG_DRM_PTN3460) += ptn3460.o +obj-$(CONFIG_DRM_BRIDGE_PANEL) += bridge_panel.o diff --git a/drivers/gpu/drm/bridge/bridge_panel.c b/drivers/gpu/drm/bridge/bridge_panel.c new file mode 100644 index 0000000..c629e93 --- /dev/null +++ b/drivers/gpu/drm/bridge/bridge_panel.c @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2014 Samsung Electronics Co., Ltd. + * + * 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 +#include +#include + +#include "drmP.h" + +#include "bridge/bridge_panel.h" + +struct bridge_panel { + struct drm_connector connector; + struct i2c_client *client; + struct drm_encoder *encoder; + struct drm_bridge *bridge; + struct regulator *backlight_fet; + struct regulator *lcd_fet; + bool backlight_fet_enabled; + bool lcd_fet_enabled; + int led_en_gpio; + int lcd_en_gpio; + int panel_pre_enable_delay; + int panel_enable_delay; + int panel_disable_delay; + int panel_post_disable_delay; +}; + +static void bridge_panel_pre_enable(struct drm_bridge *bridge) +{ + struct bridge_panel *panel = bridge->driver_private; + + if (!IS_ERR_OR_NULL(panel->lcd_fet)) + if (!panel->lcd_fet_enabled) { + if (regulator_enable(panel->lcd_fet)) + DRM_ERROR("Failed to enable LCD fet\n"); + panel->lcd_fet_enabled = true; + } + + if (gpio_is_valid(panel->lcd_en_gpio)) + gpio_set_value(panel->lcd_en_gpio, 1); + + msleep(panel->panel_pre_enable_delay); +} + +static void bridge_panel_enable(struct drm_bridge *bridge) +{ + struct bridge_panel *panel = bridge->driver_private; + + if (!IS_ERR_OR_NULL(panel->backlight_fet)) + if (!panel->backlight_fet_enabled) { + if (regulator_enable(panel->backlight_fet)) + DRM_ERROR("Failed to enable LED fet\n"); + panel->backlight_fet_enabled = true; + } + + msleep(panel->panel_enable_delay); + + if (gpio_is_valid(panel->led_en_gpio)) + gpio_set_value(panel->led_en_gpio, 1); +} + +static void bridge_panel_disable(struct drm_bridge *bridge) +{ + struct bridge_panel *panel = bridge->driver_private; + + if (gpio_is_valid(panel->led_en_gpio)) + gpio_set_value(panel->led_en_gpio, 0); + + if (!IS_ERR_OR_NULL(panel->backlight_fet)) + if (panel->backlight_fet_enabled) { + regulator_disable(panel->backlight_fet); + panel->backlight_fet_enabled = false; + } + + msleep(panel->panel_disable_delay); +} + +static void bridge_panel_post_disable(struct drm_bridge *bridge) +{ + struct bridge_panel *panel = bridge->driver_private; + + if (gpio_is_valid(panel->lcd_en_gpio)) + gpio_set_value(panel->lcd_en_gpio, 0); + + if (!IS_ERR_OR_NULL(panel->lcd_fet)) + if (panel->lcd_fet_enabled) { + regulator_disable(panel->lcd_fet); + panel->lcd_fet_enabled = false; + } + + msleep(panel->panel_post_disable_delay); +} + +void bridge_panel_destroy(struct drm_bridge *bridge) +{ + struct bridge_panel *panel = bridge->driver_private; + + drm_bridge_cleanup(bridge); + + if (gpio_is_valid(panel->lcd_en_gpio)) + gpio_free(panel->lcd_en_gpio); + if (gpio_is_valid(panel->led_en_gpio)) + gpio_free(panel->led_en_gpio); + /* Nothing else to free, we've got devm allocated memory */ +} + +struct drm_bridge_funcs bridge_panel_funcs = { + .pre_enable = bridge_panel_pre_enable, + .enable = bridge_panel_enable, + .disable = bridge_panel_disable, + .post_disable = bridge_panel_post_disable, + .destroy = bridge_panel_destroy, +}; + +struct drm_bridge *bridge_panel_init(struct drm_device *dev, + struct drm_encoder *encoder, + struct i2c_client *client, + struct device_node *node) +{ + int ret; + struct drm_bridge *bridge; + struct bridge_panel *panel; + + bridge = devm_kzalloc(dev->dev, sizeof(*bridge), GFP_KERNEL); + if (!bridge) { + DRM_ERROR("Failed to allocate drm bridge\n"); + return NULL; + } + + panel = devm_kzalloc(dev->dev, sizeof(*panel), GFP_KERNEL); + if (!panel) { + DRM_ERROR("Failed to allocate bridge panel\n"); + return NULL; + } + + panel->client = client; + panel->encoder = encoder; + panel->bridge = bridge; + + panel->lcd_en_gpio = of_get_named_gpio(node, "lcd-en-gpio", 0); + panel->lcd_en_gpio = of_get_named_gpio(node, "led-en-gpio", 0); + + of_property_read_u32(node, "panel-pre-enable-delay", + &panel->panel_pre_enable_delay); + of_property_read_u32(node, "panel-enable-delay", + &panel->panel_enable_delay); + of_property_read_u32(node, "panel-disable-delay", + &panel->panel_disable_delay); + of_property_read_u32(node, "panel-post-disable-delay", + &panel->panel_post_disable_delay); + + panel->lcd_fet = devm_regulator_get(dev->dev, "lcd_vdd"); + if (IS_ERR(panel->lcd_fet)) + return NULL; + + panel->backlight_fet = devm_regulator_get(dev->dev, "vcd_led"); + if (IS_ERR(panel->backlight_fet)) + return NULL; + + if (gpio_is_valid(panel->lcd_en_gpio)) { + ret = devm_gpio_request_one(dev->dev, panel->lcd_en_gpio, + GPIOF_OUT_INIT_LOW, "lcd_en_gpio"); + if (ret) { + DRM_ERROR("failed to get lcd-en gpio [%d]\n", ret); + return NULL; + } + } else { + panel->lcd_en_gpio = -ENODEV; + } + + if (gpio_is_valid(panel->led_en_gpio)) { + ret = devm_gpio_request_one(dev->dev, panel->led_en_gpio, + GPIOF_OUT_INIT_LOW, "led_en_gpio"); + if (ret) { + DRM_ERROR("failed to get led-en gpio [%d]\n", ret); + return NULL; + } + } else { + panel->led_en_gpio = -ENODEV; + } + + ret = drm_bridge_init(dev, bridge, &bridge_panel_funcs); + if (ret) { + DRM_ERROR("Failed to initialize bridge with drm\n"); + goto err; + } + + bridge->driver_private = panel; + + if (!encoder->bridge) + /* First entry in the bridge chain */ + encoder->bridge = bridge; + + return bridge; + +err: + if (gpio_is_valid(panel->lcd_en_gpio)) + gpio_free(panel->lcd_en_gpio); + if (gpio_is_valid(panel->led_en_gpio)) + gpio_free(panel->led_en_gpio); + return NULL; +} +EXPORT_SYMBOL(bridge_panel_init); diff --git a/include/drm/bridge/bridge_panel.h b/include/drm/bridge/bridge_panel.h new file mode 100644 index 0000000..7f0d662 --- /dev/null +++ b/include/drm/bridge/bridge_panel.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#ifndef _DRM_BRIDGE_PANEL_H_ +#define _DRM_BRIDGE_PANEL_H_ + +struct drm_device; +struct drm_encoder; +struct i2c_client; +struct device_node; + +#if defined(CONFIG_DRM_BRIDGE_PANEL) + +struct drm_bridge *bridge_panel_init(struct drm_device *dev, + struct drm_encoder *encoder, + struct i2c_client *client, + struct device_node *node); +#else + +static inline struct drm_bridge *bridge_panel_init(struct drm_device *dev, + struct drm_encoder *encoder, + struct i2c_client *client, + struct device_node *node) +{ + return 0; +} + +#endif + +#endif