[RFC PATCH v2] drm: improve various bridge devices support

Inki Dae inki.dae at samsung.com
Wed Mar 19 00:58:44 PDT 2014


This patch integrates existing drm_panel and drm_bridge frameworks
to one integrated framework, drm_hw_block.

For this, I had already sent a email to make a discussion[1] about
how we could support all bridges, one bridge between crtc and encoder,
and another bridge between encoder and panel.

Now existing drm_panel could be used only for real panel, and
drm_bridge only for lvds bridge devices between encoder and panel.
However, some embedded SoC have bridge devices of other type
between crtc and encoder, i.e. Image Enhancer chip.

So the existing encoder driver couldn't control such bridge commonly
using existing drm_bridge because only drm_encoder has drm_bridge.

Below shows how encoder driver could control bridge device using existing
drm_bridge.

display controller ----- bridge1 ----- mipi dsi ----- bridge2 ----- panel
                                          |              /|\         /|\
                                          |---------------|           |
                                      controlled by drm_bridge        |
                                          |                           |
                                          |---------------------------|
                                             controlled by drm_panel

In the other hands, drm_panel has no any dependency of drm_encoder, and
its infrastructure could be used by crtc driver with a little change.
So this integrated framework basically uses existing infrastructure of
drm_panel, and just adds drm_lvds structure to it for backward compatibility.

And then, we could add a new bridge type, i.e. drm_enhancer in the near future.
So this patch is just ready for that.

As a result, if we add drm_enhancer, crtc driver could control a bridge device
between crtc and encoder like below.

display controller ----- bridge1 ----- mipi dsi ----- bridge2 ----- panel
       |                   /|\            |              /|\        /|\
       |--------------------|             |---------------|          |
     controlled by drm_enhancer         controlled by drm_lvds       |
                                          |                          |
                                          |--------------------------|
                                            controlled by drm_panel

Changelog v2:
- Call enable and disable callback according to bridge type.
- Correct module description.

[1] http://www.spinics.net/lists/dri-devel/msg55555.html

Signed-off-by: Inki Dae <inki.dae at samsung.com>
---
 drivers/gpu/drm/Kconfig              |    4 ++
 drivers/gpu/drm/Makefile             |    2 +-
 drivers/gpu/drm/drm_hw_block.c       |  104 ++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_panel.c          |  100 --------------------------
 drivers/gpu/drm/exynos/Kconfig       |    1 +
 drivers/gpu/drm/panel/Kconfig        |    1 +
 drivers/gpu/drm/panel/panel-simple.c |   37 +++++-----
 drivers/gpu/drm/tegra/drm.h          |    2 +-
 drivers/gpu/drm/tegra/dsi.c          |   10 +--
 drivers/gpu/drm/tegra/output.c       |   22 +++---
 include/drm/drm_hw_block.h           |  127 ++++++++++++++++++++++++++++++++++
 include/drm/drm_panel.h              |   82 ----------------------
 12 files changed, 274 insertions(+), 218 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_hw_block.c
 delete mode 100644 drivers/gpu/drm/drm_panel.c
 create mode 100644 include/drm/drm_hw_block.h
 delete mode 100644 include/drm/drm_panel.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 8e7fa4d..020a0f2 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -24,6 +24,10 @@ config DRM_MIPI_DSI
 	bool
 	depends on DRM
 
+config DRM_HW_BLOCK
+	bool
+	depends on DRM
+
 config DRM_USB
 	tristate
 	depends on DRM
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 292a79d..a943663 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -18,7 +18,7 @@ drm-y       :=	drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
 drm-$(CONFIG_PCI) += ati_pcigart.o
-drm-$(CONFIG_DRM_PANEL) += drm_panel.o
+drm-$(CONFIG_DRM_HW_BLOCK) += drm_hw_block.o
 
 drm-usb-y   := drm_usb.o
 
