From patchwork Tue Apr 29 19:57:42 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 4088921 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 DEBC6BFF02 for ; Tue, 29 Apr 2014 19:57:57 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C52AA20172 for ; Tue, 29 Apr 2014 19:57:56 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id B64032021F for ; Tue, 29 Apr 2014 19:57:55 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C47856EAB1; Tue, 29 Apr 2014 12:57:54 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-qg0-f44.google.com (mail-qg0-f44.google.com [209.85.192.44]) by gabe.freedesktop.org (Postfix) with ESMTP id 0DB926EAAE for ; Tue, 29 Apr 2014 12:57:51 -0700 (PDT) Received: by mail-qg0-f44.google.com with SMTP id q108so829683qgd.31 for ; Tue, 29 Apr 2014 12:57:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Crlsslr4QNF9VEfOwiCHxdVdyu3HREcZv+IlszSSBTo=; b=W2BBJHj8hp53vIHYq1BMw1luGCZk2ZrPA1fF5WIkukXJA/n5dXiW4GCv1WwFihSauW 36QcLDprNRiQt77w4fQiTUL0rSXJ4HbBeNTJMOHBvwmzjXzRyU9ssbjaRncHeyP8RDDl xDjMnrB327GPFRLhq0hIGaDXcy3w1QF2CQBe+s0DQaopYrLGTp4UIysywbBms3mrbbJ4 nzrxPUGw7gs3QJ5pWqqriXYove642ZgUfCncMZLjbqcsgFOGZEiy5lb8hEL7Vz1HWLqW wo9dxnvKLUPk1ZtRmitD8pdQMh0ItZrkj7iKWMbAyRaRW77dfYk9AjYSs2ttp1ZwolGn U/2w== X-Received: by 10.140.46.53 with SMTP id j50mr1782281qga.27.1398801471607; Tue, 29 Apr 2014 12:57:51 -0700 (PDT) Received: from localhost (pool-108-20-245-143.bstnma.east.verizon.net. [108.20.245.143]) by mx.google.com with ESMTPSA id m2sm41376105qac.3.2014.04.29.12.57.49 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 29 Apr 2014 12:57:50 -0700 (PDT) From: Rob Clark To: dri-devel@lists.freedesktop.org Subject: [RFC 1/2] drm/bridge: add composite and panel bridges Date: Tue, 29 Apr 2014 15:57:42 -0400 Message-Id: <1398801463-29732-2-git-send-email-robdclark@gmail.com> X-Mailer: git-send-email 1.9.0 In-Reply-To: <1398801463-29732-1-git-send-email-robdclark@gmail.com> References: <1398801463-29732-1-git-send-email-robdclark@gmail.com> Cc: 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.7 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID, 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 Signed-off-by: Rob Clark --- drivers/gpu/drm/bridge/Makefile | 2 + drivers/gpu/drm/bridge/drm_bridge_util.c | 251 +++++++++++++++++++++++++++++++ drivers/gpu/drm/bridge/drm_bridge_util.h | 29 ++++ 3 files changed, 282 insertions(+) create mode 100644 drivers/gpu/drm/bridge/drm_bridge_util.c create mode 100644 drivers/gpu/drm/bridge/drm_bridge_util.h diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index b4733e1..da6b301 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -1,3 +1,5 @@ ccflags-y := -Iinclude/drm obj-$(CONFIG_DRM_PTN3460) += ptn3460.o +# TODO kconfig for drivers who use this to select it.. +obj-y += drm_bridge_util.o \ No newline at end of file diff --git a/drivers/gpu/drm/bridge/drm_bridge_util.c b/drivers/gpu/drm/bridge/drm_bridge_util.c new file mode 100644 index 0000000..89964b2 --- /dev/null +++ b/drivers/gpu/drm/bridge/drm_bridge_util.c @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2014 Red Hat + * Author: Rob Clark + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * 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. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "drm_bridge_util.h" + +/* + * Composite Bridge: + */ + +/** + * drm_composite_bridge - helper bridge class to construct a graph + * with multiple actual bridges + */ +struct drm_composite_bridge { + struct drm_bridge base; + struct drm_bridge *b1, *b2; +}; +#define to_composite_bridge(x) container_of(x, struct drm_composite_bridge, base) + +static bool +composite_bridge_mode_fixup(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_composite_bridge *cbridge = to_composite_bridge(bridge); + struct drm_bridge *b1 = cbridge->b1; + struct drm_bridge *b2 = cbridge->b2; + + if (b1->funcs->mode_fixup) + if (!b1->funcs->mode_fixup(b1, mode, adjusted_mode)) + return false; + if (b2->funcs->mode_fixup) + if (!b2->funcs->mode_fixup(b2, mode, adjusted_mode)) + return false; + + return true; +} + +static void +composite_bridge_mode_set(struct drm_bridge *bridge, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_composite_bridge *cbridge = to_composite_bridge(bridge); + struct drm_bridge *b1 = cbridge->b1; + struct drm_bridge *b2 = cbridge->b2; + + if (b1->funcs->mode_set) + b1->funcs->mode_set(b1, mode, adjusted_mode); + if (b2->funcs->mode_set) + b2->funcs->mode_set(b2, mode, adjusted_mode); +} + +static void +composite_bridge_disable(struct drm_bridge *bridge) +{ + struct drm_composite_bridge *cbridge = to_composite_bridge(bridge); + struct drm_bridge *b1 = cbridge->b1; + struct drm_bridge *b2 = cbridge->b2; + + /* note: order inverted in disable path: */ + b2->funcs->disable(b2); + b1->funcs->disable(b1); +} + +static void +composite_bridge_post_disable(struct drm_bridge *bridge) +{ + struct drm_composite_bridge *cbridge = to_composite_bridge(bridge); + struct drm_bridge *b1 = cbridge->b1; + struct drm_bridge *b2 = cbridge->b2; + + /* note: order inverted in disable path: */ + b2->funcs->post_disable(b2); + b1->funcs->post_disable(b1); +} + +static void +composite_bridge_pre_enable(struct drm_bridge *bridge) +{ + struct drm_composite_bridge *cbridge = to_composite_bridge(bridge); + struct drm_bridge *b1 = cbridge->b1; + struct drm_bridge *b2 = cbridge->b2; + + b1->funcs->pre_enable(b1); + b2->funcs->pre_enable(b2); +} + +static void +composite_bridge_enable(struct drm_bridge *bridge) +{ + struct drm_composite_bridge *cbridge = to_composite_bridge(bridge); + struct drm_bridge *b1 = cbridge->b1; + struct drm_bridge *b2 = cbridge->b2; + + b1->funcs->enable(b1); + b2->funcs->enable(b2); +} + +static void +composite_bridge_destroy(struct drm_bridge *bridge) +{ + struct drm_composite_bridge *cbridge = to_composite_bridge(bridge); + struct drm_bridge *b1 = cbridge->b1; + struct drm_bridge *b2 = cbridge->b2; + + b1->funcs->destroy(b1); + b2->funcs->destroy(b2); + + kfree(cbridge); +} + +static const struct drm_bridge_funcs composite_bridge_funcs = { + .mode_fixup = composite_bridge_mode_fixup, + .disable = composite_bridge_disable, + .post_disable = composite_bridge_post_disable, + .mode_set = composite_bridge_mode_set, + .pre_enable = composite_bridge_pre_enable, + .enable = composite_bridge_enable, + .destroy = composite_bridge_destroy, +}; + +struct drm_bridge * drm_composite_bridge_init(struct drm_bridge *b1, + struct drm_bridge *b2) +{ + struct drm_bridge *bridge = NULL; + struct drm_composite_bridge *cbridge; + int ret; + + WARN_ON(b1->dev != b2->dev); + + cbridge = kzalloc(sizeof(*cbridge), GFP_KERNEL); + if (!cbridge) { + ret = -ENOMEM; + goto fail; + } + + bridge = &cbridge->base; + + cbridge->b1 = b1; + cbridge->b2 = b2; + + drm_bridge_init(b1->dev, bridge, &composite_bridge_funcs); + + return bridge; + +fail: + if (bridge) + composite_bridge_destroy(bridge); + + return ERR_PTR(ret); +} + +/* + * Panel Bridge: + */ + +/** + * drm_panel_bridge - helper to chain up a panel + */ +struct drm_panel_bridge { + struct drm_bridge base; + struct drm_panel *panel; +}; +#define to_panel_bridge(x) container_of(x, struct drm_panel_bridge, base) + +static void +panel_bridge_disable(struct drm_bridge *bridge) +{ + struct drm_panel_bridge *pbridge = to_panel_bridge(bridge); + drm_panel_disable(pbridge->panel); +} + +static void +panel_bridge_post_disable(struct drm_bridge *bridge) +{ +//TODO +// struct drm_panel_bridge *pbridge = to_panel_bridge(bridge); +// drm_panel_post_disable(pbridge->panel); +} + +static void +panel_bridge_pre_enable(struct drm_bridge *bridge) +{ +//TODO +// struct drm_panel_bridge *pbridge = to_panel_bridge(bridge); +// drm_panel_pre_enable(pbridge->panel); +} + +static void +panel_bridge_enable(struct drm_bridge *bridge) +{ + struct drm_panel_bridge *pbridge = to_panel_bridge(bridge); + drm_panel_enable(pbridge->panel); +} + +static void +panel_bridge_destroy(struct drm_bridge *bridge) +{ + struct drm_panel_bridge *pbridge = to_panel_bridge(bridge); + kfree(pbridge); +} + +static const struct drm_bridge_funcs panel_bridge_funcs = { + .disable = panel_bridge_disable, + .post_disable = panel_bridge_post_disable, + .pre_enable = panel_bridge_pre_enable, + .enable = panel_bridge_enable, + .destroy = panel_bridge_destroy, +}; + +struct drm_bridge * drm_panel_bridge_init(struct drm_panel *panel) +{ + struct drm_bridge *bridge = NULL; + struct drm_panel_bridge *pbridge; + int ret; + + pbridge = kzalloc(sizeof(*pbridge), GFP_KERNEL); + if (!pbridge) { + ret = -ENOMEM; + goto fail; + } + + bridge = &pbridge->base; + + pbridge->panel = panel; + + drm_bridge_init(panel->drm, bridge, &panel_bridge_funcs); + + return bridge; + +fail: + if (bridge) + panel_bridge_destroy(bridge); + + return ERR_PTR(ret); +} diff --git a/drivers/gpu/drm/bridge/drm_bridge_util.h b/drivers/gpu/drm/bridge/drm_bridge_util.h new file mode 100644 index 0000000..4f7a994 --- /dev/null +++ b/drivers/gpu/drm/bridge/drm_bridge_util.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2014 Red Hat + * Author: Rob Clark + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * 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. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#ifndef DRM_BRIDGE_UTIL_H_ +#define DRM_BRIDGE_UTIL_H_ + +#include "drmP.h" +#include "drm_crtc.h" +#include "drm_panel.h" + +struct drm_bridge * drm_composite_bridge_init(struct drm_bridge *b1, + struct drm_bridge *b2); +struct drm_bridge * drm_panel_bridge_init(struct drm_panel *panel); + +#endif /* DRM_BRIDGE_UTIL_H_ */