linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC 0/5] drm/tegra: Convert to master/component framework
@ 2014-04-22 15:09 Thierry Reding
  2014-04-22 15:09 ` [RFC 1/5] drivers/base: Allow multiple masters per device Thierry Reding
                   ` (5 more replies)
  0 siblings, 6 replies; 12+ messages in thread
From: Thierry Reding @ 2014-04-22 15:09 UTC (permalink / raw)
  To: dri-devel; +Cc: Greg Kroah-Hartman, Russell King, linux-kernel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

Hi,

This series converts the Tegra DRM driver to the master/component
framework. The length of the series and the list of people in Cc is
mostly due to the fact that Tegra has some special requirements as
opposed to other drivers and therefore requires some changes outside
of DRM.

Patches 1 and 2 make some changes to the master/component framework
which are necessary to convert Tegra DRM to use it. Note that since I'm
looking for early review I haven't converted any of the existing users
since I'm not sure if these are acceptable changes.

Patch 3 adds a new interface framework that supplements the master/
component framework and can be used in situations where there is no
struct device * that a driver can bind to.

A new function is introduced in patch 4 which can be used to get rid of
the DRM bus infrastructure in individual drivers. It should be able to
replace the requirement of having a drm_bus for all USB and platform
DRM drivers. For backwards-compatibility with legacy PCI drivers some-
thing different will probably be needed.

Finally, patch 5 converts the Tegra DRM driver over to using the master/
component framework using the above four patches.

Each patch has a somewhat more elaborate description of why it is needed
or what problem it solves. The patchset applies on top of linux-next
with Daniel's DRM cleanup series applied.

I welcome any questions or comments you might have.

Thierry

Thierry Reding (5):
  drivers/base: Allow multiple masters per device
  drivers/base: Allow driver-data to be attached to a master
  drivers/base: Add interface framework
  drm: Introduce drm_set_unique()
  drm/tegra: Convert to master/component framework

 drivers/base/Makefile          |   2 +-
 drivers/base/component.c       |  31 ++-
 drivers/base/interface.c       | 186 ++++++++++++++
 drivers/gpu/drm/drm_ioctl.c    |  37 ++-
 drivers/gpu/drm/drm_stub.c     |   1 +
 drivers/gpu/drm/tegra/Makefile |   1 -
 drivers/gpu/drm/tegra/bus.c    |  64 -----
 drivers/gpu/drm/tegra/dc.c     |  58 ++---
 drivers/gpu/drm/tegra/drm.c    | 171 +++++++++----
 drivers/gpu/drm/tegra/drm.h    |  27 +-
 drivers/gpu/drm/tegra/dsi.c    | 144 +++++------
 drivers/gpu/drm/tegra/gr2d.c   |  78 +++---
 drivers/gpu/drm/tegra/gr3d.c   |  77 +++---
 drivers/gpu/drm/tegra/hdmi.c   |  69 ++---
 drivers/gpu/drm/tegra/sor.c    |  71 ++----
 drivers/gpu/host1x/Makefile    |   1 -
 drivers/gpu/host1x/bus.c       | 553 -----------------------------------------
 drivers/gpu/host1x/bus.h       |  29 ---
 drivers/gpu/host1x/dev.c       |  21 +-
 drivers/gpu/host1x/dev.h       |   7 +-
 include/drm/drmP.h             |   3 +
 include/linux/component.h      |  20 +-
 include/linux/host1x.h         |  64 +----
 include/linux/interface.h      |  40 +++
 24 files changed, 625 insertions(+), 1130 deletions(-)
 create mode 100644 drivers/base/interface.c
 delete mode 100644 drivers/gpu/drm/tegra/bus.c
 delete mode 100644 drivers/gpu/host1x/bus.c
 delete mode 100644 drivers/gpu/host1x/bus.h
 create mode 100644 include/linux/interface.h

-- 
1.9.2


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [RFC 1/5] drivers/base: Allow multiple masters per device
  2014-04-22 15:09 [RFC 0/5] drm/tegra: Convert to master/component framework Thierry Reding
@ 2014-04-22 15:09 ` Thierry Reding
  2014-04-22 15:09 ` [RFC 2/5] drivers/base: Allow driver-data to be attached to a master Thierry Reding
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Thierry Reding @ 2014-04-22 15:09 UTC (permalink / raw)
  To: dri-devel; +Cc: Greg Kroah-Hartman, Russell King, linux-kernel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

Currently the component/master framework allows only a single master to
be registered against a struct device. A master is uniquely identified
by the device and the master operations table, but the current API does
not pass enough information along to allow a master to be uniquely
identified when calling component_unbind_all().

To make it possible to register multiple masters on one device, instead
of passing around the device associated with a master, pass around the
master directly. That way it can always be uniquely identified.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/base/component.c  | 18 +++++++-----------
 include/linux/component.h | 17 ++++++++---------
 2 files changed, 15 insertions(+), 20 deletions(-)