diff --git a/drivers/gpu/drm/drm_hw_block.c b/drivers/gpu/drm/drm_hw_block.c
new file mode 100644
index 0000000..9ba73a8
--- /dev/null
+++ b/drivers/gpu/drm/drm_hw_block.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2013, NVIDIA Corporation.  All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_hw_block.h>
+
+static DEFINE_MUTEX(hw_block_lock);
+static LIST_HEAD(hw_block_list);
+
+void drm_hw_block_init(struct drm_hw_block *block)
+{
+	INIT_LIST_HEAD(&block->list);
+}
+EXPORT_SYMBOL(drm_hw_block_init);
+
+int drm_hw_block_add(struct drm_hw_block *block)
+{
+	mutex_lock(&hw_block_lock);
+	list_add_tail(&block->list, &hw_block_list);
+	mutex_unlock(&hw_block_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_hw_block_add);
+
+void drm_hw_block_remove(struct drm_hw_block *block)
+{
+	mutex_lock(&hw_block_lock);
+	list_del_init(&block->list);
+	mutex_unlock(&hw_block_lock);
+}
+EXPORT_SYMBOL(drm_hw_block_remove);
+
+int drm_hw_block_attach(struct drm_hw_block *block,
+			struct drm_connector *connector)
+{
+	if (block->type == DRM_HW_BLOCK_PANEL) {
+		if (block->connector)
+			return -EBUSY;
+
+		block->connector = connector;
+	}
+
+	block->drm = connector->dev;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_hw_block_attach);
+
+int drm_hw_block_detach(struct drm_hw_block *block)
+{
+	block->connector = NULL;
+	block->drm = NULL;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_hw_block_detach);
+
+#ifdef CONFIG_OF
+struct drm_hw_block *of_drm_find_hw_block(struct device_node *np)
+{
+	struct drm_hw_block *block;
+
+	mutex_lock(&hw_block_lock);
+
+	list_for_each_entry(block, &hw_block_list, list) {
+		if (block->dev->of_node == np) {
+			mutex_unlock(&hw_block_lock);
+			return block;
+		}
+	}
+
+	mutex_unlock(&hw_block_lock);
+	return NULL;
+}
+EXPORT_SYMBOL(of_drm_find_hw_block);
+#endif
+
+MODULE_AUTHOR("Thierry Reding <treding at nvidia.com>");
+MODULE_DESCRIPTION("DRM hardware block infrastructure");
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c
deleted file mode 100644
index 2ef988e..0000000
--- a/drivers/gpu/drm/drm_panel.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2013, NVIDIA Corporation.  All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/err.h>
-#include <linux/module.h>
-
-#include <drm/drm_crtc.h>
-#include <drm/drm_panel.h>
-
-static DEFINE_MUTEX(panel_lock);
-static LIST_HEAD(panel_list);
-
-void drm_panel_init(struct drm_panel *panel)
-{
-	INIT_LIST_HEAD(&panel->list);
-}
-EXPORT_SYMBOL(drm_panel_init);
-
-int drm_panel_add(struct drm_panel *panel)
-{
-	mutex_lock(&panel_lock);
-	list_add_tail(&panel->list, &panel_list);
-	mutex_unlock(&panel_lock);
-
-	return 0;
-}
-EXPORT_SYMBOL(drm_panel_add);
-
-void drm_panel_remove(struct drm_panel *panel)
-{
-	mutex_lock(&panel_lock);
-	list_del_init(&panel->list);
-	mutex_unlock(&panel_lock);
-}
-EXPORT_SYMBOL(drm_panel_remove);
-
-int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector)
-{
-	if (panel->connector)
-		return -EBUSY;
-
-	panel->connector = connector;
-	panel->drm = connector->dev;
-
-	return 0;
-}
-EXPORT_SYMBOL(drm_panel_attach);
-
-int drm_panel_detach(struct drm_panel *panel)
-{
-	panel->connector = NULL;
-	panel->drm = NULL;
-
-	return 0;
-}
-EXPORT_SYMBOL(drm_panel_detach);
-
-#ifdef CONFIG_OF
-struct drm_panel *of_drm_find_panel(struct device_node *np)
-{
-	struct drm_panel *panel;
-
-	mutex_lock(&panel_lock);
-
-	list_for_each_entry(panel, &panel_list, list) {
-		if (panel->dev->of_node == np) {
-			mutex_unlock(&panel_lock);
-			return panel;
-		}
-	}
-
-	mutex_unlock(&panel_lock);
-	return NULL;
-}
-EXPORT_SYMBOL(of_drm_find_panel);
-#endif
-
-MODULE_AUTHOR("Thierry Reding <treding at nvidia.com>");
-MODULE_DESCRIPTION("DRM panel infrastructure");
-MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index f227f54..4dbdd7a 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -8,6 +8,7 @@ config DRM_EXYNOS
 	select FB_CFB_IMAGEBLIT
 	select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
 	select VIDEOMODE_HELPERS
+	select DRM_PANEL
 	help
 	  Choose this option if you have a Samsung SoC EXYNOS chipset.
 	  If M is selected the module will be called exynosdrm.
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 3e0f13d..db471a0 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -1,6 +1,7 @@
 config DRM_PANEL
 	bool
 	depends on DRM
