All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/27] drm/tegra: Repatriation and DSI support
@ 2013-10-07  8:34 Thierry Reding
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

This series of patches moves the Tegra DRM driver back to drivers/gpu/drm
where it belongs. While this is not entirely trivial, decoupling it from the
host1x driver will make things easier in the long run.

Patches 1 to 14 are mostly cleanup and decoupling from host1x. After those
patches, the DRM specific parts are back in drivers/gpu/drm/tegra in which
they originated and all host1x support code that they use is exported by the
host1x driver and exposed in the include/linux/host1x.h header file.

The larger part of patches 15 to 20 have been contributed by Mikko Perttunen
and add support for HDMI on Tegra114.

Patches 21 to 23 are the panel support patches, addressing comments that I
received on an earlier version.

Patch 24 fixes an issue with the DPMS mode tracking. Connectors default to
off on Tegra, so the initial DPMS mode needs to reflect that.

Patches 25 and 27 add support for DSI and gr2d on Tegra114.

Thierry

Mikko Perttunen (4):
  drm/tegra: Add Tegra114 display controller support
  drm/tegra: Add Tegra114 HDMI support
  drm/tegra: hdmi: Detect DVI-only displays
  host1x: hdmi: Enable VDD earlier for hotplug/DDC

Thierry Reding (23):
  drm/tegra: Remove unused fields
  drm/tegra: Cleanup tegra_dc structure
  drm/tegra: Rename host1x_drm structure to tegra_drm
  drm/tegra: Rename host1x_drm_file to tegra_drm_file
  drm/tegra: Rename host1x_drm_context to tegra_drm_context
  gpu: host1x: Cleanup includes
  gpu: host1x: Do not discard .remove()
  drm/tegra: gr2d: Miscellaneous cleanups
  drm/tegra: gem: Miscellaneous cleanups
  gpu: host1x: Make host1x header file public
  drm/tegra: Introduce tegra_drm_client structure
  gpu: host1x: Expose syncpt and channel functionality
  drm/tegra: Move subdevice infrastructure to host1x
  drm/tegra: Move driver to DRM tree
  gpu: host1x: Add support for Tegra114
  drm/tegra: hdmi: Rename tegra{2,3} to tegra{20,30}
  drm: Add panel support
  drm/panel: Add simple panel support
  drm/tegra: Implement panel support
  drm/tegra: Start connectors with correct DPMS mode
  gpu: host1x: Add MIPI pad calibration support
  drm/tegra: Add DSI support
  drm/tegra: Add Tegra114 gr2d support

 .../devicetree/bindings/panel/auo,b101aw03.txt     |    7 +
 .../bindings/panel/chunghwa,claa101wb03.txt        |    7 +
 .../bindings/panel/panasonic,vvx10f004b00.txt      |    7 +
 .../devicetree/bindings/panel/simple-panel.txt     |   21 +
 MAINTAINERS                                        |    2 +
 drivers/gpu/drm/Kconfig                            |    4 +
 drivers/gpu/drm/Makefile                           |    3 +
 drivers/gpu/drm/drm_panel.c                        |   96 ++
 drivers/gpu/drm/panel/Kconfig                      |   17 +
 drivers/gpu/drm/panel/Makefile                     |    1 +
 drivers/gpu/drm/panel/panel-simple.c               |  339 +++++++
 drivers/gpu/{host1x/drm => drm/tegra}/Kconfig      |   11 +-
 drivers/gpu/drm/tegra/Makefile                     |   16 +
 drivers/gpu/drm/tegra/bus.c                        |  123 +++
 drivers/gpu/{host1x/drm => drm/tegra}/dc.c         |   34 +-
 drivers/gpu/{host1x/drm => drm/tegra}/dc.h         |    1 +
 drivers/gpu/{host1x/drm => drm/tegra}/drm.c        |  441 ++++-----
 drivers/gpu/{host1x/drm => drm/tegra}/drm.h        |   92 +-
 drivers/gpu/drm/tegra/dsi.c                        | 1026 ++++++++++++++++++++
 drivers/gpu/{host1x/drm => drm/tegra}/fb.c         |   16 +-
 drivers/gpu/{host1x/drm => drm/tegra}/gem.c        |   30 +-
 drivers/gpu/{host1x/drm => drm/tegra}/gem.h        |    4 +-
 drivers/gpu/{host1x/drm => drm/tegra}/gr2d.c       |  176 ++--
 drivers/gpu/{host1x/drm => drm/tegra}/hdmi.c       |  177 +++-
 drivers/gpu/{host1x/drm => drm/tegra}/hdmi.h       |  152 +++
 drivers/gpu/{host1x/drm => drm/tegra}/output.c     |   40 +-
 drivers/gpu/{host1x/drm => drm/tegra}/rgb.c        |    3 -
 drivers/gpu/host1x/Kconfig                         |    2 -
 drivers/gpu/host1x/Makefile                        |   14 +-
 drivers/gpu/host1x/bus.c                           |  309 ++++++
 drivers/gpu/host1x/{host1x_client.h => bus.h}      |   24 +-
 drivers/gpu/host1x/cdma.c                          |    2 +-
 drivers/gpu/host1x/channel.h                       |    6 -
 drivers/gpu/host1x/dev.c                           |   73 +-
 drivers/gpu/host1x/dev.h                           |    9 +-
 drivers/gpu/host1x/host1x.h                        |   30 -
 drivers/gpu/host1x/host1x_bo.h                     |   87 --
 drivers/gpu/host1x/hw/channel_hw.c                 |    4 +-
 drivers/gpu/host1x/hw/debug_hw.c                   |    8 -
 drivers/gpu/host1x/hw/host1x02.c                   |   42 +
 drivers/gpu/host1x/hw/host1x02.h                   |   26 +
 drivers/gpu/host1x/hw/hw_host1x02_channel.h        |  121 +++
 drivers/gpu/host1x/hw/hw_host1x02_sync.h           |  243 +++++
 drivers/gpu/host1x/hw/hw_host1x02_uclass.h         |  175 ++++
 drivers/gpu/host1x/job.c                           |    2 +-
 drivers/gpu/host1x/job.h                           |  108 ---
 drivers/gpu/host1x/mipi.c                          |  230 +++++
 drivers/gpu/host1x/syncpt.c                        |   19 +
 drivers/gpu/host1x/syncpt.h                        |   40 +-
 drivers/video/Kconfig                              |    4 +-
 include/drm/drmP.h                                 |    1 +
 include/drm/drm_panel.h                            |   78 ++
 include/linux/host1x.h                             |  278 ++++++
 53 files changed, 3922 insertions(+), 859 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/panel/auo,b101aw03.txt
 create mode 100644 Documentation/devicetree/bindings/panel/chunghwa,claa101wb03.txt
 create mode 100644 Documentation/devicetree/bindings/panel/panasonic,vvx10f004b00.txt
 create mode 100644 Documentation/devicetree/bindings/panel/simple-panel.txt
 create mode 100644 drivers/gpu/drm/drm_panel.c
 create mode 100644 drivers/gpu/drm/panel/Kconfig
 create mode 100644 drivers/gpu/drm/panel/Makefile
 create mode 100644 drivers/gpu/drm/panel/panel-simple.c
 rename drivers/gpu/{host1x/drm => drm/tegra}/Kconfig (97%)
 create mode 100644 drivers/gpu/drm/tegra/Makefile
 create mode 100644 drivers/gpu/drm/tegra/bus.c
 rename drivers/gpu/{host1x/drm => drm/tegra}/dc.c (97%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/dc.h (99%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/drm.c (56%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/drm.h (78%)
 create mode 100644 drivers/gpu/drm/tegra/dsi.c
 rename drivers/gpu/{host1x/drm => drm/tegra}/fb.c (96%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/gem.c (89%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/gem.h (98%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/gr2d.c (68%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/hdmi.c (86%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/hdmi.h (72%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/output.c (87%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/rgb.c (98%)
 create mode 100644 drivers/gpu/host1x/bus.c
 rename drivers/gpu/host1x/{host1x_client.h => bus.h} (60%)
 delete mode 100644 drivers/gpu/host1x/host1x.h
 delete mode 100644 drivers/gpu/host1x/host1x_bo.h
 create mode 100644 drivers/gpu/host1x/hw/host1x02.c
 create mode 100644 drivers/gpu/host1x/hw/host1x02.h
 create mode 100644 drivers/gpu/host1x/hw/hw_host1x02_channel.h
 create mode 100644 drivers/gpu/host1x/hw/hw_host1x02_sync.h
 create mode 100644 drivers/gpu/host1x/hw/hw_host1x02_uclass.h
 create mode 100644 drivers/gpu/host1x/mipi.c
 create mode 100644 include/drm/drm_panel.h
 create mode 100644 include/linux/host1x.h

-- 
1.8.4

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

* [PATCH v2 01/27] drm/tegra: Remove unused fields
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-10-07  8:34   ` Thierry Reding
  2013-10-07  8:34   ` [PATCH v2 02/27] drm/tegra: Cleanup tegra_dc structure Thierry Reding
                     ` (25 subsequent siblings)
  26 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

Some of the fields in struct host1x_drm haven't been used for a while,
so remove them.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/host1x/drm/drm.h | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/gpu/host1x/drm/drm.h b/drivers/gpu/host1x/drm/drm.h
index 02ce020..f7cd946 100644
--- a/drivers/gpu/host1x/drm/drm.h
+++ b/drivers/gpu/host1x/drm/drm.h
@@ -33,10 +33,6 @@ struct tegra_fbdev {
 struct host1x_drm {
 	struct drm_device *drm;
 	struct device *dev;
-	void __iomem *regs;
-	struct clk *clk;
-	int syncpt;
-	int irq;
 
 	struct mutex drm_clients_lock;
 	struct list_head drm_clients;
-- 
1.8.4

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

* [PATCH v2 02/27] drm/tegra: Cleanup tegra_dc structure
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2013-10-07  8:34   ` [PATCH v2 01/27] drm/tegra: Remove unused fields Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
  2013-10-07  8:34   ` [PATCH v2 03/27] drm/tegra: Rename host1x_drm structure to tegra_drm Thierry Reding
                     ` (24 subsequent siblings)
  26 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

Remove the unused host1x field from the structure and group the fields
more logically.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/host1x/drm/drm.h | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/gpu/host1x/drm/drm.h b/drivers/gpu/host1x/drm/drm.h
index f7cd946..b8d9f43 100644
--- a/drivers/gpu/host1x/drm/drm.h
+++ b/drivers/gpu/host1x/drm/drm.h
@@ -94,16 +94,13 @@ struct tegra_output;
 
 struct tegra_dc {
 	struct host1x_client client;
-	spinlock_t lock;
-
-	struct host1x_drm *host1x;
 	struct device *dev;
+	spinlock_t lock;
 
 	struct drm_crtc base;
 	int pipe;
 
 	struct clk *clk;
-
 	void __iomem *regs;
 	int irq;
 
-- 
1.8.4

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

* [PATCH v2 03/27] drm/tegra: Rename host1x_drm structure to tegra_drm
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2013-10-07  8:34   ` [PATCH v2 01/27] drm/tegra: Remove unused fields Thierry Reding
  2013-10-07  8:34   ` [PATCH v2 02/27] drm/tegra: Cleanup tegra_dc structure Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
  2013-10-07  8:34   ` [PATCH v2 04/27] drm/tegra: Rename host1x_drm_file to tegra_drm_file Thierry Reding
                     ` (23 subsequent siblings)
  26 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

The host1x and Tegra DRM drivers are currently tightly coupled. Renaming
the structure marks the boundary more clearly.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/host1x/dev.c           |   2 +-
 drivers/gpu/host1x/drm/dc.c        |   8 +-
 drivers/gpu/host1x/drm/drm.c       | 169 ++++++++++++++++++-------------------
 drivers/gpu/host1x/drm/drm.h       |  18 ++--
 drivers/gpu/host1x/drm/fb.c        |  14 +--
 drivers/gpu/host1x/drm/gr2d.c      |   8 +-
 drivers/gpu/host1x/drm/hdmi.c      |   8 +-
 drivers/gpu/host1x/host1x_client.h |   4 +-
 8 files changed, 115 insertions(+), 116 deletions(-)

diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index 4716302..0f7b44c 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -163,7 +163,7 @@ static int host1x_probe(struct platform_device *pdev)
 
 	host1x_debug_init(host);
 
-	host1x_drm_alloc(pdev);
+	tegra_drm_alloc(pdev);
 
 	return 0;
 
diff --git a/drivers/gpu/host1x/drm/dc.c b/drivers/gpu/host1x/drm/dc.c
index b1a05ad..c4765b3 100644
--- a/drivers/gpu/host1x/drm/dc.c
+++ b/drivers/gpu/host1x/drm/dc.c
@@ -1109,7 +1109,7 @@ static const struct host1x_client_ops dc_client_ops = {
 
 static int tegra_dc_probe(struct platform_device *pdev)
 {
-	struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent);
+	struct tegra_drm *tegra = host1x_get_drm_data(pdev->dev.parent);
 	struct resource *regs;
 	struct tegra_dc *dc;
 	int err;
@@ -1153,7 +1153,7 @@ static int tegra_dc_probe(struct platform_device *pdev)
 		return err;
 	}
 
-	err = host1x_register_client(host1x, &dc->client);
+	err = host1x_register_client(tegra, &dc->client);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
 			err);
@@ -1167,11 +1167,11 @@ static int tegra_dc_probe(struct platform_device *pdev)
 
 static int tegra_dc_remove(struct platform_device *pdev)
 {
-	struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent);
+	struct tegra_drm *tegra = host1x_get_drm_data(pdev->dev.parent);
 	struct tegra_dc *dc = platform_get_drvdata(pdev);
 	int err;
 
-	err = host1x_unregister_client(host1x, &dc->client);
+	err = host1x_unregister_client(tegra, &dc->client);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
 			err);
diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c
index 8c61cee..7230b40 100644
--- a/drivers/gpu/host1x/drm/drm.c
+++ b/drivers/gpu/host1x/drm/drm.c
@@ -30,56 +30,55 @@
 #define DRIVER_MINOR 0
 #define DRIVER_PATCHLEVEL 0
 
-struct host1x_drm_client {
+struct host1x_subdev {
 	struct host1x_client *client;
 	struct device_node *np;
 	struct list_head list;
 };
 
-static int host1x_add_drm_client(struct host1x_drm *host1x,
-				 struct device_node *np)
+static int host1x_subdev_add(struct tegra_drm *tegra, struct device_node *np)
 {
-	struct host1x_drm_client *client;
+	struct host1x_subdev *subdev;
 
-	client = kzalloc(sizeof(*client), GFP_KERNEL);
-	if (!client)
+	subdev = kzalloc(sizeof(*subdev), GFP_KERNEL);
+	if (!subdev)
 		return -ENOMEM;
 
-	INIT_LIST_HEAD(&client->list);
-	client->np = of_node_get(np);
+	INIT_LIST_HEAD(&subdev->list);
+	subdev->np = of_node_get(np);
 
-	list_add_tail(&client->list, &host1x->drm_clients);
+	list_add_tail(&subdev->list, &tegra->subdevs);
 
 	return 0;
 }
 
-static int host1x_activate_drm_client(struct host1x_drm *host1x,
-				      struct host1x_drm_client *drm,
-				      struct host1x_client *client)
+static int host1x_subdev_register(struct tegra_drm *tegra,
+				  struct host1x_subdev *subdev,
+				  struct host1x_client *client)
 {
-	mutex_lock(&host1x->drm_clients_lock);
-	list_del_init(&drm->list);
-	list_add_tail(&drm->list, &host1x->drm_active);
-	drm->client = client;
-	mutex_unlock(&host1x->drm_clients_lock);
+	mutex_lock(&tegra->subdevs_lock);
+	list_del_init(&subdev->list);
+	list_add_tail(&subdev->list, &tegra->active);
+	subdev->client = client;
+	mutex_unlock(&tegra->subdevs_lock);
 
 	return 0;
 }
 
-static int host1x_remove_drm_client(struct host1x_drm *host1x,
-				    struct host1x_drm_client *client)
+static int host1x_subdev_unregister(struct tegra_drm *tegra,
+				    struct host1x_subdev *subdev)
 {
-	mutex_lock(&host1x->drm_clients_lock);
-	list_del_init(&client->list);
-	mutex_unlock(&host1x->drm_clients_lock);
+	mutex_lock(&tegra->subdevs_lock);
+	list_del_init(&subdev->list);
+	mutex_unlock(&tegra->subdevs_lock);
 
-	of_node_put(client->np);
-	kfree(client);
+	of_node_put(subdev->np);
+	kfree(subdev);
 
 	return 0;
 }
 
-static int host1x_parse_dt(struct host1x_drm *host1x)
+static int tegra_parse_dt(struct tegra_drm *tegra)
 {
 	static const char * const compat[] = {
 		"nvidia,tegra20-dc",
@@ -95,10 +94,10 @@ static int host1x_parse_dt(struct host1x_drm *host1x)
 	for (i = 0; i < ARRAY_SIZE(compat); i++) {
 		struct device_node *np;
 
-		for_each_child_of_node(host1x->dev->of_node, np) {
+		for_each_child_of_node(tegra->dev->of_node, np) {
 			if (of_device_is_compatible(np, compat[i]) &&
 			    of_device_is_available(np)) {
-				err = host1x_add_drm_client(host1x, np);
+				err = host1x_subdev_add(tegra, np);
 				if (err < 0)
 					return err;
 			}
@@ -108,108 +107,108 @@ static int host1x_parse_dt(struct host1x_drm *host1x)
 	return 0;
 }
 
-int host1x_drm_alloc(struct platform_device *pdev)
+int tegra_drm_alloc(struct platform_device *pdev)
 {
-	struct host1x_drm *host1x;
+	struct tegra_drm *tegra;
 	int err;
 
-	host1x = devm_kzalloc(&pdev->dev, sizeof(*host1x), GFP_KERNEL);
-	if (!host1x)
+	tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
+	if (!tegra)
 		return -ENOMEM;
 
-	mutex_init(&host1x->drm_clients_lock);
-	INIT_LIST_HEAD(&host1x->drm_clients);
-	INIT_LIST_HEAD(&host1x->drm_active);
-	mutex_init(&host1x->clients_lock);
-	INIT_LIST_HEAD(&host1x->clients);
-	host1x->dev = &pdev->dev;
+	mutex_init(&tegra->subdevs_lock);
+	INIT_LIST_HEAD(&tegra->subdevs);
+	INIT_LIST_HEAD(&tegra->active);
+	mutex_init(&tegra->clients_lock);
+	INIT_LIST_HEAD(&tegra->clients);
+	tegra->dev = &pdev->dev;
 
-	err = host1x_parse_dt(host1x);
+	err = tegra_parse_dt(tegra);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to parse DT: %d\n", err);
 		return err;
 	}
 
-	host1x_set_drm_data(&pdev->dev, host1x);
+	host1x_set_drm_data(&pdev->dev, tegra);
 
 	return 0;
 }
 
-int host1x_drm_init(struct host1x_drm *host1x, struct drm_device *drm)
+int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm)
 {
 	struct host1x_client *client;
 
-	mutex_lock(&host1x->clients_lock);
+	mutex_lock(&tegra->clients_lock);
 
-	list_for_each_entry(client, &host1x->clients, list) {
+	list_for_each_entry(client, &tegra->clients, list) {
 		if (client->ops && client->ops->drm_init) {
 			int err = client->ops->drm_init(client, drm);
 			if (err < 0) {
-				dev_err(host1x->dev,
+				dev_err(tegra->dev,
 					"DRM setup failed for %s: %d\n",
 					dev_name(client->dev), err);
-				mutex_unlock(&host1x->clients_lock);
+				mutex_unlock(&tegra->clients_lock);
 				return err;
 			}
 		}
 	}
 
-	mutex_unlock(&host1x->clients_lock);
+	mutex_unlock(&tegra->clients_lock);
 
 	return 0;
 }
 
-int host1x_drm_exit(struct host1x_drm *host1x)
+int tegra_drm_exit(struct tegra_drm *tegra)
 {
-	struct platform_device *pdev = to_platform_device(host1x->dev);
+	struct platform_device *pdev = to_platform_device(tegra->dev);
 	struct host1x_client *client;
 
-	if (!host1x->drm)
+	if (!tegra->drm)
 		return 0;
 
-	mutex_lock(&host1x->clients_lock);
+	mutex_lock(&tegra->clients_lock);
 
-	list_for_each_entry_reverse(client, &host1x->clients, list) {
+	list_for_each_entry_reverse(client, &tegra->clients, list) {
 		if (client->ops && client->ops->drm_exit) {
 			int err = client->ops->drm_exit(client);
 			if (err < 0) {
-				dev_err(host1x->dev,
+				dev_err(tegra->dev,
 					"DRM cleanup failed for %s: %d\n",
 					dev_name(client->dev), err);
-				mutex_unlock(&host1x->clients_lock);
+				mutex_unlock(&tegra->clients_lock);
 				return err;
 			}
 		}
 	}
 
-	mutex_unlock(&host1x->clients_lock);
+	mutex_unlock(&tegra->clients_lock);
 
 	drm_platform_exit(&tegra_drm_driver, pdev);
-	host1x->drm = NULL;
+	tegra->drm = NULL;
 
 	return 0;
 }
 
-int host1x_register_client(struct host1x_drm *host1x,
+int host1x_register_client(struct tegra_drm *tegra,
 			   struct host1x_client *client)
 {
-	struct host1x_drm_client *drm, *tmp;
+	struct host1x_subdev *subdev, *tmp;
 	int err;
 
-	mutex_lock(&host1x->clients_lock);
-	list_add_tail(&client->list, &host1x->clients);
-	mutex_unlock(&host1x->clients_lock);
+	mutex_lock(&tegra->clients_lock);
+	list_add_tail(&client->list, &tegra->clients);
+	mutex_unlock(&tegra->clients_lock);
 
-	list_for_each_entry_safe(drm, tmp, &host1x->drm_clients, list)
-		if (drm->np == client->dev->of_node)
-			host1x_activate_drm_client(host1x, drm, client);
+	list_for_each_entry_safe(subdev, tmp, &tegra->subdevs, list)
+		if (subdev->np == client->dev->of_node)
+			host1x_subdev_register(tegra, subdev, client);
 
-	if (list_empty(&host1x->drm_clients)) {
-		struct platform_device *pdev = to_platform_device(host1x->dev);
+	if (list_empty(&tegra->subdevs)) {
+		struct platform_device *pdev = to_platform_device(tegra->dev);
 
 		err = drm_platform_init(&tegra_drm_driver, pdev);
 		if (err < 0) {
-			dev_err(host1x->dev, "drm_platform_init(): %d\n", err);
+			dev_err(tegra->dev, "drm_platform_init(): %d\n", err);
 			return err;
 		}
 	}
@@ -217,45 +216,45 @@ int host1x_register_client(struct host1x_drm *host1x,
 	return 0;
 }
 
-int host1x_unregister_client(struct host1x_drm *host1x,
+int host1x_unregister_client(struct tegra_drm *tegra,
 			     struct host1x_client *client)
 {
-	struct host1x_drm_client *drm, *tmp;
+	struct host1x_subdev *subdev, *tmp;
 	int err;
 
-	list_for_each_entry_safe(drm, tmp, &host1x->drm_active, list) {
-		if (drm->client == client) {
-			err = host1x_drm_exit(host1x);
+	list_for_each_entry_safe(subdev, tmp, &tegra->active, list) {
+		if (subdev->client == client) {
+			err = tegra_drm_exit(tegra);
 			if (err < 0) {
-				dev_err(host1x->dev, "host1x_drm_exit(): %d\n",
+				dev_err(tegra->dev, "tegra_drm_exit(): %d\n",
 					err);
 				return err;
 			}
 
-			host1x_remove_drm_client(host1x, drm);
+			host1x_subdev_unregister(tegra, subdev);
 			break;
 		}
 	}
 
-	mutex_lock(&host1x->clients_lock);
+	mutex_lock(&tegra->clients_lock);
 	list_del_init(&client->list);
-	mutex_unlock(&host1x->clients_lock);
+	mutex_unlock(&tegra->clients_lock);
 
 	return 0;
 }
 
 static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
 {
-	struct host1x_drm *host1x;
+	struct tegra_drm *tegra;
 	int err;
 
-	host1x = host1x_get_drm_data(drm->dev);
-	drm->dev_private = host1x;
-	host1x->drm = drm;
+	tegra = host1x_get_drm_data(drm->dev);
+	drm->dev_private = tegra;
+	tegra->drm = drm;
 
 	drm_mode_config_init(drm);
 
-	err = host1x_drm_init(host1x, drm);
+	err = tegra_drm_init(tegra, drm);
 	if (err < 0)
 		return err;
 
@@ -311,9 +310,9 @@ static void host1x_drm_context_free(struct host1x_drm_context *context)
 
 static void tegra_drm_lastclose(struct drm_device *drm)
 {
-	struct host1x_drm *host1x = drm->dev_private;
+	struct tegra_drm *tegra = drm->dev_private;
 
-	tegra_fbdev_restore_mode(host1x->fbdev);
+	tegra_fbdev_restore_mode(tegra->fbdev);
 }
 
 #ifdef CONFIG_DRM_TEGRA_STAGING
@@ -407,18 +406,18 @@ static int tegra_syncpt_wait(struct drm_device *drm, void *data,
 static int tegra_open_channel(struct drm_device *drm, void *data,
 			      struct drm_file *file)
 {
+	struct host1x_drm_file *fpriv = file->driver_priv;
+	struct tegra_drm *tegra = drm->dev_private;
 	struct drm_tegra_open_channel *args = data;
-	struct host1x_client *client;
 	struct host1x_drm_context *context;
-	struct host1x_drm_file *fpriv = file->driver_priv;
-	struct host1x_drm *host1x = drm->dev_private;
+	struct host1x_client *client;
 	int err = -ENODEV;
 
 	context = kzalloc(sizeof(*context), GFP_KERNEL);
 	if (!context)
 		return -ENOMEM;
 
-	list_for_each_entry(client, &host1x->clients, list)
+	list_for_each_entry(client, &tegra->clients, list)
 		if (client->class == args->client) {
 			err = client->ops->open_channel(client, context);
 			if (err)
diff --git a/drivers/gpu/host1x/drm/drm.h b/drivers/gpu/host1x/drm/drm.h
index b8d9f43..858bfc0 100644
--- a/drivers/gpu/host1x/drm/drm.h
+++ b/drivers/gpu/host1x/drm/drm.h
@@ -30,13 +30,13 @@ struct tegra_fbdev {
 	struct tegra_fb *fb;
 };
 
-struct host1x_drm {
+struct tegra_drm {
 	struct drm_device *drm;
 	struct device *dev;
 
-	struct mutex drm_clients_lock;
-	struct list_head drm_clients;
-	struct list_head drm_active;
+	struct mutex subdevs_lock;
+	struct list_head subdevs;
+	struct list_head active;
 
 	struct mutex clients_lock;
 	struct list_head clients;
@@ -68,7 +68,7 @@ struct host1x_drm_file {
 };
 
 struct host1x_client {
-	struct host1x_drm *host1x;
+	struct tegra_drm *tegra;
 	struct device *dev;
 
 	const struct host1x_client_ops *ops;
@@ -82,12 +82,12 @@ struct host1x_client {
 	struct list_head list;
 };
 
-extern int host1x_drm_init(struct host1x_drm *host1x, struct drm_device *drm);
-extern int host1x_drm_exit(struct host1x_drm *host1x);
+extern int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
+extern int tegra_drm_exit(struct tegra_drm *tegra);
 
-extern int host1x_register_client(struct host1x_drm *host1x,
+extern int host1x_register_client(struct tegra_drm *tegra,
 				  struct host1x_client *client);
-extern int host1x_unregister_client(struct host1x_drm *host1x,
+extern int host1x_unregister_client(struct tegra_drm *tegra,
 				    struct host1x_client *client);
 
 struct tegra_output;
diff --git a/drivers/gpu/host1x/drm/fb.c b/drivers/gpu/host1x/drm/fb.c
index 979a3e3..7dcd796 100644
--- a/drivers/gpu/host1x/drm/fb.c
+++ b/drivers/gpu/host1x/drm/fb.c
@@ -323,10 +323,10 @@ static void tegra_fbdev_free(struct tegra_fbdev *fbdev)
 
 static void tegra_fb_output_poll_changed(struct drm_device *drm)
 {
-	struct host1x_drm *host1x = drm->dev_private;
+	struct tegra_drm *tegra = drm->dev_private;
 
-	if (host1x->fbdev)
-		drm_fb_helper_hotplug_event(&host1x->fbdev->base);
+	if (tegra->fbdev)
+		drm_fb_helper_hotplug_event(&tegra->fbdev->base);
 }
 
 static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
@@ -336,7 +336,7 @@ static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
 
 int tegra_drm_fb_init(struct drm_device *drm)
 {
-	struct host1x_drm *host1x = drm->dev_private;
+	struct tegra_drm *tegra = drm->dev_private;
 	struct tegra_fbdev *fbdev;
 
 	drm->mode_config.min_width = 0;
@@ -352,16 +352,16 @@ int tegra_drm_fb_init(struct drm_device *drm)
 	if (IS_ERR(fbdev))
 		return PTR_ERR(fbdev);
 
-	host1x->fbdev = fbdev;
+	tegra->fbdev = fbdev;
 
 	return 0;
 }
 
 void tegra_drm_fb_exit(struct drm_device *drm)
 {
-	struct host1x_drm *host1x = drm->dev_private;
+	struct tegra_drm *tegra = drm->dev_private;
 
-	tegra_fbdev_free(host1x->fbdev);
+	tegra_fbdev_free(tegra->fbdev);
 }
 
 void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev)
diff --git a/drivers/gpu/host1x/drm/gr2d.c b/drivers/gpu/host1x/drm/gr2d.c
index 27ffcf1..5f838b1 100644
--- a/drivers/gpu/host1x/drm/gr2d.c
+++ b/drivers/gpu/host1x/drm/gr2d.c
@@ -256,7 +256,7 @@ static const struct of_device_id gr2d_match[] = {
 static int gr2d_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct host1x_drm *host1x = host1x_get_drm_data(dev->parent);
+	struct tegra_drm *tegra = host1x_get_drm_data(dev->parent);
 	int err;
 	struct gr2d *gr2d = NULL;
 	struct host1x_syncpt **syncpts;
@@ -297,7 +297,7 @@ static int gr2d_probe(struct platform_device *pdev)
 	gr2d->client.syncpts = syncpts;
 	gr2d->client.num_syncpts = 1;
 
-	err = host1x_register_client(host1x, &gr2d->client);
+	err = host1x_register_client(tegra, &gr2d->client);
 	if (err < 0) {
 		dev_err(dev, "failed to register host1x client: %d\n", err);
 		return err;
@@ -312,12 +312,12 @@ static int gr2d_probe(struct platform_device *pdev)
 
 static int __exit gr2d_remove(struct platform_device *pdev)
 {
-	struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent);
+	struct tegra_drm *tegra = host1x_get_drm_data(pdev->dev.parent);
 	struct gr2d *gr2d = platform_get_drvdata(pdev);
 	unsigned int i;
 	int err;
 
-	err = host1x_unregister_client(host1x, &gr2d->client);
+	err = host1x_unregister_client(tegra, &gr2d->client);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to unregister client: %d\n", err);
 		return err;
diff --git a/drivers/gpu/host1x/drm/hdmi.c b/drivers/gpu/host1x/drm/hdmi.c
index 644d95c..e7fb9d9 100644
--- a/drivers/gpu/host1x/drm/hdmi.c
+++ b/drivers/gpu/host1x/drm/hdmi.c
@@ -1181,7 +1181,7 @@ static const struct host1x_client_ops hdmi_client_ops = {
 
 static int tegra_hdmi_probe(struct platform_device *pdev)
 {
-	struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent);
+	struct tegra_drm *tegra = host1x_get_drm_data(pdev->dev.parent);
 	struct tegra_hdmi *hdmi;
 	struct resource *regs;
 	int err;
@@ -1256,7 +1256,7 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
 	INIT_LIST_HEAD(&hdmi->client.list);
 	hdmi->client.dev = &pdev->dev;
 
-	err = host1x_register_client(host1x, &hdmi->client);
+	err = host1x_register_client(tegra, &hdmi->client);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
 			err);
@@ -1270,11 +1270,11 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
 
 static int tegra_hdmi_remove(struct platform_device *pdev)
 {
-	struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent);
+	struct tegra_drm *tegra = host1x_get_drm_data(pdev->dev.parent);
 	struct tegra_hdmi *hdmi = platform_get_drvdata(pdev);
 	int err;
 
-	err = host1x_unregister_client(host1x, &hdmi->client);
+	err = host1x_unregister_client(tegra, &hdmi->client);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
 			err);
diff --git a/drivers/gpu/host1x/host1x_client.h b/drivers/gpu/host1x/host1x_client.h
index 9b85f10..6a0bd02 100644
--- a/drivers/gpu/host1x/host1x_client.h
+++ b/drivers/gpu/host1x/host1x_client.h
@@ -21,9 +21,9 @@ struct device;
 struct platform_device;
 
 #ifdef CONFIG_DRM_TEGRA
-int host1x_drm_alloc(struct platform_device *pdev);
+int tegra_drm_alloc(struct platform_device *pdev);
 #else
-static inline int host1x_drm_alloc(struct platform_device *pdev)
+static inline int tegra_drm_alloc(struct platform_device *pdev)
 {
 	return 0;
 }
-- 
1.8.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 04/27] drm/tegra: Rename host1x_drm_file to tegra_drm_file
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (2 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 03/27] drm/tegra: Rename host1x_drm structure to tegra_drm Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
  2013-10-07  8:34   ` [PATCH v2 05/27] drm/tegra: Rename host1x_drm_context to tegra_drm_context Thierry Reding
                     ` (22 subsequent siblings)
  26 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

This structure extends drm_file with Tegra DRM specific fields and has
nothing to do with host1x. Rename the structure to more clearly mark the
boundaries between host1x and Tegra DRM.

While at it, move the structure definition out of the header. It's never
used outside of the drm.c source file, so it can be defined within that.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/host1x/drm/drm.c | 26 +++++++++++++++-----------
 drivers/gpu/host1x/drm/drm.h |  4 ----
 2 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c
index 7230b40..67fd856 100644
--- a/drivers/gpu/host1x/drm/drm.c
+++ b/drivers/gpu/host1x/drm/drm.c
@@ -30,6 +30,10 @@
 #define DRIVER_MINOR 0
 #define DRIVER_PATCHLEVEL 0
 
+struct tegra_drm_file {
+	struct list_head contexts;
+};
+
 struct host1x_subdev {
 	struct host1x_client *client;
 	struct device_node *np;
@@ -290,7 +294,7 @@ static int tegra_drm_unload(struct drm_device *drm)
 
 static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp)
 {
-	struct host1x_drm_file *fpriv;
+	struct tegra_drm_file *fpriv;
 
 	fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
 	if (!fpriv)
@@ -316,8 +320,8 @@ static void tegra_drm_lastclose(struct drm_device *drm)
 }
 
 #ifdef CONFIG_DRM_TEGRA_STAGING
-static bool host1x_drm_file_owns_context(struct host1x_drm_file *file,
-					 struct host1x_drm_context *context)
+static bool tegra_drm_file_owns_context(struct tegra_drm_file *file,
+					struct host1x_drm_context *context)
 {
 	struct host1x_drm_context *ctx;
 
@@ -406,7 +410,7 @@ static int tegra_syncpt_wait(struct drm_device *drm, void *data,
 static int tegra_open_channel(struct drm_device *drm, void *data,
 			      struct drm_file *file)
 {
-	struct host1x_drm_file *fpriv = file->driver_priv;
+	struct tegra_drm_file *fpriv = file->driver_priv;
 	struct tegra_drm *tegra = drm->dev_private;
 	struct drm_tegra_open_channel *args = data;
 	struct host1x_drm_context *context;
@@ -437,11 +441,11 @@ static int tegra_close_channel(struct drm_device *drm, void *data,
 			       struct drm_file *file)
 {
 	struct drm_tegra_close_channel *args = data;
-	struct host1x_drm_file *fpriv = file->driver_priv;
+	struct tegra_drm_file *fpriv = file->driver_priv;
 	struct host1x_drm_context *context =
 		(struct host1x_drm_context *)(uintptr_t)args->context;
 
-	if (!host1x_drm_file_owns_context(fpriv, context))
+	if (!tegra_drm_file_owns_context(fpriv, context))
 		return -EINVAL;
 
 	list_del(&context->list);
@@ -453,13 +457,13 @@ static int tegra_close_channel(struct drm_device *drm, void *data,
 static int tegra_get_syncpt(struct drm_device *drm, void *data,
 			    struct drm_file *file)
 {
+	struct tegra_drm_file *fpriv = file->driver_priv;
 	struct drm_tegra_get_syncpt *args = data;
-	struct host1x_drm_file *fpriv = file->driver_priv;
 	struct host1x_drm_context *context =
 		(struct host1x_drm_context *)(uintptr_t)args->context;
 	struct host1x_syncpt *syncpt;
 
-	if (!host1x_drm_file_owns_context(fpriv, context))
+	if (!tegra_drm_file_owns_context(fpriv, context))
 		return -ENODEV;
 
 	if (args->index >= context->client->num_syncpts)
@@ -474,12 +478,12 @@ static int tegra_get_syncpt(struct drm_device *drm, void *data,
 static int tegra_submit(struct drm_device *drm, void *data,
 			struct drm_file *file)
 {
+	struct tegra_drm_file *fpriv = file->driver_priv;
 	struct drm_tegra_submit *args = data;
-	struct host1x_drm_file *fpriv = file->driver_priv;
 	struct host1x_drm_context *context =
 		(struct host1x_drm_context *)(uintptr_t)args->context;
 
-	if (!host1x_drm_file_owns_context(fpriv, context))
+	if (!tegra_drm_file_owns_context(fpriv, context))
 		return -ENODEV;
 
 	return context->client->ops->submit(context, args, drm, file);
@@ -558,7 +562,7 @@ static void tegra_drm_disable_vblank(struct drm_device *drm, int pipe)
 
 static void tegra_drm_preclose(struct drm_device *drm, struct drm_file *file)
 {
-	struct host1x_drm_file *fpriv = file->driver_priv;
+	struct tegra_drm_file *fpriv = file->driver_priv;
 	struct host1x_drm_context *context, *tmp;
 	struct drm_crtc *crtc;
 
diff --git a/drivers/gpu/host1x/drm/drm.h b/drivers/gpu/host1x/drm/drm.h
index 858bfc0..74869d3 100644
--- a/drivers/gpu/host1x/drm/drm.h
+++ b/drivers/gpu/host1x/drm/drm.h
@@ -63,10 +63,6 @@ struct host1x_client_ops {
 		      struct drm_file *file);
 };
 
-struct host1x_drm_file {
-	struct list_head contexts;
-};
-
 struct host1x_client {
 	struct tegra_drm *tegra;
 	struct device *dev;
-- 
1.8.4

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

* [PATCH v2 05/27] drm/tegra: Rename host1x_drm_context to tegra_drm_context
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (3 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 04/27] drm/tegra: Rename host1x_drm_file to tegra_drm_file Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
  2013-10-07  8:34   ` [PATCH v2 06/27] gpu: host1x: Cleanup includes Thierry Reding
                     ` (21 subsequent siblings)
  26 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

The structure represents a context associated with a particular process
that has opened the Tegra DRM device and requested a channel. This is a
very DRM-specific notion and has nothing to do with host1x. Rename the
structure to more clearly mark the boundaries between the two.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/host1x/drm/drm.c  | 34 +++++++++++++++++++++-------------
 drivers/gpu/host1x/drm/drm.h  |  8 ++++----
 drivers/gpu/host1x/drm/gr2d.c |  6 +++---
 3 files changed, 28 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c
index 67fd856..7f8f419 100644
--- a/drivers/gpu/host1x/drm/drm.c
+++ b/drivers/gpu/host1x/drm/drm.c
@@ -306,7 +306,7 @@ static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp)
 	return 0;
 }
 
-static void host1x_drm_context_free(struct host1x_drm_context *context)
+static void tegra_drm_context_free(struct tegra_drm_context *context)
 {
 	context->client->ops->close_channel(context);
 	kfree(context);
@@ -320,10 +320,15 @@ static void tegra_drm_lastclose(struct drm_device *drm)
 }
 
 #ifdef CONFIG_DRM_TEGRA_STAGING
+static struct tegra_drm_context *tegra_drm_get_context(__u64 context)
+{
+	return (struct tegra_drm_context *)(uintptr_t)context;
+}
+
 static bool tegra_drm_file_owns_context(struct tegra_drm_file *file,
-					struct host1x_drm_context *context)
+					struct tegra_drm_context *context)
 {
-	struct host1x_drm_context *ctx;
+	struct tegra_drm_context *ctx;
 
 	list_for_each_entry(ctx, &file->contexts, list)
 		if (ctx == context)
@@ -413,7 +418,7 @@ static int tegra_open_channel(struct drm_device *drm, void *data,
 	struct tegra_drm_file *fpriv = file->driver_priv;
 	struct tegra_drm *tegra = drm->dev_private;
 	struct drm_tegra_open_channel *args = data;
-	struct host1x_drm_context *context;
+	struct tegra_drm_context *context;
 	struct host1x_client *client;
 	int err = -ENODEV;
 
@@ -442,14 +447,15 @@ static int tegra_close_channel(struct drm_device *drm, void *data,
 {
 	struct drm_tegra_close_channel *args = data;
 	struct tegra_drm_file *fpriv = file->driver_priv;
-	struct host1x_drm_context *context =
-		(struct host1x_drm_context *)(uintptr_t)args->context;
+	struct tegra_drm_context *context;
+
+	context = tegra_drm_get_context(args->context);
 
 	if (!tegra_drm_file_owns_context(fpriv, context))
 		return -EINVAL;
 
 	list_del(&context->list);
-	host1x_drm_context_free(context);
+	tegra_drm_context_free(context);
 
 	return 0;
 }
@@ -459,10 +465,11 @@ static int tegra_get_syncpt(struct drm_device *drm, void *data,
 {
 	struct tegra_drm_file *fpriv = file->driver_priv;
 	struct drm_tegra_get_syncpt *args = data;
-	struct host1x_drm_context *context =
-		(struct host1x_drm_context *)(uintptr_t)args->context;
+	struct tegra_drm_context *context;
 	struct host1x_syncpt *syncpt;
 
+	context = tegra_drm_get_context(args->context);
+
 	if (!tegra_drm_file_owns_context(fpriv, context))
 		return -ENODEV;
 
@@ -480,8 +487,9 @@ static int tegra_submit(struct drm_device *drm, void *data,
 {
 	struct tegra_drm_file *fpriv = file->driver_priv;
 	struct drm_tegra_submit *args = data;
-	struct host1x_drm_context *context =
-		(struct host1x_drm_context *)(uintptr_t)args->context;
+	struct tegra_drm_context *context;
+
+	context = tegra_drm_get_context(args->context);
 
 	if (!tegra_drm_file_owns_context(fpriv, context))
 		return -ENODEV;
@@ -563,14 +571,14 @@ static void tegra_drm_disable_vblank(struct drm_device *drm, int pipe)
 static void tegra_drm_preclose(struct drm_device *drm, struct drm_file *file)
 {
 	struct tegra_drm_file *fpriv = file->driver_priv;
-	struct host1x_drm_context *context, *tmp;
+	struct tegra_drm_context *context, *tmp;
 	struct drm_crtc *crtc;
 
 	list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
 		tegra_dc_cancel_page_flip(crtc, file);
 
 	list_for_each_entry_safe(context, tmp, &fpriv->contexts, list)
-		host1x_drm_context_free(context);
+		tegra_drm_context_free(context);
 
 	kfree(fpriv);
 }
diff --git a/drivers/gpu/host1x/drm/drm.h b/drivers/gpu/host1x/drm/drm.h
index 74869d3..dd6b98b 100644
--- a/drivers/gpu/host1x/drm/drm.h
+++ b/drivers/gpu/host1x/drm/drm.h
@@ -46,7 +46,7 @@ struct tegra_drm {
 
 struct host1x_client;
 
-struct host1x_drm_context {
+struct tegra_drm_context {
 	struct host1x_client *client;
 	struct host1x_channel *channel;
 	struct list_head list;
@@ -56,9 +56,9 @@ struct host1x_client_ops {
 	int (*drm_init)(struct host1x_client *client, struct drm_device *drm);
 	int (*drm_exit)(struct host1x_client *client);
 	int (*open_channel)(struct host1x_client *client,
-			    struct host1x_drm_context *context);
-	void (*close_channel)(struct host1x_drm_context *context);
-	int (*submit)(struct host1x_drm_context *context,
+			    struct tegra_drm_context *context);
+	void (*close_channel)(struct tegra_drm_context *context);
+	int (*submit)(struct tegra_drm_context *context,
 		      struct drm_tegra_submit *args, struct drm_device *drm,
 		      struct drm_file *file);
 };
diff --git a/drivers/gpu/host1x/drm/gr2d.c b/drivers/gpu/host1x/drm/gr2d.c
index 5f838b1..06507c8 100644
--- a/drivers/gpu/host1x/drm/gr2d.c
+++ b/drivers/gpu/host1x/drm/gr2d.c
@@ -58,7 +58,7 @@ static int gr2d_client_exit(struct host1x_client *client)
 }
 
 static int gr2d_open_channel(struct host1x_client *client,
-			     struct host1x_drm_context *context)
+			     struct tegra_drm_context *context)
 {
 	struct gr2d *gr2d = to_gr2d(client);
 
@@ -70,7 +70,7 @@ static int gr2d_open_channel(struct host1x_client *client,
 	return 0;
 }
 
-static void gr2d_close_channel(struct host1x_drm_context *context)
+static void gr2d_close_channel(struct tegra_drm_context *context)
 {
 	host1x_channel_put(context->channel);
 }
@@ -94,7 +94,7 @@ static struct host1x_bo *host1x_bo_lookup(struct drm_device *drm,
 	return &bo->base;
 }
 
-static int gr2d_submit(struct host1x_drm_context *context,
+static int gr2d_submit(struct tegra_drm_context *context,
 		       struct drm_tegra_submit *args, struct drm_device *drm,
 		       struct drm_file *file)
 {
-- 
1.8.4

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

* [PATCH v2 06/27] gpu: host1x: Cleanup includes
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (4 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 05/27] drm/tegra: Rename host1x_drm_context to tegra_drm_context Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
       [not found]     ` <1381134884-5816-7-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2013-10-07  8:34   ` [PATCH v2 07/27] gpu: host1x: Do not discard .remove() Thierry Reding
                     ` (20 subsequent siblings)
  26 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

Most of the included files are either not required or already included
by some other header file.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/host1x/drm/dc.c      |  5 +----
 drivers/gpu/host1x/drm/drm.c     | 10 ----------
 drivers/gpu/host1x/drm/fb.c      |  2 --
 drivers/gpu/host1x/drm/gem.c     |  9 ---------
 drivers/gpu/host1x/drm/gr2d.c    |  7 -------
 drivers/gpu/host1x/drm/hdmi.c    |  8 +-------
 drivers/gpu/host1x/drm/output.c  |  2 --
 drivers/gpu/host1x/drm/rgb.c     |  3 ---
 drivers/gpu/host1x/hw/debug_hw.c |  7 -------
 9 files changed, 2 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/host1x/drm/dc.c b/drivers/gpu/host1x/drm/dc.c
index c4765b3..e11aec7 100644
--- a/drivers/gpu/host1x/drm/dc.c
+++ b/drivers/gpu/host1x/drm/dc.c
@@ -8,11 +8,8 @@
  */
 
 #include <linux/clk.h>
-#include <linux/debugfs.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
 #include <linux/clk/tegra.h>
+#include <linux/debugfs.h>
 
 #include "host1x_client.h"
 #include "dc.h"
diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c
index 7f8f419..90a1f3d 100644
--- a/drivers/gpu/host1x/drm/drm.c
+++ b/drivers/gpu/host1x/drm/drm.c
@@ -7,16 +7,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-
-#include <linux/dma-mapping.h>
-#include <asm/dma-iommu.h>
-
-#include <drm/drm.h>
-#include <drm/drmP.h>
-
 #include "host1x_client.h"
 #include "dev.h"
 #include "drm.h"
diff --git a/drivers/gpu/host1x/drm/fb.c b/drivers/gpu/host1x/drm/fb.c
index 7dcd796..1fd4e19 100644
--- a/drivers/gpu/host1x/drm/fb.c
+++ b/drivers/gpu/host1x/drm/fb.c
@@ -10,8 +10,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
-
 #include "drm.h"
 #include "gem.h"
 
diff --git a/drivers/gpu/host1x/drm/gem.c b/drivers/gpu/host1x/drm/gem.c
index 59623de..4a21378 100644
--- a/drivers/gpu/host1x/drm/gem.c
+++ b/drivers/gpu/host1x/drm/gem.c
@@ -18,15 +18,6 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/export.h>
-#include <linux/dma-mapping.h>
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-
 #include "gem.h"
 
 static inline struct tegra_bo *host1x_to_drm_bo(struct host1x_bo *bo)
diff --git a/drivers/gpu/host1x/drm/gr2d.c b/drivers/gpu/host1x/drm/gr2d.c
index 06507c8..8d9a10f 100644
--- a/drivers/gpu/host1x/drm/gr2d.c
+++ b/drivers/gpu/host1x/drm/gr2d.c
@@ -1,8 +1,4 @@
 /*
- * drivers/video/tegra/host/gr2d/gr2d.c
- *
- * Tegra Graphics 2D
- *
  * Copyright (c) 2012-2013, NVIDIA Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -18,9 +14,6 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <linux/export.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
 #include <linux/clk.h>
 
 #include "channel.h"
diff --git a/drivers/gpu/host1x/drm/hdmi.c b/drivers/gpu/host1x/drm/hdmi.c
index e7fb9d9..5d8c41c 100644
--- a/drivers/gpu/host1x/drm/hdmi.c
+++ b/drivers/gpu/host1x/drm/hdmi.c
@@ -8,16 +8,10 @@
  */
 
 #include <linux/clk.h>
+#include <linux/clk/tegra.h>
 #include <linux/debugfs.h>
-#include <linux/gpio.h>
 #include <linux/hdmi.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
-#include <linux/clk/tegra.h>
-
-#include <drm/drm_edid.h>
 
 #include "hdmi.h"
 #include "drm.h"
diff --git a/drivers/gpu/host1x/drm/output.c b/drivers/gpu/host1x/drm/output.c
index 137ae81..8f40fa6 100644
--- a/drivers/gpu/host1x/drm/output.c
+++ b/drivers/gpu/host1x/drm/output.c
@@ -7,9 +7,7 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
 #include <linux/of_gpio.h>
-#include <linux/i2c.h>
 
 #include "drm.h"
 
diff --git a/drivers/gpu/host1x/drm/rgb.c b/drivers/gpu/host1x/drm/rgb.c
index 5aa66ef..e4d2841 100644
--- a/drivers/gpu/host1x/drm/rgb.c
+++ b/drivers/gpu/host1x/drm/rgb.c
@@ -8,9 +8,6 @@
  */
 
 #include <linux/clk.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
 
 #include "drm.h"
 #include "dc.h"
diff --git a/drivers/gpu/host1x/hw/debug_hw.c b/drivers/gpu/host1x/hw/debug_hw.c
index 334c038..dfad663 100644
--- a/drivers/gpu/host1x/hw/debug_hw.c
+++ b/drivers/gpu/host1x/hw/debug_hw.c
@@ -15,13 +15,6 @@
  *
  */
 
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/mm.h>
-#include <linux/scatterlist.h>
-
-#include <linux/io.h>
-
 #include "dev.h"
 #include "debug.h"
 #include "cdma.h"
-- 
1.8.4

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

* [PATCH v2 07/27] gpu: host1x: Do not discard .remove()
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (5 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 06/27] gpu: host1x: Cleanup includes Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
  2013-10-07  8:34   ` [PATCH v2 08/27] drm/tegra: gr2d: Miscellaneous cleanups Thierry Reding
                     ` (19 subsequent siblings)
  26 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

The device can be unbound from the driver via sysfs, so regardless of
whether the driver is builtin or a module, its .remove() function needs
to stick around.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/host1x/dev.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index 0f7b44c..105aa4e 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -172,7 +172,7 @@ fail_deinit_syncpt:
 	return err;
 }
 
-static int __exit host1x_remove(struct platform_device *pdev)
+static int host1x_remove(struct platform_device *pdev)
 {
 	struct host1x *host = platform_get_drvdata(pdev);
 
@@ -184,13 +184,12 @@ static int __exit host1x_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver tegra_host1x_driver = {
-	.probe = host1x_probe,
-	.remove = __exit_p(host1x_remove),
 	.driver = {
-		.owner = THIS_MODULE,
 		.name = "tegra-host1x",
 		.of_match_table = host1x_of_match,
 	},
+	.probe = host1x_probe,
+	.remove = host1x_remove,
 };
 
 static int __init tegra_host1x_init(void)
-- 
1.8.4

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

* [PATCH v2 08/27] drm/tegra: gr2d: Miscellaneous cleanups
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (6 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 07/27] gpu: host1x: Do not discard .remove() Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
       [not found]     ` <1381134884-5816-9-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2013-10-07  8:34   ` [PATCH v2 09/27] drm/tegra: gem: " Thierry Reding
                     ` (18 subsequent siblings)
  26 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

Rework the address table code for the host1x firewall. The previous
implementation allocated a bitfield but didn't check for a valid pointer
so it could potentially crash. Furthermore setting up a bitfield makes
the code more complex than it needs to be.

Don't annotate the driver's .remove() function __exit. Even if built in
the driver can be unloaded via sysfs, so .remove() needs to stick around
after initialization. Also remove the explicit initialization of the
driver's .owner field to THIS_MODULE because that's now handled by the
driver core.

Furthermore make an error message more consistent with other subdrivers,
index the syncpts array for better readability, remove a gratuituous
newline and reorder some variable declarations to make the code easier
to read.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/host1x/drm/gr2d.c | 95 +++++++++++++++++++------------------------
 1 file changed, 41 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/host1x/drm/gr2d.c b/drivers/gpu/host1x/drm/gr2d.c
index 8d9a10f..07f0425 100644
--- a/drivers/gpu/host1x/drm/gr2d.c
+++ b/drivers/gpu/host1x/drm/gr2d.c
@@ -27,9 +27,8 @@
 
 struct gr2d {
 	struct host1x_client client;
-	struct clk *clk;
 	struct host1x_channel *channel;
-	unsigned long *addr_regs;
+	struct clk *clk;
 };
 
 static inline struct gr2d *to_gr2d(struct host1x_client *client)
@@ -37,8 +36,6 @@ static inline struct gr2d *to_gr2d(struct host1x_client *client)
 	return container_of(client, struct gr2d, client);
 }
 
-static int gr2d_is_addr_reg(struct device *dev, u32 class, u32 reg);
-
 static int gr2d_client_init(struct host1x_client *client,
 			    struct drm_device *drm)
 {
@@ -56,7 +53,6 @@ static int gr2d_open_channel(struct host1x_client *client,
 	struct gr2d *gr2d = to_gr2d(client);
 
 	context->channel = host1x_channel_get(gr2d->channel);
-
 	if (!context->channel)
 		return -ENOMEM;
 
@@ -87,11 +83,38 @@ static struct host1x_bo *host1x_bo_lookup(struct drm_device *drm,
 	return &bo->base;
 }
 
+static const u32 gr2d_addr_regs[] = {
+	0x1a, 0x1b, 0x26, 0x2b, 0x2c, 0x2d, 0x31, 0x32,
+	0x48, 0x49, 0x4a, 0x4b, 0x4c
+};
+
+static int gr2d_is_addr_reg(struct device *dev, u32 class, u32 offset)
+{
+	unsigned int i;
+
+	switch (class) {
+	case HOST1X_CLASS_HOST1X:
+		if (offset == 0x2b)
+			return 1;
+
+		break;
+
+	case HOST1X_CLASS_GR2D:
+	case HOST1X_CLASS_GR2D_SB:
+		for (i = 0; i < ARRAY_SIZE(gr2d_addr_regs); i++)
+			if (offset == gr2d_addr_regs[i])
+				return 1;
+
+		break;
+	}
+
+	return 0;
+}
+
 static int gr2d_submit(struct tegra_drm_context *context,
 		       struct drm_tegra_submit *args, struct drm_device *drm,
 		       struct drm_file *file)
 {
-	struct host1x_job *job;
 	unsigned int num_cmdbufs = args->num_cmdbufs;
 	unsigned int num_relocs = args->num_relocs;
 	unsigned int num_waitchks = args->num_waitchks;
@@ -102,6 +125,7 @@ static int gr2d_submit(struct tegra_drm_context *context,
 	struct drm_tegra_waitchk __user *waitchks =
 		(void * __user)(uintptr_t)args->waitchks;
 	struct drm_tegra_syncpt syncpt;
+	struct host1x_job *job;
 	int err;
 
 	/* We don't yet support other than one syncpt_incr struct per submit */
@@ -205,41 +229,6 @@ static struct host1x_client_ops gr2d_client_ops = {
 	.submit = gr2d_submit,
 };
 
-static void gr2d_init_addr_reg_map(struct device *dev, struct gr2d *gr2d)
-{
-	const u32 gr2d_addr_regs[] = {0x1a, 0x1b, 0x26, 0x2b, 0x2c, 0x2d, 0x31,
-				      0x32, 0x48, 0x49, 0x4a, 0x4b, 0x4c};
-	unsigned long *bitmap;
-	int i;
-
-	bitmap = devm_kzalloc(dev, DIV_ROUND_UP(256, BITS_PER_BYTE),
-			      GFP_KERNEL);
-
-	for (i = 0; i < ARRAY_SIZE(gr2d_addr_regs); ++i) {
-		u32 reg = gr2d_addr_regs[i];
-		bitmap[BIT_WORD(reg)] |= BIT_MASK(reg);
-	}
-
-	gr2d->addr_regs = bitmap;
-}
-
-static int gr2d_is_addr_reg(struct device *dev, u32 class, u32 reg)
-{
-	struct gr2d *gr2d = dev_get_drvdata(dev);
-
-	switch (class) {
-	case HOST1X_CLASS_HOST1X:
-		return reg == 0x2b;
-	case HOST1X_CLASS_GR2D:
-	case HOST1X_CLASS_GR2D_SB:
-		reg &= 0xff;
-		if (gr2d->addr_regs[BIT_WORD(reg)] & BIT_MASK(reg))
-			return 1;
-	default:
-		return 0;
-	}
-}
-
 static const struct of_device_id gr2d_match[] = {
 	{ .compatible = "nvidia,tegra30-gr2d" },
 	{ .compatible = "nvidia,tegra20-gr2d" },
@@ -248,11 +237,11 @@ static const struct of_device_id gr2d_match[] = {
 
 static int gr2d_probe(struct platform_device *pdev)
 {
+	struct tegra_drm *tegra = host1x_get_drm_data(pdev->dev.parent);
 	struct device *dev = &pdev->dev;
-	struct tegra_drm *tegra = host1x_get_drm_data(dev->parent);
-	int err;
-	struct gr2d *gr2d = NULL;
 	struct host1x_syncpt **syncpts;
+	struct gr2d *gr2d;
+	int err;
 
 	gr2d = devm_kzalloc(dev, sizeof(*gr2d), GFP_KERNEL);
 	if (!gr2d)
@@ -278,8 +267,8 @@ static int gr2d_probe(struct platform_device *pdev)
 	if (!gr2d->channel)
 		return -ENOMEM;
 
-	*syncpts = host1x_syncpt_request(dev, false);
-	if (!(*syncpts)) {
+	syncpts[0] = host1x_syncpt_request(dev, false);
+	if (!syncpts[0]) {
 		host1x_channel_free(gr2d->channel);
 		return -ENOMEM;
 	}
@@ -296,14 +285,12 @@ static int gr2d_probe(struct platform_device *pdev)
 		return err;
 	}
 
-	gr2d_init_addr_reg_map(dev, gr2d);
-
 	platform_set_drvdata(pdev, gr2d);
 
 	return 0;
 }
 
-static int __exit gr2d_remove(struct platform_device *pdev)
+static int gr2d_remove(struct platform_device *pdev)
 {
 	struct tegra_drm *tegra = host1x_get_drm_data(pdev->dev.parent);
 	struct gr2d *gr2d = platform_get_drvdata(pdev);
@@ -312,7 +299,8 @@ static int __exit gr2d_remove(struct platform_device *pdev)
 
 	err = host1x_unregister_client(tegra, &gr2d->client);
 	if (err < 0) {
-		dev_err(&pdev->dev, "failed to unregister client: %d\n", err);
+		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
+			err);
 		return err;
 	}
 
@@ -326,11 +314,10 @@ static int __exit gr2d_remove(struct platform_device *pdev)
 }
 
 struct platform_driver tegra_gr2d_driver = {
-	.probe = gr2d_probe,
-	.remove = __exit_p(gr2d_remove),
 	.driver = {
-		.owner = THIS_MODULE,
 		.name = "gr2d",
 		.of_match_table = gr2d_match,
-	}
+	},
+	.probe = gr2d_probe,
+	.remove = gr2d_remove,
 };
-- 
1.8.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 09/27] drm/tegra: gem: Miscellaneous cleanups
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (7 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 08/27] drm/tegra: gr2d: Miscellaneous cleanups Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
  2013-10-07  8:34   ` [PATCH v2 10/27] gpu: host1x: Make host1x header file public Thierry Reding
                     ` (17 subsequent siblings)
  26 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

Rename the host1x_to_drm_bo() macro to host1x_to_tegra_bo() for
consistency and fixup various stylistic issues.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/host1x/drm/gem.c | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/host1x/drm/gem.c b/drivers/gpu/host1x/drm/gem.c
index 4a21378..267c0c2 100644
--- a/drivers/gpu/host1x/drm/gem.c
+++ b/drivers/gpu/host1x/drm/gem.c
@@ -20,14 +20,14 @@
 
 #include "gem.h"
 
-static inline struct tegra_bo *host1x_to_drm_bo(struct host1x_bo *bo)
+static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo)
 {
 	return container_of(bo, struct tegra_bo, base);
 }
 
 static void tegra_bo_put(struct host1x_bo *bo)
 {
-	struct tegra_bo *obj = host1x_to_drm_bo(bo);
+	struct tegra_bo *obj = host1x_to_tegra_bo(bo);
 	struct drm_device *drm = obj->gem.dev;
 
 	mutex_lock(&drm->struct_mutex);
@@ -37,7 +37,7 @@ static void tegra_bo_put(struct host1x_bo *bo)
 
 static dma_addr_t tegra_bo_pin(struct host1x_bo *bo, struct sg_table **sgt)
 {
-	struct tegra_bo *obj = host1x_to_drm_bo(bo);
+	struct tegra_bo *obj = host1x_to_tegra_bo(bo);
 
 	return obj->paddr;
 }
@@ -48,7 +48,7 @@ static void tegra_bo_unpin(struct host1x_bo *bo, struct sg_table *sgt)
 
 static void *tegra_bo_mmap(struct host1x_bo *bo)
 {
-	struct tegra_bo *obj = host1x_to_drm_bo(bo);
+	struct tegra_bo *obj = host1x_to_tegra_bo(bo);
 
 	return obj->vaddr;
 }
@@ -59,7 +59,7 @@ static void tegra_bo_munmap(struct host1x_bo *bo, void *addr)
 
 static void *tegra_bo_kmap(struct host1x_bo *bo, unsigned int page)
 {
-	struct tegra_bo *obj = host1x_to_drm_bo(bo);
+	struct tegra_bo *obj = host1x_to_tegra_bo(bo);
 
 	return obj->vaddr + page * PAGE_SIZE;
 }
@@ -71,7 +71,7 @@ static void tegra_bo_kunmap(struct host1x_bo *bo, unsigned int page,
 
 static struct host1x_bo *tegra_bo_get(struct host1x_bo *bo)
 {
-	struct tegra_bo *obj = host1x_to_drm_bo(bo);
+	struct tegra_bo *obj = host1x_to_tegra_bo(bo);
 	struct drm_device *drm = obj->gem.dev;
 
 	mutex_lock(&drm->struct_mutex);
@@ -140,9 +140,9 @@ err_dma:
 }
 
 struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
-					    struct drm_device *drm,
-					    unsigned int size,
-					    unsigned int *handle)
+					     struct drm_device *drm,
+					     unsigned int size,
+					     unsigned int *handle)
 {
 	struct tegra_bo *bo;
 	int ret;
@@ -169,7 +169,6 @@ void tegra_bo_free_object(struct drm_gem_object *gem)
 	struct tegra_bo *bo = to_tegra_bo(gem);
 
 	drm_gem_free_mmap_offset(gem);
-
 	drm_gem_object_release(gem);
 	tegra_bo_destroy(gem->dev, bo);
 
@@ -189,7 +188,7 @@ int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm,
 		args->size = args->pitch * args->height;
 
 	bo = tegra_bo_create_with_handle(file, drm, args->size,
-					    &args->handle);
+					 &args->handle);
 	if (IS_ERR(bo))
 		return PTR_ERR(bo);
 
-- 
1.8.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 10/27] gpu: host1x: Make host1x header file public
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (8 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 09/27] drm/tegra: gem: " Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
  2013-10-07  8:34   ` [PATCH v2 11/27] drm/tegra: Introduce tegra_drm_client structure Thierry Reding
                     ` (16 subsequent siblings)
  26 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

In preparation to support host1x clients other than DRM, move this
header into a public location.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 MAINTAINERS                                    | 1 +
 drivers/gpu/host1x/drm/drm.h                   | 6 +++---
 drivers/gpu/host1x/drm/gr2d.c                  | 1 -
 drivers/gpu/host1x/hw/channel_hw.c             | 3 ++-
 {drivers/gpu/host1x => include/linux}/host1x.h | 8 +++-----
 5 files changed, 9 insertions(+), 10 deletions(-)
 rename {drivers/gpu/host1x => include/linux}/host1x.h (88%)

diff --git a/MAINTAINERS b/MAINTAINERS
index 0df0af2..a1a4c7c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2812,6 +2812,7 @@ L:	linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
 T:	git git://anongit.freedesktop.org/tegra/linux.git
 S:	Supported
 F:	drivers/gpu/host1x/
+F:	include/linux/host1x.h
 F:	include/uapi/drm/tegra_drm.h
 F:	Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
 
diff --git a/drivers/gpu/host1x/drm/drm.h b/drivers/gpu/host1x/drm/drm.h
index dd6b98b..78754f6 100644
--- a/drivers/gpu/host1x/drm/drm.h
+++ b/drivers/gpu/host1x/drm/drm.h
@@ -10,14 +10,14 @@
 #ifndef HOST1X_DRM_H
 #define HOST1X_DRM_H 1
 
+#include <uapi/drm/tegra_drm.h>
+#include <linux/host1x.h>
+
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fixed.h>
-#include <uapi/drm/tegra_drm.h>
-
-#include "host1x.h"
 
 struct tegra_fb {
 	struct drm_framebuffer base;
diff --git a/drivers/gpu/host1x/drm/gr2d.c b/drivers/gpu/host1x/drm/gr2d.c
index 07f0425..fc4476d 100644
--- a/drivers/gpu/host1x/drm/gr2d.c
+++ b/drivers/gpu/host1x/drm/gr2d.c
@@ -20,7 +20,6 @@
 #include "drm.h"
 #include "gem.h"
 #include "job.h"
-#include "host1x.h"
 #include "host1x_bo.h"
 #include "host1x_client.h"
 #include "syncpt.h"
diff --git a/drivers/gpu/host1x/hw/channel_hw.c b/drivers/gpu/host1x/hw/channel_hw.c
index ee19962..c950bc6 100644
--- a/drivers/gpu/host1x/hw/channel_hw.c
+++ b/drivers/gpu/host1x/hw/channel_hw.c
@@ -16,10 +16,11 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/host1x.h>
 #include <linux/slab.h>
+
 #include <trace/events/host1x.h>
 
-#include "host1x.h"
 #include "host1x_bo.h"
 #include "channel.h"
 #include "dev.h"
diff --git a/drivers/gpu/host1x/host1x.h b/include/linux/host1x.h
similarity index 88%
rename from drivers/gpu/host1x/host1x.h
rename to include/linux/host1x.h
index a2bc1e6..fe09939 100644
--- a/drivers/gpu/host1x/host1x.h
+++ b/include/linux/host1x.h
@@ -1,6 +1,4 @@
 /*
- * Tegra host1x driver
- *
  * Copyright (c) 2009-2013, NVIDIA Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -22,9 +20,9 @@
 #define __LINUX_HOST1X_H
 
 enum host1x_class {
-	HOST1X_CLASS_HOST1X	= 0x1,
-	HOST1X_CLASS_GR2D	= 0x51,
-	HOST1X_CLASS_GR2D_SB    = 0x52
+	HOST1X_CLASS_HOST1X = 0x1,
+	HOST1X_CLASS_GR2D = 0x51,
+	HOST1X_CLASS_GR2D_SB = 0x52,
 };
 
 #endif
-- 
1.8.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 11/27] drm/tegra: Introduce tegra_drm_client structure
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (9 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 10/27] gpu: host1x: Make host1x header file public Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
  2013-10-07  8:34   ` [PATCH v2 12/27] gpu: host1x: Expose syncpt and channel functionality Thierry Reding
                     ` (15 subsequent siblings)
  26 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

This structure derives from host1x_client. DRM-specific fields are moved
from host1x_client to this structure, so that host1x_client can remain
agnostic of DRM.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/host1x/drm/dc.c   | 35 ++++++++++++++++++-----------------
 drivers/gpu/host1x/drm/drm.c  | 30 +++++++++++++++++++-----------
 drivers/gpu/host1x/drm/drm.h  | 37 +++++++++++++++++--------------------
 drivers/gpu/host1x/drm/gr2d.c | 42 +++++++++++++++++++++++-------------------
 drivers/gpu/host1x/drm/hdmi.c | 33 +++++++++++++++++----------------
 include/linux/host1x.h        | 20 ++++++++++++++++++++
 6 files changed, 114 insertions(+), 83 deletions(-)

diff --git a/drivers/gpu/host1x/drm/dc.c b/drivers/gpu/host1x/drm/dc.c
index e11aec7..5106df0 100644
--- a/drivers/gpu/host1x/drm/dc.c
+++ b/drivers/gpu/host1x/drm/dc.c
@@ -1038,30 +1038,30 @@ static int tegra_dc_debugfs_exit(struct tegra_dc *dc)
 	return 0;
 }
 
-static int tegra_dc_drm_init(struct host1x_client *client,
-			     struct drm_device *drm)
+static int tegra_dc_init(struct host1x_client *client)
 {
-	struct tegra_dc *dc = host1x_client_to_dc(client);
+	struct tegra_drm_client *drm = to_tegra_drm_client(client);
+	struct tegra_dc *dc = tegra_drm_client_to_dc(drm);
 	int err;
 
-	dc->pipe = drm->mode_config.num_crtc;
+	dc->pipe = drm->drm->mode_config.num_crtc;
 
-	drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs);
+	drm_crtc_init(drm->drm, &dc->base, &tegra_crtc_funcs);
 	drm_mode_crtc_set_gamma_size(&dc->base, 256);
 	drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
 
-	err = tegra_dc_rgb_init(drm, dc);
+	err = tegra_dc_rgb_init(drm->drm, dc);
 	if (err < 0 && err != -ENODEV) {
 		dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
 		return err;
 	}
 
-	err = tegra_dc_add_planes(drm, dc);
+	err = tegra_dc_add_planes(drm->drm, dc);
 	if (err < 0)
 		return err;
 
 	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
-		err = tegra_dc_debugfs_init(dc, drm->primary);
+		err = tegra_dc_debugfs_init(dc, drm->drm->primary);
 		if (err < 0)
 			dev_err(dc->dev, "debugfs setup failed: %d\n", err);
 	}
@@ -1077,9 +1077,10 @@ static int tegra_dc_drm_init(struct host1x_client *client,
 	return 0;
 }
 
-static int tegra_dc_drm_exit(struct host1x_client *client)
+static int tegra_dc_exit(struct host1x_client *client)
 {
-	struct tegra_dc *dc = host1x_client_to_dc(client);
+	struct tegra_drm_client *drm = to_tegra_drm_client(client);
+	struct tegra_dc *dc = tegra_drm_client_to_dc(drm);
 	int err;
 
 	devm_free_irq(dc->dev, dc->irq, dc);
@@ -1100,8 +1101,8 @@ static int tegra_dc_drm_exit(struct host1x_client *client)
 }
 
 static const struct host1x_client_ops dc_client_ops = {
-	.drm_init = tegra_dc_drm_init,
-	.drm_exit = tegra_dc_drm_exit,
+	.init = tegra_dc_init,
+	.exit = tegra_dc_exit,
 };
 
 static int tegra_dc_probe(struct platform_device *pdev)
@@ -1140,9 +1141,9 @@ 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;
+	INIT_LIST_HEAD(&dc->client.base.list);
+	dc->client.base.ops = &dc_client_ops;
+	dc->client.base.dev = &pdev->dev;
 
 	err = tegra_dc_rgb_probe(dc);
 	if (err < 0 && err != -ENODEV) {
@@ -1150,7 +1151,7 @@ static int tegra_dc_probe(struct platform_device *pdev)
 		return err;
 	}
 
-	err = host1x_register_client(tegra, &dc->client);
+	err = host1x_register_client(tegra, &dc->client.base);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
 			err);
@@ -1168,7 +1169,7 @@ static int tegra_dc_remove(struct platform_device *pdev)
 	struct tegra_dc *dc = platform_get_drvdata(pdev);
 	int err;
 
-	err = host1x_unregister_client(tegra, &dc->client);
+	err = host1x_unregister_client(tegra, &dc->client.base);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
 			err);
diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c
index 90a1f3d..cb6a4e8 100644
--- a/drivers/gpu/host1x/drm/drm.c
+++ b/drivers/gpu/host1x/drm/drm.c
@@ -131,12 +131,18 @@ int tegra_drm_alloc(struct platform_device *pdev)
 int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm)
 {
 	struct host1x_client *client;
+	int err;
 
 	mutex_lock(&tegra->clients_lock);
 
 	list_for_each_entry(client, &tegra->clients, list) {
-		if (client->ops && client->ops->drm_init) {
-			int err = client->ops->drm_init(client, drm);
+		struct tegra_drm_client *tdc = to_tegra_drm_client(client);
+
+		/* associate client with DRM device */
+		tdc->drm = drm;
+
+		if (client->ops && client->ops->init) {
+			err = client->ops->init(client);
 			if (err < 0) {
 				dev_err(tegra->dev,
 					"DRM setup failed for %s: %d\n",
@@ -154,8 +160,9 @@ int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm)
 
 int tegra_drm_exit(struct tegra_drm *tegra)
 {
-	struct platform_device *pdev = to_platform_device(tegra->dev);
 	struct host1x_client *client;
+	struct platform_device *pdev;
+	int err;
 
 	if (!tegra->drm)
 		return 0;
@@ -163,8 +170,8 @@ int tegra_drm_exit(struct tegra_drm *tegra)
 	mutex_lock(&tegra->clients_lock);
 
 	list_for_each_entry_reverse(client, &tegra->clients, list) {
-		if (client->ops && client->ops->drm_exit) {
-			int err = client->ops->drm_exit(client);
+		if (client->ops && client->ops->exit) {
+			err = client->ops->exit(client);
 			if (err < 0) {
 				dev_err(tegra->dev,
 					"DRM cleanup failed for %s: %d\n",
@@ -177,6 +184,7 @@ int tegra_drm_exit(struct tegra_drm *tegra)
 
 	mutex_unlock(&tegra->clients_lock);
 
+	pdev = to_platform_device(tegra->dev);
 	drm_platform_exit(&tegra_drm_driver, pdev);
 	tegra->drm = NULL;
 
@@ -409,22 +417,22 @@ static int tegra_open_channel(struct drm_device *drm, void *data,
 	struct tegra_drm *tegra = drm->dev_private;
 	struct drm_tegra_open_channel *args = data;
 	struct tegra_drm_context *context;
-	struct host1x_client *client;
+	struct tegra_drm_client *client;
 	int err = -ENODEV;
 
 	context = kzalloc(sizeof(*context), GFP_KERNEL);
 	if (!context)
 		return -ENOMEM;
 
-	list_for_each_entry(client, &tegra->clients, list)
-		if (client->class == args->client) {
+	list_for_each_entry(client, &tegra->clients, base.list)
+		if (client->base.class == args->client) {
 			err = client->ops->open_channel(client, context);
 			if (err)
 				break;
 
-			context->client = client;
 			list_add(&context->list, &fpriv->contexts);
 			args->context = (uintptr_t)context;
+			context->client = client;
 			return 0;
 		}
 
@@ -463,10 +471,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->num_syncpts)
+	if (args->index >= context->client->base.num_syncpts)
 		return -EINVAL;
 
-	syncpt = context->client->syncpts[args->index];
+	syncpt = context->client->base.syncpts[args->index];
 	args->id = host1x_syncpt_id(syncpt);
 
 	return 0;
diff --git a/drivers/gpu/host1x/drm/drm.h b/drivers/gpu/host1x/drm/drm.h
index 78754f6..8c26c6b 100644
--- a/drivers/gpu/host1x/drm/drm.h
+++ b/drivers/gpu/host1x/drm/drm.h
@@ -44,18 +44,16 @@ struct tegra_drm {
 	struct tegra_fbdev *fbdev;
 };
 
-struct host1x_client;
+struct tegra_drm_client;
 
 struct tegra_drm_context {
-	struct host1x_client *client;
+	struct tegra_drm_client *client;
 	struct host1x_channel *channel;
 	struct list_head list;
 };
 
-struct host1x_client_ops {
-	int (*drm_init)(struct host1x_client *client, struct drm_device *drm);
-	int (*drm_exit)(struct host1x_client *client);
-	int (*open_channel)(struct host1x_client *client,
+struct tegra_drm_client_ops {
+	int (*open_channel)(struct tegra_drm_client *client,
 			    struct tegra_drm_context *context);
 	void (*close_channel)(struct tegra_drm_context *context);
 	int (*submit)(struct tegra_drm_context *context,
@@ -63,21 +61,19 @@ struct host1x_client_ops {
 		      struct drm_file *file);
 };
 
-struct host1x_client {
-	struct tegra_drm *tegra;
-	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;
+struct tegra_drm_client {
+	struct host1x_client base;
+	struct drm_device *drm;
 
-	struct list_head list;
+	const struct tegra_drm_client_ops *ops;
 };
 
+static inline struct tegra_drm_client *
+to_tegra_drm_client(struct host1x_client *client)
+{
+	return container_of(client, struct tegra_drm_client, base);
+}
+
 extern int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
 extern int tegra_drm_exit(struct tegra_drm *tegra);
 
@@ -89,7 +85,7 @@ extern int host1x_unregister_client(struct tegra_drm *tegra,
 struct tegra_output;
 
 struct tegra_dc {
-	struct host1x_client client;
+	struct tegra_drm_client client;
 	struct device *dev;
 	spinlock_t lock;
 
@@ -112,7 +108,8 @@ struct tegra_dc {
 	struct drm_pending_vblank_event *event;
 };
 
-static inline struct tegra_dc *host1x_client_to_dc(struct host1x_client *client)
+static inline struct tegra_dc *
+tegra_drm_client_to_dc(struct tegra_drm_client *client)
 {
 	return container_of(client, struct tegra_dc, client);
 }
diff --git a/drivers/gpu/host1x/drm/gr2d.c b/drivers/gpu/host1x/drm/gr2d.c
index fc4476d..e814918 100644
--- a/drivers/gpu/host1x/drm/gr2d.c
+++ b/drivers/gpu/host1x/drm/gr2d.c
@@ -25,18 +25,17 @@
 #include "syncpt.h"
 
 struct gr2d {
-	struct host1x_client client;
+	struct tegra_drm_client client;
 	struct host1x_channel *channel;
 	struct clk *clk;
 };
 
-static inline struct gr2d *to_gr2d(struct host1x_client *client)
+static inline struct gr2d *to_gr2d(struct tegra_drm_client *client)
 {
 	return container_of(client, struct gr2d, client);
 }
 
-static int gr2d_client_init(struct host1x_client *client,
-			    struct drm_device *drm)
+static int gr2d_client_init(struct host1x_client *client)
 {
 	return 0;
 }
@@ -46,7 +45,12 @@ static int gr2d_client_exit(struct host1x_client *client)
 	return 0;
 }
 
-static int gr2d_open_channel(struct host1x_client *client,
+static const struct host1x_client_ops gr2d_client_ops = {
+	.init = gr2d_client_init,
+	.exit = gr2d_client_exit,
+};
+
+static int gr2d_open_channel(struct tegra_drm_client *client,
 			     struct tegra_drm_context *context)
 {
 	struct gr2d *gr2d = to_gr2d(client);
@@ -139,7 +143,7 @@ static int gr2d_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->class;
+	job->class = context->client->base.class;
 	job->serialize = true;
 
 	while (num_cmdbufs) {
@@ -200,7 +204,7 @@ static int gr2d_submit(struct tegra_drm_context *context,
 	if (args->timeout && args->timeout < 10000)
 		job->timeout = args->timeout;
 
-	err = host1x_job_pin(job, context->client->dev);
+	err = host1x_job_pin(job, context->client->base.dev);
 	if (err)
 		goto fail;
 
@@ -220,9 +224,7 @@ fail:
 	return err;
 }
 
-static struct host1x_client_ops gr2d_client_ops = {
-	.drm_init = gr2d_client_init,
-	.drm_exit = gr2d_client_exit,
+static const struct tegra_drm_client_ops gr2d_ops = {
 	.open_channel = gr2d_open_channel,
 	.close_channel = gr2d_close_channel,
 	.submit = gr2d_submit,
@@ -272,13 +274,15 @@ static int gr2d_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	gr2d->client.ops = &gr2d_client_ops;
-	gr2d->client.dev = dev;
-	gr2d->client.class = HOST1X_CLASS_GR2D;
-	gr2d->client.syncpts = syncpts;
-	gr2d->client.num_syncpts = 1;
+	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;
+	gr2d->client.ops = &gr2d_ops;
 
-	err = host1x_register_client(tegra, &gr2d->client);
+	err = host1x_register_client(tegra, &gr2d->client.base);
 	if (err < 0) {
 		dev_err(dev, "failed to register host1x client: %d\n", err);
 		return err;
@@ -296,15 +300,15 @@ static int gr2d_remove(struct platform_device *pdev)
 	unsigned int i;
 	int err;
 
-	err = host1x_unregister_client(tegra, &gr2d->client);
+	err = host1x_unregister_client(tegra, &gr2d->client.base);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
 			err);
 		return err;
 	}
 
-	for (i = 0; i < gr2d->client.num_syncpts; i++)
-		host1x_syncpt_free(gr2d->client.syncpts[i]);
+	for (i = 0; i < gr2d->client.base.num_syncpts; i++)
+		host1x_syncpt_free(gr2d->client.base.syncpts[i]);
 
 	host1x_channel_free(gr2d->channel);
 	clk_disable_unprepare(gr2d->clk);
diff --git a/drivers/gpu/host1x/drm/hdmi.c b/drivers/gpu/host1x/drm/hdmi.c
index 5d8c41c..30ac9e8 100644
--- a/drivers/gpu/host1x/drm/hdmi.c
+++ b/drivers/gpu/host1x/drm/hdmi.c
@@ -19,7 +19,7 @@
 #include "host1x_client.h"
 
 struct tegra_hdmi {
-	struct host1x_client client;
+	struct tegra_drm_client client;
 	struct tegra_output output;
 	struct device *dev;
 
@@ -43,7 +43,7 @@ struct tegra_hdmi {
 };
 
 static inline struct tegra_hdmi *
-host1x_client_to_hdmi(struct host1x_client *client)
+tegra_drm_client_to_hdmi(struct tegra_drm_client *client)
 {
 	return container_of(client, struct tegra_hdmi, client);
 }
@@ -1116,24 +1116,24 @@ static int tegra_hdmi_debugfs_exit(struct tegra_hdmi *hdmi)
 	return 0;
 }
 
-static int tegra_hdmi_drm_init(struct host1x_client *client,
-			       struct drm_device *drm)
+static int tegra_hdmi_init(struct host1x_client *client)
 {
-	struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
+	struct tegra_drm_client *drm = to_tegra_drm_client(client);
+	struct tegra_hdmi *hdmi = tegra_drm_client_to_hdmi(drm);
 	int err;
 
 	hdmi->output.type = TEGRA_OUTPUT_HDMI;
 	hdmi->output.dev = client->dev;
 	hdmi->output.ops = &hdmi_ops;
 
-	err = tegra_output_init(drm, &hdmi->output);
+	err = tegra_output_init(drm->drm, &hdmi->output);
 	if (err < 0) {
 		dev_err(client->dev, "output setup failed: %d\n", err);
 		return err;
 	}
 
 	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
-		err = tegra_hdmi_debugfs_init(hdmi, drm->primary);
+		err = tegra_hdmi_debugfs_init(hdmi, drm->drm->primary);
 		if (err < 0)
 			dev_err(client->dev, "debugfs setup failed: %d\n", err);
 	}
@@ -1141,9 +1141,10 @@ static int tegra_hdmi_drm_init(struct host1x_client *client,
 	return 0;
 }
 
-static int tegra_hdmi_drm_exit(struct host1x_client *client)
+static int tegra_hdmi_exit(struct host1x_client *client)
 {
-	struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
+	struct tegra_drm_client *drm = to_tegra_drm_client(client);
+	struct tegra_hdmi *hdmi = tegra_drm_client_to_hdmi(drm);
 	int err;
 
 	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
@@ -1169,8 +1170,8 @@ static int tegra_hdmi_drm_exit(struct host1x_client *client)
 }
 
 static const struct host1x_client_ops hdmi_client_ops = {
-	.drm_init = tegra_hdmi_drm_init,
-	.drm_exit = tegra_hdmi_drm_exit,
+	.init = tegra_hdmi_init,
+	.exit = tegra_hdmi_exit,
 };
 
 static int tegra_hdmi_probe(struct platform_device *pdev)
@@ -1246,11 +1247,11 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
 
 	hdmi->irq = err;
 
-	hdmi->client.ops = &hdmi_client_ops;
-	INIT_LIST_HEAD(&hdmi->client.list);
-	hdmi->client.dev = &pdev->dev;
+	INIT_LIST_HEAD(&hdmi->client.base.list);
+	hdmi->client.base.ops = &hdmi_client_ops;
+	hdmi->client.base.dev = &pdev->dev;
 
-	err = host1x_register_client(tegra, &hdmi->client);
+	err = host1x_register_client(tegra, &hdmi->client.base);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
 			err);
@@ -1268,7 +1269,7 @@ static int tegra_hdmi_remove(struct platform_device *pdev)
 	struct tegra_hdmi *hdmi = platform_get_drvdata(pdev);
 	int err;
 
-	err = host1x_unregister_client(tegra, &hdmi->client);
+	err = host1x_unregister_client(tegra, &hdmi->client.base);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
 			err);
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index fe09939..d429a93 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -25,4 +25,24 @@ enum host1x_class {
 	HOST1X_CLASS_GR2D_SB = 0x52,
 };
 
+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 *dev;
+
+	const struct host1x_client_ops *ops;
+
+	enum host1x_class class;
+	struct host1x_channel *channel;
+
+	struct host1x_syncpt **syncpts;
+	unsigned int num_syncpts;
+};
+
 #endif
-- 
1.8.4

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

* [PATCH v2 12/27] gpu: host1x: Expose syncpt and channel functionality
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (10 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 11/27] drm/tegra: Introduce tegra_drm_client structure Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
  2013-10-07  8:34   ` [PATCH v2 13/27] drm/tegra: Move subdevice infrastructure to host1x Thierry Reding
                     ` (14 subsequent siblings)
  26 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

Expose the buffer objects, syncpoint and channel functionality in the
public public header so that drivers can use them.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/host1x/Makefile        |   2 -
 drivers/gpu/host1x/cdma.c          |   2 +-
 drivers/gpu/host1x/channel.h       |   6 --
 drivers/gpu/host1x/drm/drm.c       |   2 -
 drivers/gpu/host1x/drm/gem.h       |   4 +-
 drivers/gpu/host1x/drm/gr2d.c      |   6 +-
 drivers/gpu/host1x/drm/hdmi.c      |   2 +-
 drivers/gpu/host1x/host1x_bo.h     |  87 -----------------
 drivers/gpu/host1x/hw/channel_hw.c |   1 -
 drivers/gpu/host1x/hw/debug_hw.c   |   1 -
 drivers/gpu/host1x/job.c           |   2 +-
 drivers/gpu/host1x/job.h           | 108 ----------------------
 drivers/gpu/host1x/syncpt.c        |  19 ++++
 drivers/gpu/host1x/syncpt.h        |  40 +-------
 include/linux/host1x.h             | 185 +++++++++++++++++++++++++++++++++++++
 15 files changed, 211 insertions(+), 256 deletions(-)
 delete mode 100644 drivers/gpu/host1x/host1x_bo.h

diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index 3b037b6..64628ba 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -1,5 +1,3 @@
-ccflags-y = -Idrivers/gpu/host1x
-
 host1x-y = \
 	syncpt.o \
 	dev.o \
diff --git a/drivers/gpu/host1x/cdma.c b/drivers/gpu/host1x/cdma.c
index de72172..3995255 100644
--- a/drivers/gpu/host1x/cdma.c
+++ b/drivers/gpu/host1x/cdma.c
@@ -20,6 +20,7 @@
 #include <asm/cacheflush.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/host1x.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/kfifo.h>
@@ -30,7 +31,6 @@
 #include "channel.h"
 #include "dev.h"
 #include "debug.h"
-#include "host1x_bo.h"
 #include "job.h"
 
 /*
diff --git a/drivers/gpu/host1x/channel.h b/drivers/gpu/host1x/channel.h
index 48723b8..df767cf 100644
--- a/drivers/gpu/host1x/channel.h
+++ b/drivers/gpu/host1x/channel.h
@@ -40,12 +40,6 @@ struct host1x_channel {
 /* channel list operations */
 int host1x_channel_list_init(struct host1x *host);
 
-struct host1x_channel *host1x_channel_request(struct device *dev);
-void host1x_channel_free(struct host1x_channel *channel);
-struct host1x_channel *host1x_channel_get(struct host1x_channel *channel);
-void host1x_channel_put(struct host1x_channel *channel);
-int host1x_job_submit(struct host1x_job *job);
-
 #define host1x_for_each_channel(host, channel)				\
 	list_for_each_entry(channel, &host->chlist.list, list)
 
diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c
index cb6a4e8..e93caea 100644
--- a/drivers/gpu/host1x/drm/drm.c
+++ b/drivers/gpu/host1x/drm/drm.c
@@ -8,10 +8,8 @@
  */
 
 #include "host1x_client.h"
-#include "dev.h"
 #include "drm.h"
 #include "gem.h"
-#include "syncpt.h"
 
 #define DRIVER_NAME "tegra"
 #define DRIVER_DESC "NVIDIA Tegra graphics"
diff --git a/drivers/gpu/host1x/drm/gem.h b/drivers/gpu/host1x/drm/gem.h
index 492533a..2b54f14 100644
--- a/drivers/gpu/host1x/drm/gem.h
+++ b/drivers/gpu/host1x/drm/gem.h
@@ -19,11 +19,11 @@
 #ifndef __HOST1X_GEM_H
 #define __HOST1X_GEM_H
 
+#include <linux/host1x.h>
+
 #include <drm/drm.h>
 #include <drm/drmP.h>
 
-#include "host1x_bo.h"
-
 struct tegra_bo {
 	struct drm_gem_object gem;
 	struct host1x_bo base;
diff --git a/drivers/gpu/host1x/drm/gr2d.c b/drivers/gpu/host1x/drm/gr2d.c
index e814918..a16aaa8 100644
--- a/drivers/gpu/host1x/drm/gr2d.c
+++ b/drivers/gpu/host1x/drm/gr2d.c
@@ -16,13 +16,9 @@
 
 #include <linux/clk.h>
 
-#include "channel.h"
+#include "host1x_client.h"
 #include "drm.h"
 #include "gem.h"
-#include "job.h"
-#include "host1x_bo.h"
-#include "host1x_client.h"
-#include "syncpt.h"
 
 struct gr2d {
 	struct tegra_drm_client client;
diff --git a/drivers/gpu/host1x/drm/hdmi.c b/drivers/gpu/host1x/drm/hdmi.c
index 30ac9e8..a237004 100644
--- a/drivers/gpu/host1x/drm/hdmi.c
+++ b/drivers/gpu/host1x/drm/hdmi.c
@@ -13,10 +13,10 @@
 #include <linux/hdmi.h>
 #include <linux/regulator/consumer.h>
 
+#include "host1x_client.h"
 #include "hdmi.h"
 #include "drm.h"
 #include "dc.h"
-#include "host1x_client.h"
 
 struct tegra_hdmi {
 	struct tegra_drm_client client;
diff --git a/drivers/gpu/host1x/host1x_bo.h b/drivers/gpu/host1x/host1x_bo.h
deleted file mode 100644
index 4c1f10bd..0000000
--- a/drivers/gpu/host1x/host1x_bo.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Tegra host1x Memory Management Abstraction header
- *
- * 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_BO_H
-#define _HOST1X_BO_H
-
-struct host1x_bo;
-
-struct host1x_bo_ops {
-	struct host1x_bo *(*get)(struct host1x_bo *bo);
-	void (*put)(struct host1x_bo *bo);
-	dma_addr_t (*pin)(struct host1x_bo *bo, struct sg_table **sgt);
-	void (*unpin)(struct host1x_bo *bo, struct sg_table *sgt);
-	void *(*mmap)(struct host1x_bo *bo);
-	void (*munmap)(struct host1x_bo *bo, void *addr);
-	void *(*kmap)(struct host1x_bo *bo, unsigned int pagenum);
-	void (*kunmap)(struct host1x_bo *bo, unsigned int pagenum, void *addr);
-};
-
-struct host1x_bo {
-	const struct host1x_bo_ops *ops;
-};
-
-static inline void host1x_bo_init(struct host1x_bo *bo,
-				  const struct host1x_bo_ops *ops)
-{
-	bo->ops = ops;
-}
-
-static inline struct host1x_bo *host1x_bo_get(struct host1x_bo *bo)
-{
-	return bo->ops->get(bo);
-}
-
-static inline void host1x_bo_put(struct host1x_bo *bo)
-{
-	bo->ops->put(bo);
-}
-
-static inline dma_addr_t host1x_bo_pin(struct host1x_bo *bo,
-				       struct sg_table **sgt)
-{
-	return bo->ops->pin(bo, sgt);
-}
-
-static inline void host1x_bo_unpin(struct host1x_bo *bo, struct sg_table *sgt)
-{
-	bo->ops->unpin(bo, sgt);
-}
-
-static inline void *host1x_bo_mmap(struct host1x_bo *bo)
-{
-	return bo->ops->mmap(bo);
-}
-
-static inline void host1x_bo_munmap(struct host1x_bo *bo, void *addr)
-{
-	bo->ops->munmap(bo, addr);
-}
-
-static inline void *host1x_bo_kmap(struct host1x_bo *bo, unsigned int pagenum)
-{
-	return bo->ops->kmap(bo, pagenum);
-}
-
-static inline void host1x_bo_kunmap(struct host1x_bo *bo,
-				    unsigned int pagenum, void *addr)
-{
-	bo->ops->kunmap(bo, pagenum, addr);
-}
-
-#endif
diff --git a/drivers/gpu/host1x/hw/channel_hw.c b/drivers/gpu/host1x/hw/channel_hw.c
index c950bc6..aa9bdf3 100644
--- a/drivers/gpu/host1x/hw/channel_hw.c
+++ b/drivers/gpu/host1x/hw/channel_hw.c
@@ -21,7 +21,6 @@
 
 #include <trace/events/host1x.h>
 
-#include "host1x_bo.h"
 #include "channel.h"
 #include "dev.h"
 #include "intr.h"
diff --git a/drivers/gpu/host1x/hw/debug_hw.c b/drivers/gpu/host1x/hw/debug_hw.c
index dfad663..788fe71 100644
--- a/drivers/gpu/host1x/hw/debug_hw.c
+++ b/drivers/gpu/host1x/hw/debug_hw.c
@@ -19,7 +19,6 @@
 #include "debug.h"
 #include "cdma.h"
 #include "channel.h"
-#include "host1x_bo.h"
 
 #define HOST1X_DEBUG_MAX_PAGE_OFFSET 102400
 
diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c
index c4e1050..0ac3474 100644
--- a/drivers/gpu/host1x/job.c
+++ b/drivers/gpu/host1x/job.c
@@ -18,6 +18,7 @@
 
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
+#include <linux/host1x.h>
 #include <linux/kref.h>
 #include <linux/module.h>
 #include <linux/scatterlist.h>
@@ -27,7 +28,6 @@
 
 #include "channel.h"
 #include "dev.h"
-#include "host1x_bo.h"
 #include "job.h"
 #include "syncpt.h"
 
diff --git a/drivers/gpu/host1x/job.h b/drivers/gpu/host1x/job.h
index fba45f2..33a697d 100644
--- a/drivers/gpu/host1x/job.h
+++ b/drivers/gpu/host1x/job.h
@@ -34,15 +34,6 @@ struct host1x_cmdbuf {
 	u32 pad;
 };
 
-struct host1x_reloc {
-	struct host1x_bo *cmdbuf;
-	u32 cmdbuf_offset;
-	struct host1x_bo *target;
-	u32 target_offset;
-	u32 shift;
-	u32 pad;
-};
-
 struct host1x_waitchk {
 	struct host1x_bo *bo;
 	u32 offset;
@@ -56,105 +47,6 @@ struct host1x_job_unpin_data {
 };
 
 /*
- * Each submit is tracked as a host1x_job.
- */
-struct host1x_job {
-	/* When refcount goes to zero, job can be freed */
-	struct kref ref;
-
-	/* List entry */
-	struct list_head list;
-
-	/* Channel where job is submitted to */
-	struct host1x_channel *channel;
-
-	u32 client;
-
-	/* Gathers and their memory */
-	struct host1x_job_gather *gathers;
-	unsigned int num_gathers;
-
-	/* Wait checks to be processed at submit time */
-	struct host1x_waitchk *waitchk;
-	unsigned int num_waitchk;
-	u32 waitchk_mask;
-
-	/* Array of handles to be pinned & unpinned */
-	struct host1x_reloc *relocarray;
-	unsigned int num_relocs;
-	struct host1x_job_unpin_data *unpins;
-	unsigned int num_unpins;
-
-	dma_addr_t *addr_phys;
-	dma_addr_t *gather_addr_phys;
-	dma_addr_t *reloc_addr_phys;
-
-	/* Sync point id, number of increments and end related to the submit */
-	u32 syncpt_id;
-	u32 syncpt_incrs;
-	u32 syncpt_end;
-
-	/* Maximum time to wait for this job */
-	unsigned int timeout;
-
-	/* Index and number of slots used in the push buffer */
-	unsigned int first_get;
-	unsigned int num_slots;
-
-	/* Copy of gathers */
-	size_t gather_copy_size;
-	dma_addr_t gather_copy;
-	u8 *gather_copy_mapped;
-
-	/* Check if register is marked as an address reg */
-	int (*is_addr_reg)(struct device *dev, u32 reg, u32 class);
-
-	/* Request a SETCLASS to this class */
-	u32 class;
-
-	/* Add a channel wait for previous ops to complete */
-	bool serialize;
-};
-/*
- * Allocate memory for a job. Just enough memory will be allocated to
- * accomodate the submit.
- */
-struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,
-				    u32 num_cmdbufs, u32 num_relocs,
-				    u32 num_waitchks);
-
-/*
- * Add a gather to a job.
- */
-void host1x_job_add_gather(struct host1x_job *job, struct host1x_bo *mem_id,
-			   u32 words, u32 offset);
-
-/*
- * Increment reference going to host1x_job.
- */
-struct host1x_job *host1x_job_get(struct host1x_job *job);
-
-/*
- * Decrement reference job, free if goes to zero.
- */
-void host1x_job_put(struct host1x_job *job);
-
-/*
- * Pin memory related to job. This handles relocation of addresses to the
- * host1x address space. Handles both the gather memory and any other memory
- * referred to from the gather buffers.
- *
- * Handles also patching out host waits that would wait for an expired sync
- * point value.
- */
-int host1x_job_pin(struct host1x_job *job, struct device *dev);
-
-/*
- * Unpin memory related to job.
- */
-void host1x_job_unpin(struct host1x_job *job);
-
-/*
  * Dump contents of job to debug output.
  */
 void host1x_job_dump(struct device *dev, struct host1x_job *job);
diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c
index 409745b..03cf292 100644
--- a/drivers/gpu/host1x/syncpt.c
+++ b/drivers/gpu/host1x/syncpt.c
@@ -354,6 +354,25 @@ void host1x_syncpt_deinit(struct host1x *host)
 		kfree(sp->name);
 }
 
+/*
+ * Read max. It indicates how many operations there are in queue, either in
+ * channel or in a software thread.
+ * */
+u32 host1x_syncpt_read_max(struct host1x_syncpt *sp)
+{
+	smp_rmb();
+	return (u32)atomic_read(&sp->max_val);
+}
+
+/*
+ * Read min, which is a shadow of the current sync point value in hardware.
+ */
+u32 host1x_syncpt_read_min(struct host1x_syncpt *sp)
+{
+	smp_rmb();
+	return (u32)atomic_read(&sp->min_val);
+}
+
 int host1x_syncpt_nb_pts(struct host1x *host)
 {
 	return host->info->nb_pts;
diff --git a/drivers/gpu/host1x/syncpt.h b/drivers/gpu/host1x/syncpt.h
index 267c0b9..4eb933a 100644
--- a/drivers/gpu/host1x/syncpt.h
+++ b/drivers/gpu/host1x/syncpt.h
@@ -20,6 +20,7 @@
 #define __HOST1X_SYNCPT_H
 
 #include <linux/atomic.h>
+#include <linux/host1x.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 
@@ -50,25 +51,6 @@ int host1x_syncpt_init(struct host1x *host);
 /*  Free sync point array */
 void host1x_syncpt_deinit(struct host1x *host);
 
-/*
- * Read max. It indicates how many operations there are in queue, either in
- * channel or in a software thread.
- * */
-static inline u32 host1x_syncpt_read_max(struct host1x_syncpt *sp)
-{
-	smp_rmb();
-	return (u32)atomic_read(&sp->max_val);
-}
-
-/*
- * Read min, which is a shadow of the current sync point value in hardware.
- */
-static inline u32 host1x_syncpt_read_min(struct host1x_syncpt *sp)
-{
-	smp_rmb();
-	return (u32)atomic_read(&sp->min_val);
-}
-
 /* Return number of sync point supported. */
 int host1x_syncpt_nb_pts(struct host1x *host);
 
@@ -112,9 +94,6 @@ static inline bool host1x_syncpt_idle(struct host1x_syncpt *sp)
 	return (min == max);
 }
 
-/* Return pointer to struct denoting sync point id. */
-struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, u32 id);
-
 /* Load current value from hardware to the shadow register. */
 u32 host1x_syncpt_load(struct host1x_syncpt *sp);
 
@@ -130,16 +109,9 @@ void host1x_syncpt_restore(struct host1x *host);
 /* Read current wait base value into shadow register and return it. */
 u32 host1x_syncpt_load_wait_base(struct host1x_syncpt *sp);
 
-/* Request incrementing a sync point. */
-int host1x_syncpt_incr(struct host1x_syncpt *sp);
-
 /* Indicate future operations by incrementing the sync point max. */
 u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs);
 
-/* Wait until sync point reaches a threshold value, or a timeout. */
-int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh,
-			long timeout, u32 *value);
-
 /* Check if sync point id is valid. */
 static inline int host1x_syncpt_is_valid(struct host1x_syncpt *sp)
 {
@@ -149,14 +121,4 @@ static inline int host1x_syncpt_is_valid(struct host1x_syncpt *sp)
 /* Patch a wait by replacing it with a wait for syncpt 0 value 0 */
 int host1x_syncpt_patch_wait(struct host1x_syncpt *sp, void *patch_addr);
 
-/* Return id of the sync point */
-u32 host1x_syncpt_id(struct host1x_syncpt *sp);
-
-/* Allocate a sync point for a device. */
-struct host1x_syncpt *host1x_syncpt_request(struct device *dev,
-					    bool client_managed);
-
-/* Free a sync point. */
-void host1x_syncpt_free(struct host1x_syncpt *sp);
-
 #endif
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index d429a93..7442f2a 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -19,6 +19,9 @@
 #ifndef __LINUX_HOST1X_H
 #define __LINUX_HOST1X_H
 
+#include <linux/kref.h>
+#include <linux/types.h>
+
 enum host1x_class {
 	HOST1X_CLASS_HOST1X = 0x1,
 	HOST1X_CLASS_GR2D = 0x51,
@@ -45,4 +48,186 @@ struct host1x_client {
 	unsigned int num_syncpts;
 };
 
+/*
+ * host1x buffer objects
+ */
+
+struct host1x_bo;
+struct sg_table;
+
+struct host1x_bo_ops {
+	struct host1x_bo *(*get)(struct host1x_bo *bo);
+	void (*put)(struct host1x_bo *bo);
+	dma_addr_t (*pin)(struct host1x_bo *bo, struct sg_table **sgt);
+	void (*unpin)(struct host1x_bo *bo, struct sg_table *sgt);
+	void *(*mmap)(struct host1x_bo *bo);
+	void (*munmap)(struct host1x_bo *bo, void *addr);
+	void *(*kmap)(struct host1x_bo *bo, unsigned int pagenum);
+	void (*kunmap)(struct host1x_bo *bo, unsigned int pagenum, void *addr);
+};
+
+struct host1x_bo {
+	const struct host1x_bo_ops *ops;
+};
+
+static inline void host1x_bo_init(struct host1x_bo *bo,
+				  const struct host1x_bo_ops *ops)
+{
+	bo->ops = ops;
+}
+
+static inline struct host1x_bo *host1x_bo_get(struct host1x_bo *bo)
+{
+	return bo->ops->get(bo);
+}
+
+static inline void host1x_bo_put(struct host1x_bo *bo)
+{
+	bo->ops->put(bo);
+}
+
+static inline dma_addr_t host1x_bo_pin(struct host1x_bo *bo,
+				       struct sg_table **sgt)
+{
+	return bo->ops->pin(bo, sgt);
+}
+
+static inline void host1x_bo_unpin(struct host1x_bo *bo, struct sg_table *sgt)
+{
+	bo->ops->unpin(bo, sgt);
+}
+
+static inline void *host1x_bo_mmap(struct host1x_bo *bo)
+{
+	return bo->ops->mmap(bo);
+}
+
+static inline void host1x_bo_munmap(struct host1x_bo *bo, void *addr)
+{
+	bo->ops->munmap(bo, addr);
+}
+
+static inline void *host1x_bo_kmap(struct host1x_bo *bo, unsigned int pagenum)
+{
+	return bo->ops->kmap(bo, pagenum);
+}
+
+static inline void host1x_bo_kunmap(struct host1x_bo *bo,
+				    unsigned int pagenum, void *addr)
+{
+	bo->ops->kunmap(bo, pagenum, addr);
+}
+
+/*
+ * host1x syncpoints
+ */
+
+struct host1x_syncpt;
+struct host1x;
+
+struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, u32 id);
+u32 host1x_syncpt_id(struct host1x_syncpt *sp);
+u32 host1x_syncpt_read_min(struct host1x_syncpt *sp);
+u32 host1x_syncpt_read_max(struct host1x_syncpt *sp);
+int host1x_syncpt_incr(struct host1x_syncpt *sp);
+int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout,
+		       u32 *value);
+struct host1x_syncpt *host1x_syncpt_request(struct device *dev,
+					    bool client_managed);
+void host1x_syncpt_free(struct host1x_syncpt *sp);
+
+/*
+ * host1x channel
+ */
+
+struct host1x_channel;
+struct host1x_job;
+
+struct host1x_channel *host1x_channel_request(struct device *dev);
+void host1x_channel_free(struct host1x_channel *channel);
+struct host1x_channel *host1x_channel_get(struct host1x_channel *channel);
+void host1x_channel_put(struct host1x_channel *channel);
+int host1x_job_submit(struct host1x_job *job);
+
+/*
+ * host1x job
+ */
+
+struct host1x_reloc {
+	struct host1x_bo *cmdbuf;
+	u32 cmdbuf_offset;
+	struct host1x_bo *target;
+	u32 target_offset;
+	u32 shift;
+	u32 pad;
+};
+
+struct host1x_job {
+	/* When refcount goes to zero, job can be freed */
+	struct kref ref;
+
+	/* List entry */
+	struct list_head list;
+
+	/* Channel where job is submitted to */
+	struct host1x_channel *channel;
+
+	u32 client;
+
+	/* Gathers and their memory */
+	struct host1x_job_gather *gathers;
+	unsigned int num_gathers;
+
+	/* Wait checks to be processed at submit time */
+	struct host1x_waitchk *waitchk;
+	unsigned int num_waitchk;
+	u32 waitchk_mask;
+
+	/* Array of handles to be pinned & unpinned */
+	struct host1x_reloc *relocarray;
+	unsigned int num_relocs;
+	struct host1x_job_unpin_data *unpins;
+	unsigned int num_unpins;
+
+	dma_addr_t *addr_phys;
+	dma_addr_t *gather_addr_phys;
+	dma_addr_t *reloc_addr_phys;
+
+	/* Sync point id, number of increments and end related to the submit */
+	u32 syncpt_id;
+	u32 syncpt_incrs;
+	u32 syncpt_end;
+
+	/* Maximum time to wait for this job */
+	unsigned int timeout;
+
+	/* Index and number of slots used in the push buffer */
+	unsigned int first_get;
+	unsigned int num_slots;
+
+	/* Copy of gathers */
+	size_t gather_copy_size;
+	dma_addr_t gather_copy;
+	u8 *gather_copy_mapped;
+
+	/* Check if register is marked as an address reg */
+	int (*is_addr_reg)(struct device *dev, u32 reg, u32 class);
+
+	/* Request a SETCLASS to this class */
+	u32 class;
+
+	/* Add a channel wait for previous ops to complete */
+	bool serialize;
+};
+
+struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,
+				    u32 num_cmdbufs, u32 num_relocs,
+				    u32 num_waitchks);
+void host1x_job_add_gather(struct host1x_job *job, struct host1x_bo *mem_id,
+			   u32 words, u32 offset);
+struct host1x_job *host1x_job_get(struct host1x_job *job);
+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);
+
 #endif
-- 
1.8.4

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

* [PATCH v2 13/27] drm/tegra: Move subdevice infrastructure to host1x
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (11 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 12/27] gpu: host1x: Expose syncpt and channel functionality Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
       [not found]     ` <1381134884-5816-14-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2013-10-07  8:34   ` [PATCH v2 14/27] drm/tegra: Move driver to DRM tree Thierry Reding
                     ` (13 subsequent siblings)
  26 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

The Tegra DRM driver currently uses some infrastructure to defer the DRM
core initialization until all required devices have registered. The same
infrastructure can potentially be used by any other driver that requires
more than a single sub-device of the host1x module.

Make the infrastructure more generic and keep only the DRM specific code
in the DRM part of the driver. Eventually this will make it easy to move
the DRM driver part back to the DRM subsystem.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/host1x/Makefile                   |   2 +
 drivers/gpu/host1x/bus.c                      | 309 +++++++++++++++++++++++
 drivers/gpu/host1x/{host1x_client.h => bus.h} |  24 +-
 drivers/gpu/host1x/dev.c                      |  60 ++---
 drivers/gpu/host1x/dev.h                      |   9 +-
 drivers/gpu/host1x/drm/bus.c                  | 123 +++++++++
 drivers/gpu/host1x/drm/dc.c                   |  35 +--
 drivers/gpu/host1x/drm/drm.c                  | 347 +++++++++-----------------
 drivers/gpu/host1x/drm/drm.h                  |  31 +--
 drivers/gpu/host1x/drm/gr2d.c                 |  32 ++-
 drivers/gpu/host1x/drm/hdmi.c                 |  33 +--
 include/drm/drmP.h                            |   1 +
 include/linux/host1x.h                        |  45 +++-
 13 files changed, 700 insertions(+), 351 deletions(-)
 create mode 100644 drivers/gpu/host1x/bus.c
 rename drivers/gpu/host1x/{host1x_client.h => bus.h} (60%)
 create mode 100644 drivers/gpu/host1x/drm/bus.c

diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index 64628ba..616fe82 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -1,4 +1,5 @@
 host1x-y = \
+	bus.o \
 	syncpt.o \
 	dev.o \
 	intr.o \
@@ -15,4 +16,5 @@ host1x-$(CONFIG_DRM_TEGRA) += drm/drm.o drm/fb.o drm/dc.o
 host1x-$(CONFIG_DRM_TEGRA) += drm/output.o drm/rgb.o drm/hdmi.o
 host1x-$(CONFIG_DRM_TEGRA) += drm/gem.o
 host1x-$(CONFIG_DRM_TEGRA) += drm/gr2d.o
+host1x-$(CONFIG_DRM_TEGRA) += drm/bus.o
 obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c
new file mode 100644
index 0000000..8e96d23
--- /dev/null
+++ b/drivers/gpu/host1x/bus.c
@@ -0,0 +1,309 @@
+/*
+ * 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 "dev.h"
+
+struct host1x_subdev {
+	struct host1x_client *client;
+	struct device_node *np;
+	struct list_head list;
+};
+
+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);
+
+	list_add_tail(&subdev->list, &device->subdevs);
+
+	return 0;
+}
+
+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;
+
+	mutex_lock(&device->subdevs_lock);
+	mutex_lock(&device->clients_lock);
+	list_del_init(&subdev->list);
+	list_add_tail(&client->list, &device->clients);
+	client->parent = &device->dev;
+	subdev->client = client;
+	mutex_unlock(&device->clients_lock);
+	mutex_unlock(&device->subdevs_lock);
+
+	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)
+{
+	mutex_lock(&device->subdevs_lock);
+	list_del_init(&subdev->list);
+	mutex_unlock(&device->subdevs_lock);
+
+	of_node_put(subdev->np);
+	kfree(subdev);
+}
+
+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;
+}
+
+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;
+}
+
+int host1x_register_client(struct host1x *host1x, struct host1x_client *client)
+{
+	struct host1x_device *device;
+	struct host1x_subdev *subdev;
+
+	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);
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
+
+int host1x_unregister_client(struct host1x *host1x,
+			     struct host1x_client *client)
+{
+	struct host1x_device *device;
+	struct host1x_subdev *subdev;
+
+	list_for_each_entry(device, &host1x->devices, list)
+		list_for_each_entry(subdev, &device->subdevs, list)
+			if (subdev->client == client)
+				host1x_subdev_unregister(device, subdev);
+
+	return 0;
+}
+
+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_device *device;
+	int err;
+
+	device = kzalloc(sizeof(*device), GFP_KERNEL);
+	if (!device)
+		return -ENOMEM;
+
+	mutex_init(&device->subdevs_lock);
+	INIT_LIST_HEAD(&device->subdevs);
+	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, 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) {
+		put_device(&device->dev);
+		return err;
+	}
+
+	list_add_tail(&device->list, &host1x->devices);
+
+	return 0;
+}
+
+static void host1x_attach_driver(struct host1x *host1x,
+				 struct host1x_driver *driver)
+{
+	struct host1x_device *device;
+	int err;
+
+	list_for_each_entry(device, &host1x->devices, list)
+		if (device->driver == driver)
+			return;
+
+	err = host1x_device_add(host1x, driver);
+	if (err < 0)
+		dev_err(host1x->dev, "failed to allocate device: %d\n", err);
+}
+
+static DEFINE_MUTEX(drivers_lock);
+static LIST_HEAD(drivers);
+
+static DEFINE_MUTEX(devices_lock);
+static LIST_HEAD(devices);
+
+int host1x_register(struct host1x *host1x)
+{
+	struct host1x_driver *driver;
+
+	mutex_lock(&devices_lock);
+	list_add_tail(&host1x->list, &devices);
+	mutex_unlock(&devices_lock);
+
+	list_for_each_entry(driver, &drivers, list)
+		host1x_attach_driver(host1x, driver);
+
+	return 0;
+}
+
+int host1x_unregister(struct host1x *host1x)
+{
+	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);
diff --git a/drivers/gpu/host1x/host1x_client.h b/drivers/gpu/host1x/bus.h
similarity index 60%
rename from drivers/gpu/host1x/host1x_client.h
rename to drivers/gpu/host1x/bus.h
index 6a0bd02..4099e99 100644
--- a/drivers/gpu/host1x/host1x_client.h
+++ b/drivers/gpu/host1x/bus.h
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2013, NVIDIA Corporation.
+ * 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,
@@ -14,22 +15,15 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef HOST1X_CLIENT_H
-#define HOST1X_CLIENT_H
+#ifndef HOST1X_BUS_H
+#define HOST1X_BUS_H
 
-struct device;
-struct platform_device;
+struct host1x;
 
-#ifdef CONFIG_DRM_TEGRA
-int tegra_drm_alloc(struct platform_device *pdev);
-#else
-static inline int tegra_drm_alloc(struct platform_device *pdev)
-{
-	return 0;
-}
-#endif
+int host1x_bus_init(void);
+void host1x_bus_exit(void);
 
-void host1x_set_drm_data(struct device *dev, void *data);
-void *host1x_get_drm_data(struct device *dev);
+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 105aa4e..de0fd55 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -27,24 +27,12 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/host1x.h>
 
+#include "bus.h"
 #include "dev.h"
 #include "intr.h"
 #include "channel.h"
 #include "debug.h"
 #include "hw/host1x01.h"
-#include "host1x_client.h"
-
-void host1x_set_drm_data(struct device *dev, void *data)
-{
-	struct host1x *host1x = dev_get_drvdata(dev);
-	host1x->drm_data = data;
-}
-
-void *host1x_get_drm_data(struct device *dev)
-{
-	struct host1x *host1x = dev_get_drvdata(dev);
-	return host1x ? host1x->drm_data : NULL;
-}
 
 void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r)
 {
@@ -114,6 +102,9 @@ static int host1x_probe(struct platform_device *pdev)
 	if (!host)
 		return -ENOMEM;
 
+	mutex_init(&host->devices_lock);
+	INIT_LIST_HEAD(&host->devices);
+	INIT_LIST_HEAD(&host->list);
 	host->dev = &pdev->dev;
 	host->info = id->data;
 
@@ -163,10 +154,14 @@ static int host1x_probe(struct platform_device *pdev)
 
 	host1x_debug_init(host);
 
-	tegra_drm_alloc(pdev);
+	err = host1x_register(host);
+	if (err < 0)
+		goto fail_deinit_intr;
 
 	return 0;
 
+fail_deinit_intr:
+	host1x_intr_deinit(host);
 fail_deinit_syncpt:
 	host1x_syncpt_deinit(host);
 	return err;
@@ -176,6 +171,7 @@ static int host1x_remove(struct platform_device *pdev)
 {
 	struct host1x *host = platform_get_drvdata(pdev);
 
+	host1x_unregister(host);
 	host1x_intr_deinit(host);
 	host1x_syncpt_deinit(host);
 	clk_disable_unprepare(host->clk);
@@ -196,46 +192,24 @@ static int __init tegra_host1x_init(void)
 {
 	int err;
 
-	err = platform_driver_register(&tegra_host1x_driver);
+	err = host1x_bus_init();
 	if (err < 0)
 		return err;
 
-#ifdef CONFIG_DRM_TEGRA
-	err = platform_driver_register(&tegra_dc_driver);
-	if (err < 0)
-		goto unregister_host1x;
-
-	err = platform_driver_register(&tegra_hdmi_driver);
-	if (err < 0)
-		goto unregister_dc;
-
-	err = platform_driver_register(&tegra_gr2d_driver);
-	if (err < 0)
-		goto unregister_hdmi;
-#endif
+	err = platform_driver_register(&tegra_host1x_driver);
+	if (err < 0) {
+		host1x_bus_exit();
+		return err;
+	}
 
 	return 0;
-
-#ifdef CONFIG_DRM_TEGRA
-unregister_hdmi:
-	platform_driver_unregister(&tegra_hdmi_driver);
-unregister_dc:
-	platform_driver_unregister(&tegra_dc_driver);
-unregister_host1x:
-	platform_driver_unregister(&tegra_host1x_driver);
-	return err;
-#endif
 }
 module_init(tegra_host1x_init);
 
 static void __exit tegra_host1x_exit(void)
 {
-#ifdef CONFIG_DRM_TEGRA
-	platform_driver_unregister(&tegra_gr2d_driver);
-	platform_driver_unregister(&tegra_hdmi_driver);
-	platform_driver_unregister(&tegra_dc_driver);
-#endif
 	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 bed90a8..6cf689b 100644
--- a/drivers/gpu/host1x/dev.h
+++ b/drivers/gpu/host1x/dev.h
@@ -125,7 +125,10 @@ struct host1x {
 
 	struct dentry *debugfs;
 
-	void *drm_data;
+	struct mutex devices_lock;
+	struct list_head devices;
+
+	struct list_head list;
 };
 
 void host1x_sync_writel(struct host1x *host1x, u32 r, u32 v);
@@ -301,8 +304,4 @@ static inline void host1x_hw_show_mlocks(struct host1x *host, struct output *o)
 	host->debug_op->show_mlocks(host, o);
 }
 
-extern struct platform_driver tegra_dc_driver;
-extern struct platform_driver tegra_hdmi_driver;
-extern struct platform_driver tegra_gr2d_driver;
-
 #endif
diff --git a/drivers/gpu/host1x/drm/bus.c b/drivers/gpu/host1x/drm/bus.c
new file mode 100644
index 0000000..01c984d
--- /dev/null
+++ b/drivers/gpu/host1x/drm/bus.c
@@ -0,0 +1,123 @@
+/*
+ * 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 *driver = dev->driver->name;
+	const char *bus = dev->dev->bus->name;
+	int length;
+
+	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);
+
+	length = strlen(driver) + 1 + master->unique_len;
+
+	dev->devname = kmalloc(length + 1, GFP_KERNEL);
+	if (!dev->devname)
+		return -ENOMEM;
+
+	snprintf(dev->devname, length + 1, "%s@%s", driver, master->unique);
+
+	return 0;
+}
+
+static struct drm_bus drm_host1x_bus = {
+	.bus_type = DRIVER_BUS_HOST1X,
+	.set_busid = drm_host1x_set_busid,
+};
+
+int drm_host1x_init(struct drm_driver *driver, struct host1x_device *device)
+{
+	struct drm_device *drm;
+	int ret;
+
+	INIT_LIST_HEAD(&driver->device_list);
+	driver->bus = &drm_host1x_bus;
+
+	drm = kzalloc(sizeof(*drm), GFP_KERNEL);
+	if (!drm)
+		return -ENOMEM;
+
+	drm->dev = &device->dev;
+
+	mutex_lock(&drm_global_mutex);
+
+	ret = drm_fill_in_dev(drm, NULL, driver);
+	if (ret)
+		goto unlock;
+
+	if (drm_core_check_feature(drm, DRIVER_MODESET)) {
+		ret = drm_get_minor(drm, &drm->control, DRM_MINOR_CONTROL);
+		if (ret)
+			goto unlock;
+	}
+
+	if (drm_core_check_feature(drm, DRIVER_RENDER)) {
+		ret = drm_get_minor(drm, &drm->render, DRM_MINOR_RENDER);
+		if (ret)
+			goto put_control;
+	}
+
+	ret = drm_get_minor(drm, &drm->primary, DRM_MINOR_LEGACY);
+	if (ret)
+		goto put_render;
+
+	if (drm->driver->load) {
+		ret = drm->driver->load(drm, 0);
+		if (ret)
+			goto put_primary;
+	}
+
+	/* setup the grouping for the legacy output */
+	if (drm_core_check_feature(drm, DRIVER_MODESET)) {
+		struct drm_mode_group *group = &drm->primary->mode_group;
+
+		ret = drm_mode_group_init_legacy_group(drm, group);
+		if (ret)
+			goto put_primary;
+	}
+
+	list_add_tail(&drm->driver_item, &driver->device_list);
+	mutex_unlock(&drm_global_mutex);
+
+	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;
+
+put_primary:
+	drm_put_minor(&drm->primary);
+put_render:
+	if (drm_core_check_feature(drm, DRIVER_RENDER))
+		drm_put_minor(&drm->render);
+put_control:
+	if (drm_core_check_feature(drm, DRIVER_MODESET))
+		drm_put_minor(&drm->control);
+unlock:
+	mutex_unlock(&drm_global_mutex);
+	kfree(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/host1x/drm/dc.c b/drivers/gpu/host1x/drm/dc.c
index 5106df0..71cbda6 100644
--- a/drivers/gpu/host1x/drm/dc.c
+++ b/drivers/gpu/host1x/drm/dc.c
@@ -11,7 +11,6 @@
 #include <linux/clk/tegra.h>
 #include <linux/debugfs.h>
 
-#include "host1x_client.h"
 #include "dc.h"
 #include "drm.h"
 #include "gem.h"
@@ -1040,28 +1039,28 @@ static int tegra_dc_debugfs_exit(struct tegra_dc *dc)
 
 static int tegra_dc_init(struct host1x_client *client)
 {
-	struct tegra_drm_client *drm = to_tegra_drm_client(client);
-	struct tegra_dc *dc = tegra_drm_client_to_dc(drm);
+	struct tegra_drm *tegra = dev_get_drvdata(client->parent);
+	struct tegra_dc *dc = host1x_client_to_dc(client);
 	int err;
 
-	dc->pipe = drm->drm->mode_config.num_crtc;
+	dc->pipe = tegra->drm->mode_config.num_crtc;
 
-	drm_crtc_init(drm->drm, &dc->base, &tegra_crtc_funcs);
+	drm_crtc_init(tegra->drm, &dc->base, &tegra_crtc_funcs);
 	drm_mode_crtc_set_gamma_size(&dc->base, 256);
 	drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
 
-	err = tegra_dc_rgb_init(drm->drm, dc);
+	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);
 		return err;
 	}
 
-	err = tegra_dc_add_planes(drm->drm, dc);
+	err = tegra_dc_add_planes(tegra->drm, dc);
 	if (err < 0)
 		return err;
 
 	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
-		err = tegra_dc_debugfs_init(dc, drm->drm->primary);
+		err = tegra_dc_debugfs_init(dc, tegra->drm->primary);
 		if (err < 0)
 			dev_err(dc->dev, "debugfs setup failed: %d\n", err);
 	}
@@ -1079,8 +1078,7 @@ static int tegra_dc_init(struct host1x_client *client)
 
 static int tegra_dc_exit(struct host1x_client *client)
 {
-	struct tegra_drm_client *drm = to_tegra_drm_client(client);
-	struct tegra_dc *dc = tegra_drm_client_to_dc(drm);
+	struct tegra_dc *dc = host1x_client_to_dc(client);
 	int err;
 
 	devm_free_irq(dc->dev, dc->irq, dc);
@@ -1107,11 +1105,14 @@ static const struct host1x_client_ops dc_client_ops = {
 
 static int tegra_dc_probe(struct platform_device *pdev)
 {
-	struct tegra_drm *tegra = host1x_get_drm_data(pdev->dev.parent);
+	struct host1x *host1x = dev_get_drvdata(pdev->dev.parent);
 	struct resource *regs;
 	struct tegra_dc *dc;
 	int err;
 
+	if (!host1x)
+		return -EPROBE_DEFER;
+
 	dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL);
 	if (!dc)
 		return -ENOMEM;
@@ -1141,9 +1142,9 @@ static int tegra_dc_probe(struct platform_device *pdev)
 		return -ENXIO;
 	}
 
-	INIT_LIST_HEAD(&dc->client.base.list);
-	dc->client.base.ops = &dc_client_ops;
-	dc->client.base.dev = &pdev->dev;
+	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) {
@@ -1151,7 +1152,7 @@ static int tegra_dc_probe(struct platform_device *pdev)
 		return err;
 	}
 
-	err = host1x_register_client(tegra, &dc->client.base);
+	err = host1x_register_client(host1x, &dc->client);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
 			err);
@@ -1165,11 +1166,11 @@ static int tegra_dc_probe(struct platform_device *pdev)
 
 static int tegra_dc_remove(struct platform_device *pdev)
 {
-	struct tegra_drm *tegra = host1x_get_drm_data(pdev->dev.parent);
+	struct host1x *host1x = dev_get_drvdata(pdev->dev.parent);
 	struct tegra_dc *dc = platform_get_drvdata(pdev);
 	int err;
 
-	err = host1x_unregister_client(tegra, &dc->client.base);
+	err = host1x_unregister_client(host1x, &dc->client);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
 			err);
diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c
index e93caea..f9def3c 100644
--- a/drivers/gpu/host1x/drm/drm.c
+++ b/drivers/gpu/host1x/drm/drm.c
@@ -7,7 +7,8 @@
  * published by the Free Software Foundation.
  */
 
-#include "host1x_client.h"
+#include <linux/host1x.h>
+
 #include "drm.h"
 #include "gem.h"
 
@@ -22,239 +23,25 @@ struct tegra_drm_file {
 	struct list_head contexts;
 };
 
-struct host1x_subdev {
-	struct host1x_client *client;
-	struct device_node *np;
-	struct list_head list;
-};
-
-static int host1x_subdev_add(struct tegra_drm *tegra, 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);
-
-	list_add_tail(&subdev->list, &tegra->subdevs);
-
-	return 0;
-}
-
-static int host1x_subdev_register(struct tegra_drm *tegra,
-				  struct host1x_subdev *subdev,
-				  struct host1x_client *client)
-{
-	mutex_lock(&tegra->subdevs_lock);
-	list_del_init(&subdev->list);
-	list_add_tail(&subdev->list, &tegra->active);
-	subdev->client = client;
-	mutex_unlock(&tegra->subdevs_lock);
-
-	return 0;
-}
-
-static int host1x_subdev_unregister(struct tegra_drm *tegra,
-				    struct host1x_subdev *subdev)
-{
-	mutex_lock(&tegra->subdevs_lock);
-	list_del_init(&subdev->list);
-	mutex_unlock(&tegra->subdevs_lock);
-
-	of_node_put(subdev->np);
-	kfree(subdev);
-
-	return 0;
-}
-
-static int tegra_parse_dt(struct tegra_drm *tegra)
-{
-	static const char * const compat[] = {
-		"nvidia,tegra20-dc",
-		"nvidia,tegra20-hdmi",
-		"nvidia,tegra20-gr2d",
-		"nvidia,tegra30-dc",
-		"nvidia,tegra30-hdmi",
-		"nvidia,tegra30-gr2d",
-	};
-	unsigned int i;
-	int err;
-
-	for (i = 0; i < ARRAY_SIZE(compat); i++) {
-		struct device_node *np;
-
-		for_each_child_of_node(tegra->dev->of_node, np) {
-			if (of_device_is_compatible(np, compat[i]) &&
-			    of_device_is_available(np)) {
-				err = host1x_subdev_add(tegra, np);
-				if (err < 0)
-					return err;
-			}
-		}
-	}
-
-	return 0;
-}
-
-int tegra_drm_alloc(struct platform_device *pdev)
+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;
 	int err;
 
-	tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
+	tegra = kzalloc(sizeof(*tegra), GFP_KERNEL);
 	if (!tegra)
 		return -ENOMEM;
 
-	mutex_init(&tegra->subdevs_lock);
-	INIT_LIST_HEAD(&tegra->subdevs);
-	INIT_LIST_HEAD(&tegra->active);
+	dev_set_drvdata(drm->dev, tegra);
 	mutex_init(&tegra->clients_lock);
 	INIT_LIST_HEAD(&tegra->clients);
-	tegra->dev = &pdev->dev;
-
-	err = tegra_parse_dt(tegra);
-	if (err < 0) {
-		dev_err(&pdev->dev, "failed to parse DT: %d\n", err);
-		return err;
-	}
-
-	host1x_set_drm_data(&pdev->dev, tegra);
-
-	return 0;
-}
-
-int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm)
-{
-	struct host1x_client *client;
-	int err;
-
-	mutex_lock(&tegra->clients_lock);
-
-	list_for_each_entry(client, &tegra->clients, list) {
-		struct tegra_drm_client *tdc = to_tegra_drm_client(client);
-
-		/* associate client with DRM device */
-		tdc->drm = drm;
-
-		if (client->ops && client->ops->init) {
-			err = client->ops->init(client);
-			if (err < 0) {
-				dev_err(tegra->dev,
-					"DRM setup failed for %s: %d\n",
-					dev_name(client->dev), err);
-				mutex_unlock(&tegra->clients_lock);
-				return err;
-			}
-		}
-	}
-
-	mutex_unlock(&tegra->clients_lock);
-
-	return 0;
-}
-
-int tegra_drm_exit(struct tegra_drm *tegra)
-{
-	struct host1x_client *client;
-	struct platform_device *pdev;
-	int err;
-
-	if (!tegra->drm)
-		return 0;
-
-	mutex_lock(&tegra->clients_lock);
-
-	list_for_each_entry_reverse(client, &tegra->clients, list) {
-		if (client->ops && client->ops->exit) {
-			err = client->ops->exit(client);
-			if (err < 0) {
-				dev_err(tegra->dev,
-					"DRM cleanup failed for %s: %d\n",
-					dev_name(client->dev), err);
-				mutex_unlock(&tegra->clients_lock);
-				return err;
-			}
-		}
-	}
-
-	mutex_unlock(&tegra->clients_lock);
-
-	pdev = to_platform_device(tegra->dev);
-	drm_platform_exit(&tegra_drm_driver, pdev);
-	tegra->drm = NULL;
-
-	return 0;
-}
-
-int host1x_register_client(struct tegra_drm *tegra,
-			   struct host1x_client *client)
-{
-	struct host1x_subdev *subdev, *tmp;
-	int err;
-
-	mutex_lock(&tegra->clients_lock);
-	list_add_tail(&client->list, &tegra->clients);
-	mutex_unlock(&tegra->clients_lock);
-
-	list_for_each_entry_safe(subdev, tmp, &tegra->subdevs, list)
-		if (subdev->np == client->dev->of_node)
-			host1x_subdev_register(tegra, subdev, client);
-
-	if (list_empty(&tegra->subdevs)) {
-		struct platform_device *pdev = to_platform_device(tegra->dev);
-
-		err = drm_platform_init(&tegra_drm_driver, pdev);
-		if (err < 0) {
-			dev_err(tegra->dev, "drm_platform_init(): %d\n", err);
-			return err;
-		}
-	}
-
-	return 0;
-}
-
-int host1x_unregister_client(struct tegra_drm *tegra,
-			     struct host1x_client *client)
-{
-	struct host1x_subdev *subdev, *tmp;
-	int err;
-
-	list_for_each_entry_safe(subdev, tmp, &tegra->active, list) {
-		if (subdev->client == client) {
-			err = tegra_drm_exit(tegra);
-			if (err < 0) {
-				dev_err(tegra->dev, "tegra_drm_exit(): %d\n",
-					err);
-				return err;
-			}
-
-			host1x_subdev_unregister(tegra, subdev);
-			break;
-		}
-	}
-
-	mutex_lock(&tegra->clients_lock);
-	list_del_init(&client->list);
-	mutex_unlock(&tegra->clients_lock);
-
-	return 0;
-}
-
-static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
-{
-	struct tegra_drm *tegra;
-	int err;
-
-	tegra = host1x_get_drm_data(drm->dev);
 	drm->dev_private = tegra;
 	tegra->drm = drm;
 
 	drm_mode_config_init(drm);
 
-	err = tegra_drm_init(tegra, drm);
+	err = host1x_device_init(device);
 	if (err < 0)
 		return err;
 
@@ -280,9 +67,16 @@ 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;
+
 	drm_kms_helper_poll_fini(drm);
 	tegra_drm_fb_exit(drm);
 
+	err = host1x_device_exit(device);
+	if (err < 0)
+		return err;
+
 	drm_mode_config_cleanup(drm);
 
 	return 0;
@@ -370,10 +164,11 @@ 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 drm_tegra_syncpt_read *args = data;
-	struct host1x *host = dev_get_drvdata(drm->dev);
-	struct host1x_syncpt *sp = host1x_syncpt_get(host, args->id);
+	struct host1x_syncpt *sp;
 
+	sp = host1x_syncpt_get(host, args->id);
 	if (!sp)
 		return -EINVAL;
 
@@ -384,10 +179,11 @@ 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 drm_tegra_syncpt_incr *args = data;
-	struct host1x *host = dev_get_drvdata(drm->dev);
-	struct host1x_syncpt *sp = host1x_syncpt_get(host, args->id);
+	struct host1x_syncpt *sp;
 
+	sp = host1x_syncpt_get(host1x, args->id);
 	if (!sp)
 		return -EINVAL;
 
@@ -397,10 +193,11 @@ 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 drm_tegra_syncpt_wait *args = data;
-	struct host1x *host = dev_get_drvdata(drm->dev);
-	struct host1x_syncpt *sp = host1x_syncpt_get(host, args->id);
+	struct host1x_syncpt *sp;
 
+	sp = host1x_syncpt_get(host1x, args->id);
 	if (!sp)
 		return -EINVAL;
 
@@ -422,7 +219,7 @@ static int tegra_open_channel(struct drm_device *drm, void *data,
 	if (!context)
 		return -ENOMEM;
 
-	list_for_each_entry(client, &tegra->clients, base.list)
+	list_for_each_entry(client, &tegra->clients, list)
 		if (client->base.class == args->client) {
 			err = client->ops->open_channel(client, context);
 			if (err)
@@ -441,8 +238,8 @@ static int tegra_open_channel(struct drm_device *drm, void *data,
 static int tegra_close_channel(struct drm_device *drm, void *data,
 			       struct drm_file *file)
 {
-	struct drm_tegra_close_channel *args = data;
 	struct tegra_drm_file *fpriv = file->driver_priv;
+	struct drm_tegra_close_channel *args = data;
 	struct tegra_drm_context *context;
 
 	context = tegra_drm_get_context(args->context);
@@ -652,3 +449,97 @@ struct drm_driver tegra_drm_driver = {
 	.minor = DRIVER_MINOR,
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
+
+int tegra_drm_register_client(struct tegra_drm *tegra,
+			      struct tegra_drm_client *client)
+{
+	mutex_lock(&tegra->clients_lock);
+	list_add_tail(&client->list, &tegra->clients);
+	mutex_unlock(&tegra->clients_lock);
+
+	return 0;
+}
+
+int tegra_drm_unregister_client(struct tegra_drm *tegra,
+				struct tegra_drm_client *client)
+{
+	mutex_lock(&tegra->clients_lock);
+	list_del_init(&client->list);
+	mutex_unlock(&tegra->clients_lock);
+
+	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[] = {
+	{ .compatible = "nvidia,tegra20-dc", },
+	{ .compatible = "nvidia,tegra20-hdmi", },
+	{ .compatible = "nvidia,tegra20-gr2d", },
+	{ .compatible = "nvidia,tegra30-dc", },
+	{ .compatible = "nvidia,tegra30-hdmi", },
+	{ .compatible = "nvidia,tegra30-gr2d", },
+	{ /* sentinel */ }
+};
+
+static struct host1x_driver host1x_drm_driver = {
+	.name = "drm",
+	.probe = host1x_drm_probe,
+	.remove = host1x_drm_remove,
+	.subdevs = host1x_drm_subdevs,
+};
+
+static int __init host1x_drm_init(void)
+{
+	int err;
+
+	err = host1x_driver_register(&host1x_drm_driver);
+	if (err < 0)
+		return err;
+
+	err = platform_driver_register(&tegra_dc_driver);
+	if (err < 0)
+		goto unregister_host1x;
+
+	err = platform_driver_register(&tegra_hdmi_driver);
+	if (err < 0)
+		goto unregister_dc;
+
+	err = platform_driver_register(&tegra_gr2d_driver);
+	if (err < 0)
+		goto unregister_hdmi;
+
+	return 0;
+
+unregister_hdmi:
+	platform_driver_unregister(&tegra_hdmi_driver);
+unregister_dc:
+	platform_driver_unregister(&tegra_dc_driver);
+unregister_host1x:
+	host1x_driver_unregister(&host1x_drm_driver);
+	return err;
+}
+module_init(host1x_drm_init);
+
+static void __exit host1x_drm_exit(void)
+{
+	platform_driver_unregister(&tegra_gr2d_driver);
+	platform_driver_unregister(&tegra_hdmi_driver);
+	platform_driver_unregister(&tegra_dc_driver);
+	host1x_driver_unregister(&host1x_drm_driver);
+}
+module_exit(host1x_drm_exit);
+
+MODULE_AUTHOR("Thierry Reding <thierry.reding-RM9K5IK7kjKj5M59NBduVrNAH6kLmebB@public.gmane.org>");
+MODULE_DESCRIPTION("NVIDIA Tegra DRM driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/host1x/drm/drm.h b/drivers/gpu/host1x/drm/drm.h
index 8c26c6b..25522e2 100644
--- a/drivers/gpu/host1x/drm/drm.h
+++ b/drivers/gpu/host1x/drm/drm.h
@@ -32,11 +32,6 @@ struct tegra_fbdev {
 
 struct tegra_drm {
 	struct drm_device *drm;
-	struct device *dev;
-
-	struct mutex subdevs_lock;
-	struct list_head subdevs;
-	struct list_head active;
 
 	struct mutex clients_lock;
 	struct list_head clients;
@@ -63,29 +58,29 @@ struct tegra_drm_client_ops {
 
 struct tegra_drm_client {
 	struct host1x_client base;
-	struct drm_device *drm;
+	struct list_head list;
 
 	const struct tegra_drm_client_ops *ops;
 };
 
 static inline struct tegra_drm_client *
-to_tegra_drm_client(struct host1x_client *client)
+host1x_to_drm_client(struct host1x_client *client)
 {
 	return container_of(client, struct tegra_drm_client, base);
 }
 
+extern int tegra_drm_register_client(struct tegra_drm *tegra,
+				     struct tegra_drm_client *client);
+extern int tegra_drm_unregister_client(struct tegra_drm *tegra,
+				       struct tegra_drm_client *client);
+
 extern int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
 extern int tegra_drm_exit(struct tegra_drm *tegra);
 
-extern int host1x_register_client(struct tegra_drm *tegra,
-				  struct host1x_client *client);
-extern int host1x_unregister_client(struct tegra_drm *tegra,
-				    struct host1x_client *client);
-
 struct tegra_output;
 
 struct tegra_dc {
-	struct tegra_drm_client client;
+	struct host1x_client client;
 	struct device *dev;
 	spinlock_t lock;
 
@@ -109,7 +104,7 @@ struct tegra_dc {
 };
 
 static inline struct tegra_dc *
-tegra_drm_client_to_dc(struct tegra_drm_client *client)
+host1x_client_to_dc(struct host1x_client *client)
 {
 	return container_of(client, struct tegra_dc, client);
 }
@@ -235,6 +230,10 @@ 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 */
 extern int tegra_dc_rgb_probe(struct tegra_dc *dc);
 extern int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc);
@@ -252,6 +251,8 @@ extern int tegra_drm_fb_init(struct drm_device *drm);
 extern void tegra_drm_fb_exit(struct drm_device *drm);
 extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
 
-extern struct drm_driver tegra_drm_driver;
+extern struct platform_driver tegra_dc_driver;
+extern struct platform_driver tegra_hdmi_driver;
+extern struct platform_driver tegra_gr2d_driver;
 
 #endif /* HOST1X_DRM_H */
diff --git a/drivers/gpu/host1x/drm/gr2d.c b/drivers/gpu/host1x/drm/gr2d.c
index a16aaa8..9588072 100644
--- a/drivers/gpu/host1x/drm/gr2d.c
+++ b/drivers/gpu/host1x/drm/gr2d.c
@@ -16,7 +16,6 @@
 
 #include <linux/clk.h>
 
-#include "host1x_client.h"
 #include "drm.h"
 #include "gem.h"
 
@@ -31,19 +30,25 @@ static inline struct gr2d *to_gr2d(struct tegra_drm_client *client)
 	return container_of(client, struct gr2d, client);
 }
 
-static int gr2d_client_init(struct host1x_client *client)
+static int gr2d_init(struct host1x_client *client)
 {
-	return 0;
+	struct tegra_drm_client *drm = host1x_to_drm_client(client);
+	struct tegra_drm *tegra = dev_get_drvdata(client->parent);
+
+	return tegra_drm_register_client(tegra, drm);
 }
 
-static int gr2d_client_exit(struct host1x_client *client)
+static int gr2d_exit(struct host1x_client *client)
 {
-	return 0;
+	struct tegra_drm_client *drm = host1x_to_drm_client(client);
+	struct tegra_drm *tegra = dev_get_drvdata(client->parent);
+
+	return tegra_drm_unregister_client(tegra, drm);
 }
 
 static const struct host1x_client_ops gr2d_client_ops = {
-	.init = gr2d_client_init,
-	.exit = gr2d_client_exit,
+	.init = gr2d_init,
+	.exit = gr2d_exit,
 };
 
 static int gr2d_open_channel(struct tegra_drm_client *client,
@@ -234,12 +239,15 @@ static const struct of_device_id gr2d_match[] = {
 
 static int gr2d_probe(struct platform_device *pdev)
 {
-	struct tegra_drm *tegra = host1x_get_drm_data(pdev->dev.parent);
+	struct host1x *host1x = dev_get_drvdata(pdev->dev.parent);
 	struct device *dev = &pdev->dev;
 	struct host1x_syncpt **syncpts;
 	struct gr2d *gr2d;
 	int err;
 
+	if (!host1x)
+		return -EPROBE_DEFER;
+
 	gr2d = devm_kzalloc(dev, sizeof(*gr2d), GFP_KERNEL);
 	if (!gr2d)
 		return -ENOMEM;
@@ -276,9 +284,11 @@ static int gr2d_probe(struct platform_device *pdev)
 	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.ops = &gr2d_ops;
 
-	err = host1x_register_client(tegra, &gr2d->client.base);
+	err = host1x_register_client(host1x, &gr2d->client.base);
 	if (err < 0) {
 		dev_err(dev, "failed to register host1x client: %d\n", err);
 		return err;
@@ -291,12 +301,12 @@ static int gr2d_probe(struct platform_device *pdev)
 
 static int gr2d_remove(struct platform_device *pdev)
 {
-	struct tegra_drm *tegra = host1x_get_drm_data(pdev->dev.parent);
+	struct host1x *host1x = dev_get_drvdata(pdev->dev.parent);
 	struct gr2d *gr2d = platform_get_drvdata(pdev);
 	unsigned int i;
 	int err;
 
-	err = host1x_unregister_client(tegra, &gr2d->client.base);
+	err = host1x_unregister_client(host1x, &gr2d->client.base);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
 			err);
diff --git a/drivers/gpu/host1x/drm/hdmi.c b/drivers/gpu/host1x/drm/hdmi.c
index a237004..4489d56 100644
--- a/drivers/gpu/host1x/drm/hdmi.c
+++ b/drivers/gpu/host1x/drm/hdmi.c
@@ -13,13 +13,12 @@
 #include <linux/hdmi.h>
 #include <linux/regulator/consumer.h>
 
-#include "host1x_client.h"
 #include "hdmi.h"
 #include "drm.h"
 #include "dc.h"
 
 struct tegra_hdmi {
-	struct tegra_drm_client client;
+	struct host1x_client client;
 	struct tegra_output output;
 	struct device *dev;
 
@@ -43,7 +42,7 @@ struct tegra_hdmi {
 };
 
 static inline struct tegra_hdmi *
-tegra_drm_client_to_hdmi(struct tegra_drm_client *client)
+host1x_client_to_hdmi(struct host1x_client *client)
 {
 	return container_of(client, struct tegra_hdmi, client);
 }
@@ -1118,22 +1117,22 @@ static int tegra_hdmi_debugfs_exit(struct tegra_hdmi *hdmi)
 
 static int tegra_hdmi_init(struct host1x_client *client)
 {
-	struct tegra_drm_client *drm = to_tegra_drm_client(client);
-	struct tegra_hdmi *hdmi = tegra_drm_client_to_hdmi(drm);
+	struct tegra_drm *tegra = dev_get_drvdata(client->parent);
+	struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
 	int err;
 
 	hdmi->output.type = TEGRA_OUTPUT_HDMI;
 	hdmi->output.dev = client->dev;
 	hdmi->output.ops = &hdmi_ops;
 
-	err = tegra_output_init(drm->drm, &hdmi->output);
+	err = tegra_output_init(tegra->drm, &hdmi->output);
 	if (err < 0) {
 		dev_err(client->dev, "output setup failed: %d\n", err);
 		return err;
 	}
 
 	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
-		err = tegra_hdmi_debugfs_init(hdmi, drm->drm->primary);
+		err = tegra_hdmi_debugfs_init(hdmi, tegra->drm->primary);
 		if (err < 0)
 			dev_err(client->dev, "debugfs setup failed: %d\n", err);
 	}
@@ -1143,8 +1142,7 @@ static int tegra_hdmi_init(struct host1x_client *client)
 
 static int tegra_hdmi_exit(struct host1x_client *client)
 {
-	struct tegra_drm_client *drm = to_tegra_drm_client(client);
-	struct tegra_hdmi *hdmi = tegra_drm_client_to_hdmi(drm);
+	struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
 	int err;
 
 	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
@@ -1176,11 +1174,14 @@ static const struct host1x_client_ops hdmi_client_ops = {
 
 static int tegra_hdmi_probe(struct platform_device *pdev)
 {
-	struct tegra_drm *tegra = host1x_get_drm_data(pdev->dev.parent);
+	struct host1x *host1x = dev_get_drvdata(pdev->dev.parent);
 	struct tegra_hdmi *hdmi;
 	struct resource *regs;
 	int err;
 
+	if (!host1x)
+		return -EPROBE_DEFER;
+
 	hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
 	if (!hdmi)
 		return -ENOMEM;
@@ -1247,11 +1248,11 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
 
 	hdmi->irq = err;
 
-	INIT_LIST_HEAD(&hdmi->client.base.list);
-	hdmi->client.base.ops = &hdmi_client_ops;
-	hdmi->client.base.dev = &pdev->dev;
+	INIT_LIST_HEAD(&hdmi->client.list);
+	hdmi->client.ops = &hdmi_client_ops;
+	hdmi->client.dev = &pdev->dev;
 
-	err = host1x_register_client(tegra, &hdmi->client.base);
+	err = host1x_register_client(host1x, &hdmi->client);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
 			err);
@@ -1265,11 +1266,11 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
 
 static int tegra_hdmi_remove(struct platform_device *pdev)
 {
-	struct tegra_drm *tegra = host1x_get_drm_data(pdev->dev.parent);
+	struct host1x *host1x = dev_get_drvdata(pdev->dev.parent);
 	struct tegra_hdmi *hdmi = platform_get_drvdata(pdev);
 	int err;
 
-	err = host1x_unregister_client(tegra, &hdmi->client.base);
+	err = host1x_unregister_client(host1x, &hdmi->client);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
 			err);
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index c65f496..ec4cb60 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -150,6 +150,7 @@ int drm_err(const char *func, const char *format, ...);
 #define DRIVER_BUS_PCI 0x1
 #define DRIVER_BUS_PLATFORM 0x2
 #define DRIVER_BUS_USB 0x3
+#define DRIVER_BUS_HOST1X 0x4
 
 /***********************************************************************/
 /** \name Begin the DRM... */
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index 7442f2a..a091792 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -19,7 +19,7 @@
 #ifndef __LINUX_HOST1X_H
 #define __LINUX_HOST1X_H
 
-#include <linux/kref.h>
+#include <linux/device.h>
 #include <linux/types.h>
 
 enum host1x_class {
@@ -37,6 +37,7 @@ struct host1x_client_ops {
 
 struct host1x_client {
 	struct list_head list;
+	struct device *parent;
 	struct device *dev;
 
 	const struct host1x_client_ops *ops;
@@ -230,4 +231,46 @@ 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 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_register_client(struct host1x *host1x, struct host1x_client *client);
+int host1x_unregister_client(struct host1x *host1x,
+			     struct host1x_client *client);
+
 #endif
-- 
1.8.4

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

* [PATCH v2 14/27] drm/tegra: Move driver to DRM tree
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (12 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 13/27] drm/tegra: Move subdevice infrastructure to host1x Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
       [not found]     ` <1381134884-5816-15-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2013-10-07  8:34   ` [PATCH v2 15/27] gpu: host1x: Add support for Tegra114 Thierry Reding
                     ` (12 subsequent siblings)
  26 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

In order to subsystem-wide changes easier, move the Tegra DRM driver
back into the DRM tree.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 MAINTAINERS                                    |  1 +
 drivers/gpu/drm/Kconfig                        |  2 ++
 drivers/gpu/drm/Makefile                       |  1 +
 drivers/gpu/{host1x/drm => drm/tegra}/Kconfig  | 10 +++++-----
 drivers/gpu/drm/tegra/Makefile                 | 15 +++++++++++++++
 drivers/gpu/{host1x/drm => drm/tegra}/bus.c    |  0
 drivers/gpu/{host1x/drm => drm/tegra}/dc.c     |  0
 drivers/gpu/{host1x/drm => drm/tegra}/dc.h     |  0
 drivers/gpu/{host1x/drm => drm/tegra}/drm.c    |  0
 drivers/gpu/{host1x/drm => drm/tegra}/drm.h    |  0
 drivers/gpu/{host1x/drm => drm/tegra}/fb.c     |  0
 drivers/gpu/{host1x/drm => drm/tegra}/gem.c    |  0
 drivers/gpu/{host1x/drm => drm/tegra}/gem.h    |  0
 drivers/gpu/{host1x/drm => drm/tegra}/gr2d.c   |  0
 drivers/gpu/{host1x/drm => drm/tegra}/hdmi.c   |  0
 drivers/gpu/{host1x/drm => drm/tegra}/hdmi.h   |  0
 drivers/gpu/{host1x/drm => drm/tegra}/output.c |  0
 drivers/gpu/{host1x/drm => drm/tegra}/rgb.c    |  0
 drivers/gpu/host1x/Kconfig                     |  2 --
 drivers/gpu/host1x/Makefile                    |  8 --------
 drivers/video/Kconfig                          |  4 ++--
 21 files changed, 26 insertions(+), 17 deletions(-)
 rename drivers/gpu/{host1x/drm => drm/tegra}/Kconfig (100%)
 create mode 100644 drivers/gpu/drm/tegra/Makefile
 rename drivers/gpu/{host1x/drm => drm/tegra}/bus.c (100%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/dc.c (100%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/dc.h (100%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/drm.c (100%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/drm.h (100%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/fb.c (100%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/gem.c (100%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/gem.h (100%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/gr2d.c (100%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/hdmi.c (100%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/hdmi.h (100%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/output.c (100%)
 rename drivers/gpu/{host1x/drm => drm/tegra}/rgb.c (100%)

diff --git a/MAINTAINERS b/MAINTAINERS
index a1a4c7c..26ff91a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2811,6 +2811,7 @@ L:	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
 L:	linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
 T:	git git://anongit.freedesktop.org/tegra/linux.git
 S:	Supported
+F:	drivers/gpu/drm/tegra/
 F:	drivers/gpu/host1x/
 F:	include/linux/host1x.h
 F:	include/uapi/drm/tegra_drm.h
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 955555d..290e2ac 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -236,3 +236,5 @@ source "drivers/gpu/drm/tilcdc/Kconfig"
 source "drivers/gpu/drm/qxl/Kconfig"
 
 source "drivers/gpu/drm/msm/Kconfig"
+
+source "drivers/gpu/drm/tegra/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index f089adf..e39cd03 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -55,4 +55,5 @@ obj-$(CONFIG_DRM_OMAP)	+= omapdrm/
 obj-$(CONFIG_DRM_TILCDC)	+= tilcdc/
 obj-$(CONFIG_DRM_QXL) += qxl/
 obj-$(CONFIG_DRM_MSM) += msm/
+obj-$(CONFIG_DRM_TEGRA) += tegra/
 obj-y			+= i2c/
diff --git a/drivers/gpu/host1x/drm/Kconfig b/drivers/gpu/drm/tegra/Kconfig
similarity index 100%
rename from drivers/gpu/host1x/drm/Kconfig
rename to drivers/gpu/drm/tegra/Kconfig
index 69853a4..7759eea 100644
--- a/drivers/gpu/host1x/drm/Kconfig
+++ b/drivers/gpu/drm/tegra/Kconfig
@@ -13,6 +13,11 @@ config DRM_TEGRA
 
 if DRM_TEGRA
 
+config DRM_TEGRA_DEBUG
+	bool "NVIDIA Tegra DRM debug support"
+	help
+	  Say yes here to enable debugging support.
+
 config DRM_TEGRA_STAGING
 	bool "Enable HOST1X interface"
 	depends on STAGING
@@ -21,9 +26,4 @@ config DRM_TEGRA_STAGING
 
 	  If unsure, choose N.
 
-config DRM_TEGRA_DEBUG
-	bool "NVIDIA Tegra DRM debug support"
-	help
-	  Say yes here to enable debugging support.
-
 endif
diff --git a/drivers/gpu/drm/tegra/Makefile b/drivers/gpu/drm/tegra/Makefile
new file mode 100644
index 0000000..abb267c
--- /dev/null
+++ b/drivers/gpu/drm/tegra/Makefile
@@ -0,0 +1,15 @@
+ccflags-y += -Iinclude/drm
+ccflags-$(CONFIG_DRM_TEGRA_DEBUG) += -DDEBUG
+
+tegra-drm-y := \
+	bus.o \
+	drm.o \
+	gem.o \
+	fb.o \
+	dc.o \
+	output.o \
+	rgb.o \
+	hdmi.o \
+	gr2d.o
+
+obj-$(CONFIG_DRM_TEGRA) += tegra-drm.o
diff --git a/drivers/gpu/host1x/drm/bus.c b/drivers/gpu/drm/tegra/bus.c
similarity index 100%
rename from drivers/gpu/host1x/drm/bus.c
rename to drivers/gpu/drm/tegra/bus.c
diff --git a/drivers/gpu/host1x/drm/dc.c b/drivers/gpu/drm/tegra/dc.c
similarity index 100%
rename from drivers/gpu/host1x/drm/dc.c
rename to drivers/gpu/drm/tegra/dc.c
diff --git a/drivers/gpu/host1x/drm/dc.h b/drivers/gpu/drm/tegra/dc.h
similarity index 100%
rename from drivers/gpu/host1x/drm/dc.h
rename to drivers/gpu/drm/tegra/dc.h
diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/drm/tegra/drm.c
similarity index 100%
rename from drivers/gpu/host1x/drm/drm.c
rename to drivers/gpu/drm/tegra/drm.c
diff --git a/drivers/gpu/host1x/drm/drm.h b/drivers/gpu/drm/tegra/drm.h
similarity index 100%
rename from drivers/gpu/host1x/drm/drm.h
rename to drivers/gpu/drm/tegra/drm.h
diff --git a/drivers/gpu/host1x/drm/fb.c b/drivers/gpu/drm/tegra/fb.c
similarity index 100%
rename from drivers/gpu/host1x/drm/fb.c
rename to drivers/gpu/drm/tegra/fb.c
diff --git a/drivers/gpu/host1x/drm/gem.c b/drivers/gpu/drm/tegra/gem.c
similarity index 100%
rename from drivers/gpu/host1x/drm/gem.c
rename to drivers/gpu/drm/tegra/gem.c
diff --git a/drivers/gpu/host1x/drm/gem.h b/drivers/gpu/drm/tegra/gem.h
similarity index 100%
rename from drivers/gpu/host1x/drm/gem.h
rename to drivers/gpu/drm/tegra/gem.h
diff --git a/drivers/gpu/host1x/drm/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
similarity index 100%
rename from drivers/gpu/host1x/drm/gr2d.c
rename to drivers/gpu/drm/tegra/gr2d.c
diff --git a/drivers/gpu/host1x/drm/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
similarity index 100%
rename from drivers/gpu/host1x/drm/hdmi.c
rename to drivers/gpu/drm/tegra/hdmi.c
diff --git a/drivers/gpu/host1x/drm/hdmi.h b/drivers/gpu/drm/tegra/hdmi.h
similarity index 100%
rename from drivers/gpu/host1x/drm/hdmi.h
rename to drivers/gpu/drm/tegra/hdmi.h
diff --git a/drivers/gpu/host1x/drm/output.c b/drivers/gpu/drm/tegra/output.c
similarity index 100%
rename from drivers/gpu/host1x/drm/output.c
rename to drivers/gpu/drm/tegra/output.c
diff --git a/drivers/gpu/host1x/drm/rgb.c b/drivers/gpu/drm/tegra/rgb.c
similarity index 100%
rename from drivers/gpu/host1x/drm/rgb.c
rename to drivers/gpu/drm/tegra/rgb.c
diff --git a/drivers/gpu/host1x/Kconfig b/drivers/gpu/host1x/Kconfig
index ccfd42b..7d6bed2 100644
--- a/drivers/gpu/host1x/Kconfig
+++ b/drivers/gpu/host1x/Kconfig
@@ -19,6 +19,4 @@ config TEGRA_HOST1X_FIREWALL
 
 	  If unsure, choose Y.
 
-source "drivers/gpu/host1x/drm/Kconfig"
-
 endif
diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index 616fe82..889217c 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -9,12 +9,4 @@ host1x-y = \
 	debug.o \
 	hw/host1x01.o
 
-ccflags-y += -Iinclude/drm
-ccflags-$(CONFIG_DRM_TEGRA_DEBUG) += -DDEBUG
-
-host1x-$(CONFIG_DRM_TEGRA) += drm/drm.o drm/fb.o drm/dc.o
-host1x-$(CONFIG_DRM_TEGRA) += drm/output.o drm/rgb.o drm/hdmi.o
-host1x-$(CONFIG_DRM_TEGRA) += drm/gem.o
-host1x-$(CONFIG_DRM_TEGRA) += drm/gr2d.o
-host1x-$(CONFIG_DRM_TEGRA) += drm/bus.o
 obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 14317b7..4f2e1b3 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -19,10 +19,10 @@ source "drivers/char/agp/Kconfig"
 
 source "drivers/gpu/vga/Kconfig"
 
-source "drivers/gpu/drm/Kconfig"
-
 source "drivers/gpu/host1x/Kconfig"
 
+source "drivers/gpu/drm/Kconfig"
+
 config VGASTATE
        tristate
        default n
-- 
1.8.4

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

* [PATCH v2 15/27] gpu: host1x: Add support for Tegra114
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (13 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 14/27] drm/tegra: Move driver to DRM tree Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
       [not found]     ` <1381134884-5816-16-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2013-10-07  8:34   ` [PATCH v2 16/27] drm/tegra: Add Tegra114 display controller support Thierry Reding
                     ` (11 subsequent siblings)
  26 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

Tegra114 uses a slightly updated version of host1x with an additional
syncpoint.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
Changes in v2:
- fix register fields changed from host1x01

 drivers/gpu/host1x/Makefile                 |   3 +-
 drivers/gpu/host1x/dev.c                    |  11 ++
 drivers/gpu/host1x/hw/host1x02.c            |  42 +++++
 drivers/gpu/host1x/hw/host1x02.h            |  26 +++
 drivers/gpu/host1x/hw/hw_host1x02_channel.h | 121 ++++++++++++++
 drivers/gpu/host1x/hw/hw_host1x02_sync.h    | 243 ++++++++++++++++++++++++++++
 drivers/gpu/host1x/hw/hw_host1x02_uclass.h  | 175 ++++++++++++++++++++
 7 files changed, 620 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/host1x/hw/host1x02.c
 create mode 100644 drivers/gpu/host1x/hw/host1x02.h
 create mode 100644 drivers/gpu/host1x/hw/hw_host1x02_channel.h
 create mode 100644 drivers/gpu/host1x/hw/hw_host1x02_sync.h
 create mode 100644 drivers/gpu/host1x/hw/hw_host1x02_uclass.h

diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index 889217c..afa1e9e 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -7,6 +7,7 @@ host1x-y = \
 	channel.o \
 	job.o \
 	debug.o \
-	hw/host1x01.o
+	hw/host1x01.o \
+	hw/host1x02.o
 
 obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index de0fd55..ab402a5 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -33,6 +33,7 @@
 #include "channel.h"
 #include "debug.h"
 #include "hw/host1x01.h"
+#include "hw/host1x02.h"
 
 void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r)
 {
@@ -67,7 +68,17 @@ static const struct host1x_info host1x01_info = {
 	.sync_offset	= 0x3000,
 };
 
+static const struct host1x_info host1x02_info = {
+	.nb_channels = 9,
+	.nb_pts = 32,
+	.nb_mlocks = 16,
+	.nb_bases = 12,
+	.init = host1x02_init,
+	.sync_offset = 0x3000,
+};
+
 static struct of_device_id host1x_of_match[] = {
+	{ .compatible = "nvidia,tegra114-host1x", .data = &host1x02_info, },
 	{ .compatible = "nvidia,tegra30-host1x", .data = &host1x01_info, },
 	{ .compatible = "nvidia,tegra20-host1x", .data = &host1x01_info, },
 	{ },
diff --git a/drivers/gpu/host1x/hw/host1x02.c b/drivers/gpu/host1x/hw/host1x02.c
new file mode 100644
index 0000000..52c0467
--- /dev/null
+++ b/drivers/gpu/host1x/hw/host1x02.c
@@ -0,0 +1,42 @@
+/*
+ * Host1x init for Tegra114 SoCs
+ *
+ * Copyright (c) 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 hw specification */
+#include "hw/host1x01.h"
+#include "hw/host1x01_hardware.h"
+
+/* include code */
+#include "hw/cdma_hw.c"
+#include "hw/channel_hw.c"
+#include "hw/debug_hw.c"
+#include "hw/intr_hw.c"
+#include "hw/syncpt_hw.c"
+
+#include "dev.h"
+
+int host1x02_init(struct host1x *host)
+{
+	host->channel_op = &host1x_channel_ops;
+	host->cdma_op = &host1x_cdma_ops;
+	host->cdma_pb_op = &host1x_pushbuffer_ops;
+	host->syncpt_op = &host1x_syncpt_ops;
+	host->intr_op = &host1x_intr_ops;
+	host->debug_op = &host1x_debug_ops;
+
+	return 0;
+}
diff --git a/drivers/gpu/host1x/hw/host1x02.h b/drivers/gpu/host1x/hw/host1x02.h
new file mode 100644
index 0000000..f748660
--- /dev/null
+++ b/drivers/gpu/host1x/hw/host1x02.h
@@ -0,0 +1,26 @@
+/*
+ * Host1x init for Tegra114 SoCs
+ *
+ * Copyright (c) 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_HOST1X02_H
+#define HOST1X_HOST1X02_H
+
+struct host1x;
+
+int host1x02_init(struct host1x *host);
+
+#endif
diff --git a/drivers/gpu/host1x/hw/hw_host1x02_channel.h b/drivers/gpu/host1x/hw/hw_host1x02_channel.h
new file mode 100644
index 0000000..e490bcd
--- /dev/null
+++ b/drivers/gpu/host1x/hw/hw_host1x02_channel.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 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/>.
+ *
+ */
+
+ /*
+  * Function naming determines intended use:
+  *
+  *     <x>_r(void) : Returns the offset for register <x>.
+  *
+  *     <x>_w(void) : Returns the word offset for word (4 byte) element <x>.
+  *
+  *     <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits.
+  *
+  *     <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted
+  *         and masked to place it at field <y> of register <x>.  This value
+  *         can be |'d with others to produce a full register value for
+  *         register <x>.
+  *
+  *     <x>_<y>_m(void) : Returns a mask for field <y> of register <x>.  This
+  *         value can be ~'d and then &'d to clear the value of field <y> for
+  *         register <x>.
+  *
+  *     <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted
+  *         to place it at field <y> of register <x>.  This value can be |'d
+  *         with others to produce a full register value for <x>.
+  *
+  *     <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register
+  *         <x> value 'r' after being shifted to place its LSB at bit 0.
+  *         This value is suitable for direct comparison with other unshifted
+  *         values appropriate for use in field <y> of register <x>.
+  *
+  *     <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for
+  *         field <y> of register <x>.  This value is suitable for direct
+  *         comparison with unshifted values appropriate for use in field <y>
+  *         of register <x>.
+  */
+
+#ifndef HOST1X_HW_HOST1X02_CHANNEL_H
+#define HOST1X_HW_HOST1X02_CHANNEL_H
+
+static inline u32 host1x_channel_fifostat_r(void)
+{
+	return 0x0;
+}
+#define HOST1X_CHANNEL_FIFOSTAT \
+	host1x_channel_fifostat_r()
+static inline u32 host1x_channel_fifostat_cfempty_v(u32 r)
+{
+	return (r >> 11) & 0x1;
+}
+#define HOST1X_CHANNEL_FIFOSTAT_CFEMPTY_V(r) \
+	host1x_channel_fifostat_cfempty_v(r)
+static inline u32 host1x_channel_dmastart_r(void)
+{
+	return 0x14;
+}
+#define HOST1X_CHANNEL_DMASTART \
+	host1x_channel_dmastart_r()
+static inline u32 host1x_channel_dmaput_r(void)
+{
+	return 0x18;
+}
+#define HOST1X_CHANNEL_DMAPUT \
+	host1x_channel_dmaput_r()
+static inline u32 host1x_channel_dmaget_r(void)
+{
+	return 0x1c;
+}
+#define HOST1X_CHANNEL_DMAGET \
+	host1x_channel_dmaget_r()
+static inline u32 host1x_channel_dmaend_r(void)
+{
+	return 0x20;
+}
+#define HOST1X_CHANNEL_DMAEND \
+	host1x_channel_dmaend_r()
+static inline u32 host1x_channel_dmactrl_r(void)
+{
+	return 0x24;
+}
+#define HOST1X_CHANNEL_DMACTRL \
+	host1x_channel_dmactrl_r()
+static inline u32 host1x_channel_dmactrl_dmastop(void)
+{
+	return 1 << 0;
+}
+#define HOST1X_CHANNEL_DMACTRL_DMASTOP \
+	host1x_channel_dmactrl_dmastop()
+static inline u32 host1x_channel_dmactrl_dmastop_v(u32 r)
+{
+	return (r >> 0) & 0x1;
+}
+#define HOST1X_CHANNEL_DMACTRL_DMASTOP_V(r) \
+	host1x_channel_dmactrl_dmastop_v(r)
+static inline u32 host1x_channel_dmactrl_dmagetrst(void)
+{
+	return 1 << 1;
+}
+#define HOST1X_CHANNEL_DMACTRL_DMAGETRST \
+	host1x_channel_dmactrl_dmagetrst()
+static inline u32 host1x_channel_dmactrl_dmainitget(void)
+{
+	return 1 << 2;
+}
+#define HOST1X_CHANNEL_DMACTRL_DMAINITGET \
+	host1x_channel_dmactrl_dmainitget()
+
+#endif
diff --git a/drivers/gpu/host1x/hw/hw_host1x02_sync.h b/drivers/gpu/host1x/hw/hw_host1x02_sync.h
new file mode 100644
index 0000000..4495401
--- /dev/null
+++ b/drivers/gpu/host1x/hw/hw_host1x02_sync.h
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 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/>.
+ *
+ */
+
+ /*
+  * Function naming determines intended use:
+  *
+  *     <x>_r(void) : Returns the offset for register <x>.
+  *
+  *     <x>_w(void) : Returns the word offset for word (4 byte) element <x>.
+  *
+  *     <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits.
+  *
+  *     <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted
+  *         and masked to place it at field <y> of register <x>.  This value
+  *         can be |'d with others to produce a full register value for
+  *         register <x>.
+  *
+  *     <x>_<y>_m(void) : Returns a mask for field <y> of register <x>.  This
+  *         value can be ~'d and then &'d to clear the value of field <y> for
+  *         register <x>.
+  *
+  *     <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted
+  *         to place it at field <y> of register <x>.  This value can be |'d
+  *         with others to produce a full register value for <x>.
+  *
+  *     <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register
+  *         <x> value 'r' after being shifted to place its LSB at bit 0.
+  *         This value is suitable for direct comparison with other unshifted
+  *         values appropriate for use in field <y> of register <x>.
+  *
+  *     <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for
+  *         field <y> of register <x>.  This value is suitable for direct
+  *         comparison with unshifted values appropriate for use in field <y>
+  *         of register <x>.
+  */
+
+#ifndef HOST1X_HW_HOST1X02_SYNC_H
+#define HOST1X_HW_HOST1X02_SYNC_H
+
+#define REGISTER_STRIDE	4
+
+static inline u32 host1x_sync_syncpt_r(unsigned int id)
+{
+	return 0x400 + id * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_SYNCPT(id) \
+	host1x_sync_syncpt_r(id)
+static inline u32 host1x_sync_syncpt_thresh_cpu0_int_status_r(unsigned int id)
+{
+	return 0x40 + id * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(id) \
+	host1x_sync_syncpt_thresh_cpu0_int_status_r(id)
+static inline u32 host1x_sync_syncpt_thresh_int_disable_r(unsigned int id)
+{
+	return 0x60 + id * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(id) \
+	host1x_sync_syncpt_thresh_int_disable_r(id)
+static inline u32 host1x_sync_syncpt_thresh_int_enable_cpu0_r(unsigned int id)
+{
+	return 0x68 + id * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_SYNCPT_THRESH_INT_ENABLE_CPU0(id) \
+	host1x_sync_syncpt_thresh_int_enable_cpu0_r(id)
+static inline u32 host1x_sync_cf_setup_r(unsigned int channel)
+{
+	return 0x80 + channel * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_CF_SETUP(channel) \
+	host1x_sync_cf_setup_r(channel)
+static inline u32 host1x_sync_cf_setup_base_v(u32 r)
+{
+	return (r >> 0) & 0x3ff;
+}
+#define HOST1X_SYNC_CF_SETUP_BASE_V(r) \
+	host1x_sync_cf_setup_base_v(r)
+static inline u32 host1x_sync_cf_setup_limit_v(u32 r)
+{
+	return (r >> 16) & 0x3ff;
+}
+#define HOST1X_SYNC_CF_SETUP_LIMIT_V(r) \
+	host1x_sync_cf_setup_limit_v(r)
+static inline u32 host1x_sync_cmdproc_stop_r(void)
+{
+	return 0xac;
+}
+#define HOST1X_SYNC_CMDPROC_STOP \
+	host1x_sync_cmdproc_stop_r()
+static inline u32 host1x_sync_ch_teardown_r(void)
+{
+	return 0xb0;
+}
+#define HOST1X_SYNC_CH_TEARDOWN \
+	host1x_sync_ch_teardown_r()
+static inline u32 host1x_sync_usec_clk_r(void)
+{
+	return 0x1a4;
+}
+#define HOST1X_SYNC_USEC_CLK \
+	host1x_sync_usec_clk_r()
+static inline u32 host1x_sync_ctxsw_timeout_cfg_r(void)
+{
+	return 0x1a8;
+}
+#define HOST1X_SYNC_CTXSW_TIMEOUT_CFG \
+	host1x_sync_ctxsw_timeout_cfg_r()
+static inline u32 host1x_sync_ip_busy_timeout_r(void)
+{
+	return 0x1bc;
+}
+#define HOST1X_SYNC_IP_BUSY_TIMEOUT \
+	host1x_sync_ip_busy_timeout_r()
+static inline u32 host1x_sync_mlock_owner_r(unsigned int id)
+{
+	return 0x340 + id * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_MLOCK_OWNER(id) \
+	host1x_sync_mlock_owner_r(id)
+static inline u32 host1x_sync_mlock_owner_chid_f(u32 v)
+{
+	return (v & 0xf) << 8;
+}
+#define HOST1X_SYNC_MLOCK_OWNER_CHID_F(v) \
+	host1x_sync_mlock_owner_chid_f(v)
+static inline u32 host1x_sync_mlock_owner_cpu_owns_v(u32 r)
+{
+	return (r >> 1) & 0x1;
+}
+#define HOST1X_SYNC_MLOCK_OWNER_CPU_OWNS_V(r) \
+	host1x_sync_mlock_owner_cpu_owns_v(r)
+static inline u32 host1x_sync_mlock_owner_ch_owns_v(u32 r)
+{
+	return (r >> 0) & 0x1;
+}
+#define HOST1X_SYNC_MLOCK_OWNER_CH_OWNS_V(r) \
+	host1x_sync_mlock_owner_ch_owns_v(r)
+static inline u32 host1x_sync_syncpt_int_thresh_r(unsigned int id)
+{
+	return 0x500 + id * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_SYNCPT_INT_THRESH(id) \
+	host1x_sync_syncpt_int_thresh_r(id)
+static inline u32 host1x_sync_syncpt_base_r(unsigned int id)
+{
+	return 0x600 + id * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_SYNCPT_BASE(id) \
+	host1x_sync_syncpt_base_r(id)
+static inline u32 host1x_sync_syncpt_cpu_incr_r(unsigned int id)
+{
+	return 0x700 + id * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_SYNCPT_CPU_INCR(id) \
+	host1x_sync_syncpt_cpu_incr_r(id)
+static inline u32 host1x_sync_cbread_r(unsigned int channel)
+{
+	return 0x720 + channel * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_CBREAD(channel) \
+	host1x_sync_cbread_r(channel)
+static inline u32 host1x_sync_cfpeek_ctrl_r(void)
+{
+	return 0x74c;
+}
+#define HOST1X_SYNC_CFPEEK_CTRL \
+	host1x_sync_cfpeek_ctrl_r()
+static inline u32 host1x_sync_cfpeek_ctrl_addr_f(u32 v)
+{
+	return (v & 0x3ff) << 0;
+}
+#define HOST1X_SYNC_CFPEEK_CTRL_ADDR_F(v) \
+	host1x_sync_cfpeek_ctrl_addr_f(v)
+static inline u32 host1x_sync_cfpeek_ctrl_channr_f(u32 v)
+{
+	return (v & 0xf) << 16;
+}
+#define HOST1X_SYNC_CFPEEK_CTRL_CHANNR_F(v) \
+	host1x_sync_cfpeek_ctrl_channr_f(v)
+static inline u32 host1x_sync_cfpeek_ctrl_ena_f(u32 v)
+{
+	return (v & 0x1) << 31;
+}
+#define HOST1X_SYNC_CFPEEK_CTRL_ENA_F(v) \
+	host1x_sync_cfpeek_ctrl_ena_f(v)
+static inline u32 host1x_sync_cfpeek_read_r(void)
+{
+	return 0x750;
+}
+#define HOST1X_SYNC_CFPEEK_READ \
+	host1x_sync_cfpeek_read_r()
+static inline u32 host1x_sync_cfpeek_ptrs_r(void)
+{
+	return 0x754;
+}
+#define HOST1X_SYNC_CFPEEK_PTRS \
+	host1x_sync_cfpeek_ptrs_r()
+static inline u32 host1x_sync_cfpeek_ptrs_cf_rd_ptr_v(u32 r)
+{
+	return (r >> 0) & 0x3ff;
+}
+#define HOST1X_SYNC_CFPEEK_PTRS_CF_RD_PTR_V(r) \
+	host1x_sync_cfpeek_ptrs_cf_rd_ptr_v(r)
+static inline u32 host1x_sync_cfpeek_ptrs_cf_wr_ptr_v(u32 r)
+{
+	return (r >> 16) & 0x3ff;
+}
+#define HOST1X_SYNC_CFPEEK_PTRS_CF_WR_PTR_V(r) \
+	host1x_sync_cfpeek_ptrs_cf_wr_ptr_v(r)
+static inline u32 host1x_sync_cbstat_r(unsigned int channel)
+{
+	return 0x758 + channel * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_CBSTAT(channel) \
+	host1x_sync_cbstat_r(channel)
+static inline u32 host1x_sync_cbstat_cboffset_v(u32 r)
+{
+	return (r >> 0) & 0xffff;
+}
+#define HOST1X_SYNC_CBSTAT_CBOFFSET_V(r) \
+	host1x_sync_cbstat_cboffset_v(r)
+static inline u32 host1x_sync_cbstat_cbclass_v(u32 r)
+{
+	return (r >> 16) & 0x3ff;
+}
+#define HOST1X_SYNC_CBSTAT_CBCLASS_V(r) \
+	host1x_sync_cbstat_cbclass_v(r)
+
+#endif
diff --git a/drivers/gpu/host1x/hw/hw_host1x02_uclass.h b/drivers/gpu/host1x/hw/hw_host1x02_uclass.h
new file mode 100644
index 0000000..a3b3c98
--- /dev/null
+++ b/drivers/gpu/host1x/hw/hw_host1x02_uclass.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 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/>.
+ *
+ */
+
+ /*
+  * Function naming determines intended use:
+  *
+  *     <x>_r(void) : Returns the offset for register <x>.
+  *
+  *     <x>_w(void) : Returns the word offset for word (4 byte) element <x>.
+  *
+  *     <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits.
+  *
+  *     <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted
+  *         and masked to place it at field <y> of register <x>.  This value
+  *         can be |'d with others to produce a full register value for
+  *         register <x>.
+  *
+  *     <x>_<y>_m(void) : Returns a mask for field <y> of register <x>.  This
+  *         value can be ~'d and then &'d to clear the value of field <y> for
+  *         register <x>.
+  *
+  *     <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted
+  *         to place it at field <y> of register <x>.  This value can be |'d
+  *         with others to produce a full register value for <x>.
+  *
+  *     <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register
+  *         <x> value 'r' after being shifted to place its LSB at bit 0.
+  *         This value is suitable for direct comparison with other unshifted
+  *         values appropriate for use in field <y> of register <x>.
+  *
+  *     <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for
+  *         field <y> of register <x>.  This value is suitable for direct
+  *         comparison with unshifted values appropriate for use in field <y>
+  *         of register <x>.
+  */
+
+#ifndef HOST1X_HW_HOST1X02_UCLASS_H
+#define HOST1X_HW_HOST1X02_UCLASS_H
+
+static inline u32 host1x_uclass_incr_syncpt_r(void)
+{
+	return 0x0;
+}
+#define HOST1X_UCLASS_INCR_SYNCPT \
+	host1x_uclass_incr_syncpt_r()
+static inline u32 host1x_uclass_incr_syncpt_cond_f(u32 v)
+{
+	return (v & 0xff) << 8;
+}
+#define HOST1X_UCLASS_INCR_SYNCPT_COND_F(v) \
+	host1x_uclass_incr_syncpt_cond_f(v)
+static inline u32 host1x_uclass_incr_syncpt_indx_f(u32 v)
+{
+	return (v & 0xff) << 0;
+}
+#define HOST1X_UCLASS_INCR_SYNCPT_INDX_F(v) \
+	host1x_uclass_incr_syncpt_indx_f(v)
+static inline u32 host1x_uclass_wait_syncpt_r(void)
+{
+	return 0x8;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT \
+	host1x_uclass_wait_syncpt_r()
+static inline u32 host1x_uclass_wait_syncpt_indx_f(u32 v)
+{
+	return (v & 0xff) << 24;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_INDX_F(v) \
+	host1x_uclass_wait_syncpt_indx_f(v)
+static inline u32 host1x_uclass_wait_syncpt_thresh_f(u32 v)
+{
+	return (v & 0xffffff) << 0;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_THRESH_F(v) \
+	host1x_uclass_wait_syncpt_thresh_f(v)
+static inline u32 host1x_uclass_wait_syncpt_base_r(void)
+{
+	return 0x9;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_BASE \
+	host1x_uclass_wait_syncpt_base_r()
+static inline u32 host1x_uclass_wait_syncpt_base_indx_f(u32 v)
+{
+	return (v & 0xff) << 24;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_INDX_F(v) \
+	host1x_uclass_wait_syncpt_base_indx_f(v)
+static inline u32 host1x_uclass_wait_syncpt_base_base_indx_f(u32 v)
+{
+	return (v & 0xff) << 16;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_BASE_INDX_F(v) \
+	host1x_uclass_wait_syncpt_base_base_indx_f(v)
+static inline u32 host1x_uclass_wait_syncpt_base_offset_f(u32 v)
+{
+	return (v & 0xffff) << 0;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_OFFSET_F(v) \
+	host1x_uclass_wait_syncpt_base_offset_f(v)
+static inline u32 host1x_uclass_load_syncpt_base_base_indx_f(u32 v)
+{
+	return (v & 0xff) << 24;
+}
+#define HOST1X_UCLASS_LOAD_SYNCPT_BASE_BASE_INDX_F(v) \
+	host1x_uclass_load_syncpt_base_base_indx_f(v)
+static inline u32 host1x_uclass_load_syncpt_base_value_f(u32 v)
+{
+	return (v & 0xffffff) << 0;
+}
+#define HOST1X_UCLASS_LOAD_SYNCPT_BASE_VALUE_F(v) \
+	host1x_uclass_load_syncpt_base_value_f(v)
+static inline u32 host1x_uclass_incr_syncpt_base_base_indx_f(u32 v)
+{
+	return (v & 0xff) << 24;
+}
+#define HOST1X_UCLASS_INCR_SYNCPT_BASE_BASE_INDX_F(v) \
+	host1x_uclass_incr_syncpt_base_base_indx_f(v)
+static inline u32 host1x_uclass_incr_syncpt_base_offset_f(u32 v)
+{
+	return (v & 0xffffff) << 0;
+}
+#define HOST1X_UCLASS_INCR_SYNCPT_BASE_OFFSET_F(v) \
+	host1x_uclass_incr_syncpt_base_offset_f(v)
+static inline u32 host1x_uclass_indoff_r(void)
+{
+	return 0x2d;
+}
+#define HOST1X_UCLASS_INDOFF \
+	host1x_uclass_indoff_r()
+static inline u32 host1x_uclass_indoff_indbe_f(u32 v)
+{
+	return (v & 0xf) << 28;
+}
+#define HOST1X_UCLASS_INDOFF_INDBE_F(v) \
+	host1x_uclass_indoff_indbe_f(v)
+static inline u32 host1x_uclass_indoff_autoinc_f(u32 v)
+{
+	return (v & 0x1) << 27;
+}
+#define HOST1X_UCLASS_INDOFF_AUTOINC_F(v) \
+	host1x_uclass_indoff_autoinc_f(v)
+static inline u32 host1x_uclass_indoff_indmodid_f(u32 v)
+{
+	return (v & 0xff) << 18;
+}
+#define HOST1X_UCLASS_INDOFF_INDMODID_F(v) \
+	host1x_uclass_indoff_indmodid_f(v)
+static inline u32 host1x_uclass_indoff_indroffset_f(u32 v)
+{
+	return (v & 0xffff) << 2;
+}
+#define HOST1X_UCLASS_INDOFF_INDROFFSET_F(v) \
+	host1x_uclass_indoff_indroffset_f(v)
+static inline u32 host1x_uclass_indoff_rwn_read_v(void)
+{
+	return 1;
+}
+#define HOST1X_UCLASS_INDOFF_INDROFFSET_F(v) \
+	host1x_uclass_indoff_indroffset_f(v)
+
+#endif
-- 
1.8.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 16/27] drm/tegra: Add Tegra114 display controller support
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (14 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 15/27] gpu: host1x: Add support for Tegra114 Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
       [not found]     ` <1381134884-5816-17-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2013-10-07  8:34   ` [PATCH v2 17/27] drm/tegra: Add Tegra114 HDMI support Thierry Reding
                     ` (10 subsequent siblings)
  26 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mikko Perttunen

From: Mikko Perttunen <mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

The Tegra114 display controller is backwards-compatible with previous
generations of the Tegra SoC. No code changes are required.

Signed-off-by: Mikko Perttunen <mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/drm/tegra/dc.c  | 1 +
 drivers/gpu/drm/tegra/drm.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 71cbda6..e8a0f5f 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -1183,6 +1183,7 @@ static int tegra_dc_remove(struct platform_device *pdev)
 }
 
 static struct of_device_id tegra_dc_of_match[] = {
+	{ .compatible = "nvidia,tegra114-dc", },
 	{ .compatible = "nvidia,tegra30-dc", },
 	{ .compatible = "nvidia,tegra20-dc", },
 	{ },
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index f9def3c..e958960 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -489,6 +489,7 @@ static const struct of_device_id host1x_drm_subdevs[] = {
 	{ .compatible = "nvidia,tegra30-dc", },
 	{ .compatible = "nvidia,tegra30-hdmi", },
 	{ .compatible = "nvidia,tegra30-gr2d", },
+	{ .compatible = "nvidia,tegra114-dc", },
 	{ /* sentinel */ }
 };
 
-- 
1.8.4

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

* [PATCH v2 17/27] drm/tegra: Add Tegra114 HDMI support
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (15 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 16/27] drm/tegra: Add Tegra114 display controller support Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
       [not found]     ` <1381134884-5816-18-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2013-10-07  8:34   ` [PATCH v2 18/27] drm/tegra: hdmi: Detect DVI-only displays Thierry Reding
                     ` (9 subsequent siblings)
  26 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mikko Perttunen

From: Mikko Perttunen <mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

Tegra114 TMDS configuration requires a new peak_current field and the
driver current override bit has changed position.

Signed-off-by: Mikko Perttunen <mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/drm/tegra/drm.c  |   1 +
 drivers/gpu/drm/tegra/hdmi.c | 103 ++++++++++++++++++++++++++++-
 drivers/gpu/drm/tegra/hdmi.h | 152 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 253 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index e958960..4afc9e1 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -490,6 +490,7 @@ static const struct of_device_id host1x_drm_subdevs[] = {
 	{ .compatible = "nvidia,tegra30-hdmi", },
 	{ .compatible = "nvidia,tegra30-gr2d", },
 	{ .compatible = "nvidia,tegra114-dc", },
+	{ .compatible = "nvidia,tegra114-hdmi", },
 	{ /* sentinel */ }
 };
 
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index 4489d56..130cb6d 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -142,6 +142,7 @@ struct tmds_config {
 	u32 pll1;
 	u32 pe_current;
 	u32 drive_current;
+	u32 peak_current;
 };
 
 static const struct tmds_config tegra2_tmds_config[] = {
@@ -223,6 +224,85 @@ static const struct tmds_config tegra3_tmds_config[] = {
 	},
 };
 
+const struct tmds_config tegra114_tmds_config[] = {
+	{ /* 480p/576p / 25.2MHz/27MHz modes */
+		.pclk = 27000000,
+		.pll0 = SOR_PLL_ICHPMP(1) | SOR_PLL_BG_V17_S(3) |
+			SOR_PLL_VCOCAP(0) | SOR_PLL_RESISTORSEL,
+		.pll1 = SOR_PLL_LOADADJ(3) | SOR_PLL_TMDS_TERMADJ(0),
+		.pe_current = PE_CURRENT0(PE_CURRENT_0_mA_T114) |
+			PE_CURRENT1(PE_CURRENT_0_mA_T114) |
+			PE_CURRENT2(PE_CURRENT_0_mA_T114) |
+			PE_CURRENT3(PE_CURRENT_0_mA_T114),
+		.drive_current =
+			DRIVE_CURRENT_LANE0_T114(DRIVE_CURRENT_10_400_mA_T114) |
+			DRIVE_CURRENT_LANE1_T114(DRIVE_CURRENT_10_400_mA_T114) |
+			DRIVE_CURRENT_LANE2_T114(DRIVE_CURRENT_10_400_mA_T114) |
+			DRIVE_CURRENT_LANE3_T114(DRIVE_CURRENT_10_400_mA_T114),
+		.peak_current = PEAK_CURRENT_LANE0(PEAK_CURRENT_0_000_mA) |
+			PEAK_CURRENT_LANE1(PEAK_CURRENT_0_000_mA) |
+			PEAK_CURRENT_LANE2(PEAK_CURRENT_0_000_mA) |
+			PEAK_CURRENT_LANE3(PEAK_CURRENT_0_000_mA),
+	}, { /* 720p / 74.25MHz modes */
+		.pclk = 74250000,
+		.pll0 = SOR_PLL_ICHPMP(1) | SOR_PLL_BG_V17_S(3) |
+			SOR_PLL_VCOCAP(1) | SOR_PLL_RESISTORSEL,
+		.pll1 = SOR_PLL_PE_EN | SOR_PLL_LOADADJ(3) |
+			SOR_PLL_TMDS_TERMADJ(0),
+		.pe_current = PE_CURRENT0(PE_CURRENT_15_mA_T114) |
+			PE_CURRENT1(PE_CURRENT_15_mA_T114) |
+			PE_CURRENT2(PE_CURRENT_15_mA_T114) |
+			PE_CURRENT3(PE_CURRENT_15_mA_T114),
+		.drive_current =
+			DRIVE_CURRENT_LANE0_T114(DRIVE_CURRENT_10_400_mA_T114) |
+			DRIVE_CURRENT_LANE1_T114(DRIVE_CURRENT_10_400_mA_T114) |
+			DRIVE_CURRENT_LANE2_T114(DRIVE_CURRENT_10_400_mA_T114) |
+			DRIVE_CURRENT_LANE3_T114(DRIVE_CURRENT_10_400_mA_T114),
+		.peak_current = PEAK_CURRENT_LANE0(PEAK_CURRENT_0_000_mA) |
+			PEAK_CURRENT_LANE1(PEAK_CURRENT_0_000_mA) |
+			PEAK_CURRENT_LANE2(PEAK_CURRENT_0_000_mA) |
+			PEAK_CURRENT_LANE3(PEAK_CURRENT_0_000_mA),
+	}, { /* 1080p / 148.5MHz modes */
+		.pclk = 148500000,
+		.pll0 = SOR_PLL_ICHPMP(1) | SOR_PLL_BG_V17_S(3) |
+			SOR_PLL_VCOCAP(3) | SOR_PLL_RESISTORSEL,
+		.pll1 = SOR_PLL_PE_EN | SOR_PLL_LOADADJ(3) |
+			SOR_PLL_TMDS_TERMADJ(0),
+		.pe_current = PE_CURRENT0(PE_CURRENT_10_mA_T114) |
+			PE_CURRENT1(PE_CURRENT_10_mA_T114) |
+			PE_CURRENT2(PE_CURRENT_10_mA_T114) |
+			PE_CURRENT3(PE_CURRENT_10_mA_T114),
+		.drive_current =
+			DRIVE_CURRENT_LANE0_T114(DRIVE_CURRENT_12_400_mA_T114) |
+			DRIVE_CURRENT_LANE1_T114(DRIVE_CURRENT_12_400_mA_T114) |
+			DRIVE_CURRENT_LANE2_T114(DRIVE_CURRENT_12_400_mA_T114) |
+			DRIVE_CURRENT_LANE3_T114(DRIVE_CURRENT_12_400_mA_T114),
+		.peak_current = PEAK_CURRENT_LANE0(PEAK_CURRENT_0_000_mA) |
+			PEAK_CURRENT_LANE1(PEAK_CURRENT_0_000_mA) |
+			PEAK_CURRENT_LANE2(PEAK_CURRENT_0_000_mA) |
+			PEAK_CURRENT_LANE3(PEAK_CURRENT_0_000_mA),
+	}, { /* 225/297MHz modes */
+		.pclk = UINT_MAX,
+		.pll0 = SOR_PLL_ICHPMP(1) | SOR_PLL_BG_V17_S(3) |
+			SOR_PLL_VCOCAP(0xf) | SOR_PLL_RESISTORSEL,
+		.pll1 = SOR_PLL_LOADADJ(3) | SOR_PLL_TMDS_TERMADJ(7)
+			| SOR_PLL_TMDS_TERM_ENABLE,
+		.pe_current = PE_CURRENT0(PE_CURRENT_0_mA_T114) |
+			PE_CURRENT1(PE_CURRENT_0_mA_T114) |
+			PE_CURRENT2(PE_CURRENT_0_mA_T114) |
+			PE_CURRENT3(PE_CURRENT_0_mA_T114),
+		.drive_current =
+			DRIVE_CURRENT_LANE0_T114(DRIVE_CURRENT_25_200_mA_T114) |
+			DRIVE_CURRENT_LANE1_T114(DRIVE_CURRENT_25_200_mA_T114) |
+			DRIVE_CURRENT_LANE2_T114(DRIVE_CURRENT_25_200_mA_T114) |
+			DRIVE_CURRENT_LANE3_T114(DRIVE_CURRENT_19_200_mA_T114),
+		.peak_current = PEAK_CURRENT_LANE0(PEAK_CURRENT_3_000_mA) |
+			PEAK_CURRENT_LANE1(PEAK_CURRENT_3_000_mA) |
+			PEAK_CURRENT_LANE2(PEAK_CURRENT_3_000_mA) |
+			PEAK_CURRENT_LANE3(PEAK_CURRENT_0_800_mA),
+	},
+};
+
 static const struct tegra_hdmi_audio_config *
 tegra_hdmi_get_audio_config(unsigned int audio_freq, unsigned int pclk)
 {
@@ -564,14 +644,26 @@ static void tegra_hdmi_setup_stereo_infoframe(struct tegra_hdmi *hdmi)
 static void tegra_hdmi_setup_tmds(struct tegra_hdmi *hdmi,
 				  const struct tmds_config *tmds)
 {
+	struct device_node *np = hdmi->dev->of_node;
 	unsigned long value;
 
 	tegra_hdmi_writel(hdmi, tmds->pll0, HDMI_NV_PDISP_SOR_PLL0);
 	tegra_hdmi_writel(hdmi, tmds->pll1, HDMI_NV_PDISP_SOR_PLL1);
 	tegra_hdmi_writel(hdmi, tmds->pe_current, HDMI_NV_PDISP_PE_CURRENT);
 
-	value = tmds->drive_current | DRIVE_CURRENT_FUSE_OVERRIDE;
-	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
+	if (of_device_is_compatible(np, "nvidia,tegra114-hdmi")) {
+		tegra_hdmi_writel(hdmi, tmds->drive_current,
+				  HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
+		value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_SOR_PAD_CTLS0);
+		value |= DRIVE_CURRENT_FUSE_OVERRIDE_T114;
+		tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_PAD_CTLS0);
+		tegra_hdmi_writel(hdmi, tmds->peak_current,
+				  HDMI_NV_PDISP_SOR_IO_PEAK_CURRENT);
+	} else {
+		value = tmds->drive_current | DRIVE_CURRENT_FUSE_OVERRIDE;
+		tegra_hdmi_writel(hdmi, value,
+				  HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
+	}
 }
 
 static int tegra_output_hdmi_enable(struct tegra_output *output)
@@ -703,7 +795,10 @@ static int tegra_output_hdmi_enable(struct tegra_output *output)
 	tegra_hdmi_setup_stereo_infoframe(hdmi);
 
 	/* TMDS CONFIG */
-	if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
+	if (of_device_is_compatible(node, "nvidia,tegra114-hdmi")) {
+		num_tmds = ARRAY_SIZE(tegra114_tmds_config);
+		tmds = tegra114_tmds_config;
+	} else if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
 		num_tmds = ARRAY_SIZE(tegra3_tmds_config);
 		tmds = tegra3_tmds_config;
 	} else {
@@ -1048,6 +1143,7 @@ static int tegra_hdmi_show_regs(struct seq_file *s, void *data)
 	DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_CNTRL0);
 	DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR);
 	DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE);
+	DUMP_REG(HDMI_NV_PDISP_SOR_IO_PEAK_CURRENT);
 
 #undef DUMP_REG
 
@@ -1284,6 +1380,7 @@ static int tegra_hdmi_remove(struct platform_device *pdev)
 }
 
 static struct of_device_id tegra_hdmi_of_match[] = {
+	{ .compatible = "nvidia,tegra114-hdmi", },
 	{ .compatible = "nvidia,tegra30-hdmi", },
 	{ .compatible = "nvidia,tegra20-hdmi", },
 	{ },
diff --git a/drivers/gpu/drm/tegra/hdmi.h b/drivers/gpu/drm/tegra/hdmi.h
index 52ac36e..37925c2 100644
--- a/drivers/gpu/drm/tegra/hdmi.h
+++ b/drivers/gpu/drm/tegra/hdmi.h
@@ -233,6 +233,10 @@
 #define DRIVE_CURRENT_LANE1(x)      (((x) & 0x3f) <<  8)
 #define DRIVE_CURRENT_LANE2(x)      (((x) & 0x3f) << 16)
 #define DRIVE_CURRENT_LANE3(x)      (((x) & 0x3f) << 24)
+#define DRIVE_CURRENT_LANE0_T114(x) (((x) & 0x7f) <<  0)
+#define DRIVE_CURRENT_LANE1_T114(x) (((x) & 0x7f) <<  8)
+#define DRIVE_CURRENT_LANE2_T114(x) (((x) & 0x7f) << 16)
+#define DRIVE_CURRENT_LANE3_T114(x) (((x) & 0x7f) << 24)
 #define DRIVE_CURRENT_FUSE_OVERRIDE (1 << 31)
 
 #define DRIVE_CURRENT_1_500_mA  0x00
@@ -299,6 +303,79 @@
 #define DRIVE_CURRENT_24_375_mA 0x3d
 #define DRIVE_CURRENT_24_750_mA 0x3e
 
+#define DRIVE_CURRENT_0_000_mA_T114 0x00
+#define DRIVE_CURRENT_0_400_mA_T114 0x01
+#define DRIVE_CURRENT_0_800_mA_T114 0x02
+#define DRIVE_CURRENT_1_200_mA_T114 0x03
+#define DRIVE_CURRENT_1_600_mA_T114 0x04
+#define DRIVE_CURRENT_2_000_mA_T114 0x05
+#define DRIVE_CURRENT_2_400_mA_T114 0x06
+#define DRIVE_CURRENT_2_800_mA_T114 0x07
+#define DRIVE_CURRENT_3_200_mA_T114 0x08
+#define DRIVE_CURRENT_3_600_mA_T114 0x09
+#define DRIVE_CURRENT_4_000_mA_T114 0x0a
+#define DRIVE_CURRENT_4_400_mA_T114 0x0b
+#define DRIVE_CURRENT_4_800_mA_T114 0x0c
+#define DRIVE_CURRENT_5_200_mA_T114 0x0d
+#define DRIVE_CURRENT_5_600_mA_T114 0x0e
+#define DRIVE_CURRENT_6_000_mA_T114 0x0f
+#define DRIVE_CURRENT_6_400_mA_T114 0x10
+#define DRIVE_CURRENT_6_800_mA_T114 0x11
+#define DRIVE_CURRENT_7_200_mA_T114 0x12
+#define DRIVE_CURRENT_7_600_mA_T114 0x13
+#define DRIVE_CURRENT_8_000_mA_T114 0x14
+#define DRIVE_CURRENT_8_400_mA_T114 0x15
+#define DRIVE_CURRENT_8_800_mA_T114 0x16
+#define DRIVE_CURRENT_9_200_mA_T114 0x17
+#define DRIVE_CURRENT_9_600_mA_T114 0x18
+#define DRIVE_CURRENT_10_000_mA_T114 0x19
+#define DRIVE_CURRENT_10_400_mA_T114 0x1a
+#define DRIVE_CURRENT_10_800_mA_T114 0x1b
+#define DRIVE_CURRENT_11_200_mA_T114 0x1c
+#define DRIVE_CURRENT_11_600_mA_T114 0x1d
+#define DRIVE_CURRENT_12_000_mA_T114 0x1e
+#define DRIVE_CURRENT_12_400_mA_T114 0x1f
+#define DRIVE_CURRENT_12_800_mA_T114 0x20
+#define DRIVE_CURRENT_13_200_mA_T114 0x21
+#define DRIVE_CURRENT_13_600_mA_T114 0x22
+#define DRIVE_CURRENT_14_000_mA_T114 0x23
+#define DRIVE_CURRENT_14_400_mA_T114 0x24
+#define DRIVE_CURRENT_14_800_mA_T114 0x25
+#define DRIVE_CURRENT_15_200_mA_T114 0x26
+#define DRIVE_CURRENT_15_600_mA_T114 0x27
+#define DRIVE_CURRENT_16_000_mA_T114 0x28
+#define DRIVE_CURRENT_16_400_mA_T114 0x29
+#define DRIVE_CURRENT_16_800_mA_T114 0x2a
+#define DRIVE_CURRENT_17_200_mA_T114 0x2b
+#define DRIVE_CURRENT_17_600_mA_T114 0x2c
+#define DRIVE_CURRENT_18_000_mA_T114 0x2d
+#define DRIVE_CURRENT_18_400_mA_T114 0x2e
+#define DRIVE_CURRENT_18_800_mA_T114 0x2f
+#define DRIVE_CURRENT_19_200_mA_T114 0x30
+#define DRIVE_CURRENT_19_600_mA_T114 0x31
+#define DRIVE_CURRENT_20_000_mA_T114 0x32
+#define DRIVE_CURRENT_20_400_mA_T114 0x33
+#define DRIVE_CURRENT_20_800_mA_T114 0x34
+#define DRIVE_CURRENT_21_200_mA_T114 0x35
+#define DRIVE_CURRENT_21_600_mA_T114 0x36
+#define DRIVE_CURRENT_22_000_mA_T114 0x37
+#define DRIVE_CURRENT_22_400_mA_T114 0x38
+#define DRIVE_CURRENT_22_800_mA_T114 0x39
+#define DRIVE_CURRENT_23_200_mA_T114 0x3a
+#define DRIVE_CURRENT_23_600_mA_T114 0x3b
+#define DRIVE_CURRENT_24_000_mA_T114 0x3c
+#define DRIVE_CURRENT_24_400_mA_T114 0x3d
+#define DRIVE_CURRENT_24_800_mA_T114 0x3e
+#define DRIVE_CURRENT_25_200_mA_T114 0x3f
+#define DRIVE_CURRENT_25_400_mA_T114 0x40
+#define DRIVE_CURRENT_25_800_mA_T114 0x41
+#define DRIVE_CURRENT_26_200_mA_T114 0x42
+#define DRIVE_CURRENT_26_600_mA_T114 0x43
+#define DRIVE_CURRENT_27_000_mA_T114 0x44
+#define DRIVE_CURRENT_27_400_mA_T114 0x45
+#define DRIVE_CURRENT_27_800_mA_T114 0x46
+#define DRIVE_CURRENT_28_200_mA_T114 0x47
+
 #define HDMI_NV_PDISP_AUDIO_DEBUG0				0x7f
 #define HDMI_NV_PDISP_AUDIO_DEBUG1				0x80
 #define HDMI_NV_PDISP_AUDIO_DEBUG2				0x81
@@ -358,6 +435,23 @@
 #define PE_CURRENT_7_0_mA 0xe
 #define PE_CURRENT_7_5_mA 0xf
 
+#define PE_CURRENT_0_mA_T114 0x0
+#define PE_CURRENT_1_mA_T114 0x1
+#define PE_CURRENT_2_mA_T114 0x2
+#define PE_CURRENT_3_mA_T114 0x3
+#define PE_CURRENT_4_mA_T114 0x4
+#define PE_CURRENT_5_mA_T114 0x5
+#define PE_CURRENT_6_mA_T114 0x6
+#define PE_CURRENT_7_mA_T114 0x7
+#define PE_CURRENT_8_mA_T114 0x8
+#define PE_CURRENT_9_mA_T114 0x9
+#define PE_CURRENT_10_mA_T114 0xa
+#define PE_CURRENT_11_mA_T114 0xb
+#define PE_CURRENT_12_mA_T114 0xc
+#define PE_CURRENT_13_mA_T114 0xd
+#define PE_CURRENT_14_mA_T114 0xe
+#define PE_CURRENT_15_mA_T114 0xf
+
 #define HDMI_NV_PDISP_KEY_CTRL					0x9a
 #define HDMI_NV_PDISP_KEY_DEBUG0				0x9b
 #define HDMI_NV_PDISP_KEY_DEBUG1				0x9c
@@ -383,4 +477,62 @@
 #define HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920    0xc5
 #define HDMI_NV_PDISP_SOR_AUDIO_AVAL_DEFAULT 0xc5
 
+#define HDMI_NV_PDISP_SOR_IO_PEAK_CURRENT		0xd1
+#define PEAK_CURRENT_LANE0(x) (((x) & 0x7f) <<  0)
+#define PEAK_CURRENT_LANE1(x) (((x) & 0x7f) <<  8)
+#define PEAK_CURRENT_LANE2(x) (((x) & 0x7f) << 16)
+#define PEAK_CURRENT_LANE3(x) (((x) & 0x7f) << 24)
+
+#define PEAK_CURRENT_0_000_mA 0x00
+#define PEAK_CURRENT_0_200_mA 0x01
+#define PEAK_CURRENT_0_400_mA 0x02
+#define PEAK_CURRENT_0_600_mA 0x03
+#define PEAK_CURRENT_0_800_mA 0x04
+#define PEAK_CURRENT_1_000_mA 0x05
+#define PEAK_CURRENT_1_200_mA 0x06
+#define PEAK_CURRENT_1_400_mA 0x07
+#define PEAK_CURRENT_1_600_mA 0x08
+#define PEAK_CURRENT_1_800_mA 0x09
+#define PEAK_CURRENT_2_000_mA 0x0a
+#define PEAK_CURRENT_2_200_mA 0x0b
+#define PEAK_CURRENT_2_400_mA 0x0c
+#define PEAK_CURRENT_2_600_mA 0x0d
+#define PEAK_CURRENT_2_800_mA 0x0e
+#define PEAK_CURRENT_3_000_mA 0x0f
+#define PEAK_CURRENT_3_200_mA 0x10
+#define PEAK_CURRENT_3_400_mA 0x11
+#define PEAK_CURRENT_3_600_mA 0x12
+#define PEAK_CURRENT_3_800_mA 0x13
+#define PEAK_CURRENT_4_000_mA 0x14
+#define PEAK_CURRENT_4_200_mA 0x15
+#define PEAK_CURRENT_4_400_mA 0x16
+#define PEAK_CURRENT_4_600_mA 0x17
+#define PEAK_CURRENT_4_800_mA 0x18
+#define PEAK_CURRENT_5_000_mA 0x19
+#define PEAK_CURRENT_5_200_mA 0x1a
+#define PEAK_CURRENT_5_400_mA 0x1b
+#define PEAK_CURRENT_5_600_mA 0x1c
+#define PEAK_CURRENT_5_800_mA 0x1d
+#define PEAK_CURRENT_6_000_mA 0x1e
+#define PEAK_CURRENT_6_200_mA 0x1f
+#define PEAK_CURRENT_6_400_mA 0x20
+#define PEAK_CURRENT_6_600_mA 0x21
+#define PEAK_CURRENT_6_800_mA 0x22
+#define PEAK_CURRENT_7_000_mA 0x23
+#define PEAK_CURRENT_7_200_mA 0x24
+#define PEAK_CURRENT_7_400_mA 0x25
+#define PEAK_CURRENT_7_600_mA 0x26
+#define PEAK_CURRENT_7_800_mA 0x27
+#define PEAK_CURRENT_8_000_mA 0x28
+#define PEAK_CURRENT_8_200_mA 0x29
+#define PEAK_CURRENT_8_400_mA 0x2a
+#define PEAK_CURRENT_8_600_mA 0x2b
+#define PEAK_CURRENT_8_800_mA 0x2c
+#define PEAK_CURRENT_9_000_mA 0x2d
+#define PEAK_CURRENT_9_200_mA 0x2e
+#define PEAK_CURRENT_9_400_mA 0x2f
+
+#define HDMI_NV_PDISP_SOR_PAD_CTLS0		0xd2
+#define DRIVE_CURRENT_FUSE_OVERRIDE_T114	(1 << 31)
+
 #endif /* TEGRA_HDMI_H */
-- 
1.8.4

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

* [PATCH v2 18/27] drm/tegra: hdmi: Detect DVI-only displays
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (16 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 17/27] drm/tegra: Add Tegra114 HDMI support Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
  2013-10-07  8:34   ` [PATCH v2 19/27] host1x: hdmi: Enable VDD earlier for hotplug/DDC Thierry Reding
                     ` (8 subsequent siblings)
  26 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mikko Perttunen

From: Mikko Perttunen <mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

Use EDID data to determine whether the display supports HDMI or DVI
only. The HDMI output used to assume to be connected to HDMI displays,
but that broke support for DVI displays that don't understand the
interspersed audio/other data.

To be on the safe side, default to DVI if no EDID data is available.

Signed-off-by: Mikko Perttunen <mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
[treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org: move detection to separate function]
Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/drm/tegra/hdmi.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index 130cb6d..3808226 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -666,6 +666,18 @@ static void tegra_hdmi_setup_tmds(struct tegra_hdmi *hdmi,
 	}
 }
 
+static bool tegra_output_is_hdmi(struct tegra_output *output)
+{
+	struct edid *edid;
+
+	if (!output->connector.edid_blob_ptr)
+		return false;
+
+	edid = (struct edid *)output->connector.edid_blob_ptr->data;
+
+	return drm_detect_hdmi_monitor(edid);
+}
+
 static int tegra_output_hdmi_enable(struct tegra_output *output)
 {
 	unsigned int h_sync_width, h_front_porch, h_back_porch, i, rekey;
@@ -680,6 +692,8 @@ static int tegra_output_hdmi_enable(struct tegra_output *output)
 	int retries = 1000;
 	int err;
 
+	hdmi->dvi = !tegra_output_is_hdmi(output);
+
 	pclk = mode->clock * 1000;
 	h_sync_width = mode->hsync_end - mode->hsync_start;
 	h_back_porch = mode->htotal - mode->hsync_end;
-- 
1.8.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 19/27] host1x: hdmi: Enable VDD earlier for hotplug/DDC
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (17 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 18/27] drm/tegra: hdmi: Detect DVI-only displays Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
  2013-10-07  8:34   ` [PATCH v2 20/27] drm/tegra: hdmi: Rename tegra{2,3} to tegra{20,30} Thierry Reding
                     ` (7 subsequent siblings)
  26 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mikko Perttunen

From: Mikko Perttunen <mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

The VDD regulator used to be enabled only at tegra_output_hdmi_enable,
which is called after a sink is detected. However, the HDMI hotplug pin
works by returning the voltage supplied by the VDD pin, so this meant
that the hotplug pin was never asserted and the sink was not detected
unless the VDD regulator was set to be always on.

This patch moves the enable to the tegra_hdmi_init() function to make
sure the regulator will get enabled and therefore ensure proper hotplug
detection.

Signed-off-by: Mikko Perttunen <mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/drm/tegra/hdmi.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index 3808226..9bd912c 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -699,12 +699,6 @@ static int tegra_output_hdmi_enable(struct tegra_output *output)
 	h_back_porch = mode->htotal - mode->hsync_end;
 	h_front_porch = mode->hsync_start - mode->hdisplay;
 
-	err = regulator_enable(hdmi->vdd);
-	if (err < 0) {
-		dev_err(hdmi->dev, "failed to enable VDD regulator: %d\n", err);
-		return err;
-	}
-
 	err = regulator_enable(hdmi->pll);
 	if (err < 0) {
 		dev_err(hdmi->dev, "failed to enable PLL regulator: %d\n", err);
@@ -926,7 +920,6 @@ static int tegra_output_hdmi_disable(struct tegra_output *output)
 	tegra_periph_reset_assert(hdmi->clk);
 	clk_disable(hdmi->clk);
 	regulator_disable(hdmi->pll);
-	regulator_disable(hdmi->vdd);
 
 	return 0;
 }
@@ -1231,6 +1224,13 @@ static int tegra_hdmi_init(struct host1x_client *client)
 	struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
 	int err;
 
+	err = regulator_enable(hdmi->vdd);
+	if (err < 0) {
+		dev_err(client->dev, "failed to enable VDD regulator: %d\n",
+			err);
+		return err;
+	}
+
 	hdmi->output.type = TEGRA_OUTPUT_HDMI;
 	hdmi->output.dev = client->dev;
 	hdmi->output.ops = &hdmi_ops;
@@ -1274,6 +1274,8 @@ static int tegra_hdmi_exit(struct host1x_client *client)
 		return err;
 	}
 
+	regulator_disable(hdmi->vdd);
+
 	return 0;
 }
 
-- 
1.8.4

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

* [PATCH v2 20/27] drm/tegra: hdmi: Rename tegra{2,3} to tegra{20,30}
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (18 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 19/27] host1x: hdmi: Enable VDD earlier for hotplug/DDC Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
  2013-10-07  8:34   ` [PATCH v2 21/27] drm: Add panel support Thierry Reding
                     ` (6 subsequent siblings)
  26 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

Everything related to Tegra uses Tegra20 and Tegra30 instead of Tegra2
and Tegra3, respectively. Rename the TMDS arrays in the HDMI driver for
consistency.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/drm/tegra/hdmi.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index 9bd912c..68ab00d 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -145,7 +145,7 @@ struct tmds_config {
 	u32 peak_current;
 };
 
-static const struct tmds_config tegra2_tmds_config[] = {
+static const struct tmds_config tegra20_tmds_config[] = {
 	{ /* slow pixel clock modes */
 		.pclk = 27000000,
 		.pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
@@ -178,7 +178,7 @@ static const struct tmds_config tegra2_tmds_config[] = {
 	},
 };
 
-static const struct tmds_config tegra3_tmds_config[] = {
+static const struct tmds_config tegra30_tmds_config[] = {
 	{ /* 480p modes */
 		.pclk = 27000000,
 		.pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
@@ -807,11 +807,11 @@ static int tegra_output_hdmi_enable(struct tegra_output *output)
 		num_tmds = ARRAY_SIZE(tegra114_tmds_config);
 		tmds = tegra114_tmds_config;
 	} else if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
-		num_tmds = ARRAY_SIZE(tegra3_tmds_config);
-		tmds = tegra3_tmds_config;
+		num_tmds = ARRAY_SIZE(tegra30_tmds_config);
+		tmds = tegra30_tmds_config;
 	} else {
-		num_tmds = ARRAY_SIZE(tegra2_tmds_config);
-		tmds = tegra2_tmds_config;
+		num_tmds = ARRAY_SIZE(tegra20_tmds_config);
+		tmds = tegra20_tmds_config;
 	}
 
 	for (i = 0; i < num_tmds; i++) {
-- 
1.8.4

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

* [PATCH v2 21/27] drm: Add panel support
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (19 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 20/27] drm/tegra: hdmi: Rename tegra{2,3} to tegra{20,30} Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
  2013-10-07  8:34   ` [PATCH v2 22/27] drm/panel: Add simple " Thierry Reding
                     ` (5 subsequent siblings)
  26 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

Add a very simple framework to register and lookup panels. Panel drivers
can initialize a DRM panel and register it with the framework, allowing
them to be retrieved and used by display drivers. Currently only support
for DPMS and obtaining panel modes is provided. However it should be
sufficient to enable a large number of panels. The framework should also
be easily extensible to support more sophisticated kinds of panels such
as DSI.

The framework hasn't been tied into the DRM core, even though it should
be easily possible to do so if that's what we want. In the current
implementation, display drivers can simple make use of it to retrieve a
panel, obtain its modes and control its DPMS mode.

Note that this is currently only tested on systems that boot from a
device tree. No glue code has been written yet for systems that use
platform data, but it should be easy to add.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
Changes in v2:
- split .dpms() into separate .disable() and .enable()

 drivers/gpu/drm/Kconfig       |  2 +
 drivers/gpu/drm/Makefile      |  1 +
 drivers/gpu/drm/drm_panel.c   | 96 +++++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/panel/Kconfig |  4 ++
 include/drm/drm_panel.h       | 78 +++++++++++++++++++++++++++++++++++
 5 files changed, 181 insertions(+)
 create mode 100644 drivers/gpu/drm/drm_panel.c
 create mode 100644 drivers/gpu/drm/panel/Kconfig
 create mode 100644 include/drm/drm_panel.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 290e2ac..a1d4f8e 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -238,3 +238,5 @@ source "drivers/gpu/drm/qxl/Kconfig"
 source "drivers/gpu/drm/msm/Kconfig"
 
 source "drivers/gpu/drm/tegra/Kconfig"
+
+source "drivers/gpu/drm/panel/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index e39cd03..81363a9 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -18,6 +18,7 @@ drm-y       :=	drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
 drm-$(CONFIG_PCI) += ati_pcigart.o
+drm-$(CONFIG_DRM_PANEL) += drm_panel.o
 
 drm-usb-y   := drm_usb.o
 
diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c
new file mode 100644
index 0000000..ff6e459
--- /dev/null
+++ b/drivers/gpu/drm/drm_panel.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2013, NVIDIA Corporation.  All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <linux/err.h>
+#include <linux/export.h>
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_panel.h>
+
+static DEFINE_MUTEX(panel_lock);
+static LIST_HEAD(panel_list);
+
+void drm_panel_init(struct drm_panel *panel)
+{
+	INIT_LIST_HEAD(&panel->list);
+}
+EXPORT_SYMBOL(drm_panel_init);
+
+int drm_panel_add(struct drm_panel *panel)
+{
+	mutex_lock(&panel_lock);
+	list_add_tail(&panel->list, &panel_list);
+	mutex_unlock(&panel_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_panel_add);
+
+void drm_panel_remove(struct drm_panel *panel)
+{
+	mutex_lock(&panel_lock);
+	list_del_init(&panel->list);
+	mutex_unlock(&panel_lock);
+}
+EXPORT_SYMBOL(drm_panel_remove);
+
+int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector)
+{
+	if (panel->connector)
+		return -EBUSY;
+
+	panel->connector = connector;
+	panel->drm = connector->dev;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_panel_attach);
+
+int drm_panel_detach(struct drm_panel *panel)
+{
+	panel->connector = NULL;
+	panel->drm = NULL;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_panel_detach);
+
+#ifdef CONFIG_OF
+struct drm_panel *of_drm_find_panel(struct device_node *np)
+{
+	struct drm_panel *panel;
+
+	mutex_lock(&panel_lock);
+
+	list_for_each_entry(panel, &panel_list, list) {
+		if (panel->dev->of_node == np) {
+			mutex_unlock(&panel_lock);
+			return panel;
+		}
+	}
+
+	mutex_unlock(&panel_lock);
+	return NULL;
+}
+EXPORT_SYMBOL(of_drm_find_panel);
+#endif
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
new file mode 100644
index 0000000..2ddd5bd
--- /dev/null
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -0,0 +1,4 @@
+menuconfig DRM_PANEL
+	bool "DRM panel support"
+	help
+	  Panel registration and lookup framework.
diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h
new file mode 100644
index 0000000..4c8760b
--- /dev/null
+++ b/include/drm/drm_panel.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2013, NVIDIA Corporation.  All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __DRM_PANEL_H__
+#define __DRM_PANEL_H__
+
+#include <linux/list.h>
+
+struct drm_connector;
+struct drm_device;
+struct drm_panel;
+
+struct drm_panel_funcs {
+	void (*disable)(struct drm_panel *panel);
+	void (*enable)(struct drm_panel *panel);
+	int (*get_modes)(struct drm_panel *panel);
+};
+
+struct drm_panel {
+	struct drm_device *drm;
+	struct drm_connector *connector;
+	struct device *dev;
+
+	const struct drm_panel_funcs *funcs;
+
+	struct list_head list;
+};
+
+static inline void drm_panel_disable(struct drm_panel *panel)
+{
+	if (panel && panel->funcs && panel->funcs->disable)
+		panel->funcs->disable(panel);
+}
+
+static inline void drm_panel_enable(struct drm_panel *panel)
+{
+	if (panel && panel->funcs && panel->funcs->enable)
+		panel->funcs->enable(panel);
+}
+
+void drm_panel_init(struct drm_panel *panel);
+
+int drm_panel_add(struct drm_panel *panel);
+void drm_panel_remove(struct drm_panel *panel);
+
+int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector);
+int drm_panel_detach(struct drm_panel *panel);
+
+#ifdef CONFIG_OF
+struct drm_panel *of_drm_find_panel(struct device_node *np);
+#else
+static inline struct drm_panel *of_drm_find_panel(struct device_node *np)
+{
+	return NULL;
+}
+#endif
+
+#endif
-- 
1.8.4

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

* [PATCH v2 22/27] drm/panel: Add simple panel support
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (20 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 21/27] drm: Add panel support Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
       [not found]     ` <1381134884-5816-23-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2013-10-07  8:34   ` [PATCH v2 23/27] drm/tegra: Implement " Thierry Reding
                     ` (4 subsequent siblings)
  26 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

Add a driver for simple panels. Such panels can have a regulator that
provides the supply voltage and a separate GPIO to enable the panel.
Optionally the panels can have a backlight associated with them so it
can be enabled or disabled according to the panel's power management
mode.

Support is added for three panels: An AU Optronics 10.1" WSVGA, a
Chunghwa Picture Tubes 10.1" WXGA and a Panasonic 10.1 WUXGA TFT LCD
panel.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
Changes in v2:
- update vendor prefixes (cptt -> chunghwa, pc -> panasonic)
- split up panel binding documents per-panel
- make regulator mandatory
- add flag to keep track of enabled status

 .../devicetree/bindings/panel/auo,b101aw03.txt     |   7 +
 .../bindings/panel/chunghwa,claa101wb03.txt        |   7 +
 .../bindings/panel/panasonic,vvx10f004b00.txt      |   7 +
 .../devicetree/bindings/panel/simple-panel.txt     |  21 ++
 drivers/gpu/drm/Makefile                           |   1 +
 drivers/gpu/drm/panel/Kconfig                      |  13 +
 drivers/gpu/drm/panel/Makefile                     |   1 +
 drivers/gpu/drm/panel/panel-simple.c               | 339 +++++++++++++++++++++
 8 files changed, 396 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/panel/auo,b101aw03.txt
 create mode 100644 Documentation/devicetree/bindings/panel/chunghwa,claa101wb03.txt
 create mode 100644 Documentation/devicetree/bindings/panel/panasonic,vvx10f004b00.txt
 create mode 100644 Documentation/devicetree/bindings/panel/simple-panel.txt
 create mode 100644 drivers/gpu/drm/panel/Makefile
 create mode 100644 drivers/gpu/drm/panel/panel-simple.c

diff --git a/Documentation/devicetree/bindings/panel/auo,b101aw03.txt b/Documentation/devicetree/bindings/panel/auo,b101aw03.txt
new file mode 100644
index 0000000..72e088a
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/auo,b101aw03.txt
@@ -0,0 +1,7 @@
+AU Optronics Corporation 10.1" WSVGA TFT LCD panel
+
+Required properties:
+- compatible: should be "auo,b101aw03"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/panel/chunghwa,claa101wb03.txt b/Documentation/devicetree/bindings/panel/chunghwa,claa101wb03.txt
new file mode 100644
index 0000000..0ab2c05
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/chunghwa,claa101wb03.txt
@@ -0,0 +1,7 @@
+Chunghwa Picture Tubes Ltd. 10.1" WXGA TFT LCD panel
+
+Required properties:
+- compatible: should be "chunghwa,claa101wb03"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/panel/panasonic,vvx10f004b00.txt b/Documentation/devicetree/bindings/panel/panasonic,vvx10f004b00.txt
new file mode 100644
index 0000000..d328b03
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/panasonic,vvx10f004b00.txt
@@ -0,0 +1,7 @@
+Panasonic Corporation 10.1" WUXGA TFT LCD panel
+
+Required properties:
+- compatible: should be "panasonic,vvx10f004b00"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/panel/simple-panel.txt b/Documentation/devicetree/bindings/panel/simple-panel.txt
new file mode 100644
index 0000000..1341bbf
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/simple-panel.txt
@@ -0,0 +1,21 @@
+Simple display panel
+
+Required properties:
+- power-supply: regulator to provide the supply voltage
+
+Optional properties:
+- ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
+- enable-gpios: GPIO pin to enable or disable the panel
+- backlight: phandle of the backlight device attached to the panel
+
+Example:
+
+	panel: panel {
+		compatible = "cptt,claa101wb01";
+		ddc-i2c-bus = <&panelddc>;
+
+		power-supply = <&vdd_pnl_reg>;
+		enable-gpios = <&gpio 90 0>;
+
+		backlight = <&backlight>;
+	};
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 81363a9..a9859e0 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -58,3 +58,4 @@ obj-$(CONFIG_DRM_QXL) += qxl/
 obj-$(CONFIG_DRM_MSM) += msm/
 obj-$(CONFIG_DRM_TEGRA) += tegra/
 obj-y			+= i2c/
+obj-y			+= panel/
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 2ddd5bd..843087b 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -2,3 +2,16 @@ menuconfig DRM_PANEL
 	bool "DRM panel support"
 	help
 	  Panel registration and lookup framework.
+
+if DRM_PANEL
+
+config DRM_PANEL_SIMPLE
+	bool "support for simple panels"
+	depends on OF
+	help
+	  DRM panel driver for dumb panels that need at most a regulator and
+	  a GPIO to be powered up. Optionally a backlight can be attached so
+	  that it can be automatically turned off when the panel goes into a
+	  low power state.
+
+endif
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
new file mode 100644
index 0000000..af9dfa2
--- /dev/null
+++ b/drivers/gpu/drm/panel/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
new file mode 100644
index 0000000..b0fb103
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2013, NVIDIA Corporation.  All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <linux/backlight.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_panel.h>
+
+struct panel_desc {
+	const struct drm_display_mode *modes;
+	unsigned int num_modes;
+
+	struct {
+		unsigned int width;
+		unsigned int height;
+	} size;
+};
+
+/* TODO: convert to gpiod_*() API once it's been merged */
+#define GPIO_ACTIVE_LOW	(1 << 0)
+
+struct panel_simple {
+	struct drm_panel base;
+	bool enabled;
+
+	const struct panel_desc *desc;
+
+	struct backlight_device *backlight;
+	struct regulator *supply;
+
+	unsigned long enable_gpio_flags;
+	int enable_gpio;
+};
+
+static inline struct panel_simple *to_panel_simple(struct drm_panel *panel)
+{
+	return container_of(panel, struct panel_simple, base);
+}
+
+static void panel_simple_disable(struct drm_panel *panel)
+{
+	struct panel_simple *p = to_panel_simple(panel);
+
+	if (!p->enabled)
+		return;
+
+	if (p->backlight) {
+		p->backlight->props.power = FB_BLANK_POWERDOWN;
+		backlight_update_status(p->backlight);
+	}
+
+	if (gpio_is_valid(p->enable_gpio)) {
+		if (p->enable_gpio_flags & GPIO_ACTIVE_LOW)
+			gpio_set_value(p->enable_gpio, 1);
+		else
+			gpio_set_value(p->enable_gpio, 0);
+	}
+
+	regulator_disable(p->supply);
+	p->enabled = false;
+}
+
+static void panel_simple_enable(struct drm_panel *panel)
+{
+	struct panel_simple *p = to_panel_simple(panel);
+	int err;
+
+	if (p->enabled)
+		return;
+
+	err = regulator_enable(p->supply);
+	if (err < 0)
+		dev_err(panel->dev, "failed to enable supply: %d\n", err);
+
+	if (gpio_is_valid(p->enable_gpio)) {
+		if (p->enable_gpio_flags & GPIO_ACTIVE_LOW)
+			gpio_set_value(p->enable_gpio, 0);
+		else
+			gpio_set_value(p->enable_gpio, 1);
+	}
+
+	if (p->backlight) {
+		p->backlight->props.power = FB_BLANK_UNBLANK;
+		backlight_update_status(p->backlight);
+	}
+
+	p->enabled = true;
+}
+
+static int panel_simple_get_modes(struct drm_panel *panel)
+{
+	struct panel_simple *p = to_panel_simple(panel);
+	struct drm_display_mode *mode;
+	unsigned int i;
+
+	for (i = 0; i < p->desc->num_modes; i++) {
+		mode = drm_mode_duplicate(panel->drm, &p->desc->modes[i]);
+		if (!mode)
+			return -ENOMEM;
+
+		drm_mode_set_name(mode);
+
+		drm_mode_probed_add(panel->connector, mode);
+	}
+
+	return p->desc->num_modes;
+}
+
+static const struct drm_panel_funcs panel_simple_funcs = {
+	.disable = panel_simple_disable,
+	.enable = panel_simple_enable,
+	.get_modes = panel_simple_get_modes,
+};
+
+static const struct drm_display_mode auo_b101aw03_mode = {
+	.clock = 51450,
+	.hdisplay = 1024,
+	.hsync_start = 1024 + 156,
+	.hsync_end = 1024 + 156 + 8,
+	.htotal = 1024 + 156 + 8 + 156,
+	.vdisplay = 600,
+	.vsync_start = 600 + 16,
+	.vsync_end = 600 + 16 + 6,
+	.vtotal = 600 + 16 + 6 + 16,
+	.vrefresh = 60,
+};
+
+static const struct panel_desc auo_b101aw03 = {
+	.modes = &auo_b101aw03_mode,
+	.num_modes = 1,
+	.size = {
+		.width = 223,
+		.height = 125,
+	},
+};
+
+static const struct drm_display_mode chunghwa_claa101wb01_mode = {
+	.clock = 69300,
+	.hdisplay = 1366,
+	.hsync_start = 1366 + 48,
+	.hsync_end = 1366 + 48 + 32,
+	.htotal = 1366 + 48 + 32 + 20,
+	.vdisplay = 768,
+	.vsync_start = 768 + 16,
+	.vsync_end = 768 + 16 + 8,
+	.vtotal = 768 + 16 + 8 + 16,
+	.vrefresh = 60,
+};
+
+static const struct panel_desc chunghwa_claa101wb01 = {
+	.modes = &chunghwa_claa101wb01_mode,
+	.num_modes = 1,
+	.size = {
+		.width = 223,
+		.height = 125,
+	},
+};
+
+static const struct drm_display_mode panasonic_vvx10f004b00_mode = {
+	.clock = 154700,
+	.hdisplay = 1920,
+	.hsync_start = 1920 + 154,
+	.hsync_end = 1920 + 154 + 16,
+	.htotal = 1920 + 154 + 16 + 32,
+	.vdisplay = 1200,
+	.vsync_start = 1200 + 17,
+	.vsync_end = 1200 + 17 + 2,
+	.vtotal = 1200 + 17 + 2 + 16,
+	.vrefresh = 60,
+};
+
+static const struct panel_desc panasonic_vvx10f004b00 = {
+	.modes = &panasonic_vvx10f004b00_mode,
+	.num_modes = 1,
+	.size = {
+		.width = 217,
+		.height = 136,
+	},
+};
+
+static const struct of_device_id panel_simple_of_match[] = {
+	{
+		.compatible = "auo,b101aw03",
+		.data = &auo_b101aw03,
+	}, {
+		.compatible = "chunghwa,claa101wb01",
+		.data = &chunghwa_claa101wb01
+	}, {
+		.compatible = "panasonic,vvx10f004b00",
+		.data = &panasonic_vvx10f004b00
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(of, panel_simple_of_match);
+
+static int panel_simple_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *id;
+	struct device_node *backlight;
+	struct panel_simple *panel;
+	enum of_gpio_flags flags;
+	int err;
+
+	panel = devm_kzalloc(&pdev->dev, sizeof(*panel), GFP_KERNEL);
+	if (!panel)
+		return -ENOMEM;
+
+	id = of_match_node(panel_simple_of_match, pdev->dev.of_node);
+	if (!id)
+		return -ENODEV;
+
+	panel->desc = id->data;
+	panel->enabled = false;
+
+	panel->supply = devm_regulator_get(&pdev->dev, "power");
+	if (IS_ERR(panel->supply))
+		return PTR_ERR(panel->supply);
+
+	panel->enable_gpio = of_get_named_gpio_flags(pdev->dev.of_node,
+						     "enable-gpios", 0,
+						     &flags);
+	if (gpio_is_valid(panel->enable_gpio)) {
+		unsigned int value;
+
+		if (flags & OF_GPIO_ACTIVE_LOW)
+			panel->enable_gpio_flags |= GPIO_ACTIVE_LOW;
+
+		err = gpio_request(panel->enable_gpio, "enable");
+		if (err < 0) {
+			dev_err(&pdev->dev, "failed to request GPIO#%u: %d\n",
+				panel->enable_gpio, err);
+			return err;
+		}
+
+		value = (panel->enable_gpio_flags & GPIO_ACTIVE_LOW) != 0;
+
+		err = gpio_direction_output(panel->enable_gpio, value);
+		if (err < 0) {
+			dev_err(&pdev->dev, "failed to setup GPIO%u: %d\n",
+				panel->enable_gpio, err);
+			goto free_gpio;
+		}
+	}
+
+	backlight = of_parse_phandle(pdev->dev.of_node, "backlight", 0);
+	if (backlight) {
+		panel->backlight = of_find_backlight_by_node(backlight);
+		if (!panel->backlight) {
+			err = -EPROBE_DEFER;
+			goto free_gpio;
+		}
+
+		of_node_put(backlight);
+	}
+
+	drm_panel_init(&panel->base);
+	panel->base.dev = &pdev->dev;
+	panel->base.funcs = &panel_simple_funcs;
+
+	err = drm_panel_add(&panel->base);
+	if (err < 0)
+		goto free_gpio;
+
+	platform_set_drvdata(pdev, panel);
+
+	return 0;
+
+free_gpio:
+	if (gpio_is_valid(panel->enable_gpio))
+		gpio_free(panel->enable_gpio);
+
+	return err;
+}
+
+static int panel_simple_remove(struct platform_device *pdev)
+{
+	struct panel_simple *panel = platform_get_drvdata(pdev);
+
+	if (gpio_is_valid(panel->enable_gpio)) {
+		if (panel->enable_gpio_flags & GPIO_ACTIVE_LOW)
+			gpio_set_value(panel->enable_gpio, 1);
+		else
+			gpio_set_value(panel->enable_gpio, 0);
+
+		gpio_free(panel->enable_gpio);
+	}
+
+	regulator_disable(panel->supply);
+
+	if (panel->backlight)
+		put_device(&panel->backlight->dev);
+
+	drm_panel_detach(&panel->base);
+	drm_panel_remove(&panel->base);
+
+	return 0;
+}
+
+static struct platform_driver panel_simple_driver = {
+	.driver = {
+		.name = "panel-simple",
+		.owner = THIS_MODULE,
+		.of_match_table = panel_simple_of_match,
+	},
+	.probe = panel_simple_probe,
+	.remove = panel_simple_remove,
+};
+module_platform_driver(panel_simple_driver);
+
+MODULE_DESCRIPTION("DRM Driver for Simple Panels");
+MODULE_AUTHOR("Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>");
+MODULE_LICENSE("GPL v2");
-- 
1.8.4

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

* [PATCH v2 23/27] drm/tegra: Implement panel support
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (21 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 22/27] drm/panel: Add simple " Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
  2013-10-07  8:34   ` [PATCH v2 24/27] drm/tegra: Start connectors with correct DPMS mode Thierry Reding
                     ` (3 subsequent siblings)
  26 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

Use the DRM panel framework to attach a panel to an output.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/drm/tegra/Kconfig  |  1 +
 drivers/gpu/drm/tegra/drm.h    |  1 +
 drivers/gpu/drm/tegra/output.c | 32 ++++++++++++++++++++++++++++++--
 3 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig
index 7759eea..d1dde2b 100644
--- a/drivers/gpu/drm/tegra/Kconfig
+++ b/drivers/gpu/drm/tegra/Kconfig
@@ -2,6 +2,7 @@ config DRM_TEGRA
 	bool "NVIDIA Tegra DRM"
 	depends on DRM
 	select DRM_KMS_HELPER
+	select DRM_PANEL
 	select FB_SYS_FILLRECT
 	select FB_SYS_COPYAREA
 	select FB_SYS_IMAGEBLIT
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 25522e2..a8ba13c 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -176,6 +176,7 @@ struct tegra_output {
 	const struct tegra_output_ops *ops;
 	enum tegra_output_type type;
 
+	struct drm_panel *panel;
 	struct i2c_adapter *ddc;
 	const struct edid *edid;
 	unsigned int hpd_irq;
diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c
index 8f40fa6..be6ef34 100644
--- a/drivers/gpu/drm/tegra/output.c
+++ b/drivers/gpu/drm/tegra/output.c
@@ -9,6 +9,7 @@
 
 #include <linux/of_gpio.h>
 
+#include <drm/drm_panel.h>
 #include "drm.h"
 
 static int tegra_connector_get_modes(struct drm_connector *connector)
@@ -17,6 +18,9 @@ static int tegra_connector_get_modes(struct drm_connector *connector)
 	struct edid *edid = NULL;
 	int err = 0;
 
+	if (output->panel)
+		return output->panel->funcs->get_modes(output->panel);
+
 	if (output->edid)
 		edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL);
 	else if (output->ddc)
@@ -72,6 +76,9 @@ tegra_connector_detect(struct drm_connector *connector, bool force)
 		else
 			status = connector_status_connected;
 	} else {
+		if (output->panel)
+			status = connector_status_connected;
+
 		if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
 			status = connector_status_connected;
 	}
@@ -103,6 +110,15 @@ static const struct drm_encoder_funcs encoder_funcs = {
 
 static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode)
 {
+	struct tegra_output *output = encoder_to_output(encoder);
+	struct drm_panel *panel = output->panel;
+
+	if (panel && panel->funcs) {
+		if (mode != DRM_MODE_DPMS_ON)
+			drm_panel_disable(panel);
+		else
+			drm_panel_enable(panel);
+	}
 }
 
 static bool tegra_encoder_mode_fixup(struct drm_encoder *encoder,
@@ -151,14 +167,23 @@ static irqreturn_t hpd_irq(int irq, void *data)
 
 int tegra_output_parse_dt(struct tegra_output *output)
 {
+	struct device_node *ddc, *panel;
 	enum of_gpio_flags flags;
-	struct device_node *ddc;
 	size_t size;
 	int err;
 
 	if (!output->of_node)
 		output->of_node = output->dev->of_node;
 
+	panel = of_parse_phandle(output->of_node, "nvidia,panel", 0);
+	if (panel) {
+		output->panel = of_drm_find_panel(panel);
+		if (!output->panel)
+			return -EPROBE_DEFER;
+
+		of_node_put(panel);
+	}
+
 	output->edid = of_get_property(output->of_node, "nvidia,edid", &size);
 
 	ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0);
@@ -173,7 +198,7 @@ int tegra_output_parse_dt(struct tegra_output *output)
 		of_node_put(ddc);
 	}
 
-	if (!output->edid && !output->ddc)
+	if (!output->panel && !output->edid && !output->ddc)
 		return -ENODEV;
 
 	output->hpd_gpio = of_get_named_gpio_flags(output->of_node,
@@ -240,6 +265,9 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
 			   connector);
 	drm_connector_helper_add(&output->connector, &connector_helper_funcs);
 
+	if (output->panel)
+		drm_panel_attach(output->panel, &output->connector);
+
 	drm_encoder_init(drm, &output->encoder, &encoder_funcs, encoder);
 	drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs);
 
-- 
1.8.4

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

* [PATCH v2 24/27] drm/tegra: Start connectors with correct DPMS mode
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (22 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 23/27] drm/tegra: Implement " Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
  2013-10-07  8:34   ` [PATCH v2 25/27] gpu: host1x: Add MIPI pad calibration support Thierry Reding
                     ` (2 subsequent siblings)
  26 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

A connector's DPMS mode isn't initialized by default, therefore using a
default of 0 (DRM_MODE_DPMS_ON). This can cause problems in that the DRM
core won't explicitly turn on a connector because it thinks that it is
already on.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
Note that it would probably make sense to do this in the core, but after
some discussion on IRC it became clear that other drivers (specifically
i915) use similar workarounds and moving this to the core may cause them
to regress.

 drivers/gpu/drm/tegra/output.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c
index be6ef34..d911fe8 100644
--- a/drivers/gpu/drm/tegra/output.c
+++ b/drivers/gpu/drm/tegra/output.c
@@ -264,6 +264,7 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
 	drm_connector_init(drm, &output->connector, &connector_funcs,
 			   connector);
 	drm_connector_helper_add(&output->connector, &connector_helper_funcs);
+	output->connector.dpms = DRM_MODE_DPMS_OFF;
 
 	if (output->panel)
 		drm_panel_attach(output->panel, &output->connector);
-- 
1.8.4

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

* [PATCH v2 25/27] gpu: host1x: Add MIPI pad calibration support
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (23 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 24/27] drm/tegra: Start connectors with correct DPMS mode Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
       [not found]     ` <1381134884-5816-26-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2013-10-07  8:34   ` [PATCH v2 26/27] drm/tegra: Add DSI support Thierry Reding
  2013-10-07  8:34   ` [PATCH v2 27/27] drm/tegra: Add Tegra114 gr2d support Thierry Reding
  26 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

This driver adds support to perform calibration of the MIPI pads for CSI
and DSI.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
Changes in v2:
- rename fields to mirror the names in the TRM
- remove unused fields

 drivers/gpu/host1x/Makefile |   1 +
 drivers/gpu/host1x/dev.c    |  17 +++-
 drivers/gpu/host1x/dev.h    |   2 +
 drivers/gpu/host1x/mipi.c   | 230 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/host1x.h      |   2 +
 5 files changed, 248 insertions(+), 4 deletions(-)
 create mode 100644 drivers/gpu/host1x/mipi.c

diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index afa1e9e..de305c2 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -7,6 +7,7 @@ host1x-y = \
 	channel.o \
 	job.o \
 	debug.o \
+	mipi.o \
 	hw/host1x01.o \
 	hw/host1x02.o
 
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index ab402a5..12d6333 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -208,17 +208,26 @@ static int __init tegra_host1x_init(void)
 		return err;
 
 	err = platform_driver_register(&tegra_host1x_driver);
-	if (err < 0) {
-		host1x_bus_exit();
-		return err;
-	}
+	if (err < 0)
+		goto unregister_bus;
+
+	err = platform_driver_register(&tegra_mipi_driver);
+	if (err < 0)
+		goto unregister_host1x;
 
 	return 0;
+
+unregister_host1x:
+	platform_driver_unregister(&tegra_host1x_driver);
+unregister_bus:
+	host1x_bus_exit();
+	return err;
 }
 module_init(tegra_host1x_init);
 
 static void __exit tegra_host1x_exit(void)
 {
+	platform_driver_unregister(&tegra_mipi_driver);
 	platform_driver_unregister(&tegra_host1x_driver);
 	host1x_bus_exit();
 }
diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h
index 6cf689b..65c80dc 100644
--- a/drivers/gpu/host1x/dev.h
+++ b/drivers/gpu/host1x/dev.h
@@ -304,4 +304,6 @@ static inline void host1x_hw_show_mlocks(struct host1x *host, struct output *o)
 	host->debug_op->show_mlocks(host, o);
 }
 
+extern struct platform_driver tegra_mipi_driver;
+
 #endif
diff --git a/drivers/gpu/host1x/mipi.c b/drivers/gpu/host1x/mipi.c
new file mode 100644
index 0000000..8a54613
--- /dev/null
+++ b/drivers/gpu/host1x/mipi.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2013 NVIDIA Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define MIPI_CAL_CTRL			0x00
+#define MIPI_CAL_CTRL_START		(1 << 0)
+
+#define MIPI_CAL_AUTOCAL_CTRL		0x01
+
+#define MIPI_CAL_STATUS			0x02
+#define MIPI_CAL_STATUS_DONE		(1 << 16)
+#define MIPI_CAL_STATUS_ACTIVE		(1 <<  0)
+
+#define MIPI_CAL_CONFIG_CSIA		0x05
+#define MIPI_CAL_CONFIG_CSIB		0x06
+#define MIPI_CAL_CONFIG_CSIC		0x07
+#define MIPI_CAL_CONFIG_CSID		0x08
+#define MIPI_CAL_CONFIG_CSIE		0x09
+#define MIPI_CAL_CONFIG_DSIA		0x0e
+#define MIPI_CAL_CONFIG_DSIB		0x0f
+#define MIPI_CAL_CONFIG_DSIC		0x10
+#define MIPI_CAL_CONFIG_DSID		0x11
+
+#define MIPI_CAL_CONFIG_SELECT		(1 << 21)
+#define MIPI_CAL_CONFIG_HSPDOS(x)	(((x) & 0x1f) << 16)
+#define MIPI_CAL_CONFIG_HSPUOS(x)	(((x) & 0x1f) <<  8)
+#define MIPI_CAL_CONFIG_TERMOS(x)	(((x) & 0x1f) <<  0)
+
+#define MIPI_CAL_BIAS_PAD_CFG0		0x16
+#define MIPI_CAL_BIAS_PAD_PDVCLAMP	(1 << 1)
+#define MIPI_CAL_BIAS_PAD_E_VCLAMP_REF	(1 << 0)
+
+#define MIPI_CAL_BIAS_PAD_CFG1		0x17
+
+#define MIPI_CAL_BIAS_PAD_CFG2		0x18
+#define MIPI_CAL_BIAS_PAD_PDVREG	(1 << 1)
+
+static const struct module {
+	unsigned long reg;
+} modules[] = {
+	{ .reg = MIPI_CAL_CONFIG_CSIA },
+	{ .reg = MIPI_CAL_CONFIG_CSIB },
+	{ .reg = MIPI_CAL_CONFIG_CSIC },
+	{ .reg = MIPI_CAL_CONFIG_CSID },
+	{ .reg = MIPI_CAL_CONFIG_CSIE },
+	{ .reg = MIPI_CAL_CONFIG_DSIA },
+	{ .reg = MIPI_CAL_CONFIG_DSIB },
+	{ .reg = MIPI_CAL_CONFIG_DSIC },
+	{ .reg = MIPI_CAL_CONFIG_DSID },
+};
+
+struct tegra_mipi {
+	void __iomem *regs;
+	struct mutex lock;
+	struct clk *clk;
+};
+
+static inline unsigned long tegra_mipi_readl(struct tegra_mipi *mipi,
+					     unsigned long reg)
+{
+	return readl(mipi->regs + (reg << 2));
+}
+
+static inline void tegra_mipi_writel(struct tegra_mipi *mipi,
+				     unsigned long value, unsigned long reg)
+{
+	writel(value, mipi->regs + (reg << 2));
+}
+
+int tegra_mipi_calibrate(struct device *device)
+{
+	struct platform_device *pdev;
+	unsigned int timeout = 20, i;
+	struct of_phandle_args args;
+	unsigned long value, pads;
+	struct tegra_mipi *mipi;
+	int err;
+
+	err = of_parse_phandle_with_args(device->of_node, "calibrate",
+					 "#calibrate-cells", 0, &args);
+	if (err < 0)
+		return err;
+
+	pdev = of_find_device_by_node(args.np);
+	if (!pdev) {
+		of_node_put(args.np);
+		return -ENODEV;
+	}
+
+	of_node_put(args.np);
+	pads = args.args[0];
+
+	mipi = platform_get_drvdata(pdev);
+	if (!mipi) {
+		err = -ENODEV;
+		goto out;
+	}
+
+	err = clk_enable(mipi->clk);
+	if (err < 0)
+		goto out;
+
+	mutex_lock(&mipi->lock);
+
+	value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG0);
+	value &= ~MIPI_CAL_BIAS_PAD_PDVCLAMP;
+	value |= MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;
+	tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG0);
+
+	value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2);
+	value &= ~MIPI_CAL_BIAS_PAD_PDVREG;
+	tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
+
+	for (i = 0; i < ARRAY_SIZE(modules); i++) {
+		if (pads & BIT(i))
+			value = MIPI_CAL_CONFIG_SELECT |
+				MIPI_CAL_CONFIG_HSPDOS(0) |
+				MIPI_CAL_CONFIG_HSPUOS(4) |
+				MIPI_CAL_CONFIG_TERMOS(5);
+		else
+			value = 0;
+
+		tegra_mipi_writel(mipi, value, modules[i].reg);
+	}
+
+	tegra_mipi_writel(mipi, MIPI_CAL_CTRL_START, MIPI_CAL_CTRL);
+
+	while (timeout) {
+		value = tegra_mipi_readl(mipi, MIPI_CAL_STATUS);
+		if ((value & MIPI_CAL_STATUS_ACTIVE) == 0 &&
+		    (value & MIPI_CAL_STATUS_DONE) != 0)
+			break;
+
+		usleep_range(10, 100);
+		timeout--;
+	}
+
+	mutex_unlock(&mipi->lock);
+	clk_disable(mipi->clk);
+
+	if (timeout == 0)
+		err = -ETIMEDOUT;
+	else
+		err = 0;
+
+out:
+	platform_device_put(pdev);
+	return err;
+}
+EXPORT_SYMBOL_GPL(tegra_mipi_calibrate);
+
+static int tegra_mipi_probe(struct platform_device *pdev)
+{
+	struct tegra_mipi *mipi;
+	struct resource *res;
+	int err;
+
+	mipi = devm_kzalloc(&pdev->dev, sizeof(*mipi), GFP_KERNEL);
+	if (!mipi)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mipi->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(mipi->regs))
+		return PTR_ERR(mipi->regs);
+
+	mutex_init(&mipi->lock);
+
+	mipi->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(mipi->clk)) {
+		dev_err(&pdev->dev, "failed to get clock\n");
+		return PTR_ERR(mipi->clk);
+	}
+
+	err = clk_prepare(mipi->clk);
+	if (err < 0)
+		return err;
+
+	platform_set_drvdata(pdev, mipi);
+
+	return 0;
+}
+
+static int tegra_mipi_remove(struct platform_device *pdev)
+{
+	struct tegra_mipi *mipi = platform_get_drvdata(pdev);
+
+	clk_unprepare(mipi->clk);
+
+	return 0;
+}
+
+static struct of_device_id tegra_mipi_of_match[] = {
+	{ .compatible = "nvidia,tegra114-mipi", },
+	{ },
+};
+
+struct platform_driver tegra_mipi_driver = {
+	.driver = {
+		.name = "tegra-mipi",
+		.of_match_table = tegra_mipi_of_match,
+	},
+	.probe = tegra_mipi_probe,
+	.remove = tegra_mipi_remove,
+};
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index a091792..9bf44a6 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -273,4 +273,6 @@ int host1x_register_client(struct host1x *host1x, struct host1x_client *client);
 int host1x_unregister_client(struct host1x *host1x,
 			     struct host1x_client *client);
 
+int tegra_mipi_calibrate(struct device *device);
+
 #endif
-- 
1.8.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 26/27] drm/tegra: Add DSI support
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (24 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 25/27] gpu: host1x: Add MIPI pad calibration support Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
       [not found]     ` <1381134884-5816-27-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2013-10-07  8:34   ` [PATCH v2 27/27] drm/tegra: Add Tegra114 gr2d support Thierry Reding
  26 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

This commit adds support for both DSI outputs found on Tegra. Only very
minimal functionality is implemented, so advanced features like ganged
mode won't work.

Due to the lack of other test hardware, some sections of the driver are
hardcoded to work with Dalmore.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/drm/tegra/Makefile |    1 +
 drivers/gpu/drm/tegra/dc.h     |    1 +
 drivers/gpu/drm/tegra/drm.c    |   10 +-
 drivers/gpu/drm/tegra/drm.h    |    2 +
 drivers/gpu/drm/tegra/dsi.c    | 1026 ++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/tegra/output.c |    5 +
 6 files changed, 1044 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/tegra/dsi.c

diff --git a/drivers/gpu/drm/tegra/Makefile b/drivers/gpu/drm/tegra/Makefile
index abb267c..6d16d43 100644
--- a/drivers/gpu/drm/tegra/Makefile
+++ b/drivers/gpu/drm/tegra/Makefile
@@ -10,6 +10,7 @@ tegra-drm-y := \
 	output.o \
 	rgb.o \
 	hdmi.o \
+	dsi.o \
 	gr2d.o
 
 obj-$(CONFIG_DRM_TEGRA) += tegra-drm.o
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index 79eaec9..5e2006c 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -116,6 +116,7 @@
 
 #define DC_DISP_DISP_WIN_OPTIONS		0x402
 #define HDMI_ENABLE (1 << 30)
+#define DSI_ENABLE  (1 << 29)
 
 #define DC_DISP_DISP_MEM_HIGH_PRIORITY		0x403
 #define CURSOR_THRESHOLD(x)   (((x) & 0x03) << 24)
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 4afc9e1..d95be81 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -490,6 +490,7 @@ static const struct of_device_id host1x_drm_subdevs[] = {
 	{ .compatible = "nvidia,tegra30-hdmi", },
 	{ .compatible = "nvidia,tegra30-gr2d", },
 	{ .compatible = "nvidia,tegra114-dc", },
+	{ .compatible = "nvidia,tegra114-dsi", },
 	{ .compatible = "nvidia,tegra114-hdmi", },
 	{ /* sentinel */ }
 };
@@ -513,10 +514,14 @@ static int __init host1x_drm_init(void)
 	if (err < 0)
 		goto unregister_host1x;
 
-	err = platform_driver_register(&tegra_hdmi_driver);
+	err = platform_driver_register(&tegra_dsi_driver);
 	if (err < 0)
 		goto unregister_dc;
 
+	err = platform_driver_register(&tegra_hdmi_driver);
+	if (err < 0)
+		goto unregister_dsi;
+
 	err = platform_driver_register(&tegra_gr2d_driver);
 	if (err < 0)
 		goto unregister_hdmi;
@@ -525,6 +530,8 @@ static int __init host1x_drm_init(void)
 
 unregister_hdmi:
 	platform_driver_unregister(&tegra_hdmi_driver);
+unregister_dsi:
+	platform_driver_unregister(&tegra_dsi_driver);
 unregister_dc:
 	platform_driver_unregister(&tegra_dc_driver);
 unregister_host1x:
@@ -537,6 +544,7 @@ static void __exit host1x_drm_exit(void)
 {
 	platform_driver_unregister(&tegra_gr2d_driver);
 	platform_driver_unregister(&tegra_hdmi_driver);
+	platform_driver_unregister(&tegra_dsi_driver);
 	platform_driver_unregister(&tegra_dc_driver);
 	host1x_driver_unregister(&host1x_drm_driver);
 }
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index a8ba13c..3dd43c7 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -167,6 +167,7 @@ struct tegra_output_ops {
 enum tegra_output_type {
 	TEGRA_OUTPUT_RGB,
 	TEGRA_OUTPUT_HDMI,
+	TEGRA_OUTPUT_DSI,
 };
 
 struct tegra_output {
@@ -253,6 +254,7 @@ extern void tegra_drm_fb_exit(struct drm_device *drm);
 extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
 
 extern struct platform_driver tegra_dc_driver;
+extern struct platform_driver tegra_dsi_driver;
 extern struct platform_driver tegra_hdmi_driver;
 extern struct platform_driver tegra_gr2d_driver;
 
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
new file mode 100644
index 0000000..0059f56
--- /dev/null
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -0,0 +1,1026 @@
+/*
+ * Copyright (C) 2013 NVIDIA Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk/tegra.h>
+#include <linux/debugfs.h>
+#include <linux/host1x.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "drm.h"
+#include "dc.h"
+
+#define DSI_INCR_SYNCPT			0x00
+#define DSI_INCR_SYNCPT_CONTROL		0x01
+#define DSI_INCR_SYNCPT_ERROR		0x02
+#define DSI_CTXSW			0x08
+#define DSI_RD_DATA			0x09
+#define DSI_WR_DATA			0x0a
+#define DSI_POWER_CONTROL		0x0b
+#define DSI_POWER_CONTROL_ENABLE	(1 << 0)
+#define DSI_INT_ENABLE			0x0c
+#define DSI_INT_STATUS			0x0d
+#define DSI_INT_MASK			0x0e
+#define DSI_HOST_CONTROL		0x0f
+#define DSI_HOST_CONTROL_RAW		(1 << 6)
+#define DSI_HOST_CONTROL_HS		(1 << 5)
+#define DSI_HOST_CONTROL_CS		(1 << 1)
+#define DSI_HOST_CONTROL_ECC		(1 << 0)
+#define DSI_CONTROL			0x10
+#define DSI_CONTROL_HS_CLK_CTRL		(1 << 20)
+#define DSI_CONTROL_CHANNEL(c)		(((c) & 0x3) << 16)
+#define DSI_CONTROL_FORMAT(f)		(((f) & 0x3) << 12)
+#define DSI_CONTROL_TX_TRIG(x)		(((x) & 0x3) <<  8)
+#define DSI_CONTROL_LANES(n)		(((n) & 0x3) <<  4)
+#define DSI_CONTROL_DCS_ENABLE		(1 << 3)
+#define DSI_CONTROL_SOURCE(s)		(((s) & 0x1) <<  2)
+#define DSI_CONTROL_VIDEO_ENABLE	(1 << 1)
+#define DSI_CONTROL_HOST_ENABLE		(1 << 0)
+#define DSI_SOL_DELAY			0x11
+#define DSI_MAX_THRESHOLD		0x12
+#define DSI_TRIGGER			0x13
+#define DSI_TX_CRC			0x14
+#define DSI_STATUS			0x15
+#define DSI_INIT_SEQ_CONTROL		0x1a
+#define DSI_INIT_SEQ_DATA_0		0x1b
+#define DSI_INIT_SEQ_DATA_1		0x1c
+#define DSI_INIT_SEQ_DATA_2		0x1d
+#define DSI_INIT_SEQ_DATA_3		0x1e
+#define DSI_INIT_SEQ_DATA_4		0x1f
+#define DSI_INIT_SEQ_DATA_5		0x20
+#define DSI_INIT_SEQ_DATA_6		0x21
+#define DSI_INIT_SEQ_DATA_7		0x22
+#define DSI_PKT_SEQ_0_LO		0x23
+#define DSI_PKT_SEQ_0_HI		0x24
+#define DSI_PKT_SEQ_1_LO		0x25
+#define DSI_PKT_SEQ_1_HI		0x26
+#define DSI_PKT_SEQ_2_LO		0x27
+#define DSI_PKT_SEQ_2_HI		0x28
+#define DSI_PKT_SEQ_3_LO		0x29
+#define DSI_PKT_SEQ_3_HI		0x2a
+#define DSI_PKT_SEQ_4_LO		0x2b
+#define DSI_PKT_SEQ_4_HI		0x2c
+#define DSI_PKT_SEQ_5_LO		0x2d
+#define DSI_PKT_SEQ_5_HI		0x2e
+#define DSI_DCS_CMDS			0x33
+#define DSI_PKT_LEN_0_1			0x34
+#define DSI_PKT_LEN_2_3			0x35
+#define DSI_PKT_LEN_4_5			0x36
+#define DSI_PKT_LEN_6_7			0x37
+#define DSI_PHY_TIMING_0		0x3c
+#define DSI_PHY_TIMING_1		0x3d
+#define DSI_PHY_TIMING_2		0x3e
+#define DSI_BTA_TIMING			0x3f
+
+#define DSI_TIMING_FIELD(value, period, hwinc) \
+	((DIV_ROUND_CLOSEST(value, period) - (hwinc)) & 0xff)
+
+#define DSI_TIMEOUT_0			0x44
+#define DSI_TIMEOUT_LRX(x)		(((x) & 0xffff) << 16)
+#define DSI_TIMEOUT_HTX(x)		(((x) & 0xffff) <<  0)
+#define DSI_TIMEOUT_1			0x45
+#define DSI_TIMEOUT_PR(x)		(((x) & 0xffff) << 16)
+#define DSI_TIMEOUT_TA(x)		(((x) & 0xffff) <<  0)
+#define DSI_TO_TALLY			0x46
+#define DSI_TALLY_TA(x)			(((x) & 0xff) << 16)
+#define DSI_TALLY_LRX(x)		(((x) & 0xff) <<  8)
+#define DSI_TALLY_HTX(x)		(((x) & 0xff) <<  0)
+#define DSI_PAD_CONTROL_0		0x4b
+#define DSI_PAD_CONTROL_VS1_PDIO(x)	(((x) & 0xf) <<  0)
+#define DSI_PAD_CONTROL_VS1_PDIO_CLK	(1 <<  8)
+#define DSI_PAD_CONTROL_VS1_PULLDN(x)	(((x) & 0xf) << 16)
+#define DSI_PAD_CONTROL_VS1_PULLDN_CLK	(1 << 24)
+#define DSI_PAD_CONTROL_CD		0x4c
+#define DSI_PAD_CD_STATUS		0x4d
+#define DSI_VIDEO_MODE_CONTROL		0x4e
+#define DSI_PAD_CONTROL_1		0x4f
+#define DSI_PAD_CONTROL_2		0x50
+#define DSI_PAD_OUT_CLK(x)		(((x) & 0x7) <<  0)
+#define DSI_PAD_LP_DN(x)		(((x) & 0x7) <<  4)
+#define DSI_PAD_LP_UP(x)		(((x) & 0x7) <<  8)
+#define DSI_PAD_SLEW_DN(x)		(((x) & 0x7) << 12)
+#define DSI_PAD_SLEW_UP(x)		(((x) & 0x7) << 16)
+#define DSI_PAD_CONTROL_3		0x51
+#define DSI_PAD_CONTROL_4		0x52
+#define DSI_GANGED_MODE_CONTROL		0x53
+#define DSI_GANGED_MODE_START		0x54
+#define DSI_GANGED_MODE_SIZE		0x55
+#define DSI_RAW_DATA_BYTE_COUNT		0x56
+#define DSI_ULTRA_LOW_POWER_CONTROL	0x57
+#define DSI_INIT_SEQ_DATA_8		0x58
+#define DSI_INIT_SEQ_DATA_9		0x59
+#define DSI_INIT_SEQ_DATA_10		0x5a
+#define DSI_INIT_SEQ_DATA_11		0x5b
+#define DSI_INIT_SEQ_DATA_12		0x5c
+#define DSI_INIT_SEQ_DATA_13		0x5d
+#define DSI_INIT_SEQ_DATA_14		0x5e
+#define DSI_INIT_SEQ_DATA_15		0x5f
+
+enum dsi_format {
+	DSI_FORMAT_16P,
+	DSI_FORMAT_18NP,
+	DSI_FORMAT_18P,
+	DSI_FORMAT_24P,
+};
+
+/*
+ * D-PHY timing parameters
+ *
+ * A detailed description of these parameters can be found in the  MIPI
+ * Alliance Specification for D-PHY, Section 5.9 "Global Operation Timing
+ * Parameters".
+ *
+ * All parameters are specified in nanoseconds.
+ */
+struct dsi_phy_timing {
+	unsigned int clkmiss;
+	unsigned int clkpost;
+	unsigned int clkpre;
+	unsigned int clkprepare;
+	unsigned int clksettle;
+	unsigned int clktermen;
+	unsigned int clktrail;
+	unsigned int clkzero;
+	unsigned int dtermen;
+	unsigned int eot;
+	unsigned int hsexit;
+	unsigned int hsprepare;
+	unsigned int hszero;
+	unsigned int hssettle;
+	unsigned int hsskip;
+	unsigned int hstrail;
+	unsigned int init;
+	unsigned int lpx;
+	unsigned int taget;
+	unsigned int tago;
+	unsigned int tasure;
+	unsigned int wakeup;
+};
+
+/*
+ * Default D-PHY timings based on MIPI D-PHY specification. Derived from
+ * the valid ranges specified in Section 5.9 of the D-PHY specification
+ * with minor adjustments.
+ */
+static int dsi_phy_timing_get_default(struct dsi_phy_timing *timing,
+				      unsigned long period)
+{
+	timing->clkmiss = 0;
+	timing->clkpost = 70 + 52 * period;
+	timing->clkpre = 8;
+	timing->clkprepare = 65;
+	timing->clksettle = 95;
+	timing->clktermen = 0;
+	timing->clktrail = 80;
+	timing->clkzero = 260;
+	timing->dtermen = 0;
+	timing->eot = 0;
+	timing->hsexit = 120;
+	timing->hsprepare = 65 + 5 * period;
+	timing->hszero = 145 + 5 * period;
+	timing->hssettle = 85 + 6 * period;
+	timing->hsskip = 40;
+	timing->hstrail = max(8 * period, 60 + 4 * period);
+	timing->init = 100000;
+	timing->lpx = 60;
+	timing->taget = 5 * timing->lpx;
+	timing->tago = 4 * timing->lpx;
+	timing->tasure = 2 * timing->lpx;
+	timing->wakeup = 1000000;
+
+	return 0;
+}
+
+/*
+ * Validate D-PHY timing according to MIPI Alliance Specification for D-PHY,
+ * Section 5.9 "Global Operation Timing Parameters".
+ */
+static int dsi_phy_timing_validate(struct dsi_phy_timing *timing,
+				   unsigned long period)
+{
+	if (timing->clkmiss > 60)
+		return -EINVAL;
+
+	if (timing->clkpost < (60 + 52 * period))
+		return -EINVAL;
+
+	if (timing->clkpre < 8)
+		return -EINVAL;
+
+	if (timing->clkprepare < 38 || timing->clkprepare > 95)
+		return -EINVAL;
+
+	if (timing->clksettle < 95 || timing->clksettle > 300)
+		return -EINVAL;
+
+	if (timing->clktermen > 38)
+		return -EINVAL;
+
+	if (timing->clktrail < 60)
+		return -EINVAL;
+
+	if (timing->clkprepare + timing->clkzero < 300)
+		return -EINVAL;
+
+	if (timing->dtermen > 35 + 4 * period)
+		return -EINVAL;
+
+	if (timing->eot > 105 + 12 * period)
+		return -EINVAL;
+
+	if (timing->hsexit < 100)
+		return -EINVAL;
+
+	if (timing->hsprepare < 40 + 4 * period ||
+	    timing->hsprepare > 85 + 6 * period)
+		return -EINVAL;
+
+	if (timing->hsprepare + timing->hszero < 145 + 10 * period)
+		return -EINVAL;
+
+	if ((timing->hssettle < 85 + 6 * period) ||
+	    (timing->hssettle > 145 + 10 * period))
+		return -EINVAL;
+
+	if (timing->hsskip < 40 || timing->hsskip > 55 + 4 * period)
+		return -EINVAL;
+
+	if (timing->hstrail < max(8 * period, 60 + 4 * period))
+		return -EINVAL;
+
+	if (timing->init < 100000)
+		return -EINVAL;
+
+	if (timing->lpx < 50)
+		return -EINVAL;
+
+	if (timing->taget != 5 * timing->lpx)
+		return -EINVAL;
+
+	if (timing->tago != 4 * timing->lpx)
+		return -EINVAL;
+
+	if (timing->tasure < timing->lpx || timing->tasure > 2 * timing->lpx)
+		return -EINVAL;
+
+	if (timing->wakeup < 1000000)
+		return -EINVAL;
+
+	return 0;
+}
+
+struct tegra_dsi {
+	struct host1x_client client;
+	struct tegra_output output;
+	struct device *dev;
+
+	void __iomem *regs;
+
+	struct clk *clk_parent;
+	struct clk *clk;
+
+	struct drm_info_list *debugfs_files;
+	struct drm_minor *minor;
+	struct dentry *debugfs;
+
+	enum dsi_format format;
+	unsigned int lanes;
+};
+
+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 *to_dsi(struct tegra_output *output)
+{
+	return container_of(output, struct tegra_dsi, output);
+}
+
+static inline unsigned long tegra_dsi_readl(struct tegra_dsi *dsi,
+					    unsigned long reg)
+{
+	return readl(dsi->regs + (reg << 2));
+}
+
+static inline void tegra_dsi_writel(struct tegra_dsi *dsi, unsigned long value,
+				    unsigned long reg)
+{
+	writel(value, dsi->regs + (reg << 2));
+}
+
+static int tegra_dsi_show_regs(struct seq_file *s, void *data)
+{
+	struct drm_info_node *node = s->private;
+	struct tegra_dsi *dsi = node->info_ent->data;
+
+#define DUMP_REG(name)						\
+	seq_printf(s, "%-32s %#05x %08lx\n", #name, name,	\
+		   tegra_dsi_readl(dsi, name))
+
+	DUMP_REG(DSI_INCR_SYNCPT);
+	DUMP_REG(DSI_INCR_SYNCPT_CONTROL);
+	DUMP_REG(DSI_INCR_SYNCPT_ERROR);
+	DUMP_REG(DSI_CTXSW);
+	DUMP_REG(DSI_RD_DATA);
+	DUMP_REG(DSI_WR_DATA);
+	DUMP_REG(DSI_POWER_CONTROL);
+	DUMP_REG(DSI_INT_ENABLE);
+	DUMP_REG(DSI_INT_STATUS);
+	DUMP_REG(DSI_INT_MASK);
+	DUMP_REG(DSI_HOST_CONTROL);
+	DUMP_REG(DSI_CONTROL);
+	DUMP_REG(DSI_SOL_DELAY);
+	DUMP_REG(DSI_MAX_THRESHOLD);
+	DUMP_REG(DSI_TRIGGER);
+	DUMP_REG(DSI_TX_CRC);
+	DUMP_REG(DSI_STATUS);
+
+	DUMP_REG(DSI_INIT_SEQ_CONTROL);
+	DUMP_REG(DSI_INIT_SEQ_DATA_0);
+	DUMP_REG(DSI_INIT_SEQ_DATA_1);
+	DUMP_REG(DSI_INIT_SEQ_DATA_2);
+	DUMP_REG(DSI_INIT_SEQ_DATA_3);
+	DUMP_REG(DSI_INIT_SEQ_DATA_4);
+	DUMP_REG(DSI_INIT_SEQ_DATA_5);
+	DUMP_REG(DSI_INIT_SEQ_DATA_6);
+	DUMP_REG(DSI_INIT_SEQ_DATA_7);
+
+	DUMP_REG(DSI_PKT_SEQ_0_LO);
+	DUMP_REG(DSI_PKT_SEQ_0_HI);
+	DUMP_REG(DSI_PKT_SEQ_1_LO);
+	DUMP_REG(DSI_PKT_SEQ_1_HI);
+	DUMP_REG(DSI_PKT_SEQ_2_LO);
+	DUMP_REG(DSI_PKT_SEQ_2_HI);
+	DUMP_REG(DSI_PKT_SEQ_3_LO);
+	DUMP_REG(DSI_PKT_SEQ_3_HI);
+	DUMP_REG(DSI_PKT_SEQ_4_LO);
+	DUMP_REG(DSI_PKT_SEQ_4_HI);
+	DUMP_REG(DSI_PKT_SEQ_5_LO);
+	DUMP_REG(DSI_PKT_SEQ_5_HI);
+
+	DUMP_REG(DSI_DCS_CMDS);
+
+	DUMP_REG(DSI_PKT_LEN_0_1);
+	DUMP_REG(DSI_PKT_LEN_2_3);
+	DUMP_REG(DSI_PKT_LEN_4_5);
+	DUMP_REG(DSI_PKT_LEN_6_7);
+
+	DUMP_REG(DSI_PHY_TIMING_0);
+	DUMP_REG(DSI_PHY_TIMING_1);
+	DUMP_REG(DSI_PHY_TIMING_2);
+	DUMP_REG(DSI_BTA_TIMING);
+
+	DUMP_REG(DSI_TIMEOUT_0);
+	DUMP_REG(DSI_TIMEOUT_1);
+	DUMP_REG(DSI_TO_TALLY);
+
+	DUMP_REG(DSI_PAD_CONTROL_0);
+	DUMP_REG(DSI_PAD_CONTROL_CD);
+	DUMP_REG(DSI_PAD_CD_STATUS);
+	DUMP_REG(DSI_VIDEO_MODE_CONTROL);
+	DUMP_REG(DSI_PAD_CONTROL_1);
+	DUMP_REG(DSI_PAD_CONTROL_2);
+	DUMP_REG(DSI_PAD_CONTROL_3);
+	DUMP_REG(DSI_PAD_CONTROL_4);
+
+	DUMP_REG(DSI_GANGED_MODE_CONTROL);
+	DUMP_REG(DSI_GANGED_MODE_START);
+	DUMP_REG(DSI_GANGED_MODE_SIZE);
+
+	DUMP_REG(DSI_RAW_DATA_BYTE_COUNT);
+	DUMP_REG(DSI_ULTRA_LOW_POWER_CONTROL);
+
+	DUMP_REG(DSI_INIT_SEQ_DATA_8);
+	DUMP_REG(DSI_INIT_SEQ_DATA_9);
+	DUMP_REG(DSI_INIT_SEQ_DATA_10);
+	DUMP_REG(DSI_INIT_SEQ_DATA_11);
+	DUMP_REG(DSI_INIT_SEQ_DATA_12);
+	DUMP_REG(DSI_INIT_SEQ_DATA_13);
+	DUMP_REG(DSI_INIT_SEQ_DATA_14);
+	DUMP_REG(DSI_INIT_SEQ_DATA_15);
+
+#undef DUMP_REG
+
+	return 0;
+}
+
+static struct drm_info_list debugfs_files[] = {
+	{ "regs", tegra_dsi_show_regs, 0, NULL },
+};
+
+static int tegra_dsi_debugfs_init(struct tegra_dsi *dsi,
+				  struct drm_minor *minor)
+{
+	const char *name = dev_name(dsi->dev);
+	unsigned int i;
+	int err;
+
+	dsi->debugfs = debugfs_create_dir(name, minor->debugfs_root);
+	if (!dsi->debugfs)
+		return -ENOMEM;
+
+	dsi->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
+				     GFP_KERNEL);
+	if (!dsi->debugfs_files) {
+		err = -ENOMEM;
+		goto remove;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
+		dsi->debugfs_files[i].data = dsi;
+
+	err = drm_debugfs_create_files(dsi->debugfs_files,
+				       ARRAY_SIZE(debugfs_files),
+				       dsi->debugfs, minor);
+	if (err < 0)
+		goto free;
+
+	dsi->minor = minor;
+
+	return 0;
+
+free:
+	kfree(dsi->debugfs_files);
+	dsi->debugfs_files = NULL;
+remove:
+	debugfs_remove(dsi->debugfs);
+	dsi->debugfs = NULL;
+
+	return err;
+}
+
+static int tegra_dsi_debugfs_exit(struct tegra_dsi *dsi)
+{
+	drm_debugfs_remove_files(dsi->debugfs_files, ARRAY_SIZE(debugfs_files),
+				 dsi->minor);
+	dsi->minor = NULL;
+
+	kfree(dsi->debugfs_files);
+	dsi->debugfs_files = NULL;
+
+	debugfs_remove(dsi->debugfs);
+	dsi->debugfs = NULL;
+
+	return 0;
+}
+
+enum {
+	CMD_VS = 0x01,
+	CMD_VE = 0x11,
+
+	CMD_HS = 0x21,
+	CMD_HE = 0x31,
+
+	CMD_EOT = 0x08,
+	CMD_NULL = 0x09,
+	CMD_SHORTW = 0x15,
+	CMD_BLNK = 0x19,
+	CMD_LONGW = 0x39,
+
+	CMD_RGB = 0x00,
+	CMD_RGB_16BPP = 0x0E,
+	CMD_RGB_18BPP = 0x1E,
+	CMD_RGB_18BPPNP = 0x2E,
+	CMD_RGB_24BPP = 0x3E,
+};
+
+#define PKT_ID0(id)	((((id) & 0x3f) << 3) | (1 << 9))
+#define PKT_LEN0(len)	(((len) & 0x7) << 0)
+#define PKT_ID1(id)	((((id) & 0x3f) << 13) | (1 << 19))
+#define PKT_LEN1(len)	(((len) & 0x7) << 10)
+#define PKT_ID2(id)	((((id) & 0x3f) << 23) | (1 << 29))
+#define PKT_LEN2(len)	(((len) & 0x7) << 20)
+#define PKT_ID3(id)	((((id) & 0x3f) << 3) | (1 << 9))
+#define PKT_LEN3(len)	(((len) & 0x7) << 0)
+#define PKT_ID4(id)	((((id) & 0x3f) << 13) | (1 << 19))
+#define PKT_LEN4(len)	(((len) & 0x7) << 10)
+#define PKT_ID5(id)	((((id) & 0x3f) << 23) | (1 << 29))
+#define PKT_LEN5(len)	(((len) & 0x7) << 20)
+#define PKT_LP		(1 << 30)
+#define NUM_PKT_SEQ	12
+
+/* non-burst mode with sync-end */
+static const u32 pkt_seq_vnb_syne[NUM_PKT_SEQ] = {
+	PKT_ID0(CMD_VS) | PKT_LEN0(0) | PKT_ID1(CMD_BLNK) | PKT_LEN1(1) |
+	PKT_ID2(CMD_HE) | PKT_LEN2(0) | PKT_LP,
+	0,
+	PKT_ID0(CMD_VE) | PKT_LEN0(0) | PKT_ID1(CMD_BLNK) | PKT_LEN1(1) |
+	PKT_ID2(CMD_HE) | PKT_LEN2(0) | PKT_LP,
+	0,
+	PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_BLNK) | PKT_LEN1(1) |
+	PKT_ID2(CMD_HE) | PKT_LEN2(0) | PKT_LP,
+	0,
+	PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_BLNK) | PKT_LEN1(1) |
+	PKT_ID2(CMD_HE) | PKT_LEN2(0),
+	PKT_ID3(CMD_BLNK) | PKT_LEN3(2) | PKT_ID4(CMD_RGB_24BPP) | PKT_LEN4(3) |
+	PKT_ID5(CMD_BLNK) | PKT_LEN5(4),
+	PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_BLNK) | PKT_LEN1(1) |
+	PKT_ID2(CMD_HE) | PKT_LEN2(0) | PKT_LP,
+	0,
+	PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_BLNK) | PKT_LEN1(1) |
+	PKT_ID2(CMD_HE) | PKT_LEN2(0),
+	PKT_ID3(CMD_BLNK) | PKT_LEN3(2) | PKT_ID4(CMD_RGB_24BPP) | PKT_LEN4(3) |
+	PKT_ID5(CMD_BLNK) | PKT_LEN5(4),
+};
+
+static int tegra_dsi_set_phy_timing(struct tegra_dsi *dsi)
+{
+	struct dsi_phy_timing timing;
+	unsigned long value, period;
+	long rate;
+	int err;
+
+	rate = clk_get_rate(dsi->clk);
+	if (rate < 0)
+		return rate;
+
+	period = DIV_ROUND_CLOSEST(1000000000UL, rate * 2);
+
+	err = dsi_phy_timing_get_default(&timing, period);
+	if (err < 0)
+		return err;
+
+	err = dsi_phy_timing_validate(&timing, period);
+	if (err < 0) {
+		dev_err(dsi->dev, "failed to validate D-PHY timing: %d\n", err);
+		return err;
+	}
+
+	/*
+	 * The D-PHY timing fields below are expressed in byte-clock cycles,
+	 * so multiply the period by 8.
+	 */
+	period *= 8;
+
+	value = DSI_TIMING_FIELD(timing.hsexit, period, 1) << 24 |
+		DSI_TIMING_FIELD(timing.hstrail, period, 0) << 16 |
+		DSI_TIMING_FIELD(timing.hszero, period, 3) << 8 |
+		DSI_TIMING_FIELD(timing.hsprepare, period, 1);
+	tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_0);
+
+	value = DSI_TIMING_FIELD(timing.clktrail, period, 1) << 24 |
+		DSI_TIMING_FIELD(timing.clkpost, period, 1) << 16 |
+		DSI_TIMING_FIELD(timing.clkzero, period, 1) << 8 |
+		DSI_TIMING_FIELD(timing.lpx, period, 1);
+	tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_1);
+
+	value = DSI_TIMING_FIELD(timing.clkprepare, period, 1) << 16 |
+		DSI_TIMING_FIELD(timing.clkpre, period, 1) << 8 |
+		DSI_TIMING_FIELD(0xff * period, period, 0) << 0;
+	tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_2);
+
+	value = DSI_TIMING_FIELD(timing.taget, period, 1) << 16 |
+		DSI_TIMING_FIELD(timing.tasure, period, 1) << 8 |
+		DSI_TIMING_FIELD(timing.tago, period, 1);
+	tegra_dsi_writel(dsi, value, DSI_BTA_TIMING);
+
+	return 0;
+}
+
+static int tegra_dsi_get_muldiv(enum dsi_format format, unsigned int *mulp,
+				unsigned int *divp)
+{
+	switch (format) {
+	case DSI_FORMAT_16P:
+		*mulp = 2;
+		*divp = 1;
+		break;
+
+	case DSI_FORMAT_18NP:
+		*mulp = 9;
+		*divp = 4;
+		break;
+
+	case DSI_FORMAT_18P:
+	case DSI_FORMAT_24P:
+		*mulp = 3;
+		*divp = 1;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int tegra_output_dsi_enable(struct tegra_output *output)
+{
+	struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
+	struct drm_display_mode *mode = &dc->base.mode;
+	unsigned int hact, hsw, hbp, hfp, i, mul, div;
+	struct tegra_dsi *dsi = to_dsi(output);
+	/* FIXME: don't hardcode this */
+	const u32 *pkt_seq = pkt_seq_vnb_syne;
+	unsigned long value;
+	int err;
+
+	err = tegra_dsi_get_muldiv(dsi->format, &mul, &div);
+	if (err < 0)
+		return err;
+
+	err = clk_enable(dsi->clk);
+	if (err < 0)
+		return err;
+
+	tegra_periph_reset_deassert(dsi->clk);
+
+	value = DSI_CONTROL_CHANNEL(0) | DSI_CONTROL_FORMAT(dsi->format) |
+		DSI_CONTROL_LANES(dsi->lanes - 1) | DSI_CONTROL_SOURCE(0);
+	tegra_dsi_writel(dsi, value, DSI_CONTROL);
+
+	tegra_dc_writel(dc, DSI_ENABLE, DC_DISP_DISP_WIN_OPTIONS);
+
+	value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
+		PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
+	tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
+
+	tegra_dc_writel(dc, DISP_CTRL_MODE_C_DISPLAY, DC_CMD_DISPLAY_COMMAND);
+	tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
+	tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
+
+	tegra_dsi_writel(dsi, 0x000001e0, DSI_MAX_THRESHOLD);
+
+	value = DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_CS |
+		DSI_HOST_CONTROL_ECC;
+	tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
+
+	value = tegra_dsi_readl(dsi, DSI_CONTROL);
+	value |= DSI_CONTROL_HS_CLK_CTRL;
+	value &= ~DSI_CONTROL_TX_TRIG(3);
+	value &= ~DSI_CONTROL_DCS_ENABLE;
+	value |= DSI_CONTROL_VIDEO_ENABLE;
+	value &= ~DSI_CONTROL_HOST_ENABLE;
+	tegra_dsi_writel(dsi, value, DSI_CONTROL);
+
+	err = tegra_dsi_set_phy_timing(dsi);
+	if (err < 0)
+		return err;
+
+	for (i = 0; i < NUM_PKT_SEQ; i++)
+		tegra_dsi_writel(dsi, pkt_seq[i], DSI_PKT_SEQ_0_LO + i);
+
+	/* horizontal active pixels */
+	hact = mode->hdisplay * mul / div;
+
+	/* horizontal sync width */
+	hsw = (mode->hsync_end - mode->hsync_start) * mul / div;
+	hsw -= 10;
+
+	/* horizontal back porch */
+	hbp = (mode->htotal - mode->hsync_end) * mul / div;
+	hbp -= 14;
+
+	/* horizontal front porch */
+	hfp = (mode->hsync_start  - mode->hdisplay) * mul / div;
+	hfp -= 8;
+
+	tegra_dsi_writel(dsi, hsw << 16 | 0, DSI_PKT_LEN_0_1);
+	tegra_dsi_writel(dsi, hact << 16 | hbp, DSI_PKT_LEN_2_3);
+	tegra_dsi_writel(dsi, hfp, DSI_PKT_LEN_4_5);
+	tegra_dsi_writel(dsi, 0x0f0f << 16, DSI_PKT_LEN_6_7);
+
+	/* set SOL delay */
+	tegra_dsi_writel(dsi, 8 * mul / div, DSI_SOL_DELAY);
+
+	return 0;
+}
+
+static int tegra_output_dsi_disable(struct tegra_output *output)
+{
+	struct tegra_dsi *dsi = to_dsi(output);
+
+	clk_disable(dsi->clk);
+
+	return 0;
+}
+
+static int tegra_output_dsi_setup_clock(struct tegra_output *output,
+					struct clk *clk, unsigned long pclk)
+{
+	struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
+	struct drm_display_mode *mode = &dc->base.mode;
+	struct tegra_dsi *dsi = to_dsi(output);
+	unsigned long bclk, plld, value;
+	unsigned int timeout, mul, div;
+	struct clk *base;
+	int err;
+
+	err = tegra_dsi_get_muldiv(dsi->format, &mul, &div);
+	if (err < 0)
+		return err;
+
+	pclk = mode->htotal * mode->vtotal * mode->vrefresh;
+	bclk = (pclk * mul) / (div * dsi->lanes);
+	plld = DIV_ROUND_UP(bclk * 8, 1000000);
+	pclk = (plld * 1000000) / 2;
+
+	err = clk_set_parent(clk, dsi->clk_parent);
+	if (err < 0) {
+		dev_err(dsi->dev, "failed to set parent clock: %d\n", err);
+		return err;
+	}
+
+	base = clk_get_parent(dsi->clk_parent);
+
+	/*
+	 * This assumes that the parent clock is pll_d_out0 or pll_d2_out
+	 * respectively, each of which divides the base pll_d by 2.
+	 */
+	err = clk_set_rate(base, pclk * 2);
+	if (err < 0) {
+		dev_err(dsi->dev, "failed to set base clock rate to %lu Hz\n",
+			pclk * 2);
+		return err;
+	}
+
+	/* one frame high-speed transmission timeout */
+	timeout = (bclk / mode->vrefresh) / 512;
+	value = DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(timeout);
+	tegra_dsi_writel(dsi, value, DSI_TIMEOUT_0);
+
+	/* 2 ms peripheral timeout for panel */
+	timeout = 2 * bclk / 512 * 1000;
+	value = DSI_TIMEOUT_PR(timeout) | DSI_TIMEOUT_TA(0x2000);
+	tegra_dsi_writel(dsi, value, DSI_TIMEOUT_1);
+
+	value = DSI_TALLY_TA(0) | DSI_TALLY_LRX(0) | DSI_TALLY_HTX(0);
+	tegra_dsi_writel(dsi, value, DSI_TO_TALLY);
+
+	return 0;
+}
+
+static int tegra_output_dsi_check_mode(struct tegra_output *output,
+				       struct drm_display_mode *mode,
+				       enum drm_mode_status *status)
+{
+	/*
+	 * FIXME: For now, always assume that the mode is okay.
+	 */
+
+	*status = MODE_OK;
+
+	return 0;
+}
+
+static const struct tegra_output_ops dsi_ops = {
+	.enable = tegra_output_dsi_enable,
+	.disable = tegra_output_dsi_disable,
+	.setup_clock = tegra_output_dsi_setup_clock,
+	.check_mode = tegra_output_dsi_check_mode,
+};
+
+static int tegra_dsi_pad_enable(struct tegra_dsi *dsi)
+{
+	unsigned long value;
+
+	value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0);
+	tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0);
+
+	return 0;
+}
+
+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);
+	unsigned long value, i;
+	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);
+	}
+
+	/*
+	 * enable high-speed mode, checksum generation, ECC generation and
+	 * disable raw mode
+	 */
+	value = tegra_dsi_readl(dsi, DSI_HOST_CONTROL);
+	value |= DSI_HOST_CONTROL_ECC | DSI_HOST_CONTROL_CS |
+		 DSI_HOST_CONTROL_HS;
+	value &= ~DSI_HOST_CONTROL_RAW;
+	tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
+
+	tegra_dsi_writel(dsi, 0, DSI_SOL_DELAY);
+	tegra_dsi_writel(dsi, 0, DSI_MAX_THRESHOLD);
+
+	tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_CONTROL);
+
+	for (i = 0; i < 8; i++) {
+		tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_0 + i);
+		tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_8 + i);
+	}
+
+	for (i = 0; i < 12; i++)
+		tegra_dsi_writel(dsi, 0, DSI_PKT_SEQ_0_LO + i);
+
+	tegra_dsi_writel(dsi, 0, DSI_DCS_CMDS);
+
+	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0);
+	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1);
+	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2);
+	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3);
+	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4);
+
+	/* start calibration */
+	tegra_dsi_pad_enable(dsi);
+
+	value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) |
+		DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) |
+		DSI_PAD_OUT_CLK(0x0);
+	tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2);
+
+	err = tegra_mipi_calibrate(dsi->dev);
+	if (err < 0) {
+		dev_err(dsi->dev, "MIPI calibration failed: %d\n", err);
+		return err;
+	}
+
+	tegra_dsi_writel(dsi, DSI_POWER_CONTROL_ENABLE, DSI_POWER_CONTROL);
+	usleep_range(300, 1000);
+
+	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;
+	int err;
+
+	parent = clk_get_parent(dsi->clk);
+	if (!parent)
+		return -EINVAL;
+
+	err = clk_set_parent(parent, dsi->clk_parent);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int tegra_dsi_probe(struct platform_device *pdev)
+{
+	struct host1x *host1x = dev_get_drvdata(pdev->dev.parent);
+	struct tegra_dsi *dsi;
+	struct resource *regs;
+	int err;
+
+	if (!host1x)
+		return -EPROBE_DEFER;
+
+	dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);
+	if (!dsi)
+		return -ENOMEM;
+
+	dsi->output.dev = dsi->dev = &pdev->dev;
+
+	err = tegra_output_parse_dt(&dsi->output);
+	if (err < 0)
+		return err;
+
+	/*
+	 * FIXME: Don't hardcode these. Perhaps they should be queried from
+	 *        the panel or from the DSI interface's DT node.
+	 */
+	dsi->format = DSI_FORMAT_24P;
+	dsi->lanes = 4;
+
+	dsi->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dsi->clk))
+		return PTR_ERR(dsi->clk);;
+
+	err = clk_prepare_enable(dsi->clk);
+	if (err < 0)
+		return err;
+
+	dsi->clk_parent = devm_clk_get(&pdev->dev, "parent");
+	if (IS_ERR(dsi->clk_parent))
+		return PTR_ERR(dsi->clk_parent);
+
+	err = clk_prepare_enable(dsi->clk_parent);
+	if (err < 0)
+		return err;
+
+	err = tegra_dsi_setup_clocks(dsi);
+	if (err < 0)
+		return err;
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	dsi->regs = devm_ioremap_resource(&pdev->dev, regs);
+	if (!dsi->regs)
+		return -EADDRNOTAVAIL;
+
+	INIT_LIST_HEAD(&dsi->client.list);
+	dsi->client.ops = &dsi_client_ops;
+	dsi->client.dev = &pdev->dev;
+
+	err = host1x_register_client(host1x, &dsi->client);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
+			err);
+		return err;
+	}
+
+	platform_set_drvdata(pdev, dsi);
+
+	return 0;
+}
+
+static int tegra_dsi_remove(struct platform_device *pdev)
+{
+	struct host1x *host1x = dev_get_drvdata(pdev->dev.parent);
+	struct tegra_dsi *dsi = platform_get_drvdata(pdev);
+	int err;
+
+	err = host1x_unregister_client(host1x, &dsi->client);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
+			err);
+		return err;
+	}
+
+	clk_disable_unprepare(dsi->clk_parent);
+	clk_disable_unprepare(dsi->clk);
+
+	return 0;
+}
+
+static const struct of_device_id tegra_dsi_of_match[] = {
+	{ .compatible = "nvidia,tegra114-dsi", },
+	{ },
+};
+
+struct platform_driver tegra_dsi_driver = {
+	.driver = {
+		.name = "tegra-dsi",
+		.of_match_table = tegra_dsi_of_match,
+	},
+	.probe = tegra_dsi_probe,
+	.remove = tegra_dsi_remove,
+};
diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c
index d911fe8..b885a8c 100644
--- a/drivers/gpu/drm/tegra/output.c
+++ b/drivers/gpu/drm/tegra/output.c
@@ -255,6 +255,11 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
 		encoder = DRM_MODE_ENCODER_TMDS;
 		break;
 
+	case TEGRA_OUTPUT_DSI:
+		connector = DRM_MODE_CONNECTOR_DSI;
+		encoder = DRM_MODE_ENCODER_DSI;
+		break;
+
 	default:
 		connector = DRM_MODE_CONNECTOR_Unknown;
 		encoder = DRM_MODE_ENCODER_NONE;
-- 
1.8.4

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

* [PATCH v2 27/27] drm/tegra: Add Tegra114 gr2d support
       [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
                     ` (25 preceding siblings ...)
  2013-10-07  8:34   ` [PATCH v2 26/27] drm/tegra: Add DSI support Thierry Reding
@ 2013-10-07  8:34   ` Thierry Reding
       [not found]     ` <1381134884-5816-28-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  26 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-07  8:34 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

The gr2d hardware in Tegra114 is compatible with that of Tegra20 and
Tegra30. No functionaly changes are required.

Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/gpu/drm/tegra/drm.c  | 1 +
 drivers/gpu/drm/tegra/gr2d.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index d95be81..b9e0977 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -492,6 +492,7 @@ static const struct of_device_id host1x_drm_subdevs[] = {
 	{ .compatible = "nvidia,tegra114-dc", },
 	{ .compatible = "nvidia,tegra114-dsi", },
 	{ .compatible = "nvidia,tegra114-hdmi", },
+	{ .compatible = "nvidia,tegra114-gr2d", },
 	{ /* sentinel */ }
 };
 
diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
index 9588072..f4e478b 100644
--- a/drivers/gpu/drm/tegra/gr2d.c
+++ b/drivers/gpu/drm/tegra/gr2d.c
@@ -232,6 +232,7 @@ static const struct tegra_drm_client_ops gr2d_ops = {
 };
 
 static const struct of_device_id gr2d_match[] = {
+	{ .compatible = "nvidia,tegra114-gr2d" },
 	{ .compatible = "nvidia,tegra30-gr2d" },
 	{ .compatible = "nvidia,tegra20-gr2d" },
 	{ },
-- 
1.8.4

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

* Re: [PATCH v2 08/27] drm/tegra: gr2d: Miscellaneous cleanups
       [not found]     ` <1381134884-5816-9-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-10-07 11:34       ` Erik Faye-Lund
       [not found]         ` <CABPQNSbkS40_jyGz14s08+x3e+-pxnfy90V7pzAOfiqUF2ma2g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Erik Faye-Lund @ 2013-10-07 11:34 UTC (permalink / raw)
  To: Thierry Reding
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On Mon, Oct 7, 2013 at 10:34 AM, Thierry Reding
<thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> Rework the address table code for the host1x firewall. The previous
> implementation allocated a bitfield but didn't check for a valid pointer
> so it could potentially crash.

I don't think it could crash. The bitmaps was allocated as a 256-bit
field, and the register offset gets AND'ed with 0xFF before being
looked up. What am I missing?

> Furthermore setting up a bitfield makes
> the code more complex than it needs to be.

Doesn't this perform worse than the current implementation? Going from
1 to 13 checks per write sounds less than ideal to me...

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

* Re: [PATCH v2 08/27] drm/tegra: gr2d: Miscellaneous cleanups
       [not found]         ` <CABPQNSbkS40_jyGz14s08+x3e+-pxnfy90V7pzAOfiqUF2ma2g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2013-10-07 12:14           ` Thierry Reding
       [not found]             ` <20131007121452.GA8324-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-07 12:14 UTC (permalink / raw)
  To: Erik Faye-Lund
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

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

On Mon, Oct 07, 2013 at 01:34:44PM +0200, Erik Faye-Lund wrote:
> On Mon, Oct 7, 2013 at 10:34 AM, Thierry Reding
> <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> > Rework the address table code for the host1x firewall. The previous
> > implementation allocated a bitfield but didn't check for a valid pointer
> > so it could potentially crash.
> 
> I don't think it could crash. The bitmaps was allocated as a 256-bit
> field, and the register offset gets AND'ed with 0xFF before being
> looked up. What am I missing?

The pointer returned from the allocation is never checked, so it could
theoretically be NULL and be used regardless.

Also I'm not sure that AND'ing with 0xff is the right thing to do here.

> > Furthermore setting up a bitfield makes
> > the code more complex than it needs to be.
> 
> Doesn't this perform worse than the current implementation? Going from
> 1 to 13 checks per write sounds less than ideal to me...

I'm not so sure. Caching should alleviate the issue with the increased
amount of data. Then there's the fact that previously we needed to
divide and compute the remainder of the division for the BIT_MASK and
BIT_WORD operations.

One other added benefit of this approach is that the address registers
are stored in a const array and therefore could reside in a read-only
memory region. With the previous approach, once somebody had access to
the bitmap, it could easily be overwritten with zeros and effectively
make the firewall useless. I'm not sure how likely that would be, but it
could be done.

I guess one could actually go and run a benchmark against both versions
and balance the performance impact against the possible security
implications. But given that we don't really have any benchmarks that's
pretty hard to do.

Thierry

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

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

* Re: [PATCH v2 08/27] drm/tegra: gr2d: Miscellaneous cleanups
       [not found]             ` <20131007121452.GA8324-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
@ 2013-10-07 12:52               ` Terje Bergström
       [not found]                 ` <5252AE8C.9090609-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2013-10-07 12:53               ` Erik Faye-Lund
  1 sibling, 1 reply; 87+ messages in thread
From: Terje Bergström @ 2013-10-07 12:52 UTC (permalink / raw)
  To: Thierry Reding, Erik Faye-Lund
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On 07.10.2013 15:14, Thierry Reding wrote:
> * PGP Signed by an unknown key
> 
> On Mon, Oct 07, 2013 at 01:34:44PM +0200, Erik Faye-Lund wrote:
>> On Mon, Oct 7, 2013 at 10:34 AM, Thierry Reding
>> <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>>> Rework the address table code for the host1x firewall. The previous
>>> implementation allocated a bitfield but didn't check for a valid pointer
>>> so it could potentially crash.
>>
>> I don't think it could crash. The bitmaps was allocated as a 256-bit
>> field, and the register offset gets AND'ed with 0xFF before being
>> looked up. What am I missing?
> 
> The pointer returned from the allocation is never checked, so it could
> theoretically be NULL and be used regardless.
> 
> Also I'm not sure that AND'ing with 0xff is the right thing to do here.

Oops, there's a check for NULL missing. If that allocation fails, probe
should fail, so we just need to propagate the error condition. Otherwise
we might just leave the firewall off, and let everything go in unchecked.

AND 0xff is necessary, because the same registers are mirrored in
multiple contexts. AND removes the offset coming from context, and
leaves just the plain register offset.

> I'm not so sure. Caching should alleviate the issue with the increased
> amount of data. Then there's the fact that previously we needed to
> divide and compute the remainder of the division for the BIT_MASK and
> BIT_WORD operations.

Don't these get compiled into shifts and bitwise ands?

> One other added benefit of this approach is that the address registers
> are stored in a const array and therefore could reside in a read-only
> memory region. With the previous approach, once somebody had access to
> the bitmap, it could easily be overwritten with zeros and effectively
> make the firewall useless. I'm not sure how likely that would be, but it
> could be done.

If somebody gets access to the bitmap, he has access to kernel data
structures. GR2D firewall is the least of our worries in this case.

Terje

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

* Re: [PATCH v2 08/27] drm/tegra: gr2d: Miscellaneous cleanups
       [not found]             ` <20131007121452.GA8324-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
  2013-10-07 12:52               ` Terje Bergström
@ 2013-10-07 12:53               ` Erik Faye-Lund
       [not found]                 ` <CABPQNSb52HmS-2T=MUXteMFc1tndHdvtUnZqsVsPKjP1Dy6Esw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  1 sibling, 1 reply; 87+ messages in thread
From: Erik Faye-Lund @ 2013-10-07 12:53 UTC (permalink / raw)
  To: Thierry Reding
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On Mon, Oct 7, 2013 at 2:14 PM, Thierry Reding <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> On Mon, Oct 07, 2013 at 01:34:44PM +0200, Erik Faye-Lund wrote:
>> On Mon, Oct 7, 2013 at 10:34 AM, Thierry Reding
>> <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> > Rework the address table code for the host1x firewall. The previous
>> > implementation allocated a bitfield but didn't check for a valid pointer
>> > so it could potentially crash.
>>
>> I don't think it could crash. The bitmaps was allocated as a 256-bit
>> field, and the register offset gets AND'ed with 0xFF before being
>> looked up. What am I missing?
>
> The pointer returned from the allocation is never checked, so it could
> theoretically be NULL and be used regardless.
>

Right. Thanks for clarifying.

> Also I'm not sure that AND'ing with 0xff is the right thing to do here.

Well, maybe not. I'm not entirely convinced it's *not*, though.

>> > Furthermore setting up a bitfield makes
>> > the code more complex than it needs to be.
>>
>> Doesn't this perform worse than the current implementation? Going from
>> 1 to 13 checks per write sounds less than ideal to me...
>
> I'm not so sure. Caching should alleviate the issue with the increased
> amount of data. Then there's the fact that previously we needed to
> divide and compute the remainder of the division for the BIT_MASK and
> BIT_WORD operations.

That's an AND and a shift, not division and modulo, both single-cycle
instructions on ARM. I'm pretty sure that'd be a win.

> One other added benefit of this approach is that the address registers
> are stored in a const array and therefore could reside in a read-only
> memory region. With the previous approach, once somebody had access to
> the bitmap, it could easily be overwritten with zeros and effectively
> make the firewall useless. I'm not sure how likely that would be, but it
> could be done.

Perhaps the bitmap could be generated compile-time and stuck in
read-only memory?

> I guess one could actually go and run a benchmark against both versions
> and balance the performance impact against the possible security
> implications. But given that we don't really have any benchmarks that's
> pretty hard to do.

Well, perhaps we could have both? :)

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

* Re: [PATCH v2 08/27] drm/tegra: gr2d: Miscellaneous cleanups
       [not found]                 ` <CABPQNSb52HmS-2T=MUXteMFc1tndHdvtUnZqsVsPKjP1Dy6Esw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2013-10-07 13:02                   ` Erik Faye-Lund
       [not found]                     ` <CABPQNSZGyuS3wAvJ8fFj=LMXxFJz9x_sKqEWW7QbiqC1gneLKw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Erik Faye-Lund @ 2013-10-07 13:02 UTC (permalink / raw)
  To: Thierry Reding
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On Mon, Oct 7, 2013 at 2:53 PM, Erik Faye-Lund <kusmabite-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> On Mon, Oct 7, 2013 at 2:14 PM, Thierry Reding <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> On Mon, Oct 07, 2013 at 01:34:44PM +0200, Erik Faye-Lund wrote:
>>> On Mon, Oct 7, 2013 at 10:34 AM, Thierry Reding
>>> <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>>> > Rework the address table code for the host1x firewall. The previous
>>> > implementation allocated a bitfield but didn't check for a valid pointer
>>> > so it could potentially crash.
>>>
>>> I don't think it could crash. The bitmaps was allocated as a 256-bit
>>> field, and the register offset gets AND'ed with 0xFF before being
>>> looked up. What am I missing?
>>
>> The pointer returned from the allocation is never checked, so it could
>> theoretically be NULL and be used regardless.
>>
>> Also I'm not sure that AND'ing with 0xff is the right thing to do here.
>
> Well, maybe not. I'm not entirely convinced it's *not*, though.
>

I'm sorry, I intended to fill out a bit more here before I hit send,
and totally forgot.

Point is, it seems only 0x00..0x4c is used (and then repeated at
multiples of 0x4000 for each context, but the offsets don't have
enough bits to reach that far), from looking at the TRM.

So the question is really how the hardware treats writes to
non-existent registers. My guess would be that they are simply not
recorded, and if that's the case it doesn't matter what we do. And
doing an unconditional AND is faster than doing a bit-test followed by
a conditional branch.

Of course, if the hardware does *not* ignore writes to non-existent
register, then we might be in trouble. But for that, we'd probably
want a full map of valid registers, not just saying that they aren't
pointers, no?

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

* Re: [PATCH v2 08/27] drm/tegra: gr2d: Miscellaneous cleanups
       [not found]                 ` <5252AE8C.9090609-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-10-07 13:05                   ` Erik Faye-Lund
       [not found]                     ` <CABPQNSa59hBU__yjQMZsdEghpSwH1ayJYiD6HrBrhABicgzxuA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2013-10-07 13:13                   ` Thierry Reding
  1 sibling, 1 reply; 87+ messages in thread
From: Erik Faye-Lund @ 2013-10-07 13:05 UTC (permalink / raw)
  To: Terje Bergström
  Cc: Thierry Reding, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On Mon, Oct 7, 2013 at 2:52 PM, Terje Bergström <tbergstrom-DDmLM1+adcphl2p70BpVqQ@public.gmane.orgm> wrote:
> On 07.10.2013 15:14, Thierry Reding wrote:
>> * PGP Signed by an unknown key
>>
>> On Mon, Oct 07, 2013 at 01:34:44PM +0200, Erik Faye-Lund wrote:
>>> On Mon, Oct 7, 2013 at 10:34 AM, Thierry Reding
>>> <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>>>> Rework the address table code for the host1x firewall. The previous
>>>> implementation allocated a bitfield but didn't check for a valid pointer
>>>> so it could potentially crash.
>>>
>>> I don't think it could crash. The bitmaps was allocated as a 256-bit
>>> field, and the register offset gets AND'ed with 0xFF before being
>>> looked up. What am I missing?
>>
>> The pointer returned from the allocation is never checked, so it could
>> theoretically be NULL and be used regardless.
>>
>> Also I'm not sure that AND'ing with 0xff is the right thing to do here.
>
> Oops, there's a check for NULL missing. If that allocation fails, probe
> should fail, so we just need to propagate the error condition. Otherwise
> we might just leave the firewall off, and let everything go in unchecked.
>
> AND 0xff is necessary, because the same registers are mirrored in
> multiple contexts. AND removes the offset coming from context, and
> leaves just the plain register offset.
>

The offsets in the commands don't have enough bits to reach over to
the next context. The contexts are repeated at multiples of 0x4000,
and 0xFFF is the largest encodable offset. So I don't really thing the
AND is needed for *that* purpose.

> If somebody gets access to the bitmap, he has access to kernel data
> structures. GR2D firewall is the least of our worries in this case.

Indeed, that's only a problem if someone is already on the other side
of the air-tight hatch.

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

* Re: [PATCH v2 08/27] drm/tegra: gr2d: Miscellaneous cleanups
       [not found]                 ` <5252AE8C.9090609-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2013-10-07 13:05                   ` Erik Faye-Lund
@ 2013-10-07 13:13                   ` Thierry Reding
  1 sibling, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-07 13:13 UTC (permalink / raw)
  To: Terje Bergström
  Cc: Erik Faye-Lund, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

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

On Mon, Oct 07, 2013 at 03:52:28PM +0300, Terje Bergström wrote:
> On 07.10.2013 15:14, Thierry Reding wrote:
> > * PGP Signed by an unknown key
> > 
> > On Mon, Oct 07, 2013 at 01:34:44PM +0200, Erik Faye-Lund wrote:
> >> On Mon, Oct 7, 2013 at 10:34 AM, Thierry Reding
> >> <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> >>> Rework the address table code for the host1x firewall. The previous
> >>> implementation allocated a bitfield but didn't check for a valid pointer
> >>> so it could potentially crash.
> >>
> >> I don't think it could crash. The bitmaps was allocated as a 256-bit
> >> field, and the register offset gets AND'ed with 0xFF before being
> >> looked up. What am I missing?
> > 
> > The pointer returned from the allocation is never checked, so it could
> > theoretically be NULL and be used regardless.
> > 
> > Also I'm not sure that AND'ing with 0xff is the right thing to do here.
> 
> Oops, there's a check for NULL missing. If that allocation fails, probe
> should fail, so we just need to propagate the error condition. Otherwise
> we might just leave the firewall off, and let everything go in unchecked.

Yes, definitely.

> AND 0xff is necessary, because the same registers are mirrored in
> multiple contexts. AND removes the offset coming from context, and
> leaves just the plain register offset.

That looks like something which should go into a comment.

> > I'm not so sure. Caching should alleviate the issue with the increased
> > amount of data. Then there's the fact that previously we needed to
> > divide and compute the remainder of the division for the BIT_MASK and
> > BIT_WORD operations.
> 
> Don't these get compiled into shifts and bitwise ands?

Yes, they are.

> > One other added benefit of this approach is that the address registers
> > are stored in a const array and therefore could reside in a read-only
> > memory region. With the previous approach, once somebody had access to
> > the bitmap, it could easily be overwritten with zeros and effectively
> > make the firewall useless. I'm not sure how likely that would be, but it
> > could be done.
> 
> If somebody gets access to the bitmap, he has access to kernel data
> structures. GR2D firewall is the least of our worries in this case.

I see the point. Oh well, all my arguments are torn down. I'll drop this
patch. Or at least the part that rewrites the gr2d_is_addr() and make it
check for failed allocations properly.

For what it's worth, I still think the plain table lookup is much easier
to understand.

Thierry

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

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

* Re: [PATCH v2 08/27] drm/tegra: gr2d: Miscellaneous cleanups
       [not found]                     ` <CABPQNSa59hBU__yjQMZsdEghpSwH1ayJYiD6HrBrhABicgzxuA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2013-10-08  5:36                       ` Terje Bergström
  0 siblings, 0 replies; 87+ messages in thread
From: Terje Bergström @ 2013-10-08  5:36 UTC (permalink / raw)
  To: kusmabite-Re5JQEeQqe8AvxtiuMwx3w
  Cc: Thierry Reding, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On 07.10.2013 16:05, Erik Faye-Lund wrote:
> On Mon, Oct 7, 2013 at 2:52 PM, Terje Bergström <tbergstrom@nvidia.com> wrote:
>> AND 0xff is necessary, because the same registers are mirrored in
>> multiple contexts. AND removes the offset coming from context, and
>> leaves just the plain register offset.
> The offsets in the commands don't have enough bits to reach over to
> the next context. The contexts are repeated at multiples of 0x4000,
> and 0xFFF is the largest encodable offset. So I don't really thing the
> AND is needed for *that* purpose.

Well, that was embarrassing. Of course that is true. You can access all
registers via MMIO or with SETCLASS to correct context. But that was
still the reason I used when I wrote that 0xff, so it's bogus.

Real fix is to do what Thierry already did: limit the bitmap to max
register number we're interested in, and have a if() to fail fast if
register number falls outside that range.

Even better, get IOMMU up and running.

Terje

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

* Re: [PATCH v2 08/27] drm/tegra: gr2d: Miscellaneous cleanups
       [not found]                     ` <CABPQNSZGyuS3wAvJ8fFj=LMXxFJz9x_sKqEWW7QbiqC1gneLKw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2013-10-08  5:48                       ` Terje Bergström
       [not found]                         ` <52539CC0.3020901-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Terje Bergström @ 2013-10-08  5:48 UTC (permalink / raw)
  To: kusmabite-Re5JQEeQqe8AvxtiuMwx3w, Thierry Reding
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On 07.10.2013 16:02, Erik Faye-Lund wrote:
> So the question is really how the hardware treats writes to
> non-existent registers. My guess would be that they are simply not
> recorded, and if that's the case it doesn't matter what we do. And
> doing an unconditional AND is faster than doing a bit-test followed by
> a conditional branch.

Hardware ignores writes to non-existent registers. Sometimes
non-existent registers are taken into use in future versions, though.

Terje

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

* Re: [PATCH v2 06/27] gpu: host1x: Cleanup includes
       [not found]     ` <1381134884-5816-7-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-10-08  5:59       ` Terje Bergström
       [not found]         ` <52539F5E.1060005-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Terje Bergström @ 2013-10-08  5:59 UTC (permalink / raw)
  To: Thierry Reding, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

On 07.10.2013 11:34, Thierry Reding wrote:
> Most of the included files are either not required or already included
> by some other header file.

What's the general policy? I personally feel that each source file
should #include all the header files it needs, and should not rely on
header files #including other header files.

This way if header file A stops needing header file B, we don't need to
go and fix all users of header file A that assume B is included.

I've been hit by this multiple times in Linux kernel - sometimes some
header files just assume another header file is #included and refuses to
compile it it isn't.

Terje

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

* Re: [PATCH v2 13/27] drm/tegra: Move subdevice infrastructure to host1x
       [not found]     ` <1381134884-5816-14-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-10-08  6:25       ` Terje Bergström
       [not found]         ` <5253A563.1060409-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2013-11-04 10:20       ` Daniel Vetter
  1 sibling, 1 reply; 87+ messages in thread
From: Terje Bergström @ 2013-10-08  6:25 UTC (permalink / raw)
  To: Thierry Reding, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

On 07.10.2013 11:34, Thierry Reding wrote:
> The Tegra DRM driver currently uses some infrastructure to defer the DRM
> core initialization until all required devices have registered. The same
> infrastructure can potentially be used by any other driver that requires
> more than a single sub-device of the host1x module.
> 
> Make the infrastructure more generic and keep only the DRM specific code
> in the DRM part of the driver. Eventually this will make it easy to move
> the DRM driver part back to the DRM subsystem.

Do we need the host1x_client/tegra_drm_client concept outside DRM? You
separated the two in an earlier patch, but the whole structure is there
because of limitation in DRM. Shouldn't we keep management of drm
clients entirely inside drm?

Second, do we need an own drm_bus for host1x clients? Does it bring
something drm_platform doesn't? I couldn't see any immediate difference
between the two.

Terje

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

* Re: [PATCH v2 06/27] gpu: host1x: Cleanup includes
       [not found]         ` <52539F5E.1060005-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-10-08  9:45           ` Thierry Reding
  0 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-08  9:45 UTC (permalink / raw)
  To: Terje Bergström
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

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

On Tue, Oct 08, 2013 at 08:59:58AM +0300, Terje Bergström wrote:
> On 07.10.2013 11:34, Thierry Reding wrote:
> > Most of the included files are either not required or already included
> > by some other header file.
> 
> What's the general policy? I personally feel that each source file
> should #include all the header files it needs, and should not rely on
> header files #including other header files.
> 
> This way if header file A stops needing header file B, we don't need to
> go and fix all users of header file A that assume B is included.
> 
> I've been hit by this multiple times in Linux kernel - sometimes some
> header files just assume another header file is #included and refuses to
> compile it it isn't.

Explicit includes are probably the safest route when dealing with
headers from include/linux, which can be volatile. However, in this case
any of the general header files are already included by driver private
header files, which are not subject to the same volatility. Or when they
change we'll see breakage immediately because pretty much everything
about the driver will be rebuilt.

It even has the advantage that if a file in include/linux or include/drm
changes in a way that breaks compilation, we only have to change one of
the driver private headers instead of all source files.

Thierry

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

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

* Re: [PATCH v2 13/27] drm/tegra: Move subdevice infrastructure to host1x
       [not found]         ` <5253A563.1060409-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-10-08  9:52           ` Thierry Reding
  0 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-08  9:52 UTC (permalink / raw)
  To: Terje Bergström
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

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

On Tue, Oct 08, 2013 at 09:25:39AM +0300, Terje Bergström wrote:
> On 07.10.2013 11:34, Thierry Reding wrote:
> > The Tegra DRM driver currently uses some infrastructure to defer the DRM
> > core initialization until all required devices have registered. The same
> > infrastructure can potentially be used by any other driver that requires
> > more than a single sub-device of the host1x module.
> > 
> > Make the infrastructure more generic and keep only the DRM specific code
> > in the DRM part of the driver. Eventually this will make it easy to move
> > the DRM driver part back to the DRM subsystem.
> 
> Do we need the host1x_client/tegra_drm_client concept outside DRM? You
> separated the two in an earlier patch, but the whole structure is there
> because of limitation in DRM. Shouldn't we keep management of drm
> clients entirely inside drm?

The DRM specific parts are still all managed within the DRM driver.
However the host1x_client API, and specifically the method in which
sub-devices can be registered (host1x_client to host1x_device) is
completely subsystem agnostic.

That part can be used subsequently by things such as a V4L2 driver
to achieve the same thing we've done with Tegra DRM, namely to use
several sub-devices collectively to provide the functionality of a
"composite" device (VI/CSI).

> Second, do we need an own drm_bus for host1x clients? Does it bring
> something drm_platform doesn't? I couldn't see any immediate difference
> between the two.

The difference is in that we pass in a host1x_device, which is not a
platform device, but really just a wrapped struct device. That in turn
provides the whole composite device infrastructure. So, no, it can't be
done with drm_platform.

Thierry

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

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

* Re: [PATCH v2 08/27] drm/tegra: gr2d: Miscellaneous cleanups
       [not found]                         ` <52539CC0.3020901-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-10-08 11:11                           ` Erik Faye-Lund
  0 siblings, 0 replies; 87+ messages in thread
From: Erik Faye-Lund @ 2013-10-08 11:11 UTC (permalink / raw)
  To: Terje Bergström
  Cc: Thierry Reding, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On Tue, Oct 8, 2013 at 7:48 AM, Terje Bergström <tbergstrom-DDmLM1+adcphl2p70BpVqQ@public.gmane.orgm> wrote:
> On 07.10.2013 16:02, Erik Faye-Lund wrote:
>> So the question is really how the hardware treats writes to
>> non-existent registers. My guess would be that they are simply not
>> recorded, and if that's the case it doesn't matter what we do. And
>> doing an unconditional AND is faster than doing a bit-test followed by
>> a conditional branch.
>
> Hardware ignores writes to non-existent registers. Sometimes
> non-existent registers are taken into use in future versions, though.

Right. That might be a motivation to treat non-existent registers as
errors. But then I start to wonder about "holes" in the pointer
address space should be treated differently. For instance, from the
TRM it looks like registers 0x3 - 0x8, 0xe, 0x15 and 0x42 are
undefined for T20. If writes to registers beyond 0x4c fails, shouldn't
these also fail? Or are somehow guaranteed that these holes will never
be plugged? Are they simply missing from the TRM?

I dunno...

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

* Re: [PATCH v2 14/27] drm/tegra: Move driver to DRM tree
       [not found]     ` <1381134884-5816-15-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-10-11 22:11       ` Stephen Warren
       [not found]         ` <52587797.7000402-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Stephen Warren @ 2013-10-11 22:11 UTC (permalink / raw)
  To: Thierry Reding, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

On 10/07/2013 02:34 AM, Thierry Reding wrote:
> In order to subsystem-wide changes easier, move the Tegra DRM driver
             ^^ make ?

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

* Re: [PATCH v2 15/27] gpu: host1x: Add support for Tegra114
       [not found]     ` <1381134884-5816-16-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-10-11 22:13       ` Stephen Warren
       [not found]         ` <525877F3.9070004-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Stephen Warren @ 2013-10-11 22:13 UTC (permalink / raw)
  To: Thierry Reding, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

On 10/07/2013 02:34 AM, Thierry Reding wrote:
> Tegra114 uses a slightly updated version of host1x with an additional
> syncpoint.

>  drivers/gpu/host1x/hw/host1x02.c            |  42 +++++
>  drivers/gpu/host1x/hw/host1x02.h            |  26 +++
>  drivers/gpu/host1x/hw/hw_host1x02_channel.h | 121 ++++++++++++++
>  drivers/gpu/host1x/hw/hw_host1x02_sync.h    | 243 ++++++++++++++++++++++++++++
>  drivers/gpu/host1x/hw/hw_host1x02_uclass.h  | 175 ++++++++++++++++++++

That seems like an awful lot of extra lines to support just one extra
syncpoint. Are there other changes? If not, can the code be
shared/parameterized somehow?

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

* Re: [PATCH v2 16/27] drm/tegra: Add Tegra114 display controller support
       [not found]     ` <1381134884-5816-17-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-10-11 22:14       ` Stephen Warren
       [not found]         ` <52587843.9070806-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Stephen Warren @ 2013-10-11 22:14 UTC (permalink / raw)
  To: Thierry Reding, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mikko Perttunen

On 10/07/2013 02:34 AM, Thierry Reding wrote:
> From: Mikko Perttunen <mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> 
> The Tegra114 display controller is backwards-compatible with previous
> generations of the Tegra SoC. No code changes are required.

If the HW is backwards-compatible, then there's no need to add extra
compatible values to the driver; just write the following in the DT, and
it'll just work:

compatible = "nvidia,tegra114-dc", "nvidia,tegra30-dc";

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

* Re: [PATCH v2 17/27] drm/tegra: Add Tegra114 HDMI support
       [not found]     ` <1381134884-5816-18-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-10-11 22:19       ` Stephen Warren
       [not found]         ` <52587967.6050806-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Stephen Warren @ 2013-10-11 22:19 UTC (permalink / raw)
  To: Thierry Reding, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mikko Perttunen

On 10/07/2013 02:34 AM, Thierry Reding wrote:
> From: Mikko Perttunen <mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> 
> Tegra114 TMDS configuration requires a new peak_current field and the
> driver current override bit has changed position.

> diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c

>  static const struct tmds_config tegra2_tmds_config[] = {
> @@ -223,6 +224,85 @@ static const struct tmds_config tegra3_tmds_config[] = {

Not related to this patch, but those should have been named
tegra20_tmds_config[] and tegra30_tmds_config[].

>  static void tegra_hdmi_setup_tmds(struct tegra_hdmi *hdmi,

> -	value = tmds->drive_current | DRIVE_CURRENT_FUSE_OVERRIDE;
> -	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
> +	if (of_device_is_compatible(np, "nvidia,tegra114-hdmi")) {

Let's not check this at run-time. Instead, host1x_drm_subdevs[]'s .data
field should be used to contain either flags or a pointer to a
configuration structure, either of which can be directly consulted to
determine the properties of the HW in a feature-oriented/semantic way.

drivers/gpio/gpio-tegra.c's
tegra20_gpio_config/tegra30_gpio_config/tegra_gpio_of_match provide a
good example of this.

This means that if Tegra124 is identical to Tegra114, yet a hypothetical
Tegra999 is different, you don't have to keep adjusting these if
conditions throughout the code; they can simply refer to the same
feature bit forever.

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

* Re: [PATCH v2 17/27] drm/tegra: Add Tegra114 HDMI support
       [not found]         ` <52587967.6050806-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-10-11 22:22           ` Stephen Warren
       [not found]             ` <52587A16.7050200-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
  2013-10-12 11:41           ` Thierry Reding
  1 sibling, 1 reply; 87+ messages in thread
From: Stephen Warren @ 2013-10-11 22:22 UTC (permalink / raw)
  To: Thierry Reding, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mikko Perttunen

On 10/11/2013 04:19 PM, Stephen Warren wrote:
> On 10/07/2013 02:34 AM, Thierry Reding wrote:
>> From: Mikko Perttunen <mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
>>
>> Tegra114 TMDS configuration requires a new peak_current field and the
>> driver current override bit has changed position.
> 
>> diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
> 
>>  static const struct tmds_config tegra2_tmds_config[] = {
>> @@ -223,6 +224,85 @@ static const struct tmds_config tegra3_tmds_config[] = {
> 
> Not related to this patch, but those should have been named
> tegra20_tmds_config[] and tegra30_tmds_config[].

I see that patch 20 fixes this:-)

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

* Re: [PATCH v2 22/27] drm/panel: Add simple panel support
       [not found]     ` <1381134884-5816-23-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-10-11 22:33       ` Stephen Warren
       [not found]         ` <52587CBD.8010304-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Stephen Warren @ 2013-10-11 22:33 UTC (permalink / raw)
  To: Thierry Reding, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

On 10/07/2013 02:34 AM, Thierry Reding wrote:
> Add a driver for simple panels. Such panels can have a regulator that
> provides the supply voltage and a separate GPIO to enable the panel.
> Optionally the panels can have a backlight associated with them so it
> can be enabled or disabled according to the panel's power management
> mode.
> 
> Support is added for three panels: An AU Optronics 10.1" WSVGA, a
> Chunghwa Picture Tubes 10.1" WXGA and a Panasonic 10.1 WUXGA TFT LCD
> panel.

>  .../devicetree/bindings/panel/auo,b101aw03.txt     |   7 +
>  .../bindings/panel/chunghwa,claa101wb03.txt        |   7 +
>  .../bindings/panel/panasonic,vvx10f004b00.txt      |   7 +
>  .../devicetree/bindings/panel/simple-panel.txt     |  21 ++

Since this patch defines new DT bindings, it should also be sent to the
DT binding maintainers and DT mailing list.

> diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c

> +static int panel_simple_remove(struct platform_device *pdev)
> +{
> +	struct panel_simple *panel = platform_get_drvdata(pdev);
> +
> +	if (gpio_is_valid(panel->enable_gpio)) {
> +		if (panel->enable_gpio_flags & GPIO_ACTIVE_LOW)
> +			gpio_set_value(panel->enable_gpio, 1);
> +		else
> +			gpio_set_value(panel->enable_gpio, 0);
> +
> +		gpio_free(panel->enable_gpio);
> +	}
> +
> +	regulator_disable(panel->supply);

Can you just call panel_simple_disable() to do the HW cleanup, and just
do resource cleanup here?

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

* Re: [PATCH v2 25/27] gpu: host1x: Add MIPI pad calibration support
       [not found]     ` <1381134884-5816-26-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-10-11 22:37       ` Stephen Warren
       [not found]         ` <52587DAF.9080003-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Stephen Warren @ 2013-10-11 22:37 UTC (permalink / raw)
  To: Thierry Reding, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

On 10/07/2013 02:34 AM, Thierry Reding wrote:
> This driver adds support to perform calibration of the MIPI pads for CSI
> and DSI.

> diff --git a/drivers/gpu/host1x/mipi.c b/drivers/gpu/host1x/mipi.c

> +int tegra_mipi_calibrate(struct device *device)
...
> +	err = of_parse_phandle_with_args(device->of_node, "calibrate",
> +					 "#calibrate-cells", 0, &args);
...
> +static struct of_device_id tegra_mipi_of_match[] = {
> +	{ .compatible = "nvidia,tegra114-mipi", },

Is the DT binding for that compatible value documented anywhere? I'm not
sure what #calibrate-cells means; it doesn't seem to be used...

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

* Re: [PATCH v2 26/27] drm/tegra: Add DSI support
       [not found]     ` <1381134884-5816-27-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-10-11 22:43       ` Stephen Warren
       [not found]         ` <52587F17.7060104-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Stephen Warren @ 2013-10-11 22:43 UTC (permalink / raw)
  To: Thierry Reding, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

On 10/07/2013 02:34 AM, Thierry Reding wrote:
> This commit adds support for both DSI outputs found on Tegra. Only very
> minimal functionality is implemented, so advanced features like ganged
> mode won't work.
> 
> Due to the lack of other test hardware, some sections of the driver are
> hardcoded to work with Dalmore.

> diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c

> +static int tegra_dsi_show_regs(struct seq_file *s, void *data)
> +{
> +	struct drm_info_node *node = s->private;
> +	struct tegra_dsi *dsi = node->info_ent->data;
> +
> +#define DUMP_REG(name)						\
> +	seq_printf(s, "%-32s %#05x %08lx\n", #name, name,	\
> +		   tegra_dsi_readl(dsi, name))
> +
> +	DUMP_REG(DSI_INCR_SYNCPT);

Does it make sense to use an MMIO regmap instead? That way, you get all
the debugfs files for free...

> +static int tegra_dsi_probe(struct platform_device *pdev)

> +	dsi->clk_parent = devm_clk_get(&pdev->dev, "parent");
> +	if (IS_ERR(dsi->clk_parent))
> +		return PTR_ERR(dsi->clk_parent);
...
> +static const struct of_device_id tegra_dsi_of_match[] = {
> +	{ .compatible = "nvidia,tegra114-dsi", },

Is this DT binding documented? The clk_get() call above in particular
imposes the requirement that DT contain a clock with that name, which
should be part of the binding documentation.

Hopefully the values that this driver hard-codes won't be an issue for
the DT binding; we can simply make those values the default if
properties are missing. I assume it's likely that such a strategy will
work here?

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

* Re: [PATCH v2 27/27] drm/tegra: Add Tegra114 gr2d support
       [not found]     ` <1381134884-5816-28-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-10-11 22:43       ` Stephen Warren
       [not found]         ` <52587F2D.9070007-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Stephen Warren @ 2013-10-11 22:43 UTC (permalink / raw)
  To: Thierry Reding, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

On 10/07/2013 02:34 AM, Thierry Reding wrote:
> The gr2d hardware in Tegra114 is compatible with that of Tegra20 and
> Tegra30. No functionaly changes are required.

Similarly here, if the HW is 100% backwards-compatible, there's no need
to add compatible values to the driver.

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

* Re: [PATCH v2 14/27] drm/tegra: Move driver to DRM tree
       [not found]         ` <52587797.7000402-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-10-12 11:16           ` Thierry Reding
  0 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-12 11:16 UTC (permalink / raw)
  To: Stephen Warren
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

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

On Fri, Oct 11, 2013 at 04:11:35PM -0600, Stephen Warren wrote:
> On 10/07/2013 02:34 AM, Thierry Reding wrote:
> > In order to subsystem-wide changes easier, move the Tegra DRM driver
>              ^^ make ?

I had noticed myself already and fixed it up.

Thanks,
Thierry

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

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

* Re: [PATCH v2 15/27] gpu: host1x: Add support for Tegra114
       [not found]         ` <525877F3.9070004-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-10-12 11:24           ` Thierry Reding
  2013-10-14  5:30             ` Terje Bergström
  2013-10-14 18:07             ` Stephen Warren
  0 siblings, 2 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-12 11:24 UTC (permalink / raw)
  To: Stephen Warren, Terje Bergstrom
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

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

On Fri, Oct 11, 2013 at 04:13:07PM -0600, Stephen Warren wrote:
> On 10/07/2013 02:34 AM, Thierry Reding wrote:
> > Tegra114 uses a slightly updated version of host1x with an additional
> > syncpoint.
> 
> >  drivers/gpu/host1x/hw/host1x02.c            |  42 +++++
> >  drivers/gpu/host1x/hw/host1x02.h            |  26 +++
> >  drivers/gpu/host1x/hw/hw_host1x02_channel.h | 121 ++++++++++++++
> >  drivers/gpu/host1x/hw/hw_host1x02_sync.h    | 243 ++++++++++++++++++++++++++++
> >  drivers/gpu/host1x/hw/hw_host1x02_uclass.h  | 175 ++++++++++++++++++++
> 
> That seems like an awful lot of extra lines to support just one extra
> syncpoint. Are there other changes? If not, can the code be
> shared/parameterized somehow?

Yeah, I don't like very much how this is currently done. I mean about
half of this is actually duplicate code because of the static inline
functions used for register defines. As discussed elsewhere this was
originally meant to be used for coverage testing, but nobody's done
anything like that as far as I know. I'm also not convinced that these
would be very useful in coverage testing, but adding Terje on Cc and
unless he or anyone else has any (strong) objections I'll go and remove
the duplicate definitions and while at it see if I can come up with a
way to share more code/definitions between versions of host1x.

Do you see this as a blocker for 3.13 or can I do the cleanup after
that? As far as I know Tegra124 has a more heavily modified version of
host1x so implementing Tegra124 support might be a good opportunity to
clean this up anyway.

Thierry

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

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

* Re: [PATCH v2 16/27] drm/tegra: Add Tegra114 display controller support
       [not found]         ` <52587843.9070806-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-10-12 11:32           ` Thierry Reding
  2013-10-14 18:05             ` Stephen Warren
  0 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-12 11:32 UTC (permalink / raw)
  To: Stephen Warren
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mikko Perttunen

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

On Fri, Oct 11, 2013 at 04:14:27PM -0600, Stephen Warren wrote:
> On 10/07/2013 02:34 AM, Thierry Reding wrote:
> > From: Mikko Perttunen <mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> > 
> > The Tegra114 display controller is backwards-compatible with previous
> > generations of the Tegra SoC. No code changes are required.
> 
> If the HW is backwards-compatible, then there's no need to add extra
> compatible values to the driver; just write the following in the DT, and
> it'll just work:
> 
> compatible = "nvidia,tegra114-dc", "nvidia,tegra30-dc";

One reason why I thought it might be useful to still include this, even
though unnecessary, was to match it to the host1x_drm_subdevs table. We
can probably remove the entry from there as well, though.

As far as I can tell, the same holds for Tegra30, which is also
backwards compatible with Tegra20 but the DTS doesn't contain the
Tegra20 compatible. So to keep ABI compatibility we'll need to keep the
nvidia,tegra30-dc in the driver's match tables, but I could still update
the DTS to include the nvidia,tegra20-dc for correctness.

Does that make sense?

Thierry

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

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

* Re: [PATCH v2 17/27] drm/tegra: Add Tegra114 HDMI support
       [not found]             ` <52587A16.7050200-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-10-12 11:35               ` Thierry Reding
  0 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-12 11:35 UTC (permalink / raw)
  To: Stephen Warren
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mikko Perttunen

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

On Fri, Oct 11, 2013 at 04:22:14PM -0600, Stephen Warren wrote:
> On 10/11/2013 04:19 PM, Stephen Warren wrote:
> > On 10/07/2013 02:34 AM, Thierry Reding wrote:
> >> From: Mikko Perttunen <mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> >>
> >> Tegra114 TMDS configuration requires a new peak_current field and the
> >> driver current override bit has changed position.
> > 
> >> diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
> > 
> >>  static const struct tmds_config tegra2_tmds_config[] = {
> >> @@ -223,6 +224,85 @@ static const struct tmds_config tegra3_tmds_config[] = {
> > 
> > Not related to this patch, but those should have been named
> > tegra20_tmds_config[] and tegra30_tmds_config[].
> 
> I see that patch 20 fixes this:-)

I can probably move patch 20 to somewhere earlier in the patch series,
so that these changes are there when Tegra114 support is added.

Thierry

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

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

* Re: [PATCH v2 17/27] drm/tegra: Add Tegra114 HDMI support
       [not found]         ` <52587967.6050806-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
  2013-10-11 22:22           ` Stephen Warren
@ 2013-10-12 11:41           ` Thierry Reding
  2013-10-14 18:10             ` Stephen Warren
  1 sibling, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-12 11:41 UTC (permalink / raw)
  To: Stephen Warren
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mikko Perttunen

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

On Fri, Oct 11, 2013 at 04:19:19PM -0600, Stephen Warren wrote:
> On 10/07/2013 02:34 AM, Thierry Reding wrote:
> > From: Mikko Perttunen <mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> > 
> > Tegra114 TMDS configuration requires a new peak_current field and the
> > driver current override bit has changed position.
> 
> > diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
> 
> >  static const struct tmds_config tegra2_tmds_config[] = {
> > @@ -223,6 +224,85 @@ static const struct tmds_config tegra3_tmds_config[] = {
> 
> Not related to this patch, but those should have been named
> tegra20_tmds_config[] and tegra30_tmds_config[].
> 
> >  static void tegra_hdmi_setup_tmds(struct tegra_hdmi *hdmi,
> 
> > -	value = tmds->drive_current | DRIVE_CURRENT_FUSE_OVERRIDE;
> > -	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
> > +	if (of_device_is_compatible(np, "nvidia,tegra114-hdmi")) {
> 
> Let's not check this at run-time. Instead, host1x_drm_subdevs[]'s .data
> field should be used to contain either flags or a pointer to a
> configuration structure, either of which can be directly consulted to
> determine the properties of the HW in a feature-oriented/semantic way.
> 
> drivers/gpio/gpio-tegra.c's
> tegra20_gpio_config/tegra30_gpio_config/tegra_gpio_of_match provide a
> good example of this.
> 
> This means that if Tegra124 is identical to Tegra114, yet a hypothetical
> Tegra999 is different, you don't have to keep adjusting these if
> conditions throughout the code; they can simply refer to the same
> feature bit forever.

Okay, I'll see what I can come up with. It's unfortunately not as simple
as the GPIO driver's parameterization, and who knows what other
differences will be introduced in some later versions of this block.

What I mean is that at some point it becomes questionable whether it
makes sense to parameterize at all if you have to encode the register
offset and bit position within that register for a large number of bits.

Thierry

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

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

* Re: [PATCH v2 15/27] gpu: host1x: Add support for Tegra114
  2013-10-12 11:24           ` Thierry Reding
@ 2013-10-14  5:30             ` Terje Bergström
       [not found]               ` <525B8174.4000907-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2013-10-14 18:07             ` Stephen Warren
  1 sibling, 1 reply; 87+ messages in thread
From: Terje Bergström @ 2013-10-14  5:30 UTC (permalink / raw)
  To: Thierry Reding, Stephen Warren
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On 12.10.2013 14:24, Thierry Reding wrote:
> Yeah, I don't like very much how this is currently done. I mean about
> half of this is actually duplicate code because of the static inline
> functions used for register defines. As discussed elsewhere this was
> originally meant to be used for coverage testing, but nobody's done
> anything like that as far as I know. I'm also not convinced that these
> would be very useful in coverage testing, but adding Terje on Cc and
> unless he or anyone else has any (strong) objections I'll go and remove
> the duplicate definitions and while at it see if I can come up with a
> way to share more code/definitions between versions of host1x.
> 
> Do you see this as a blocker for 3.13 or can I do the cleanup after
> that? As far as I know Tegra124 has a more heavily modified version of
> host1x so implementing Tegra124 support might be a good opportunity to
> clean this up anyway.

For Tegra114 the register level changes are small (one channel added,
wait bases, expanded fifo, etc) but for Tegra124 they're bigger. So
let's keep the long term in mind.

I'm ok with removing the inlines. Just the energy spent in discussing it
over and over again is more than the benefits that a proper compiler
gives over the preprocessor (type checking, real syntax checking,
coverage, gdb breakpoints, etc). For some reason (which escapes me)
preprocessor magic seems to be the norm in Linux kernel.

Parameterized code gets easily really ugly, difficult to debug and
difficult to port to new chips. There's much less work and opportunity
of mistake in maintaining data in a couple of files than subtle
algorithms all over the driver. If we don't have inlines in hw headers,
the headers become tiny and any benefits of parameterized code versus
per-hw version headers vanish.

Terje

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

* Re: [PATCH v2 27/27] drm/tegra: Add Tegra114 gr2d support
       [not found]         ` <52587F2D.9070007-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-10-14  5:58           ` Terje Bergström
       [not found]             ` <525B880A.7090802-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Terje Bergström @ 2013-10-14  5:58 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

On 12.10.2013 01:43, Stephen Warren wrote:
> On 10/07/2013 02:34 AM, Thierry Reding wrote:
>> The gr2d hardware in Tegra114 is compatible with that of Tegra20 and
>> Tegra30. No functionaly changes are required.
> Similarly here, if the HW is 100% backwards-compatible, there's no need
> to add compatible values to the driver.

We've used this mechanism for attaching a per-hw-version data structure
in match table to accomodate differences in how the hardware is power
gated, reset, booted, some per-soc performance related changes etc. It's
also used in staging features for new chips, such as disabling power
features when they're not working/verified yet.

Upstream driver is not yet in a state where that is relevant.

With this, would we still be able to do that with match table? It sounds
like we could, because we can still (even with multiple compatible
properties) add separate entries in match table and I guess the
compatible properties matched in order.

Terje

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

* Re: [PATCH v2 25/27] gpu: host1x: Add MIPI pad calibration support
       [not found]         ` <52587DAF.9080003-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-10-14 13:44           ` Thierry Reding
  0 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-14 13:44 UTC (permalink / raw)
  To: Stephen Warren
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

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

On Fri, Oct 11, 2013 at 04:37:35PM -0600, Stephen Warren wrote:
> On 10/07/2013 02:34 AM, Thierry Reding wrote:
> > This driver adds support to perform calibration of the MIPI pads for CSI
> > and DSI.
> 
> > diff --git a/drivers/gpu/host1x/mipi.c b/drivers/gpu/host1x/mipi.c
> 
> > +int tegra_mipi_calibrate(struct device *device)
> ...
> > +	err = of_parse_phandle_with_args(device->of_node, "calibrate",
> > +					 "#calibrate-cells", 0, &args);
> ...
> > +static struct of_device_id tegra_mipi_of_match[] = {
> > +	{ .compatible = "nvidia,tegra114-mipi", },
> 
> Is the DT binding for that compatible value documented anywhere? I'm not
> sure what #calibrate-cells means; it doesn't seem to be used...

I forgot to add a binding document, but I've complemented my local patch
series with one. The #calibrate-cells defines the number of cells used
for the specifier and should be 1. I suspect that we'll never get to
have more than 32 pads that can be calibrated, but perhaps at some point
data other than a bitmask of the pads will be needed.

Thierry

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

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

* Re: [PATCH v2 26/27] drm/tegra: Add DSI support
       [not found]         ` <52587F17.7060104-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-10-14 13:55           ` Thierry Reding
       [not found]             ` <20131014135548.GB16302-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-14 13:55 UTC (permalink / raw)
  To: Stephen Warren
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

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

On Fri, Oct 11, 2013 at 04:43:35PM -0600, Stephen Warren wrote:
> On 10/07/2013 02:34 AM, Thierry Reding wrote:
> > This commit adds support for both DSI outputs found on Tegra. Only very
> > minimal functionality is implemented, so advanced features like ganged
> > mode won't work.
> > 
> > Due to the lack of other test hardware, some sections of the driver are
> > hardcoded to work with Dalmore.
> 
> > diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
> 
> > +static int tegra_dsi_show_regs(struct seq_file *s, void *data)
> > +{
> > +	struct drm_info_node *node = s->private;
> > +	struct tegra_dsi *dsi = node->info_ent->data;
> > +
> > +#define DUMP_REG(name)						\
> > +	seq_printf(s, "%-32s %#05x %08lx\n", #name, name,	\
> > +		   tegra_dsi_readl(dsi, name))
> > +
> > +	DUMP_REG(DSI_INCR_SYNCPT);
> 
> Does it make sense to use an MMIO regmap instead? That way, you get all
> the debugfs files for free...

As far as I know, regmap doesn't give you the symbolic names for the
registers. I find that a rather useful feature because it allows to
easily compare the registers to the ones in our downstream kernels.

> > +static int tegra_dsi_probe(struct platform_device *pdev)
> 
> > +	dsi->clk_parent = devm_clk_get(&pdev->dev, "parent");
> > +	if (IS_ERR(dsi->clk_parent))
> > +		return PTR_ERR(dsi->clk_parent);
> ...
> > +static const struct of_device_id tegra_dsi_of_match[] = {
> > +	{ .compatible = "nvidia,tegra114-dsi", },
> 
> Is this DT binding documented? The clk_get() call above in particular
> imposes the requirement that DT contain a clock with that name, which
> should be part of the binding documentation.

I've documented the requirement for both the regular "dsi" as well as
the "parent" clock in the binding documentation, which I forgot to
update in the previous series.

Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt is where
this is documented. The DSI node has a compatible property of
nvidia,tegra<chip>-dsi, which I think is a common way to write the
binding at least for Tegra.

> Hopefully the values that this driver hard-codes won't be an issue for
> the DT binding; we can simply make those values the default if
> properties are missing. I assume it's likely that such a strategy will
> work here?

They shouldn't. In fact I think it should be possible to probe them
either using mechanisms built into DSI, or by querying the attached
panel (as matched by the corresponding device tree node).

I haven't done the latter yet because I plan to investigate whether
builtin DSI functionality can be used to probe for the information.

Thierry

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

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

* Re: [PATCH v2 27/27] drm/tegra: Add Tegra114 gr2d support
       [not found]             ` <525B880A.7090802-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-10-14 14:00               ` Thierry Reding
       [not found]                 ` <20131014140010.GC16302-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
  2013-10-14 18:13               ` Stephen Warren
  1 sibling, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-14 14:00 UTC (permalink / raw)
  To: Terje Bergström
  Cc: Stephen Warren, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

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

On Mon, Oct 14, 2013 at 08:58:34AM +0300, Terje Bergström wrote:
> On 12.10.2013 01:43, Stephen Warren wrote:
> > On 10/07/2013 02:34 AM, Thierry Reding wrote:
> >> The gr2d hardware in Tegra114 is compatible with that of Tegra20 and
> >> Tegra30. No functionaly changes are required.
> > Similarly here, if the HW is 100% backwards-compatible, there's no need
> > to add compatible values to the driver.
> 
> We've used this mechanism for attaching a per-hw-version data structure
> in match table to accomodate differences in how the hardware is power
> gated, reset, booted, some per-soc performance related changes etc. It's
> also used in staging features for new chips, such as disabling power
> features when they're not working/verified yet.
> 
> Upstream driver is not yet in a state where that is relevant.
> 
> With this, would we still be able to do that with match table? It sounds
> like we could, because we can still (even with multiple compatible
> properties) add separate entries in match table and I guess the
> compatible properties matched in order.

Yes, as long as the device tree files includes the most specific value
in the compatible this should still be possible. So we'd have this:

	gr2d@54140000 {
		compatible = "nvida,tegra114-gr2d", "nvidia,tegra20-gr2d";
		...
	};

and the driver will match on "nvidia,tegra20-gr2d" if the more specific
"nvidia,tegra114-gr2d" is not there. When the driver is updated to
support Tegra114 specific functionality, then a more specific entry can
be added to the compatible table to handle it.

Thierry

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

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

* Re: [PATCH v2 22/27] drm/panel: Add simple panel support
       [not found]         ` <52587CBD.8010304-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-10-14 14:10           ` Thierry Reding
  0 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-14 14:10 UTC (permalink / raw)
  To: Stephen Warren
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

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

On Fri, Oct 11, 2013 at 04:33:33PM -0600, Stephen Warren wrote:
> On 10/07/2013 02:34 AM, Thierry Reding wrote:
> > Add a driver for simple panels. Such panels can have a regulator that
> > provides the supply voltage and a separate GPIO to enable the panel.
> > Optionally the panels can have a backlight associated with them so it
> > can be enabled or disabled according to the panel's power management
> > mode.
> > 
> > Support is added for three panels: An AU Optronics 10.1" WSVGA, a
> > Chunghwa Picture Tubes 10.1" WXGA and a Panasonic 10.1 WUXGA TFT LCD
> > panel.
> 
> >  .../devicetree/bindings/panel/auo,b101aw03.txt     |   7 +
> >  .../bindings/panel/chunghwa,claa101wb03.txt        |   7 +
> >  .../bindings/panel/panasonic,vvx10f004b00.txt      |   7 +
> >  .../devicetree/bindings/panel/simple-panel.txt     |  21 ++
> 
> Since this patch defines new DT bindings, it should also be sent to the
> DT binding maintainers and DT mailing list.

I Cc'ed at least the DT mailing list. The get_maintainer.pl generated
list was pretty large, and I keep getting different feedback about
whether it's a good idea to Cc individual people or just the relevant
mailing lists. In this case I assumed that all DT binding maintainers
would be reading the DT mailing list and therefore see the patches. I
can change my habit though if you prefer to get an extra copy.

One slight inconvenience with large series like this is that a lot of
work is required to handcraft an appropriate list of people and lists
to send the patches to. Furthermore I personally like receiving whole
patch series because it gives me full context, but other people seem
to want only the patches that they need to worry about. So what I
usually do is handcraft a list of people I want to send patches to
and use it for the whole series. If that list grows too large, I'll
usually trim it down to include only lists. Having to handcraft lists
for each individual patch doesn't sound that useful to me.

> > diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
> 
> > +static int panel_simple_remove(struct platform_device *pdev)
> > +{
> > +	struct panel_simple *panel = platform_get_drvdata(pdev);
> > +
> > +	if (gpio_is_valid(panel->enable_gpio)) {
> > +		if (panel->enable_gpio_flags & GPIO_ACTIVE_LOW)
> > +			gpio_set_value(panel->enable_gpio, 1);
> > +		else
> > +			gpio_set_value(panel->enable_gpio, 0);
> > +
> > +		gpio_free(panel->enable_gpio);
> > +	}
> > +
> > +	regulator_disable(panel->supply);
> 
> Can you just call panel_simple_disable() to do the HW cleanup, and just
> do resource cleanup here?

Yes, I can.

Thanks,
Thierry

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

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

* Re: [PATCH v2 16/27] drm/tegra: Add Tegra114 display controller support
  2013-10-12 11:32           ` Thierry Reding
@ 2013-10-14 18:05             ` Stephen Warren
       [not found]               ` <525C325E.2090700-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Stephen Warren @ 2013-10-14 18:05 UTC (permalink / raw)
  To: Thierry Reding
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mikko Perttunen

On 10/12/2013 05:32 AM, Thierry Reding wrote:
> On Fri, Oct 11, 2013 at 04:14:27PM -0600, Stephen Warren wrote:
>> On 10/07/2013 02:34 AM, Thierry Reding wrote:
>>> From: Mikko Perttunen <mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
>>> 
>>> The Tegra114 display controller is backwards-compatible with
>>> previous generations of the Tegra SoC. No code changes are
>>> required.
>> 
>> If the HW is backwards-compatible, then there's no need to add
>> extra compatible values to the driver; just write the following
>> in the DT, and it'll just work:
>> 
>> compatible = "nvidia,tegra114-dc", "nvidia,tegra30-dc";
> 
> One reason why I thought it might be useful to still include this,
> even though unnecessary, was to match it to the host1x_drm_subdevs
> table. We can probably remove the entry from there as well,
> though.
> 
> As far as I can tell, the same holds for Tegra30, which is also 
> backwards compatible with Tegra20 but the DTS doesn't contain the 
> Tegra20 compatible. So to keep ABI compatibility we'll need to keep
> the nvidia,tegra30-dc in the driver's match tables, but I could
> still update the DTS to include the nvidia,tegra20-dc for
> correctness.
> 
> Does that make sense?

Yes, fixing the Tegra30 .dtsi file sounds like a good idea.

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

* Re: [PATCH v2 15/27] gpu: host1x: Add support for Tegra114
  2013-10-12 11:24           ` Thierry Reding
  2013-10-14  5:30             ` Terje Bergström
@ 2013-10-14 18:07             ` Stephen Warren
       [not found]               ` <525C32E5.2020406-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
  1 sibling, 1 reply; 87+ messages in thread
From: Stephen Warren @ 2013-10-14 18:07 UTC (permalink / raw)
  To: Thierry Reding, Terje Bergstrom
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On 10/12/2013 05:24 AM, Thierry Reding wrote:
> On Fri, Oct 11, 2013 at 04:13:07PM -0600, Stephen Warren wrote:
>> On 10/07/2013 02:34 AM, Thierry Reding wrote:
>>> Tegra114 uses a slightly updated version of host1x with an
>>> additional syncpoint.
>> 
>>> drivers/gpu/host1x/hw/host1x02.c            |  42 +++++ 
>>> drivers/gpu/host1x/hw/host1x02.h            |  26 +++ 
>>> drivers/gpu/host1x/hw/hw_host1x02_channel.h | 121
>>> ++++++++++++++ drivers/gpu/host1x/hw/hw_host1x02_sync.h    |
>>> 243 ++++++++++++++++++++++++++++ 
>>> drivers/gpu/host1x/hw/hw_host1x02_uclass.h  | 175
>>> ++++++++++++++++++++
>> 
>> That seems like an awful lot of extra lines to support just one
>> extra syncpoint. Are there other changes? If not, can the code
>> be shared/parameterized somehow?
> 
> Yeah, I don't like very much how this is currently done. I mean
> about half of this is actually duplicate code because of the static
> inline functions used for register defines. As discussed elsewhere
> this was originally meant to be used for coverage testing, but
> nobody's done anything like that as far as I know. I'm also not
> convinced that these would be very useful in coverage testing, but
> adding Terje on Cc and unless he or anyone else has any (strong)
> objections I'll go and remove the duplicate definitions and while
> at it see if I can come up with a way to share more
> code/definitions between versions of host1x.
> 
> Do you see this as a blocker for 3.13 or can I do the cleanup
> after that? As far as I know Tegra124 has a more heavily modified
> version of host1x so implementing Tegra124 support might be a good
> opportunity to clean this up anyway.

I guess I'm unsure re: whether it's a blocker. It's certainly not some
kind of ABI issue, so it's not like it forces our hand later; we can
easily refactor the code later. However, I'm slightly worried that if
we do actually intend to do that, it'll be seen as code-churn. Still,
I guess if the main DRM maintainers don't object to this, I'm OK with it.

Re: Terje's points, we (e.g. Terje) should work with the HW designers
to stop moving things about, so we don't have incompatible HW.

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

* Re: [PATCH v2 17/27] drm/tegra: Add Tegra114 HDMI support
  2013-10-12 11:41           ` Thierry Reding
@ 2013-10-14 18:10             ` Stephen Warren
       [not found]               ` <525C338D.50801-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Stephen Warren @ 2013-10-14 18:10 UTC (permalink / raw)
  To: Thierry Reding
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mikko Perttunen

On 10/12/2013 05:41 AM, Thierry Reding wrote:
> On Fri, Oct 11, 2013 at 04:19:19PM -0600, Stephen Warren wrote:
>> On 10/07/2013 02:34 AM, Thierry Reding wrote:
>>> From: Mikko Perttunen <mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
>>> 
>>> Tegra114 TMDS configuration requires a new peak_current field
>>> and the driver current override bit has changed position.
>> 
>>> diff --git a/drivers/gpu/drm/tegra/hdmi.c
>>> b/drivers/gpu/drm/tegra/hdmi.c
>> 
>>> static const struct tmds_config tegra2_tmds_config[] = { @@
>>> -223,6 +224,85 @@ static const struct tmds_config
>>> tegra3_tmds_config[] = {
>> 
>> Not related to this patch, but those should have been named 
>> tegra20_tmds_config[] and tegra30_tmds_config[].
>> 
>>> static void tegra_hdmi_setup_tmds(struct tegra_hdmi *hdmi,
>> 
>>> -	value = tmds->drive_current | DRIVE_CURRENT_FUSE_OVERRIDE; -
>>> tegra_hdmi_writel(hdmi, value,
>>> HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT); +	if
>>> (of_device_is_compatible(np, "nvidia,tegra114-hdmi")) {
>> 
>> Let's not check this at run-time. Instead, host1x_drm_subdevs[]'s
>> .data field should be used to contain either flags or a pointer
>> to a configuration structure, either of which can be directly
>> consulted to determine the properties of the HW in a
>> feature-oriented/semantic way.
>> 
>> drivers/gpio/gpio-tegra.c's 
>> tegra20_gpio_config/tegra30_gpio_config/tegra_gpio_of_match
>> provide a good example of this.
>> 
>> This means that if Tegra124 is identical to Tegra114, yet a
>> hypothetical Tegra999 is different, you don't have to keep
>> adjusting these if conditions throughout the code; they can
>> simply refer to the same feature bit forever.
> 
> Okay, I'll see what I can come up with. It's unfortunately not as
> simple as the GPIO driver's parameterization, and who knows what
> other differences will be introduced in some later versions of this
> block.
> 
> What I mean is that at some point it becomes questionable whether
> it makes sense to parameterize at all if you have to encode the
> register offset and bit position within that register for a large
> number of bits.

Well, I wasn't advocating that we shouldn't have an if statement at
all. Simply that the if statement shouldn't be doing string compares
of specific HW. Either of the following would be fine:

if (hdmi->soc_data->some_feature_flag)
   // just represents some code; doesn't have to be a function call
   do_something();
else;
  do_something_else();

or:

do_something(hdmi->soc_data->some_feature_value);

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

* Re: [PATCH v2 27/27] drm/tegra: Add Tegra114 gr2d support
       [not found]             ` <525B880A.7090802-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2013-10-14 14:00               ` Thierry Reding
@ 2013-10-14 18:13               ` Stephen Warren
  1 sibling, 0 replies; 87+ messages in thread
From: Stephen Warren @ 2013-10-14 18:13 UTC (permalink / raw)
  To: Terje Bergström, Thierry Reding,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA

On 10/13/2013 11:58 PM, Terje Bergström wrote:
> On 12.10.2013 01:43, Stephen Warren wrote:
>> On 10/07/2013 02:34 AM, Thierry Reding wrote:
>>> The gr2d hardware in Tegra114 is compatible with that of Tegra20 and
>>> Tegra30. No functionaly changes are required.
>>
>> Similarly here, if the HW is 100% backwards-compatible, there's no need
>> to add compatible values to the driver.
> 
> We've used this mechanism for attaching a per-hw-version data structure
> in match table to accomodate differences in how the hardware is power
> gated, reset, booted, some per-soc performance related changes etc.

If there are differences in those aspects of the HW, such that a driver
written only to the full specification of e.g. Tegra30 would not work on
Tegra114, then the HW is not actually compatible, and hence we do need
multiple compatible values in DT, and entries in the of_match table.

It sounds like the statement in the commit description:

>>> The gr2d hardware in Tegra114 is compatible with that of Tegra20 and
>>> Tegra30. No functionaly changes are required.

Might not be absolutely accurate in terms of HW, but only in terms of
the features that the driver uses so far. It'd be good to explicitly
qualify this in the commit description.

...
> Upstream driver is not yet in a state where that is relevant.

The compatible values should be picked based on the full feature-set of
the HW, not based on the subset of features supported by a particular
driver.

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

* Re: [PATCH v2 27/27] drm/tegra: Add Tegra114 gr2d support
       [not found]                 ` <20131014140010.GC16302-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
@ 2013-10-14 18:14                   ` Stephen Warren
       [not found]                     ` <525C3497.6010700-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Stephen Warren @ 2013-10-14 18:14 UTC (permalink / raw)
  To: Thierry Reding, Terje Bergström
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On 10/14/2013 08:00 AM, Thierry Reding wrote:
> On Mon, Oct 14, 2013 at 08:58:34AM +0300, Terje Bergström wrote:
>> On 12.10.2013 01:43, Stephen Warren wrote:
>>> On 10/07/2013 02:34 AM, Thierry Reding wrote:
>>>> The gr2d hardware in Tegra114 is compatible with that of
>>>> Tegra20 and Tegra30. No functionaly changes are required.
>>> Similarly here, if the HW is 100% backwards-compatible, there's
>>> no need to add compatible values to the driver.
>> 
>> We've used this mechanism for attaching a per-hw-version data
>> structure in match table to accomodate differences in how the
>> hardware is power gated, reset, booted, some per-soc performance
>> related changes etc. It's also used in staging features for new
>> chips, such as disabling power features when they're not
>> working/verified yet.
>> 
>> Upstream driver is not yet in a state where that is relevant.
>> 
>> With this, would we still be able to do that with match table? It
>> sounds like we could, because we can still (even with multiple
>> compatible properties) add separate entries in match table and I
>> guess the compatible properties matched in order.
> 
> Yes, as long as the device tree files includes the most specific
> value in the compatible this should still be possible. So we'd have
> this:
> 
> gr2d@54140000 { compatible = "nvida,tegra114-gr2d",
> "nvidia,tegra20-gr2d"; ... };
> 
> and the driver will match on "nvidia,tegra20-gr2d" if the more
> specific "nvidia,tegra114-gr2d" is not there. When the driver is
> updated to support Tegra114 specific functionality, then a more
> specific entry can be added to the compatible table to handle it.

True, but the DT fragment above is also only accurate /if/ a driver
that only knows about "nvidia,tegra20-gr2d" can operate 100% of the
features in Tegra20 HW on Tegra114 HW forever.

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

* Re: [PATCH v2 26/27] drm/tegra: Add DSI support
       [not found]             ` <20131014135548.GB16302-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
@ 2013-10-14 18:16               ` Stephen Warren
       [not found]                 ` <525C3510.60802-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Stephen Warren @ 2013-10-14 18:16 UTC (permalink / raw)
  To: Thierry Reding
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On 10/14/2013 07:55 AM, Thierry Reding wrote:
> On Fri, Oct 11, 2013 at 04:43:35PM -0600, Stephen Warren wrote:
>> On 10/07/2013 02:34 AM, Thierry Reding wrote:
>>> This commit adds support for both DSI outputs found on Tegra. Only very
>>> minimal functionality is implemented, so advanced features like ganged
>>> mode won't work.
>>>
>>> Due to the lack of other test hardware, some sections of the driver are
>>> hardcoded to work with Dalmore.
>>
>>> diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
>>
>>> +static int tegra_dsi_show_regs(struct seq_file *s, void *data)
>>> +{
>>> +	struct drm_info_node *node = s->private;
>>> +	struct tegra_dsi *dsi = node->info_ent->data;
>>> +
>>> +#define DUMP_REG(name)						\
>>> +	seq_printf(s, "%-32s %#05x %08lx\n", #name, name,	\
>>> +		   tegra_dsi_readl(dsi, name))
>>> +
>>> +	DUMP_REG(DSI_INCR_SYNCPT);
>>
>> Does it make sense to use an MMIO regmap instead? That way, you get all
>> the debugfs files for free...
> 
> As far as I know, regmap doesn't give you the symbolic names for the
> registers. I find that a rather useful feature because it allows to
> easily compare the registers to the ones in our downstream kernels.

True. However, we should really be writing user-space scripts to encode
that information. Such a script could be useful e.g. if reading the
information directly from /dev/mem or JTAG too, and bloating the kernel
with debug strings doesn't seem like a great idea.

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

* Re: [PATCH v2 27/27] drm/tegra: Add Tegra114 gr2d support
       [not found]                     ` <525C3497.6010700-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-10-15  5:51                       ` Terje Bergström
       [not found]                         ` <525CD7F3.10907-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2013-10-15  8:37                       ` Thierry Reding
  1 sibling, 1 reply; 87+ messages in thread
From: Terje Bergström @ 2013-10-15  5:51 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On 14.10.2013 21:14, Stephen Warren wrote:
> On 10/14/2013 08:00 AM, Thierry Reding wrote:
>> Yes, as long as the device tree files includes the most specific
>> value in the compatible this should still be possible. So we'd have
>> this:
>>
>> gr2d@54140000 { compatible = "nvida,tegra114-gr2d",
>> "nvidia,tegra20-gr2d"; ... };
>>
>> and the driver will match on "nvidia,tegra20-gr2d" if the more
>> specific "nvidia,tegra114-gr2d" is not there. When the driver is
>> updated to support Tegra114 specific functionality, then a more
>> specific entry can be added to the compatible table to handle it.
> 
> True, but the DT fragment above is also only accurate /if/ a driver
> that only knows about "nvidia,tegra20-gr2d" can operate 100% of the
> features in Tegra20 HW on Tegra114 HW forever.

I don't know of any hardware incompatibility. The only difference is
related to something not directly to 2D. We moved host1x away from the
power domain, so in Tegra114 we're able to power gate 2D and EPP. The
DVFS tables are also different.

I'd say say adding the compatible property "nvidia,tegra20-gr2d" for
Tegra114's 2D is accurate and we're able to use the match table to drive
any SW policy differences.

Terje

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

* Re: [PATCH v2 15/27] gpu: host1x: Add support for Tegra114
       [not found]               ` <525C32E5.2020406-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-10-15  8:03                 ` Thierry Reding
  0 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-15  8:03 UTC (permalink / raw)
  To: Stephen Warren, Dave Airlie
  Cc: Terje Bergstrom, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

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

On Mon, Oct 14, 2013 at 12:07:33PM -0600, Stephen Warren wrote:
> On 10/12/2013 05:24 AM, Thierry Reding wrote:
> > On Fri, Oct 11, 2013 at 04:13:07PM -0600, Stephen Warren wrote:
> >> On 10/07/2013 02:34 AM, Thierry Reding wrote:
> >>> Tegra114 uses a slightly updated version of host1x with an
> >>> additional syncpoint.
> >> 
> >>> drivers/gpu/host1x/hw/host1x02.c            |  42 +++++ 
> >>> drivers/gpu/host1x/hw/host1x02.h            |  26 +++ 
> >>> drivers/gpu/host1x/hw/hw_host1x02_channel.h | 121
> >>> ++++++++++++++ drivers/gpu/host1x/hw/hw_host1x02_sync.h    |
> >>> 243 ++++++++++++++++++++++++++++ 
> >>> drivers/gpu/host1x/hw/hw_host1x02_uclass.h  | 175
> >>> ++++++++++++++++++++
> >> 
> >> That seems like an awful lot of extra lines to support just one
> >> extra syncpoint. Are there other changes? If not, can the code
> >> be shared/parameterized somehow?
> > 
> > Yeah, I don't like very much how this is currently done. I mean
> > about half of this is actually duplicate code because of the static
> > inline functions used for register defines. As discussed elsewhere
> > this was originally meant to be used for coverage testing, but
> > nobody's done anything like that as far as I know. I'm also not
> > convinced that these would be very useful in coverage testing, but
> > adding Terje on Cc and unless he or anyone else has any (strong)
> > objections I'll go and remove the duplicate definitions and while
> > at it see if I can come up with a way to share more
> > code/definitions between versions of host1x.
> > 
> > Do you see this as a blocker for 3.13 or can I do the cleanup
> > after that? As far as I know Tegra124 has a more heavily modified
> > version of host1x so implementing Tegra124 support might be a good
> > opportunity to clean this up anyway.
> 
> I guess I'm unsure re: whether it's a blocker. It's certainly not some
> kind of ABI issue, so it's not like it forces our hand later; we can
> easily refactor the code later. However, I'm slightly worried that if
> we do actually intend to do that, it'll be seen as code-churn. Still,
> I guess if the main DRM maintainers don't object to this, I'm OK with it.

Adding Dave. Dave, do you have any objections to cleaning this up after
3.13? I'd prefer not to have to do it this cycle because I'd like to
focus on what patches I currently have. The plan is to upstream support
for the next SoC (Tegra124) for 3.14 and I'd much rather do the cleanup
along with that work.

Does that sound reasonable?

Thierry

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

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

* Re: [PATCH v2 15/27] gpu: host1x: Add support for Tegra114
       [not found]               ` <525B8174.4000907-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-10-15  8:05                 ` Thierry Reding
  0 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-15  8:05 UTC (permalink / raw)
  To: Terje Bergström
  Cc: Stephen Warren, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

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

On Mon, Oct 14, 2013 at 08:30:28AM +0300, Terje Bergström wrote:
> On 12.10.2013 14:24, Thierry Reding wrote:
> > Yeah, I don't like very much how this is currently done. I mean about
> > half of this is actually duplicate code because of the static inline
> > functions used for register defines. As discussed elsewhere this was
> > originally meant to be used for coverage testing, but nobody's done
> > anything like that as far as I know. I'm also not convinced that these
> > would be very useful in coverage testing, but adding Terje on Cc and
> > unless he or anyone else has any (strong) objections I'll go and remove
> > the duplicate definitions and while at it see if I can come up with a
> > way to share more code/definitions between versions of host1x.
> > 
> > Do you see this as a blocker for 3.13 or can I do the cleanup after
> > that? As far as I know Tegra124 has a more heavily modified version of
> > host1x so implementing Tegra124 support might be a good opportunity to
> > clean this up anyway.
> 
> For Tegra114 the register level changes are small (one channel added,
> wait bases, expanded fifo, etc) but for Tegra124 they're bigger. So
> let's keep the long term in mind.

I agree with Stephen here. We should really be working together with HW
to prevent as many incompatibilities as we can.

> I'm ok with removing the inlines. Just the energy spent in discussing it
> over and over again is more than the benefits that a proper compiler
> gives over the preprocessor (type checking, real syntax checking,
> coverage, gdb breakpoints, etc). For some reason (which escapes me)
> preprocessor magic seems to be the norm in Linux kernel.
> 
> Parameterized code gets easily really ugly, difficult to debug and
> difficult to port to new chips. There's much less work and opportunity
> of mistake in maintaining data in a couple of files than subtle
> algorithms all over the driver. If we don't have inlines in hw headers,
> the headers become tiny and any benefits of parameterized code versus
> per-hw version headers vanish.

I'll keep that in mind when I revisit this.

Thierry

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

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

* Re: [PATCH v2 16/27] drm/tegra: Add Tegra114 display controller support
       [not found]               ` <525C325E.2090700-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-10-15  8:06                 ` Thierry Reding
  0 siblings, 0 replies; 87+ messages in thread
From: Thierry Reding @ 2013-10-15  8:06 UTC (permalink / raw)
  To: Stephen Warren
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mikko Perttunen

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

On Mon, Oct 14, 2013 at 12:05:18PM -0600, Stephen Warren wrote:
> On 10/12/2013 05:32 AM, Thierry Reding wrote:
> > On Fri, Oct 11, 2013 at 04:14:27PM -0600, Stephen Warren wrote:
> >> On 10/07/2013 02:34 AM, Thierry Reding wrote:
> >>> From: Mikko Perttunen <mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> >>> 
> >>> The Tegra114 display controller is backwards-compatible with
> >>> previous generations of the Tegra SoC. No code changes are
> >>> required.
> >> 
> >> If the HW is backwards-compatible, then there's no need to add
> >> extra compatible values to the driver; just write the following
> >> in the DT, and it'll just work:
> >> 
> >> compatible = "nvidia,tegra114-dc", "nvidia,tegra30-dc";
> > 
> > One reason why I thought it might be useful to still include this,
> > even though unnecessary, was to match it to the host1x_drm_subdevs
> > table. We can probably remove the entry from there as well,
> > though.
> > 
> > As far as I can tell, the same holds for Tegra30, which is also 
> > backwards compatible with Tegra20 but the DTS doesn't contain the 
> > Tegra20 compatible. So to keep ABI compatibility we'll need to keep
> > the nvidia,tegra30-dc in the driver's match tables, but I could
> > still update the DTS to include the nvidia,tegra20-dc for
> > correctness.
> > 
> > Does that make sense?
> 
> Yes, fixing the Tegra30 .dtsi file sounds like a good idea.

Done.

Thierry

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

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

* Re: [PATCH v2 17/27] drm/tegra: Add Tegra114 HDMI support
       [not found]               ` <525C338D.50801-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-10-15  8:13                 ` Thierry Reding
       [not found]                   ` <20131015081318.GG7856-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-15  8:13 UTC (permalink / raw)
  To: Stephen Warren
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mikko Perttunen

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

On Mon, Oct 14, 2013 at 12:10:21PM -0600, Stephen Warren wrote:
> On 10/12/2013 05:41 AM, Thierry Reding wrote:
> > On Fri, Oct 11, 2013 at 04:19:19PM -0600, Stephen Warren wrote:
> >> On 10/07/2013 02:34 AM, Thierry Reding wrote:
> >>> From: Mikko Perttunen <mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> >>> 
> >>> Tegra114 TMDS configuration requires a new peak_current field
> >>> and the driver current override bit has changed position.
> >> 
> >>> diff --git a/drivers/gpu/drm/tegra/hdmi.c
> >>> b/drivers/gpu/drm/tegra/hdmi.c
> >> 
> >>> static const struct tmds_config tegra2_tmds_config[] = { @@
> >>> -223,6 +224,85 @@ static const struct tmds_config
> >>> tegra3_tmds_config[] = {
> >> 
> >> Not related to this patch, but those should have been named 
> >> tegra20_tmds_config[] and tegra30_tmds_config[].
> >> 
> >>> static void tegra_hdmi_setup_tmds(struct tegra_hdmi *hdmi,
> >> 
> >>> -	value = tmds->drive_current | DRIVE_CURRENT_FUSE_OVERRIDE; -
> >>> tegra_hdmi_writel(hdmi, value,
> >>> HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT); +	if
> >>> (of_device_is_compatible(np, "nvidia,tegra114-hdmi")) {
> >> 
> >> Let's not check this at run-time. Instead, host1x_drm_subdevs[]'s
> >> .data field should be used to contain either flags or a pointer
> >> to a configuration structure, either of which can be directly
> >> consulted to determine the properties of the HW in a
> >> feature-oriented/semantic way.
> >> 
> >> drivers/gpio/gpio-tegra.c's 
> >> tegra20_gpio_config/tegra30_gpio_config/tegra_gpio_of_match
> >> provide a good example of this.
> >> 
> >> This means that if Tegra124 is identical to Tegra114, yet a
> >> hypothetical Tegra999 is different, you don't have to keep
> >> adjusting these if conditions throughout the code; they can
> >> simply refer to the same feature bit forever.
> > 
> > Okay, I'll see what I can come up with. It's unfortunately not as
> > simple as the GPIO driver's parameterization, and who knows what
> > other differences will be introduced in some later versions of this
> > block.
> > 
> > What I mean is that at some point it becomes questionable whether
> > it makes sense to parameterize at all if you have to encode the
> > register offset and bit position within that register for a large
> > number of bits.
> 
> Well, I wasn't advocating that we shouldn't have an if statement at
> all. Simply that the if statement shouldn't be doing string compares
> of specific HW. Either of the following would be fine:
> 
> if (hdmi->soc_data->some_feature_flag)
>    // just represents some code; doesn't have to be a function call
>    do_something();
> else;
>   do_something_else();
> 
> or:
> 
> do_something(hdmi->soc_data->some_feature_value);

But the fact that a bit has moved from one register to another can
hardly be defined as feature. At least I couldn't come up with any
sensible name for one.

We could of course just add a version number into a per-SoC descriptor
and use that, but that's not any better than checking for the compatible
value, really.

Ideally of course the hardware wouldn't change in these ways from one
generation to the next...

That said, I've opted to go with putting the register and bit position
into a per-SoC descriptor and parameterize on that, along with a boolean
flag for the existence of the IO peak current register.

Thierry

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

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

* Re: [PATCH v2 26/27] drm/tegra: Add DSI support
       [not found]                 ` <525C3510.60802-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-10-15  8:33                   ` Thierry Reding
       [not found]                     ` <20131015083342.GH7856-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-15  8:33 UTC (permalink / raw)
  To: Stephen Warren
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

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

On Mon, Oct 14, 2013 at 12:16:48PM -0600, Stephen Warren wrote:
> On 10/14/2013 07:55 AM, Thierry Reding wrote:
> > On Fri, Oct 11, 2013 at 04:43:35PM -0600, Stephen Warren wrote:
> >> On 10/07/2013 02:34 AM, Thierry Reding wrote:
> >>> This commit adds support for both DSI outputs found on Tegra. Only very
> >>> minimal functionality is implemented, so advanced features like ganged
> >>> mode won't work.
> >>>
> >>> Due to the lack of other test hardware, some sections of the driver are
> >>> hardcoded to work with Dalmore.
> >>
> >>> diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
> >>
> >>> +static int tegra_dsi_show_regs(struct seq_file *s, void *data)
> >>> +{
> >>> +	struct drm_info_node *node = s->private;
> >>> +	struct tegra_dsi *dsi = node->info_ent->data;
> >>> +
> >>> +#define DUMP_REG(name)						\
> >>> +	seq_printf(s, "%-32s %#05x %08lx\n", #name, name,	\
> >>> +		   tegra_dsi_readl(dsi, name))
> >>> +
> >>> +	DUMP_REG(DSI_INCR_SYNCPT);
> >>
> >> Does it make sense to use an MMIO regmap instead? That way, you get all
> >> the debugfs files for free...
> > 
> > As far as I know, regmap doesn't give you the symbolic names for the
> > registers. I find that a rather useful feature because it allows to
> > easily compare the registers to the ones in our downstream kernels.
> 
> True. However, we should really be writing user-space scripts to encode
> that information. Such a script could be useful e.g. if reading the
> information directly from /dev/mem or JTAG too, and bloating the kernel
> with debug strings doesn't seem like a great idea.

I don't agree. While I see some value in having such userspace scripts,
having the symbolic names in debugfs allows anyone to look at a readable
form of the data without having to have access to those scripts. Besides
it's called *debug*fs for a purpose, isn't it? There's plenty of edited
data that's not just a plain dump of data.

Thierry

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

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

* Re: [PATCH v2 27/27] drm/tegra: Add Tegra114 gr2d support
       [not found]                     ` <525C3497.6010700-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
  2013-10-15  5:51                       ` Terje Bergström
@ 2013-10-15  8:37                       ` Thierry Reding
       [not found]                         ` <20131015083731.GI7856-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
  1 sibling, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-15  8:37 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Terje Bergström, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

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

On Mon, Oct 14, 2013 at 12:14:47PM -0600, Stephen Warren wrote:
> On 10/14/2013 08:00 AM, Thierry Reding wrote:
> > On Mon, Oct 14, 2013 at 08:58:34AM +0300, Terje Bergström wrote:
> >> On 12.10.2013 01:43, Stephen Warren wrote:
> >>> On 10/07/2013 02:34 AM, Thierry Reding wrote:
> >>>> The gr2d hardware in Tegra114 is compatible with that of
> >>>> Tegra20 and Tegra30. No functionaly changes are required.
> >>> Similarly here, if the HW is 100% backwards-compatible, there's
> >>> no need to add compatible values to the driver.
> >> 
> >> We've used this mechanism for attaching a per-hw-version data
> >> structure in match table to accomodate differences in how the
> >> hardware is power gated, reset, booted, some per-soc performance
> >> related changes etc. It's also used in staging features for new
> >> chips, such as disabling power features when they're not
> >> working/verified yet.
> >> 
> >> Upstream driver is not yet in a state where that is relevant.
> >> 
> >> With this, would we still be able to do that with match table? It
> >> sounds like we could, because we can still (even with multiple
> >> compatible properties) add separate entries in match table and I
> >> guess the compatible properties matched in order.
> > 
> > Yes, as long as the device tree files includes the most specific
> > value in the compatible this should still be possible. So we'd have
> > this:
> > 
> > gr2d@54140000 { compatible = "nvida,tegra114-gr2d",
> > "nvidia,tegra20-gr2d"; ... };
> > 
> > and the driver will match on "nvidia,tegra20-gr2d" if the more
> > specific "nvidia,tegra114-gr2d" is not there. When the driver is
> > updated to support Tegra114 specific functionality, then a more
> > specific entry can be added to the compatible table to handle it.
> 
> True, but the DT fragment above is also only accurate /if/ a driver
> that only knows about "nvidia,tegra20-gr2d" can operate 100% of the
> features in Tegra20 HW on Tegra114 HW forever.

Yes, but given that we also list "nvidia,tegra114-gr2d" in the property
it will be possible to add that to the driver when new functionality is
implemented and immediately take advantage of it on Tegra114 hardware
with an old device tree file which has both compatible values.

Thierry

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

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

* Re: [PATCH v2 27/27] drm/tegra: Add Tegra114 gr2d support
       [not found]                         ` <525CD7F3.10907-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-10-15 15:12                           ` Stephen Warren
  0 siblings, 0 replies; 87+ messages in thread
From: Stephen Warren @ 2013-10-15 15:12 UTC (permalink / raw)
  To: Terje Bergström, Thierry Reding
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On 10/14/2013 11:51 PM, Terje Bergström wrote:
> On 14.10.2013 21:14, Stephen Warren wrote:
>> On 10/14/2013 08:00 AM, Thierry Reding wrote:
>>> Yes, as long as the device tree files includes the most specific
>>> value in the compatible this should still be possible. So we'd have
>>> this:
>>>
>>> gr2d@54140000 { compatible = "nvida,tegra114-gr2d",
>>> "nvidia,tegra20-gr2d"; ... };
>>>
>>> and the driver will match on "nvidia,tegra20-gr2d" if the more
>>> specific "nvidia,tegra114-gr2d" is not there. When the driver is
>>> updated to support Tegra114 specific functionality, then a more
>>> specific entry can be added to the compatible table to handle it.
>>
>> True, but the DT fragment above is also only accurate /if/ a driver
>> that only knows about "nvidia,tegra20-gr2d" can operate 100% of the
>> features in Tegra20 HW on Tegra114 HW forever.
> 
> I don't know of any hardware incompatibility. The only difference is
> related to something not directly to 2D. We moved host1x away from the
> power domain, so in Tegra114 we're able to power gate 2D and EPP. The
> DVFS tables are also different.
> 
> I'd say say adding the compatible property "nvidia,tegra20-gr2d" for
> Tegra114's 2D is accurate and we're able to use the match table to drive
> any SW policy differences.

The compatible value shouldn't be used for SW policy differences. DT is
about HW, not SW policy. You have to decide: either the HW is 100%
backwards-compatible, or it's not. You can't decide that the HW is
compatible, but then require different compatible values.

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

* Re: [PATCH v2 17/27] drm/tegra: Add Tegra114 HDMI support
       [not found]                   ` <20131015081318.GG7856-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
@ 2013-10-15 15:17                     ` Stephen Warren
  0 siblings, 0 replies; 87+ messages in thread
From: Stephen Warren @ 2013-10-15 15:17 UTC (permalink / raw)
  To: Thierry Reding
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mikko Perttunen

On 10/15/2013 02:13 AM, Thierry Reding wrote:
> On Mon, Oct 14, 2013 at 12:10:21PM -0600, Stephen Warren wrote:
>> On 10/12/2013 05:41 AM, Thierry Reding wrote:
>>> On Fri, Oct 11, 2013 at 04:19:19PM -0600, Stephen Warren
>>> wrote:
>>>> On 10/07/2013 02:34 AM, Thierry Reding wrote:
>>>>> From: Mikko Perttunen <mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
>>>>> 
>>>>> Tegra114 TMDS configuration requires a new peak_current
>>>>> field and the driver current override bit has changed
>>>>> position.
>>>> 
>>>>> diff --git a/drivers/gpu/drm/tegra/hdmi.c 
>>>>> b/drivers/gpu/drm/tegra/hdmi.c
>>>> 
>>>>> static const struct tmds_config tegra2_tmds_config[] = {
>>>>> @@ -223,6 +224,85 @@ static const struct tmds_config 
>>>>> tegra3_tmds_config[] = {
>>>> 
>>>> Not related to this patch, but those should have been named 
>>>> tegra20_tmds_config[] and tegra30_tmds_config[].
>>>> 
>>>>> static void tegra_hdmi_setup_tmds(struct tegra_hdmi *hdmi,
>>>> 
>>>>> -	value = tmds->drive_current |
>>>>> DRIVE_CURRENT_FUSE_OVERRIDE; - tegra_hdmi_writel(hdmi,
>>>>> value, HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT); +	if 
>>>>> (of_device_is_compatible(np, "nvidia,tegra114-hdmi")) {
>>>> 
>>>> Let's not check this at run-time. Instead,
>>>> host1x_drm_subdevs[]'s .data field should be used to contain
>>>> either flags or a pointer to a configuration structure,
>>>> either of which can be directly consulted to determine the
>>>> properties of the HW in a feature-oriented/semantic way.
>>>> 
>>>> drivers/gpio/gpio-tegra.c's 
>>>> tegra20_gpio_config/tegra30_gpio_config/tegra_gpio_of_match 
>>>> provide a good example of this.
>>>> 
>>>> This means that if Tegra124 is identical to Tegra114, yet a 
>>>> hypothetical Tegra999 is different, you don't have to keep 
>>>> adjusting these if conditions throughout the code; they can 
>>>> simply refer to the same feature bit forever.
>>> 
>>> Okay, I'll see what I can come up with. It's unfortunately not
>>> as simple as the GPIO driver's parameterization, and who knows
>>> what other differences will be introduced in some later
>>> versions of this block.
>>> 
>>> What I mean is that at some point it becomes questionable
>>> whether it makes sense to parameterize at all if you have to
>>> encode the register offset and bit position within that
>>> register for a large number of bits.
>> 
>> Well, I wasn't advocating that we shouldn't have an if statement
>> at all. Simply that the if statement shouldn't be doing string
>> compares of specific HW. Either of the following would be fine:
>> 
>> if (hdmi->soc_data->some_feature_flag) // just represents some
>> code; doesn't have to be a function call do_something(); else; 
>> do_something_else();
>> 
>> or:
>> 
>> do_something(hdmi->soc_data->some_feature_value);
> 
> But the fact that a bit has moved from one register to another can 
> hardly be defined as feature. At least I couldn't come up with any 
> sensible name for one.

The feature is the name/identification of the register the field is
in. For example, foo_field_in_bar_reg. Admittedly this isn't "feature"
in the typical sense, but more a "facet of the SW-visible interface".

> We could of course just add a version number into a per-SoC
> descriptor and use that, but that's not any better than checking
> for the compatible value, really.

Even that would be better; it'd avoid a strcmp() every time the code
ran, and also allow the of_match table's data to map from compatible
value to register layout ID. It's quite possible that we have 4 SoCs:

SoC / Register location of field X / Other features, etc.
100   A                              P
200   B                              Q
300   B                              Q
400   B                              R

Where P, Q, R need different compatible values, but the location of
the register field we're talking about isn't 1:1 with the compatible
values, but rather many:1.

> Ideally of course the hardware wouldn't change in these ways from
> one generation to the next...
> 
> That said, I've opted to go with putting the register and bit
> position into a per-SoC descriptor and parameterize on that, along
> with a boolean flag for the existence of the IO peak current
> register.

Sounds good.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 27/27] drm/tegra: Add Tegra114 gr2d support
       [not found]                         ` <20131015083731.GI7856-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
@ 2013-10-15 15:19                           ` Stephen Warren
       [not found]                             ` <525D5CF6.3020600-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Stephen Warren @ 2013-10-15 15:19 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Terje Bergström, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On 10/15/2013 02:37 AM, Thierry Reding wrote:
> On Mon, Oct 14, 2013 at 12:14:47PM -0600, Stephen Warren wrote:
>> On 10/14/2013 08:00 AM, Thierry Reding wrote:
>>> On Mon, Oct 14, 2013 at 08:58:34AM +0300, Terje Bergström
>>> wrote:
>>>> On 12.10.2013 01:43, Stephen Warren wrote:
>>>>> On 10/07/2013 02:34 AM, Thierry Reding wrote:
>>>>>> The gr2d hardware in Tegra114 is compatible with that of 
>>>>>> Tegra20 and Tegra30. No functionaly changes are
>>>>>> required.
>>>>> Similarly here, if the HW is 100% backwards-compatible,
>>>>> there's no need to add compatible values to the driver.
>>>> 
>>>> We've used this mechanism for attaching a per-hw-version
>>>> data structure in match table to accomodate differences in
>>>> how the hardware is power gated, reset, booted, some per-soc
>>>> performance related changes etc. It's also used in staging
>>>> features for new chips, such as disabling power features when
>>>> they're not working/verified yet.
>>>> 
>>>> Upstream driver is not yet in a state where that is
>>>> relevant.
>>>> 
>>>> With this, would we still be able to do that with match
>>>> table? It sounds like we could, because we can still (even
>>>> with multiple compatible properties) add separate entries in
>>>> match table and I guess the compatible properties matched in
>>>> order.
>>> 
>>> Yes, as long as the device tree files includes the most
>>> specific value in the compatible this should still be possible.
>>> So we'd have this:
>>> 
>>> gr2d@54140000 { compatible = "nvida,tegra114-gr2d", 
>>> "nvidia,tegra20-gr2d"; ... };
>>> 
>>> and the driver will match on "nvidia,tegra20-gr2d" if the more 
>>> specific "nvidia,tegra114-gr2d" is not there. When the driver
>>> is updated to support Tegra114 specific functionality, then a
>>> more specific entry can be added to the compatible table to
>>> handle it.
>> 
>> True, but the DT fragment above is also only accurate /if/ a
>> driver that only knows about "nvidia,tegra20-gr2d" can operate
>> 100% of the features in Tegra20 HW on Tegra114 HW forever.
> 
> Yes, but given that we also list "nvidia,tegra114-gr2d" in the
> property it will be possible to add that to the driver when new
> functionality is implemented and immediately take advantage of it
> on Tegra114 hardware with an old device tree file which has both
> compatible values.

Taking advantage of new functionality isn't the issue. The issue is
whether a driver that was written purely to the spec of Tegra20 can
successfully operate on the HW. If it can't, then the HW is not
compatible with Tegra20. Terje's previous comments sounded like the HW
is not backwards-compatible, although his more recent comments make it
sound like only SW policy differences, which shouldn't be part of DT
anyway.

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

* Re: [PATCH v2 26/27] drm/tegra: Add DSI support
       [not found]                     ` <20131015083342.GH7856-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
@ 2013-10-15 17:21                       ` Stephen Warren
       [not found]                         ` <525D7983.6010001-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Stephen Warren @ 2013-10-15 17:21 UTC (permalink / raw)
  To: Thierry Reding
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On 10/15/2013 02:33 AM, Thierry Reding wrote:
> On Mon, Oct 14, 2013 at 12:16:48PM -0600, Stephen Warren wrote:
>> On 10/14/2013 07:55 AM, Thierry Reding wrote:
>>> On Fri, Oct 11, 2013 at 04:43:35PM -0600, Stephen Warren
>>> wrote:
>>>> On 10/07/2013 02:34 AM, Thierry Reding wrote:
>>>>> This commit adds support for both DSI outputs found on
>>>>> Tegra. Only very minimal functionality is implemented, so
>>>>> advanced features like ganged mode won't work.
>>>>> 
>>>>> Due to the lack of other test hardware, some sections of
>>>>> the driver are hardcoded to work with Dalmore.
>>>> 
>>>>> diff --git a/drivers/gpu/drm/tegra/dsi.c
>>>>> b/drivers/gpu/drm/tegra/dsi.c
>>>> 
>>>>> +static int tegra_dsi_show_regs(struct seq_file *s, void
>>>>> *data) +{ +	struct drm_info_node *node = s->private; +
>>>>> struct tegra_dsi *dsi = node->info_ent->data; + +#define
>>>>> DUMP_REG(name)						\ +	seq_printf(s, "%-32s %#05x
>>>>> %08lx\n", #name, name,	\ +		   tegra_dsi_readl(dsi, name)) 
>>>>> + +	DUMP_REG(DSI_INCR_SYNCPT);
>>>> 
>>>> Does it make sense to use an MMIO regmap instead? That way,
>>>> you get all the debugfs files for free...
>>> 
>>> As far as I know, regmap doesn't give you the symbolic names
>>> for the registers. I find that a rather useful feature because
>>> it allows to easily compare the registers to the ones in our
>>> downstream kernels.
>> 
>> True. However, we should really be writing user-space scripts to
>> encode that information. Such a script could be useful e.g. if
>> reading the information directly from /dev/mem or JTAG too, and
>> bloating the kernel with debug strings doesn't seem like a great
>> idea.
> 
> I don't agree. While I see some value in having such userspace
> scripts, having the symbolic names in debugfs allows anyone to look
> at a readable form of the data without having to have access to
> those scripts. Besides it's called *debug*fs for a purpose, isn't
> it? There's plenty of edited data that's not just a plain dump of
> data.

Perhaps you should work to enhance regmap's debugfs files to support
optionally naming registers?

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

* Re: [PATCH v2 26/27] drm/tegra: Add DSI support
       [not found]                         ` <525D7983.6010001-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-10-16  8:40                           ` Thierry Reding
       [not found]                             ` <20131016084031.GB21963-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-16  8:40 UTC (permalink / raw)
  To: Stephen Warren
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

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

On Tue, Oct 15, 2013 at 11:21:07AM -0600, Stephen Warren wrote:
> On 10/15/2013 02:33 AM, Thierry Reding wrote:
> > On Mon, Oct 14, 2013 at 12:16:48PM -0600, Stephen Warren wrote:
> >> On 10/14/2013 07:55 AM, Thierry Reding wrote:
> >>> On Fri, Oct 11, 2013 at 04:43:35PM -0600, Stephen Warren
> >>> wrote:
> >>>> On 10/07/2013 02:34 AM, Thierry Reding wrote:
> >>>>> This commit adds support for both DSI outputs found on
> >>>>> Tegra. Only very minimal functionality is implemented, so
> >>>>> advanced features like ganged mode won't work.
> >>>>> 
> >>>>> Due to the lack of other test hardware, some sections of
> >>>>> the driver are hardcoded to work with Dalmore.
> >>>> 
> >>>>> diff --git a/drivers/gpu/drm/tegra/dsi.c
> >>>>> b/drivers/gpu/drm/tegra/dsi.c
> >>>> 
> >>>>> +static int tegra_dsi_show_regs(struct seq_file *s, void
> >>>>> *data) +{ +	struct drm_info_node *node = s->private; +
> >>>>> struct tegra_dsi *dsi = node->info_ent->data; + +#define
> >>>>> DUMP_REG(name)						\ +	seq_printf(s, "%-32s %#05x
> >>>>> %08lx\n", #name, name,	\ +		   tegra_dsi_readl(dsi, name)) 
> >>>>> + +	DUMP_REG(DSI_INCR_SYNCPT);
> >>>> 
> >>>> Does it make sense to use an MMIO regmap instead? That way,
> >>>> you get all the debugfs files for free...
> >>> 
> >>> As far as I know, regmap doesn't give you the symbolic names
> >>> for the registers. I find that a rather useful feature because
> >>> it allows to easily compare the registers to the ones in our
> >>> downstream kernels.
> >> 
> >> True. However, we should really be writing user-space scripts to
> >> encode that information. Such a script could be useful e.g. if
> >> reading the information directly from /dev/mem or JTAG too, and
> >> bloating the kernel with debug strings doesn't seem like a great
> >> idea.
> > 
> > I don't agree. While I see some value in having such userspace
> > scripts, having the symbolic names in debugfs allows anyone to look
> > at a readable form of the data without having to have access to
> > those scripts. Besides it's called *debug*fs for a purpose, isn't
> > it? There's plenty of edited data that's not just a plain dump of
> > data.
> 
> Perhaps you should work to enhance regmap's debugfs files to support
> optionally naming registers?

Just to follow up with what we've discussed on IRC: I'll take a stab at
refactoring the debugfs file output into something more generic that can
possibly be leveraged by regmap as well. That should provide a somewhat
more lightweight alternative to regmap for implementations that don't
need regmap for anything else while at the same time providing something
so not every driver has to come up with something custom.

Does that sum it up correctly?

Thierry

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

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

* Re: [PATCH v2 27/27] drm/tegra: Add Tegra114 gr2d support
       [not found]                             ` <525D5CF6.3020600-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-10-16  8:48                               ` Thierry Reding
       [not found]                                 ` <20131016084804.GC21963-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-10-16  8:48 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Terje Bergström, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

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

On Tue, Oct 15, 2013 at 09:19:18AM -0600, Stephen Warren wrote:
> On 10/15/2013 02:37 AM, Thierry Reding wrote:
> > On Mon, Oct 14, 2013 at 12:14:47PM -0600, Stephen Warren wrote:
> >> On 10/14/2013 08:00 AM, Thierry Reding wrote:
> >>> On Mon, Oct 14, 2013 at 08:58:34AM +0300, Terje Bergström
> >>> wrote:
> >>>> On 12.10.2013 01:43, Stephen Warren wrote:
> >>>>> On 10/07/2013 02:34 AM, Thierry Reding wrote:
> >>>>>> The gr2d hardware in Tegra114 is compatible with that of 
> >>>>>> Tegra20 and Tegra30. No functionaly changes are
> >>>>>> required.
> >>>>> Similarly here, if the HW is 100% backwards-compatible,
> >>>>> there's no need to add compatible values to the driver.
> >>>> 
> >>>> We've used this mechanism for attaching a per-hw-version
> >>>> data structure in match table to accomodate differences in
> >>>> how the hardware is power gated, reset, booted, some per-soc
> >>>> performance related changes etc. It's also used in staging
> >>>> features for new chips, such as disabling power features when
> >>>> they're not working/verified yet.
> >>>> 
> >>>> Upstream driver is not yet in a state where that is
> >>>> relevant.
> >>>> 
> >>>> With this, would we still be able to do that with match
> >>>> table? It sounds like we could, because we can still (even
> >>>> with multiple compatible properties) add separate entries in
> >>>> match table and I guess the compatible properties matched in
> >>>> order.
> >>> 
> >>> Yes, as long as the device tree files includes the most
> >>> specific value in the compatible this should still be possible.
> >>> So we'd have this:
> >>> 
> >>> gr2d@54140000 { compatible = "nvida,tegra114-gr2d", 
> >>> "nvidia,tegra20-gr2d"; ... };
> >>> 
> >>> and the driver will match on "nvidia,tegra20-gr2d" if the more 
> >>> specific "nvidia,tegra114-gr2d" is not there. When the driver
> >>> is updated to support Tegra114 specific functionality, then a
> >>> more specific entry can be added to the compatible table to
> >>> handle it.
> >> 
> >> True, but the DT fragment above is also only accurate /if/ a
> >> driver that only knows about "nvidia,tegra20-gr2d" can operate
> >> 100% of the features in Tegra20 HW on Tegra114 HW forever.
> > 
> > Yes, but given that we also list "nvidia,tegra114-gr2d" in the
> > property it will be possible to add that to the driver when new
> > functionality is implemented and immediately take advantage of it
> > on Tegra114 hardware with an old device tree file which has both
> > compatible values.
> 
> Taking advantage of new functionality isn't the issue. The issue is
> whether a driver that was written purely to the spec of Tegra20 can
> successfully operate on the HW. If it can't, then the HW is not
> compatible with Tegra20. Terje's previous comments sounded like the HW
> is not backwards-compatible, although his more recent comments make it
> sound like only SW policy differences, which shouldn't be part of DT
> anyway.

Well, as good as I can tell it is backwards-compatible. I've been
testing the code included in this series with the same simple test
program that clears a rectangle on Tegra20, Tegra30 and Tegra114.

Furthermore our internal register specification files are identical,
with the exception of some whitespace changes for all three generations.
I think that qualifies as backwards-compatible?

Thierry

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

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

* Re: [PATCH v2 27/27] drm/tegra: Add Tegra114 gr2d support
       [not found]                                 ` <20131016084804.GC21963-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
@ 2013-10-16 12:05                                   ` Terje Bergström
  2013-10-16 17:00                                   ` Stephen Warren
  1 sibling, 0 replies; 87+ messages in thread
From: Terje Bergström @ 2013-10-16 12:05 UTC (permalink / raw)
  To: Thierry Reding, Stephen Warren
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On 16.10.2013 11:48, Thierry Reding wrote:
> On Tue, Oct 15, 2013 at 09:19:18AM -0600, Stephen Warren wrote:
>> Taking advantage of new functionality isn't the issue. The issue is
>> whether a driver that was written purely to the spec of Tegra20 can
>> successfully operate on the HW. If it can't, then the HW is not
>> compatible with Tegra20. Terje's previous comments sounded like the HW
>> is not backwards-compatible, although his more recent comments make it
>> sound like only SW policy differences, which shouldn't be part of DT
>> anyway.
> 
> Well, as good as I can tell it is backwards-compatible. I've been
> testing the code included in this series with the same simple test
> program that clears a rectangle on Tegra20, Tegra30 and Tegra114.
> 
> Furthermore our internal register specification files are identical,
> with the exception of some whitespace changes for all three generations.
> I think that qualifies as backwards-compatible?

A driver written for Tegra20 2D works with Tegra114 2D. Not necessarily
vice versa, because Tegra114's driver can ask for higher clocks, or it
might want to power gate 2D.

I mentioned earlier bringup activities. Perhaps Stephen took that in a
way I didn't intend.

Terje

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

* Re: [PATCH v2 26/27] drm/tegra: Add DSI support
       [not found]                             ` <20131016084031.GB21963-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
@ 2013-10-16 16:58                               ` Stephen Warren
  0 siblings, 0 replies; 87+ messages in thread
From: Stephen Warren @ 2013-10-16 16:58 UTC (permalink / raw)
  To: Thierry Reding
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On 10/16/2013 02:40 AM, Thierry Reding wrote:
...
> Just to follow up with what we've discussed on IRC: I'll take a
> stab at refactoring the debugfs file output into something more
> generic that can possibly be leveraged by regmap as well. That
> should provide a somewhat more lightweight alternative to regmap
> for implementations that don't need regmap for anything else while
> at the same time providing something so not every driver has to
> come up with something custom.
> 
> Does that sum it up correctly?

Yes.

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

* Re: [PATCH v2 27/27] drm/tegra: Add Tegra114 gr2d support
       [not found]                                 ` <20131016084804.GC21963-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
  2013-10-16 12:05                                   ` Terje Bergström
@ 2013-10-16 17:00                                   ` Stephen Warren
  1 sibling, 0 replies; 87+ messages in thread
From: Stephen Warren @ 2013-10-16 17:00 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Terje Bergström, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On 10/16/2013 02:48 AM, Thierry Reding wrote:
> On Tue, Oct 15, 2013 at 09:19:18AM -0600, Stephen Warren wrote:
>> On 10/15/2013 02:37 AM, Thierry Reding wrote:
>>> On Mon, Oct 14, 2013 at 12:14:47PM -0600, Stephen Warren
>>> wrote:
>>>> On 10/14/2013 08:00 AM, Thierry Reding wrote:
>>>>> On Mon, Oct 14, 2013 at 08:58:34AM +0300, Terje Bergström 
>>>>> wrote:
>>>>>> On 12.10.2013 01:43, Stephen Warren wrote:
>>>>>>> On 10/07/2013 02:34 AM, Thierry Reding wrote:
>>>>>>>> The gr2d hardware in Tegra114 is compatible with that
>>>>>>>> of Tegra20 and Tegra30. No functionaly changes are 
>>>>>>>> required.
>>>>>>> Similarly here, if the HW is 100%
>>>>>>> backwards-compatible, there's no need to add compatible
>>>>>>> values to the driver.
>>>>>> 
>>>>>> We've used this mechanism for attaching a per-hw-version 
>>>>>> data structure in match table to accomodate differences
>>>>>> in how the hardware is power gated, reset, booted, some
>>>>>> per-soc performance related changes etc. It's also used
>>>>>> in staging features for new chips, such as disabling
>>>>>> power features when they're not working/verified yet.
>>>>>> 
>>>>>> Upstream driver is not yet in a state where that is 
>>>>>> relevant.
>>>>>> 
>>>>>> With this, would we still be able to do that with match 
>>>>>> table? It sounds like we could, because we can still
>>>>>> (even with multiple compatible properties) add separate
>>>>>> entries in match table and I guess the compatible
>>>>>> properties matched in order.
>>>>> 
>>>>> Yes, as long as the device tree files includes the most 
>>>>> specific value in the compatible this should still be
>>>>> possible. So we'd have this:
>>>>> 
>>>>> gr2d@54140000 { compatible = "nvida,tegra114-gr2d", 
>>>>> "nvidia,tegra20-gr2d"; ... };
>>>>> 
>>>>> and the driver will match on "nvidia,tegra20-gr2d" if the
>>>>> more specific "nvidia,tegra114-gr2d" is not there. When the
>>>>> driver is updated to support Tegra114 specific
>>>>> functionality, then a more specific entry can be added to
>>>>> the compatible table to handle it.
>>>> 
>>>> True, but the DT fragment above is also only accurate /if/ a 
>>>> driver that only knows about "nvidia,tegra20-gr2d" can
>>>> operate 100% of the features in Tegra20 HW on Tegra114 HW
>>>> forever.
>>> 
>>> Yes, but given that we also list "nvidia,tegra114-gr2d" in the 
>>> property it will be possible to add that to the driver when
>>> new functionality is implemented and immediately take advantage
>>> of it on Tegra114 hardware with an old device tree file which
>>> has both compatible values.
>> 
>> Taking advantage of new functionality isn't the issue. The issue
>> is whether a driver that was written purely to the spec of
>> Tegra20 can successfully operate on the HW. If it can't, then the
>> HW is not compatible with Tegra20. Terje's previous comments
>> sounded like the HW is not backwards-compatible, although his
>> more recent comments make it sound like only SW policy
>> differences, which shouldn't be part of DT anyway.
> 
> Well, as good as I can tell it is backwards-compatible. I've been 
> testing the code included in this series with the same simple test 
> program that clears a rectangle on Tegra20, Tegra30 and Tegra114.

All that means is that the subset of features we use so far is compatible.

> Furthermore our internal register specification files are
> identical, with the exception of some whitespace changes for all
> three generations. I think that qualifies as backwards-compatible?

On the other hand, that sounds like an almost perfect definition of
backwards-compatible. Can you also validate that any module
clock/power/reset inputs are identical? If so, the case is closed:-)

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

* Re: [PATCH v2 13/27] drm/tegra: Move subdevice infrastructure to host1x
       [not found]     ` <1381134884-5816-14-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2013-10-08  6:25       ` Terje Bergström
@ 2013-11-04 10:20       ` Daniel Vetter
       [not found]         ` <20131104102054.GD4167-dv86pmgwkMBes7Z6vYuT8azUEOm+Xw19@public.gmane.org>
  1 sibling, 1 reply; 87+ messages in thread
From: Daniel Vetter @ 2013-11-04 10:20 UTC (permalink / raw)
  To: Thierry Reding
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Dave Airlie

On Mon, Oct 07, 2013 at 10:34:30AM +0200, Thierry Reding wrote:
> +static struct drm_bus drm_host1x_bus = {
> +	.bus_type = DRIVER_BUS_HOST1X,
> +	.set_busid = drm_host1x_set_busid,
> +};

Imo this needs to die asap, i.e. before it lands in drm-next. I've just
spent a bit of time trying to rid ourselves of this midlayer
brain-damange, and now new stuff crops up. See

http://cgit.freedesktop.org/~danvet/drm/log/?h=drm-init-cleanup

drm_bus is a terribly midlayer madness disaster and needs to just burn
down. So what exactly is the reason here to not go with the drm_platform.c
stuff until I've gotten around to completely rip it all out?

Adding Dave.

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

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

* Re: [PATCH v2 13/27] drm/tegra: Move subdevice infrastructure to host1x
       [not found]         ` <20131104102054.GD4167-dv86pmgwkMBes7Z6vYuT8azUEOm+Xw19@public.gmane.org>
@ 2013-11-04 11:06           ` Thierry Reding
       [not found]             ` <20131104110655.GN27445-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
  0 siblings, 1 reply; 87+ messages in thread
From: Thierry Reding @ 2013-11-04 11:06 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Dave Airlie

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

On Mon, Nov 04, 2013 at 11:20:55AM +0100, Daniel Vetter wrote:
> On Mon, Oct 07, 2013 at 10:34:30AM +0200, Thierry Reding wrote:
> > +static struct drm_bus drm_host1x_bus = {
> > +	.bus_type = DRIVER_BUS_HOST1X,
> > +	.set_busid = drm_host1x_set_busid,
> > +};
> 
> Imo this needs to die asap, i.e. before it lands in drm-next. I've just
> spent a bit of time trying to rid ourselves of this midlayer
> brain-damange, and now new stuff crops up. See
> 
> http://cgit.freedesktop.org/~danvet/drm/log/?h=drm-init-cleanup
> 
> drm_bus is a terribly midlayer madness disaster and needs to just burn
> down. So what exactly is the reason here to not go with the drm_platform.c
> stuff until I've gotten around to completely rip it all out?

Dave asked me whether it was possible to move the Tegra DRM driver back
into drivers/gpu/drm (from drivers/gpu/host1x/drm) and introducing this
new bus was the only solution I saw (besides perhaps using cross-
subsystem global variables) to do that.

Now, I'm not a big fan at all of the whole drm_bus shebang myself, so
whatever help you need in getting rid of it, please let me know. The
drm_bus implementation that this adds is about 34 lines, so it shouldn't
be difficult to get rid of. If you throw out drm_driver.bus completely,
then it should be a matter of just deleting that code and the rest
should be able to continue working as is. The only reason I added it is
because the kernel crashes if its not there, depending on what userspace
is run.

So I find myself in the middle of controversy again... I seem to have a
knack for it.

Thierry

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

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

* Re: [PATCH v2 13/27] drm/tegra: Move subdevice infrastructure to host1x
       [not found]             ` <20131104110655.GN27445-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
@ 2013-11-04 16:08               ` Daniel Vetter
  0 siblings, 0 replies; 87+ messages in thread
From: Daniel Vetter @ 2013-11-04 16:08 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Daniel Vetter, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Dave Airlie

On Mon, Nov 04, 2013 at 12:06:57PM +0100, Thierry Reding wrote:
> On Mon, Nov 04, 2013 at 11:20:55AM +0100, Daniel Vetter wrote:
> > On Mon, Oct 07, 2013 at 10:34:30AM +0200, Thierry Reding wrote:
> > > +static struct drm_bus drm_host1x_bus = {
> > > +	.bus_type = DRIVER_BUS_HOST1X,
> > > +	.set_busid = drm_host1x_set_busid,
> > > +};
> > 
> > Imo this needs to die asap, i.e. before it lands in drm-next. I've just
> > spent a bit of time trying to rid ourselves of this midlayer
> > brain-damange, and now new stuff crops up. See
> > 
> > http://cgit.freedesktop.org/~danvet/drm/log/?h=drm-init-cleanup
> > 
> > drm_bus is a terribly midlayer madness disaster and needs to just burn
> > down. So what exactly is the reason here to not go with the drm_platform.c
> > stuff until I've gotten around to completely rip it all out?
> 
> Dave asked me whether it was possible to move the Tegra DRM driver back
> into drivers/gpu/drm (from drivers/gpu/host1x/drm) and introducing this
> new bus was the only solution I saw (besides perhaps using cross-
> subsystem global variables) to do that.
> 
> Now, I'm not a big fan at all of the whole drm_bus shebang myself, so
> whatever help you need in getting rid of it, please let me know. The
> drm_bus implementation that this adds is about 34 lines, so it shouldn't
> be difficult to get rid of. If you throw out drm_driver.bus completely,
> then it should be a matter of just deleting that code and the rest
> should be able to continue working as is. The only reason I added it is
> because the kernel crashes if its not there, depending on what userspace
> is run.

Oh, so you actually need the bus->set_busid callback? Since that's one of
those old ugly dragons from the ums days and really shouldn't be used by
anything modern. E.g. rendernodes completely disallow it, and afaik the
x86 systems I have here also don't use it. So you've copy&pasted a piece
of lore that you _never_ should have used, and since I'm too late we now
have userspace that depends upon it :(

Aside: The reason we have drm_platform.c is to make the shadow-attach
possible that ums drm drivers needed. Luckily we've never merged an ARM
shadow-attaching ums drm driver, but unfortunately everyone just kept on
using the old crap without too much though.

If you just need to prevent the Oops (and please hunt down that piece of
userspace calling the setversion ioctl and figure out where it is, link to
sources highly appreciated) you can peek at drm_usb.c for the true noop
implementation. Would be great if you can figure this out before -rc1 - I
want to dump my current pile of patches onto Dave by then for 3.14.

Wrt the drm_put_dev in drm_host1x_exit I don't care one bit what you do in
your driver, as long as you call drm_put_dev directly ;-) It looks like
I'm lucky and can just drop the tegra patch as soon as your tree has
landed.

> So I find myself in the middle of controversy again... I seem to have a
> knack for it.

Looks like it's just a small one here ... you need to try harder.

Btw the longer-term plan is that you can embedd the struct drm_device into
whatever driver private struct is suitable and completely control it's
lifetime. That would allow us to ditch the drm_dev->usbdevice and
->platform_device pointers (killing dev->agp and dev->pdev is much harder
due to the big pile of legacy drives, but in principal not impossible for
someone with too much time).
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

end of thread, other threads:[~2013-11-04 16:08 UTC | newest]

Thread overview: 87+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-10-07  8:34 [PATCH v2 00/27] drm/tegra: Repatriation and DSI support Thierry Reding
     [not found] ` <1381134884-5816-1-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-10-07  8:34   ` [PATCH v2 01/27] drm/tegra: Remove unused fields Thierry Reding
2013-10-07  8:34   ` [PATCH v2 02/27] drm/tegra: Cleanup tegra_dc structure Thierry Reding
2013-10-07  8:34   ` [PATCH v2 03/27] drm/tegra: Rename host1x_drm structure to tegra_drm Thierry Reding
2013-10-07  8:34   ` [PATCH v2 04/27] drm/tegra: Rename host1x_drm_file to tegra_drm_file Thierry Reding
2013-10-07  8:34   ` [PATCH v2 05/27] drm/tegra: Rename host1x_drm_context to tegra_drm_context Thierry Reding
2013-10-07  8:34   ` [PATCH v2 06/27] gpu: host1x: Cleanup includes Thierry Reding
     [not found]     ` <1381134884-5816-7-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-10-08  5:59       ` Terje Bergström
     [not found]         ` <52539F5E.1060005-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-10-08  9:45           ` Thierry Reding
2013-10-07  8:34   ` [PATCH v2 07/27] gpu: host1x: Do not discard .remove() Thierry Reding
2013-10-07  8:34   ` [PATCH v2 08/27] drm/tegra: gr2d: Miscellaneous cleanups Thierry Reding
     [not found]     ` <1381134884-5816-9-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-10-07 11:34       ` Erik Faye-Lund
     [not found]         ` <CABPQNSbkS40_jyGz14s08+x3e+-pxnfy90V7pzAOfiqUF2ma2g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2013-10-07 12:14           ` Thierry Reding
     [not found]             ` <20131007121452.GA8324-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
2013-10-07 12:52               ` Terje Bergström
     [not found]                 ` <5252AE8C.9090609-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-10-07 13:05                   ` Erik Faye-Lund
     [not found]                     ` <CABPQNSa59hBU__yjQMZsdEghpSwH1ayJYiD6HrBrhABicgzxuA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2013-10-08  5:36                       ` Terje Bergström
2013-10-07 13:13                   ` Thierry Reding
2013-10-07 12:53               ` Erik Faye-Lund
     [not found]                 ` <CABPQNSb52HmS-2T=MUXteMFc1tndHdvtUnZqsVsPKjP1Dy6Esw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2013-10-07 13:02                   ` Erik Faye-Lund
     [not found]                     ` <CABPQNSZGyuS3wAvJ8fFj=LMXxFJz9x_sKqEWW7QbiqC1gneLKw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2013-10-08  5:48                       ` Terje Bergström
     [not found]                         ` <52539CC0.3020901-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-10-08 11:11                           ` Erik Faye-Lund
2013-10-07  8:34   ` [PATCH v2 09/27] drm/tegra: gem: " Thierry Reding
2013-10-07  8:34   ` [PATCH v2 10/27] gpu: host1x: Make host1x header file public Thierry Reding
2013-10-07  8:34   ` [PATCH v2 11/27] drm/tegra: Introduce tegra_drm_client structure Thierry Reding
2013-10-07  8:34   ` [PATCH v2 12/27] gpu: host1x: Expose syncpt and channel functionality Thierry Reding
2013-10-07  8:34   ` [PATCH v2 13/27] drm/tegra: Move subdevice infrastructure to host1x Thierry Reding
     [not found]     ` <1381134884-5816-14-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-10-08  6:25       ` Terje Bergström
     [not found]         ` <5253A563.1060409-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-10-08  9:52           ` Thierry Reding
2013-11-04 10:20       ` Daniel Vetter
     [not found]         ` <20131104102054.GD4167-dv86pmgwkMBes7Z6vYuT8azUEOm+Xw19@public.gmane.org>
2013-11-04 11:06           ` Thierry Reding
     [not found]             ` <20131104110655.GN27445-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
2013-11-04 16:08               ` Daniel Vetter
2013-10-07  8:34   ` [PATCH v2 14/27] drm/tegra: Move driver to DRM tree Thierry Reding
     [not found]     ` <1381134884-5816-15-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-10-11 22:11       ` Stephen Warren
     [not found]         ` <52587797.7000402-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-10-12 11:16           ` Thierry Reding
2013-10-07  8:34   ` [PATCH v2 15/27] gpu: host1x: Add support for Tegra114 Thierry Reding
     [not found]     ` <1381134884-5816-16-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-10-11 22:13       ` Stephen Warren
     [not found]         ` <525877F3.9070004-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-10-12 11:24           ` Thierry Reding
2013-10-14  5:30             ` Terje Bergström
     [not found]               ` <525B8174.4000907-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-10-15  8:05                 ` Thierry Reding
2013-10-14 18:07             ` Stephen Warren
     [not found]               ` <525C32E5.2020406-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-10-15  8:03                 ` Thierry Reding
2013-10-07  8:34   ` [PATCH v2 16/27] drm/tegra: Add Tegra114 display controller support Thierry Reding
     [not found]     ` <1381134884-5816-17-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-10-11 22:14       ` Stephen Warren
     [not found]         ` <52587843.9070806-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-10-12 11:32           ` Thierry Reding
2013-10-14 18:05             ` Stephen Warren
     [not found]               ` <525C325E.2090700-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-10-15  8:06                 ` Thierry Reding
2013-10-07  8:34   ` [PATCH v2 17/27] drm/tegra: Add Tegra114 HDMI support Thierry Reding
     [not found]     ` <1381134884-5816-18-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-10-11 22:19       ` Stephen Warren
     [not found]         ` <52587967.6050806-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-10-11 22:22           ` Stephen Warren
     [not found]             ` <52587A16.7050200-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-10-12 11:35               ` Thierry Reding
2013-10-12 11:41           ` Thierry Reding
2013-10-14 18:10             ` Stephen Warren
     [not found]               ` <525C338D.50801-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-10-15  8:13                 ` Thierry Reding
     [not found]                   ` <20131015081318.GG7856-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
2013-10-15 15:17                     ` Stephen Warren
2013-10-07  8:34   ` [PATCH v2 18/27] drm/tegra: hdmi: Detect DVI-only displays Thierry Reding
2013-10-07  8:34   ` [PATCH v2 19/27] host1x: hdmi: Enable VDD earlier for hotplug/DDC Thierry Reding
2013-10-07  8:34   ` [PATCH v2 20/27] drm/tegra: hdmi: Rename tegra{2,3} to tegra{20,30} Thierry Reding
2013-10-07  8:34   ` [PATCH v2 21/27] drm: Add panel support Thierry Reding
2013-10-07  8:34   ` [PATCH v2 22/27] drm/panel: Add simple " Thierry Reding
     [not found]     ` <1381134884-5816-23-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-10-11 22:33       ` Stephen Warren
     [not found]         ` <52587CBD.8010304-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-10-14 14:10           ` Thierry Reding
2013-10-07  8:34   ` [PATCH v2 23/27] drm/tegra: Implement " Thierry Reding
2013-10-07  8:34   ` [PATCH v2 24/27] drm/tegra: Start connectors with correct DPMS mode Thierry Reding
2013-10-07  8:34   ` [PATCH v2 25/27] gpu: host1x: Add MIPI pad calibration support Thierry Reding
     [not found]     ` <1381134884-5816-26-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-10-11 22:37       ` Stephen Warren
     [not found]         ` <52587DAF.9080003-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-10-14 13:44           ` Thierry Reding
2013-10-07  8:34   ` [PATCH v2 26/27] drm/tegra: Add DSI support Thierry Reding
     [not found]     ` <1381134884-5816-27-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-10-11 22:43       ` Stephen Warren
     [not found]         ` <52587F17.7060104-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-10-14 13:55           ` Thierry Reding
     [not found]             ` <20131014135548.GB16302-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
2013-10-14 18:16               ` Stephen Warren
     [not found]                 ` <525C3510.60802-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-10-15  8:33                   ` Thierry Reding
     [not found]                     ` <20131015083342.GH7856-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
2013-10-15 17:21                       ` Stephen Warren
     [not found]                         ` <525D7983.6010001-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-10-16  8:40                           ` Thierry Reding
     [not found]                             ` <20131016084031.GB21963-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
2013-10-16 16:58                               ` Stephen Warren
2013-10-07  8:34   ` [PATCH v2 27/27] drm/tegra: Add Tegra114 gr2d support Thierry Reding
     [not found]     ` <1381134884-5816-28-git-send-email-treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-10-11 22:43       ` Stephen Warren
     [not found]         ` <52587F2D.9070007-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-10-14  5:58           ` Terje Bergström
     [not found]             ` <525B880A.7090802-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-10-14 14:00               ` Thierry Reding
     [not found]                 ` <20131014140010.GC16302-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
2013-10-14 18:14                   ` Stephen Warren
     [not found]                     ` <525C3497.6010700-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-10-15  5:51                       ` Terje Bergström
     [not found]                         ` <525CD7F3.10907-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-10-15 15:12                           ` Stephen Warren
2013-10-15  8:37                       ` Thierry Reding
     [not found]                         ` <20131015083731.GI7856-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
2013-10-15 15:19                           ` Stephen Warren
     [not found]                             ` <525D5CF6.3020600-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-10-16  8:48                               ` Thierry Reding
     [not found]                                 ` <20131016084804.GC21963-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
2013-10-16 12:05                                   ` Terje Bergström
2013-10-16 17:00                                   ` Stephen Warren
2013-10-14 18:13               ` Stephen Warren

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.