summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/host1x/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/host1x/drm')
-rw-r--r--drivers/gpu/host1x/drm/bus.c76
-rw-r--r--drivers/gpu/host1x/drm/dc.c30
-rw-r--r--drivers/gpu/host1x/drm/drm.c347
-rw-r--r--drivers/gpu/host1x/drm/drm.h31
-rw-r--r--drivers/gpu/host1x/drm/gr2d.c60
-rw-r--r--drivers/gpu/host1x/drm/hdmi.c28
6 files changed, 271 insertions, 301 deletions
diff --git a/drivers/gpu/host1x/drm/bus.c b/drivers/gpu/host1x/drm/bus.c
new file mode 100644
index 000000000000..565f8f7b9a47
--- /dev/null
+++ b/drivers/gpu/host1x/drm/bus.c
@@ -0,0 +1,76 @@
+/*
+ * 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 = drm_dev_alloc(driver, &device->dev);
+ if (!drm)
+ return -ENOMEM;
+
+ ret = drm_dev_register(drm, 0);
+ if (ret)
+ goto err_free;
+
+ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name,
+ driver->major, driver->minor, driver->patchlevel,
+ driver->date, drm->primary->index);
+
+ return 0;
+
+err_free:
+ drm_dev_free(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 5106df08f046..588d4ba0d8cf 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,7 +1105,6 @@ 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 resource *regs;
struct tegra_dc *dc;
int err;
@@ -1141,9 +1138,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 +1148,7 @@ static int tegra_dc_probe(struct platform_device *pdev)
return err;
}
- err = host1x_register_client(tegra, &dc->client.base);
+ err = host1x_client_register(&dc->client);
if (err < 0) {
dev_err(&pdev->dev, "failed to register host1x client: %d\n",
err);
@@ -1165,11 +1162,10 @@ 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 tegra_dc *dc = platform_get_drvdata(pdev);
int err;
- err = host1x_unregister_client(tegra, &dc->client.base);
+ err = host1x_client_unregister(&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 1abcdbc7f4cd..c2db409bbd63 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@avionic-design.de>");
+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 8c26c6b1f5e1..25522e23c7b8 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 dfb822428ca0..4e407e30da1c 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"
@@ -35,19 +34,45 @@ 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);
+ struct gr2d *gr2d = to_gr2d(drm);
+
+ gr2d->channel = host1x_channel_request(client->dev);
+ if (!gr2d->channel)
+ return -ENOMEM;
+
+ client->syncpts[0] = host1x_syncpt_request(client->dev, false);
+ if (!client->syncpts[0]) {
+ host1x_channel_free(gr2d->channel);
+ return -ENOMEM;
+ }
+
+ return tegra_drm_register_client(tegra, drm);
}
-static int gr2d_client_exit(struct host1x_client *client)
+static int gr2d_exit(struct host1x_client *client)
{
+ struct tegra_drm_client *drm = host1x_to_drm_client(client);
+ struct tegra_drm *tegra = dev_get_drvdata(client->parent);
+ struct gr2d *gr2d = to_gr2d(drm);
+ int err;
+
+ err = tegra_drm_unregister_client(tegra, drm);
+ if (err < 0)
+ return err;
+
+ host1x_syncpt_free(client->syncpts[0]);
+ host1x_channel_free(gr2d->channel);
+
return 0;
}
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,
@@ -240,7 +265,6 @@ static const u32 gr2d_addr_regs[] = {
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 host1x_syncpt **syncpts;
struct gr2d *gr2d;
@@ -267,25 +291,17 @@ static int gr2d_probe(struct platform_device *pdev)
return err;
}
- gr2d->channel = host1x_channel_request(dev);
- if (!gr2d->channel)
- return -ENOMEM;
-
- *syncpts = host1x_syncpt_request(dev, false);
- if (!(*syncpts)) {
- host1x_channel_free(gr2d->channel);
- return -ENOMEM;
- }
-
INIT_LIST_HEAD(&gr2d->client.base.list);
gr2d->client.base.ops = &gr2d_client_ops;
gr2d->client.base.dev = dev;
gr2d->client.base.class = HOST1X_CLASS_GR2D;
gr2d->client.base.syncpts = syncpts;
gr2d->client.base.num_syncpts = 1;
+
+ INIT_LIST_HEAD(&gr2d->client.list);
gr2d->client.ops = &gr2d_ops;
- err = host1x_register_client(tegra, &gr2d->client.base);
+ err = host1x_client_register(&gr2d->client.base);
if (err < 0) {
dev_err(dev, "failed to register host1x client: %d\n", err);
return err;
@@ -302,22 +318,16 @@ 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 gr2d *gr2d = platform_get_drvdata(pdev);
- unsigned int i;
int err;
- err = host1x_unregister_client(tegra, &gr2d->client.base);
+ err = host1x_client_unregister(&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.base.num_syncpts; i++)
- host1x_syncpt_free(gr2d->client.base.syncpts[i]);
-
- host1x_channel_free(gr2d->channel);
clk_disable_unprepare(gr2d->clk);
return 0;
diff --git a/drivers/gpu/host1x/drm/hdmi.c b/drivers/gpu/host1x/drm/hdmi.c
index a2370045993c..f5663d15670b 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,7 +1174,6 @@ 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 tegra_hdmi *hdmi;
struct resource *regs;
int err;
@@ -1247,11 +1244,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_client_register(&hdmi->client);
if (err < 0) {
dev_err(&pdev->dev, "failed to register host1x client: %d\n",
err);
@@ -1265,11 +1262,10 @@ 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 tegra_hdmi *hdmi = platform_get_drvdata(pdev);
int err;
- err = host1x_unregister_client(tegra, &hdmi->client.base);
+ err = host1x_client_unregister(&hdmi->client);
if (err < 0) {
dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
err);