+	select DRM_HW_BLOCK
 	help
 	  Panel registration and lookup framework.
 
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 3e611af..f304f66 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -32,7 +32,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_mipi_dsi.h>
-#include <drm/drm_panel.h>
+#include <drm/drm_hw_block.h>
 
 struct panel_desc {
 	const struct drm_display_mode *modes;
@@ -48,7 +48,7 @@ struct panel_desc {
 #define GPIO_ACTIVE_LOW	(1 << 0)
 
 struct panel_simple {
-	struct drm_panel base;
+	struct drm_hw_block base;
 	bool enabled;
 
 	const struct panel_desc *desc;
@@ -61,9 +61,9 @@ struct panel_simple {
 	int enable_gpio;
 };
 
-static inline struct panel_simple *to_panel_simple(struct drm_panel *panel)
+static inline struct panel_simple *to_panel_simple(struct drm_hw_block *block)
 {
-	return container_of(panel, struct panel_simple, base);
+	return container_of(block, struct panel_simple, base);
 }
 
 static int panel_simple_get_fixed_modes(struct panel_simple *panel)
@@ -98,9 +98,9 @@ static int panel_simple_get_fixed_modes(struct panel_simple *panel)
 	return num;
 }
 
-static int panel_simple_disable(struct drm_panel *panel)
+static int panel_simple_disable(struct drm_hw_block *block)
 {
-	struct panel_simple *p = to_panel_simple(panel);
+	struct panel_simple *p = to_panel_simple(block);
 
 	if (!p->enabled)
 		return 0;
@@ -123,9 +123,9 @@ static int panel_simple_disable(struct drm_panel *panel)
 	return 0;
 }
 
-static int panel_simple_enable(struct drm_panel *panel)
+static int panel_simple_enable(struct drm_hw_block *block)
 {
-	struct panel_simple *p = to_panel_simple(panel);
+	struct panel_simple *p = to_panel_simple(block);
 	int err;
 
 	if (p->enabled)
@@ -133,7 +133,7 @@ static int panel_simple_enable(struct drm_panel *panel)
 
 	err = regulator_enable(p->supply);
 	if (err < 0) {
-		dev_err(panel->dev, "failed to enable supply: %d\n", err);
+		dev_err(block->dev, "failed to enable supply: %d\n", err);
 		return err;
 	}
 
@@ -154,16 +154,16 @@ static int panel_simple_enable(struct drm_panel *panel)
 	return 0;
 }
 
-static int panel_simple_get_modes(struct drm_panel *panel)
+static int panel_simple_get_modes(struct drm_hw_block *block)
 {
-	struct panel_simple *p = to_panel_simple(panel);
+	struct panel_simple *p = to_panel_simple(block);
 	int num = 0;
 
 	/* probe EDID if a DDC bus is available */
 	if (p->ddc) {
-		struct edid *edid = drm_get_edid(panel->connector, p->ddc);
+		struct edid *edid = drm_get_edid(block->connector, p->ddc);
 		if (edid) {
-			num += drm_add_edid_modes(panel->connector, edid);
+			num += drm_add_edid_modes(block->connector, edid);
 			kfree(edid);
 		}
 	}
@@ -246,11 +246,12 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
 		}
 	}
 
-	drm_panel_init(&panel->base);
+	panel->base.type = DRM_HW_BLOCK_PANEL;
+	drm_hw_block_init(&panel->base);
 	panel->base.dev = dev;
-	panel->base.funcs = &panel_simple_funcs;
+	panel->base.panel_funcs = &panel_simple_funcs;
 
-	err = drm_panel_add(&panel->base);
+	err = drm_hw_block_add(&panel->base);
 	if (err < 0)
 		goto free_ddc;
 
@@ -275,8 +276,8 @@ static int panel_simple_remove(struct device *dev)
 {
 	struct panel_simple *panel = dev_get_drvdata(dev);
 
-	drm_panel_detach(&panel->base);
-	drm_panel_remove(&panel->base);
+	drm_hw_block_detach(&panel->base);
+	drm_hw_block_remove(&panel->base);
 
 	panel_simple_disable(&panel->base);
 
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index bf1cac7..a8ec39f 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -194,7 +194,7 @@ struct tegra_output {
 	const struct tegra_output_ops *ops;
 	enum tegra_output_type type;
 
-	struct drm_panel *panel;
+	struct drm_hw_block *block;
 	struct i2c_adapter *ddc;
 	const struct edid *edid;
 	unsigned int hpd_irq;
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index d452faab..012a1ba 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -29,7 +29,7 @@
 #include <linux/reset.h>
 
 #include <drm/drm_mipi_dsi.h>
-#include <drm/drm_panel.h>
+#include <drm/drm_hw_block.h>
 
 #include <video/mipi_display.h>
 
@@ -792,8 +792,8 @@ static int tegra_dsi_host_attach(struct mipi_dsi_host *host,
 	dsi->format = device->format;
 	dsi->lanes = device->lanes;
 
-	output->panel = of_drm_find_panel(device->dev.of_node);
-	if (output->panel) {
+	output->block = of_drm_find_hw_block(device->dev.of_node);
+	if (output->block) {
 		if (output->connector.dev)
 			drm_helper_hpd_irq_event(output->connector.dev);
 	}
@@ -807,11 +807,11 @@ static int tegra_dsi_host_detach(struct mipi_dsi_host *host,
 	struct tegra_dsi *dsi = host_to_tegra(host);
 	struct tegra_output *output = &dsi->output;
 
-	if (output->panel && &device->dev == output->panel->dev) {
+	if (output->block && &device->dev == output->block->dev) {
 		if (output->connector.dev)
 			drm_helper_hpd_irq_event(output->connector.dev);
 
-		output->panel = NULL;
+		output->block = NULL;
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c
index f1b5030..c2e0740 100644
--- a/drivers/gpu/drm/tegra/output.c
+++ b/drivers/gpu/drm/tegra/output.c
@@ -9,7 +9,7 @@
 
 #include <linux/of_gpio.h>
 
-#include <drm/drm_panel.h>
+#include <drm/drm_hw_block.h>
 #include "drm.h"
 
 static int tegra_connector_get_modes(struct drm_connector *connector)
@@ -18,8 +18,8 @@ static int tegra_connector_get_modes(struct drm_connector *connector)
 	struct edid *edid = NULL;
 	int err = 0;
 
-	if (output->panel) {
-		err = output->panel->funcs->get_modes(output->panel);
+	if (output->block) {
+		err = output->block->panel_funcs->get_modes(output->block);
 		if (err > 0)
 			return err;
 	}
@@ -79,7 +79,7 @@ tegra_connector_detect(struct drm_connector *connector, bool force)
 		else
 			status = connector_status_connected;
 	} else {
-		if (!output->panel)
+		if (!output->block)
 			status = connector_status_disconnected;
 		else
 			status = connector_status_connected;
@@ -128,14 +128,14 @@ static const struct drm_encoder_funcs encoder_funcs = {
 static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode)
 {
 	struct tegra_output *output = encoder_to_output(encoder);
-	struct drm_panel *panel = output->panel;
+	struct drm_hw_block *block = output->block;
 
 	if (mode != DRM_MODE_DPMS_ON) {
-		drm_panel_disable(panel);
+		drm_hw_block_disable(block);
 		tegra_output_disable(output);
 	} else {
 		tegra_output_enable(output);
-		drm_panel_enable(panel);
+		drm_hw_block_enable(block);
 	}
 }
 
@@ -195,8 +195,8 @@ int tegra_output_probe(struct tegra_output *output)
 
 	panel = of_parse_phandle(output->of_node, "nvidia,panel", 0);
 	if (panel) {
-		output->panel = of_drm_find_panel(panel);
-		if (!output->panel)
+		output->block = of_drm_find_hw_block(panel);
+		if (!output->block)
 			return -EPROBE_DEFER;
 
 		of_node_put(panel);
@@ -300,8 +300,8 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
 	drm_connector_helper_add(&output->connector, &connector_helper_funcs);
 	output->connector.dpms = DRM_MODE_DPMS_OFF;
 
-	if (output->panel)
-		drm_panel_attach(output->panel, &output->connector);
+	if (output->block)
+		drm_hw_block_attach(output->block, &output->connector);
 
 	drm_encoder_init(drm, &output->encoder, &encoder_funcs, encoder);
 	drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs);
diff --git a/include/drm/drm_hw_block.h b/include/drm/drm_hw_block.h
new file mode 100644
index 0000000..81fb308
--- /dev/null
+++ b/include/drm/drm_hw_block.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2013, NVIDIA Corporation.  All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __DRM_HW_BLOCK_H__
+#define __DRM_HW_BLOCK_H__
+
+#include <linux/list.h>
+
+struct drm_connector;
+struct drm_device;
+struct drm_hw_block;
+struct drm_display_mode;
+
+enum drm_block_type {
+	DRM_HW_BLOCK_PANEL,
+	DRM_HW_BLOCK_LVDS,
+	/* TODO. add other bridge type types if needed. */
+};
+struct drm_panel_funcs {
+	int (*disable)(struct drm_hw_block *block);
+	int (*enable)(struct drm_hw_block *block);
+	int (*get_modes)(struct drm_hw_block *block);
+};
+
+struct drm_lvds_funcs {
+	bool (*mode_fixup)(struct drm_hw_block *bridge,
+				const struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode);
+	int (*disable)(struct drm_hw_block *block);
+	int (*enable)(struct drm_hw_block *block);
+	void (*mode_set)(struct drm_hw_block *block,
+				struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode);
+	void (*pre_enable)(struct drm_hw_block *block);
+	void (*destroy)(struct drm_hw_block *block);
+};
+
+struct drm_hw_block {
+	enum drm_block_type type;
+	struct device *dev;
+	struct drm_device *drm;
+
+	struct drm_connector *connector;
+
+	const struct drm_panel_funcs *panel_funcs;
+	const struct drm_lvds_funcs *lvds_funcs;
+
+	/* TODO. Add callbacks for other bridge types if needed. */
+
+	struct list_head list;
+};
+
+static inline int drm_hw_block_disable(struct drm_hw_block *block)
+{
+	if (!block)
+		return -EINVAL;
+
+	if (block->type == DRM_HW_BLOCK_PANEL) {
+		if (block->panel_funcs && block->panel_funcs->disable)
+			return block->panel_funcs->disable(block);
+	}
+
+	if (block->type == DRM_HW_BLOCK_LVDS) {
+		if (block->lvds_funcs && block->lvds_funcs->disable)
+			return block->lvds_funcs->disable(block);
+	}
+
+	return -ENOSYS;
+}
+
+static inline int drm_hw_block_enable(struct drm_hw_block *block)
+{
+	if (!block)
+		return -EINVAL;
+
+	if (block->type == DRM_HW_BLOCK_PANEL) {
+		if (block->panel_funcs && block->panel_funcs->enable)
+			return block->panel_funcs->enable(block);
+	}
+
+	if (block->type == DRM_HW_BLOCK_LVDS) {
+		if (block->lvds_funcs && block->lvds_funcs->enable)
+			return block->lvds_funcs->enable(block);
+	}
+
+	return -ENOSYS;
+}
+
+void drm_hw_block_init(struct drm_hw_block *block);
+
+int drm_hw_block_add(struct drm_hw_block *block);
+void drm_hw_block_remove(struct drm_hw_block *block);
+
+int drm_hw_block_attach(struct drm_hw_block *block,
+			struct drm_connector *connector);
+int drm_hw_block_detach(struct drm_hw_block *block);
+
+#ifdef CONFIG_OF
+struct drm_hw_block *of_drm_find_hw_block(struct device_node *np);
+#else
+static inline struct drm_hw_block *of_drm_find_hw_block(struct device_node *np)
+{
+	return NULL;
+}
+#endif
+
+#endif
diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h
deleted file mode 100644
index c2ab77a..0000000
--- a/include/drm/drm_panel.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2013, NVIDIA Corporation.  All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef __DRM_PANEL_H__
-#define __DRM_PANEL_H__
-
-#include <linux/list.h>
-
-struct drm_connector;
-struct drm_device;
-struct drm_panel;
-
-struct drm_panel_funcs {
-	int (*disable)(struct drm_panel *panel);
-	int (*enable)(struct drm_panel *panel);
-	int (*get_modes)(struct drm_panel *panel);
-};
-
-struct drm_panel {
-	struct drm_device *drm;
-	struct drm_connector *connector;
-	struct device *dev;
-
-	const struct drm_panel_funcs *funcs;
-
-	struct list_head list;
-};
-
-static inline int drm_panel_disable(struct drm_panel *panel)
-{
-	if (panel && panel->funcs && panel->funcs->disable)
-		return panel->funcs->disable(panel);
-
-	return panel ? -ENOSYS : -EINVAL;
-}
-
-static inline int drm_panel_enable(struct drm_panel *panel)
-{
-	if (panel && panel->funcs && panel->funcs->enable)
-		return panel->funcs->enable(panel);
-
-	return panel ? -ENOSYS : -EINVAL;
-}
-
-void drm_panel_init(struct drm_panel *panel);
-
-int drm_panel_add(struct drm_panel *panel);
-void drm_panel_remove(struct drm_panel *panel);
-
-int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector);
-int drm_panel_detach(struct drm_panel *panel);
-
-#ifdef CONFIG_OF
-struct drm_panel *of_drm_find_panel(struct device_node *np);
-#else
-static inline struct drm_panel *of_drm_find_panel(struct device_node *np)
-{
-	return NULL;
-}
-#endif
-
-#endif
-- 
1.7.9.5



More information about the dri-devel mailing list