diff --git a/drivers/base/component.c b/drivers/base/component.c
index c4778995cd72..14fe81bf5ed2 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -120,7 +120,7 @@ static int try_to_bring_up_master(struct master *master,
 		 * Search the list of components, looking for components that
 		 * belong to this master, and attach them to the master.
 		 */
-		if (master->ops->add_components(master->dev, master)) {
+		if (master->ops->add_components(master, master->dev)) {
 			/* Failed to find all components */
 			master_remove_components(master);
 			ret = 0;
@@ -139,7 +139,7 @@ static int try_to_bring_up_master(struct master *master,
 		}
 
 		/* Found all components */
-		ret = master->ops->bind(master->dev);
+		ret = master->ops->bind(master, master->dev);
 		if (ret < 0) {
 			devres_release_group(master->dev, NULL);
 			dev_info(master->dev, "master bind failed: %d\n", ret);
@@ -172,7 +172,7 @@ static int try_to_bring_up_masters(struct component *component)
 static void take_down_master(struct master *master)
 {
 	if (master->bound) {
-		master->ops->unbind(master->dev);
+		master->ops->unbind(master, master->dev);
 		devres_release_group(master->dev, NULL);
 		master->bound = false;
 	}
@@ -233,21 +233,19 @@ static void component_unbind(struct component *component,
 {
 	WARN_ON(!component->bound);
 
-	component->ops->unbind(component->dev, master->dev, data);
+	component->ops->unbind(component->dev, master, data);
 	component->bound = false;
 
 	/* Release all resources claimed in the binding of this component */
 	devres_release_group(component->dev, component);
 }
 
-void component_unbind_all(struct device *master_dev, void *data)
+void component_unbind_all(struct master *master, void *data)
 {
-	struct master *master;
 	struct component *c;
 
 	WARN_ON(!mutex_is_locked(&component_mutex));
 
-	master = __master_find(master_dev, NULL);
 	if (!master)
 		return;
 
@@ -282,7 +280,7 @@ static int component_bind(struct component *component, struct master *master,
 	dev_dbg(master->dev, "binding %s (ops %ps)\n",
 		dev_name(component->dev), component->ops);
 
-	ret = component->ops->bind(component->dev, master->dev, data);
+	ret = component->ops->bind(component->dev, master, data);
 	if (!ret) {
 		component->bound = true;
 
@@ -308,15 +306,13 @@ static int component_bind(struct component *component, struct master *master,
 	return ret;
 }
 
-int component_bind_all(struct device *master_dev, void *data)
+int component_bind_all(struct master *master, void *data)
 {
-	struct master *master;
 	struct component *c;
 	int ret = 0;
 
 	WARN_ON(!mutex_is_locked(&component_mutex));
 
-	master = __master_find(master_dev, NULL);
 	if (!master)
 		return -EINVAL;
 
diff --git a/include/linux/component.h b/include/linux/component.h
index 68870182ca1e..89fe8bb35053 100644
--- a/include/linux/component.h
+++ b/include/linux/component.h
@@ -2,24 +2,23 @@
 #define COMPONENT_H
 
 struct device;
+struct master;
 
 struct component_ops {
-	int (*bind)(struct device *, struct device *, void *);
-	void (*unbind)(struct device *, struct device *, void *);
+	int (*bind)(struct device *, struct master *, void *);
+	void (*unbind)(struct device *, struct master *, void *);
 };
 
 int component_add(struct device *, const struct component_ops *);
 void component_del(struct device *, const struct component_ops *);
 
-int component_bind_all(struct device *, void *);
-void component_unbind_all(struct device *, void *);
-
-struct master;
+int component_bind_all(struct master *, void *);
+void component_unbind_all(struct master *, void *);
 
 struct component_master_ops {
-	int (*add_components)(struct device *, struct master *);
-	int (*bind)(struct device *);
-	void (*unbind)(struct device *);
+	int (*add_components)(struct master *, struct device *);
+	int (*bind)(struct master *, struct device *);
+	void (*unbind)(struct master *, struct device *);
 };
 
 int component_master_add(struct device *, const struct component_master_ops *);
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [RFC 2/5] drivers/base: Allow driver-data to be attached to a master
  2014-04-22 15:09 [RFC 0/5] drm/tegra: Convert to master/component framework Thierry Reding
  2014-04-22 15:09 ` [RFC 1/5] drivers/base: Allow multiple masters per device Thierry Reding
@ 2014-04-22 15:09 ` Thierry Reding
  2014-04-22 15:09 ` [RFC 3/5] drivers/base: Add interface framework Thierry Reding
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Thierry Reding @ 2014-04-22 15:09 UTC (permalink / raw)
  To: dri-devel; +Cc: Greg Kroah-Hartman, Russell King, linux-kernel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

Similarly to what can be done for device drivers, allow driver-specific
data to be attached to a master. This is necessary for masters whose
device is already bound to by a different driver and therefore cannot be
used to store the driver-specific data.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/base/component.c  | 13 +++++++++++++
 include/linux/component.h |  3 +++
 2 files changed, 16 insertions(+)

diff --git a/drivers/base/component.c b/drivers/base/component.c
index 14fe81bf5ed2..e3693c6d552f 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -25,6 +25,8 @@ struct master {
 
 	const struct component_master_ops *ops;
 	struct device *dev;
+
+	void *drvdata;
 };
 
 struct component {
@@ -53,6 +55,17 @@ static struct master *__master_find(struct device *dev,
 	return NULL;
 }
 
+void master_set_drvdata(struct master *master, void *data)
+{
+	if (master)
+		master->drvdata = data;
+}
+
+void *master_get_drvdata(struct master *master)
+{
+	return master ? master->drvdata : NULL;
+}
+
 /* Attach an unattached component to a master. */
 static void component_attach_master(struct master *master, struct component *c)
 {
diff --git a/include/linux/component.h b/include/linux/component.h
index 89fe8bb35053..9c2ec9fe48d6 100644
--- a/include/linux/component.h
+++ b/include/linux/component.h
@@ -25,6 +25,9 @@ int component_master_add(struct device *, const struct component_master_ops *);
 void component_master_del(struct device *,
 	const struct component_master_ops *);
 
+void master_set_drvdata(struct master *, void *);
+void *master_get_drvdata(struct master *);
+
 int component_master_add_child(struct master *master,
 	int (*compare)(struct device *, void *), void *compare_data);
 
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [RFC 3/5] drivers/base: Add interface framework
  2014-04-22 15:09 [RFC 0/5] drm/tegra: Convert to master/component framework Thierry Reding
  2014-04-22 15:09 ` [RFC 1/5] drivers/base: Allow multiple masters per device Thierry Reding
  2014-04-22 15:09 ` [RFC 2/5] drivers/base: Allow driver-data to be attached to a master Thierry Reding
@ 2014-04-22 15:09 ` Thierry Reding
  2014-04-22 15:09 ` [RFC 4/5] drm: Introduce drm_set_unique() Thierry Reding
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Thierry Reding @ 2014-04-22 15:09 UTC (permalink / raw)
  To: dri-devel; +Cc: Greg Kroah-Hartman, Russell King, linux-kernel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

Some drivers, such as graphics drivers in the DRM subsystem, do not have
a real device that they can bind to. They are often composed of several
devices, each having their own driver. The master/component framework
can be used in these situations to collect the devices pertaining to one
logical device, wait until all of them have registered and then bind
them all at once.

For some situations this is only a partial solution. An implementation
of a master still needs to be registered with the system somehow. Many
drivers currently resort to creating a dummy device that a driver can
bind to and register the master against. This is problematic since it
requires (and presumes) knowledge about the system within drivers.

Furthermore there are setups where a suitable device already exists, but
is already bound to a driver. For example, on Tegra the following device
tree extract (simplified) represents the host1x device along with child
devices:

	host1x {
		display-controller {
			...
		};

		display-controller {
			...
		};

		hdmi {
			...
		};

		dsi {
			...
		};

		csi {
			...
		};

		video-input {
			...
		};
	};

Each of the child devices is in turn a client of host1x, in that it can
request resources (command stream DMA channels and syncpoints) from it.
To implement the DMA channel and syncpoint infrastructure, host1x comes
with its own driver. Children are implemented in separate drivers. In
Linux this set of devices would be exposed by DRM and V4L2 drivers.

However, neither the DRM nor the V4L2 drivers have a single device that
they can bind to. The DRM device is composed of the display controllers
and the various output devices, whereas the V4L2 device is composed of
one or more video input devices.

This patch introduces the concept of an interface and drivers that can
bind to a given interface. An interface can be exposed by any device,
and interface drivers can bind to these interfaces. Multiple drivers can
bind against a single interface. When a device is removed, interfaces
exposed by it will be removed as well, thereby removing the drivers that
were bound to those interfaces.

In the example above, the host1x device would expose the "tegra-host1x"
interface. DRM and V4L2 drivers can then bind to that interface and
instantiate the respective subsystem objects from there.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/base/Makefile     |   2 +-
 drivers/base/interface.c  | 186 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/interface.h |  40 ++++++++++
 3 files changed, 227 insertions(+), 1 deletion(-)
 create mode 100644 drivers/base/interface.c
 create mode 100644 include/linux/interface.h

diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 04b314e0fa51..b5278904e443 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -4,7 +4,7 @@ obj-y			:= component.o core.o bus.o dd.o syscore.o \
 			   driver.o class.o platform.o \
 			   cpu.o firmware.o init.o map.o devres.o \
 			   attribute_container.o transport_class.o \
-			   topology.o container.o
+			   topology.o container.o interface.o
 obj-$(CONFIG_DEVTMPFS)	+= devtmpfs.o
 obj-$(CONFIG_DMA_CMA) += dma-contiguous.o
 obj-y			+= power/
diff --git a/drivers/base/interface.c b/drivers/base/interface.c
new file mode 100644
index 000000000000..411f6cdf90e7
--- /dev/null
+++ b/drivers/base/interface.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2014 NVIDIA Corporation. All rights reserved.
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) "interface: " fmt
+
+#include <linux/device.h>
+#include <linux/interface.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+static DEFINE_MUTEX(interfaces_lock);
+static LIST_HEAD(interfaces);
+static LIST_HEAD(drivers);
+
+struct interface_attachment {
+	struct interface_driver *driver;
+	struct list_head list;
+};
+
+static bool interface_match(struct interface *intf,
+			    struct interface_driver *driver)
+{
+	return strcmp(intf->name, driver->name) == 0;
+}
+
+static bool interface_attached(struct interface *intf,
+			       struct interface_driver *driver)
+{
+	struct interface_attachment *attach;
+
+	list_for_each_entry(attach, &intf->drivers, list)
+		if (attach->driver == driver)
+			return true;
+
+	return false;
+}
+
+static int interface_attach(struct interface *intf,
+			    struct interface_driver *driver)
+{
+	struct interface_attachment *attach;
+
+	attach = kzalloc(sizeof(*attach), GFP_KERNEL);
+	if (!attach)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&attach->list);
+	attach->driver = driver;
+
+	list_add_tail(&attach->list, &intf->drivers);
+
+	return 0;
+}
+
+static void interface_detach(struct interface *intf,
+			     struct interface_driver *driver)
+{
+	struct interface_attachment *attach;
+
+	list_for_each_entry(attach, &intf->drivers, list) {
+		if (attach->driver == driver) {
+			list_del(&attach->list);
+			kfree(attach);
+			return;
+		}
+	}
+}
+
+static void interface_bind(struct interface *intf,
+			   struct interface_driver *driver)
+{
+	int err;
+
+	if (interface_attached(intf, driver))
+		return;
+
+	if (!interface_match(intf, driver))
+		return;
+
+	err = interface_attach(intf, driver);
+	if (err < 0) {
+		pr_err("failed to attach driver %ps to interface %s: %d\n",
+		       driver, intf->name, err);
+		return;
+	}
+
+	err = driver->bind(intf);
+	if (err < 0) {
+		pr_err("failed to bind driver %ps to interface %s: %d\n",
+		       driver, intf->name, err);
+		interface_detach(intf, driver);
+		return;
+	}
+
+	pr_debug("driver %ps bound to interface %s\n", driver, intf->name);
+}
+
+static void interface_unbind(struct interface *intf,
+			     struct interface_driver *driver)
+{
+	if (!interface_attached(intf, driver))
+		return;
+
+	interface_detach(intf, driver);
+	driver->unbind(intf);
+
+	pr_debug("driver %ps unbound from interface %s\n", driver, intf->name);
+}
+
+int interface_add(struct interface *intf)
+{
+	struct interface_driver *driver;
+
+	INIT_LIST_HEAD(&intf->drivers);
+	INIT_LIST_HEAD(&intf->list);
+
+	mutex_lock(&interfaces_lock);
+
+	list_add_tail(&intf->list, &interfaces);
+
+	pr_debug("interface %s added for device %s\n", intf->name,
+		 dev_name(intf->dev));
+
+	list_for_each_entry(driver, &drivers, list)
+		interface_bind(intf, driver);
+
+	mutex_unlock(&interfaces_lock);
+
+	return 0;
+}
+
+void interface_remove(struct interface *intf)
+{
+	struct interface_driver *driver;
+
+	mutex_lock(&interfaces_lock);
+
+	list_for_each_entry(driver, &drivers, list)
+		interface_unbind(intf, driver);
+
+	list_del_init(&intf->list);
+
+	pr_debug("interface %s removed for device %s\n", intf->name,
+		 dev_name(intf->dev));
+
+	mutex_unlock(&interfaces_lock);
+}
+
+int interface_register_driver(struct interface_driver *driver)
+{
+	struct interface *intf;
+
+	mutex_lock(&interfaces_lock);
+
+	list_add_tail(&driver->list, &drivers);
+
+	pr_debug("driver %ps added\n", driver);
+
+	list_for_each_entry(intf, &interfaces, list)
+		interface_bind(intf, driver);
+
+	mutex_unlock(&interfaces_lock);
+
+	return 0;
+}
+
+void interface_unregister_driver(struct interface_driver *driver)
+{
+	struct interface *intf;
+
+	mutex_lock(&interfaces_lock);
+
+	list_for_each_entry(intf, &interfaces, list)
+		interface_unbind(intf, driver);
+
+	list_del_init(&driver->list);
+
+	pr_debug("driver %ps removed\n", driver);
+
+	mutex_unlock(&interfaces_lock);
+}
diff --git a/include/linux/interface.h b/include/linux/interface.h
new file mode 100644
index 000000000000..2c49ad3912fe
--- /dev/null
+++ b/include/linux/interface.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 NVIDIA Corporation. All rights reserved.
+ *
+ * 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.
+ */
+
+#ifndef INTERFACE_H
+#define INTERFACE_H
+
+#include <linux/list.h>
+
+struct device;
+struct interface;
+
+struct interface_driver {
+	const char *name;
+
+	int (*bind)(struct interface *intf);
+	void (*unbind)(struct interface *intf);
+
+	struct list_head list;
+};
+
+int interface_register_driver(struct interface_driver *driver);
+void interface_unregister_driver(struct interface_driver *driver);
+
+struct interface {
+	const char *name;
+	struct device *dev;
+
+	struct list_head drivers;
+	struct list_head list;
+};
+
+int interface_add(struct interface *intf);
+void interface_remove(struct interface *intf);
+
+#endif
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [RFC 4/5] drm: Introduce drm_set_unique()
  2014-04-22 15:09 [RFC 0/5] drm/tegra: Convert to master/component framework Thierry Reding
                   ` (2 preceding siblings ...)
  2014-04-22 15:09 ` [RFC 3/5] drivers/base: Add interface framework Thierry Reding
@ 2014-04-22 15:09 ` Thierry Reding
  2014-04-22 15:48   ` Daniel Vetter
  2014-04-22 15:09 ` [RFC 5/5] drm/tegra: Convert to master/component framework Thierry Reding
  2014-04-30 22:01 ` [RFC 0/5] " Thierry Reding
  5 siblings, 1 reply; 12+ messages in thread
From: Thierry Reding @ 2014-04-22 15:09 UTC (permalink / raw)
  To: dri-devel; +Cc: Greg Kroah-Hartman, Russell King, linux-kernel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

Add a helper function that allows drivers to statically set the unique
name of the device. This will allow platform and USB drivers to get rid
of their DRM bus implementations and directly use drm_dev_alloc() and
drm_dev_register().

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpu/drm/drm_ioctl.c | 37 +++++++++++++++++++++++++++++++------
 drivers/gpu/drm/drm_stub.c  |  1 +
 include/drm/drmP.h          |  3 +++
 3 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 2dd3a6d8382b..371db3bef60c 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -42,6 +42,20 @@
 #include <asm/mtrr.h>
 #endif
 
+int drm_set_unique(struct drm_device *dev, const char *fmt, ...)
+{
+	va_list ap;
+
+	kfree(dev->unique);
+
+	va_start(ap, fmt);
+	dev->unique = kvasprintf(GFP_KERNEL, fmt, ap);
+	va_end(ap);
+
+	return dev->unique ? 0 : -ENOMEM;
+}
+EXPORT_SYMBOL(drm_set_unique);
+
 /**
  * Get the bus id.
  *
@@ -131,13 +145,24 @@ static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
 	if (master->unique != NULL)
 		drm_unset_busid(dev, master);
 
-	ret = dev->driver->bus->set_busid(dev, master);
-	if (ret)
-		goto err;
+	if (dev->driver->bus && dev->driver->bus->set_busid) {
+		ret = dev->driver->bus->set_busid(dev, master);
+		if (ret) {
+			drm_unset_busid(dev, master);
+			return ret;
+		}
+	} else {
+		WARN(dev->unique == NULL,
+		     "No drm_bus.set_busid() implementation provided by %ps. "
+		     "Set the unique name explicitly using drm_set_unique().",
+		     dev->driver);
+
+		master->unique = kstrdup(dev->unique, GFP_KERNEL);
+		if (master->unique)
+			master->unique_len = strlen(dev->unique);
+	}
+
 	return 0;
-err:
-	drm_unset_busid(dev, master);
-	return ret;
 }
 
 /**
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 3a8e832ad151..9465cf766fe7 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -646,6 +646,7 @@ static void drm_dev_release(struct kref *ref)
 	drm_minor_free(dev, DRM_MINOR_CONTROL);
 
 	mutex_destroy(&dev->master_mutex);
+	kfree(dev->unique);
 	kfree(dev);
 }
 
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 8c80c1894b41..8fdefcdc4036 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1158,6 +1158,8 @@ struct drm_device {
 	struct drm_vma_offset_manager *vma_offset_manager;
 	/*@} */
 	int switch_power_state;
+
+	char *unique;
 };
 
 #define DRM_SWITCH_POWER_ON 0
@@ -1238,6 +1240,7 @@ extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
 				/* Misc. IOCTL support (drm_ioctl.h) */
 extern int drm_irq_by_busid(struct drm_device *dev, void *data,
 			    struct drm_file *file_priv);
+extern int drm_set_unique(struct drm_device *dev, const char *fmt, ...);
 extern int drm_getunique(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv);
 extern int drm_setunique(struct drm_device *dev, void *data,
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [RFC 5/5] drm/tegra: Convert to master/component framework
  2014-04-22 15:09 [RFC 0/5] drm/tegra: Convert to master/component framework Thierry Reding
                   ` (3 preceding siblings ...)
  2014-04-22 15:09 ` [RFC 4/5] drm: Introduce drm_set_unique() Thierry Reding
@ 2014-04-22 15:09 ` Thierry Reding
  2014-04-30 22:01 ` [RFC 0/5] " Thierry Reding
  5 siblings, 0 replies; 12+ messages in thread
From: Thierry Reding @ 2014-04-22 15:09 UTC (permalink / raw)
  To: dri-devel; +Cc: Greg Kroah-Hartman, Russell King, linux-kernel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

Instead of the current implementation, reuse the recently introduced
master/component framework, which is equivalent in most regards. One
issue is that there is no device to bind the DRM driver to. In order
to still allow the driver to be probed, expose an interface from the
host1x device and provide an interface driver to bind to that.

The interface driver then registers (or removes) the master that will be
used to instantiate and bind the DRM driver. Since the drm_host1x bus
implementation is now gone the dummy device instantiated by it can no
longer be used as the parent for the DRM device. However since the
parent device doesn't need to be modified, the host1x parent device that
exposes the interface can be used instead.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpu/drm/tegra/Makefile |   1 -
 drivers/gpu/drm/tegra/bus.c    |  64 -----
 drivers/gpu/drm/tegra/dc.c     |  58 ++---
 drivers/gpu/drm/tegra/drm.c    | 171 +++++++++----
 drivers/gpu/drm/tegra/drm.h    |  27 +-
 drivers/gpu/drm/tegra/dsi.c    | 144 +++++------
 drivers/gpu/drm/tegra/gr2d.c   |  78 +++---
 drivers/gpu/drm/tegra/gr3d.c   |  77 +++---
 drivers/gpu/drm/tegra/hdmi.c   |  69 ++---
 drivers/gpu/drm/tegra/sor.c    |  71 ++----
 drivers/gpu/host1x/Makefile    |   1 -
 drivers/gpu/host1x/bus.c       | 553 -----------------------------------------
 drivers/gpu/host1x/bus.h       |  29 ---
 drivers/gpu/host1x/dev.c       |  21 +-
 drivers/gpu/host1x/dev.h       |   7 +-
 include/linux/host1x.h         |  64 +----
 16 files changed, 332 insertions(+), 1103 deletions(-)
 delete mode 100644 drivers/gpu/drm/tegra/bus.c
 delete mode 100644 drivers/gpu/host1x/bus.c
 delete mode 100644 drivers/gpu/host1x/bus.h

diff --git a/drivers/gpu/drm/tegra/Makefile b/drivers/gpu/drm/tegra/Makefile
index 905f6cad1061..e24584eb2e58 100644
--- a/drivers/gpu/drm/tegra/Makefile
+++ b/drivers/gpu/drm/tegra/Makefile
@@ -1,7 +1,6 @@
 ccflags-$(CONFIG_DRM_TEGRA_DEBUG) += -DDEBUG
 
 tegra-drm-y := \
-	bus.o \
 	drm.o \
 	gem.o \
 	fb.o \
diff --git a/drivers/gpu/drm/tegra/bus.c b/drivers/gpu/drm/tegra/bus.c
deleted file mode 100644
index b3a66d65cb53..000000000000
--- a/drivers/gpu/drm/tegra/bus.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2013 NVIDIA Corporation
- *
- * 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.
- */
-
-#include "drm.h"
-
-static int drm_host1x_set_busid(struct drm_device *dev,
-				struct drm_master *master)
-{
-	const char *device = dev_name(dev->dev);
-	const char *bus = dev->dev->bus->name;
-
-	master->unique_len = strlen(bus) + 1 + strlen(device);
-	master->unique_size = master->unique_len;
-
-	master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL);
-	if (!master->unique)
-		return -ENOMEM;
-
-	snprintf(master->unique, master->unique_len + 1, "%s:%s", bus, device);
-
-	return 0;
-}
-
-static struct drm_bus drm_host1x_bus = {
-	.set_busid = drm_host1x_set_busid,
-};
-
-int drm_host1x_init(struct drm_driver *driver, struct host1x_device *device)
-{
-	struct drm_device *drm;
-	int ret;
-
-	driver->bus = &drm_host1x_bus;
-
-	drm = drm_dev_alloc(driver, &device->dev);
-	if (!drm)
-		return -ENOMEM;
-
-	ret = drm_dev_register(drm, 0);
-	if (ret)
-		goto err_free;
-
-	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name,
-		 driver->major, driver->minor, driver->patchlevel,
-		 driver->date, drm->primary->index);
-
-	return 0;
-
-err_free:
-	drm_dev_unref(drm);
-	return ret;
-}
-
-void drm_host1x_exit(struct drm_driver *driver, struct host1x_device *device)
-{
-	struct tegra_drm *tegra = dev_get_drvdata(&device->dev);
-
-	drm_put_dev(tegra->drm);
-}
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 3a54cf01e9fc..fc97d8a64cb6 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -1102,10 +1102,10 @@ static int tegra_dc_debugfs_exit(struct tegra_dc *dc)
 	return 0;
 }
 
-static int tegra_dc_init(struct host1x_client *client)
+static int tegra_dc_bind(struct device *dev, struct master *master, void *data)
 {
-	struct tegra_drm *tegra = dev_get_drvdata(client->parent);
-	struct tegra_dc *dc = host1x_client_to_dc(client);
+	struct tegra_drm *tegra = master_get_drvdata(master);
+	struct tegra_dc *dc = dev_get_drvdata(dev);
 	int err;
 
 	drm_crtc_init(tegra->drm, &dc->base, &tegra_crtc_funcs);
@@ -1114,7 +1114,7 @@ static int tegra_dc_init(struct host1x_client *client)
 
 	err = tegra_dc_rgb_init(tegra->drm, dc);
 	if (err < 0 && err != -ENODEV) {
-		dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
+		dev_err(dev, "failed to initialize RGB output: %d\n", err);
 		return err;
 	}
 
@@ -1125,23 +1125,23 @@ static int tegra_dc_init(struct host1x_client *client)
 	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
 		err = tegra_dc_debugfs_init(dc, tegra->drm->primary);
 		if (err < 0)
-			dev_err(dc->dev, "debugfs setup failed: %d\n", err);
+			dev_err(dev, "debugfs setup failed: %d\n", err);
 	}
 
-	err = devm_request_irq(dc->dev, dc->irq, tegra_dc_irq, 0,
-			       dev_name(dc->dev), dc);
+	err = devm_request_irq(dev, dc->irq, tegra_dc_irq, 0, dev_name(dev),
+			       dc);
 	if (err < 0) {
-		dev_err(dc->dev, "failed to request IRQ#%u: %d\n", dc->irq,
-			err);
+		dev_err(dev, "failed to request IRQ#%u: %d\n", dc->irq, err);
 		return err;
 	}
 
 	return 0;
 }
 
-static int tegra_dc_exit(struct host1x_client *client)
+static void tegra_dc_unbind(struct device *dev, struct master *master,
+			    void *data)
 {
-	struct tegra_dc *dc = host1x_client_to_dc(client);
+	struct tegra_dc *dc = dev_get_drvdata(dev);
 	int err;
 
 	devm_free_irq(dc->dev, dc->irq, dc);
@@ -1149,21 +1149,17 @@ static int tegra_dc_exit(struct host1x_client *client)
 	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
 		err = tegra_dc_debugfs_exit(dc);
 		if (err < 0)
-			dev_err(dc->dev, "debugfs cleanup failed: %d\n", err);
+			dev_err(dev, "debugfs cleanup failed: %d\n", err);
 	}
 
 	err = tegra_dc_rgb_exit(dc);
-	if (err) {
-		dev_err(dc->dev, "failed to shutdown RGB output: %d\n", err);
-		return err;
-	}
-
-	return 0;
+	if (err)
+		dev_err(dev, "failed to shutdown RGB output: %d\n", err);
 }
 
-static const struct host1x_client_ops dc_client_ops = {
-	.init = tegra_dc_init,
-	.exit = tegra_dc_exit,
+static const struct component_ops tegra_dc_component_ops = {
+	.bind = tegra_dc_bind,
+	.unbind = tegra_dc_unbind,
 };
 
 static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
@@ -1239,6 +1235,8 @@ static int tegra_dc_probe(struct platform_device *pdev)
 	if (!dc)
 		return -ENOMEM;
 
+	platform_set_drvdata(pdev, dc);
+
 	id = of_match_node(tegra_dc_of_match, pdev->dev.of_node);
 	if (!id)
 		return -ENODEV;
@@ -1279,25 +1277,18 @@ static int tegra_dc_probe(struct platform_device *pdev)
 		return -ENXIO;
 	}
 
-	INIT_LIST_HEAD(&dc->client.list);
-	dc->client.ops = &dc_client_ops;
-	dc->client.dev = &pdev->dev;
-
 	err = tegra_dc_rgb_probe(dc);
 	if (err < 0 && err != -ENODEV) {
 		dev_err(&pdev->dev, "failed to probe RGB output: %d\n", err);
 		return err;
 	}
 
-	err = host1x_client_register(&dc->client);
+	err = component_add(&pdev->dev, &tegra_dc_component_ops);
 	if (err < 0) {
-		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
-			err);
+		dev_err(&pdev->dev, "failed to register component: %d\n", err);
 		return err;
 	}
 
-	platform_set_drvdata(pdev, dc);
-
 	return 0;
 }
 
@@ -1306,12 +1297,7 @@ static int tegra_dc_remove(struct platform_device *pdev)
 	struct tegra_dc *dc = platform_get_drvdata(pdev);
 	int err;
 
-	err = host1x_client_unregister(&dc->client);
-	if (err < 0) {
-		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
-			err);
-		return err;
-	}
+	component_del(&pdev->dev, &tegra_dc_component_ops);
 
 	err = tegra_dc_rgb_remove(dc);
 	if (err < 0) {
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index d492c2f12ca8..78f7ab6d355b 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -7,7 +7,9 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/component.h>
 #include <linux/host1x.h>
+#include <linux/interface.h>
 
 #include "drm.h"
 #include "gem.h"
@@ -25,20 +27,9 @@ struct tegra_drm_file {
 
 static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
 {
-	struct host1x_device *device = to_host1x_device(drm->dev);
-	struct tegra_drm *tegra;
+	struct tegra_drm *tegra = drm->dev_private;
 	int err;
 
-	tegra = kzalloc(sizeof(*tegra), GFP_KERNEL);
-	if (!tegra)
-		return -ENOMEM;
-
-	dev_set_drvdata(drm->dev, tegra);
-	mutex_init(&tegra->clients_lock);
-	INIT_LIST_HEAD(&tegra->clients);
-	drm->dev_private = tegra;
-	tegra->drm = drm;
-
 	drm_mode_config_init(drm);
 
 	err = tegra_drm_fb_prepare(drm);
@@ -47,7 +38,7 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
 
 	drm_kms_helper_poll_init(drm);
 
-	err = host1x_device_init(device);
+	err = component_bind_all(tegra->master, drm);
 	if (err < 0)
 		return err;
 
@@ -71,17 +62,14 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
 
 static int tegra_drm_unload(struct drm_device *drm)
 {
-	struct host1x_device *device = to_host1x_device(drm->dev);
-	int err;
+	struct tegra_drm *tegra = drm->dev_private;
 
 	drm_kms_helper_poll_fini(drm);
 	tegra_drm_fb_exit(drm);
-	drm_vblank_cleanup(drm);
 	drm_mode_config_cleanup(drm);
+	drm_vblank_cleanup(drm);
 
-	err = host1x_device_exit(device);
-	if (err < 0)
-		return err;
+	component_unbind_all(tegra->master, drm);
 
 	return 0;
 }
@@ -162,7 +150,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
 	job->num_relocs = args->num_relocs;
 	job->num_waitchk = args->num_waitchks;
 	job->client = (u32)args->context;
-	job->class = context->client->base.class;
+	job->class = context->client->class;
 	job->serialize = true;
 
 	while (num_cmdbufs) {
@@ -227,7 +215,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
 	if (args->timeout && args->timeout < 10000)
 		job->timeout = args->timeout;
 
-	err = host1x_job_pin(job, context->client->base.dev);
+	err = host1x_job_pin(job, context->client->dev);
 	if (err)
 		goto fail;
 
@@ -303,7 +291,7 @@ static int tegra_gem_mmap(struct drm_device *drm, void *data,
 static int tegra_syncpt_read(struct drm_device *drm, void *data,
 			     struct drm_file *file)
 {
-	struct host1x *host = dev_get_drvdata(drm->dev->parent);
+	struct host1x *host = dev_get_drvdata(drm->dev);
 	struct drm_tegra_syncpt_read *args = data;
 	struct host1x_syncpt *sp;
 
@@ -318,7 +306,7 @@ static int tegra_syncpt_read(struct drm_device *drm, void *data,
 static int tegra_syncpt_incr(struct drm_device *drm, void *data,
 			     struct drm_file *file)
 {
-	struct host1x *host1x = dev_get_drvdata(drm->dev->parent);
+	struct host1x *host1x = dev_get_drvdata(drm->dev);
 	struct drm_tegra_syncpt_incr *args = data;
 	struct host1x_syncpt *sp;
 
@@ -332,7 +320,7 @@ static int tegra_syncpt_incr(struct drm_device *drm, void *data,
 static int tegra_syncpt_wait(struct drm_device *drm, void *data,
 			     struct drm_file *file)
 {
-	struct host1x *host1x = dev_get_drvdata(drm->dev->parent);
+	struct host1x *host1x = dev_get_drvdata(drm->dev);
 	struct drm_tegra_syncpt_wait *args = data;
 	struct host1x_syncpt *sp;
 
@@ -359,7 +347,7 @@ static int tegra_open_channel(struct drm_device *drm, void *data,
 		return -ENOMEM;
 
 	list_for_each_entry(client, &tegra->clients, list)
-		if (client->base.class == args->client) {
+		if (client->class == args->client) {
 			err = client->ops->open_channel(client, context);
 			if (err)
 				break;
@@ -405,10 +393,10 @@ static int tegra_get_syncpt(struct drm_device *drm, void *data,
 	if (!tegra_drm_file_owns_context(fpriv, context))
 		return -ENODEV;
 
-	if (args->index >= context->client->base.num_syncpts)
+	if (args->index >= context->client->num_syncpts)
 		return -EINVAL;
 
-	syncpt = context->client->base.syncpts[args->index];
+	syncpt = context->client->syncpts[args->index];
 	args->id = host1x_syncpt_id(syncpt);
 
 	return 0;
@@ -443,10 +431,10 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data,
 	if (!tegra_drm_file_owns_context(fpriv, context))
 		return -ENODEV;
 
-	if (args->syncpt >= context->client->base.num_syncpts)
+	if (args->syncpt >= context->client->num_syncpts)
 		return -EINVAL;
 
-	syncpt = context->client->base.syncpts[args->syncpt];
+	syncpt = context->client->syncpts[args->syncpt];
 
 	base = host1x_syncpt_get_base(syncpt);
 	if (!base)
@@ -644,19 +632,7 @@ int tegra_drm_unregister_client(struct tegra_drm *tegra,
 	return 0;
 }
 
-static int host1x_drm_probe(struct host1x_device *device)
-{
-	return drm_host1x_init(&tegra_drm_driver, device);
-}
-
-static int host1x_drm_remove(struct host1x_device *device)
-{
-	drm_host1x_exit(&tegra_drm_driver, device);
-
-	return 0;
-}
-
-static const struct of_device_id host1x_drm_subdevs[] = {
+static const struct of_device_id tegra_drm_subdevs[] = {
 	{ .compatible = "nvidia,tegra20-dc", },
 	{ .compatible = "nvidia,tegra20-hdmi", },
 	{ .compatible = "nvidia,tegra20-gr2d", },
@@ -674,18 +650,105 @@ static const struct of_device_id host1x_drm_subdevs[] = {
 	{ /* sentinel */ }
 };
 
-static struct host1x_driver host1x_drm_driver = {
-	.name = "drm",
-	.probe = host1x_drm_probe,
-	.remove = host1x_drm_remove,
-	.subdevs = host1x_drm_subdevs,
+static int tegra_drm_compare(struct device *dev, void *data)
+{
+	struct device_node *np = data;
+
+	return dev->of_node == np;
+}
+
+static int tegra_drm_add_components(struct master *master, struct device *dev)
+{
+	struct device_node *np;
+	int err = 0;
+
+	for_each_child_of_node(dev->of_node, np) {
+		if (!of_device_is_available(np))
+			continue;
+
+		if (!of_match_node(tegra_drm_subdevs, np))
+			continue;
+
+		err = component_master_add_child(master, tegra_drm_compare, np);
+		if (err < 0)
+			break;
+	}
+
+	return err;
+}
+
+static int tegra_drm_bind(struct master *master, struct device *dev)
+{
+	struct tegra_drm *tegra;
+	struct drm_device *drm;
+	int err;
+
+	tegra = kzalloc(sizeof(*tegra), GFP_KERNEL);
+	if (!tegra)
+		return -ENOMEM;
+
+	mutex_init(&tegra->clients_lock);
+	INIT_LIST_HEAD(&tegra->clients);
+	tegra->master = master;
+
+	drm = drm_dev_alloc(&tegra_drm_driver, dev);
+	if (!dev) {
+		err = -ENOMEM;
+		goto free;
+	}
+
+	drm_set_unique(drm, "%s", dev_name(dev));
+	master_set_drvdata(master, tegra);
+	drm->dev_private = tegra;
+	tegra->drm = drm;
+
+	err = drm_dev_register(drm, 0);
+	if (err < 0)
+		goto unref;
+
+	return 0;
+
+unref:
+	drm_dev_unref(drm);
+free:
+	kfree(tegra);
+	return err;
+}
+
+static void tegra_drm_unbind(struct master *master, struct device *dev)
+{
+	struct tegra_drm *tegra = master_get_drvdata(master);
+
+	drm_put_dev(tegra->drm);
+}
+
+static const struct component_master_ops tegra_drm_master_ops = {
+	.add_components = tegra_drm_add_components,
+	.bind = tegra_drm_bind,
+	.unbind = tegra_drm_unbind,
+};
+
+static int host1x_interface_bind(struct interface *intf)
+{
+	return component_master_add(intf->dev, &tegra_drm_master_ops);
+}
+
+static void host1x_interface_unbind(struct interface *intf)
+{
+	component_master_del(intf->dev, &tegra_drm_master_ops);
+}
+
+static struct interface_driver host1x_interface_driver = {
+	.name = "nvidia,tegra-host1x",
+	.bind = host1x_interface_bind,
+	.unbind = host1x_interface_unbind,
 };
 
-static int __init host1x_drm_init(void)
+static int __init tegra_drm_init(void)
 {
 	int err;
 
-	err = host1x_driver_register(&host1x_drm_driver);
+	err = interface_register_driver(&host1x_interface_driver);
 	if (err < 0)
 		return err;
 
@@ -732,12 +795,12 @@ unregister_dsi:
 unregister_dc:
 	platform_driver_unregister(&tegra_dc_driver);
 unregister_host1x:
-	host1x_driver_unregister(&host1x_drm_driver);
+	interface_unregister_driver(&host1x_interface_driver);
 	return err;
 }
-module_init(host1x_drm_init);
+module_init(tegra_drm_init);
 
-static void __exit host1x_drm_exit(void)
+static void __exit tegra_drm_exit(void)
 {
 	platform_driver_unregister(&tegra_gr3d_driver);
 	platform_driver_unregister(&tegra_gr2d_driver);
@@ -746,9 +809,9 @@ static void __exit host1x_drm_exit(void)
 	platform_driver_unregister(&tegra_sor_driver);
 	platform_driver_unregister(&tegra_dsi_driver);
 	platform_driver_unregister(&tegra_dc_driver);
-	host1x_driver_unregister(&host1x_drm_driver);
+	interface_unregister_driver(&host1x_interface_driver);
 }
-module_exit(host1x_drm_exit);
+module_exit(tegra_drm_exit);
 
 MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
 MODULE_DESCRIPTION("NVIDIA Tegra DRM driver");
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index d100f706d818..ff29611e8a97 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -36,6 +36,7 @@ struct tegra_fbdev {
 
 struct tegra_drm {
 	struct drm_device *drm;
+	struct master *master;
 
 	struct mutex clients_lock;
 	struct list_head clients;
@@ -68,31 +69,25 @@ int tegra_drm_submit(struct tegra_drm_context *context,
 		     struct drm_file *file);
 
 struct tegra_drm_client {
-	struct host1x_client base;
 	struct list_head list;
+	struct device *dev;
+
+	enum host1x_class class;
+	struct host1x_syncpt **syncpts;
+	unsigned int num_syncpts;
 
 	const struct tegra_drm_client_ops *ops;
 };
 
-static inline struct tegra_drm_client *
-host1x_to_drm_client(struct host1x_client *client)
-{
-	return container_of(client, struct tegra_drm_client, base);
-}
-
 int tegra_drm_register_client(struct tegra_drm *tegra,
 			      struct tegra_drm_client *client);
 int tegra_drm_unregister_client(struct tegra_drm *tegra,
 				struct tegra_drm_client *client);
 
-int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
-int tegra_drm_exit(struct tegra_drm *tegra);
-
 struct tegra_dc_soc_info;
 struct tegra_output;
 
 struct tegra_dc {
-	struct host1x_client client;
 	struct device *dev;
 	spinlock_t lock;
 
@@ -118,12 +113,6 @@ struct tegra_dc {
 	const struct tegra_dc_soc_info *soc;
 };
 
-static inline struct tegra_dc *
-host1x_client_to_dc(struct host1x_client *client)
-{
-	return container_of(client, struct tegra_dc, client);
-}
-
 static inline struct tegra_dc *to_tegra_dc(struct drm_crtc *crtc)
 {
 	return crtc ? container_of(crtc, struct tegra_dc, base) : NULL;
@@ -249,10 +238,6 @@ static inline int tegra_output_check_mode(struct tegra_output *output,
 	return output ? -ENOSYS : -EINVAL;
 }
 
-/* from bus.c */
-int drm_host1x_init(struct drm_driver *driver, struct host1x_device *device);
-void drm_host1x_exit(struct drm_driver *driver, struct host1x_device *device);
-
 /* from rgb.c */
 int tegra_dc_rgb_probe(struct tegra_dc *dc);
 int tegra_dc_rgb_remove(struct tegra_dc *dc);
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index 3838575f71c6..0325e5206b66 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -30,7 +30,6 @@
 #define DSI_HOST_FIFO_DEPTH 64
 
 struct tegra_dsi {
-	struct host1x_client client;
 	struct tegra_output output;
 	struct device *dev;
 
@@ -56,12 +55,6 @@ struct tegra_dsi {
 	bool enabled;
 };
 
-static inline struct tegra_dsi *
-host1x_client_to_dsi(struct host1x_client *client)
-{
-	return container_of(client, struct tegra_dsi, client);
-}
-
 static inline struct tegra_dsi *host_to_tegra(struct mipi_dsi_host *host)
 {
 	return container_of(host, struct tegra_dsi, host);
@@ -713,68 +706,6 @@ static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
 	return tegra_mipi_calibrate(dsi->mipi);
 }
 
-static int tegra_dsi_init(struct host1x_client *client)
-{
-	struct tegra_drm *tegra = dev_get_drvdata(client->parent);
-	struct tegra_dsi *dsi = host1x_client_to_dsi(client);
-	int err;
-
-	dsi->output.type = TEGRA_OUTPUT_DSI;
-	dsi->output.dev = client->dev;
-	dsi->output.ops = &dsi_ops;
-
-	err = tegra_output_init(tegra->drm, &dsi->output);
-	if (err < 0) {
-		dev_err(client->dev, "output setup failed: %d\n", err);
-		return err;
-	}
-
-	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
-		err = tegra_dsi_debugfs_init(dsi, tegra->drm->primary);
-		if (err < 0)
-			dev_err(dsi->dev, "debugfs setup failed: %d\n", err);
-	}
-
-	err = tegra_dsi_pad_calibrate(dsi);
-	if (err < 0) {
-		dev_err(dsi->dev, "MIPI calibration failed: %d\n", err);
-		return err;
-	}
-
-	return 0;
-}
-
-static int tegra_dsi_exit(struct host1x_client *client)
-{
-	struct tegra_dsi *dsi = host1x_client_to_dsi(client);
-	int err;
-
-	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
-		err = tegra_dsi_debugfs_exit(dsi);
-		if (err < 0)
-			dev_err(dsi->dev, "debugfs cleanup failed: %d\n", err);
-	}
-
-	err = tegra_output_disable(&dsi->output);
-	if (err < 0) {
-		dev_err(client->dev, "output failed to disable: %d\n", err);
-		return err;
-	}
-
-	err = tegra_output_exit(&dsi->output);
-	if (err < 0) {
-		dev_err(client->dev, "output cleanup failed: %d\n", err);
-		return err;
-	}
-
-	return 0;
-}
-
-static const struct host1x_client_ops dsi_client_ops = {
-	.init = tegra_dsi_init,
-	.exit = tegra_dsi_exit,
-};
-
 static int tegra_dsi_setup_clocks(struct tegra_dsi *dsi)
 {
 	struct clk *parent;
@@ -831,6 +762,62 @@ static const struct mipi_dsi_host_ops tegra_dsi_host_ops = {
 	.detach = tegra_dsi_host_detach,
 };
 
+static int dsi_bind(struct device *dev, struct master *master, void *data)
+{
+	struct tegra_drm *tegra = master_get_drvdata(master);
+	struct tegra_dsi *dsi = dev_get_drvdata(dev);
+	int err;
+
+	dsi->output.type = TEGRA_OUTPUT_DSI;
+	dsi->output.ops = &dsi_ops;
+	dsi->output.dev = dev;
+
+	err = tegra_output_init(tegra->drm, &dsi->output);
+	if (err < 0) {
+		dev_err(dev, "output setup failed: %d\n", err);
+		return err;
+	}
+
+	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
+		err = tegra_dsi_debugfs_init(dsi, tegra->drm->primary);
+		if (err < 0)
+			dev_err(dev, "debugfs setup failed: %d\n", err);
+	}
+
+	err = tegra_dsi_pad_calibrate(dsi);
+	if (err < 0) {
+		dev_err(dev, "MIPI calibration failed: %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static void dsi_unbind(struct device *dev, struct master *master, void *data)
+{
+	struct tegra_dsi *dsi = dev_get_drvdata(dev);
+	int err;
+
+	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
+		err = tegra_dsi_debugfs_exit(dsi);
+		if (err < 0)
+			dev_err(dev, "debugfs cleanup failed: %d\n", err);
+	}
+
+	err = tegra_output_disable(&dsi->output);
+	if (err < 0)
+		dev_err(dev, "output failed to disable: %d\n", err);
+
+	err = tegra_output_exit(&dsi->output);
+	if (err < 0)
+		dev_err(dev, "output cleanup failed: %d\n", err);
+}
+
+static const struct component_ops dsi_component_ops = {
+	.bind = dsi_bind,
+	.unbind = dsi_unbind,
+};
+
 static int tegra_dsi_probe(struct platform_device *pdev)
 {
 	struct tegra_dsi *dsi;
@@ -842,6 +829,7 @@ static int tegra_dsi_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	dsi->output.dev = dsi->dev = &pdev->dev;
+	platform_set_drvdata(pdev, dsi);
 
 	err = tegra_output_probe(&dsi->output);
 	if (err < 0)
@@ -932,19 +920,12 @@ static int tegra_dsi_probe(struct platform_device *pdev)
 		return err;
 	}
 
-	INIT_LIST_HEAD(&dsi->client.list);
-	dsi->client.ops = &dsi_client_ops;
-	dsi->client.dev = &pdev->dev;
-
-	err = host1x_client_register(&dsi->client);
+	err = component_add(&pdev->dev, &dsi_component_ops);
 	if (err < 0) {
-		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
-			err);
+		dev_err(&pdev->dev, "failed to register component: %d\n", err);
 		return err;
 	}
 
-	platform_set_drvdata(pdev, dsi);
-
 	return 0;
 }
 
@@ -953,12 +934,7 @@ static int tegra_dsi_remove(struct platform_device *pdev)
 	struct tegra_dsi *dsi = platform_get_drvdata(pdev);
 	int err;
 
-	err = host1x_client_unregister(&dsi->client);
-	if (err < 0) {
-		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
-			err);
-		return err;
-	}
+	component_del(&pdev->dev, &dsi_component_ops);
 
 	mipi_dsi_host_unregister(&dsi->host);
 	tegra_mipi_free(dsi->mipi);
diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
index 2c7ca748edf5..f4bfdd0079d8 100644
--- a/drivers/gpu/drm/tegra/gr2d.c
+++ b/drivers/gpu/drm/tegra/gr2d.c
@@ -25,46 +25,49 @@ static inline struct gr2d *to_gr2d(struct tegra_drm_client *client)
 	return container_of(client, struct gr2d, client);
 }
 
-static int gr2d_init(struct host1x_client *client)
+static int gr2d_bind(struct device *dev, struct master *master, void *data)
 {
-	struct tegra_drm_client *drm = host1x_to_drm_client(client);
-	struct tegra_drm *tegra = dev_get_drvdata(client->parent);
+	struct tegra_drm *tegra = master_get_drvdata(master);
 	unsigned long flags = HOST1X_SYNCPT_HAS_BASE;
-	struct gr2d *gr2d = to_gr2d(drm);
+	struct gr2d *gr2d = dev_get_drvdata(dev);
+	int err;
 
-	gr2d->channel = host1x_channel_request(client->dev);
+	gr2d->channel = host1x_channel_request(dev);
 	if (!gr2d->channel)
 		return -ENOMEM;
 
-	client->syncpts[0] = host1x_syncpt_request(client->dev, flags);
-	if (!client->syncpts[0]) {
+	gr2d->client.syncpts[0] = host1x_syncpt_request(dev, flags);
+	if (!gr2d->client.syncpts[0]) {
 		host1x_channel_free(gr2d->channel);
 		return -ENOMEM;
 	}
 
-	return tegra_drm_register_client(tegra, drm);
+	err = tegra_drm_register_client(tegra, &gr2d->client);
+	if (err < 0) {
+		dev_err(dev, "failed to register client: %d\n", err);
+		return err;
+	}
+
+	return 0;
 }
 
-static int gr2d_exit(struct host1x_client *client)
+static void gr2d_unbind(struct device *dev, struct master *master, void *data)
 {
-	struct tegra_drm_client *drm = host1x_to_drm_client(client);
-	struct tegra_drm *tegra = dev_get_drvdata(client->parent);
-	struct gr2d *gr2d = to_gr2d(drm);
+	struct tegra_drm *tegra = master_get_drvdata(master);
+	struct gr2d *gr2d = dev_get_drvdata(dev);
 	int err;
 
-	err = tegra_drm_unregister_client(tegra, drm);
+	err = tegra_drm_unregister_client(tegra, &gr2d->client);
 	if (err < 0)
-		return err;
+		dev_err(dev, "failed to unregister client: %d\n", err);
 
-	host1x_syncpt_free(client->syncpts[0]);
+	host1x_syncpt_free(gr2d->client.syncpts[0]);
 	host1x_channel_free(gr2d->channel);
-
-	return 0;
 }
 
-static const struct host1x_client_ops gr2d_client_ops = {
-	.init = gr2d_init,
-	.exit = gr2d_exit,
+static const struct component_ops tegra_gr2d_component_ops = {
+	.bind = gr2d_bind,
+	.unbind = gr2d_unbind,
 };
 
 static int gr2d_open_channel(struct tegra_drm_client *client,
@@ -150,6 +153,8 @@ static int gr2d_probe(struct platform_device *pdev)
 	if (!gr2d)
 		return -ENOMEM;
 
+	platform_set_drvdata(pdev, gr2d);
+
 	syncpts = devm_kzalloc(dev, sizeof(*syncpts), GFP_KERNEL);
 	if (!syncpts)
 		return -ENOMEM;
@@ -166,28 +171,22 @@ static int gr2d_probe(struct platform_device *pdev)
 		return err;
 	}
 
-	INIT_LIST_HEAD(&gr2d->client.base.list);
-	gr2d->client.base.ops = &gr2d_client_ops;
-	gr2d->client.base.dev = dev;
-	gr2d->client.base.class = HOST1X_CLASS_GR2D;
-	gr2d->client.base.syncpts = syncpts;
-	gr2d->client.base.num_syncpts = 1;
-
 	INIT_LIST_HEAD(&gr2d->client.list);
+	gr2d->client.class = HOST1X_CLASS_GR2D;
+	gr2d->client.syncpts = syncpts;
+	gr2d->client.num_syncpts = 1;
 	gr2d->client.ops = &gr2d_ops;
-
-	err = host1x_client_register(&gr2d->client.base);
-	if (err < 0) {
-		dev_err(dev, "failed to register host1x client: %d\n", err);
-		clk_disable_unprepare(gr2d->clk);
-		return err;
-	}
+	gr2d->client.dev = dev;
 
 	/* initialize address register map */
 	for (i = 0; i < ARRAY_SIZE(gr2d_addr_regs); i++)
 		set_bit(gr2d_addr_regs[i], gr2d->addr_regs);
 
-	platform_set_drvdata(pdev, gr2d);
+	err = component_add(&pdev->dev, &tegra_gr2d_component_ops);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register component: %d\n", err);
+		return err;
+	}
 
 	return 0;
 }
@@ -195,15 +194,8 @@ static int gr2d_probe(struct platform_device *pdev)
 static int gr2d_remove(struct platform_device *pdev)
 {
 	struct gr2d *gr2d = platform_get_drvdata(pdev);
-	int err;
-
-	err = host1x_client_unregister(&gr2d->client.base);
-	if (err < 0) {
-		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
-			err);
-		return err;
-	}
 
+	component_del(&pdev->dev, &tegra_gr2d_component_ops);
 	clk_disable_unprepare(gr2d->clk);
 
 	return 0;
diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
index 0cbb24b1ae04..c45502ad684e 100644
--- a/drivers/gpu/drm/tegra/gr3d.c
+++ b/drivers/gpu/drm/tegra/gr3d.c
@@ -34,46 +34,49 @@ static inline struct gr3d *to_gr3d(struct tegra_drm_client *client)
 	return container_of(client, struct gr3d, client);
 }
 
-static int gr3d_init(struct host1x_client *client)
+static int gr3d_bind(struct device *dev, struct master *master, void *data)
 {
-	struct tegra_drm_client *drm = host1x_to_drm_client(client);
-	struct tegra_drm *tegra = dev_get_drvdata(client->parent);
+	struct tegra_drm *tegra = master_get_drvdata(master);
 	unsigned long flags = HOST1X_SYNCPT_HAS_BASE;
-	struct gr3d *gr3d = to_gr3d(drm);
+	struct gr3d *gr3d = dev_get_drvdata(dev);
+	int err;
 
-	gr3d->channel = host1x_channel_request(client->dev);
+	gr3d->channel = host1x_channel_request(dev);
 	if (!gr3d->channel)
 		return -ENOMEM;
 
-	client->syncpts[0] = host1x_syncpt_request(client->dev, flags);
-	if (!client->syncpts[0]) {
+	gr3d->client.syncpts[0] = host1x_syncpt_request(dev, flags);
+	if (!gr3d->client.syncpts[0]) {
 		host1x_channel_free(gr3d->channel);
 		return -ENOMEM;
 	}
 
-	return tegra_drm_register_client(tegra, drm);
+	err = tegra_drm_register_client(tegra, &gr3d->client);
+	if (err < 0) {
+		dev_err(dev, "failed to register client: %d\n", err);
+		return err;
+	}
+
+	return 0;
 }
 
-static int gr3d_exit(struct host1x_client *client)
+static void gr3d_unbind(struct device *dev, struct master *master, void *data)
 {
-	struct tegra_drm_client *drm = host1x_to_drm_client(client);
-	struct tegra_drm *tegra = dev_get_drvdata(client->parent);
-	struct gr3d *gr3d = to_gr3d(drm);
+	struct tegra_drm *tegra = master_get_drvdata(master);
+	struct gr3d *gr3d = dev_get_drvdata(dev);
 	int err;
 
-	err = tegra_drm_unregister_client(tegra, drm);
+	err = tegra_drm_unregister_client(tegra, &gr3d->client);
 	if (err < 0)
-		return err;
+		dev_err(dev, "failed to unregister client: %d\n", err);
 
-	host1x_syncpt_free(client->syncpts[0]);
+	host1x_syncpt_free(gr3d->client.syncpts[0]);
 	host1x_channel_free(gr3d->channel);
-
-	return 0;
 }
 
-static const struct host1x_client_ops gr3d_client_ops = {
-	.init = gr3d_init,
-	.exit = gr3d_exit,
+static const struct component_ops tegra_gr3d_component_ops = {
+	.bind = gr3d_bind,
+	.unbind = gr3d_unbind,
 };
 
 static int gr3d_open_channel(struct tegra_drm_client *client,
@@ -248,6 +251,8 @@ static int gr3d_probe(struct platform_device *pdev)
 	if (!gr3d)
 		return -ENOMEM;
 
+	platform_set_drvdata(pdev, gr3d);
+
 	syncpts = devm_kzalloc(&pdev->dev, sizeof(*syncpts), GFP_KERNEL);
 	if (!syncpts)
 		return -ENOMEM;
@@ -297,28 +302,22 @@ static int gr3d_probe(struct platform_device *pdev)
 		}
 	}
 
-	INIT_LIST_HEAD(&gr3d->client.base.list);
-	gr3d->client.base.ops = &gr3d_client_ops;
-	gr3d->client.base.dev = &pdev->dev;
-	gr3d->client.base.class = HOST1X_CLASS_GR3D;
-	gr3d->client.base.syncpts = syncpts;
-	gr3d->client.base.num_syncpts = 1;
-
 	INIT_LIST_HEAD(&gr3d->client.list);
+	gr3d->client.class = HOST1X_CLASS_GR3D;
+	gr3d->client.syncpts = syncpts;
+	gr3d->client.num_syncpts = 1;
 	gr3d->client.ops = &gr3d_ops;
-
-	err = host1x_client_register(&gr3d->client.base);
-	if (err < 0) {
-		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
-			err);
-		return err;
-	}
+	gr3d->client.dev = &pdev->dev;
 
 	/* initialize address register map */
 	for (i = 0; i < ARRAY_SIZE(gr3d_addr_regs); i++)
 		set_bit(gr3d_addr_regs[i], gr3d->addr_regs);
 
-	platform_set_drvdata(pdev, gr3d);
+	err = component_add(&pdev->dev, &tegra_gr3d_component_ops);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register component: %d\n", err);
+		return err;
+	}
 
 	return 0;
 }
@@ -326,14 +325,8 @@ static int gr3d_probe(struct platform_device *pdev)
 static int gr3d_remove(struct platform_device *pdev)
 {
 	struct gr3d *gr3d = platform_get_drvdata(pdev);
-	int err;
 
-	err = host1x_client_unregister(&gr3d->client.base);
-	if (err < 0) {
-		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
-			err);
-		return err;
-	}
+	component_del(&pdev->dev, &tegra_gr3d_component_ops);
 
 	if (gr3d->clk_secondary) {
 		tegra_powergate_power_off(TEGRA_POWERGATE_3D1);
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index fec1a63d32c9..c27149718753 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -37,7 +37,6 @@ struct tegra_hdmi_config {
 };
 
 struct tegra_hdmi {
-	struct host1x_client client;
 	struct tegra_output output;
 	struct device *dev;
 	bool enabled;
@@ -65,12 +64,6 @@ struct tegra_hdmi {
 	struct dentry *debugfs;
 };
 
-static inline struct tegra_hdmi *
-host1x_client_to_hdmi(struct host1x_client *client)
-{
-	return container_of(client, struct tegra_hdmi, client);
-}
-
 static inline struct tegra_hdmi *to_hdmi(struct tegra_output *output)
 {
 	return container_of(output, struct tegra_hdmi, output);
@@ -1345,41 +1338,40 @@ static int tegra_hdmi_debugfs_exit(struct tegra_hdmi *hdmi)
 	return 0;
 }
 
-static int tegra_hdmi_init(struct host1x_client *client)
+static int hdmi_bind(struct device *dev, struct master *master, void *data)
 {
-	struct tegra_drm *tegra = dev_get_drvdata(client->parent);
-	struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
+	struct tegra_drm *tegra = master_get_drvdata(master);
+	struct tegra_hdmi *hdmi = dev_get_drvdata(dev);
 	int err;
 
 	hdmi->output.type = TEGRA_OUTPUT_HDMI;
-	hdmi->output.dev = client->dev;
 	hdmi->output.ops = &hdmi_ops;
+	hdmi->output.dev = dev;
 
 	err = tegra_output_init(tegra->drm, &hdmi->output);
 	if (err < 0) {
-		dev_err(client->dev, "output setup failed: %d\n", err);
+		dev_err(dev, "output setup failed: %d\n", err);
 		return err;
 	}
 
 	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
 		err = tegra_hdmi_debugfs_init(hdmi, tegra->drm->primary);
 		if (err < 0)
-			dev_err(client->dev, "debugfs setup failed: %d\n", err);
+			dev_err(dev, "debugfs setup failed: %d\n", err);
 	}
 
 	err = regulator_enable(hdmi->hdmi);
 	if (err < 0) {
-		dev_err(client->dev, "failed to enable HDMI regulator: %d\n",
-			err);
+		dev_err(dev, "failed to enable HDMI regulator: %d\n", err);
 		return err;
 	}
 
 	return 0;
 }
 
-static int tegra_hdmi_exit(struct host1x_client *client)
+static void hdmi_unbind(struct device *dev, struct master *master, void *data)
 {
-	struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
+	struct tegra_hdmi *hdmi = dev_get_drvdata(dev);
 	int err;
 
 	regulator_disable(hdmi->hdmi);
@@ -1387,28 +1379,21 @@ static int tegra_hdmi_exit(struct host1x_client *client)
 	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
 		err = tegra_hdmi_debugfs_exit(hdmi);
 		if (err < 0)
-			dev_err(client->dev, "debugfs cleanup failed: %d\n",
-				err);
+			dev_err(dev, "debugfs cleanup failed: %d\n", err);
 	}
 
 	err = tegra_output_disable(&hdmi->output);
-	if (err < 0) {
-		dev_err(client->dev, "output failed to disable: %d\n", err);
-		return err;
-	}
+	if (err < 0)
+		dev_err(dev, "output failed to disable: %d\n", err);
 
 	err = tegra_output_exit(&hdmi->output);
-	if (err < 0) {
-		dev_err(client->dev, "output cleanup failed: %d\n", err);
-		return err;
-	}
-
-	return 0;
+	if (err < 0)
+		dev_err(dev, "output cleanup failed: %d\n", err);
 }
 
-static const struct host1x_client_ops hdmi_client_ops = {
-	.init = tegra_hdmi_init,
-	.exit = tegra_hdmi_exit,
+static const struct component_ops hdmi_component_ops = {
+	.bind = hdmi_bind,
+	.unbind = hdmi_unbind,
 };
 
 static const struct tegra_hdmi_config tegra20_hdmi_config = {
@@ -1466,6 +1451,8 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
 	if (!hdmi)
 		return -ENOMEM;
 
+	platform_set_drvdata(pdev, hdmi);
+
 	hdmi->config = match->data;
 	hdmi->dev = &pdev->dev;
 	hdmi->audio_source = AUTO;
@@ -1530,19 +1517,12 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
 
 	hdmi->irq = err;
 
-	INIT_LIST_HEAD(&hdmi->client.list);
-	hdmi->client.ops = &hdmi_client_ops;
-	hdmi->client.dev = &pdev->dev;
-
-	err = host1x_client_register(&hdmi->client);
+	err = component_add(&pdev->dev, &hdmi_component_ops);
 	if (err < 0) {
-		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
-			err);
+		dev_err(&pdev->dev, "failed to register component: %d\n", err);
 		return err;
 	}
 
-	platform_set_drvdata(pdev, hdmi);
-
 	return 0;
 }
 
@@ -1551,12 +1531,7 @@ static int tegra_hdmi_remove(struct platform_device *pdev)
 	struct tegra_hdmi *hdmi = platform_get_drvdata(pdev);
 	int err;
 
-	err = host1x_client_unregister(&hdmi->client);
-	if (err < 0) {
-		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
-			err);
-		return err;
-	}
+	component_del(&pdev->dev, &hdmi_component_ops);
 
 	err = tegra_output_remove(&hdmi->output);
 	if (err < 0) {
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index 7d66f6e53919..60535e380d18 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -20,7 +20,6 @@
 #include "sor.h"
 
 struct tegra_sor {
-	struct host1x_client client;
 	struct tegra_output output;
 	struct device *dev;
 
@@ -40,12 +39,6 @@ struct tegra_sor {
 	struct dentry *debugfs;
 };
 
-static inline struct tegra_sor *
-host1x_client_to_sor(struct host1x_client *client)
-{
-	return container_of(client, struct tegra_sor, client);
-}
-
 static inline struct tegra_sor *to_sor(struct tegra_output *output)
 {
 	return container_of(output, struct tegra_sor, output);
@@ -1042,10 +1035,10 @@ static int tegra_sor_debugfs_exit(struct tegra_sor *sor)
 	return 0;
 }
 
-static int tegra_sor_init(struct host1x_client *client)
+static int sor_bind(struct device *dev, struct master *master, void *data)
 {
-	struct tegra_drm *tegra = dev_get_drvdata(client->parent);
-	struct tegra_sor *sor = host1x_client_to_sor(client);
+	struct tegra_drm *tegra = master_get_drvdata(master);
+	struct tegra_sor *sor = dev_get_drvdata(dev);
 	int err;
 
 	if (!sor->dpaux)
@@ -1058,7 +1051,7 @@ static int tegra_sor_init(struct host1x_client *client)
 
 	err = tegra_output_init(tegra->drm, &sor->output);
 	if (err < 0) {
-		dev_err(sor->dev, "output setup failed: %d\n", err);
+		dev_err(dev, "output setup failed: %d\n", err);
 		return err;
 	}
 
@@ -1067,13 +1060,13 @@ static int tegra_sor_init(struct host1x_client *client)
 
 		err = tegra_sor_debugfs_init(sor, root);
 		if (err < 0)
-			dev_err(sor->dev, "debugfs setup failed: %d\n", err);
+			dev_err(dev, "debugfs setup failed: %d\n", err);
 	}
 
 	if (sor->dpaux) {
 		err = tegra_dpaux_attach(sor->dpaux, &sor->output);
 		if (err < 0) {
-			dev_err(sor->dev, "failed to attach DP: %d\n", err);
+			dev_err(dev, "failed to attach DP: %d\n", err);
 			return err;
 		}
 	}
@@ -1081,43 +1074,35 @@ static int tegra_sor_init(struct host1x_client *client)
 	return 0;
 }
 
-static int tegra_sor_exit(struct host1x_client *client)
+static void sor_unbind(struct device *dev, struct master *master, void *data)
 {
-	struct tegra_sor *sor = host1x_client_to_sor(client);
+	struct tegra_sor *sor = dev_get_drvdata(dev);
 	int err;
 
 	err = tegra_output_disable(&sor->output);
-	if (err < 0) {
-		dev_err(sor->dev, "output failed to disable: %d\n", err);
-		return err;
-	}
+	if (err < 0)
+		dev_err(dev, "output failed to disable: %d\n", err);
 
 	if (sor->dpaux) {
 		err = tegra_dpaux_detach(sor->dpaux);
-		if (err < 0) {
-			dev_err(sor->dev, "failed to detach DP: %d\n", err);
-			return err;
-		}
+		if (err < 0)
+			dev_err(dev, "failed to detach DP: %d\n", err);
 	}
 
 	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
 		err = tegra_sor_debugfs_exit(sor);
 		if (err < 0)
-			dev_err(sor->dev, "debugfs cleanup failed: %d\n", err);
+			dev_err(dev, "debugfs cleanup failed: %d\n", err);
 	}
 
 	err = tegra_output_exit(&sor->output);
-	if (err < 0) {
-		dev_err(sor->dev, "output cleanup failed: %d\n", err);
-		return err;
-	}
-
-	return 0;
+	if (err < 0)
+		dev_err(dev, "output cleanup failed: %d\n", err);
 }
 
-static const struct host1x_client_ops sor_client_ops = {
-	.init = tegra_sor_init,
-	.exit = tegra_sor_exit,
+static const struct component_ops tegra_sor_component_ops = {
+	.bind = sor_bind,
+	.unbind = sor_unbind,
 };
 
 static int tegra_sor_probe(struct platform_device *pdev)
@@ -1132,6 +1117,7 @@ static int tegra_sor_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	sor->output.dev = sor->dev = &pdev->dev;
+	platform_set_drvdata(pdev, sor);
 
 	np = of_parse_phandle(pdev->dev.of_node, "nvidia,dpaux", 0);
 	if (np) {
@@ -1183,35 +1169,22 @@ static int tegra_sor_probe(struct platform_device *pdev)
 	if (err < 0)
 		return err;
 
-	INIT_LIST_HEAD(&sor->client.list);
-	sor->client.ops = &sor_client_ops;
-	sor->client.dev = &pdev->dev;
-
 	mutex_init(&sor->lock);
 
-	err = host1x_client_register(&sor->client);
+	err = component_add(&pdev->dev, &tegra_sor_component_ops);
 	if (err < 0) {
-		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
-			err);
+		dev_err(&pdev->dev, "failed to register component: %d\n", err);
 		return err;
 	}
 
-	platform_set_drvdata(pdev, sor);
-
 	return 0;
 }
 
 static int tegra_sor_remove(struct platform_device *pdev)
 {
 	struct tegra_sor *sor = platform_get_drvdata(pdev);
-	int err;
 
-	err = host1x_client_unregister(&sor->client);
-	if (err < 0) {
-		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
-			err);
-		return err;
-	}
+	component_del(&pdev->dev, &tegra_sor_component_ops);
 
 	clk_disable_unprepare(sor->clk_parent);
 	clk_disable_unprepare(sor->clk_safe);
diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index c1189f004441..2ff37ab71fd2 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -1,5 +1,4 @@
 host1x-y = \
-	bus.o \
 	syncpt.o \
 	dev.o \
 	intr.o \
diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c
deleted file mode 100644
index ccdd2e6da5e3..000000000000
--- a/drivers/gpu/host1x/bus.c
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- * Copyright (C) 2012 Avionic Design GmbH
- * Copyright (C) 2012-2013, NVIDIA Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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 <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/host1x.h>
-#include <linux/of.h>
-#include <linux/slab.h>
-
-#include "bus.h"
-#include "dev.h"
-
-static DEFINE_MUTEX(clients_lock);
-static LIST_HEAD(clients);
-
-static DEFINE_MUTEX(drivers_lock);
-static LIST_HEAD(drivers);
-
-static DEFINE_MUTEX(devices_lock);
-static LIST_HEAD(devices);
-
-struct host1x_subdev {
-	struct host1x_client *client;
-	struct device_node *np;
-	struct list_head list;
-};
-
-/**
- * host1x_subdev_add() - add a new subdevice with an associated device node
- */
-static int host1x_subdev_add(struct host1x_device *device,
-			     struct device_node *np)
-{
-	struct host1x_subdev *subdev;
-
-	subdev = kzalloc(sizeof(*subdev), GFP_KERNEL);
-	if (!subdev)
-		return -ENOMEM;
-
-	INIT_LIST_HEAD(&subdev->list);
-	subdev->np = of_node_get(np);
-
-	mutex_lock(&device->subdevs_lock);
-	list_add_tail(&subdev->list, &device->subdevs);
-	mutex_unlock(&device->subdevs_lock);
-
-	return 0;
-}
-
-/**
- * host1x_subdev_del() - remove subdevice
- */
-static void host1x_subdev_del(struct host1x_subdev *subdev)
-{
-	list_del(&subdev->list);
-	of_node_put(subdev->np);
-	kfree(subdev);
-}
-
-/**
- * host1x_device_parse_dt() - scan device tree and add matching subdevices
- */
-static int host1x_device_parse_dt(struct host1x_device *device)
-{
-	struct device_node *np;
-	int err;
-
-	for_each_child_of_node(device->dev.parent->of_node, np) {
-		if (of_match_node(device->driver->subdevs, np) &&
-		    of_device_is_available(np)) {
-			err = host1x_subdev_add(device, np);
-			if (err < 0)
-				return err;
-		}
-	}
-
-	return 0;
-}
-
-static void host1x_subdev_register(struct host1x_device *device,
-				   struct host1x_subdev *subdev,
-				   struct host1x_client *client)
-{
-	int err;
-
-	/*
-	 * Move the subdevice to the list of active (registered) subdevices
-	 * and associate it with a client. At the same time, associate the
-	 * client with its parent device.
-	 */
-	mutex_lock(&device->subdevs_lock);
-	mutex_lock(&device->clients_lock);
-	list_move_tail(&client->list, &device->clients);
-	list_move_tail(&subdev->list, &device->active);
-	client->parent = &device->dev;
-	subdev->client = client;
-	mutex_unlock(&device->clients_lock);
-	mutex_unlock(&device->subdevs_lock);
-
-	/*
-	 * When all subdevices have been registered, the composite device is
-	 * ready to be probed.
-	 */
-	if (list_empty(&device->subdevs)) {
-		err = device->driver->probe(device);
-		if (err < 0)
-			dev_err(&device->dev, "probe failed: %d\n", err);
-	}
-}
-
-static void __host1x_subdev_unregister(struct host1x_device *device,
-				       struct host1x_subdev *subdev)
-{
-	struct host1x_client *client = subdev->client;
-	int err;
-
-	/*
-	 * If all subdevices have been activated, we're about to remove the
-	 * first active subdevice, so unload the driver first.
-	 */
-	if (list_empty(&device->subdevs)) {
-		err = device->driver->remove(device);
-		if (err < 0)
-			dev_err(&device->dev, "remove failed: %d\n", err);
-	}
-
-	/*
-	 * Move the subdevice back to the list of idle subdevices and remove
-	 * it from list of clients.
-	 */
-	mutex_lock(&device->clients_lock);
-	subdev->client = NULL;
-	client->parent = NULL;
-	list_move_tail(&subdev->list, &device->subdevs);
-	/*
-	 * XXX: Perhaps don't do this here, but rather explicitly remove it
-	 * when the device is about to be deleted.
-	 *
-	 * This is somewhat complicated by the fact that this function is
-	 * used to remove the subdevice when a client is unregistered but
-	 * also when the composite device is about to be removed.
-	 */
-	list_del_init(&client->list);
-	mutex_unlock(&device->clients_lock);
-}
-
-static void host1x_subdev_unregister(struct host1x_device *device,
-				     struct host1x_subdev *subdev)
-{
-	mutex_lock(&device->subdevs_lock);
-	__host1x_subdev_unregister(device, subdev);
-	mutex_unlock(&device->subdevs_lock);
-}
-
-int host1x_device_init(struct host1x_device *device)
-{
-	struct host1x_client *client;
-	int err;
-
-	mutex_lock(&device->clients_lock);
-
-	list_for_each_entry(client, &device->clients, list) {
-		if (client->ops && client->ops->init) {
-			err = client->ops->init(client);
-			if (err < 0) {
-				dev_err(&device->dev,
-					"failed to initialize %s: %d\n",
-					dev_name(client->dev), err);
-				mutex_unlock(&device->clients_lock);
-				return err;
-			}
-		}
-	}
-
-	mutex_unlock(&device->clients_lock);
-
-	return 0;
-}
-EXPORT_SYMBOL(host1x_device_init);
-
-int host1x_device_exit(struct host1x_device *device)
-{
-	struct host1x_client *client;
-	int err;
-
-	mutex_lock(&device->clients_lock);
-
-	list_for_each_entry_reverse(client, &device->clients, list) {
-		if (client->ops && client->ops->exit) {
-			err = client->ops->exit(client);
-			if (err < 0) {
-				dev_err(&device->dev,
-					"failed to cleanup %s: %d\n",
-					dev_name(client->dev), err);
-				mutex_unlock(&device->clients_lock);
-				return err;
-			}
-		}
-	}
-
-	mutex_unlock(&device->clients_lock);
-
-	return 0;
-}
-EXPORT_SYMBOL(host1x_device_exit);
-
-static int host1x_register_client(struct host1x *host1x,
-				  struct host1x_client *client)
-{
-	struct host1x_device *device;
-	struct host1x_subdev *subdev;
-
-	mutex_lock(&host1x->devices_lock);
-
-	list_for_each_entry(device, &host1x->devices, list) {
-		list_for_each_entry(subdev, &device->subdevs, list) {
-			if (subdev->np == client->dev->of_node) {
-				host1x_subdev_register(device, subdev, client);
-				mutex_unlock(&host1x->devices_lock);
-				return 0;
-			}
-		}
-	}
-
-	mutex_unlock(&host1x->devices_lock);
-	return -ENODEV;
-}
-
-static int host1x_unregister_client(struct host1x *host1x,
-				    struct host1x_client *client)
-{
-	struct host1x_device *device, *dt;
-	struct host1x_subdev *subdev;
-
-	mutex_lock(&host1x->devices_lock);
-
-	list_for_each_entry_safe(device, dt, &host1x->devices, list) {
-		list_for_each_entry(subdev, &device->active, list) {
-			if (subdev->client == client) {
-				host1x_subdev_unregister(device, subdev);
-				mutex_unlock(&host1x->devices_lock);
-				return 0;
-			}
-		}
-	}
-
-	mutex_unlock(&host1x->devices_lock);
-	return -ENODEV;
-}
-
-static struct bus_type host1x_bus_type = {
-	.name = "host1x",
-};
-
-int host1x_bus_init(void)
-{
-	return bus_register(&host1x_bus_type);
-}
-
-void host1x_bus_exit(void)
-{
-	bus_unregister(&host1x_bus_type);
-}
-
-static void host1x_device_release(struct device *dev)
-{
-	struct host1x_device *device = to_host1x_device(dev);
-
-	kfree(device);
-}
-
-static int host1x_device_add(struct host1x *host1x,
-			     struct host1x_driver *driver)
-{
-	struct host1x_client *client, *tmp;
-	struct host1x_subdev *subdev;
-	struct host1x_device *device;
-	int err;
-
-	device = kzalloc(sizeof(*device), GFP_KERNEL);
-	if (!device)
-		return -ENOMEM;
-
-	mutex_init(&device->subdevs_lock);
-	INIT_LIST_HEAD(&device->subdevs);
-	INIT_LIST_HEAD(&device->active);
-	mutex_init(&device->clients_lock);
-	INIT_LIST_HEAD(&device->clients);
-	INIT_LIST_HEAD(&device->list);
-	device->driver = driver;
-
-	device->dev.coherent_dma_mask = host1x->dev->coherent_dma_mask;
-	device->dev.dma_mask = &device->dev.coherent_dma_mask;
-	device->dev.release = host1x_device_release;
-	dev_set_name(&device->dev, "%s", driver->name);
-	device->dev.bus = &host1x_bus_type;
-	device->dev.parent = host1x->dev;
-
-	err = device_register(&device->dev);
-	if (err < 0)
-		return err;
-
-	err = host1x_device_parse_dt(device);
-	if (err < 0) {
-		device_unregister(&device->dev);
-		return err;
-	}
-
-	mutex_lock(&host1x->devices_lock);
-	list_add_tail(&device->list, &host1x->devices);
-	mutex_unlock(&host1x->devices_lock);
-
-	mutex_lock(&clients_lock);
-
-	list_for_each_entry_safe(client, tmp, &clients, list) {
-		list_for_each_entry(subdev, &device->subdevs, list) {
-			if (subdev->np == client->dev->of_node) {
-				host1x_subdev_register(device, subdev, client);
-				break;
-			}
-		}
-	}
-
-	mutex_unlock(&clients_lock);
-
-	return 0;
-}
-
-/*
- * Removes a device by first unregistering any subdevices and then removing
- * itself from the list of devices.
- *
- * This function must be called with the host1x->devices_lock held.
- */
-static void host1x_device_del(struct host1x *host1x,
-			      struct host1x_device *device)
-{
-	struct host1x_subdev *subdev, *sd;
-	struct host1x_client *client, *cl;
-
-	mutex_lock(&device->subdevs_lock);
-
-	/* unregister subdevices */
-	list_for_each_entry_safe(subdev, sd, &device->active, list) {
-		/*
-		 * host1x_subdev_unregister() will remove the client from
-		 * any lists, so we'll need to manually add it back to the
-		 * list of idle clients.
-		 *
-		 * XXX: Alternatively, perhaps don't remove the client from
-		 * any lists in host1x_subdev_unregister() and instead do
-		 * that explicitly from host1x_unregister_client()?
-		 */
-		client = subdev->client;
-
-		__host1x_subdev_unregister(device, subdev);
-
-		/* add the client to the list of idle clients */
-		mutex_lock(&clients_lock);
-		list_add_tail(&client->list, &clients);
-		mutex_unlock(&clients_lock);
-	}
-
-	/* remove subdevices */
-	list_for_each_entry_safe(subdev, sd, &device->subdevs, list)
-		host1x_subdev_del(subdev);
-
-	mutex_unlock(&device->subdevs_lock);
-
-	/* move clients to idle list */
-	mutex_lock(&clients_lock);
-	mutex_lock(&device->clients_lock);
-
-	list_for_each_entry_safe(client, cl, &device->clients, list)
-		list_move_tail(&client->list, &clients);
-
-	mutex_unlock(&device->clients_lock);
-	mutex_unlock(&clients_lock);
-
-	/* finally remove the device */
-	list_del_init(&device->list);
-	device_unregister(&device->dev);
-}
-
-static void host1x_attach_driver(struct host1x *host1x,
-				 struct host1x_driver *driver)
-{
-	struct host1x_device *device;
-	int err;
-
-	mutex_lock(&host1x->devices_lock);
-
-	list_for_each_entry(device, &host1x->devices, list) {
-		if (device->driver == driver) {
-			mutex_unlock(&host1x->devices_lock);
-			return;
-		}
-	}
-
-	mutex_unlock(&host1x->devices_lock);
-
-	err = host1x_device_add(host1x, driver);
-	if (err < 0)
-		dev_err(host1x->dev, "failed to allocate device: %d\n", err);
-}
-
-static void host1x_detach_driver(struct host1x *host1x,
-				 struct host1x_driver *driver)
-{
-	struct host1x_device *device, *tmp;
-
-	mutex_lock(&host1x->devices_lock);
-
-	list_for_each_entry_safe(device, tmp, &host1x->devices, list)
-		if (device->driver == driver)
-			host1x_device_del(host1x, device);
-
-	mutex_unlock(&host1x->devices_lock);
-}
-
-int host1x_register(struct host1x *host1x)
-{
-	struct host1x_driver *driver;
-
-	mutex_lock(&devices_lock);
-	list_add_tail(&host1x->list, &devices);
-	mutex_unlock(&devices_lock);
-
-	mutex_lock(&drivers_lock);
-
-	list_for_each_entry(driver, &drivers, list)
-		host1x_attach_driver(host1x, driver);
-
-	mutex_unlock(&drivers_lock);
-
-	return 0;
-}
-
-int host1x_unregister(struct host1x *host1x)
-{
-	struct host1x_driver *driver;
-
-	mutex_lock(&drivers_lock);
-
-	list_for_each_entry(driver, &drivers, list)
-		host1x_detach_driver(host1x, driver);
-
-	mutex_unlock(&drivers_lock);
-
-	mutex_lock(&devices_lock);
-	list_del_init(&host1x->list);
-	mutex_unlock(&devices_lock);
-
-	return 0;
-}
-
-int host1x_driver_register(struct host1x_driver *driver)
-{
-	struct host1x *host1x;
-
-	INIT_LIST_HEAD(&driver->list);
-
-	mutex_lock(&drivers_lock);
-	list_add_tail(&driver->list, &drivers);
-	mutex_unlock(&drivers_lock);
-
-	mutex_lock(&devices_lock);
-
-	list_for_each_entry(host1x, &devices, list)
-		host1x_attach_driver(host1x, driver);
-
-	mutex_unlock(&devices_lock);
-
-	return 0;
-}
-EXPORT_SYMBOL(host1x_driver_register);
-
-void host1x_driver_unregister(struct host1x_driver *driver)
-{
-	mutex_lock(&drivers_lock);
-	list_del_init(&driver->list);
-	mutex_unlock(&drivers_lock);
-}
-EXPORT_SYMBOL(host1x_driver_unregister);
-
-int host1x_client_register(struct host1x_client *client)
-{
-	struct host1x *host1x;
-	int err;
-
-	mutex_lock(&devices_lock);
-
-	list_for_each_entry(host1x, &devices, list) {
-		err = host1x_register_client(host1x, client);
-		if (!err) {
-			mutex_unlock(&devices_lock);
-			return 0;
-		}
-	}
-
-	mutex_unlock(&devices_lock);
-
-	mutex_lock(&clients_lock);
-	list_add_tail(&client->list, &clients);
-	mutex_unlock(&clients_lock);
-
-	return 0;
-}
-EXPORT_SYMBOL(host1x_client_register);
-
-int host1x_client_unregister(struct host1x_client *client)
-{
-	struct host1x_client *c;
-	struct host1x *host1x;
-	int err;
-
-	mutex_lock(&devices_lock);
-
-	list_for_each_entry(host1x, &devices, list) {
-		err = host1x_unregister_client(host1x, client);
-		if (!err) {
-			mutex_unlock(&devices_lock);
-			return 0;
-		}
-	}
-
-	mutex_unlock(&devices_lock);
-	mutex_lock(&clients_lock);
-
-	list_for_each_entry(c, &clients, list) {
-		if (c == client) {
-			list_del_init(&c->list);
-			break;
-		}
-	}
-
-	mutex_unlock(&clients_lock);
-
-	return 0;
-}
-EXPORT_SYMBOL(host1x_client_unregister);
diff --git a/drivers/gpu/host1x/bus.h b/drivers/gpu/host1x/bus.h
deleted file mode 100644
index 4099e99212c8..000000000000
--- a/drivers/gpu/host1x/bus.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2012 Avionic Design GmbH
- * Copyright (C) 2012-2013, NVIDIA Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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 <http://www.gnu.org/licenses/>.
- */
-
-#ifndef HOST1X_BUS_H
-#define HOST1X_BUS_H
-
-struct host1x;
-
-int host1x_bus_init(void);
-void host1x_bus_exit(void);
-
-int host1x_register(struct host1x *host1x);
-int host1x_unregister(struct host1x *host1x);
-
-#endif
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index 2529908d304b..b92812ba6f18 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -27,7 +27,6 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/host1x.h>
 
-#include "bus.h"
 #include "dev.h"
 #include "intr.h"
 #include "channel.h"
@@ -124,8 +123,8 @@ static int host1x_probe(struct platform_device *pdev)
 	if (!host)
 		return -ENOMEM;
 
-	mutex_init(&host->devices_lock);
-	INIT_LIST_HEAD(&host->devices);
+	mutex_init(&host->masters_lock);
+	INIT_LIST_HEAD(&host->masters);
 	INIT_LIST_HEAD(&host->list);
 	host->dev = &pdev->dev;
 	host->info = id->data;
@@ -176,7 +175,10 @@ static int host1x_probe(struct platform_device *pdev)
 
 	host1x_debug_init(host);
 
-	err = host1x_register(host);
+	host->interface.name = "nvidia,tegra-host1x";
+	host->interface.dev = &pdev->dev;
+
+	err = interface_add(&host->interface);
 	if (err < 0)
 		goto fail_deinit_intr;
 
@@ -195,7 +197,7 @@ static int host1x_remove(struct platform_device *pdev)
 {
 	struct host1x *host = platform_get_drvdata(pdev);
 
-	host1x_unregister(host);
+	interface_remove(&host->interface);
 	host1x_intr_deinit(host);
 	host1x_syncpt_deinit(host);
 	clk_disable_unprepare(host->clk);
@@ -216,13 +218,9 @@ static int __init tegra_host1x_init(void)
 {
 	int err;
 
-	err = host1x_bus_init();
-	if (err < 0)
-		return err;
-
 	err = platform_driver_register(&tegra_host1x_driver);
 	if (err < 0)
-		goto unregister_bus;
+		return err;
 
 	err = platform_driver_register(&tegra_mipi_driver);
 	if (err < 0)
@@ -232,8 +230,6 @@ static int __init tegra_host1x_init(void)
 
 unregister_host1x:
 	platform_driver_unregister(&tegra_host1x_driver);
-unregister_bus:
-	host1x_bus_exit();
 	return err;
 }
 module_init(tegra_host1x_init);
@@ -242,7 +238,6 @@ static void __exit tegra_host1x_exit(void)
 {
 	platform_driver_unregister(&tegra_mipi_driver);
 	platform_driver_unregister(&tegra_host1x_driver);
-	host1x_bus_exit();
 }
 module_exit(tegra_host1x_exit);
 
diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h
index 0b6e8e9629c5..90e4716ee220 100644
--- a/drivers/gpu/host1x/dev.h
+++ b/drivers/gpu/host1x/dev.h
@@ -17,6 +17,7 @@
 #ifndef HOST1X_DEV_H
 #define HOST1X_DEV_H
 
+#include <linux/interface.h>
 #include <linux/platform_device.h>
 #include <linux/device.h>
 
@@ -127,9 +128,9 @@ struct host1x {
 
 	struct dentry *debugfs;
 
-	struct mutex devices_lock;
-	struct list_head devices;
-
+	struct interface interface;
+	struct mutex masters_lock;
+	struct list_head masters;
 	struct list_head list;
 };
 
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index b432b3ddbc13..14b6161328df 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -19,6 +19,7 @@
 #ifndef __LINUX_HOST1X_H
 #define __LINUX_HOST1X_H
 
+#include <linux/component.h>
 #include <linux/device.h>
 #include <linux/types.h>
 
@@ -30,27 +31,6 @@ enum host1x_class {
 	HOST1X_CLASS_GPU = 0x61,
 };
 
-struct host1x_client;
-
-struct host1x_client_ops {
-	int (*init)(struct host1x_client *client);
-	int (*exit)(struct host1x_client *client);
-};
-
-struct host1x_client {
-	struct list_head list;
-	struct device *parent;
-	struct device *dev;
-
-	const struct host1x_client_ops *ops;
-
-	enum host1x_class class;
-	struct host1x_channel *channel;
-
-	struct host1x_syncpt **syncpts;
-	unsigned int num_syncpts;
-};
-
 /*
  * host1x buffer objects
  */
@@ -241,48 +221,6 @@ void host1x_job_put(struct host1x_job *job);
 int host1x_job_pin(struct host1x_job *job, struct device *dev);
 void host1x_job_unpin(struct host1x_job *job);
 
-/*
- * subdevice probe infrastructure
- */
-
-struct host1x_device;
-
-struct host1x_driver {
-	const struct of_device_id *subdevs;
-	struct list_head list;
-	const char *name;
-
-	int (*probe)(struct host1x_device *device);
-	int (*remove)(struct host1x_device *device);
-};
-
-int host1x_driver_register(struct host1x_driver *driver);
-void host1x_driver_unregister(struct host1x_driver *driver);
-
-struct host1x_device {
-	struct host1x_driver *driver;
-	struct list_head list;
-	struct device dev;
-
-	struct mutex subdevs_lock;
-	struct list_head subdevs;
-	struct list_head active;
-
-	struct mutex clients_lock;
-	struct list_head clients;
-};
-
-static inline struct host1x_device *to_host1x_device(struct device *dev)
-{
-	return container_of(dev, struct host1x_device, dev);
-}
-
-int host1x_device_init(struct host1x_device *device);
-int host1x_device_exit(struct host1x_device *device);
-
-int host1x_client_register(struct host1x_client *client);
-int host1x_client_unregister(struct host1x_client *client);
-
 struct tegra_mipi_device;
 
 struct tegra_mipi_device *tegra_mipi_request(struct device *device);
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [RFC 4/5] drm: Introduce drm_set_unique()
  2014-04-22 15:09 ` [RFC 4/5] drm: Introduce drm_set_unique() Thierry Reding
@ 2014-04-22 15:48   ` Daniel Vetter
  2014-04-23  7:17     ` Thierry Reding
  0 siblings, 1 reply; 12+ messages in thread
From: Daniel Vetter @ 2014-04-22 15:48 UTC (permalink / raw)
  To: Thierry Reding
  Cc: dri-devel, linux-tegra, Greg Kroah-Hartman, linux-kernel, Russell King

On Tue, Apr 22, 2014 at 05:09:32PM +0200, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> Add a helper function that allows drivers to statically set the unique
> name of the device. This will allow platform and USB drivers to get rid
> of their DRM bus implementations and directly use drm_dev_alloc() and
> drm_dev_register().
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  drivers/gpu/drm/drm_ioctl.c | 37 +++++++++++++++++++++++++++++++------
>  drivers/gpu/drm/drm_stub.c  |  1 +
>  include/drm/drmP.h          |  3 +++
>  3 files changed, 35 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
> index 2dd3a6d8382b..371db3bef60c 100644
> --- a/drivers/gpu/drm/drm_ioctl.c
> +++ b/drivers/gpu/drm/drm_ioctl.c
> @@ -42,6 +42,20 @@
>  #include <asm/mtrr.h>
>  #endif
>  
> +int drm_set_unique(struct drm_device *dev, const char *fmt, ...)

Can you please add a bit of kerneldoc for this? drm_ioctl.c isn't yet
pulled into the drm reference docbook, but better to have it there
already. With that fixed this is

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> +{
> +	va_list ap;
> +
> +	kfree(dev->unique);
> +
> +	va_start(ap, fmt);
> +	dev->unique = kvasprintf(GFP_KERNEL, fmt, ap);
> +	va_end(ap);
> +
> +	return dev->unique ? 0 : -ENOMEM;
> +}
> +EXPORT_SYMBOL(drm_set_unique);
> +
>  /**
>   * Get the bus id.
>   *
> @@ -131,13 +145,24 @@ static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
>  	if (master->unique != NULL)
>  		drm_unset_busid(dev, master);
>  
> -	ret = dev->driver->bus->set_busid(dev, master);
> -	if (ret)
> -		goto err;
> +	if (dev->driver->bus && dev->driver->bus->set_busid) {
> +		ret = dev->driver->bus->set_busid(dev, master);
> +		if (ret) {
> +			drm_unset_busid(dev, master);
> +			return ret;
> +		}
> +	} else {
> +		WARN(dev->unique == NULL,
> +		     "No drm_bus.set_busid() implementation provided by %ps. "
> +		     "Set the unique name explicitly using drm_set_unique().",
> +		     dev->driver);
> +
> +		master->unique = kstrdup(dev->unique, GFP_KERNEL);
> +		if (master->unique)
> +			master->unique_len = strlen(dev->unique);
> +	}
> +
>  	return 0;
> -err:
> -	drm_unset_busid(dev, master);
> -	return ret;
>  }
>  
>  /**
> diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
> index 3a8e832ad151..9465cf766fe7 100644
> --- a/drivers/gpu/drm/drm_stub.c
> +++ b/drivers/gpu/drm/drm_stub.c
> @@ -646,6 +646,7 @@ static void drm_dev_release(struct kref *ref)
>  	drm_minor_free(dev, DRM_MINOR_CONTROL);
>  
>  	mutex_destroy(&dev->master_mutex);
> +	kfree(dev->unique);
>  	kfree(dev);
>  }
>  
> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index 8c80c1894b41..8fdefcdc4036 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -1158,6 +1158,8 @@ struct drm_device {
>  	struct drm_vma_offset_manager *vma_offset_manager;
>  	/*@} */
>  	int switch_power_state;
> +
> +	char *unique;
>  };
>  
>  #define DRM_SWITCH_POWER_ON 0
> @@ -1238,6 +1240,7 @@ extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
>  				/* Misc. IOCTL support (drm_ioctl.h) */
>  extern int drm_irq_by_busid(struct drm_device *dev, void *data,
>  			    struct drm_file *file_priv);
> +extern int drm_set_unique(struct drm_device *dev, const char *fmt, ...);
>  extern int drm_getunique(struct drm_device *dev, void *data,
>  			 struct drm_file *file_priv);
>  extern int drm_setunique(struct drm_device *dev, void *data,
> -- 
> 1.9.2
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC 4/5] drm: Introduce drm_set_unique()
  2014-04-22 15:48   ` Daniel Vetter
@ 2014-04-23  7:17     ` Thierry Reding
  2014-04-23  8:40       ` Daniel Vetter
  0 siblings, 1 reply; 12+ messages in thread
From: Thierry Reding @ 2014-04-23  7:17 UTC (permalink / raw)
  To: dri-devel, linux-tegra, Greg Kroah-Hartman, linux-kernel, Russell King

[-- Attachment #1: Type: text/plain, Size: 1521 bytes --]

On Tue, Apr 22, 2014 at 05:48:07PM +0200, Daniel Vetter wrote:
> On Tue, Apr 22, 2014 at 05:09:32PM +0200, Thierry Reding wrote:
> > From: Thierry Reding <treding@nvidia.com>
> > 
> > Add a helper function that allows drivers to statically set the unique
> > name of the device. This will allow platform and USB drivers to get rid
> > of their DRM bus implementations and directly use drm_dev_alloc() and
> > drm_dev_register().
> > 
> > Signed-off-by: Thierry Reding <treding@nvidia.com>
> > ---
> >  drivers/gpu/drm/drm_ioctl.c | 37 +++++++++++++++++++++++++++++++------
> >  drivers/gpu/drm/drm_stub.c  |  1 +
> >  include/drm/drmP.h          |  3 +++
> >  3 files changed, 35 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
> > index 2dd3a6d8382b..371db3bef60c 100644
> > --- a/drivers/gpu/drm/drm_ioctl.c
> > +++ b/drivers/gpu/drm/drm_ioctl.c
> > @@ -42,6 +42,20 @@
> >  #include <asm/mtrr.h>
> >  #endif
> >  
> > +int drm_set_unique(struct drm_device *dev, const char *fmt, ...)
> 
> Can you please add a bit of kerneldoc for this? drm_ioctl.c isn't yet
> pulled into the drm reference docbook, but better to have it there
> already.

On second thought, wouldn't this be better located in drm_stub.c? It
isn't really related to the IOCTL code except that one of the IOCTLs now
uses the information set by this function. Logically I think it belongs
with the likes of drm_dev_alloc() and drm_dev_register().

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC 4/5] drm: Introduce drm_set_unique()
  2014-04-23  7:17     ` Thierry Reding
@ 2014-04-23  8:40       ` Daniel Vetter
  2014-04-23 10:48         ` David Herrmann
  2014-04-23 13:37         ` Thierry Reding
  0 siblings, 2 replies; 12+ messages in thread
From: Daniel Vetter @ 2014-04-23  8:40 UTC (permalink / raw)
  To: Thierry Reding
  Cc: dri-devel, linux-tegra, Greg Kroah-Hartman, linux-kernel, Russell King

On Wed, Apr 23, 2014 at 09:17:16AM +0200, Thierry Reding wrote:
> On Tue, Apr 22, 2014 at 05:48:07PM +0200, Daniel Vetter wrote:
> > On Tue, Apr 22, 2014 at 05:09:32PM +0200, Thierry Reding wrote:
> > > From: Thierry Reding <treding@nvidia.com>
> > > 
> > > Add a helper function that allows drivers to statically set the unique
> > > name of the device. This will allow platform and USB drivers to get rid
> > > of their DRM bus implementations and directly use drm_dev_alloc() and
> > > drm_dev_register().
> > > 
> > > Signed-off-by: Thierry Reding <treding@nvidia.com>
> > > ---
> > >  drivers/gpu/drm/drm_ioctl.c | 37 +++++++++++++++++++++++++++++++------
> > >  drivers/gpu/drm/drm_stub.c  |  1 +
> > >  include/drm/drmP.h          |  3 +++
> > >  3 files changed, 35 insertions(+), 6 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
> > > index 2dd3a6d8382b..371db3bef60c 100644
> > > --- a/drivers/gpu/drm/drm_ioctl.c
> > > +++ b/drivers/gpu/drm/drm_ioctl.c
> > > @@ -42,6 +42,20 @@
> > >  #include <asm/mtrr.h>
> > >  #endif
> > >  
> > > +int drm_set_unique(struct drm_device *dev, const char *fmt, ...)
> > 
> > Can you please add a bit of kerneldoc for this? drm_ioctl.c isn't yet
> > pulled into the drm reference docbook, but better to have it there
> > already.
> 
> On second thought, wouldn't this be better located in drm_stub.c? It
> isn't really related to the IOCTL code except that one of the IOCTLs now
> uses the information set by this function. Logically I think it belongs
> with the likes of drm_dev_alloc() and drm_dev_register().

Yeah makes sense. Tbh the entire split-up of these core drm functions is
still a bit messy, so I don't mind if it's a bit inconsistent really. We
can do the suffling when someone bothers with the kerneldoc for all of
them and pulls it into the drm docbook.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC 4/5] drm: Introduce drm_set_unique()
  2014-04-23  8:40       ` Daniel Vetter
@ 2014-04-23 10:48         ` David Herrmann
  2014-04-23 13:37         ` Thierry Reding
  1 sibling, 0 replies; 12+ messages in thread
From: David Herrmann @ 2014-04-23 10:48 UTC (permalink / raw)
  To: Thierry Reding, dri-devel, linux-tegra, Greg Kroah-Hartman,
	linux-kernel, Russell King

Hi

On Wed, Apr 23, 2014 at 10:40 AM, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Wed, Apr 23, 2014 at 09:17:16AM +0200, Thierry Reding wrote:
>> On second thought, wouldn't this be better located in drm_stub.c? It
>> isn't really related to the IOCTL code except that one of the IOCTLs now
>> uses the information set by this function. Logically I think it belongs
>> with the likes of drm_dev_alloc() and drm_dev_register().
>
> Yeah makes sense. Tbh the entire split-up of these core drm functions is
> still a bit messy, so I don't mind if it's a bit inconsistent really. We
> can do the suffling when someone bothers with the kerneldoc for all of
> them and pulls it into the drm docbook.

During drm_dev_*() cleanup, I tried to keep the following structure:
  drm_drv.c: global drm-module setup
  drm_stub.c: drm_device allocation, registration and lifetime management
  drm_fops.c: reference-implementation of the drm file_operations

The only thing that's wrongly placed is ioctl handling (which somehow
ended up in drm_drv.c instead of drm_fops.c). drm_stub.c is where all
the generic and mandatory DRM device handling is placed so yeah, I'd
put the set_unique() there.

Thanks
David

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC 4/5] drm: Introduce drm_set_unique()
  2014-04-23  8:40       ` Daniel Vetter
  2014-04-23 10:48         ` David Herrmann
@ 2014-04-23 13:37         ` Thierry Reding
  1 sibling, 0 replies; 12+ messages in thread
From: Thierry Reding @ 2014-04-23 13:37 UTC (permalink / raw)
  To: dri-devel, linux-tegra, Greg Kroah-Hartman, linux-kernel, Russell King

[-- Attachment #1: Type: text/plain, Size: 2214 bytes --]

On Wed, Apr 23, 2014 at 10:40:57AM +0200, Daniel Vetter wrote:
> On Wed, Apr 23, 2014 at 09:17:16AM +0200, Thierry Reding wrote:
> > On Tue, Apr 22, 2014 at 05:48:07PM +0200, Daniel Vetter wrote:
> > > On Tue, Apr 22, 2014 at 05:09:32PM +0200, Thierry Reding wrote:
> > > > From: Thierry Reding <treding@nvidia.com>
> > > > 
> > > > Add a helper function that allows drivers to statically set the unique
> > > > name of the device. This will allow platform and USB drivers to get rid
> > > > of their DRM bus implementations and directly use drm_dev_alloc() and
> > > > drm_dev_register().
> > > > 
> > > > Signed-off-by: Thierry Reding <treding@nvidia.com>
> > > > ---
> > > >  drivers/gpu/drm/drm_ioctl.c | 37 +++++++++++++++++++++++++++++++------
> > > >  drivers/gpu/drm/drm_stub.c  |  1 +
> > > >  include/drm/drmP.h          |  3 +++
> > > >  3 files changed, 35 insertions(+), 6 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
> > > > index 2dd3a6d8382b..371db3bef60c 100644
> > > > --- a/drivers/gpu/drm/drm_ioctl.c
> > > > +++ b/drivers/gpu/drm/drm_ioctl.c
> > > > @@ -42,6 +42,20 @@
> > > >  #include <asm/mtrr.h>
> > > >  #endif
> > > >  
> > > > +int drm_set_unique(struct drm_device *dev, const char *fmt, ...)
> > > 
> > > Can you please add a bit of kerneldoc for this? drm_ioctl.c isn't yet
> > > pulled into the drm reference docbook, but better to have it there
> > > already.
> > 
> > On second thought, wouldn't this be better located in drm_stub.c? It
> > isn't really related to the IOCTL code except that one of the IOCTLs now
> > uses the information set by this function. Logically I think it belongs
> > with the likes of drm_dev_alloc() and drm_dev_register().
> 
> Yeah makes sense. Tbh the entire split-up of these core drm functions is
> still a bit messy, so I don't mind if it's a bit inconsistent really. We
> can do the suffling when someone bothers with the kerneldoc for all of
> them and pulls it into the drm docbook.

I ended up doing exactly that when I wrote the drm_set_unique() docbook
pieces and I've sent out patches based on top of v2 of this patch just
now.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC 0/5] drm/tegra: Convert to master/component framework
  2014-04-22 15:09 [RFC 0/5] drm/tegra: Convert to master/component framework Thierry Reding
                   ` (4 preceding siblings ...)
  2014-04-22 15:09 ` [RFC 5/5] drm/tegra: Convert to master/component framework Thierry Reding
@ 2014-04-30 22:01 ` Thierry Reding
  5 siblings, 0 replies; 12+ messages in thread
From: Thierry Reding @ 2014-04-30 22:01 UTC (permalink / raw)
  To: dri-devel; +Cc: Greg Kroah-Hartman, Russell King, linux-kernel, linux-tegra

[-- Attachment #1: Type: text/plain, Size: 3422 bytes --]

On Tue, Apr 22, 2014 at 05:09:28PM +0200, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> Hi,
> 
> This series converts the Tegra DRM driver to the master/component
> framework. The length of the series and the list of people in Cc is
> mostly due to the fact that Tegra has some special requirements as
> opposed to other drivers and therefore requires some changes outside
> of DRM.
> 
> Patches 1 and 2 make some changes to the master/component framework
> which are necessary to convert Tegra DRM to use it. Note that since I'm
> looking for early review I haven't converted any of the existing users
> since I'm not sure if these are acceptable changes.
> 
> Patch 3 adds a new interface framework that supplements the master/
> component framework and can be used in situations where there is no
> struct device * that a driver can bind to.
> 
> A new function is introduced in patch 4 which can be used to get rid of
> the DRM bus infrastructure in individual drivers. It should be able to
> replace the requirement of having a drm_bus for all USB and platform
> DRM drivers. For backwards-compatibility with legacy PCI drivers some-
> thing different will probably be needed.
> 
> Finally, patch 5 converts the Tegra DRM driver over to using the master/
> component framework using the above four patches.
> 
> Each patch has a somewhat more elaborate description of why it is needed
> or what problem it solves. The patchset applies on top of linux-next
> with Daniel's DRM cleanup series applied.
> 
> I welcome any questions or comments you might have.
> 
> Thierry
> 
> Thierry Reding (5):
>   drivers/base: Allow multiple masters per device
>   drivers/base: Allow driver-data to be attached to a master
>   drivers/base: Add interface framework
>   drm: Introduce drm_set_unique()
>   drm/tegra: Convert to master/component framework

Ping. Anyone?

Thierry

>  drivers/base/Makefile          |   2 +-
>  drivers/base/component.c       |  31 ++-
>  drivers/base/interface.c       | 186 ++++++++++++++
>  drivers/gpu/drm/drm_ioctl.c    |  37 ++-
>  drivers/gpu/drm/drm_stub.c     |   1 +
>  drivers/gpu/drm/tegra/Makefile |   1 -
>  drivers/gpu/drm/tegra/bus.c    |  64 -----
>  drivers/gpu/drm/tegra/dc.c     |  58 ++---
>  drivers/gpu/drm/tegra/drm.c    | 171 +++++++++----
>  drivers/gpu/drm/tegra/drm.h    |  27 +-
>  drivers/gpu/drm/tegra/dsi.c    | 144 +++++------
>  drivers/gpu/drm/tegra/gr2d.c   |  78 +++---
>  drivers/gpu/drm/tegra/gr3d.c   |  77 +++---
>  drivers/gpu/drm/tegra/hdmi.c   |  69 ++---
>  drivers/gpu/drm/tegra/sor.c    |  71 ++----
>  drivers/gpu/host1x/Makefile    |   1 -
>  drivers/gpu/host1x/bus.c       | 553 -----------------------------------------
>  drivers/gpu/host1x/bus.h       |  29 ---
>  drivers/gpu/host1x/dev.c       |  21 +-
>  drivers/gpu/host1x/dev.h       |   7 +-
>  include/drm/drmP.h             |   3 +
>  include/linux/component.h      |  20 +-
>  include/linux/host1x.h         |  64 +----
>  include/linux/interface.h      |  40 +++
>  24 files changed, 625 insertions(+), 1130 deletions(-)
>  create mode 100644 drivers/base/interface.c
>  delete mode 100644 drivers/gpu/drm/tegra/bus.c
>  delete mode 100644 drivers/gpu/host1x/bus.c
>  delete mode 100644 drivers/gpu/host1x/bus.h
>  create mode 100644 include/linux/interface.h
> 
> -- 
> 1.9.2
> 

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2014-04-30 22:03 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-22 15:09 [RFC 0/5] drm/tegra: Convert to master/component framework Thierry Reding
2014-04-22 15:09 ` [RFC 1/5] drivers/base: Allow multiple masters per device Thierry Reding
2014-04-22 15:09 ` [RFC 2/5] drivers/base: Allow driver-data to be attached to a master Thierry Reding
2014-04-22 15:09 ` [RFC 3/5] drivers/base: Add interface framework Thierry Reding
2014-04-22 15:09 ` [RFC 4/5] drm: Introduce drm_set_unique() Thierry Reding
2014-04-22 15:48   ` Daniel Vetter
2014-04-23  7:17     ` Thierry Reding
2014-04-23  8:40       ` Daniel Vetter
2014-04-23 10:48         ` David Herrmann
2014-04-23 13:37         ` Thierry Reding
2014-04-22 15:09 ` [RFC 5/5] drm/tegra: Convert to master/component framework Thierry Reding
2014-04-30 22:01 ` [RFC 0/5] " Thierry Reding

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).