diff options
Diffstat (limited to 'drivers/gpu/host1x')
50 files changed, 2625 insertions, 6208 deletions
diff --git a/drivers/gpu/host1x/Kconfig b/drivers/gpu/host1x/Kconfig index ccfd42b2360..b2fd029d67b 100644 --- a/drivers/gpu/host1x/Kconfig +++ b/drivers/gpu/host1x/Kconfig @@ -1,6 +1,6 @@  config TEGRA_HOST1X  	tristate "NVIDIA Tegra host1x driver" -	depends on ARCH_TEGRA || ARCH_MULTIPLATFORM +	depends on ARCH_TEGRA || (ARM && COMPILE_TEST)  	help  	  Driver for the NVIDIA Tegra host1x hardware. @@ -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 3b037b6e029..c1189f00444 100644 --- a/drivers/gpu/host1x/Makefile +++ b/drivers/gpu/host1x/Makefile @@ -1,6 +1,5 @@ -ccflags-y = -Idrivers/gpu/host1x -  host1x-y = \ +	bus.o \  	syncpt.o \  	dev.o \  	intr.o \ @@ -8,13 +7,9 @@ host1x-y = \  	channel.o \  	job.o \  	debug.o \ -	hw/host1x01.o - -ccflags-y += -Iinclude/drm -ccflags-$(CONFIG_DRM_TEGRA_DEBUG) += -DDEBUG +	mipi.o \ +	hw/host1x01.o \ +	hw/host1x02.o \ +	hw/host1x04.o -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  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 00000000000..aaf54859adb --- /dev/null +++ b/drivers/gpu/host1x/bus.c @@ -0,0 +1,553 @@ +/* + * Copyright (C) 2012 Avionic Design GmbH + * Copyright (C) 2012-2013, NVIDIA Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/host1x.h> +#include <linux/of.h> +#include <linux/slab.h> + +#include "bus.h" +#include "dev.h" + +static DEFINE_MUTEX(clients_lock); +static LIST_HEAD(clients); + +static DEFINE_MUTEX(drivers_lock); +static LIST_HEAD(drivers); + +static DEFINE_MUTEX(devices_lock); +static LIST_HEAD(devices); + +struct host1x_subdev { +	struct host1x_client *client; +	struct device_node *np; +	struct list_head list; +}; + +/** + * host1x_subdev_add() - add a new subdevice with an associated device node + */ +static int host1x_subdev_add(struct host1x_device *device, +			     struct device_node *np) +{ +	struct host1x_subdev *subdev; + +	subdev = kzalloc(sizeof(*subdev), GFP_KERNEL); +	if (!subdev) +		return -ENOMEM; + +	INIT_LIST_HEAD(&subdev->list); +	subdev->np = of_node_get(np); + +	mutex_lock(&device->subdevs_lock); +	list_add_tail(&subdev->list, &device->subdevs); +	mutex_unlock(&device->subdevs_lock); + +	return 0; +} + +/** + * host1x_subdev_del() - remove subdevice + */ +static void host1x_subdev_del(struct host1x_subdev *subdev) +{ +	list_del(&subdev->list); +	of_node_put(subdev->np); +	kfree(subdev); +} + +/** + * host1x_device_parse_dt() - scan device tree and add matching subdevices + */ +static int host1x_device_parse_dt(struct host1x_device *device) +{ +	struct device_node *np; +	int err; + +	for_each_child_of_node(device->dev.parent->of_node, np) { +		if (of_match_node(device->driver->subdevs, np) && +		    of_device_is_available(np)) { +			err = host1x_subdev_add(device, np); +			if (err < 0) +				return err; +		} +	} + +	return 0; +} + +static void host1x_subdev_register(struct host1x_device *device, +				   struct host1x_subdev *subdev, +				   struct host1x_client *client) +{ +	int err; + +	/* +	 * Move the subdevice to the list of active (registered) subdevices +	 * and associate it with a client. At the same time, associate the +	 * client with its parent device. +	 */ +	mutex_lock(&device->subdevs_lock); +	mutex_lock(&device->clients_lock); +	list_move_tail(&client->list, &device->clients); +	list_move_tail(&subdev->list, &device->active); +	client->parent = &device->dev; +	subdev->client = client; +	mutex_unlock(&device->clients_lock); +	mutex_unlock(&device->subdevs_lock); + +	/* +	 * When all subdevices have been registered, the composite device is +	 * ready to be probed. +	 */ +	if (list_empty(&device->subdevs)) { +		err = device->driver->probe(device); +		if (err < 0) +			dev_err(&device->dev, "probe failed: %d\n", err); +	} +} + +static void __host1x_subdev_unregister(struct host1x_device *device, +				       struct host1x_subdev *subdev) +{ +	struct host1x_client *client = subdev->client; +	int err; + +	/* +	 * If all subdevices have been activated, we're about to remove the +	 * first active subdevice, so unload the driver first. +	 */ +	if (list_empty(&device->subdevs)) { +		err = device->driver->remove(device); +		if (err < 0) +			dev_err(&device->dev, "remove failed: %d\n", err); +	} + +	/* +	 * Move the subdevice back to the list of idle subdevices and remove +	 * it from list of clients. +	 */ +	mutex_lock(&device->clients_lock); +	subdev->client = NULL; +	client->parent = NULL; +	list_move_tail(&subdev->list, &device->subdevs); +	/* +	 * XXX: Perhaps don't do this here, but rather explicitly remove it +	 * when the device is about to be deleted. +	 * +	 * This is somewhat complicated by the fact that this function is +	 * used to remove the subdevice when a client is unregistered but +	 * also when the composite device is about to be removed. +	 */ +	list_del_init(&client->list); +	mutex_unlock(&device->clients_lock); +} + +static void host1x_subdev_unregister(struct host1x_device *device, +				     struct host1x_subdev *subdev) +{ +	mutex_lock(&device->subdevs_lock); +	__host1x_subdev_unregister(device, subdev); +	mutex_unlock(&device->subdevs_lock); +} + +int host1x_device_init(struct host1x_device *device) +{ +	struct host1x_client *client; +	int err; + +	mutex_lock(&device->clients_lock); + +	list_for_each_entry(client, &device->clients, list) { +		if (client->ops && client->ops->init) { +			err = client->ops->init(client); +			if (err < 0) { +				dev_err(&device->dev, +					"failed to initialize %s: %d\n", +					dev_name(client->dev), err); +				mutex_unlock(&device->clients_lock); +				return err; +			} +		} +	} + +	mutex_unlock(&device->clients_lock); + +	return 0; +} +EXPORT_SYMBOL(host1x_device_init); + +int host1x_device_exit(struct host1x_device *device) +{ +	struct host1x_client *client; +	int err; + +	mutex_lock(&device->clients_lock); + +	list_for_each_entry_reverse(client, &device->clients, list) { +		if (client->ops && client->ops->exit) { +			err = client->ops->exit(client); +			if (err < 0) { +				dev_err(&device->dev, +					"failed to cleanup %s: %d\n", +					dev_name(client->dev), err); +				mutex_unlock(&device->clients_lock); +				return err; +			} +		} +	} + +	mutex_unlock(&device->clients_lock); + +	return 0; +} +EXPORT_SYMBOL(host1x_device_exit); + +static int host1x_add_client(struct host1x *host1x, +			     struct host1x_client *client) +{ +	struct host1x_device *device; +	struct host1x_subdev *subdev; + +	mutex_lock(&host1x->devices_lock); + +	list_for_each_entry(device, &host1x->devices, list) { +		list_for_each_entry(subdev, &device->subdevs, list) { +			if (subdev->np == client->dev->of_node) { +				host1x_subdev_register(device, subdev, client); +				mutex_unlock(&host1x->devices_lock); +				return 0; +			} +		} +	} + +	mutex_unlock(&host1x->devices_lock); +	return -ENODEV; +} + +static int host1x_del_client(struct host1x *host1x, +			     struct host1x_client *client) +{ +	struct host1x_device *device, *dt; +	struct host1x_subdev *subdev; + +	mutex_lock(&host1x->devices_lock); + +	list_for_each_entry_safe(device, dt, &host1x->devices, list) { +		list_for_each_entry(subdev, &device->active, list) { +			if (subdev->client == client) { +				host1x_subdev_unregister(device, subdev); +				mutex_unlock(&host1x->devices_lock); +				return 0; +			} +		} +	} + +	mutex_unlock(&host1x->devices_lock); +	return -ENODEV; +} + +static struct bus_type host1x_bus_type = { +	.name = "host1x", +}; + +int host1x_bus_init(void) +{ +	return bus_register(&host1x_bus_type); +} + +void host1x_bus_exit(void) +{ +	bus_unregister(&host1x_bus_type); +} + +static void host1x_device_release(struct device *dev) +{ +	struct host1x_device *device = to_host1x_device(dev); + +	kfree(device); +} + +static int host1x_device_add(struct host1x *host1x, +			     struct host1x_driver *driver) +{ +	struct host1x_client *client, *tmp; +	struct host1x_subdev *subdev; +	struct host1x_device *device; +	int err; + +	device = kzalloc(sizeof(*device), GFP_KERNEL); +	if (!device) +		return -ENOMEM; + +	mutex_init(&device->subdevs_lock); +	INIT_LIST_HEAD(&device->subdevs); +	INIT_LIST_HEAD(&device->active); +	mutex_init(&device->clients_lock); +	INIT_LIST_HEAD(&device->clients); +	INIT_LIST_HEAD(&device->list); +	device->driver = driver; + +	device->dev.coherent_dma_mask = host1x->dev->coherent_dma_mask; +	device->dev.dma_mask = &device->dev.coherent_dma_mask; +	device->dev.release = host1x_device_release; +	dev_set_name(&device->dev, "%s", driver->name); +	device->dev.bus = &host1x_bus_type; +	device->dev.parent = host1x->dev; + +	err = device_register(&device->dev); +	if (err < 0) +		return err; + +	err = host1x_device_parse_dt(device); +	if (err < 0) { +		device_unregister(&device->dev); +		return err; +	} + +	mutex_lock(&host1x->devices_lock); +	list_add_tail(&device->list, &host1x->devices); +	mutex_unlock(&host1x->devices_lock); + +	mutex_lock(&clients_lock); + +	list_for_each_entry_safe(client, tmp, &clients, list) { +		list_for_each_entry(subdev, &device->subdevs, list) { +			if (subdev->np == client->dev->of_node) { +				host1x_subdev_register(device, subdev, client); +				break; +			} +		} +	} + +	mutex_unlock(&clients_lock); + +	return 0; +} + +/* + * Removes a device by first unregistering any subdevices and then removing + * itself from the list of devices. + * + * This function must be called with the host1x->devices_lock held. + */ +static void host1x_device_del(struct host1x *host1x, +			      struct host1x_device *device) +{ +	struct host1x_subdev *subdev, *sd; +	struct host1x_client *client, *cl; + +	mutex_lock(&device->subdevs_lock); + +	/* unregister subdevices */ +	list_for_each_entry_safe(subdev, sd, &device->active, list) { +		/* +		 * host1x_subdev_unregister() will remove the client from +		 * any lists, so we'll need to manually add it back to the +		 * list of idle clients. +		 * +		 * XXX: Alternatively, perhaps don't remove the client from +		 * any lists in host1x_subdev_unregister() and instead do +		 * that explicitly from host1x_unregister_client()? +		 */ +		client = subdev->client; + +		__host1x_subdev_unregister(device, subdev); + +		/* add the client to the list of idle clients */ +		mutex_lock(&clients_lock); +		list_add_tail(&client->list, &clients); +		mutex_unlock(&clients_lock); +	} + +	/* remove subdevices */ +	list_for_each_entry_safe(subdev, sd, &device->subdevs, list) +		host1x_subdev_del(subdev); + +	mutex_unlock(&device->subdevs_lock); + +	/* move clients to idle list */ +	mutex_lock(&clients_lock); +	mutex_lock(&device->clients_lock); + +	list_for_each_entry_safe(client, cl, &device->clients, list) +		list_move_tail(&client->list, &clients); + +	mutex_unlock(&device->clients_lock); +	mutex_unlock(&clients_lock); + +	/* finally remove the device */ +	list_del_init(&device->list); +	device_unregister(&device->dev); +} + +static void host1x_attach_driver(struct host1x *host1x, +				 struct host1x_driver *driver) +{ +	struct host1x_device *device; +	int err; + +	mutex_lock(&host1x->devices_lock); + +	list_for_each_entry(device, &host1x->devices, list) { +		if (device->driver == driver) { +			mutex_unlock(&host1x->devices_lock); +			return; +		} +	} + +	mutex_unlock(&host1x->devices_lock); + +	err = host1x_device_add(host1x, driver); +	if (err < 0) +		dev_err(host1x->dev, "failed to allocate device: %d\n", err); +} + +static void host1x_detach_driver(struct host1x *host1x, +				 struct host1x_driver *driver) +{ +	struct host1x_device *device, *tmp; + +	mutex_lock(&host1x->devices_lock); + +	list_for_each_entry_safe(device, tmp, &host1x->devices, list) +		if (device->driver == driver) +			host1x_device_del(host1x, device); + +	mutex_unlock(&host1x->devices_lock); +} + +int host1x_register(struct host1x *host1x) +{ +	struct host1x_driver *driver; + +	mutex_lock(&devices_lock); +	list_add_tail(&host1x->list, &devices); +	mutex_unlock(&devices_lock); + +	mutex_lock(&drivers_lock); + +	list_for_each_entry(driver, &drivers, list) +		host1x_attach_driver(host1x, driver); + +	mutex_unlock(&drivers_lock); + +	return 0; +} + +int host1x_unregister(struct host1x *host1x) +{ +	struct host1x_driver *driver; + +	mutex_lock(&drivers_lock); + +	list_for_each_entry(driver, &drivers, list) +		host1x_detach_driver(host1x, driver); + +	mutex_unlock(&drivers_lock); + +	mutex_lock(&devices_lock); +	list_del_init(&host1x->list); +	mutex_unlock(&devices_lock); + +	return 0; +} + +int host1x_driver_register(struct host1x_driver *driver) +{ +	struct host1x *host1x; + +	INIT_LIST_HEAD(&driver->list); + +	mutex_lock(&drivers_lock); +	list_add_tail(&driver->list, &drivers); +	mutex_unlock(&drivers_lock); + +	mutex_lock(&devices_lock); + +	list_for_each_entry(host1x, &devices, list) +		host1x_attach_driver(host1x, driver); + +	mutex_unlock(&devices_lock); + +	return 0; +} +EXPORT_SYMBOL(host1x_driver_register); + +void host1x_driver_unregister(struct host1x_driver *driver) +{ +	mutex_lock(&drivers_lock); +	list_del_init(&driver->list); +	mutex_unlock(&drivers_lock); +} +EXPORT_SYMBOL(host1x_driver_unregister); + +int host1x_client_register(struct host1x_client *client) +{ +	struct host1x *host1x; +	int err; + +	mutex_lock(&devices_lock); + +	list_for_each_entry(host1x, &devices, list) { +		err = host1x_add_client(host1x, client); +		if (!err) { +			mutex_unlock(&devices_lock); +			return 0; +		} +	} + +	mutex_unlock(&devices_lock); + +	mutex_lock(&clients_lock); +	list_add_tail(&client->list, &clients); +	mutex_unlock(&clients_lock); + +	return 0; +} +EXPORT_SYMBOL(host1x_client_register); + +int host1x_client_unregister(struct host1x_client *client) +{ +	struct host1x_client *c; +	struct host1x *host1x; +	int err; + +	mutex_lock(&devices_lock); + +	list_for_each_entry(host1x, &devices, list) { +		err = host1x_del_client(host1x, client); +		if (!err) { +			mutex_unlock(&devices_lock); +			return 0; +		} +	} + +	mutex_unlock(&devices_lock); +	mutex_lock(&clients_lock); + +	list_for_each_entry(c, &clients, list) { +		if (c == client) { +			list_del_init(&c->list); +			break; +		} +	} + +	mutex_unlock(&clients_lock); + +	return 0; +} +EXPORT_SYMBOL(host1x_client_unregister); diff --git a/drivers/gpu/host1x/host1x_client.h b/drivers/gpu/host1x/bus.h index 9b85f10f4a4..4099e99212c 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 host1x_drm_alloc(struct platform_device *pdev); -#else -static inline int host1x_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/cdma.c b/drivers/gpu/host1x/cdma.c index de72172d3b5..3995255b16c 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.c b/drivers/gpu/host1x/channel.c index 83ea51b9f0f..b4ae3affb98 100644 --- a/drivers/gpu/host1x/channel.c +++ b/drivers/gpu/host1x/channel.c @@ -43,6 +43,7 @@ int host1x_job_submit(struct host1x_job *job)  	return host1x_hw_channel_submit(host, job);  } +EXPORT_SYMBOL(host1x_job_submit);  struct host1x_channel *host1x_channel_get(struct host1x_channel *channel)  { @@ -60,6 +61,7 @@ struct host1x_channel *host1x_channel_get(struct host1x_channel *channel)  	return err ? NULL : channel;  } +EXPORT_SYMBOL(host1x_channel_get);  void host1x_channel_put(struct host1x_channel *channel)  { @@ -76,6 +78,7 @@ void host1x_channel_put(struct host1x_channel *channel)  	mutex_unlock(&channel->reflock);  } +EXPORT_SYMBOL(host1x_channel_put);  struct host1x_channel *host1x_channel_request(struct device *dev)  { @@ -115,6 +118,7 @@ fail:  	mutex_unlock(&host->chlist_mutex);  	return NULL;  } +EXPORT_SYMBOL(host1x_channel_request);  void host1x_channel_free(struct host1x_channel *channel)  { @@ -124,3 +128,4 @@ void host1x_channel_free(struct host1x_channel *channel)  	list_del(&channel->list);  	kfree(channel);  } +EXPORT_SYMBOL(host1x_channel_free); diff --git a/drivers/gpu/host1x/channel.h b/drivers/gpu/host1x/channel.h index 48723b8eea4..df767cf90d5 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/debug.c b/drivers/gpu/host1x/debug.c index 3ec7d77de24..ee3d12b51c5 100644 --- a/drivers/gpu/host1x/debug.c +++ b/drivers/gpu/host1x/debug.c @@ -96,7 +96,6 @@ static void show_all(struct host1x *m, struct output *o)  		show_channels(ch, o, true);  } -#ifdef CONFIG_DEBUG_FS  static void show_all_no_fifo(struct host1x *host1x, struct output *o)  {  	struct host1x_channel *ch; @@ -153,7 +152,7 @@ static const struct file_operations host1x_debug_fops = {  	.release	= single_release,  }; -void host1x_debug_init(struct host1x *host1x) +static void host1x_debugfs_init(struct host1x *host1x)  {  	struct dentry *de = debugfs_create_dir("tegra-host1x", NULL); @@ -180,18 +179,22 @@ void host1x_debug_init(struct host1x *host1x)  			   &host1x_debug_force_timeout_channel);  } -void host1x_debug_deinit(struct host1x *host1x) +static void host1x_debugfs_exit(struct host1x *host1x)  {  	debugfs_remove_recursive(host1x->debugfs);  } -#else +  void host1x_debug_init(struct host1x *host1x)  { +	if (IS_ENABLED(CONFIG_DEBUG_FS)) +		host1x_debugfs_init(host1x);  } +  void host1x_debug_deinit(struct host1x *host1x)  { +	if (IS_ENABLED(CONFIG_DEBUG_FS)) +		host1x_debugfs_exit(host1x);  } -#endif  void host1x_debug_dump(struct host1x *host1x)  { diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index 47163029987..2529908d304 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -27,24 +27,14 @@  #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; -} +#include "hw/host1x02.h" +#include "hw/host1x04.h"  void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r)  { @@ -79,7 +69,27 @@ 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 const struct host1x_info host1x04_info = { +	.nb_channels = 12, +	.nb_pts = 192, +	.nb_mlocks = 16, +	.nb_bases = 64, +	.init = host1x04_init, +	.sync_offset = 0x2100, +}; +  static struct of_device_id host1x_of_match[] = { +	{ .compatible = "nvidia,tegra124-host1x", .data = &host1x04_info, }, +	{ .compatible = "nvidia,tegra114-host1x", .data = &host1x02_info, },  	{ .compatible = "nvidia,tegra30-host1x", .data = &host1x01_info, },  	{ .compatible = "nvidia,tegra20-host1x", .data = &host1x01_info, },  	{ }, @@ -114,6 +124,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; @@ -152,7 +165,7 @@ static int host1x_probe(struct platform_device *pdev)  	err = host1x_syncpt_init(host);  	if (err) {  		dev_err(&pdev->dev, "failed to initialize syncpts\n"); -		return err; +		goto fail_unprepare_disable;  	}  	err = host1x_intr_init(host, syncpt_irq); @@ -163,19 +176,26 @@ static int host1x_probe(struct platform_device *pdev)  	host1x_debug_init(host); -	host1x_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); +fail_unprepare_disable: +	clk_disable_unprepare(host->clk);  	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); +	host1x_unregister(host);  	host1x_intr_deinit(host);  	host1x_syncpt_deinit(host);  	clk_disable_unprepare(host->clk); @@ -184,59 +204,45 @@ 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)  {  	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); +	err = platform_driver_register(&tegra_host1x_driver);  	if (err < 0) -		goto unregister_dc; +		goto unregister_bus; -	err = platform_driver_register(&tegra_gr2d_driver); +	err = platform_driver_register(&tegra_mipi_driver);  	if (err < 0) -		goto unregister_hdmi; -#endif +		goto unregister_host1x;  	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); +unregister_bus: +	host1x_bus_exit();  	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_mipi_driver);  	platform_driver_unregister(&tegra_host1x_driver); +	host1x_bus_exit();  }  module_exit(tegra_host1x_exit); diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h index bed90a8131b..0b6e8e9629c 100644 --- a/drivers/gpu/host1x/dev.h +++ b/drivers/gpu/host1x/dev.h @@ -27,6 +27,7 @@  #include "job.h"  struct host1x_syncpt; +struct host1x_syncpt_base;  struct host1x_channel;  struct host1x_cdma;  struct host1x_job; @@ -102,6 +103,7 @@ struct host1x {  	void __iomem *regs;  	struct host1x_syncpt *syncpt; +	struct host1x_syncpt_base *bases;  	struct device *dev;  	struct clk *clk; @@ -125,7 +127,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 +306,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_dc_driver; -extern struct platform_driver tegra_hdmi_driver; -extern struct platform_driver tegra_gr2d_driver; +extern struct platform_driver tegra_mipi_driver;  #endif diff --git a/drivers/gpu/host1x/drm/Kconfig b/drivers/gpu/host1x/drm/Kconfig deleted file mode 100644 index 69853a4de40..00000000000 --- a/drivers/gpu/host1x/drm/Kconfig +++ /dev/null @@ -1,29 +0,0 @@ -config DRM_TEGRA -	bool "NVIDIA Tegra DRM" -	depends on DRM -	select DRM_KMS_HELPER -	select FB_SYS_FILLRECT -	select FB_SYS_COPYAREA -	select FB_SYS_IMAGEBLIT -	help -	  Choose this option if you have an NVIDIA Tegra SoC. - -	  To compile this driver as a module, choose M here: the module -	  will be called tegra-drm. - -if DRM_TEGRA - -config DRM_TEGRA_STAGING -	bool "Enable HOST1X interface" -	depends on STAGING -	help -	  Say yes if HOST1X should be available for userspace DRM users. - -	  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/host1x/drm/dc.c b/drivers/gpu/host1x/drm/dc.c deleted file mode 100644 index b1a05ad901c..00000000000 --- a/drivers/gpu/host1x/drm/dc.c +++ /dev/null @@ -1,1200 +0,0 @@ -/* - * Copyright (C) 2012 Avionic Design GmbH - * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#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 "host1x_client.h" -#include "dc.h" -#include "drm.h" -#include "gem.h" - -struct tegra_plane { -	struct drm_plane base; -	unsigned int index; -}; - -static inline struct tegra_plane *to_tegra_plane(struct drm_plane *plane) -{ -	return container_of(plane, struct tegra_plane, base); -} - -static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, -			      struct drm_framebuffer *fb, int crtc_x, -			      int crtc_y, unsigned int crtc_w, -			      unsigned int crtc_h, uint32_t src_x, -			      uint32_t src_y, uint32_t src_w, uint32_t src_h) -{ -	struct tegra_plane *p = to_tegra_plane(plane); -	struct tegra_dc *dc = to_tegra_dc(crtc); -	struct tegra_dc_window window; -	unsigned int i; - -	memset(&window, 0, sizeof(window)); -	window.src.x = src_x >> 16; -	window.src.y = src_y >> 16; -	window.src.w = src_w >> 16; -	window.src.h = src_h >> 16; -	window.dst.x = crtc_x; -	window.dst.y = crtc_y; -	window.dst.w = crtc_w; -	window.dst.h = crtc_h; -	window.format = tegra_dc_format(fb->pixel_format); -	window.bits_per_pixel = fb->bits_per_pixel; - -	for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) { -		struct tegra_bo *bo = tegra_fb_get_plane(fb, i); - -		window.base[i] = bo->paddr + fb->offsets[i]; - -		/* -		 * Tegra doesn't support different strides for U and V planes -		 * so we display a warning if the user tries to display a -		 * framebuffer with such a configuration. -		 */ -		if (i >= 2) { -			if (fb->pitches[i] != window.stride[1]) -				DRM_ERROR("unsupported UV-plane configuration\n"); -		} else { -			window.stride[i] = fb->pitches[i]; -		} -	} - -	return tegra_dc_setup_window(dc, p->index, &window); -} - -static int tegra_plane_disable(struct drm_plane *plane) -{ -	struct tegra_dc *dc = to_tegra_dc(plane->crtc); -	struct tegra_plane *p = to_tegra_plane(plane); -	unsigned long value; - -	if (!plane->crtc) -		return 0; - -	value = WINDOW_A_SELECT << p->index; -	tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); - -	value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS); -	value &= ~WIN_ENABLE; -	tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS); - -	tegra_dc_writel(dc, WIN_A_UPDATE << p->index, DC_CMD_STATE_CONTROL); -	tegra_dc_writel(dc, WIN_A_ACT_REQ << p->index, DC_CMD_STATE_CONTROL); - -	return 0; -} - -static void tegra_plane_destroy(struct drm_plane *plane) -{ -	tegra_plane_disable(plane); -	drm_plane_cleanup(plane); -} - -static const struct drm_plane_funcs tegra_plane_funcs = { -	.update_plane = tegra_plane_update, -	.disable_plane = tegra_plane_disable, -	.destroy = tegra_plane_destroy, -}; - -static const uint32_t plane_formats[] = { -	DRM_FORMAT_XBGR8888, -	DRM_FORMAT_XRGB8888, -	DRM_FORMAT_RGB565, -	DRM_FORMAT_UYVY, -	DRM_FORMAT_YUV420, -	DRM_FORMAT_YUV422, -}; - -static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc) -{ -	unsigned int i; -	int err = 0; - -	for (i = 0; i < 2; i++) { -		struct tegra_plane *plane; - -		plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL); -		if (!plane) -			return -ENOMEM; - -		plane->index = 1 + i; - -		err = drm_plane_init(drm, &plane->base, 1 << dc->pipe, -				     &tegra_plane_funcs, plane_formats, -				     ARRAY_SIZE(plane_formats), false); -		if (err < 0) -			return err; -	} - -	return 0; -} - -static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, -			     struct drm_framebuffer *fb) -{ -	unsigned int format = tegra_dc_format(fb->pixel_format); -	struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); -	unsigned long value; - -	tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); - -	value = fb->offsets[0] + y * fb->pitches[0] + -		x * fb->bits_per_pixel / 8; - -	tegra_dc_writel(dc, bo->paddr + value, DC_WINBUF_START_ADDR); -	tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE); -	tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH); - -	value = GENERAL_UPDATE | WIN_A_UPDATE; -	tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); - -	value = GENERAL_ACT_REQ | WIN_A_ACT_REQ; -	tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); - -	return 0; -} - -void tegra_dc_enable_vblank(struct tegra_dc *dc) -{ -	unsigned long value, flags; - -	spin_lock_irqsave(&dc->lock, flags); - -	value = tegra_dc_readl(dc, DC_CMD_INT_MASK); -	value |= VBLANK_INT; -	tegra_dc_writel(dc, value, DC_CMD_INT_MASK); - -	spin_unlock_irqrestore(&dc->lock, flags); -} - -void tegra_dc_disable_vblank(struct tegra_dc *dc) -{ -	unsigned long value, flags; - -	spin_lock_irqsave(&dc->lock, flags); - -	value = tegra_dc_readl(dc, DC_CMD_INT_MASK); -	value &= ~VBLANK_INT; -	tegra_dc_writel(dc, value, DC_CMD_INT_MASK); - -	spin_unlock_irqrestore(&dc->lock, flags); -} - -static void tegra_dc_finish_page_flip(struct tegra_dc *dc) -{ -	struct drm_device *drm = dc->base.dev; -	struct drm_crtc *crtc = &dc->base; -	unsigned long flags, base; -	struct tegra_bo *bo; - -	if (!dc->event) -		return; - -	bo = tegra_fb_get_plane(crtc->fb, 0); - -	/* check if new start address has been latched */ -	tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS); -	base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR); -	tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS); - -	if (base == bo->paddr + crtc->fb->offsets[0]) { -		spin_lock_irqsave(&drm->event_lock, flags); -		drm_send_vblank_event(drm, dc->pipe, dc->event); -		drm_vblank_put(drm, dc->pipe); -		dc->event = NULL; -		spin_unlock_irqrestore(&drm->event_lock, flags); -	} -} - -void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) -{ -	struct tegra_dc *dc = to_tegra_dc(crtc); -	struct drm_device *drm = crtc->dev; -	unsigned long flags; - -	spin_lock_irqsave(&drm->event_lock, flags); - -	if (dc->event && dc->event->base.file_priv == file) { -		dc->event->base.destroy(&dc->event->base); -		drm_vblank_put(drm, dc->pipe); -		dc->event = NULL; -	} - -	spin_unlock_irqrestore(&drm->event_lock, flags); -} - -static int tegra_dc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, -			      struct drm_pending_vblank_event *event, uint32_t page_flip_flags) -{ -	struct tegra_dc *dc = to_tegra_dc(crtc); -	struct drm_device *drm = crtc->dev; - -	if (dc->event) -		return -EBUSY; - -	if (event) { -		event->pipe = dc->pipe; -		dc->event = event; -		drm_vblank_get(drm, dc->pipe); -	} - -	tegra_dc_set_base(dc, 0, 0, fb); -	crtc->fb = fb; - -	return 0; -} - -static const struct drm_crtc_funcs tegra_crtc_funcs = { -	.page_flip = tegra_dc_page_flip, -	.set_config = drm_crtc_helper_set_config, -	.destroy = drm_crtc_cleanup, -}; - -static void tegra_crtc_disable(struct drm_crtc *crtc) -{ -	struct drm_device *drm = crtc->dev; -	struct drm_plane *plane; - -	list_for_each_entry(plane, &drm->mode_config.plane_list, head) { -		if (plane->crtc == crtc) { -			tegra_plane_disable(plane); -			plane->crtc = NULL; - -			if (plane->fb) { -				drm_framebuffer_unreference(plane->fb); -				plane->fb = NULL; -			} -		} -	} -} - -static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc, -				  const struct drm_display_mode *mode, -				  struct drm_display_mode *adjusted) -{ -	return true; -} - -static inline u32 compute_dda_inc(unsigned int in, unsigned int out, bool v, -				  unsigned int bpp) -{ -	fixed20_12 outf = dfixed_init(out); -	fixed20_12 inf = dfixed_init(in); -	u32 dda_inc; -	int max; - -	if (v) -		max = 15; -	else { -		switch (bpp) { -		case 2: -			max = 8; -			break; - -		default: -			WARN_ON_ONCE(1); -			/* fallthrough */ -		case 4: -			max = 4; -			break; -		} -	} - -	outf.full = max_t(u32, outf.full - dfixed_const(1), dfixed_const(1)); -	inf.full -= dfixed_const(1); - -	dda_inc = dfixed_div(inf, outf); -	dda_inc = min_t(u32, dda_inc, dfixed_const(max)); - -	return dda_inc; -} - -static inline u32 compute_initial_dda(unsigned int in) -{ -	fixed20_12 inf = dfixed_init(in); -	return dfixed_frac(inf); -} - -static int tegra_dc_set_timings(struct tegra_dc *dc, -				struct drm_display_mode *mode) -{ -	/* TODO: For HDMI compliance, h & v ref_to_sync should be set to 1 */ -	unsigned int h_ref_to_sync = 0; -	unsigned int v_ref_to_sync = 0; -	unsigned long value; - -	tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS); - -	value = (v_ref_to_sync << 16) | h_ref_to_sync; -	tegra_dc_writel(dc, value, DC_DISP_REF_TO_SYNC); - -	value = ((mode->vsync_end - mode->vsync_start) << 16) | -		((mode->hsync_end - mode->hsync_start) <<  0); -	tegra_dc_writel(dc, value, DC_DISP_SYNC_WIDTH); - -	value = ((mode->vtotal - mode->vsync_end) << 16) | -		((mode->htotal - mode->hsync_end) <<  0); -	tegra_dc_writel(dc, value, DC_DISP_BACK_PORCH); - -	value = ((mode->vsync_start - mode->vdisplay) << 16) | -		((mode->hsync_start - mode->hdisplay) <<  0); -	tegra_dc_writel(dc, value, DC_DISP_FRONT_PORCH); - -	value = (mode->vdisplay << 16) | mode->hdisplay; -	tegra_dc_writel(dc, value, DC_DISP_ACTIVE); - -	return 0; -} - -static int tegra_crtc_setup_clk(struct drm_crtc *crtc, -				struct drm_display_mode *mode, -				unsigned long *div) -{ -	unsigned long pclk = mode->clock * 1000, rate; -	struct tegra_dc *dc = to_tegra_dc(crtc); -	struct tegra_output *output = NULL; -	struct drm_encoder *encoder; -	long err; - -	list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list, head) -		if (encoder->crtc == crtc) { -			output = encoder_to_output(encoder); -			break; -		} - -	if (!output) -		return -ENODEV; - -	/* -	 * This assumes that the display controller will divide its parent -	 * clock by 2 to generate the pixel clock. -	 */ -	err = tegra_output_setup_clock(output, dc->clk, pclk * 2); -	if (err < 0) { -		dev_err(dc->dev, "failed to setup clock: %ld\n", err); -		return err; -	} - -	rate = clk_get_rate(dc->clk); -	*div = (rate * 2 / pclk) - 2; - -	DRM_DEBUG_KMS("rate: %lu, div: %lu\n", rate, *div); - -	return 0; -} - -static bool tegra_dc_format_is_yuv(unsigned int format, bool *planar) -{ -	switch (format) { -	case WIN_COLOR_DEPTH_YCbCr422: -	case WIN_COLOR_DEPTH_YUV422: -		if (planar) -			*planar = false; - -		return true; - -	case WIN_COLOR_DEPTH_YCbCr420P: -	case WIN_COLOR_DEPTH_YUV420P: -	case WIN_COLOR_DEPTH_YCbCr422P: -	case WIN_COLOR_DEPTH_YUV422P: -	case WIN_COLOR_DEPTH_YCbCr422R: -	case WIN_COLOR_DEPTH_YUV422R: -	case WIN_COLOR_DEPTH_YCbCr422RA: -	case WIN_COLOR_DEPTH_YUV422RA: -		if (planar) -			*planar = true; - -		return true; -	} - -	return false; -} - -int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, -			  const struct tegra_dc_window *window) -{ -	unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp; -	unsigned long value; -	bool yuv, planar; - -	/* -	 * For YUV planar modes, the number of bytes per pixel takes into -	 * account only the luma component and therefore is 1. -	 */ -	yuv = tegra_dc_format_is_yuv(window->format, &planar); -	if (!yuv) -		bpp = window->bits_per_pixel / 8; -	else -		bpp = planar ? 1 : 2; - -	value = WINDOW_A_SELECT << index; -	tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); - -	tegra_dc_writel(dc, window->format, DC_WIN_COLOR_DEPTH); -	tegra_dc_writel(dc, 0, DC_WIN_BYTE_SWAP); - -	value = V_POSITION(window->dst.y) | H_POSITION(window->dst.x); -	tegra_dc_writel(dc, value, DC_WIN_POSITION); - -	value = V_SIZE(window->dst.h) | H_SIZE(window->dst.w); -	tegra_dc_writel(dc, value, DC_WIN_SIZE); - -	h_offset = window->src.x * bpp; -	v_offset = window->src.y; -	h_size = window->src.w * bpp; -	v_size = window->src.h; - -	value = V_PRESCALED_SIZE(v_size) | H_PRESCALED_SIZE(h_size); -	tegra_dc_writel(dc, value, DC_WIN_PRESCALED_SIZE); - -	/* -	 * For DDA computations the number of bytes per pixel for YUV planar -	 * modes needs to take into account all Y, U and V components. -	 */ -	if (yuv && planar) -		bpp = 2; - -	h_dda = compute_dda_inc(window->src.w, window->dst.w, false, bpp); -	v_dda = compute_dda_inc(window->src.h, window->dst.h, true, bpp); - -	value = V_DDA_INC(v_dda) | H_DDA_INC(h_dda); -	tegra_dc_writel(dc, value, DC_WIN_DDA_INC); - -	h_dda = compute_initial_dda(window->src.x); -	v_dda = compute_initial_dda(window->src.y); - -	tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA); -	tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA); - -	tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE); -	tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE); - -	tegra_dc_writel(dc, window->base[0], DC_WINBUF_START_ADDR); - -	if (yuv && planar) { -		tegra_dc_writel(dc, window->base[1], DC_WINBUF_START_ADDR_U); -		tegra_dc_writel(dc, window->base[2], DC_WINBUF_START_ADDR_V); -		value = window->stride[1] << 16 | window->stride[0]; -		tegra_dc_writel(dc, value, DC_WIN_LINE_STRIDE); -	} else { -		tegra_dc_writel(dc, window->stride[0], DC_WIN_LINE_STRIDE); -	} - -	tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET); -	tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET); - -	value = WIN_ENABLE; - -	if (yuv) { -		/* setup default colorspace conversion coefficients */ -		tegra_dc_writel(dc, 0x00f0, DC_WIN_CSC_YOF); -		tegra_dc_writel(dc, 0x012a, DC_WIN_CSC_KYRGB); -		tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KUR); -		tegra_dc_writel(dc, 0x0198, DC_WIN_CSC_KVR); -		tegra_dc_writel(dc, 0x039b, DC_WIN_CSC_KUG); -		tegra_dc_writel(dc, 0x032f, DC_WIN_CSC_KVG); -		tegra_dc_writel(dc, 0x0204, DC_WIN_CSC_KUB); -		tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KVB); - -		value |= CSC_ENABLE; -	} else if (window->bits_per_pixel < 24) { -		value |= COLOR_EXPAND; -	} - -	tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS); - -	/* -	 * Disable blending and assume Window A is the bottom-most window, -	 * Window C is the top-most window and Window B is in the middle. -	 */ -	tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_NOKEY); -	tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_1WIN); - -	switch (index) { -	case 0: -		tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_X); -		tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y); -		tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY); -		break; - -	case 1: -		tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X); -		tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y); -		tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY); -		break; - -	case 2: -		tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X); -		tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_Y); -		tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_3WIN_XY); -		break; -	} - -	tegra_dc_writel(dc, WIN_A_UPDATE << index, DC_CMD_STATE_CONTROL); -	tegra_dc_writel(dc, WIN_A_ACT_REQ << index, DC_CMD_STATE_CONTROL); - -	return 0; -} - -unsigned int tegra_dc_format(uint32_t format) -{ -	switch (format) { -	case DRM_FORMAT_XBGR8888: -		return WIN_COLOR_DEPTH_R8G8B8A8; - -	case DRM_FORMAT_XRGB8888: -		return WIN_COLOR_DEPTH_B8G8R8A8; - -	case DRM_FORMAT_RGB565: -		return WIN_COLOR_DEPTH_B5G6R5; - -	case DRM_FORMAT_UYVY: -		return WIN_COLOR_DEPTH_YCbCr422; - -	case DRM_FORMAT_YUV420: -		return WIN_COLOR_DEPTH_YCbCr420P; - -	case DRM_FORMAT_YUV422: -		return WIN_COLOR_DEPTH_YCbCr422P; - -	default: -		break; -	} - -	WARN(1, "unsupported pixel format %u, using default\n", format); -	return WIN_COLOR_DEPTH_B8G8R8A8; -} - -static int tegra_crtc_mode_set(struct drm_crtc *crtc, -			       struct drm_display_mode *mode, -			       struct drm_display_mode *adjusted, -			       int x, int y, struct drm_framebuffer *old_fb) -{ -	struct tegra_bo *bo = tegra_fb_get_plane(crtc->fb, 0); -	struct tegra_dc *dc = to_tegra_dc(crtc); -	struct tegra_dc_window window; -	unsigned long div, value; -	int err; - -	drm_vblank_pre_modeset(crtc->dev, dc->pipe); - -	err = tegra_crtc_setup_clk(crtc, mode, &div); -	if (err) { -		dev_err(dc->dev, "failed to setup clock for CRTC: %d\n", err); -		return err; -	} - -	/* program display mode */ -	tegra_dc_set_timings(dc, mode); - -	value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL; -	tegra_dc_writel(dc, value, DC_DISP_DATA_ENABLE_OPTIONS); - -	value = tegra_dc_readl(dc, DC_COM_PIN_OUTPUT_POLARITY(1)); -	value &= ~LVS_OUTPUT_POLARITY_LOW; -	value &= ~LHS_OUTPUT_POLARITY_LOW; -	tegra_dc_writel(dc, value, DC_COM_PIN_OUTPUT_POLARITY(1)); - -	value = DISP_DATA_FORMAT_DF1P1C | DISP_ALIGNMENT_MSB | -		DISP_ORDER_RED_BLUE; -	tegra_dc_writel(dc, value, DC_DISP_DISP_INTERFACE_CONTROL); - -	tegra_dc_writel(dc, 0x00010001, DC_DISP_SHIFT_CLOCK_OPTIONS); - -	value = SHIFT_CLK_DIVIDER(div) | PIXEL_CLK_DIVIDER_PCD1; -	tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL); - -	/* setup window parameters */ -	memset(&window, 0, sizeof(window)); -	window.src.x = 0; -	window.src.y = 0; -	window.src.w = mode->hdisplay; -	window.src.h = mode->vdisplay; -	window.dst.x = 0; -	window.dst.y = 0; -	window.dst.w = mode->hdisplay; -	window.dst.h = mode->vdisplay; -	window.format = tegra_dc_format(crtc->fb->pixel_format); -	window.bits_per_pixel = crtc->fb->bits_per_pixel; -	window.stride[0] = crtc->fb->pitches[0]; -	window.base[0] = bo->paddr; - -	err = tegra_dc_setup_window(dc, 0, &window); -	if (err < 0) -		dev_err(dc->dev, "failed to enable root plane\n"); - -	return 0; -} - -static int tegra_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, -				    struct drm_framebuffer *old_fb) -{ -	struct tegra_dc *dc = to_tegra_dc(crtc); - -	return tegra_dc_set_base(dc, x, y, crtc->fb); -} - -static void tegra_crtc_prepare(struct drm_crtc *crtc) -{ -	struct tegra_dc *dc = to_tegra_dc(crtc); -	unsigned int syncpt; -	unsigned long value; - -	/* hardware initialization */ -	tegra_periph_reset_deassert(dc->clk); -	usleep_range(10000, 20000); - -	if (dc->pipe) -		syncpt = SYNCPT_VBLANK1; -	else -		syncpt = SYNCPT_VBLANK0; - -	/* initialize display controller */ -	tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL); -	tegra_dc_writel(dc, 0x100 | syncpt, DC_CMD_CONT_SYNCPT_VSYNC); - -	value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | WIN_A_OF_INT; -	tegra_dc_writel(dc, value, DC_CMD_INT_TYPE); - -	value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | -		WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT; -	tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY); - -	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); - -	value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND); -	value |= DISP_CTRL_MODE_C_DISPLAY; -	tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND); - -	/* initialize timer */ -	value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) | -		WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20); -	tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY); - -	value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(1) | -		WINDOW_B_THRESHOLD(1) | WINDOW_C_THRESHOLD(1); -	tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER); - -	value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT; -	tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE); - -	value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT; -	tegra_dc_writel(dc, value, DC_CMD_INT_MASK); -} - -static void tegra_crtc_commit(struct drm_crtc *crtc) -{ -	struct tegra_dc *dc = to_tegra_dc(crtc); -	unsigned long value; - -	value = GENERAL_UPDATE | WIN_A_UPDATE; -	tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); - -	value = GENERAL_ACT_REQ | WIN_A_ACT_REQ; -	tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); - -	drm_vblank_post_modeset(crtc->dev, dc->pipe); -} - -static void tegra_crtc_load_lut(struct drm_crtc *crtc) -{ -} - -static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = { -	.disable = tegra_crtc_disable, -	.mode_fixup = tegra_crtc_mode_fixup, -	.mode_set = tegra_crtc_mode_set, -	.mode_set_base = tegra_crtc_mode_set_base, -	.prepare = tegra_crtc_prepare, -	.commit = tegra_crtc_commit, -	.load_lut = tegra_crtc_load_lut, -}; - -static irqreturn_t tegra_dc_irq(int irq, void *data) -{ -	struct tegra_dc *dc = data; -	unsigned long status; - -	status = tegra_dc_readl(dc, DC_CMD_INT_STATUS); -	tegra_dc_writel(dc, status, DC_CMD_INT_STATUS); - -	if (status & FRAME_END_INT) { -		/* -		dev_dbg(dc->dev, "%s(): frame end\n", __func__); -		*/ -	} - -	if (status & VBLANK_INT) { -		/* -		dev_dbg(dc->dev, "%s(): vertical blank\n", __func__); -		*/ -		drm_handle_vblank(dc->base.dev, dc->pipe); -		tegra_dc_finish_page_flip(dc); -	} - -	if (status & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)) { -		/* -		dev_dbg(dc->dev, "%s(): underflow\n", __func__); -		*/ -	} - -	return IRQ_HANDLED; -} - -static int tegra_dc_show_regs(struct seq_file *s, void *data) -{ -	struct drm_info_node *node = s->private; -	struct tegra_dc *dc = node->info_ent->data; - -#define DUMP_REG(name)						\ -	seq_printf(s, "%-40s %#05x %08lx\n", #name, name,	\ -		   tegra_dc_readl(dc, name)) - -	DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT); -	DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT_CNTRL); -	DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT_ERROR); -	DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT); -	DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT_CNTRL); -	DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT_ERROR); -	DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT); -	DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT_CNTRL); -	DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT_ERROR); -	DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT); -	DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT_CNTRL); -	DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT_ERROR); -	DUMP_REG(DC_CMD_CONT_SYNCPT_VSYNC); -	DUMP_REG(DC_CMD_DISPLAY_COMMAND_OPTION0); -	DUMP_REG(DC_CMD_DISPLAY_COMMAND); -	DUMP_REG(DC_CMD_SIGNAL_RAISE); -	DUMP_REG(DC_CMD_DISPLAY_POWER_CONTROL); -	DUMP_REG(DC_CMD_INT_STATUS); -	DUMP_REG(DC_CMD_INT_MASK); -	DUMP_REG(DC_CMD_INT_ENABLE); -	DUMP_REG(DC_CMD_INT_TYPE); -	DUMP_REG(DC_CMD_INT_POLARITY); -	DUMP_REG(DC_CMD_SIGNAL_RAISE1); -	DUMP_REG(DC_CMD_SIGNAL_RAISE2); -	DUMP_REG(DC_CMD_SIGNAL_RAISE3); -	DUMP_REG(DC_CMD_STATE_ACCESS); -	DUMP_REG(DC_CMD_STATE_CONTROL); -	DUMP_REG(DC_CMD_DISPLAY_WINDOW_HEADER); -	DUMP_REG(DC_CMD_REG_ACT_CONTROL); -	DUMP_REG(DC_COM_CRC_CONTROL); -	DUMP_REG(DC_COM_CRC_CHECKSUM); -	DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(0)); -	DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(1)); -	DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(2)); -	DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(3)); -	DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(0)); -	DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(1)); -	DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(2)); -	DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(3)); -	DUMP_REG(DC_COM_PIN_OUTPUT_DATA(0)); -	DUMP_REG(DC_COM_PIN_OUTPUT_DATA(1)); -	DUMP_REG(DC_COM_PIN_OUTPUT_DATA(2)); -	DUMP_REG(DC_COM_PIN_OUTPUT_DATA(3)); -	DUMP_REG(DC_COM_PIN_INPUT_ENABLE(0)); -	DUMP_REG(DC_COM_PIN_INPUT_ENABLE(1)); -	DUMP_REG(DC_COM_PIN_INPUT_ENABLE(2)); -	DUMP_REG(DC_COM_PIN_INPUT_ENABLE(3)); -	DUMP_REG(DC_COM_PIN_INPUT_DATA(0)); -	DUMP_REG(DC_COM_PIN_INPUT_DATA(1)); -	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(0)); -	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(1)); -	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(2)); -	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(3)); -	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(4)); -	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(5)); -	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(6)); -	DUMP_REG(DC_COM_PIN_MISC_CONTROL); -	DUMP_REG(DC_COM_PIN_PM0_CONTROL); -	DUMP_REG(DC_COM_PIN_PM0_DUTY_CYCLE); -	DUMP_REG(DC_COM_PIN_PM1_CONTROL); -	DUMP_REG(DC_COM_PIN_PM1_DUTY_CYCLE); -	DUMP_REG(DC_COM_SPI_CONTROL); -	DUMP_REG(DC_COM_SPI_START_BYTE); -	DUMP_REG(DC_COM_HSPI_WRITE_DATA_AB); -	DUMP_REG(DC_COM_HSPI_WRITE_DATA_CD); -	DUMP_REG(DC_COM_HSPI_CS_DC); -	DUMP_REG(DC_COM_SCRATCH_REGISTER_A); -	DUMP_REG(DC_COM_SCRATCH_REGISTER_B); -	DUMP_REG(DC_COM_GPIO_CTRL); -	DUMP_REG(DC_COM_GPIO_DEBOUNCE_COUNTER); -	DUMP_REG(DC_COM_CRC_CHECKSUM_LATCHED); -	DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS0); -	DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS1); -	DUMP_REG(DC_DISP_DISP_WIN_OPTIONS); -	DUMP_REG(DC_DISP_DISP_MEM_HIGH_PRIORITY); -	DUMP_REG(DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER); -	DUMP_REG(DC_DISP_DISP_TIMING_OPTIONS); -	DUMP_REG(DC_DISP_REF_TO_SYNC); -	DUMP_REG(DC_DISP_SYNC_WIDTH); -	DUMP_REG(DC_DISP_BACK_PORCH); -	DUMP_REG(DC_DISP_ACTIVE); -	DUMP_REG(DC_DISP_FRONT_PORCH); -	DUMP_REG(DC_DISP_H_PULSE0_CONTROL); -	DUMP_REG(DC_DISP_H_PULSE0_POSITION_A); -	DUMP_REG(DC_DISP_H_PULSE0_POSITION_B); -	DUMP_REG(DC_DISP_H_PULSE0_POSITION_C); -	DUMP_REG(DC_DISP_H_PULSE0_POSITION_D); -	DUMP_REG(DC_DISP_H_PULSE1_CONTROL); -	DUMP_REG(DC_DISP_H_PULSE1_POSITION_A); -	DUMP_REG(DC_DISP_H_PULSE1_POSITION_B); -	DUMP_REG(DC_DISP_H_PULSE1_POSITION_C); -	DUMP_REG(DC_DISP_H_PULSE1_POSITION_D); -	DUMP_REG(DC_DISP_H_PULSE2_CONTROL); -	DUMP_REG(DC_DISP_H_PULSE2_POSITION_A); -	DUMP_REG(DC_DISP_H_PULSE2_POSITION_B); -	DUMP_REG(DC_DISP_H_PULSE2_POSITION_C); -	DUMP_REG(DC_DISP_H_PULSE2_POSITION_D); -	DUMP_REG(DC_DISP_V_PULSE0_CONTROL); -	DUMP_REG(DC_DISP_V_PULSE0_POSITION_A); -	DUMP_REG(DC_DISP_V_PULSE0_POSITION_B); -	DUMP_REG(DC_DISP_V_PULSE0_POSITION_C); -	DUMP_REG(DC_DISP_V_PULSE1_CONTROL); -	DUMP_REG(DC_DISP_V_PULSE1_POSITION_A); -	DUMP_REG(DC_DISP_V_PULSE1_POSITION_B); -	DUMP_REG(DC_DISP_V_PULSE1_POSITION_C); -	DUMP_REG(DC_DISP_V_PULSE2_CONTROL); -	DUMP_REG(DC_DISP_V_PULSE2_POSITION_A); -	DUMP_REG(DC_DISP_V_PULSE3_CONTROL); -	DUMP_REG(DC_DISP_V_PULSE3_POSITION_A); -	DUMP_REG(DC_DISP_M0_CONTROL); -	DUMP_REG(DC_DISP_M1_CONTROL); -	DUMP_REG(DC_DISP_DI_CONTROL); -	DUMP_REG(DC_DISP_PP_CONTROL); -	DUMP_REG(DC_DISP_PP_SELECT_A); -	DUMP_REG(DC_DISP_PP_SELECT_B); -	DUMP_REG(DC_DISP_PP_SELECT_C); -	DUMP_REG(DC_DISP_PP_SELECT_D); -	DUMP_REG(DC_DISP_DISP_CLOCK_CONTROL); -	DUMP_REG(DC_DISP_DISP_INTERFACE_CONTROL); -	DUMP_REG(DC_DISP_DISP_COLOR_CONTROL); -	DUMP_REG(DC_DISP_SHIFT_CLOCK_OPTIONS); -	DUMP_REG(DC_DISP_DATA_ENABLE_OPTIONS); -	DUMP_REG(DC_DISP_SERIAL_INTERFACE_OPTIONS); -	DUMP_REG(DC_DISP_LCD_SPI_OPTIONS); -	DUMP_REG(DC_DISP_BORDER_COLOR); -	DUMP_REG(DC_DISP_COLOR_KEY0_LOWER); -	DUMP_REG(DC_DISP_COLOR_KEY0_UPPER); -	DUMP_REG(DC_DISP_COLOR_KEY1_LOWER); -	DUMP_REG(DC_DISP_COLOR_KEY1_UPPER); -	DUMP_REG(DC_DISP_CURSOR_FOREGROUND); -	DUMP_REG(DC_DISP_CURSOR_BACKGROUND); -	DUMP_REG(DC_DISP_CURSOR_START_ADDR); -	DUMP_REG(DC_DISP_CURSOR_START_ADDR_NS); -	DUMP_REG(DC_DISP_CURSOR_POSITION); -	DUMP_REG(DC_DISP_CURSOR_POSITION_NS); -	DUMP_REG(DC_DISP_INIT_SEQ_CONTROL); -	DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_A); -	DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_B); -	DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_C); -	DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_D); -	DUMP_REG(DC_DISP_DC_MCCIF_FIFOCTRL); -	DUMP_REG(DC_DISP_MCCIF_DISPLAY0A_HYST); -	DUMP_REG(DC_DISP_MCCIF_DISPLAY0B_HYST); -	DUMP_REG(DC_DISP_MCCIF_DISPLAY1A_HYST); -	DUMP_REG(DC_DISP_MCCIF_DISPLAY1B_HYST); -	DUMP_REG(DC_DISP_DAC_CRT_CTRL); -	DUMP_REG(DC_DISP_DISP_MISC_CONTROL); -	DUMP_REG(DC_DISP_SD_CONTROL); -	DUMP_REG(DC_DISP_SD_CSC_COEFF); -	DUMP_REG(DC_DISP_SD_LUT(0)); -	DUMP_REG(DC_DISP_SD_LUT(1)); -	DUMP_REG(DC_DISP_SD_LUT(2)); -	DUMP_REG(DC_DISP_SD_LUT(3)); -	DUMP_REG(DC_DISP_SD_LUT(4)); -	DUMP_REG(DC_DISP_SD_LUT(5)); -	DUMP_REG(DC_DISP_SD_LUT(6)); -	DUMP_REG(DC_DISP_SD_LUT(7)); -	DUMP_REG(DC_DISP_SD_LUT(8)); -	DUMP_REG(DC_DISP_SD_FLICKER_CONTROL); -	DUMP_REG(DC_DISP_DC_PIXEL_COUNT); -	DUMP_REG(DC_DISP_SD_HISTOGRAM(0)); -	DUMP_REG(DC_DISP_SD_HISTOGRAM(1)); -	DUMP_REG(DC_DISP_SD_HISTOGRAM(2)); -	DUMP_REG(DC_DISP_SD_HISTOGRAM(3)); -	DUMP_REG(DC_DISP_SD_HISTOGRAM(4)); -	DUMP_REG(DC_DISP_SD_HISTOGRAM(5)); -	DUMP_REG(DC_DISP_SD_HISTOGRAM(6)); -	DUMP_REG(DC_DISP_SD_HISTOGRAM(7)); -	DUMP_REG(DC_DISP_SD_BL_TF(0)); -	DUMP_REG(DC_DISP_SD_BL_TF(1)); -	DUMP_REG(DC_DISP_SD_BL_TF(2)); -	DUMP_REG(DC_DISP_SD_BL_TF(3)); -	DUMP_REG(DC_DISP_SD_BL_CONTROL); -	DUMP_REG(DC_DISP_SD_HW_K_VALUES); -	DUMP_REG(DC_DISP_SD_MAN_K_VALUES); -	DUMP_REG(DC_WIN_WIN_OPTIONS); -	DUMP_REG(DC_WIN_BYTE_SWAP); -	DUMP_REG(DC_WIN_BUFFER_CONTROL); -	DUMP_REG(DC_WIN_COLOR_DEPTH); -	DUMP_REG(DC_WIN_POSITION); -	DUMP_REG(DC_WIN_SIZE); -	DUMP_REG(DC_WIN_PRESCALED_SIZE); -	DUMP_REG(DC_WIN_H_INITIAL_DDA); -	DUMP_REG(DC_WIN_V_INITIAL_DDA); -	DUMP_REG(DC_WIN_DDA_INC); -	DUMP_REG(DC_WIN_LINE_STRIDE); -	DUMP_REG(DC_WIN_BUF_STRIDE); -	DUMP_REG(DC_WIN_UV_BUF_STRIDE); -	DUMP_REG(DC_WIN_BUFFER_ADDR_MODE); -	DUMP_REG(DC_WIN_DV_CONTROL); -	DUMP_REG(DC_WIN_BLEND_NOKEY); -	DUMP_REG(DC_WIN_BLEND_1WIN); -	DUMP_REG(DC_WIN_BLEND_2WIN_X); -	DUMP_REG(DC_WIN_BLEND_2WIN_Y); -	DUMP_REG(DC_WIN_BLEND_3WIN_XY); -	DUMP_REG(DC_WIN_HP_FETCH_CONTROL); -	DUMP_REG(DC_WINBUF_START_ADDR); -	DUMP_REG(DC_WINBUF_START_ADDR_NS); -	DUMP_REG(DC_WINBUF_START_ADDR_U); -	DUMP_REG(DC_WINBUF_START_ADDR_U_NS); -	DUMP_REG(DC_WINBUF_START_ADDR_V); -	DUMP_REG(DC_WINBUF_START_ADDR_V_NS); -	DUMP_REG(DC_WINBUF_ADDR_H_OFFSET); -	DUMP_REG(DC_WINBUF_ADDR_H_OFFSET_NS); -	DUMP_REG(DC_WINBUF_ADDR_V_OFFSET); -	DUMP_REG(DC_WINBUF_ADDR_V_OFFSET_NS); -	DUMP_REG(DC_WINBUF_UFLOW_STATUS); -	DUMP_REG(DC_WINBUF_AD_UFLOW_STATUS); -	DUMP_REG(DC_WINBUF_BD_UFLOW_STATUS); -	DUMP_REG(DC_WINBUF_CD_UFLOW_STATUS); - -#undef DUMP_REG - -	return 0; -} - -static struct drm_info_list debugfs_files[] = { -	{ "regs", tegra_dc_show_regs, 0, NULL }, -}; - -static int tegra_dc_debugfs_init(struct tegra_dc *dc, struct drm_minor *minor) -{ -	unsigned int i; -	char *name; -	int err; - -	name = kasprintf(GFP_KERNEL, "dc.%d", dc->pipe); -	dc->debugfs = debugfs_create_dir(name, minor->debugfs_root); -	kfree(name); - -	if (!dc->debugfs) -		return -ENOMEM; - -	dc->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files), -				    GFP_KERNEL); -	if (!dc->debugfs_files) { -		err = -ENOMEM; -		goto remove; -	} - -	for (i = 0; i < ARRAY_SIZE(debugfs_files); i++) -		dc->debugfs_files[i].data = dc; - -	err = drm_debugfs_create_files(dc->debugfs_files, -				       ARRAY_SIZE(debugfs_files), -				       dc->debugfs, minor); -	if (err < 0) -		goto free; - -	dc->minor = minor; - -	return 0; - -free: -	kfree(dc->debugfs_files); -	dc->debugfs_files = NULL; -remove: -	debugfs_remove(dc->debugfs); -	dc->debugfs = NULL; - -	return err; -} - -static int tegra_dc_debugfs_exit(struct tegra_dc *dc) -{ -	drm_debugfs_remove_files(dc->debugfs_files, ARRAY_SIZE(debugfs_files), -				 dc->minor); -	dc->minor = NULL; - -	kfree(dc->debugfs_files); -	dc->debugfs_files = NULL; - -	debugfs_remove(dc->debugfs); -	dc->debugfs = NULL; - -	return 0; -} - -static int tegra_dc_drm_init(struct host1x_client *client, -			     struct drm_device *drm) -{ -	struct tegra_dc *dc = host1x_client_to_dc(client); -	int err; - -	dc->pipe = drm->mode_config.num_crtc; - -	drm_crtc_init(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); -	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); -	if (err < 0) -		return err; - -	if (IS_ENABLED(CONFIG_DEBUG_FS)) { -		err = tegra_dc_debugfs_init(dc, drm->primary); -		if (err < 0) -			dev_err(dc->dev, "debugfs setup failed: %d\n", err); -	} - -	err = devm_request_irq(dc->dev, dc->irq, tegra_dc_irq, 0, -			       dev_name(dc->dev), dc); -	if (err < 0) { -		dev_err(dc->dev, "failed to request IRQ#%u: %d\n", dc->irq, -			err); -		return err; -	} - -	return 0; -} - -static int tegra_dc_drm_exit(struct host1x_client *client) -{ -	struct tegra_dc *dc = host1x_client_to_dc(client); -	int err; - -	devm_free_irq(dc->dev, dc->irq, dc); - -	if (IS_ENABLED(CONFIG_DEBUG_FS)) { -		err = tegra_dc_debugfs_exit(dc); -		if (err < 0) -			dev_err(dc->dev, "debugfs cleanup failed: %d\n", err); -	} - -	err = tegra_dc_rgb_exit(dc); -	if (err) { -		dev_err(dc->dev, "failed to shutdown RGB output: %d\n", err); -		return err; -	} - -	return 0; -} - -static const struct host1x_client_ops dc_client_ops = { -	.drm_init = tegra_dc_drm_init, -	.drm_exit = tegra_dc_drm_exit, -}; - -static int tegra_dc_probe(struct platform_device *pdev) -{ -	struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent); -	struct resource *regs; -	struct tegra_dc *dc; -	int err; - -	dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL); -	if (!dc) -		return -ENOMEM; - -	spin_lock_init(&dc->lock); -	INIT_LIST_HEAD(&dc->list); -	dc->dev = &pdev->dev; - -	dc->clk = devm_clk_get(&pdev->dev, NULL); -	if (IS_ERR(dc->clk)) { -		dev_err(&pdev->dev, "failed to get clock\n"); -		return PTR_ERR(dc->clk); -	} - -	err = clk_prepare_enable(dc->clk); -	if (err < 0) -		return err; - -	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	dc->regs = devm_ioremap_resource(&pdev->dev, regs); -	if (IS_ERR(dc->regs)) -		return PTR_ERR(dc->regs); - -	dc->irq = platform_get_irq(pdev, 0); -	if (dc->irq < 0) { -		dev_err(&pdev->dev, "failed to get IRQ\n"); -		return -ENXIO; -	} - -	INIT_LIST_HEAD(&dc->client.list); -	dc->client.ops = &dc_client_ops; -	dc->client.dev = &pdev->dev; - -	err = tegra_dc_rgb_probe(dc); -	if (err < 0 && err != -ENODEV) { -		dev_err(&pdev->dev, "failed to probe RGB output: %d\n", err); -		return err; -	} - -	err = host1x_register_client(host1x, &dc->client); -	if (err < 0) { -		dev_err(&pdev->dev, "failed to register host1x client: %d\n", -			err); -		return err; -	} - -	platform_set_drvdata(pdev, dc); - -	return 0; -} - -static int tegra_dc_remove(struct platform_device *pdev) -{ -	struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent); -	struct tegra_dc *dc = platform_get_drvdata(pdev); -	int err; - -	err = host1x_unregister_client(host1x, &dc->client); -	if (err < 0) { -		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", -			err); -		return err; -	} - -	clk_disable_unprepare(dc->clk); - -	return 0; -} - -static struct of_device_id tegra_dc_of_match[] = { -	{ .compatible = "nvidia,tegra30-dc", }, -	{ .compatible = "nvidia,tegra20-dc", }, -	{ }, -}; - -struct platform_driver tegra_dc_driver = { -	.driver = { -		.name = "tegra-dc", -		.owner = THIS_MODULE, -		.of_match_table = tegra_dc_of_match, -	}, -	.probe = tegra_dc_probe, -	.remove = tegra_dc_remove, -}; diff --git a/drivers/gpu/host1x/drm/dc.h b/drivers/gpu/host1x/drm/dc.h deleted file mode 100644 index 79eaec9aac7..00000000000 --- a/drivers/gpu/host1x/drm/dc.h +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright (C) 2012 Avionic Design GmbH - * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef TEGRA_DC_H -#define TEGRA_DC_H 1 - -#define DC_CMD_GENERAL_INCR_SYNCPT		0x000 -#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL	0x001 -#define DC_CMD_GENERAL_INCR_SYNCPT_ERROR	0x002 -#define DC_CMD_WIN_A_INCR_SYNCPT		0x008 -#define DC_CMD_WIN_A_INCR_SYNCPT_CNTRL		0x009 -#define DC_CMD_WIN_A_INCR_SYNCPT_ERROR		0x00a -#define DC_CMD_WIN_B_INCR_SYNCPT		0x010 -#define DC_CMD_WIN_B_INCR_SYNCPT_CNTRL		0x011 -#define DC_CMD_WIN_B_INCR_SYNCPT_ERROR		0x012 -#define DC_CMD_WIN_C_INCR_SYNCPT		0x018 -#define DC_CMD_WIN_C_INCR_SYNCPT_CNTRL		0x019 -#define DC_CMD_WIN_C_INCR_SYNCPT_ERROR		0x01a -#define DC_CMD_CONT_SYNCPT_VSYNC		0x028 -#define DC_CMD_DISPLAY_COMMAND_OPTION0		0x031 -#define DC_CMD_DISPLAY_COMMAND			0x032 -#define DISP_CTRL_MODE_STOP (0 << 5) -#define DISP_CTRL_MODE_C_DISPLAY (1 << 5) -#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5) -#define DC_CMD_SIGNAL_RAISE			0x033 -#define DC_CMD_DISPLAY_POWER_CONTROL		0x036 -#define PW0_ENABLE (1 <<  0) -#define PW1_ENABLE (1 <<  2) -#define PW2_ENABLE (1 <<  4) -#define PW3_ENABLE (1 <<  6) -#define PW4_ENABLE (1 <<  8) -#define PM0_ENABLE (1 << 16) -#define PM1_ENABLE (1 << 18) - -#define DC_CMD_INT_STATUS			0x037 -#define DC_CMD_INT_MASK				0x038 -#define DC_CMD_INT_ENABLE			0x039 -#define DC_CMD_INT_TYPE				0x03a -#define DC_CMD_INT_POLARITY			0x03b -#define CTXSW_INT     (1 << 0) -#define FRAME_END_INT (1 << 1) -#define VBLANK_INT    (1 << 2) -#define WIN_A_UF_INT  (1 << 8) -#define WIN_B_UF_INT  (1 << 9) -#define WIN_C_UF_INT  (1 << 10) -#define WIN_A_OF_INT  (1 << 14) -#define WIN_B_OF_INT  (1 << 15) -#define WIN_C_OF_INT  (1 << 16) - -#define DC_CMD_SIGNAL_RAISE1			0x03c -#define DC_CMD_SIGNAL_RAISE2			0x03d -#define DC_CMD_SIGNAL_RAISE3			0x03e - -#define DC_CMD_STATE_ACCESS			0x040 -#define READ_MUX  (1 << 0) -#define WRITE_MUX (1 << 2) - -#define DC_CMD_STATE_CONTROL			0x041 -#define GENERAL_ACT_REQ (1 <<  0) -#define WIN_A_ACT_REQ   (1 <<  1) -#define WIN_B_ACT_REQ   (1 <<  2) -#define WIN_C_ACT_REQ   (1 <<  3) -#define GENERAL_UPDATE  (1 <<  8) -#define WIN_A_UPDATE    (1 <<  9) -#define WIN_B_UPDATE    (1 << 10) -#define WIN_C_UPDATE    (1 << 11) -#define NC_HOST_TRIG    (1 << 24) - -#define DC_CMD_DISPLAY_WINDOW_HEADER		0x042 -#define WINDOW_A_SELECT (1 << 4) -#define WINDOW_B_SELECT (1 << 5) -#define WINDOW_C_SELECT (1 << 6) - -#define DC_CMD_REG_ACT_CONTROL			0x043 - -#define DC_COM_CRC_CONTROL			0x300 -#define DC_COM_CRC_CHECKSUM			0x301 -#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x)) -#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x)) -#define LVS_OUTPUT_POLARITY_LOW (1 << 28) -#define LHS_OUTPUT_POLARITY_LOW (1 << 30) -#define DC_COM_PIN_OUTPUT_DATA(x) (0x30a + (x)) -#define DC_COM_PIN_INPUT_ENABLE(x) (0x30e + (x)) -#define DC_COM_PIN_INPUT_DATA(x) (0x312 + (x)) -#define DC_COM_PIN_OUTPUT_SELECT(x) (0x314 + (x)) - -#define DC_COM_PIN_MISC_CONTROL			0x31b -#define DC_COM_PIN_PM0_CONTROL			0x31c -#define DC_COM_PIN_PM0_DUTY_CYCLE		0x31d -#define DC_COM_PIN_PM1_CONTROL			0x31e -#define DC_COM_PIN_PM1_DUTY_CYCLE		0x31f - -#define DC_COM_SPI_CONTROL			0x320 -#define DC_COM_SPI_START_BYTE			0x321 -#define DC_COM_HSPI_WRITE_DATA_AB		0x322 -#define DC_COM_HSPI_WRITE_DATA_CD		0x323 -#define DC_COM_HSPI_CS_DC			0x324 -#define DC_COM_SCRATCH_REGISTER_A		0x325 -#define DC_COM_SCRATCH_REGISTER_B		0x326 -#define DC_COM_GPIO_CTRL			0x327 -#define DC_COM_GPIO_DEBOUNCE_COUNTER		0x328 -#define DC_COM_CRC_CHECKSUM_LATCHED		0x329 - -#define DC_DISP_DISP_SIGNAL_OPTIONS0		0x400 -#define H_PULSE_0_ENABLE (1 <<  8) -#define H_PULSE_1_ENABLE (1 << 10) -#define H_PULSE_2_ENABLE (1 << 12) - -#define DC_DISP_DISP_SIGNAL_OPTIONS1		0x401 - -#define DC_DISP_DISP_WIN_OPTIONS		0x402 -#define HDMI_ENABLE (1 << 30) - -#define DC_DISP_DISP_MEM_HIGH_PRIORITY		0x403 -#define CURSOR_THRESHOLD(x)   (((x) & 0x03) << 24) -#define WINDOW_A_THRESHOLD(x) (((x) & 0x7f) << 16) -#define WINDOW_B_THRESHOLD(x) (((x) & 0x7f) <<  8) -#define WINDOW_C_THRESHOLD(x) (((x) & 0xff) <<  0) - -#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER	0x404 -#define CURSOR_DELAY(x)   (((x) & 0x3f) << 24) -#define WINDOW_A_DELAY(x) (((x) & 0x3f) << 16) -#define WINDOW_B_DELAY(x) (((x) & 0x3f) <<  8) -#define WINDOW_C_DELAY(x) (((x) & 0x3f) <<  0) - -#define DC_DISP_DISP_TIMING_OPTIONS		0x405 -#define VSYNC_H_POSITION(x) ((x) & 0xfff) - -#define DC_DISP_REF_TO_SYNC			0x406 -#define DC_DISP_SYNC_WIDTH			0x407 -#define DC_DISP_BACK_PORCH			0x408 -#define DC_DISP_ACTIVE				0x409 -#define DC_DISP_FRONT_PORCH			0x40a -#define DC_DISP_H_PULSE0_CONTROL		0x40b -#define DC_DISP_H_PULSE0_POSITION_A		0x40c -#define DC_DISP_H_PULSE0_POSITION_B		0x40d -#define DC_DISP_H_PULSE0_POSITION_C		0x40e -#define DC_DISP_H_PULSE0_POSITION_D		0x40f -#define DC_DISP_H_PULSE1_CONTROL		0x410 -#define DC_DISP_H_PULSE1_POSITION_A		0x411 -#define DC_DISP_H_PULSE1_POSITION_B		0x412 -#define DC_DISP_H_PULSE1_POSITION_C		0x413 -#define DC_DISP_H_PULSE1_POSITION_D		0x414 -#define DC_DISP_H_PULSE2_CONTROL		0x415 -#define DC_DISP_H_PULSE2_POSITION_A		0x416 -#define DC_DISP_H_PULSE2_POSITION_B		0x417 -#define DC_DISP_H_PULSE2_POSITION_C		0x418 -#define DC_DISP_H_PULSE2_POSITION_D		0x419 -#define DC_DISP_V_PULSE0_CONTROL		0x41a -#define DC_DISP_V_PULSE0_POSITION_A		0x41b -#define DC_DISP_V_PULSE0_POSITION_B		0x41c -#define DC_DISP_V_PULSE0_POSITION_C		0x41d -#define DC_DISP_V_PULSE1_CONTROL		0x41e -#define DC_DISP_V_PULSE1_POSITION_A		0x41f -#define DC_DISP_V_PULSE1_POSITION_B		0x420 -#define DC_DISP_V_PULSE1_POSITION_C		0x421 -#define DC_DISP_V_PULSE2_CONTROL		0x422 -#define DC_DISP_V_PULSE2_POSITION_A		0x423 -#define DC_DISP_V_PULSE3_CONTROL		0x424 -#define DC_DISP_V_PULSE3_POSITION_A		0x425 -#define DC_DISP_M0_CONTROL			0x426 -#define DC_DISP_M1_CONTROL			0x427 -#define DC_DISP_DI_CONTROL			0x428 -#define DC_DISP_PP_CONTROL			0x429 -#define DC_DISP_PP_SELECT_A			0x42a -#define DC_DISP_PP_SELECT_B			0x42b -#define DC_DISP_PP_SELECT_C			0x42c -#define DC_DISP_PP_SELECT_D			0x42d - -#define PULSE_MODE_NORMAL    (0 << 3) -#define PULSE_MODE_ONE_CLOCK (1 << 3) -#define PULSE_POLARITY_HIGH  (0 << 4) -#define PULSE_POLARITY_LOW   (1 << 4) -#define PULSE_QUAL_ALWAYS    (0 << 6) -#define PULSE_QUAL_VACTIVE   (2 << 6) -#define PULSE_QUAL_VACTIVE1  (3 << 6) -#define PULSE_LAST_START_A   (0 << 8) -#define PULSE_LAST_END_A     (1 << 8) -#define PULSE_LAST_START_B   (2 << 8) -#define PULSE_LAST_END_B     (3 << 8) -#define PULSE_LAST_START_C   (4 << 8) -#define PULSE_LAST_END_C     (5 << 8) -#define PULSE_LAST_START_D   (6 << 8) -#define PULSE_LAST_END_D     (7 << 8) - -#define PULSE_START(x) (((x) & 0xfff) <<  0) -#define PULSE_END(x)   (((x) & 0xfff) << 16) - -#define DC_DISP_DISP_CLOCK_CONTROL		0x42e -#define PIXEL_CLK_DIVIDER_PCD1  (0 << 8) -#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8) -#define PIXEL_CLK_DIVIDER_PCD2  (2 << 8) -#define PIXEL_CLK_DIVIDER_PCD3  (3 << 8) -#define PIXEL_CLK_DIVIDER_PCD4  (4 << 8) -#define PIXEL_CLK_DIVIDER_PCD6  (5 << 8) -#define PIXEL_CLK_DIVIDER_PCD8  (6 << 8) -#define PIXEL_CLK_DIVIDER_PCD9  (7 << 8) -#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8) -#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8) -#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8) -#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8) -#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8) -#define SHIFT_CLK_DIVIDER(x)    ((x) & 0xff) - -#define DC_DISP_DISP_INTERFACE_CONTROL		0x42f -#define DISP_DATA_FORMAT_DF1P1C    (0 << 0) -#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0) -#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0) -#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0) -#define DISP_DATA_FORMAT_DF2S      (4 << 0) -#define DISP_DATA_FORMAT_DF3S      (5 << 0) -#define DISP_DATA_FORMAT_DFSPI     (6 << 0) -#define DISP_DATA_FORMAT_DF1P3C24B (7 << 0) -#define DISP_DATA_FORMAT_DF1P3C18B (8 << 0) -#define DISP_ALIGNMENT_MSB         (0 << 8) -#define DISP_ALIGNMENT_LSB         (1 << 8) -#define DISP_ORDER_RED_BLUE        (0 << 9) -#define DISP_ORDER_BLUE_RED        (1 << 9) - -#define DC_DISP_DISP_COLOR_CONTROL		0x430 -#define BASE_COLOR_SIZE666     (0 << 0) -#define BASE_COLOR_SIZE111     (1 << 0) -#define BASE_COLOR_SIZE222     (2 << 0) -#define BASE_COLOR_SIZE333     (3 << 0) -#define BASE_COLOR_SIZE444     (4 << 0) -#define BASE_COLOR_SIZE555     (5 << 0) -#define BASE_COLOR_SIZE565     (6 << 0) -#define BASE_COLOR_SIZE332     (7 << 0) -#define BASE_COLOR_SIZE888     (8 << 0) -#define DITHER_CONTROL_DISABLE (0 << 8) -#define DITHER_CONTROL_ORDERED (2 << 8) -#define DITHER_CONTROL_ERRDIFF (3 << 8) - -#define DC_DISP_SHIFT_CLOCK_OPTIONS		0x431 - -#define DC_DISP_DATA_ENABLE_OPTIONS		0x432 -#define DE_SELECT_ACTIVE_BLANK  (0 << 0) -#define DE_SELECT_ACTIVE        (1 << 0) -#define DE_SELECT_ACTIVE_IS     (2 << 0) -#define DE_CONTROL_ONECLK       (0 << 2) -#define DE_CONTROL_NORMAL       (1 << 2) -#define DE_CONTROL_EARLY_EXT    (2 << 2) -#define DE_CONTROL_EARLY        (3 << 2) -#define DE_CONTROL_ACTIVE_BLANK (4 << 2) - -#define DC_DISP_SERIAL_INTERFACE_OPTIONS	0x433 -#define DC_DISP_LCD_SPI_OPTIONS			0x434 -#define DC_DISP_BORDER_COLOR			0x435 -#define DC_DISP_COLOR_KEY0_LOWER		0x436 -#define DC_DISP_COLOR_KEY0_UPPER		0x437 -#define DC_DISP_COLOR_KEY1_LOWER		0x438 -#define DC_DISP_COLOR_KEY1_UPPER		0x439 - -#define DC_DISP_CURSOR_FOREGROUND		0x43c -#define DC_DISP_CURSOR_BACKGROUND		0x43d - -#define DC_DISP_CURSOR_START_ADDR		0x43e -#define DC_DISP_CURSOR_START_ADDR_NS		0x43f - -#define DC_DISP_CURSOR_POSITION			0x440 -#define DC_DISP_CURSOR_POSITION_NS		0x441 - -#define DC_DISP_INIT_SEQ_CONTROL		0x442 -#define DC_DISP_SPI_INIT_SEQ_DATA_A		0x443 -#define DC_DISP_SPI_INIT_SEQ_DATA_B		0x444 -#define DC_DISP_SPI_INIT_SEQ_DATA_C		0x445 -#define DC_DISP_SPI_INIT_SEQ_DATA_D		0x446 - -#define DC_DISP_DC_MCCIF_FIFOCTRL		0x480 -#define DC_DISP_MCCIF_DISPLAY0A_HYST		0x481 -#define DC_DISP_MCCIF_DISPLAY0B_HYST		0x482 -#define DC_DISP_MCCIF_DISPLAY1A_HYST		0x483 -#define DC_DISP_MCCIF_DISPLAY1B_HYST		0x484 - -#define DC_DISP_DAC_CRT_CTRL			0x4c0 -#define DC_DISP_DISP_MISC_CONTROL		0x4c1 -#define DC_DISP_SD_CONTROL			0x4c2 -#define DC_DISP_SD_CSC_COEFF			0x4c3 -#define DC_DISP_SD_LUT(x)			(0x4c4 + (x)) -#define DC_DISP_SD_FLICKER_CONTROL		0x4cd -#define DC_DISP_DC_PIXEL_COUNT			0x4ce -#define DC_DISP_SD_HISTOGRAM(x)			(0x4cf + (x)) -#define DC_DISP_SD_BL_PARAMETERS		0x4d7 -#define DC_DISP_SD_BL_TF(x)			(0x4d8 + (x)) -#define DC_DISP_SD_BL_CONTROL			0x4dc -#define DC_DISP_SD_HW_K_VALUES			0x4dd -#define DC_DISP_SD_MAN_K_VALUES			0x4de - -#define DC_WIN_CSC_YOF				0x611 -#define DC_WIN_CSC_KYRGB			0x612 -#define DC_WIN_CSC_KUR				0x613 -#define DC_WIN_CSC_KVR				0x614 -#define DC_WIN_CSC_KUG				0x615 -#define DC_WIN_CSC_KVG				0x616 -#define DC_WIN_CSC_KUB				0x617 -#define DC_WIN_CSC_KVB				0x618 - -#define DC_WIN_WIN_OPTIONS			0x700 -#define COLOR_EXPAND (1 <<  6) -#define CSC_ENABLE   (1 << 18) -#define WIN_ENABLE   (1 << 30) - -#define DC_WIN_BYTE_SWAP			0x701 -#define BYTE_SWAP_NOSWAP  (0 << 0) -#define BYTE_SWAP_SWAP2   (1 << 0) -#define BYTE_SWAP_SWAP4   (2 << 0) -#define BYTE_SWAP_SWAP4HW (3 << 0) - -#define DC_WIN_BUFFER_CONTROL			0x702 -#define BUFFER_CONTROL_HOST  (0 << 0) -#define BUFFER_CONTROL_VI    (1 << 0) -#define BUFFER_CONTROL_EPP   (2 << 0) -#define BUFFER_CONTROL_MPEGE (3 << 0) -#define BUFFER_CONTROL_SB2D  (4 << 0) - -#define DC_WIN_COLOR_DEPTH			0x703 -#define WIN_COLOR_DEPTH_P1              0 -#define WIN_COLOR_DEPTH_P2              1 -#define WIN_COLOR_DEPTH_P4              2 -#define WIN_COLOR_DEPTH_P8              3 -#define WIN_COLOR_DEPTH_B4G4R4A4        4 -#define WIN_COLOR_DEPTH_B5G5R5A         5 -#define WIN_COLOR_DEPTH_B5G6R5          6 -#define WIN_COLOR_DEPTH_AB5G5R5         7 -#define WIN_COLOR_DEPTH_B8G8R8A8       12 -#define WIN_COLOR_DEPTH_R8G8B8A8       13 -#define WIN_COLOR_DEPTH_B6x2G6x2R6x2A8 14 -#define WIN_COLOR_DEPTH_R6x2G6x2B6x2A8 15 -#define WIN_COLOR_DEPTH_YCbCr422       16 -#define WIN_COLOR_DEPTH_YUV422         17 -#define WIN_COLOR_DEPTH_YCbCr420P      18 -#define WIN_COLOR_DEPTH_YUV420P        19 -#define WIN_COLOR_DEPTH_YCbCr422P      20 -#define WIN_COLOR_DEPTH_YUV422P        21 -#define WIN_COLOR_DEPTH_YCbCr422R      22 -#define WIN_COLOR_DEPTH_YUV422R        23 -#define WIN_COLOR_DEPTH_YCbCr422RA     24 -#define WIN_COLOR_DEPTH_YUV422RA       25 - -#define DC_WIN_POSITION				0x704 -#define H_POSITION(x) (((x) & 0x1fff) <<  0) -#define V_POSITION(x) (((x) & 0x1fff) << 16) - -#define DC_WIN_SIZE				0x705 -#define H_SIZE(x) (((x) & 0x1fff) <<  0) -#define V_SIZE(x) (((x) & 0x1fff) << 16) - -#define DC_WIN_PRESCALED_SIZE			0x706 -#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) <<  0) -#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16) - -#define DC_WIN_H_INITIAL_DDA			0x707 -#define DC_WIN_V_INITIAL_DDA			0x708 -#define DC_WIN_DDA_INC				0x709 -#define H_DDA_INC(x) (((x) & 0xffff) <<  0) -#define V_DDA_INC(x) (((x) & 0xffff) << 16) - -#define DC_WIN_LINE_STRIDE			0x70a -#define DC_WIN_BUF_STRIDE			0x70b -#define DC_WIN_UV_BUF_STRIDE			0x70c -#define DC_WIN_BUFFER_ADDR_MODE			0x70d -#define DC_WIN_DV_CONTROL			0x70e - -#define DC_WIN_BLEND_NOKEY			0x70f -#define DC_WIN_BLEND_1WIN			0x710 -#define DC_WIN_BLEND_2WIN_X			0x711 -#define DC_WIN_BLEND_2WIN_Y			0x712 -#define DC_WIN_BLEND_3WIN_XY			0x713 - -#define DC_WIN_HP_FETCH_CONTROL			0x714 - -#define DC_WINBUF_START_ADDR			0x800 -#define DC_WINBUF_START_ADDR_NS			0x801 -#define DC_WINBUF_START_ADDR_U			0x802 -#define DC_WINBUF_START_ADDR_U_NS		0x803 -#define DC_WINBUF_START_ADDR_V			0x804 -#define DC_WINBUF_START_ADDR_V_NS		0x805 - -#define DC_WINBUF_ADDR_H_OFFSET			0x806 -#define DC_WINBUF_ADDR_H_OFFSET_NS		0x807 -#define DC_WINBUF_ADDR_V_OFFSET			0x808 -#define DC_WINBUF_ADDR_V_OFFSET_NS		0x809 - -#define DC_WINBUF_UFLOW_STATUS			0x80a - -#define DC_WINBUF_AD_UFLOW_STATUS		0xbca -#define DC_WINBUF_BD_UFLOW_STATUS		0xdca -#define DC_WINBUF_CD_UFLOW_STATUS		0xfca - -/* synchronization points */ -#define SYNCPT_VBLANK0 26 -#define SYNCPT_VBLANK1 27 - -#endif /* TEGRA_DC_H */ diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c deleted file mode 100644 index 8c61ceeaa12..00000000000 --- a/drivers/gpu/host1x/drm/drm.c +++ /dev/null @@ -1,647 +0,0 @@ -/* - * Copyright (C) 2012 Avionic Design GmbH - * Copyright (C) 2012-2013 NVIDIA CORPORATION.  All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#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" -#include "gem.h" -#include "syncpt.h" - -#define DRIVER_NAME "tegra" -#define DRIVER_DESC "NVIDIA Tegra graphics" -#define DRIVER_DATE "20120330" -#define DRIVER_MAJOR 0 -#define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 0 - -struct host1x_drm_client { -	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) -{ -	struct host1x_drm_client *client; - -	client = kzalloc(sizeof(*client), GFP_KERNEL); -	if (!client) -		return -ENOMEM; - -	INIT_LIST_HEAD(&client->list); -	client->np = of_node_get(np); - -	list_add_tail(&client->list, &host1x->drm_clients); - -	return 0; -} - -static int host1x_activate_drm_client(struct host1x_drm *host1x, -				      struct host1x_drm_client *drm, -				      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); - -	return 0; -} - -static int host1x_remove_drm_client(struct host1x_drm *host1x, -				    struct host1x_drm_client *client) -{ -	mutex_lock(&host1x->drm_clients_lock); -	list_del_init(&client->list); -	mutex_unlock(&host1x->drm_clients_lock); - -	of_node_put(client->np); -	kfree(client); - -	return 0; -} - -static int host1x_parse_dt(struct host1x_drm *host1x) -{ -	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(host1x->dev->of_node, np) { -			if (of_device_is_compatible(np, compat[i]) && -			    of_device_is_available(np)) { -				err = host1x_add_drm_client(host1x, np); -				if (err < 0) -					return err; -			} -		} -	} - -	return 0; -} - -int host1x_drm_alloc(struct platform_device *pdev) -{ -	struct host1x_drm *host1x; -	int err; - -	host1x = devm_kzalloc(&pdev->dev, sizeof(*host1x), GFP_KERNEL); -	if (!host1x) -		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; - -	err = host1x_parse_dt(host1x); -	if (err < 0) { -		dev_err(&pdev->dev, "failed to parse DT: %d\n", err); -		return err; -	} - -	host1x_set_drm_data(&pdev->dev, host1x); - -	return 0; -} - -int host1x_drm_init(struct host1x_drm *host1x, struct drm_device *drm) -{ -	struct host1x_client *client; - -	mutex_lock(&host1x->clients_lock); - -	list_for_each_entry(client, &host1x->clients, list) { -		if (client->ops && client->ops->drm_init) { -			int err = client->ops->drm_init(client, drm); -			if (err < 0) { -				dev_err(host1x->dev, -					"DRM setup failed for %s: %d\n", -					dev_name(client->dev), err); -				mutex_unlock(&host1x->clients_lock); -				return err; -			} -		} -	} - -	mutex_unlock(&host1x->clients_lock); - -	return 0; -} - -int host1x_drm_exit(struct host1x_drm *host1x) -{ -	struct platform_device *pdev = to_platform_device(host1x->dev); -	struct host1x_client *client; - -	if (!host1x->drm) -		return 0; - -	mutex_lock(&host1x->clients_lock); - -	list_for_each_entry_reverse(client, &host1x->clients, list) { -		if (client->ops && client->ops->drm_exit) { -			int err = client->ops->drm_exit(client); -			if (err < 0) { -				dev_err(host1x->dev, -					"DRM cleanup failed for %s: %d\n", -					dev_name(client->dev), err); -				mutex_unlock(&host1x->clients_lock); -				return err; -			} -		} -	} - -	mutex_unlock(&host1x->clients_lock); - -	drm_platform_exit(&tegra_drm_driver, pdev); -	host1x->drm = NULL; - -	return 0; -} - -int host1x_register_client(struct host1x_drm *host1x, -			   struct host1x_client *client) -{ -	struct host1x_drm_client *drm, *tmp; -	int err; - -	mutex_lock(&host1x->clients_lock); -	list_add_tail(&client->list, &host1x->clients); -	mutex_unlock(&host1x->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); - -	if (list_empty(&host1x->drm_clients)) { -		struct platform_device *pdev = to_platform_device(host1x->dev); - -		err = drm_platform_init(&tegra_drm_driver, pdev); -		if (err < 0) { -			dev_err(host1x->dev, "drm_platform_init(): %d\n", err); -			return err; -		} -	} - -	return 0; -} - -int host1x_unregister_client(struct host1x_drm *host1x, -			     struct host1x_client *client) -{ -	struct host1x_drm_client *drm, *tmp; -	int err; - -	list_for_each_entry_safe(drm, tmp, &host1x->drm_active, list) { -		if (drm->client == client) { -			err = host1x_drm_exit(host1x); -			if (err < 0) { -				dev_err(host1x->dev, "host1x_drm_exit(): %d\n", -					err); -				return err; -			} - -			host1x_remove_drm_client(host1x, drm); -			break; -		} -	} - -	mutex_lock(&host1x->clients_lock); -	list_del_init(&client->list); -	mutex_unlock(&host1x->clients_lock); - -	return 0; -} - -static int tegra_drm_load(struct drm_device *drm, unsigned long flags) -{ -	struct host1x_drm *host1x; -	int err; - -	host1x = host1x_get_drm_data(drm->dev); -	drm->dev_private = host1x; -	host1x->drm = drm; - -	drm_mode_config_init(drm); - -	err = host1x_drm_init(host1x, drm); -	if (err < 0) -		return err; - -	/* -	 * We don't use the drm_irq_install() helpers provided by the DRM -	 * core, so we need to set this manually in order to allow the -	 * DRM_IOCTL_WAIT_VBLANK to operate correctly. -	 */ -	drm->irq_enabled = 1; - -	err = drm_vblank_init(drm, drm->mode_config.num_crtc); -	if (err < 0) -		return err; - -	err = tegra_drm_fb_init(drm); -	if (err < 0) -		return err; - -	drm_kms_helper_poll_init(drm); - -	return 0; -} - -static int tegra_drm_unload(struct drm_device *drm) -{ -	drm_kms_helper_poll_fini(drm); -	tegra_drm_fb_exit(drm); - -	drm_mode_config_cleanup(drm); - -	return 0; -} - -static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp) -{ -	struct host1x_drm_file *fpriv; - -	fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL); -	if (!fpriv) -		return -ENOMEM; - -	INIT_LIST_HEAD(&fpriv->contexts); -	filp->driver_priv = fpriv; - -	return 0; -} - -static void host1x_drm_context_free(struct host1x_drm_context *context) -{ -	context->client->ops->close_channel(context); -	kfree(context); -} - -static void tegra_drm_lastclose(struct drm_device *drm) -{ -	struct host1x_drm *host1x = drm->dev_private; - -	tegra_fbdev_restore_mode(host1x->fbdev); -} - -#ifdef CONFIG_DRM_TEGRA_STAGING -static bool host1x_drm_file_owns_context(struct host1x_drm_file *file, -					 struct host1x_drm_context *context) -{ -	struct host1x_drm_context *ctx; - -	list_for_each_entry(ctx, &file->contexts, list) -		if (ctx == context) -			return true; - -	return false; -} - -static int tegra_gem_create(struct drm_device *drm, void *data, -			    struct drm_file *file) -{ -	struct drm_tegra_gem_create *args = data; -	struct tegra_bo *bo; - -	bo = tegra_bo_create_with_handle(file, drm, args->size, -					 &args->handle); -	if (IS_ERR(bo)) -		return PTR_ERR(bo); - -	return 0; -} - -static int tegra_gem_mmap(struct drm_device *drm, void *data, -			  struct drm_file *file) -{ -	struct drm_tegra_gem_mmap *args = data; -	struct drm_gem_object *gem; -	struct tegra_bo *bo; - -	gem = drm_gem_object_lookup(drm, file, args->handle); -	if (!gem) -		return -EINVAL; - -	bo = to_tegra_bo(gem); - -	args->offset = drm_vma_node_offset_addr(&bo->gem.vma_node); - -	drm_gem_object_unreference(gem); - -	return 0; -} - -static int tegra_syncpt_read(struct drm_device *drm, void *data, -			     struct drm_file *file) -{ -	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); - -	if (!sp) -		return -EINVAL; - -	args->value = host1x_syncpt_read_min(sp); -	return 0; -} - -static int tegra_syncpt_incr(struct drm_device *drm, void *data, -			     struct drm_file *file) -{ -	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); - -	if (!sp) -		return -EINVAL; - -	return host1x_syncpt_incr(sp); -} - -static int tegra_syncpt_wait(struct drm_device *drm, void *data, -			     struct drm_file *file) -{ -	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); - -	if (!sp) -		return -EINVAL; - -	return host1x_syncpt_wait(sp, args->thresh, args->timeout, -				  &args->value); -} - -static int tegra_open_channel(struct drm_device *drm, void *data, -			      struct drm_file *file) -{ -	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; -	int err = -ENODEV; - -	context = kzalloc(sizeof(*context), GFP_KERNEL); -	if (!context) -		return -ENOMEM; - -	list_for_each_entry(client, &host1x->clients, list) -		if (client->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; -			return 0; -		} - -	kfree(context); -	return err; -} - -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 host1x_drm_context *context = -		(struct host1x_drm_context *)(uintptr_t)args->context; - -	if (!host1x_drm_file_owns_context(fpriv, context)) -		return -EINVAL; - -	list_del(&context->list); -	host1x_drm_context_free(context); - -	return 0; -} - -static int tegra_get_syncpt(struct drm_device *drm, void *data, -			    struct drm_file *file) -{ -	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)) -		return -ENODEV; - -	if (args->index >= context->client->num_syncpts) -		return -EINVAL; - -	syncpt = context->client->syncpts[args->index]; -	args->id = host1x_syncpt_id(syncpt); - -	return 0; -} - -static int tegra_submit(struct drm_device *drm, void *data, -			struct drm_file *file) -{ -	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)) -		return -ENODEV; - -	return context->client->ops->submit(context, args, drm, file); -} -#endif - -static const struct drm_ioctl_desc tegra_drm_ioctls[] = { -#ifdef CONFIG_DRM_TEGRA_STAGING -	DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED | DRM_AUTH), -	DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED), -	DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, DRM_UNLOCKED), -	DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, DRM_UNLOCKED), -	DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT, tegra_syncpt_wait, DRM_UNLOCKED), -	DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL, tegra_open_channel, DRM_UNLOCKED), -	DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL, tegra_close_channel, DRM_UNLOCKED), -	DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED), -	DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED), -#endif -}; - -static const struct file_operations tegra_drm_fops = { -	.owner = THIS_MODULE, -	.open = drm_open, -	.release = drm_release, -	.unlocked_ioctl = drm_ioctl, -	.mmap = tegra_drm_mmap, -	.poll = drm_poll, -	.read = drm_read, -#ifdef CONFIG_COMPAT -	.compat_ioctl = drm_compat_ioctl, -#endif -	.llseek = noop_llseek, -}; - -static struct drm_crtc *tegra_crtc_from_pipe(struct drm_device *drm, int pipe) -{ -	struct drm_crtc *crtc; - -	list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) { -		struct tegra_dc *dc = to_tegra_dc(crtc); - -		if (dc->pipe == pipe) -			return crtc; -	} - -	return NULL; -} - -static u32 tegra_drm_get_vblank_counter(struct drm_device *dev, int crtc) -{ -	/* TODO: implement real hardware counter using syncpoints */ -	return drm_vblank_count(dev, crtc); -} - -static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe) -{ -	struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe); -	struct tegra_dc *dc = to_tegra_dc(crtc); - -	if (!crtc) -		return -ENODEV; - -	tegra_dc_enable_vblank(dc); - -	return 0; -} - -static void tegra_drm_disable_vblank(struct drm_device *drm, int pipe) -{ -	struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe); -	struct tegra_dc *dc = to_tegra_dc(crtc); - -	if (crtc) -		tegra_dc_disable_vblank(dc); -} - -static void tegra_drm_preclose(struct drm_device *drm, struct drm_file *file) -{ -	struct host1x_drm_file *fpriv = file->driver_priv; -	struct host1x_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); - -	kfree(fpriv); -} - -#ifdef CONFIG_DEBUG_FS -static int tegra_debugfs_framebuffers(struct seq_file *s, void *data) -{ -	struct drm_info_node *node = (struct drm_info_node *)s->private; -	struct drm_device *drm = node->minor->dev; -	struct drm_framebuffer *fb; - -	mutex_lock(&drm->mode_config.fb_lock); - -	list_for_each_entry(fb, &drm->mode_config.fb_list, head) { -		seq_printf(s, "%3d: user size: %d x %d, depth %d, %d bpp, refcount %d\n", -			   fb->base.id, fb->width, fb->height, fb->depth, -			   fb->bits_per_pixel, -			   atomic_read(&fb->refcount.refcount)); -	} - -	mutex_unlock(&drm->mode_config.fb_lock); - -	return 0; -} - -static struct drm_info_list tegra_debugfs_list[] = { -	{ "framebuffers", tegra_debugfs_framebuffers, 0 }, -}; - -static int tegra_debugfs_init(struct drm_minor *minor) -{ -	return drm_debugfs_create_files(tegra_debugfs_list, -					ARRAY_SIZE(tegra_debugfs_list), -					minor->debugfs_root, minor); -} - -static void tegra_debugfs_cleanup(struct drm_minor *minor) -{ -	drm_debugfs_remove_files(tegra_debugfs_list, -				 ARRAY_SIZE(tegra_debugfs_list), minor); -} -#endif - -struct drm_driver tegra_drm_driver = { -	.driver_features = DRIVER_MODESET | DRIVER_GEM, -	.load = tegra_drm_load, -	.unload = tegra_drm_unload, -	.open = tegra_drm_open, -	.preclose = tegra_drm_preclose, -	.lastclose = tegra_drm_lastclose, - -	.get_vblank_counter = tegra_drm_get_vblank_counter, -	.enable_vblank = tegra_drm_enable_vblank, -	.disable_vblank = tegra_drm_disable_vblank, - -#if defined(CONFIG_DEBUG_FS) -	.debugfs_init = tegra_debugfs_init, -	.debugfs_cleanup = tegra_debugfs_cleanup, -#endif - -	.gem_free_object = tegra_bo_free_object, -	.gem_vm_ops = &tegra_bo_vm_ops, -	.dumb_create = tegra_bo_dumb_create, -	.dumb_map_offset = tegra_bo_dumb_map_offset, -	.dumb_destroy = drm_gem_dumb_destroy, - -	.ioctls = tegra_drm_ioctls, -	.num_ioctls = ARRAY_SIZE(tegra_drm_ioctls), -	.fops = &tegra_drm_fops, - -	.name = DRIVER_NAME, -	.desc = DRIVER_DESC, -	.date = DRIVER_DATE, -	.major = DRIVER_MAJOR, -	.minor = DRIVER_MINOR, -	.patchlevel = DRIVER_PATCHLEVEL, -}; diff --git a/drivers/gpu/host1x/drm/drm.h b/drivers/gpu/host1x/drm/drm.h deleted file mode 100644 index 02ce020f257..00000000000 --- a/drivers/gpu/host1x/drm/drm.h +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright (C) 2012 Avionic Design GmbH - * Copyright (C) 2012-2013 NVIDIA CORPORATION.  All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef HOST1X_DRM_H -#define HOST1X_DRM_H 1 - -#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; -	struct tegra_bo **planes; -	unsigned int num_planes; -}; - -struct tegra_fbdev { -	struct drm_fb_helper base; -	struct tegra_fb *fb; -}; - -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; -	struct list_head drm_active; - -	struct mutex clients_lock; -	struct list_head clients; - -	struct tegra_fbdev *fbdev; -}; - -struct host1x_client; - -struct host1x_drm_context { -	struct host1x_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 host1x_drm_context *context); -	void (*close_channel)(struct host1x_drm_context *context); -	int (*submit)(struct host1x_drm_context *context, -		      struct drm_tegra_submit *args, struct drm_device *drm, -		      struct drm_file *file); -}; - -struct host1x_drm_file { -	struct list_head contexts; -}; - -struct host1x_client { -	struct host1x_drm *host1x; -	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 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 host1x_register_client(struct host1x_drm *host1x, -				  struct host1x_client *client); -extern int host1x_unregister_client(struct host1x_drm *host1x, -				    struct host1x_client *client); - -struct tegra_output; - -struct tegra_dc { -	struct host1x_client client; -	spinlock_t lock; - -	struct host1x_drm *host1x; -	struct device *dev; - -	struct drm_crtc base; -	int pipe; - -	struct clk *clk; - -	void __iomem *regs; -	int irq; - -	struct tegra_output *rgb; - -	struct list_head list; - -	struct drm_info_list *debugfs_files; -	struct drm_minor *minor; -	struct dentry *debugfs; - -	/* page-flip handling */ -	struct drm_pending_vblank_event *event; -}; - -static inline struct tegra_dc *host1x_client_to_dc(struct host1x_client *client) -{ -	return container_of(client, struct tegra_dc, client); -} - -static inline struct tegra_dc *to_tegra_dc(struct drm_crtc *crtc) -{ -	return container_of(crtc, struct tegra_dc, base); -} - -static inline void tegra_dc_writel(struct tegra_dc *dc, unsigned long value, -				   unsigned long reg) -{ -	writel(value, dc->regs + (reg << 2)); -} - -static inline unsigned long tegra_dc_readl(struct tegra_dc *dc, -					   unsigned long reg) -{ -	return readl(dc->regs + (reg << 2)); -} - -struct tegra_dc_window { -	struct { -		unsigned int x; -		unsigned int y; -		unsigned int w; -		unsigned int h; -	} src; -	struct { -		unsigned int x; -		unsigned int y; -		unsigned int w; -		unsigned int h; -	} dst; -	unsigned int bits_per_pixel; -	unsigned int format; -	unsigned int stride[2]; -	unsigned long base[3]; -}; - -/* from dc.c */ -extern unsigned int tegra_dc_format(uint32_t format); -extern int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, -				 const struct tegra_dc_window *window); -extern void tegra_dc_enable_vblank(struct tegra_dc *dc); -extern void tegra_dc_disable_vblank(struct tegra_dc *dc); -extern void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, -				      struct drm_file *file); - -struct tegra_output_ops { -	int (*enable)(struct tegra_output *output); -	int (*disable)(struct tegra_output *output); -	int (*setup_clock)(struct tegra_output *output, struct clk *clk, -			   unsigned long pclk); -	int (*check_mode)(struct tegra_output *output, -			  struct drm_display_mode *mode, -			  enum drm_mode_status *status); -}; - -enum tegra_output_type { -	TEGRA_OUTPUT_RGB, -	TEGRA_OUTPUT_HDMI, -}; - -struct tegra_output { -	struct device_node *of_node; -	struct device *dev; - -	const struct tegra_output_ops *ops; -	enum tegra_output_type type; - -	struct i2c_adapter *ddc; -	const struct edid *edid; -	unsigned int hpd_irq; -	int hpd_gpio; - -	struct drm_encoder encoder; -	struct drm_connector connector; -}; - -static inline struct tegra_output *encoder_to_output(struct drm_encoder *e) -{ -	return container_of(e, struct tegra_output, encoder); -} - -static inline struct tegra_output *connector_to_output(struct drm_connector *c) -{ -	return container_of(c, struct tegra_output, connector); -} - -static inline int tegra_output_enable(struct tegra_output *output) -{ -	if (output && output->ops && output->ops->enable) -		return output->ops->enable(output); - -	return output ? -ENOSYS : -EINVAL; -} - -static inline int tegra_output_disable(struct tegra_output *output) -{ -	if (output && output->ops && output->ops->disable) -		return output->ops->disable(output); - -	return output ? -ENOSYS : -EINVAL; -} - -static inline int tegra_output_setup_clock(struct tegra_output *output, -					   struct clk *clk, unsigned long pclk) -{ -	if (output && output->ops && output->ops->setup_clock) -		return output->ops->setup_clock(output, clk, pclk); - -	return output ? -ENOSYS : -EINVAL; -} - -static inline int tegra_output_check_mode(struct tegra_output *output, -					  struct drm_display_mode *mode, -					  enum drm_mode_status *status) -{ -	if (output && output->ops && output->ops->check_mode) -		return output->ops->check_mode(output, mode, status); - -	return output ? -ENOSYS : -EINVAL; -} - -/* 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); -extern int tegra_dc_rgb_exit(struct tegra_dc *dc); - -/* from output.c */ -extern int tegra_output_parse_dt(struct tegra_output *output); -extern int tegra_output_init(struct drm_device *drm, struct tegra_output *output); -extern int tegra_output_exit(struct tegra_output *output); - -/* from fb.c */ -struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, -				    unsigned int index); -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; - -#endif /* HOST1X_DRM_H */ diff --git a/drivers/gpu/host1x/drm/fb.c b/drivers/gpu/host1x/drm/fb.c deleted file mode 100644 index 979a3e32b78..00000000000 --- a/drivers/gpu/host1x/drm/fb.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright (C) 2012-2013 Avionic Design GmbH - * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved. - * - * Based on the KMS/FB CMA helpers - *   Copyright (C) 2012 Analog Device Inc. - * - * 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 <linux/module.h> - -#include "drm.h" -#include "gem.h" - -static inline struct tegra_fb *to_tegra_fb(struct drm_framebuffer *fb) -{ -	return container_of(fb, struct tegra_fb, base); -} - -static inline struct tegra_fbdev *to_tegra_fbdev(struct drm_fb_helper *helper) -{ -	return container_of(helper, struct tegra_fbdev, base); -} - -struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, -				    unsigned int index) -{ -	struct tegra_fb *fb = to_tegra_fb(framebuffer); - -	if (index >= drm_format_num_planes(framebuffer->pixel_format)) -		return NULL; - -	return fb->planes[index]; -} - -static void tegra_fb_destroy(struct drm_framebuffer *framebuffer) -{ -	struct tegra_fb *fb = to_tegra_fb(framebuffer); -	unsigned int i; - -	for (i = 0; i < fb->num_planes; i++) { -		struct tegra_bo *bo = fb->planes[i]; - -		if (bo) -			drm_gem_object_unreference_unlocked(&bo->gem); -	} - -	drm_framebuffer_cleanup(framebuffer); -	kfree(fb->planes); -	kfree(fb); -} - -static int tegra_fb_create_handle(struct drm_framebuffer *framebuffer, -				  struct drm_file *file, unsigned int *handle) -{ -	struct tegra_fb *fb = to_tegra_fb(framebuffer); - -	return drm_gem_handle_create(file, &fb->planes[0]->gem, handle); -} - -static struct drm_framebuffer_funcs tegra_fb_funcs = { -	.destroy = tegra_fb_destroy, -	.create_handle = tegra_fb_create_handle, -}; - -static struct tegra_fb *tegra_fb_alloc(struct drm_device *drm, -				       struct drm_mode_fb_cmd2 *mode_cmd, -				       struct tegra_bo **planes, -				       unsigned int num_planes) -{ -	struct tegra_fb *fb; -	unsigned int i; -	int err; - -	fb = kzalloc(sizeof(*fb), GFP_KERNEL); -	if (!fb) -		return ERR_PTR(-ENOMEM); - -	fb->planes = kzalloc(num_planes * sizeof(*planes), GFP_KERNEL); -	if (!fb->planes) -		return ERR_PTR(-ENOMEM); - -	fb->num_planes = num_planes; - -	drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd); - -	for (i = 0; i < fb->num_planes; i++) -		fb->planes[i] = planes[i]; - -	err = drm_framebuffer_init(drm, &fb->base, &tegra_fb_funcs); -	if (err < 0) { -		dev_err(drm->dev, "failed to initialize framebuffer: %d\n", -			err); -		kfree(fb->planes); -		kfree(fb); -		return ERR_PTR(err); -	} - -	return fb; -} - -static struct drm_framebuffer *tegra_fb_create(struct drm_device *drm, -					       struct drm_file *file, -					       struct drm_mode_fb_cmd2 *cmd) -{ -	unsigned int hsub, vsub, i; -	struct tegra_bo *planes[4]; -	struct drm_gem_object *gem; -	struct tegra_fb *fb; -	int err; - -	hsub = drm_format_horz_chroma_subsampling(cmd->pixel_format); -	vsub = drm_format_vert_chroma_subsampling(cmd->pixel_format); - -	for (i = 0; i < drm_format_num_planes(cmd->pixel_format); i++) { -		unsigned int width = cmd->width / (i ? hsub : 1); -		unsigned int height = cmd->height / (i ? vsub : 1); -		unsigned int size, bpp; - -		gem = drm_gem_object_lookup(drm, file, cmd->handles[i]); -		if (!gem) { -			err = -ENXIO; -			goto unreference; -		} - -		bpp = drm_format_plane_cpp(cmd->pixel_format, i); - -		size = (height - 1) * cmd->pitches[i] + -		       width * bpp + cmd->offsets[i]; - -		if (gem->size < size) { -			err = -EINVAL; -			goto unreference; -		} - -		planes[i] = to_tegra_bo(gem); -	} - -	fb = tegra_fb_alloc(drm, cmd, planes, i); -	if (IS_ERR(fb)) { -		err = PTR_ERR(fb); -		goto unreference; -	} - -	return &fb->base; - -unreference: -	while (i--) -		drm_gem_object_unreference_unlocked(&planes[i]->gem); - -	return ERR_PTR(err); -} - -static struct fb_ops tegra_fb_ops = { -	.owner = THIS_MODULE, -	.fb_fillrect = sys_fillrect, -	.fb_copyarea = sys_copyarea, -	.fb_imageblit = sys_imageblit, -	.fb_check_var = drm_fb_helper_check_var, -	.fb_set_par = drm_fb_helper_set_par, -	.fb_blank = drm_fb_helper_blank, -	.fb_pan_display = drm_fb_helper_pan_display, -	.fb_setcmap = drm_fb_helper_setcmap, -}; - -static int tegra_fbdev_probe(struct drm_fb_helper *helper, -			     struct drm_fb_helper_surface_size *sizes) -{ -	struct tegra_fbdev *fbdev = to_tegra_fbdev(helper); -	struct drm_device *drm = helper->dev; -	struct drm_mode_fb_cmd2 cmd = { 0 }; -	unsigned int bytes_per_pixel; -	struct drm_framebuffer *fb; -	unsigned long offset; -	struct fb_info *info; -	struct tegra_bo *bo; -	size_t size; -	int err; - -	bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8); - -	cmd.width = sizes->surface_width; -	cmd.height = sizes->surface_height; -	cmd.pitches[0] = sizes->surface_width * bytes_per_pixel; -	cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, -						     sizes->surface_depth); - -	size = cmd.pitches[0] * cmd.height; - -	bo = tegra_bo_create(drm, size); -	if (IS_ERR(bo)) -		return PTR_ERR(bo); - -	info = framebuffer_alloc(0, drm->dev); -	if (!info) { -		dev_err(drm->dev, "failed to allocate framebuffer info\n"); -		tegra_bo_free_object(&bo->gem); -		return -ENOMEM; -	} - -	fbdev->fb = tegra_fb_alloc(drm, &cmd, &bo, 1); -	if (IS_ERR(fbdev->fb)) { -		dev_err(drm->dev, "failed to allocate DRM framebuffer\n"); -		err = PTR_ERR(fbdev->fb); -		goto release; -	} - -	fb = &fbdev->fb->base; -	helper->fb = fb; -	helper->fbdev = info; - -	info->par = helper; -	info->flags = FBINFO_FLAG_DEFAULT; -	info->fbops = &tegra_fb_ops; - -	err = fb_alloc_cmap(&info->cmap, 256, 0); -	if (err < 0) { -		dev_err(drm->dev, "failed to allocate color map: %d\n", err); -		goto destroy; -	} - -	drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); -	drm_fb_helper_fill_var(info, helper, fb->width, fb->height); - -	offset = info->var.xoffset * bytes_per_pixel + -		 info->var.yoffset * fb->pitches[0]; - -	drm->mode_config.fb_base = (resource_size_t)bo->paddr; -	info->screen_base = bo->vaddr + offset; -	info->screen_size = size; -	info->fix.smem_start = (unsigned long)(bo->paddr + offset); -	info->fix.smem_len = size; - -	return 0; - -destroy: -	drm_framebuffer_unregister_private(fb); -	tegra_fb_destroy(fb); -release: -	framebuffer_release(info); -	return err; -} - -static struct drm_fb_helper_funcs tegra_fb_helper_funcs = { -	.fb_probe = tegra_fbdev_probe, -}; - -static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm, -					      unsigned int preferred_bpp, -					      unsigned int num_crtc, -					      unsigned int max_connectors) -{ -	struct drm_fb_helper *helper; -	struct tegra_fbdev *fbdev; -	int err; - -	fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); -	if (!fbdev) { -		dev_err(drm->dev, "failed to allocate DRM fbdev\n"); -		return ERR_PTR(-ENOMEM); -	} - -	fbdev->base.funcs = &tegra_fb_helper_funcs; -	helper = &fbdev->base; - -	err = drm_fb_helper_init(drm, &fbdev->base, num_crtc, max_connectors); -	if (err < 0) { -		dev_err(drm->dev, "failed to initialize DRM FB helper\n"); -		goto free; -	} - -	err = drm_fb_helper_single_add_all_connectors(&fbdev->base); -	if (err < 0) { -		dev_err(drm->dev, "failed to add connectors\n"); -		goto fini; -	} - -	drm_helper_disable_unused_functions(drm); - -	err = drm_fb_helper_initial_config(&fbdev->base, preferred_bpp); -	if (err < 0) { -		dev_err(drm->dev, "failed to set initial configuration\n"); -		goto fini; -	} - -	return fbdev; - -fini: -	drm_fb_helper_fini(&fbdev->base); -free: -	kfree(fbdev); -	return ERR_PTR(err); -} - -static void tegra_fbdev_free(struct tegra_fbdev *fbdev) -{ -	struct fb_info *info = fbdev->base.fbdev; - -	if (info) { -		int err; - -		err = unregister_framebuffer(info); -		if (err < 0) -			DRM_DEBUG_KMS("failed to unregister framebuffer\n"); - -		if (info->cmap.len) -			fb_dealloc_cmap(&info->cmap); - -		framebuffer_release(info); -	} - -	if (fbdev->fb) { -		drm_framebuffer_unregister_private(&fbdev->fb->base); -		tegra_fb_destroy(&fbdev->fb->base); -	} - -	drm_fb_helper_fini(&fbdev->base); -	kfree(fbdev); -} - -static void tegra_fb_output_poll_changed(struct drm_device *drm) -{ -	struct host1x_drm *host1x = drm->dev_private; - -	if (host1x->fbdev) -		drm_fb_helper_hotplug_event(&host1x->fbdev->base); -} - -static const struct drm_mode_config_funcs tegra_drm_mode_funcs = { -	.fb_create = tegra_fb_create, -	.output_poll_changed = tegra_fb_output_poll_changed, -}; - -int tegra_drm_fb_init(struct drm_device *drm) -{ -	struct host1x_drm *host1x = drm->dev_private; -	struct tegra_fbdev *fbdev; - -	drm->mode_config.min_width = 0; -	drm->mode_config.min_height = 0; - -	drm->mode_config.max_width = 4096; -	drm->mode_config.max_height = 4096; - -	drm->mode_config.funcs = &tegra_drm_mode_funcs; - -	fbdev = tegra_fbdev_create(drm, 32, drm->mode_config.num_crtc, -				   drm->mode_config.num_connector); -	if (IS_ERR(fbdev)) -		return PTR_ERR(fbdev); - -	host1x->fbdev = fbdev; - -	return 0; -} - -void tegra_drm_fb_exit(struct drm_device *drm) -{ -	struct host1x_drm *host1x = drm->dev_private; - -	tegra_fbdev_free(host1x->fbdev); -} - -void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev) -{ -	if (fbdev) { -		drm_modeset_lock_all(fbdev->base.dev); -		drm_fb_helper_restore_fbdev_mode(&fbdev->base); -		drm_modeset_unlock_all(fbdev->base.dev); -	} -} diff --git a/drivers/gpu/host1x/drm/gem.c b/drivers/gpu/host1x/drm/gem.c deleted file mode 100644 index 59623de4ee1..00000000000 --- a/drivers/gpu/host1x/drm/gem.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * NVIDIA Tegra DRM GEM helper functions - * - * Copyright (C) 2012 Sascha Hauer, Pengutronix - * Copyright (C) 2013 NVIDIA CORPORATION, All rights reserved. - * - * Based on the GEM/CMA helpers - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - */ - -#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) -{ -	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 drm_device *drm = obj->gem.dev; - -	mutex_lock(&drm->struct_mutex); -	drm_gem_object_unreference(&obj->gem); -	mutex_unlock(&drm->struct_mutex); -} - -static dma_addr_t tegra_bo_pin(struct host1x_bo *bo, struct sg_table **sgt) -{ -	struct tegra_bo *obj = host1x_to_drm_bo(bo); - -	return obj->paddr; -} - -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); - -	return obj->vaddr; -} - -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); - -	return obj->vaddr + page * PAGE_SIZE; -} - -static void tegra_bo_kunmap(struct host1x_bo *bo, unsigned int page, -			    void *addr) -{ -} - -static struct host1x_bo *tegra_bo_get(struct host1x_bo *bo) -{ -	struct tegra_bo *obj = host1x_to_drm_bo(bo); -	struct drm_device *drm = obj->gem.dev; - -	mutex_lock(&drm->struct_mutex); -	drm_gem_object_reference(&obj->gem); -	mutex_unlock(&drm->struct_mutex); - -	return bo; -} - -const struct host1x_bo_ops tegra_bo_ops = { -	.get = tegra_bo_get, -	.put = tegra_bo_put, -	.pin = tegra_bo_pin, -	.unpin = tegra_bo_unpin, -	.mmap = tegra_bo_mmap, -	.munmap = tegra_bo_munmap, -	.kmap = tegra_bo_kmap, -	.kunmap = tegra_bo_kunmap, -}; - -static void tegra_bo_destroy(struct drm_device *drm, struct tegra_bo *bo) -{ -	dma_free_writecombine(drm->dev, bo->gem.size, bo->vaddr, bo->paddr); -} - -struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size) -{ -	struct tegra_bo *bo; -	int err; - -	bo = kzalloc(sizeof(*bo), GFP_KERNEL); -	if (!bo) -		return ERR_PTR(-ENOMEM); - -	host1x_bo_init(&bo->base, &tegra_bo_ops); -	size = round_up(size, PAGE_SIZE); - -	bo->vaddr = dma_alloc_writecombine(drm->dev, size, &bo->paddr, -					   GFP_KERNEL | __GFP_NOWARN); -	if (!bo->vaddr) { -		dev_err(drm->dev, "failed to allocate buffer with size %u\n", -			size); -		err = -ENOMEM; -		goto err_dma; -	} - -	err = drm_gem_object_init(drm, &bo->gem, size); -	if (err) -		goto err_init; - -	err = drm_gem_create_mmap_offset(&bo->gem); -	if (err) -		goto err_mmap; - -	return bo; - -err_mmap: -	drm_gem_object_release(&bo->gem); -err_init: -	tegra_bo_destroy(drm, bo); -err_dma: -	kfree(bo); - -	return ERR_PTR(err); - -} - -struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file, -					    struct drm_device *drm, -					    unsigned int size, -					    unsigned int *handle) -{ -	struct tegra_bo *bo; -	int ret; - -	bo = tegra_bo_create(drm, size); -	if (IS_ERR(bo)) -		return bo; - -	ret = drm_gem_handle_create(file, &bo->gem, handle); -	if (ret) -		goto err; - -	drm_gem_object_unreference_unlocked(&bo->gem); - -	return bo; - -err: -	tegra_bo_free_object(&bo->gem); -	return ERR_PTR(ret); -} - -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); - -	kfree(bo); -} - -int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm, -			 struct drm_mode_create_dumb *args) -{ -	int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8); -	struct tegra_bo *bo; - -	if (args->pitch < min_pitch) -		args->pitch = min_pitch; - -	if (args->size < args->pitch * args->height) -		args->size = args->pitch * args->height; - -	bo = tegra_bo_create_with_handle(file, drm, args->size, -					    &args->handle); -	if (IS_ERR(bo)) -		return PTR_ERR(bo); - -	return 0; -} - -int tegra_bo_dumb_map_offset(struct drm_file *file, struct drm_device *drm, -			     uint32_t handle, uint64_t *offset) -{ -	struct drm_gem_object *gem; -	struct tegra_bo *bo; - -	mutex_lock(&drm->struct_mutex); - -	gem = drm_gem_object_lookup(drm, file, handle); -	if (!gem) { -		dev_err(drm->dev, "failed to lookup GEM object\n"); -		mutex_unlock(&drm->struct_mutex); -		return -EINVAL; -	} - -	bo = to_tegra_bo(gem); - -	*offset = drm_vma_node_offset_addr(&bo->gem.vma_node); - -	drm_gem_object_unreference(gem); - -	mutex_unlock(&drm->struct_mutex); - -	return 0; -} - -const struct vm_operations_struct tegra_bo_vm_ops = { -	.open = drm_gem_vm_open, -	.close = drm_gem_vm_close, -}; - -int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma) -{ -	struct drm_gem_object *gem; -	struct tegra_bo *bo; -	int ret; - -	ret = drm_gem_mmap(file, vma); -	if (ret) -		return ret; - -	gem = vma->vm_private_data; -	bo = to_tegra_bo(gem); - -	ret = remap_pfn_range(vma, vma->vm_start, bo->paddr >> PAGE_SHIFT, -			      vma->vm_end - vma->vm_start, vma->vm_page_prot); -	if (ret) -		drm_gem_vm_close(vma); - -	return ret; -} diff --git a/drivers/gpu/host1x/drm/gem.h b/drivers/gpu/host1x/drm/gem.h deleted file mode 100644 index 492533a2dac..00000000000 --- a/drivers/gpu/host1x/drm/gem.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Tegra host1x GEM implementation - * - * 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_GEM_H -#define __HOST1X_GEM_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; -	dma_addr_t paddr; -	void *vaddr; -}; - -static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem) -{ -	return container_of(gem, struct tegra_bo, gem); -} - -extern const struct host1x_bo_ops tegra_bo_ops; - -struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size); -struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file, -					    struct drm_device *drm, -					    unsigned int size, -					    unsigned int *handle); -void tegra_bo_free_object(struct drm_gem_object *gem); -int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm, -			 struct drm_mode_create_dumb *args); -int tegra_bo_dumb_map_offset(struct drm_file *file, struct drm_device *drm, -			     uint32_t handle, uint64_t *offset); - -int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma); - -extern const struct vm_operations_struct tegra_bo_vm_ops; - -#endif diff --git a/drivers/gpu/host1x/drm/gr2d.c b/drivers/gpu/host1x/drm/gr2d.c deleted file mode 100644 index 27ffcf15a4b..00000000000 --- a/drivers/gpu/host1x/drm/gr2d.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * 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 - * 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/export.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/clk.h> - -#include "channel.h" -#include "drm.h" -#include "gem.h" -#include "job.h" -#include "host1x.h" -#include "host1x_bo.h" -#include "host1x_client.h" -#include "syncpt.h" - -struct gr2d { -	struct host1x_client client; -	struct clk *clk; -	struct host1x_channel *channel; -	unsigned long *addr_regs; -}; - -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) -{ -	return 0; -} - -static int gr2d_client_exit(struct host1x_client *client) -{ -	return 0; -} - -static int gr2d_open_channel(struct host1x_client *client, -			     struct host1x_drm_context *context) -{ -	struct gr2d *gr2d = to_gr2d(client); - -	context->channel = host1x_channel_get(gr2d->channel); - -	if (!context->channel) -		return -ENOMEM; - -	return 0; -} - -static void gr2d_close_channel(struct host1x_drm_context *context) -{ -	host1x_channel_put(context->channel); -} - -static struct host1x_bo *host1x_bo_lookup(struct drm_device *drm, -					  struct drm_file *file, -					  u32 handle) -{ -	struct drm_gem_object *gem; -	struct tegra_bo *bo; - -	gem = drm_gem_object_lookup(drm, file, handle); -	if (!gem) -		return NULL; - -	mutex_lock(&drm->struct_mutex); -	drm_gem_object_unreference(gem); -	mutex_unlock(&drm->struct_mutex); - -	bo = to_tegra_bo(gem); -	return &bo->base; -} - -static int gr2d_submit(struct host1x_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; -	struct drm_tegra_cmdbuf __user *cmdbufs = -		(void * __user)(uintptr_t)args->cmdbufs; -	struct drm_tegra_reloc __user *relocs = -		(void * __user)(uintptr_t)args->relocs; -	struct drm_tegra_waitchk __user *waitchks = -		(void * __user)(uintptr_t)args->waitchks; -	struct drm_tegra_syncpt syncpt; -	int err; - -	/* We don't yet support other than one syncpt_incr struct per submit */ -	if (args->num_syncpts != 1) -		return -EINVAL; - -	job = host1x_job_alloc(context->channel, args->num_cmdbufs, -			       args->num_relocs, args->num_waitchks); -	if (!job) -		return -ENOMEM; - -	job->num_relocs = args->num_relocs; -	job->num_waitchk = args->num_waitchks; -	job->client = (u32)args->context; -	job->class = context->client->class; -	job->serialize = true; - -	while (num_cmdbufs) { -		struct drm_tegra_cmdbuf cmdbuf; -		struct host1x_bo *bo; - -		err = copy_from_user(&cmdbuf, cmdbufs, sizeof(cmdbuf)); -		if (err) -			goto fail; - -		bo = host1x_bo_lookup(drm, file, cmdbuf.handle); -		if (!bo) { -			err = -ENOENT; -			goto fail; -		} - -		host1x_job_add_gather(job, bo, cmdbuf.words, cmdbuf.offset); -		num_cmdbufs--; -		cmdbufs++; -	} - -	err = copy_from_user(job->relocarray, relocs, -			     sizeof(*relocs) * num_relocs); -	if (err) -		goto fail; - -	while (num_relocs--) { -		struct host1x_reloc *reloc = &job->relocarray[num_relocs]; -		struct host1x_bo *cmdbuf, *target; - -		cmdbuf = host1x_bo_lookup(drm, file, (u32)reloc->cmdbuf); -		target = host1x_bo_lookup(drm, file, (u32)reloc->target); - -		reloc->cmdbuf = cmdbuf; -		reloc->target = target; - -		if (!reloc->target || !reloc->cmdbuf) { -			err = -ENOENT; -			goto fail; -		} -	} - -	err = copy_from_user(job->waitchk, waitchks, -			     sizeof(*waitchks) * num_waitchks); -	if (err) -		goto fail; - -	err = copy_from_user(&syncpt, (void * __user)(uintptr_t)args->syncpts, -			     sizeof(syncpt)); -	if (err) -		goto fail; - -	job->syncpt_id = syncpt.id; -	job->syncpt_incrs = syncpt.incrs; -	job->timeout = 10000; -	job->is_addr_reg = gr2d_is_addr_reg; - -	if (args->timeout && args->timeout < 10000) -		job->timeout = args->timeout; - -	err = host1x_job_pin(job, context->client->dev); -	if (err) -		goto fail; - -	err = host1x_job_submit(job); -	if (err) -		goto fail_submit; - -	args->fence = job->syncpt_end; - -	host1x_job_put(job); -	return 0; - -fail_submit: -	host1x_job_unpin(job); -fail: -	host1x_job_put(job); -	return err; -} - -static struct host1x_client_ops gr2d_client_ops = { -	.drm_init = gr2d_client_init, -	.drm_exit = gr2d_client_exit, -	.open_channel = gr2d_open_channel, -	.close_channel = gr2d_close_channel, -	.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" }, -	{ }, -}; - -static int gr2d_probe(struct platform_device *pdev) -{ -	struct device *dev = &pdev->dev; -	struct host1x_drm *host1x = host1x_get_drm_data(dev->parent); -	int err; -	struct gr2d *gr2d = NULL; -	struct host1x_syncpt **syncpts; - -	gr2d = devm_kzalloc(dev, sizeof(*gr2d), GFP_KERNEL); -	if (!gr2d) -		return -ENOMEM; - -	syncpts = devm_kzalloc(dev, sizeof(*syncpts), GFP_KERNEL); -	if (!syncpts) -		return -ENOMEM; - -	gr2d->clk = devm_clk_get(dev, NULL); -	if (IS_ERR(gr2d->clk)) { -		dev_err(dev, "cannot get clock\n"); -		return PTR_ERR(gr2d->clk); -	} - -	err = clk_prepare_enable(gr2d->clk); -	if (err) { -		dev_err(dev, "cannot turn on clock\n"); -		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; -	} - -	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; - -	err = host1x_register_client(host1x, &gr2d->client); -	if (err < 0) { -		dev_err(dev, "failed to register host1x client: %d\n", err); -		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) -{ -	struct host1x_drm *host1x = 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); -	if (err < 0) { -		dev_err(&pdev->dev, "failed to unregister client: %d\n", err); -		return err; -	} - -	for (i = 0; i < gr2d->client.num_syncpts; i++) -		host1x_syncpt_free(gr2d->client.syncpts[i]); - -	host1x_channel_free(gr2d->channel); -	clk_disable_unprepare(gr2d->clk); - -	return 0; -} - -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, -	} -}; diff --git a/drivers/gpu/host1x/drm/hdmi.c b/drivers/gpu/host1x/drm/hdmi.c deleted file mode 100644 index 644d95c7d48..00000000000 --- a/drivers/gpu/host1x/drm/hdmi.c +++ /dev/null @@ -1,1304 +0,0 @@ -/* - * Copyright (C) 2012 Avionic Design GmbH - * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/clk.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" -#include "dc.h" -#include "host1x_client.h" - -struct tegra_hdmi { -	struct host1x_client client; -	struct tegra_output output; -	struct device *dev; - -	struct regulator *vdd; -	struct regulator *pll; - -	void __iomem *regs; -	unsigned int irq; - -	struct clk *clk_parent; -	struct clk *clk; - -	unsigned int audio_source; -	unsigned int audio_freq; -	bool stereo; -	bool dvi; - -	struct drm_info_list *debugfs_files; -	struct drm_minor *minor; -	struct dentry *debugfs; -}; - -static inline struct tegra_hdmi * -host1x_client_to_hdmi(struct host1x_client *client) -{ -	return container_of(client, struct tegra_hdmi, client); -} - -static inline struct tegra_hdmi *to_hdmi(struct tegra_output *output) -{ -	return container_of(output, struct tegra_hdmi, output); -} - -#define HDMI_AUDIOCLK_FREQ 216000000 -#define HDMI_REKEY_DEFAULT 56 - -enum { -	AUTO = 0, -	SPDIF, -	HDA, -}; - -static inline unsigned long tegra_hdmi_readl(struct tegra_hdmi *hdmi, -					     unsigned long reg) -{ -	return readl(hdmi->regs + (reg << 2)); -} - -static inline void tegra_hdmi_writel(struct tegra_hdmi *hdmi, unsigned long val, -				     unsigned long reg) -{ -	writel(val, hdmi->regs + (reg << 2)); -} - -struct tegra_hdmi_audio_config { -	unsigned int pclk; -	unsigned int n; -	unsigned int cts; -	unsigned int aval; -}; - -static const struct tegra_hdmi_audio_config tegra_hdmi_audio_32k[] = { -	{  25200000, 4096,  25200, 24000 }, -	{  27000000, 4096,  27000, 24000 }, -	{  74250000, 4096,  74250, 24000 }, -	{ 148500000, 4096, 148500, 24000 }, -	{         0,    0,      0,     0 }, -}; - -static const struct tegra_hdmi_audio_config tegra_hdmi_audio_44_1k[] = { -	{  25200000, 5880,  26250, 25000 }, -	{  27000000, 5880,  28125, 25000 }, -	{  74250000, 4704,  61875, 20000 }, -	{ 148500000, 4704, 123750, 20000 }, -	{         0,    0,      0,     0 }, -}; - -static const struct tegra_hdmi_audio_config tegra_hdmi_audio_48k[] = { -	{  25200000, 6144,  25200, 24000 }, -	{  27000000, 6144,  27000, 24000 }, -	{  74250000, 6144,  74250, 24000 }, -	{ 148500000, 6144, 148500, 24000 }, -	{         0,    0,      0,     0 }, -}; - -static const struct tegra_hdmi_audio_config tegra_hdmi_audio_88_2k[] = { -	{  25200000, 11760,  26250, 25000 }, -	{  27000000, 11760,  28125, 25000 }, -	{  74250000,  9408,  61875, 20000 }, -	{ 148500000,  9408, 123750, 20000 }, -	{         0,     0,      0,     0 }, -}; - -static const struct tegra_hdmi_audio_config tegra_hdmi_audio_96k[] = { -	{  25200000, 12288,  25200, 24000 }, -	{  27000000, 12288,  27000, 24000 }, -	{  74250000, 12288,  74250, 24000 }, -	{ 148500000, 12288, 148500, 24000 }, -	{         0,     0,      0,     0 }, -}; - -static const struct tegra_hdmi_audio_config tegra_hdmi_audio_176_4k[] = { -	{  25200000, 23520,  26250, 25000 }, -	{  27000000, 23520,  28125, 25000 }, -	{  74250000, 18816,  61875, 20000 }, -	{ 148500000, 18816, 123750, 20000 }, -	{         0,     0,      0,     0 }, -}; - -static const struct tegra_hdmi_audio_config tegra_hdmi_audio_192k[] = { -	{  25200000, 24576,  25200, 24000 }, -	{  27000000, 24576,  27000, 24000 }, -	{  74250000, 24576,  74250, 24000 }, -	{ 148500000, 24576, 148500, 24000 }, -	{         0,     0,      0,     0 }, -}; - -struct tmds_config { -	unsigned int pclk; -	u32 pll0; -	u32 pll1; -	u32 pe_current; -	u32 drive_current; -}; - -static const struct tmds_config tegra2_tmds_config[] = { -	{ /* slow pixel clock modes */ -		.pclk = 27000000, -		.pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | -			SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) | -			SOR_PLL_TX_REG_LOAD(3), -		.pll1 = SOR_PLL_TMDS_TERM_ENABLE, -		.pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) | -			PE_CURRENT1(PE_CURRENT_0_0_mA) | -			PE_CURRENT2(PE_CURRENT_0_0_mA) | -			PE_CURRENT3(PE_CURRENT_0_0_mA), -		.drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) | -			DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) | -			DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) | -			DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA), -	}, -	{ /* high pixel clock modes */ -		.pclk = UINT_MAX, -		.pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | -			SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) | -			SOR_PLL_TX_REG_LOAD(3), -		.pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN, -		.pe_current = PE_CURRENT0(PE_CURRENT_6_0_mA) | -			PE_CURRENT1(PE_CURRENT_6_0_mA) | -			PE_CURRENT2(PE_CURRENT_6_0_mA) | -			PE_CURRENT3(PE_CURRENT_6_0_mA), -		.drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) | -			DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) | -			DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) | -			DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA), -	}, -}; - -static const struct tmds_config tegra3_tmds_config[] = { -	{ /* 480p modes */ -		.pclk = 27000000, -		.pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | -			SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) | -			SOR_PLL_TX_REG_LOAD(0), -		.pll1 = SOR_PLL_TMDS_TERM_ENABLE, -		.pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) | -			PE_CURRENT1(PE_CURRENT_0_0_mA) | -			PE_CURRENT2(PE_CURRENT_0_0_mA) | -			PE_CURRENT3(PE_CURRENT_0_0_mA), -		.drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) | -			DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) | -			DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) | -			DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA), -	}, { /* 720p modes */ -		.pclk = 74250000, -		.pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | -			SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) | -			SOR_PLL_TX_REG_LOAD(0), -		.pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN, -		.pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) | -			PE_CURRENT1(PE_CURRENT_5_0_mA) | -			PE_CURRENT2(PE_CURRENT_5_0_mA) | -			PE_CURRENT3(PE_CURRENT_5_0_mA), -		.drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) | -			DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) | -			DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) | -			DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA), -	}, { /* 1080p modes */ -		.pclk = UINT_MAX, -		.pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | -			SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(3) | -			SOR_PLL_TX_REG_LOAD(0), -		.pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN, -		.pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) | -			PE_CURRENT1(PE_CURRENT_5_0_mA) | -			PE_CURRENT2(PE_CURRENT_5_0_mA) | -			PE_CURRENT3(PE_CURRENT_5_0_mA), -		.drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) | -			DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) | -			DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) | -			DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA), -	}, -}; - -static const struct tegra_hdmi_audio_config * -tegra_hdmi_get_audio_config(unsigned int audio_freq, unsigned int pclk) -{ -	const struct tegra_hdmi_audio_config *table; - -	switch (audio_freq) { -	case 32000: -		table = tegra_hdmi_audio_32k; -		break; - -	case 44100: -		table = tegra_hdmi_audio_44_1k; -		break; - -	case 48000: -		table = tegra_hdmi_audio_48k; -		break; - -	case 88200: -		table = tegra_hdmi_audio_88_2k; -		break; - -	case 96000: -		table = tegra_hdmi_audio_96k; -		break; - -	case 176400: -		table = tegra_hdmi_audio_176_4k; -		break; - -	case 192000: -		table = tegra_hdmi_audio_192k; -		break; - -	default: -		return NULL; -	} - -	while (table->pclk) { -		if (table->pclk == pclk) -			return table; - -		table++; -	} - -	return NULL; -} - -static void tegra_hdmi_setup_audio_fs_tables(struct tegra_hdmi *hdmi) -{ -	const unsigned int freqs[] = { -		32000, 44100, 48000, 88200, 96000, 176400, 192000 -	}; -	unsigned int i; - -	for (i = 0; i < ARRAY_SIZE(freqs); i++) { -		unsigned int f = freqs[i]; -		unsigned int eight_half; -		unsigned long value; -		unsigned int delta; - -		if (f > 96000) -			delta = 2; -		else if (f > 480000) -			delta = 6; -		else -			delta = 9; - -		eight_half = (8 * HDMI_AUDIOCLK_FREQ) / (f * 128); -		value = AUDIO_FS_LOW(eight_half - delta) | -			AUDIO_FS_HIGH(eight_half + delta); -		tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_FS(i)); -	} -} - -static int tegra_hdmi_setup_audio(struct tegra_hdmi *hdmi, unsigned int pclk) -{ -	struct device_node *node = hdmi->dev->of_node; -	const struct tegra_hdmi_audio_config *config; -	unsigned int offset = 0; -	unsigned long value; - -	switch (hdmi->audio_source) { -	case HDA: -		value = AUDIO_CNTRL0_SOURCE_SELECT_HDAL; -		break; - -	case SPDIF: -		value = AUDIO_CNTRL0_SOURCE_SELECT_SPDIF; -		break; - -	default: -		value = AUDIO_CNTRL0_SOURCE_SELECT_AUTO; -		break; -	} - -	if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) { -		value |= AUDIO_CNTRL0_ERROR_TOLERANCE(6) | -			 AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0); -		tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0); -	} else { -		value |= AUDIO_CNTRL0_INJECT_NULLSMPL; -		tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_AUDIO_CNTRL0); - -		value = AUDIO_CNTRL0_ERROR_TOLERANCE(6) | -			AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0); -		tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0); -	} - -	config = tegra_hdmi_get_audio_config(hdmi->audio_freq, pclk); -	if (!config) { -		dev_err(hdmi->dev, "cannot set audio to %u at %u pclk\n", -			hdmi->audio_freq, pclk); -		return -EINVAL; -	} - -	tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_HDMI_ACR_CTRL); - -	value = AUDIO_N_RESETF | AUDIO_N_GENERATE_ALTERNATE | -		AUDIO_N_VALUE(config->n - 1); -	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N); - -	tegra_hdmi_writel(hdmi, ACR_SUBPACK_N(config->n) | ACR_ENABLE, -			  HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH); - -	value = ACR_SUBPACK_CTS(config->cts); -	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW); - -	value = SPARE_HW_CTS | SPARE_FORCE_SW_CTS | SPARE_CTS_RESET_VAL(1); -	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_SPARE); - -	value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_AUDIO_N); -	value &= ~AUDIO_N_RESETF; -	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N); - -	if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) { -		switch (hdmi->audio_freq) { -		case 32000: -			offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320; -			break; - -		case 44100: -			offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441; -			break; - -		case 48000: -			offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480; -			break; - -		case 88200: -			offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882; -			break; - -		case 96000: -			offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960; -			break; - -		case 176400: -			offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764; -			break; - -		case 192000: -			offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920; -			break; -		} - -		tegra_hdmi_writel(hdmi, config->aval, offset); -	} - -	tegra_hdmi_setup_audio_fs_tables(hdmi); - -	return 0; -} - -static inline unsigned long tegra_hdmi_subpack(const u8 *ptr, size_t size) -{ -	unsigned long value = 0; -	size_t i; - -	for (i = size; i > 0; i--) -		value = (value << 8) | ptr[i - 1]; - -	return value; -} - -static void tegra_hdmi_write_infopack(struct tegra_hdmi *hdmi, const void *data, -				      size_t size) -{ -	const u8 *ptr = data; -	unsigned long offset; -	unsigned long value; -	size_t i, j; - -	switch (ptr[0]) { -	case HDMI_INFOFRAME_TYPE_AVI: -		offset = HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER; -		break; - -	case HDMI_INFOFRAME_TYPE_AUDIO: -		offset = HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER; -		break; - -	case HDMI_INFOFRAME_TYPE_VENDOR: -		offset = HDMI_NV_PDISP_HDMI_GENERIC_HEADER; -		break; - -	default: -		dev_err(hdmi->dev, "unsupported infoframe type: %02x\n", -			ptr[0]); -		return; -	} - -	value = INFOFRAME_HEADER_TYPE(ptr[0]) | -		INFOFRAME_HEADER_VERSION(ptr[1]) | -		INFOFRAME_HEADER_LEN(ptr[2]); -	tegra_hdmi_writel(hdmi, value, offset); -	offset++; - -	/* -	 * Each subpack contains 7 bytes, divided into: -	 * - subpack_low: bytes 0 - 3 -	 * - subpack_high: bytes 4 - 6 (with byte 7 padded to 0x00) -	 */ -	for (i = 3, j = 0; i < size; i += 7, j += 8) { -		size_t rem = size - i, num = min_t(size_t, rem, 4); - -		value = tegra_hdmi_subpack(&ptr[i], num); -		tegra_hdmi_writel(hdmi, value, offset++); - -		num = min_t(size_t, rem - num, 3); - -		value = tegra_hdmi_subpack(&ptr[i + 4], num); -		tegra_hdmi_writel(hdmi, value, offset++); -	} -} - -static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi, -					   struct drm_display_mode *mode) -{ -	struct hdmi_avi_infoframe frame; -	u8 buffer[17]; -	ssize_t err; - -	if (hdmi->dvi) { -		tegra_hdmi_writel(hdmi, 0, -				  HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL); -		return; -	} - -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); -	if (err < 0) { -		dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err); -		return; -	} - -	err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer)); -	if (err < 0) { -		dev_err(hdmi->dev, "failed to pack AVI infoframe: %zd\n", err); -		return; -	} - -	tegra_hdmi_write_infopack(hdmi, buffer, err); - -	tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE, -			  HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL); -} - -static void tegra_hdmi_setup_audio_infoframe(struct tegra_hdmi *hdmi) -{ -	struct hdmi_audio_infoframe frame; -	u8 buffer[14]; -	ssize_t err; - -	if (hdmi->dvi) { -		tegra_hdmi_writel(hdmi, 0, -				  HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL); -		return; -	} - -	err = hdmi_audio_infoframe_init(&frame); -	if (err < 0) { -		dev_err(hdmi->dev, "failed to initialize audio infoframe: %d\n", -			err); -		return; -	} - -	frame.channels = 2; - -	err = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer)); -	if (err < 0) { -		dev_err(hdmi->dev, "failed to pack audio infoframe: %zd\n", -			err); -		return; -	} - -	/* -	 * The audio infoframe has only one set of subpack registers, so the -	 * infoframe needs to be truncated. One set of subpack registers can -	 * contain 7 bytes. Including the 3 byte header only the first 10 -	 * bytes can be programmed. -	 */ -	tegra_hdmi_write_infopack(hdmi, buffer, min(10, err)); - -	tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE, -			  HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL); -} - -static void tegra_hdmi_setup_stereo_infoframe(struct tegra_hdmi *hdmi) -{ -	struct hdmi_vendor_infoframe frame; -	unsigned long value; -	u8 buffer[10]; -	ssize_t err; - -	if (!hdmi->stereo) { -		value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); -		value &= ~GENERIC_CTRL_ENABLE; -		tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); -		return; -	} - -	hdmi_vendor_infoframe_init(&frame); -	frame.s3d_struct = HDMI_3D_STRUCTURE_FRAME_PACKING; - -	err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer)); -	if (err < 0) { -		dev_err(hdmi->dev, "failed to pack vendor infoframe: %zd\n", -			err); -		return; -	} - -	tegra_hdmi_write_infopack(hdmi, buffer, err); - -	value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); -	value |= GENERIC_CTRL_ENABLE; -	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); -} - -static void tegra_hdmi_setup_tmds(struct tegra_hdmi *hdmi, -				  const struct tmds_config *tmds) -{ -	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); -} - -static int tegra_output_hdmi_enable(struct tegra_output *output) -{ -	unsigned int h_sync_width, h_front_porch, h_back_porch, i, rekey; -	struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc); -	struct drm_display_mode *mode = &dc->base.mode; -	struct tegra_hdmi *hdmi = to_hdmi(output); -	struct device_node *node = hdmi->dev->of_node; -	unsigned int pulse_start, div82, pclk; -	const struct tmds_config *tmds; -	unsigned int num_tmds; -	unsigned long value; -	int retries = 1000; -	int err; - -	pclk = mode->clock * 1000; -	h_sync_width = mode->hsync_end - mode->hsync_start; -	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); -		return err; -	} - -	/* -	 * This assumes that the display controller will divide its parent -	 * clock by 2 to generate the pixel clock. -	 */ -	err = tegra_output_setup_clock(output, hdmi->clk, pclk * 2); -	if (err < 0) { -		dev_err(hdmi->dev, "failed to setup clock: %d\n", err); -		return err; -	} - -	err = clk_set_rate(hdmi->clk, pclk); -	if (err < 0) -		return err; - -	err = clk_enable(hdmi->clk); -	if (err < 0) { -		dev_err(hdmi->dev, "failed to enable clock: %d\n", err); -		return err; -	} - -	tegra_periph_reset_assert(hdmi->clk); -	usleep_range(1000, 2000); -	tegra_periph_reset_deassert(hdmi->clk); - -	tegra_dc_writel(dc, VSYNC_H_POSITION(1), -			DC_DISP_DISP_TIMING_OPTIONS); -	tegra_dc_writel(dc, DITHER_CONTROL_DISABLE | BASE_COLOR_SIZE888, -			DC_DISP_DISP_COLOR_CONTROL); - -	/* video_preamble uses h_pulse2 */ -	pulse_start = 1 + h_sync_width + h_back_porch - 10; - -	tegra_dc_writel(dc, H_PULSE_2_ENABLE, DC_DISP_DISP_SIGNAL_OPTIONS0); - -	value = PULSE_MODE_NORMAL | PULSE_POLARITY_HIGH | PULSE_QUAL_VACTIVE | -		PULSE_LAST_END_A; -	tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_CONTROL); - -	value = PULSE_START(pulse_start) | PULSE_END(pulse_start + 8); -	tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_POSITION_A); - -	value = VSYNC_WINDOW_END(0x210) | VSYNC_WINDOW_START(0x200) | -		VSYNC_WINDOW_ENABLE; -	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_VSYNC_WINDOW); - -	if (dc->pipe) -		value = HDMI_SRC_DISPLAYB; -	else -		value = HDMI_SRC_DISPLAYA; - -	if ((mode->hdisplay == 720) && ((mode->vdisplay == 480) || -					(mode->vdisplay == 576))) -		tegra_hdmi_writel(hdmi, -				  value | ARM_VIDEO_RANGE_FULL, -				  HDMI_NV_PDISP_INPUT_CONTROL); -	else -		tegra_hdmi_writel(hdmi, -				  value | ARM_VIDEO_RANGE_LIMITED, -				  HDMI_NV_PDISP_INPUT_CONTROL); - -	div82 = clk_get_rate(hdmi->clk) / 1000000 * 4; -	value = SOR_REFCLK_DIV_INT(div82 >> 2) | SOR_REFCLK_DIV_FRAC(div82); -	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_REFCLK); - -	if (!hdmi->dvi) { -		err = tegra_hdmi_setup_audio(hdmi, pclk); -		if (err < 0) -			hdmi->dvi = true; -	} - -	if (of_device_is_compatible(node, "nvidia,tegra20-hdmi")) { -		/* -		 * TODO: add ELD support -		 */ -	} - -	rekey = HDMI_REKEY_DEFAULT; -	value = HDMI_CTRL_REKEY(rekey); -	value |= HDMI_CTRL_MAX_AC_PACKET((h_sync_width + h_back_porch + -					  h_front_porch - rekey - 18) / 32); - -	if (!hdmi->dvi) -		value |= HDMI_CTRL_ENABLE; - -	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_CTRL); - -	if (hdmi->dvi) -		tegra_hdmi_writel(hdmi, 0x0, -				  HDMI_NV_PDISP_HDMI_GENERIC_CTRL); -	else -		tegra_hdmi_writel(hdmi, GENERIC_CTRL_AUDIO, -				  HDMI_NV_PDISP_HDMI_GENERIC_CTRL); - -	tegra_hdmi_setup_avi_infoframe(hdmi, mode); -	tegra_hdmi_setup_audio_infoframe(hdmi); -	tegra_hdmi_setup_stereo_infoframe(hdmi); - -	/* TMDS CONFIG */ -	if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) { -		num_tmds = ARRAY_SIZE(tegra3_tmds_config); -		tmds = tegra3_tmds_config; -	} else { -		num_tmds = ARRAY_SIZE(tegra2_tmds_config); -		tmds = tegra2_tmds_config; -	} - -	for (i = 0; i < num_tmds; i++) { -		if (pclk <= tmds[i].pclk) { -			tegra_hdmi_setup_tmds(hdmi, &tmds[i]); -			break; -		} -	} - -	tegra_hdmi_writel(hdmi, -			  SOR_SEQ_CTL_PU_PC(0) | -			  SOR_SEQ_PU_PC_ALT(0) | -			  SOR_SEQ_PD_PC(8) | -			  SOR_SEQ_PD_PC_ALT(8), -			  HDMI_NV_PDISP_SOR_SEQ_CTL); - -	value = SOR_SEQ_INST_WAIT_TIME(1) | -		SOR_SEQ_INST_WAIT_UNITS_VSYNC | -		SOR_SEQ_INST_HALT | -		SOR_SEQ_INST_PIN_A_LOW | -		SOR_SEQ_INST_PIN_B_LOW | -		SOR_SEQ_INST_DRIVE_PWM_OUT_LO; - -	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(0)); -	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(8)); - -	value = 0x1c800; -	value &= ~SOR_CSTM_ROTCLK(~0); -	value |= SOR_CSTM_ROTCLK(2); -	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_CSTM); - -	tegra_dc_writel(dc, DISP_CTRL_MODE_STOP, 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); - -	/* start SOR */ -	tegra_hdmi_writel(hdmi, -			  SOR_PWR_NORMAL_STATE_PU | -			  SOR_PWR_NORMAL_START_NORMAL | -			  SOR_PWR_SAFE_STATE_PD | -			  SOR_PWR_SETTING_NEW_TRIGGER, -			  HDMI_NV_PDISP_SOR_PWR); -	tegra_hdmi_writel(hdmi, -			  SOR_PWR_NORMAL_STATE_PU | -			  SOR_PWR_NORMAL_START_NORMAL | -			  SOR_PWR_SAFE_STATE_PD | -			  SOR_PWR_SETTING_NEW_DONE, -			  HDMI_NV_PDISP_SOR_PWR); - -	do { -		BUG_ON(--retries < 0); -		value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_SOR_PWR); -	} while (value & SOR_PWR_SETTING_NEW_PENDING); - -	value = SOR_STATE_ASY_CRCMODE_COMPLETE | -		SOR_STATE_ASY_OWNER_HEAD0 | -		SOR_STATE_ASY_SUBOWNER_BOTH | -		SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A | -		SOR_STATE_ASY_DEPOL_POS; - -	/* setup sync polarities */ -	if (mode->flags & DRM_MODE_FLAG_PHSYNC) -		value |= SOR_STATE_ASY_HSYNCPOL_POS; - -	if (mode->flags & DRM_MODE_FLAG_NHSYNC) -		value |= SOR_STATE_ASY_HSYNCPOL_NEG; - -	if (mode->flags & DRM_MODE_FLAG_PVSYNC) -		value |= SOR_STATE_ASY_VSYNCPOL_POS; - -	if (mode->flags & DRM_MODE_FLAG_NVSYNC) -		value |= SOR_STATE_ASY_VSYNCPOL_NEG; - -	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE2); - -	value = SOR_STATE_ASY_HEAD_OPMODE_AWAKE | SOR_STATE_ASY_ORMODE_NORMAL; -	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE1); - -	tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0); -	tegra_hdmi_writel(hdmi, SOR_STATE_UPDATE, HDMI_NV_PDISP_SOR_STATE0); -	tegra_hdmi_writel(hdmi, value | SOR_STATE_ATTACHED, -			  HDMI_NV_PDISP_SOR_STATE1); -	tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0); - -	tegra_dc_writel(dc, HDMI_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); - -	value = DISP_CTRL_MODE_C_DISPLAY; -	tegra_dc_writel(dc, value, 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); - -	/* TODO: add HDCP support */ - -	return 0; -} - -static int tegra_output_hdmi_disable(struct tegra_output *output) -{ -	struct tegra_hdmi *hdmi = to_hdmi(output); - -	tegra_periph_reset_assert(hdmi->clk); -	clk_disable(hdmi->clk); -	regulator_disable(hdmi->pll); -	regulator_disable(hdmi->vdd); - -	return 0; -} - -static int tegra_output_hdmi_setup_clock(struct tegra_output *output, -					 struct clk *clk, unsigned long pclk) -{ -	struct tegra_hdmi *hdmi = to_hdmi(output); -	struct clk *base; -	int err; - -	err = clk_set_parent(clk, hdmi->clk_parent); -	if (err < 0) { -		dev_err(output->dev, "failed to set parent: %d\n", err); -		return err; -	} - -	base = clk_get_parent(hdmi->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(output->dev, -			"failed to set base clock rate to %lu Hz\n", -			pclk * 2); - -	return 0; -} - -static int tegra_output_hdmi_check_mode(struct tegra_output *output, -					struct drm_display_mode *mode, -					enum drm_mode_status *status) -{ -	struct tegra_hdmi *hdmi = to_hdmi(output); -	unsigned long pclk = mode->clock * 1000; -	struct clk *parent; -	long err; - -	parent = clk_get_parent(hdmi->clk_parent); - -	err = clk_round_rate(parent, pclk * 4); -	if (err < 0) -		*status = MODE_NOCLOCK; -	else -		*status = MODE_OK; - -	return 0; -} - -static const struct tegra_output_ops hdmi_ops = { -	.enable = tegra_output_hdmi_enable, -	.disable = tegra_output_hdmi_disable, -	.setup_clock = tegra_output_hdmi_setup_clock, -	.check_mode = tegra_output_hdmi_check_mode, -}; - -static int tegra_hdmi_show_regs(struct seq_file *s, void *data) -{ -	struct drm_info_node *node = s->private; -	struct tegra_hdmi *hdmi = node->info_ent->data; -	int err; - -	err = clk_enable(hdmi->clk); -	if (err) -		return err; - -#define DUMP_REG(name)						\ -	seq_printf(s, "%-56s %#05x %08lx\n", #name, name,	\ -		tegra_hdmi_readl(hdmi, name)) - -	DUMP_REG(HDMI_CTXSW); -	DUMP_REG(HDMI_NV_PDISP_SOR_STATE0); -	DUMP_REG(HDMI_NV_PDISP_SOR_STATE1); -	DUMP_REG(HDMI_NV_PDISP_SOR_STATE2); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_MSB); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_LSB); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_MSB); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_LSB); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_MSB); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_LSB); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_MSB); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_LSB); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_MSB); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_LSB); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_MSB); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_LSB); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CTRL); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CMODE); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_MSB); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_LSB); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_MSB); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB2); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB1); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_RI); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_MSB); -	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_LSB); -	DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU0); -	DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU_RDATA0); -	DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU1); -	DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU2); -	DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL); -	DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS); -	DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER); -	DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW); -	DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH); -	DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL); -	DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS); -	DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER); -	DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW); -	DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH); -	DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW); -	DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH); -	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_CTRL); -	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_STATUS); -	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_HEADER); -	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW); -	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH); -	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW); -	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH); -	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW); -	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH); -	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW); -	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH); -	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_CTRL); -	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW); -	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH); -	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW); -	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH); -	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW); -	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH); -	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW); -	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH); -	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW); -	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH); -	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW); -	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH); -	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW); -	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH); -	DUMP_REG(HDMI_NV_PDISP_HDMI_CTRL); -	DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_KEEPOUT); -	DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_WINDOW); -	DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_CTRL); -	DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_STATUS); -	DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_SUBPACK); -	DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS1); -	DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS2); -	DUMP_REG(HDMI_NV_PDISP_HDMI_EMU0); -	DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1); -	DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1_RDATA); -	DUMP_REG(HDMI_NV_PDISP_HDMI_SPARE); -	DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1); -	DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS2); -	DUMP_REG(HDMI_NV_PDISP_HDMI_HDCPRIF_ROM_CTRL); -	DUMP_REG(HDMI_NV_PDISP_SOR_CAP); -	DUMP_REG(HDMI_NV_PDISP_SOR_PWR); -	DUMP_REG(HDMI_NV_PDISP_SOR_TEST); -	DUMP_REG(HDMI_NV_PDISP_SOR_PLL0); -	DUMP_REG(HDMI_NV_PDISP_SOR_PLL1); -	DUMP_REG(HDMI_NV_PDISP_SOR_PLL2); -	DUMP_REG(HDMI_NV_PDISP_SOR_CSTM); -	DUMP_REG(HDMI_NV_PDISP_SOR_LVDS); -	DUMP_REG(HDMI_NV_PDISP_SOR_CRCA); -	DUMP_REG(HDMI_NV_PDISP_SOR_CRCB); -	DUMP_REG(HDMI_NV_PDISP_SOR_BLANK); -	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_CTL); -	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(0)); -	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(1)); -	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(2)); -	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(3)); -	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(4)); -	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(5)); -	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(6)); -	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(7)); -	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(8)); -	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(9)); -	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(10)); -	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(11)); -	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(12)); -	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(13)); -	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(14)); -	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(15)); -	DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA0); -	DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA1); -	DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA0); -	DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA1); -	DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA0); -	DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA1); -	DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA0); -	DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA1); -	DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA0); -	DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA1); -	DUMP_REG(HDMI_NV_PDISP_SOR_TRIG); -	DUMP_REG(HDMI_NV_PDISP_SOR_MSCHECK); -	DUMP_REG(HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT); -	DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG0); -	DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG1); -	DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG2); -	DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(0)); -	DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(1)); -	DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(2)); -	DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(3)); -	DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(4)); -	DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(5)); -	DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(6)); -	DUMP_REG(HDMI_NV_PDISP_AUDIO_PULSE_WIDTH); -	DUMP_REG(HDMI_NV_PDISP_AUDIO_THRESHOLD); -	DUMP_REG(HDMI_NV_PDISP_AUDIO_CNTRL0); -	DUMP_REG(HDMI_NV_PDISP_AUDIO_N); -	DUMP_REG(HDMI_NV_PDISP_HDCPRIF_ROM_TIMING); -	DUMP_REG(HDMI_NV_PDISP_SOR_REFCLK); -	DUMP_REG(HDMI_NV_PDISP_CRC_CONTROL); -	DUMP_REG(HDMI_NV_PDISP_INPUT_CONTROL); -	DUMP_REG(HDMI_NV_PDISP_SCRATCH); -	DUMP_REG(HDMI_NV_PDISP_PE_CURRENT); -	DUMP_REG(HDMI_NV_PDISP_KEY_CTRL); -	DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG0); -	DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG1); -	DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG2); -	DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_0); -	DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_1); -	DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_2); -	DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_3); -	DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG); -	DUMP_REG(HDMI_NV_PDISP_KEY_SKEY_INDEX); -	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); - -#undef DUMP_REG - -	clk_disable(hdmi->clk); - -	return 0; -} - -static struct drm_info_list debugfs_files[] = { -	{ "regs", tegra_hdmi_show_regs, 0, NULL }, -}; - -static int tegra_hdmi_debugfs_init(struct tegra_hdmi *hdmi, -				   struct drm_minor *minor) -{ -	unsigned int i; -	int err; - -	hdmi->debugfs = debugfs_create_dir("hdmi", minor->debugfs_root); -	if (!hdmi->debugfs) -		return -ENOMEM; - -	hdmi->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files), -				      GFP_KERNEL); -	if (!hdmi->debugfs_files) { -		err = -ENOMEM; -		goto remove; -	} - -	for (i = 0; i < ARRAY_SIZE(debugfs_files); i++) -		hdmi->debugfs_files[i].data = hdmi; - -	err = drm_debugfs_create_files(hdmi->debugfs_files, -				       ARRAY_SIZE(debugfs_files), -				       hdmi->debugfs, minor); -	if (err < 0) -		goto free; - -	hdmi->minor = minor; - -	return 0; - -free: -	kfree(hdmi->debugfs_files); -	hdmi->debugfs_files = NULL; -remove: -	debugfs_remove(hdmi->debugfs); -	hdmi->debugfs = NULL; - -	return err; -} - -static int tegra_hdmi_debugfs_exit(struct tegra_hdmi *hdmi) -{ -	drm_debugfs_remove_files(hdmi->debugfs_files, ARRAY_SIZE(debugfs_files), -				 hdmi->minor); -	hdmi->minor = NULL; - -	kfree(hdmi->debugfs_files); -	hdmi->debugfs_files = NULL; - -	debugfs_remove(hdmi->debugfs); -	hdmi->debugfs = NULL; - -	return 0; -} - -static int tegra_hdmi_drm_init(struct host1x_client *client, -			       struct drm_device *drm) -{ -	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, &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); -		if (err < 0) -			dev_err(client->dev, "debugfs setup failed: %d\n", err); -	} - -	return 0; -} - -static int tegra_hdmi_drm_exit(struct host1x_client *client) -{ -	struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client); -	int err; - -	if (IS_ENABLED(CONFIG_DEBUG_FS)) { -		err = tegra_hdmi_debugfs_exit(hdmi); -		if (err < 0) -			dev_err(client->dev, "debugfs cleanup failed: %d\n", -				err); -	} - -	err = tegra_output_disable(&hdmi->output); -	if (err < 0) { -		dev_err(client->dev, "output failed to disable: %d\n", err); -		return err; -	} - -	err = tegra_output_exit(&hdmi->output); -	if (err < 0) { -		dev_err(client->dev, "output cleanup failed: %d\n", err); -		return err; -	} - -	return 0; -} - -static const struct host1x_client_ops hdmi_client_ops = { -	.drm_init = tegra_hdmi_drm_init, -	.drm_exit = tegra_hdmi_drm_exit, -}; - -static int tegra_hdmi_probe(struct platform_device *pdev) -{ -	struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent); -	struct tegra_hdmi *hdmi; -	struct resource *regs; -	int err; - -	hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); -	if (!hdmi) -		return -ENOMEM; - -	hdmi->dev = &pdev->dev; -	hdmi->audio_source = AUTO; -	hdmi->audio_freq = 44100; -	hdmi->stereo = false; -	hdmi->dvi = false; - -	hdmi->clk = devm_clk_get(&pdev->dev, NULL); -	if (IS_ERR(hdmi->clk)) { -		dev_err(&pdev->dev, "failed to get clock\n"); -		return PTR_ERR(hdmi->clk); -	} - -	err = clk_prepare(hdmi->clk); -	if (err < 0) -		return err; - -	hdmi->clk_parent = devm_clk_get(&pdev->dev, "parent"); -	if (IS_ERR(hdmi->clk_parent)) -		return PTR_ERR(hdmi->clk_parent); - -	err = clk_prepare(hdmi->clk_parent); -	if (err < 0) -		return err; - -	err = clk_set_parent(hdmi->clk, hdmi->clk_parent); -	if (err < 0) { -		dev_err(&pdev->dev, "failed to setup clocks: %d\n", err); -		return err; -	} - -	hdmi->vdd = devm_regulator_get(&pdev->dev, "vdd"); -	if (IS_ERR(hdmi->vdd)) { -		dev_err(&pdev->dev, "failed to get VDD regulator\n"); -		return PTR_ERR(hdmi->vdd); -	} - -	hdmi->pll = devm_regulator_get(&pdev->dev, "pll"); -	if (IS_ERR(hdmi->pll)) { -		dev_err(&pdev->dev, "failed to get PLL regulator\n"); -		return PTR_ERR(hdmi->pll); -	} - -	hdmi->output.dev = &pdev->dev; - -	err = tegra_output_parse_dt(&hdmi->output); -	if (err < 0) -		return err; - -	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!regs) -		return -ENXIO; - -	hdmi->regs = devm_ioremap_resource(&pdev->dev, regs); -	if (IS_ERR(hdmi->regs)) -		return PTR_ERR(hdmi->regs); - -	err = platform_get_irq(pdev, 0); -	if (err < 0) -		return err; - -	hdmi->irq = err; - -	hdmi->client.ops = &hdmi_client_ops; -	INIT_LIST_HEAD(&hdmi->client.list); -	hdmi->client.dev = &pdev->dev; - -	err = host1x_register_client(host1x, &hdmi->client); -	if (err < 0) { -		dev_err(&pdev->dev, "failed to register host1x client: %d\n", -			err); -		return err; -	} - -	platform_set_drvdata(pdev, hdmi); - -	return 0; -} - -static int tegra_hdmi_remove(struct platform_device *pdev) -{ -	struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent); -	struct tegra_hdmi *hdmi = platform_get_drvdata(pdev); -	int err; - -	err = host1x_unregister_client(host1x, &hdmi->client); -	if (err < 0) { -		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", -			err); -		return err; -	} - -	clk_unprepare(hdmi->clk_parent); -	clk_unprepare(hdmi->clk); - -	return 0; -} - -static struct of_device_id tegra_hdmi_of_match[] = { -	{ .compatible = "nvidia,tegra30-hdmi", }, -	{ .compatible = "nvidia,tegra20-hdmi", }, -	{ }, -}; - -struct platform_driver tegra_hdmi_driver = { -	.driver = { -		.name = "tegra-hdmi", -		.owner = THIS_MODULE, -		.of_match_table = tegra_hdmi_of_match, -	}, -	.probe = tegra_hdmi_probe, -	.remove = tegra_hdmi_remove, -}; diff --git a/drivers/gpu/host1x/drm/hdmi.h b/drivers/gpu/host1x/drm/hdmi.h deleted file mode 100644 index 52ac36e08cc..00000000000 --- a/drivers/gpu/host1x/drm/hdmi.h +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (C) 2012 Avionic Design GmbH - * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef TEGRA_HDMI_H -#define TEGRA_HDMI_H 1 - -/* register definitions */ -#define HDMI_CTXSW						0x00 - -#define HDMI_NV_PDISP_SOR_STATE0				0x01 -#define SOR_STATE_UPDATE (1 << 0) - -#define HDMI_NV_PDISP_SOR_STATE1				0x02 -#define SOR_STATE_ASY_HEAD_OPMODE_AWAKE (2 << 0) -#define SOR_STATE_ASY_ORMODE_NORMAL     (1 << 2) -#define SOR_STATE_ATTACHED              (1 << 3) - -#define HDMI_NV_PDISP_SOR_STATE2				0x03 -#define SOR_STATE_ASY_OWNER_NONE         (0 <<  0) -#define SOR_STATE_ASY_OWNER_HEAD0        (1 <<  0) -#define SOR_STATE_ASY_SUBOWNER_NONE      (0 <<  4) -#define SOR_STATE_ASY_SUBOWNER_SUBHEAD0  (1 <<  4) -#define SOR_STATE_ASY_SUBOWNER_SUBHEAD1  (2 <<  4) -#define SOR_STATE_ASY_SUBOWNER_BOTH      (3 <<  4) -#define SOR_STATE_ASY_CRCMODE_ACTIVE     (0 <<  6) -#define SOR_STATE_ASY_CRCMODE_COMPLETE   (1 <<  6) -#define SOR_STATE_ASY_CRCMODE_NON_ACTIVE (2 <<  6) -#define SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A (1 << 8) -#define SOR_STATE_ASY_PROTOCOL_CUSTOM        (15 << 8) -#define SOR_STATE_ASY_HSYNCPOL_POS       (0 << 12) -#define SOR_STATE_ASY_HSYNCPOL_NEG       (1 << 12) -#define SOR_STATE_ASY_VSYNCPOL_POS       (0 << 13) -#define SOR_STATE_ASY_VSYNCPOL_NEG       (1 << 13) -#define SOR_STATE_ASY_DEPOL_POS          (0 << 14) -#define SOR_STATE_ASY_DEPOL_NEG          (1 << 14) - -#define HDMI_NV_PDISP_RG_HDCP_AN_MSB				0x04 -#define HDMI_NV_PDISP_RG_HDCP_AN_LSB				0x05 -#define HDMI_NV_PDISP_RG_HDCP_CN_MSB				0x06 -#define HDMI_NV_PDISP_RG_HDCP_CN_LSB				0x07 -#define HDMI_NV_PDISP_RG_HDCP_AKSV_MSB				0x08 -#define HDMI_NV_PDISP_RG_HDCP_AKSV_LSB				0x09 -#define HDMI_NV_PDISP_RG_HDCP_BKSV_MSB				0x0a -#define HDMI_NV_PDISP_RG_HDCP_BKSV_LSB				0x0b -#define HDMI_NV_PDISP_RG_HDCP_CKSV_MSB				0x0c -#define HDMI_NV_PDISP_RG_HDCP_CKSV_LSB				0x0d -#define HDMI_NV_PDISP_RG_HDCP_DKSV_MSB				0x0e -#define HDMI_NV_PDISP_RG_HDCP_DKSV_LSB				0x0f -#define HDMI_NV_PDISP_RG_HDCP_CTRL				0x10 -#define HDMI_NV_PDISP_RG_HDCP_CMODE				0x11 -#define HDMI_NV_PDISP_RG_HDCP_MPRIME_MSB			0x12 -#define HDMI_NV_PDISP_RG_HDCP_MPRIME_LSB			0x13 -#define HDMI_NV_PDISP_RG_HDCP_SPRIME_MSB			0x14 -#define HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB2			0x15 -#define HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB1			0x16 -#define HDMI_NV_PDISP_RG_HDCP_RI				0x17 -#define HDMI_NV_PDISP_RG_HDCP_CS_MSB				0x18 -#define HDMI_NV_PDISP_RG_HDCP_CS_LSB				0x19 -#define HDMI_NV_PDISP_HDMI_AUDIO_EMU0				0x1a -#define HDMI_NV_PDISP_HDMI_AUDIO_EMU_RDATA0			0x1b -#define HDMI_NV_PDISP_HDMI_AUDIO_EMU1				0x1c -#define HDMI_NV_PDISP_HDMI_AUDIO_EMU2				0x1d - -#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL			0x1e -#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS		0x1f -#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER		0x20 -#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW		0x21 -#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH	0x22 -#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL			0x23 -#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS			0x24 -#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER			0x25 -#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW		0x26 -#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH		0x27 -#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW		0x28 -#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH		0x29 - -#define INFOFRAME_CTRL_ENABLE (1 << 0) - -#define INFOFRAME_HEADER_TYPE(x)    (((x) & 0xff) <<  0) -#define INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) <<  8) -#define INFOFRAME_HEADER_LEN(x)     (((x) & 0x0f) << 16) - -#define HDMI_NV_PDISP_HDMI_GENERIC_CTRL				0x2a -#define GENERIC_CTRL_ENABLE (1 <<  0) -#define GENERIC_CTRL_OTHER  (1 <<  4) -#define GENERIC_CTRL_SINGLE (1 <<  8) -#define GENERIC_CTRL_HBLANK (1 << 12) -#define GENERIC_CTRL_AUDIO  (1 << 16) - -#define HDMI_NV_PDISP_HDMI_GENERIC_STATUS			0x2b -#define HDMI_NV_PDISP_HDMI_GENERIC_HEADER			0x2c -#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW			0x2d -#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH		0x2e -#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW			0x2f -#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH		0x30 -#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW			0x31 -#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH		0x32 -#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW			0x33 -#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH		0x34 - -#define HDMI_NV_PDISP_HDMI_ACR_CTRL				0x35 -#define HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW			0x36 -#define HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH		0x37 -#define HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW			0x38 -#define HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH		0x39 -#define HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW			0x3a -#define HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH		0x3b -#define HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW			0x3c -#define HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH		0x3d -#define HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW			0x3e -#define HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH		0x3f -#define HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW			0x40 -#define HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH		0x41 -#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW			0x42 -#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH		0x43 - -#define ACR_SUBPACK_CTS(x) (((x) & 0xffffff) << 8) -#define ACR_SUBPACK_N(x)   (((x) & 0xffffff) << 0) -#define ACR_ENABLE         (1 << 31) - -#define HDMI_NV_PDISP_HDMI_CTRL					0x44 -#define HDMI_CTRL_REKEY(x)         (((x) & 0x7f) <<  0) -#define HDMI_CTRL_MAX_AC_PACKET(x) (((x) & 0x1f) << 16) -#define HDMI_CTRL_ENABLE           (1 << 30) - -#define HDMI_NV_PDISP_HDMI_VSYNC_KEEPOUT			0x45 -#define HDMI_NV_PDISP_HDMI_VSYNC_WINDOW				0x46 -#define VSYNC_WINDOW_END(x)   (((x) & 0x3ff) <<  0) -#define VSYNC_WINDOW_START(x) (((x) & 0x3ff) << 16) -#define VSYNC_WINDOW_ENABLE   (1 << 31) - -#define HDMI_NV_PDISP_HDMI_GCP_CTRL				0x47 -#define HDMI_NV_PDISP_HDMI_GCP_STATUS				0x48 -#define HDMI_NV_PDISP_HDMI_GCP_SUBPACK				0x49 -#define HDMI_NV_PDISP_HDMI_CHANNEL_STATUS1			0x4a -#define HDMI_NV_PDISP_HDMI_CHANNEL_STATUS2			0x4b -#define HDMI_NV_PDISP_HDMI_EMU0					0x4c -#define HDMI_NV_PDISP_HDMI_EMU1					0x4d -#define HDMI_NV_PDISP_HDMI_EMU1_RDATA				0x4e - -#define HDMI_NV_PDISP_HDMI_SPARE				0x4f -#define SPARE_HW_CTS           (1 << 0) -#define SPARE_FORCE_SW_CTS     (1 << 1) -#define SPARE_CTS_RESET_VAL(x) (((x) & 0x7) << 16) - -#define HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1			0x50 -#define HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS2			0x51 -#define HDMI_NV_PDISP_HDMI_HDCPRIF_ROM_CTRL			0x53 -#define HDMI_NV_PDISP_SOR_CAP					0x54 -#define HDMI_NV_PDISP_SOR_PWR					0x55 -#define SOR_PWR_NORMAL_STATE_PD     (0 <<  0) -#define SOR_PWR_NORMAL_STATE_PU     (1 <<  0) -#define SOR_PWR_NORMAL_START_NORMAL (0 <<  1) -#define SOR_PWR_NORMAL_START_ALT    (1 <<  1) -#define SOR_PWR_SAFE_STATE_PD       (0 << 16) -#define SOR_PWR_SAFE_STATE_PU       (1 << 16) -#define SOR_PWR_SETTING_NEW_DONE    (0 << 31) -#define SOR_PWR_SETTING_NEW_PENDING (1 << 31) -#define SOR_PWR_SETTING_NEW_TRIGGER (1 << 31) - -#define HDMI_NV_PDISP_SOR_TEST					0x56 -#define HDMI_NV_PDISP_SOR_PLL0					0x57 -#define SOR_PLL_PWR            (1 << 0) -#define SOR_PLL_PDBG           (1 << 1) -#define SOR_PLL_VCAPD          (1 << 2) -#define SOR_PLL_PDPORT         (1 << 3) -#define SOR_PLL_RESISTORSEL    (1 << 4) -#define SOR_PLL_PULLDOWN       (1 << 5) -#define SOR_PLL_VCOCAP(x)      (((x) & 0xf) <<  8) -#define SOR_PLL_BG_V17_S(x)    (((x) & 0xf) << 12) -#define SOR_PLL_FILTER(x)      (((x) & 0xf) << 16) -#define SOR_PLL_ICHPMP(x)      (((x) & 0xf) << 24) -#define SOR_PLL_TX_REG_LOAD(x) (((x) & 0xf) << 28) - -#define HDMI_NV_PDISP_SOR_PLL1					0x58 -#define SOR_PLL_TMDS_TERM_ENABLE (1 << 8) -#define SOR_PLL_TMDS_TERMADJ(x)  (((x) & 0xf) <<  9) -#define SOR_PLL_LOADADJ(x)       (((x) & 0xf) << 20) -#define SOR_PLL_PE_EN            (1 << 28) -#define SOR_PLL_HALF_FULL_PE     (1 << 29) -#define SOR_PLL_S_D_PIN_PE       (1 << 30) - -#define HDMI_NV_PDISP_SOR_PLL2					0x59 - -#define HDMI_NV_PDISP_SOR_CSTM					0x5a -#define SOR_CSTM_ROTCLK(x) (((x) & 0xf) << 24) - -#define HDMI_NV_PDISP_SOR_LVDS					0x5b -#define HDMI_NV_PDISP_SOR_CRCA					0x5c -#define HDMI_NV_PDISP_SOR_CRCB					0x5d -#define HDMI_NV_PDISP_SOR_BLANK					0x5e -#define HDMI_NV_PDISP_SOR_SEQ_CTL				0x5f -#define SOR_SEQ_CTL_PU_PC(x) (((x) & 0xf) <<  0) -#define SOR_SEQ_PU_PC_ALT(x) (((x) & 0xf) <<  4) -#define SOR_SEQ_PD_PC(x)     (((x) & 0xf) <<  8) -#define SOR_SEQ_PD_PC_ALT(x) (((x) & 0xf) << 12) -#define SOR_SEQ_PC(x)        (((x) & 0xf) << 16) -#define SOR_SEQ_STATUS       (1 << 28) -#define SOR_SEQ_SWITCH       (1 << 30) - -#define HDMI_NV_PDISP_SOR_SEQ_INST(x)				(0x60 + (x)) - -#define SOR_SEQ_INST_WAIT_TIME(x)     (((x) & 0x3ff) << 0) -#define SOR_SEQ_INST_WAIT_UNITS_VSYNC (2 << 12) -#define SOR_SEQ_INST_HALT             (1 << 15) -#define SOR_SEQ_INST_PIN_A_LOW        (0 << 21) -#define SOR_SEQ_INST_PIN_A_HIGH       (1 << 21) -#define SOR_SEQ_INST_PIN_B_LOW        (0 << 22) -#define SOR_SEQ_INST_PIN_B_HIGH       (1 << 22) -#define SOR_SEQ_INST_DRIVE_PWM_OUT_LO (1 << 23) - -#define HDMI_NV_PDISP_SOR_VCRCA0				0x72 -#define HDMI_NV_PDISP_SOR_VCRCA1				0x73 -#define HDMI_NV_PDISP_SOR_CCRCA0				0x74 -#define HDMI_NV_PDISP_SOR_CCRCA1				0x75 -#define HDMI_NV_PDISP_SOR_EDATAA0				0x76 -#define HDMI_NV_PDISP_SOR_EDATAA1				0x77 -#define HDMI_NV_PDISP_SOR_COUNTA0				0x78 -#define HDMI_NV_PDISP_SOR_COUNTA1				0x79 -#define HDMI_NV_PDISP_SOR_DEBUGA0				0x7a -#define HDMI_NV_PDISP_SOR_DEBUGA1				0x7b -#define HDMI_NV_PDISP_SOR_TRIG					0x7c -#define HDMI_NV_PDISP_SOR_MSCHECK				0x7d - -#define HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT			0x7e -#define DRIVE_CURRENT_LANE0(x)      (((x) & 0x3f) <<  0) -#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_FUSE_OVERRIDE (1 << 31) - -#define DRIVE_CURRENT_1_500_mA  0x00 -#define DRIVE_CURRENT_1_875_mA  0x01 -#define DRIVE_CURRENT_2_250_mA  0x02 -#define DRIVE_CURRENT_2_625_mA  0x03 -#define DRIVE_CURRENT_3_000_mA  0x04 -#define DRIVE_CURRENT_3_375_mA  0x05 -#define DRIVE_CURRENT_3_750_mA  0x06 -#define DRIVE_CURRENT_4_125_mA  0x07 -#define DRIVE_CURRENT_4_500_mA  0x08 -#define DRIVE_CURRENT_4_875_mA  0x09 -#define DRIVE_CURRENT_5_250_mA  0x0a -#define DRIVE_CURRENT_5_625_mA  0x0b -#define DRIVE_CURRENT_6_000_mA  0x0c -#define DRIVE_CURRENT_6_375_mA  0x0d -#define DRIVE_CURRENT_6_750_mA  0x0e -#define DRIVE_CURRENT_7_125_mA  0x0f -#define DRIVE_CURRENT_7_500_mA  0x10 -#define DRIVE_CURRENT_7_875_mA  0x11 -#define DRIVE_CURRENT_8_250_mA  0x12 -#define DRIVE_CURRENT_8_625_mA  0x13 -#define DRIVE_CURRENT_9_000_mA  0x14 -#define DRIVE_CURRENT_9_375_mA  0x15 -#define DRIVE_CURRENT_9_750_mA  0x16 -#define DRIVE_CURRENT_10_125_mA 0x17 -#define DRIVE_CURRENT_10_500_mA 0x18 -#define DRIVE_CURRENT_10_875_mA 0x19 -#define DRIVE_CURRENT_11_250_mA 0x1a -#define DRIVE_CURRENT_11_625_mA 0x1b -#define DRIVE_CURRENT_12_000_mA 0x1c -#define DRIVE_CURRENT_12_375_mA 0x1d -#define DRIVE_CURRENT_12_750_mA 0x1e -#define DRIVE_CURRENT_13_125_mA 0x1f -#define DRIVE_CURRENT_13_500_mA 0x20 -#define DRIVE_CURRENT_13_875_mA 0x21 -#define DRIVE_CURRENT_14_250_mA 0x22 -#define DRIVE_CURRENT_14_625_mA 0x23 -#define DRIVE_CURRENT_15_000_mA 0x24 -#define DRIVE_CURRENT_15_375_mA 0x25 -#define DRIVE_CURRENT_15_750_mA 0x26 -#define DRIVE_CURRENT_16_125_mA 0x27 -#define DRIVE_CURRENT_16_500_mA 0x28 -#define DRIVE_CURRENT_16_875_mA 0x29 -#define DRIVE_CURRENT_17_250_mA 0x2a -#define DRIVE_CURRENT_17_625_mA 0x2b -#define DRIVE_CURRENT_18_000_mA 0x2c -#define DRIVE_CURRENT_18_375_mA 0x2d -#define DRIVE_CURRENT_18_750_mA 0x2e -#define DRIVE_CURRENT_19_125_mA 0x2f -#define DRIVE_CURRENT_19_500_mA 0x30 -#define DRIVE_CURRENT_19_875_mA 0x31 -#define DRIVE_CURRENT_20_250_mA 0x32 -#define DRIVE_CURRENT_20_625_mA 0x33 -#define DRIVE_CURRENT_21_000_mA 0x34 -#define DRIVE_CURRENT_21_375_mA 0x35 -#define DRIVE_CURRENT_21_750_mA 0x36 -#define DRIVE_CURRENT_22_125_mA 0x37 -#define DRIVE_CURRENT_22_500_mA 0x38 -#define DRIVE_CURRENT_22_875_mA 0x39 -#define DRIVE_CURRENT_23_250_mA 0x3a -#define DRIVE_CURRENT_23_625_mA 0x3b -#define DRIVE_CURRENT_24_000_mA 0x3c -#define DRIVE_CURRENT_24_375_mA 0x3d -#define DRIVE_CURRENT_24_750_mA 0x3e - -#define HDMI_NV_PDISP_AUDIO_DEBUG0				0x7f -#define HDMI_NV_PDISP_AUDIO_DEBUG1				0x80 -#define HDMI_NV_PDISP_AUDIO_DEBUG2				0x81 - -#define HDMI_NV_PDISP_AUDIO_FS(x)				(0x82 + (x)) -#define AUDIO_FS_LOW(x)  (((x) & 0xfff) <<  0) -#define AUDIO_FS_HIGH(x) (((x) & 0xfff) << 16) - -#define HDMI_NV_PDISP_AUDIO_PULSE_WIDTH				0x89 -#define HDMI_NV_PDISP_AUDIO_THRESHOLD				0x8a -#define HDMI_NV_PDISP_AUDIO_CNTRL0				0x8b -#define AUDIO_CNTRL0_ERROR_TOLERANCE(x)  (((x) & 0xff) << 0) -#define AUDIO_CNTRL0_SOURCE_SELECT_AUTO  (0 << 20) -#define AUDIO_CNTRL0_SOURCE_SELECT_SPDIF (1 << 20) -#define AUDIO_CNTRL0_SOURCE_SELECT_HDAL  (2 << 20) -#define AUDIO_CNTRL0_FRAMES_PER_BLOCK(x) (((x) & 0xff) << 24) - -#define HDMI_NV_PDISP_AUDIO_N					0x8c -#define AUDIO_N_VALUE(x)           (((x) & 0xfffff) << 0) -#define AUDIO_N_RESETF             (1 << 20) -#define AUDIO_N_GENERATE_NORMAL    (0 << 24) -#define AUDIO_N_GENERATE_ALTERNATE (1 << 24) - -#define HDMI_NV_PDISP_HDCPRIF_ROM_TIMING			0x94 -#define HDMI_NV_PDISP_SOR_REFCLK				0x95 -#define SOR_REFCLK_DIV_INT(x)  (((x) & 0xff) << 8) -#define SOR_REFCLK_DIV_FRAC(x) (((x) & 0x03) << 6) - -#define HDMI_NV_PDISP_CRC_CONTROL				0x96 -#define HDMI_NV_PDISP_INPUT_CONTROL				0x97 -#define HDMI_SRC_DISPLAYA       (0 << 0) -#define HDMI_SRC_DISPLAYB       (1 << 0) -#define ARM_VIDEO_RANGE_FULL    (0 << 1) -#define ARM_VIDEO_RANGE_LIMITED (1 << 1) - -#define HDMI_NV_PDISP_SCRATCH					0x98 -#define HDMI_NV_PDISP_PE_CURRENT				0x99 -#define PE_CURRENT0(x) (((x) & 0xf) << 0) -#define PE_CURRENT1(x) (((x) & 0xf) << 8) -#define PE_CURRENT2(x) (((x) & 0xf) << 16) -#define PE_CURRENT3(x) (((x) & 0xf) << 24) - -#define PE_CURRENT_0_0_mA 0x0 -#define PE_CURRENT_0_5_mA 0x1 -#define PE_CURRENT_1_0_mA 0x2 -#define PE_CURRENT_1_5_mA 0x3 -#define PE_CURRENT_2_0_mA 0x4 -#define PE_CURRENT_2_5_mA 0x5 -#define PE_CURRENT_3_0_mA 0x6 -#define PE_CURRENT_3_5_mA 0x7 -#define PE_CURRENT_4_0_mA 0x8 -#define PE_CURRENT_4_5_mA 0x9 -#define PE_CURRENT_5_0_mA 0xa -#define PE_CURRENT_5_5_mA 0xb -#define PE_CURRENT_6_0_mA 0xc -#define PE_CURRENT_6_5_mA 0xd -#define PE_CURRENT_7_0_mA 0xe -#define PE_CURRENT_7_5_mA 0xf - -#define HDMI_NV_PDISP_KEY_CTRL					0x9a -#define HDMI_NV_PDISP_KEY_DEBUG0				0x9b -#define HDMI_NV_PDISP_KEY_DEBUG1				0x9c -#define HDMI_NV_PDISP_KEY_DEBUG2				0x9d -#define HDMI_NV_PDISP_KEY_HDCP_KEY_0				0x9e -#define HDMI_NV_PDISP_KEY_HDCP_KEY_1				0x9f -#define HDMI_NV_PDISP_KEY_HDCP_KEY_2				0xa0 -#define HDMI_NV_PDISP_KEY_HDCP_KEY_3				0xa1 -#define HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG				0xa2 -#define HDMI_NV_PDISP_KEY_SKEY_INDEX				0xa3 - -#define HDMI_NV_PDISP_SOR_AUDIO_CNTRL0				0xac -#define AUDIO_CNTRL0_INJECT_NULLSMPL (1 << 29) -#define HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR			0xbc -#define HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE			0xbd - -#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320    0xbf -#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441    0xc0 -#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882    0xc1 -#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764    0xc2 -#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480    0xc3 -#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960    0xc4 -#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920    0xc5 -#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_DEFAULT 0xc5 - -#endif /* TEGRA_HDMI_H */ diff --git a/drivers/gpu/host1x/drm/output.c b/drivers/gpu/host1x/drm/output.c deleted file mode 100644 index 137ae81ab80..00000000000 --- a/drivers/gpu/host1x/drm/output.c +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (C) 2012 Avionic Design GmbH - * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/module.h> -#include <linux/of_gpio.h> -#include <linux/i2c.h> - -#include "drm.h" - -static int tegra_connector_get_modes(struct drm_connector *connector) -{ -	struct tegra_output *output = connector_to_output(connector); -	struct edid *edid = NULL; -	int err = 0; - -	if (output->edid) -		edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL); -	else if (output->ddc) -		edid = drm_get_edid(connector, output->ddc); - -	drm_mode_connector_update_edid_property(connector, edid); - -	if (edid) { -		err = drm_add_edid_modes(connector, edid); -		kfree(edid); -	} - -	return err; -} - -static int tegra_connector_mode_valid(struct drm_connector *connector, -				      struct drm_display_mode *mode) -{ -	struct tegra_output *output = connector_to_output(connector); -	enum drm_mode_status status = MODE_OK; -	int err; - -	err = tegra_output_check_mode(output, mode, &status); -	if (err < 0) -		return MODE_ERROR; - -	return status; -} - -static struct drm_encoder * -tegra_connector_best_encoder(struct drm_connector *connector) -{ -	struct tegra_output *output = connector_to_output(connector); - -	return &output->encoder; -} - -static const struct drm_connector_helper_funcs connector_helper_funcs = { -	.get_modes = tegra_connector_get_modes, -	.mode_valid = tegra_connector_mode_valid, -	.best_encoder = tegra_connector_best_encoder, -}; - -static enum drm_connector_status -tegra_connector_detect(struct drm_connector *connector, bool force) -{ -	struct tegra_output *output = connector_to_output(connector); -	enum drm_connector_status status = connector_status_unknown; - -	if (gpio_is_valid(output->hpd_gpio)) { -		if (gpio_get_value(output->hpd_gpio) == 0) -			status = connector_status_disconnected; -		else -			status = connector_status_connected; -	} else { -		if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) -			status = connector_status_connected; -	} - -	return status; -} - -static void tegra_connector_destroy(struct drm_connector *connector) -{ -	drm_sysfs_connector_remove(connector); -	drm_connector_cleanup(connector); -} - -static const struct drm_connector_funcs connector_funcs = { -	.dpms = drm_helper_connector_dpms, -	.detect = tegra_connector_detect, -	.fill_modes = drm_helper_probe_single_connector_modes, -	.destroy = tegra_connector_destroy, -}; - -static void tegra_encoder_destroy(struct drm_encoder *encoder) -{ -	drm_encoder_cleanup(encoder); -} - -static const struct drm_encoder_funcs encoder_funcs = { -	.destroy = tegra_encoder_destroy, -}; - -static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode) -{ -} - -static bool tegra_encoder_mode_fixup(struct drm_encoder *encoder, -				     const struct drm_display_mode *mode, -				     struct drm_display_mode *adjusted) -{ -	return true; -} - -static void tegra_encoder_prepare(struct drm_encoder *encoder) -{ -} - -static void tegra_encoder_commit(struct drm_encoder *encoder) -{ -} - -static void tegra_encoder_mode_set(struct drm_encoder *encoder, -				   struct drm_display_mode *mode, -				   struct drm_display_mode *adjusted) -{ -	struct tegra_output *output = encoder_to_output(encoder); -	int err; - -	err = tegra_output_enable(output); -	if (err < 0) -		dev_err(encoder->dev->dev, "tegra_output_enable(): %d\n", err); -} - -static const struct drm_encoder_helper_funcs encoder_helper_funcs = { -	.dpms = tegra_encoder_dpms, -	.mode_fixup = tegra_encoder_mode_fixup, -	.prepare = tegra_encoder_prepare, -	.commit = tegra_encoder_commit, -	.mode_set = tegra_encoder_mode_set, -}; - -static irqreturn_t hpd_irq(int irq, void *data) -{ -	struct tegra_output *output = data; - -	drm_helper_hpd_irq_event(output->connector.dev); - -	return IRQ_HANDLED; -} - -int tegra_output_parse_dt(struct tegra_output *output) -{ -	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; - -	output->edid = of_get_property(output->of_node, "nvidia,edid", &size); - -	ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0); -	if (ddc) { -		output->ddc = of_find_i2c_adapter_by_node(ddc); -		if (!output->ddc) { -			err = -EPROBE_DEFER; -			of_node_put(ddc); -			return err; -		} - -		of_node_put(ddc); -	} - -	if (!output->edid && !output->ddc) -		return -ENODEV; - -	output->hpd_gpio = of_get_named_gpio_flags(output->of_node, -						   "nvidia,hpd-gpio", 0, -						   &flags); - -	return 0; -} - -int tegra_output_init(struct drm_device *drm, struct tegra_output *output) -{ -	int connector, encoder, err; - -	if (gpio_is_valid(output->hpd_gpio)) { -		unsigned long flags; - -		err = gpio_request_one(output->hpd_gpio, GPIOF_DIR_IN, -				       "HDMI hotplug detect"); -		if (err < 0) { -			dev_err(output->dev, "gpio_request_one(): %d\n", err); -			return err; -		} - -		err = gpio_to_irq(output->hpd_gpio); -		if (err < 0) { -			dev_err(output->dev, "gpio_to_irq(): %d\n", err); -			goto free_hpd; -		} - -		output->hpd_irq = err; - -		flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | -			IRQF_ONESHOT; - -		err = request_threaded_irq(output->hpd_irq, NULL, hpd_irq, -					   flags, "hpd", output); -		if (err < 0) { -			dev_err(output->dev, "failed to request IRQ#%u: %d\n", -				output->hpd_irq, err); -			goto free_hpd; -		} - -		output->connector.polled = DRM_CONNECTOR_POLL_HPD; -	} - -	switch (output->type) { -	case TEGRA_OUTPUT_RGB: -		connector = DRM_MODE_CONNECTOR_LVDS; -		encoder = DRM_MODE_ENCODER_LVDS; -		break; - -	case TEGRA_OUTPUT_HDMI: -		connector = DRM_MODE_CONNECTOR_HDMIA; -		encoder = DRM_MODE_ENCODER_TMDS; -		break; - -	default: -		connector = DRM_MODE_CONNECTOR_Unknown; -		encoder = DRM_MODE_ENCODER_NONE; -		break; -	} - -	drm_connector_init(drm, &output->connector, &connector_funcs, -			   connector); -	drm_connector_helper_add(&output->connector, &connector_helper_funcs); - -	drm_encoder_init(drm, &output->encoder, &encoder_funcs, encoder); -	drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs); - -	drm_mode_connector_attach_encoder(&output->connector, &output->encoder); -	drm_sysfs_connector_add(&output->connector); - -	output->encoder.possible_crtcs = 0x3; - -	return 0; - -free_hpd: -	gpio_free(output->hpd_gpio); - -	return err; -} - -int tegra_output_exit(struct tegra_output *output) -{ -	if (gpio_is_valid(output->hpd_gpio)) { -		free_irq(output->hpd_irq, output); -		gpio_free(output->hpd_gpio); -	} - -	if (output->ddc) -		put_device(&output->ddc->dev); - -	return 0; -} diff --git a/drivers/gpu/host1x/drm/rgb.c b/drivers/gpu/host1x/drm/rgb.c deleted file mode 100644 index 5aa66ef7a94..00000000000 --- a/drivers/gpu/host1x/drm/rgb.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (C) 2012 Avionic Design GmbH - * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/clk.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/platform_device.h> - -#include "drm.h" -#include "dc.h" - -struct tegra_rgb { -	struct tegra_output output; -	struct clk *clk_parent; -	struct clk *clk; -}; - -static inline struct tegra_rgb *to_rgb(struct tegra_output *output) -{ -	return container_of(output, struct tegra_rgb, output); -} - -struct reg_entry { -	unsigned long offset; -	unsigned long value; -}; - -static const struct reg_entry rgb_enable[] = { -	{ DC_COM_PIN_OUTPUT_ENABLE(0),   0x00000000 }, -	{ DC_COM_PIN_OUTPUT_ENABLE(1),   0x00000000 }, -	{ DC_COM_PIN_OUTPUT_ENABLE(2),   0x00000000 }, -	{ DC_COM_PIN_OUTPUT_ENABLE(3),   0x00000000 }, -	{ DC_COM_PIN_OUTPUT_POLARITY(0), 0x00000000 }, -	{ DC_COM_PIN_OUTPUT_POLARITY(1), 0x01000000 }, -	{ DC_COM_PIN_OUTPUT_POLARITY(2), 0x00000000 }, -	{ DC_COM_PIN_OUTPUT_POLARITY(3), 0x00000000 }, -	{ DC_COM_PIN_OUTPUT_DATA(0),     0x00000000 }, -	{ DC_COM_PIN_OUTPUT_DATA(1),     0x00000000 }, -	{ DC_COM_PIN_OUTPUT_DATA(2),     0x00000000 }, -	{ DC_COM_PIN_OUTPUT_DATA(3),     0x00000000 }, -	{ DC_COM_PIN_OUTPUT_SELECT(0),   0x00000000 }, -	{ DC_COM_PIN_OUTPUT_SELECT(1),   0x00000000 }, -	{ DC_COM_PIN_OUTPUT_SELECT(2),   0x00000000 }, -	{ DC_COM_PIN_OUTPUT_SELECT(3),   0x00000000 }, -	{ DC_COM_PIN_OUTPUT_SELECT(4),   0x00210222 }, -	{ DC_COM_PIN_OUTPUT_SELECT(5),   0x00002200 }, -	{ DC_COM_PIN_OUTPUT_SELECT(6),   0x00020000 }, -}; - -static const struct reg_entry rgb_disable[] = { -	{ DC_COM_PIN_OUTPUT_SELECT(6),   0x00000000 }, -	{ DC_COM_PIN_OUTPUT_SELECT(5),   0x00000000 }, -	{ DC_COM_PIN_OUTPUT_SELECT(4),   0x00000000 }, -	{ DC_COM_PIN_OUTPUT_SELECT(3),   0x00000000 }, -	{ DC_COM_PIN_OUTPUT_SELECT(2),   0x00000000 }, -	{ DC_COM_PIN_OUTPUT_SELECT(1),   0x00000000 }, -	{ DC_COM_PIN_OUTPUT_SELECT(0),   0x00000000 }, -	{ DC_COM_PIN_OUTPUT_DATA(3),     0xaaaaaaaa }, -	{ DC_COM_PIN_OUTPUT_DATA(2),     0xaaaaaaaa }, -	{ DC_COM_PIN_OUTPUT_DATA(1),     0xaaaaaaaa }, -	{ DC_COM_PIN_OUTPUT_DATA(0),     0xaaaaaaaa }, -	{ DC_COM_PIN_OUTPUT_POLARITY(3), 0x00000000 }, -	{ DC_COM_PIN_OUTPUT_POLARITY(2), 0x00000000 }, -	{ DC_COM_PIN_OUTPUT_POLARITY(1), 0x00000000 }, -	{ DC_COM_PIN_OUTPUT_POLARITY(0), 0x00000000 }, -	{ DC_COM_PIN_OUTPUT_ENABLE(3),   0x55555555 }, -	{ DC_COM_PIN_OUTPUT_ENABLE(2),   0x55555555 }, -	{ DC_COM_PIN_OUTPUT_ENABLE(1),   0x55150005 }, -	{ DC_COM_PIN_OUTPUT_ENABLE(0),   0x55555555 }, -}; - -static void tegra_dc_write_regs(struct tegra_dc *dc, -				const struct reg_entry *table, -				unsigned int num) -{ -	unsigned int i; - -	for (i = 0; i < num; i++) -		tegra_dc_writel(dc, table[i].value, table[i].offset); -} - -static int tegra_output_rgb_enable(struct tegra_output *output) -{ -	struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc); - -	tegra_dc_write_regs(dc, rgb_enable, ARRAY_SIZE(rgb_enable)); - -	return 0; -} - -static int tegra_output_rgb_disable(struct tegra_output *output) -{ -	struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc); - -	tegra_dc_write_regs(dc, rgb_disable, ARRAY_SIZE(rgb_disable)); - -	return 0; -} - -static int tegra_output_rgb_setup_clock(struct tegra_output *output, -					struct clk *clk, unsigned long pclk) -{ -	struct tegra_rgb *rgb = to_rgb(output); - -	return clk_set_parent(clk, rgb->clk_parent); -} - -static int tegra_output_rgb_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. There are -	 * unresolved issues with clk_round_rate(), which doesn't always -	 * reliably report whether a frequency can be set or not. -	 */ - -	*status = MODE_OK; - -	return 0; -} - -static const struct tegra_output_ops rgb_ops = { -	.enable = tegra_output_rgb_enable, -	.disable = tegra_output_rgb_disable, -	.setup_clock = tegra_output_rgb_setup_clock, -	.check_mode = tegra_output_rgb_check_mode, -}; - -int tegra_dc_rgb_probe(struct tegra_dc *dc) -{ -	struct device_node *np; -	struct tegra_rgb *rgb; -	int err; - -	np = of_get_child_by_name(dc->dev->of_node, "rgb"); -	if (!np || !of_device_is_available(np)) -		return -ENODEV; - -	rgb = devm_kzalloc(dc->dev, sizeof(*rgb), GFP_KERNEL); -	if (!rgb) -		return -ENOMEM; - -	rgb->output.dev = dc->dev; -	rgb->output.of_node = np; - -	err = tegra_output_parse_dt(&rgb->output); -	if (err < 0) -		return err; - -	rgb->clk = devm_clk_get(dc->dev, NULL); -	if (IS_ERR(rgb->clk)) { -		dev_err(dc->dev, "failed to get clock\n"); -		return PTR_ERR(rgb->clk); -	} - -	rgb->clk_parent = devm_clk_get(dc->dev, "parent"); -	if (IS_ERR(rgb->clk_parent)) { -		dev_err(dc->dev, "failed to get parent clock\n"); -		return PTR_ERR(rgb->clk_parent); -	} - -	err = clk_set_parent(rgb->clk, rgb->clk_parent); -	if (err < 0) { -		dev_err(dc->dev, "failed to set parent clock: %d\n", err); -		return err; -	} - -	dc->rgb = &rgb->output; - -	return 0; -} - -int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc) -{ -	struct tegra_rgb *rgb = to_rgb(dc->rgb); -	int err; - -	if (!dc->rgb) -		return -ENODEV; - -	rgb->output.type = TEGRA_OUTPUT_RGB; -	rgb->output.ops = &rgb_ops; - -	err = tegra_output_init(dc->base.dev, &rgb->output); -	if (err < 0) { -		dev_err(dc->dev, "output setup failed: %d\n", err); -		return err; -	} - -	/* -	 * By default, outputs can be associated with each display controller. -	 * RGB outputs are an exception, so we make sure they can be attached -	 * to only their parent display controller. -	 */ -	rgb->output.encoder.possible_crtcs = 1 << dc->pipe; - -	return 0; -} - -int tegra_dc_rgb_exit(struct tegra_dc *dc) -{ -	if (dc->rgb) { -		int err; - -		err = tegra_output_disable(dc->rgb); -		if (err < 0) { -			dev_err(dc->dev, "output failed to disable: %d\n", err); -			return err; -		} - -		err = tegra_output_exit(dc->rgb); -		if (err < 0) { -			dev_err(dc->dev, "output cleanup failed: %d\n", err); -			return err; -		} - -		dc->rgb = NULL; -	} - -	return 0; -} diff --git a/drivers/gpu/host1x/host1x.h b/drivers/gpu/host1x/host1x.h deleted file mode 100644 index a2bc1e65e97..00000000000 --- a/drivers/gpu/host1x/host1x.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Tegra host1x driver - * - * Copyright (c) 2009-2013, NVIDIA Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. - */ - -#ifndef __LINUX_HOST1X_H -#define __LINUX_HOST1X_H - -enum host1x_class { -	HOST1X_CLASS_HOST1X	= 0x1, -	HOST1X_CLASS_GR2D	= 0x51, -	HOST1X_CLASS_GR2D_SB    = 0x52 -}; - -#endif diff --git a/drivers/gpu/host1x/host1x_bo.h b/drivers/gpu/host1x/host1x_bo.h deleted file mode 100644 index 4c1f10bd773..00000000000 --- 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/Makefile b/drivers/gpu/host1x/hw/Makefile deleted file mode 100644 index 9b50863a223..00000000000 --- a/drivers/gpu/host1x/hw/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -ccflags-y = -Idrivers/gpu/host1x - -host1x-hw-objs  = \ -	host1x01.o - -obj-$(CONFIG_TEGRA_HOST1X) += host1x-hw.o diff --git a/drivers/gpu/host1x/hw/cdma_hw.c b/drivers/gpu/host1x/hw/cdma_hw.c index 2ee4ad55c4d..6b09b71940c 100644 --- a/drivers/gpu/host1x/hw/cdma_hw.c +++ b/drivers/gpu/host1x/hw/cdma_hw.c @@ -20,10 +20,10 @@  #include <linux/scatterlist.h>  #include <linux/dma-mapping.h> -#include "cdma.h" -#include "channel.h" -#include "dev.h" -#include "debug.h" +#include "../cdma.h" +#include "../channel.h" +#include "../dev.h" +#include "../debug.h"  /*   * Put the restart at the end of pushbuffer memor @@ -54,8 +54,8 @@ static void cdma_timeout_cpu_incr(struct host1x_cdma *cdma, u32 getptr,  		u32 *p = (u32 *)((u32)pb->mapped + getptr);  		*(p++) = HOST1X_OPCODE_NOP;  		*(p++) = HOST1X_OPCODE_NOP; -		dev_dbg(host1x->dev, "%s: NOP at 0x%x\n", __func__, -			pb->phys + getptr); +		dev_dbg(host1x->dev, "%s: NOP at %#llx\n", __func__, +			(u64)pb->phys + getptr);  		getptr = (getptr + 8) & (pb->size_bytes - 1);  	}  	wmb(); diff --git a/drivers/gpu/host1x/hw/channel_hw.c b/drivers/gpu/host1x/hw/channel_hw.c index ee199623e36..4608257ab65 100644 --- a/drivers/gpu/host1x/hw/channel_hw.c +++ b/drivers/gpu/host1x/hw/channel_hw.c @@ -16,15 +16,15 @@   * 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" -#include "intr.h" -#include "job.h" +#include "../channel.h" +#include "../dev.h" +#include "../intr.h" +#include "../job.h"  #define HOST1X_CHANNEL_SIZE 16384  #define TRACE_MAX_LENGTH 128U @@ -67,6 +67,22 @@ static void submit_gathers(struct host1x_job *job)  	}  } +static inline void synchronize_syncpt_base(struct host1x_job *job) +{ +	struct host1x *host = dev_get_drvdata(job->channel->dev->parent); +	struct host1x_syncpt *sp = host->syncpt + job->syncpt_id; +	u32 id, value; + +	value = host1x_syncpt_read_max(sp); +	id = sp->base->id; + +	host1x_cdma_push(&job->channel->cdma, +			 host1x_opcode_setclass(HOST1X_CLASS_HOST1X, +				HOST1X_UCLASS_LOAD_SYNCPT_BASE, 1), +			 HOST1X_UCLASS_LOAD_SYNCPT_BASE_BASE_INDX_F(id) | +			 HOST1X_UCLASS_LOAD_SYNCPT_BASE_VALUE_F(value)); +} +  static int channel_submit(struct host1x_job *job)  {  	struct host1x_channel *ch = job->channel; @@ -118,6 +134,10 @@ static int channel_submit(struct host1x_job *job)  					host1x_syncpt_read_max(sp)));  	} +	/* Synchronize base register to allow using it for relative waiting */ +	if (sp->base) +		synchronize_syncpt_base(job); +  	syncval = host1x_syncpt_incr_max(sp, user_syncpt_incrs);  	job->syncpt_end = syncval; diff --git a/drivers/gpu/host1x/hw/debug_hw.c b/drivers/gpu/host1x/hw/debug_hw.c index 334c038052f..f72c873eff8 100644 --- a/drivers/gpu/host1x/hw/debug_hw.c +++ b/drivers/gpu/host1x/hw/debug_hw.c @@ -15,18 +15,10 @@   *   */ -#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" -#include "channel.h" -#include "host1x_bo.h" +#include "../dev.h" +#include "../debug.h" +#include "../cdma.h" +#include "../channel.h"  #define HOST1X_DEBUG_MAX_PAGE_OFFSET 102400 @@ -171,8 +163,8 @@ static void show_channel_gathers(struct output *o, struct host1x_cdma *cdma)  				continue;  			} -			host1x_debug_output(o, "    GATHER at %08x+%04x, %d words\n", -					    g->base, g->offset, g->words); +			host1x_debug_output(o, "    GATHER at %#llx+%04x, %d words\n", +					    (u64)g->base, g->offset, g->words);  			show_gather(o, g->base + g->offset, g->words, cdma,  				    g->base, mapped); diff --git a/drivers/gpu/host1x/hw/host1x01.c b/drivers/gpu/host1x/hw/host1x01.c index a14e91cd1e5..859b73beb4d 100644 --- a/drivers/gpu/host1x/hw/host1x01.c +++ b/drivers/gpu/host1x/hw/host1x01.c @@ -17,17 +17,17 @@   */  /* include hw specification */ -#include "hw/host1x01.h" -#include "hw/host1x01_hardware.h" +#include "host1x01.h" +#include "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 "cdma_hw.c" +#include "channel_hw.c" +#include "debug_hw.c" +#include "intr_hw.c" +#include "syncpt_hw.c" -#include "dev.h" +#include "../dev.h"  int host1x01_init(struct host1x *host)  { diff --git a/drivers/gpu/host1x/hw/host1x02.c b/drivers/gpu/host1x/hw/host1x02.c new file mode 100644 index 00000000000..928946c2144 --- /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 "host1x02.h" +#include "host1x02_hardware.h" + +/* include code */ +#include "cdma_hw.c" +#include "channel_hw.c" +#include "debug_hw.c" +#include "intr_hw.c" +#include "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 00000000000..f7486609a90 --- /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/host1x02_hardware.h b/drivers/gpu/host1x/hw/host1x02_hardware.h new file mode 100644 index 00000000000..154901860bc --- /dev/null +++ b/drivers/gpu/host1x/hw/host1x02_hardware.h @@ -0,0 +1,142 @@ +/* + * Tegra host1x Register Offsets for Tegra114 + * + * Copyright (c) 2010-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_HARDWARE_H +#define __HOST1X_HOST1X02_HARDWARE_H + +#include <linux/types.h> +#include <linux/bitops.h> + +#include "hw_host1x02_channel.h" +#include "hw_host1x02_sync.h" +#include "hw_host1x02_uclass.h" + +static inline u32 host1x_class_host_wait_syncpt( +	unsigned indx, unsigned threshold) +{ +	return host1x_uclass_wait_syncpt_indx_f(indx) +		| host1x_uclass_wait_syncpt_thresh_f(threshold); +} + +static inline u32 host1x_class_host_load_syncpt_base( +	unsigned indx, unsigned threshold) +{ +	return host1x_uclass_load_syncpt_base_base_indx_f(indx) +		| host1x_uclass_load_syncpt_base_value_f(threshold); +} + +static inline u32 host1x_class_host_wait_syncpt_base( +	unsigned indx, unsigned base_indx, unsigned offset) +{ +	return host1x_uclass_wait_syncpt_base_indx_f(indx) +		| host1x_uclass_wait_syncpt_base_base_indx_f(base_indx) +		| host1x_uclass_wait_syncpt_base_offset_f(offset); +} + +static inline u32 host1x_class_host_incr_syncpt_base( +	unsigned base_indx, unsigned offset) +{ +	return host1x_uclass_incr_syncpt_base_base_indx_f(base_indx) +		| host1x_uclass_incr_syncpt_base_offset_f(offset); +} + +static inline u32 host1x_class_host_incr_syncpt( +	unsigned cond, unsigned indx) +{ +	return host1x_uclass_incr_syncpt_cond_f(cond) +		| host1x_uclass_incr_syncpt_indx_f(indx); +} + +static inline u32 host1x_class_host_indoff_reg_write( +	unsigned mod_id, unsigned offset, bool auto_inc) +{ +	u32 v = host1x_uclass_indoff_indbe_f(0xf) +		| host1x_uclass_indoff_indmodid_f(mod_id) +		| host1x_uclass_indoff_indroffset_f(offset); +	if (auto_inc) +		v |= host1x_uclass_indoff_autoinc_f(1); +	return v; +} + +static inline u32 host1x_class_host_indoff_reg_read( +	unsigned mod_id, unsigned offset, bool auto_inc) +{ +	u32 v = host1x_uclass_indoff_indmodid_f(mod_id) +		| host1x_uclass_indoff_indroffset_f(offset) +		| host1x_uclass_indoff_rwn_read_v(); +	if (auto_inc) +		v |= host1x_uclass_indoff_autoinc_f(1); +	return v; +} + +/* cdma opcodes */ +static inline u32 host1x_opcode_setclass( +	unsigned class_id, unsigned offset, unsigned mask) +{ +	return (0 << 28) | (offset << 16) | (class_id << 6) | mask; +} + +static inline u32 host1x_opcode_incr(unsigned offset, unsigned count) +{ +	return (1 << 28) | (offset << 16) | count; +} + +static inline u32 host1x_opcode_nonincr(unsigned offset, unsigned count) +{ +	return (2 << 28) | (offset << 16) | count; +} + +static inline u32 host1x_opcode_mask(unsigned offset, unsigned mask) +{ +	return (3 << 28) | (offset << 16) | mask; +} + +static inline u32 host1x_opcode_imm(unsigned offset, unsigned value) +{ +	return (4 << 28) | (offset << 16) | value; +} + +static inline u32 host1x_opcode_imm_incr_syncpt(unsigned cond, unsigned indx) +{ +	return host1x_opcode_imm(host1x_uclass_incr_syncpt_r(), +		host1x_class_host_incr_syncpt(cond, indx)); +} + +static inline u32 host1x_opcode_restart(unsigned address) +{ +	return (5 << 28) | (address >> 4); +} + +static inline u32 host1x_opcode_gather(unsigned count) +{ +	return (6 << 28) | count; +} + +static inline u32 host1x_opcode_gather_nonincr(unsigned offset,	unsigned count) +{ +	return (6 << 28) | (offset << 16) | BIT(15) | count; +} + +static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count) +{ +	return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count; +} + +#define HOST1X_OPCODE_NOP host1x_opcode_nonincr(0, 0) + +#endif diff --git a/drivers/gpu/host1x/hw/host1x04.c b/drivers/gpu/host1x/hw/host1x04.c new file mode 100644 index 00000000000..8007c70fa9c --- /dev/null +++ b/drivers/gpu/host1x/hw/host1x04.c @@ -0,0 +1,42 @@ +/* + * Host1x init for Tegra124 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 "host1x04.h" +#include "host1x04_hardware.h" + +/* include code */ +#include "cdma_hw.c" +#include "channel_hw.c" +#include "debug_hw.c" +#include "intr_hw.c" +#include "syncpt_hw.c" + +#include "../dev.h" + +int host1x04_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/host1x04.h b/drivers/gpu/host1x/hw/host1x04.h new file mode 100644 index 00000000000..a9ab7496c06 --- /dev/null +++ b/drivers/gpu/host1x/hw/host1x04.h @@ -0,0 +1,26 @@ +/* + * Host1x init for Tegra124 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_HOST1X04_H +#define HOST1X_HOST1X04_H + +struct host1x; + +int host1x04_init(struct host1x *host); + +#endif diff --git a/drivers/gpu/host1x/hw/host1x04_hardware.h b/drivers/gpu/host1x/hw/host1x04_hardware.h new file mode 100644 index 00000000000..de1a3817532 --- /dev/null +++ b/drivers/gpu/host1x/hw/host1x04_hardware.h @@ -0,0 +1,142 @@ +/* + * Tegra host1x Register Offsets for Tegra124 + * + * Copyright (c) 2010-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_HOST1X04_HARDWARE_H +#define __HOST1X_HOST1X04_HARDWARE_H + +#include <linux/types.h> +#include <linux/bitops.h> + +#include "hw_host1x04_channel.h" +#include "hw_host1x04_sync.h" +#include "hw_host1x04_uclass.h" + +static inline u32 host1x_class_host_wait_syncpt( +	unsigned indx, unsigned threshold) +{ +	return host1x_uclass_wait_syncpt_indx_f(indx) +		| host1x_uclass_wait_syncpt_thresh_f(threshold); +} + +static inline u32 host1x_class_host_load_syncpt_base( +	unsigned indx, unsigned threshold) +{ +	return host1x_uclass_load_syncpt_base_base_indx_f(indx) +		| host1x_uclass_load_syncpt_base_value_f(threshold); +} + +static inline u32 host1x_class_host_wait_syncpt_base( +	unsigned indx, unsigned base_indx, unsigned offset) +{ +	return host1x_uclass_wait_syncpt_base_indx_f(indx) +		| host1x_uclass_wait_syncpt_base_base_indx_f(base_indx) +		| host1x_uclass_wait_syncpt_base_offset_f(offset); +} + +static inline u32 host1x_class_host_incr_syncpt_base( +	unsigned base_indx, unsigned offset) +{ +	return host1x_uclass_incr_syncpt_base_base_indx_f(base_indx) +		| host1x_uclass_incr_syncpt_base_offset_f(offset); +} + +static inline u32 host1x_class_host_incr_syncpt( +	unsigned cond, unsigned indx) +{ +	return host1x_uclass_incr_syncpt_cond_f(cond) +		| host1x_uclass_incr_syncpt_indx_f(indx); +} + +static inline u32 host1x_class_host_indoff_reg_write( +	unsigned mod_id, unsigned offset, bool auto_inc) +{ +	u32 v = host1x_uclass_indoff_indbe_f(0xf) +		| host1x_uclass_indoff_indmodid_f(mod_id) +		| host1x_uclass_indoff_indroffset_f(offset); +	if (auto_inc) +		v |= host1x_uclass_indoff_autoinc_f(1); +	return v; +} + +static inline u32 host1x_class_host_indoff_reg_read( +	unsigned mod_id, unsigned offset, bool auto_inc) +{ +	u32 v = host1x_uclass_indoff_indmodid_f(mod_id) +		| host1x_uclass_indoff_indroffset_f(offset) +		| host1x_uclass_indoff_rwn_read_v(); +	if (auto_inc) +		v |= host1x_uclass_indoff_autoinc_f(1); +	return v; +} + +/* cdma opcodes */ +static inline u32 host1x_opcode_setclass( +	unsigned class_id, unsigned offset, unsigned mask) +{ +	return (0 << 28) | (offset << 16) | (class_id << 6) | mask; +} + +static inline u32 host1x_opcode_incr(unsigned offset, unsigned count) +{ +	return (1 << 28) | (offset << 16) | count; +} + +static inline u32 host1x_opcode_nonincr(unsigned offset, unsigned count) +{ +	return (2 << 28) | (offset << 16) | count; +} + +static inline u32 host1x_opcode_mask(unsigned offset, unsigned mask) +{ +	return (3 << 28) | (offset << 16) | mask; +} + +static inline u32 host1x_opcode_imm(unsigned offset, unsigned value) +{ +	return (4 << 28) | (offset << 16) | value; +} + +static inline u32 host1x_opcode_imm_incr_syncpt(unsigned cond, unsigned indx) +{ +	return host1x_opcode_imm(host1x_uclass_incr_syncpt_r(), +		host1x_class_host_incr_syncpt(cond, indx)); +} + +static inline u32 host1x_opcode_restart(unsigned address) +{ +	return (5 << 28) | (address >> 4); +} + +static inline u32 host1x_opcode_gather(unsigned count) +{ +	return (6 << 28) | count; +} + +static inline u32 host1x_opcode_gather_nonincr(unsigned offset,	unsigned count) +{ +	return (6 << 28) | (offset << 16) | BIT(15) | count; +} + +static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count) +{ +	return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count; +} + +#define HOST1X_OPCODE_NOP host1x_opcode_nonincr(0, 0) + +#endif diff --git a/drivers/gpu/host1x/hw/hw_host1x01_uclass.h b/drivers/gpu/host1x/hw/hw_host1x01_uclass.h index 42f3ce19ca3..f7553599ee2 100644 --- a/drivers/gpu/host1x/hw/hw_host1x01_uclass.h +++ b/drivers/gpu/host1x/hw/hw_host1x01_uclass.h @@ -111,6 +111,12 @@ static inline u32 host1x_uclass_wait_syncpt_base_offset_f(u32 v)  }  #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_r(void) +{ +	return 0xb; +} +#define HOST1X_UCLASS_LOAD_SYNCPT_BASE \ +	host1x_uclass_load_syncpt_base_r()  static inline u32 host1x_uclass_load_syncpt_base_base_indx_f(u32 v)  {  	return (v & 0xff) << 24; 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 00000000000..e490bcde33f --- /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 00000000000..4495401525e --- /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 00000000000..028e49d9bac --- /dev/null +++ b/drivers/gpu/host1x/hw/hw_host1x02_uclass.h @@ -0,0 +1,181 @@ +/* + * 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_r(void) +{ +	return 0xb; +} +#define HOST1X_UCLASS_LOAD_SYNCPT_BASE \ +	host1x_uclass_load_syncpt_base_r() +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 diff --git a/drivers/gpu/host1x/hw/hw_host1x04_channel.h b/drivers/gpu/host1x/hw/hw_host1x04_channel.h new file mode 100644 index 00000000000..95e6f96142b --- /dev/null +++ b/drivers/gpu/host1x/hw/hw_host1x04_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_HOST1X04_CHANNEL_H +#define HOST1X_HW_HOST1X04_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_host1x04_sync.h b/drivers/gpu/host1x/hw/hw_host1x04_sync.h new file mode 100644 index 00000000000..ef2275b5407 --- /dev/null +++ b/drivers/gpu/host1x/hw/hw_host1x04_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_HOST1X04_SYNC_H +#define HOST1X_HW_HOST1X04_SYNC_H + +#define REGISTER_STRIDE	4 + +static inline u32 host1x_sync_syncpt_r(unsigned int id) +{ +	return 0xf80 + 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 0xe80 + 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 0xf00 + 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 0xf20 + 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 0xc00 + 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 0x1380 + 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 0xf60 + 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 0xc80 + 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 0xcc0 + 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_host1x04_uclass.h b/drivers/gpu/host1x/hw/hw_host1x04_uclass.h new file mode 100644 index 00000000000..d1460e97149 --- /dev/null +++ b/drivers/gpu/host1x/hw/hw_host1x04_uclass.h @@ -0,0 +1,181 @@ +/* + * 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_HOST1X04_UCLASS_H +#define HOST1X_HW_HOST1X04_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_r(void) +{ +	return 0xb; +} +#define HOST1X_UCLASS_LOAD_SYNCPT_BASE \ +	host1x_uclass_load_syncpt_base_r() +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 diff --git a/drivers/gpu/host1x/hw/intr_hw.c b/drivers/gpu/host1x/hw/intr_hw.c index b592eef1efc..498b37e3905 100644 --- a/drivers/gpu/host1x/hw/intr_hw.c +++ b/drivers/gpu/host1x/hw/intr_hw.c @@ -20,10 +20,9 @@  #include <linux/interrupt.h>  #include <linux/irq.h>  #include <linux/io.h> -#include <asm/mach/irq.h> -#include "intr.h" -#include "dev.h" +#include "../intr.h" +#include "../dev.h"  /*   * Sync point threshold interrupt service function @@ -48,7 +47,7 @@ static irqreturn_t syncpt_thresh_isr(int irq, void *dev_id)  	unsigned long reg;  	int i, id; -	for (i = 0; i <= BIT_WORD(host->info->nb_pts); i++) { +	for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); i++) {  		reg = host1x_sync_readl(host,  			HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i));  		for_each_set_bit(id, ®, BITS_PER_LONG) { @@ -65,7 +64,7 @@ static void _host1x_intr_disable_all_syncpt_intrs(struct host1x *host)  {  	u32 i; -	for (i = 0; i <= BIT_WORD(host->info->nb_pts); ++i) { +	for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); ++i) {  		host1x_sync_writel(host, 0xffffffffu,  			HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(i));  		host1x_sync_writel(host, 0xffffffffu, diff --git a/drivers/gpu/host1x/hw/syncpt_hw.c b/drivers/gpu/host1x/hw/syncpt_hw.c index 0cf6095d336..56e85395ac2 100644 --- a/drivers/gpu/host1x/hw/syncpt_hw.c +++ b/drivers/gpu/host1x/hw/syncpt_hw.c @@ -18,8 +18,8 @@  #include <linux/io.h> -#include "dev.h" -#include "syncpt.h" +#include "../dev.h" +#include "../syncpt.h"  /*   * Write the current syncpoint value back to hw. diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c index c4e1050f225..112f27e51bc 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" @@ -75,12 +75,14 @@ struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,  	return job;  } +EXPORT_SYMBOL(host1x_job_alloc);  struct host1x_job *host1x_job_get(struct host1x_job *job)  {  	kref_get(&job->ref);  	return job;  } +EXPORT_SYMBOL(host1x_job_get);  static void job_free(struct kref *ref)  { @@ -93,6 +95,7 @@ void host1x_job_put(struct host1x_job *job)  {  	kref_put(&job->ref, job_free);  } +EXPORT_SYMBOL(host1x_job_put);  void host1x_job_add_gather(struct host1x_job *job, struct host1x_bo *bo,  			   u32 words, u32 offset) @@ -104,6 +107,7 @@ void host1x_job_add_gather(struct host1x_job *job, struct host1x_bo *bo,  	cur_gather->offset = offset;  	job->num_gathers++;  } +EXPORT_SYMBOL(host1x_job_add_gather);  /*   * NULL an already satisfied WAIT_SYNCPT host method, by patching its @@ -264,7 +268,7 @@ static unsigned int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf)  }  static bool check_reloc(struct host1x_reloc *reloc, struct host1x_bo *cmdbuf, -		       unsigned int offset) +			unsigned int offset)  {  	offset *= sizeof(u32); @@ -281,7 +285,7 @@ struct host1x_firewall {  	unsigned int num_relocs;  	struct host1x_reloc *reloc; -	struct host1x_bo *cmdbuf_id; +	struct host1x_bo *cmdbuf;  	unsigned int offset;  	u32 words; @@ -291,25 +295,37 @@ struct host1x_firewall {  	u32 count;  }; +static int check_register(struct host1x_firewall *fw, unsigned long offset) +{ +	if (fw->job->is_addr_reg(fw->dev, fw->class, offset)) { +		if (!fw->num_relocs) +			return -EINVAL; + +		if (!check_reloc(fw->reloc, fw->cmdbuf, fw->offset)) +			return -EINVAL; + +		fw->num_relocs--; +		fw->reloc++; +	} + +	return 0; +} +  static int check_mask(struct host1x_firewall *fw)  {  	u32 mask = fw->mask;  	u32 reg = fw->reg; +	int ret;  	while (mask) {  		if (fw->words == 0)  			return -EINVAL;  		if (mask & 1) { -			if (fw->job->is_addr_reg(fw->dev, fw->class, reg)) { -				if (!fw->num_relocs) -					return -EINVAL; -				if (!check_reloc(fw->reloc, fw->cmdbuf_id, -						 fw->offset)) -					return -EINVAL; -				fw->reloc++; -				fw->num_relocs--; -			} +			ret = check_register(fw, reg); +			if (ret < 0) +				return ret; +  			fw->words--;  			fw->offset++;  		} @@ -324,19 +340,16 @@ static int check_incr(struct host1x_firewall *fw)  {  	u32 count = fw->count;  	u32 reg = fw->reg; +	int ret;  	while (count) {  		if (fw->words == 0)  			return -EINVAL; -		if (fw->job->is_addr_reg(fw->dev, fw->class, reg)) { -			if (!fw->num_relocs) -				return -EINVAL; -			if (!check_reloc(fw->reloc, fw->cmdbuf_id, fw->offset)) -				return -EINVAL; -			fw->reloc++; -			fw->num_relocs--; -		} +		ret = check_register(fw, reg); +		if (ret < 0) +			return ret; +  		reg++;  		fw->words--;  		fw->offset++; @@ -348,21 +361,17 @@ static int check_incr(struct host1x_firewall *fw)  static int check_nonincr(struct host1x_firewall *fw)  { -	int is_addr_reg = fw->job->is_addr_reg(fw->dev, fw->class, fw->reg);  	u32 count = fw->count; +	int ret;  	while (count) {  		if (fw->words == 0)  			return -EINVAL; -		if (is_addr_reg) { -			if (!fw->num_relocs) -				return -EINVAL; -			if (!check_reloc(fw->reloc, fw->cmdbuf_id, fw->offset)) -				return -EINVAL; -			fw->reloc++; -			fw->num_relocs--; -		} +		ret = check_register(fw, fw->reg); +		if (ret < 0) +			return ret; +  		fw->words--;  		fw->offset++;  		count--; @@ -381,7 +390,7 @@ static int validate(struct host1x_firewall *fw, struct host1x_job_gather *g)  		return 0;  	fw->words = g->words; -	fw->cmdbuf_id = g->bo; +	fw->cmdbuf = g->bo;  	fw->offset = 0;  	while (fw->words && !err) { @@ -436,10 +445,6 @@ static int validate(struct host1x_firewall *fw, struct host1x_job_gather *g)  		}  	} -	/* No relocs should remain at this point */ -	if (fw->num_relocs) -		err = -EINVAL; -  out:  	return err;  } @@ -493,6 +498,10 @@ static inline int copy_gathers(struct host1x_job *job, struct device *dev)  		offset += g->words * sizeof(u32);  	} +	/* No relocs should remain at this point */ +	if (fw.num_relocs) +		return -EINVAL; +  	return 0;  } @@ -529,7 +538,7 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev)  		g->base = job->gather_addr_phys[i]; -		for (j = 0; j < job->num_gathers; j++) +		for (j = i + 1; j < job->num_gathers; j++)  			if (job->gathers[j].bo == g->bo)  				job->gathers[j].handled = true; @@ -555,6 +564,7 @@ out:  	return err;  } +EXPORT_SYMBOL(host1x_job_pin);  void host1x_job_unpin(struct host1x_job *job)  { @@ -572,6 +582,7 @@ void host1x_job_unpin(struct host1x_job *job)  				      job->gather_copy_mapped,  				      job->gather_copy);  } +EXPORT_SYMBOL(host1x_job_unpin);  /*   * Debug routine used to dump job entries diff --git a/drivers/gpu/host1x/job.h b/drivers/gpu/host1x/job.h index fba45f20458..33a697d6dce 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/mipi.c b/drivers/gpu/host1x/mipi.c new file mode 100644 index 00000000000..9882ea12202 --- /dev/null +++ b/drivers/gpu/host1x/mipi.c @@ -0,0 +1,275 @@ +/* + * 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/host1x.h> +#include <linux/io.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include "dev.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; +}; + +struct tegra_mipi_device { +	struct platform_device *pdev; +	struct tegra_mipi *mipi; +	struct device *device; +	unsigned long pads; +}; + +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)); +} + +struct tegra_mipi_device *tegra_mipi_request(struct device *device) +{ +	struct device_node *np = device->of_node; +	struct tegra_mipi_device *dev; +	struct of_phandle_args args; +	int err; + +	err = of_parse_phandle_with_args(np, "nvidia,mipi-calibrate", +					 "#nvidia,mipi-calibrate-cells", 0, +					 &args); +	if (err < 0) +		return ERR_PTR(err); + +	dev = kzalloc(sizeof(*dev), GFP_KERNEL); +	if (!dev) { +		of_node_put(args.np); +		err = -ENOMEM; +		goto out; +	} + +	dev->pdev = of_find_device_by_node(args.np); +	if (!dev->pdev) { +		of_node_put(args.np); +		err = -ENODEV; +		goto free; +	} + +	of_node_put(args.np); + +	dev->mipi = platform_get_drvdata(dev->pdev); +	if (!dev->mipi) { +		err = -EPROBE_DEFER; +		goto pdev_put; +	} + +	dev->pads = args.args[0]; +	dev->device = device; + +	return dev; + +pdev_put: +	platform_device_put(dev->pdev); +free: +	kfree(dev); +out: +	return ERR_PTR(err); +} +EXPORT_SYMBOL(tegra_mipi_request); + +void tegra_mipi_free(struct tegra_mipi_device *device) +{ +	platform_device_put(device->pdev); +	kfree(device); +} +EXPORT_SYMBOL(tegra_mipi_free); + +static int tegra_mipi_wait(struct tegra_mipi *mipi) +{ +	unsigned long timeout = jiffies + msecs_to_jiffies(250); +	unsigned long value; + +	while (time_before(jiffies, timeout)) { +		value = tegra_mipi_readl(mipi, MIPI_CAL_STATUS); +		if ((value & MIPI_CAL_STATUS_ACTIVE) == 0 && +		    (value & MIPI_CAL_STATUS_DONE) != 0) +			return 0; + +		usleep_range(10, 50); +	} + +	return -ETIMEDOUT; +} + +int tegra_mipi_calibrate(struct tegra_mipi_device *device) +{ +	unsigned long value; +	unsigned int i; +	int err; + +	err = clk_enable(device->mipi->clk); +	if (err < 0) +		return err; + +	mutex_lock(&device->mipi->lock); + +	value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG0); +	value &= ~MIPI_CAL_BIAS_PAD_PDVCLAMP; +	value |= MIPI_CAL_BIAS_PAD_E_VCLAMP_REF; +	tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG0); + +	value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG2); +	value &= ~MIPI_CAL_BIAS_PAD_PDVREG; +	tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG2); + +	for (i = 0; i < ARRAY_SIZE(modules); i++) { +		if (device->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(device->mipi, value, modules[i].reg); +	} + +	tegra_mipi_writel(device->mipi, MIPI_CAL_CTRL_START, MIPI_CAL_CTRL); + +	err = tegra_mipi_wait(device->mipi); + +	mutex_unlock(&device->mipi->lock); +	clk_disable(device->mipi->clk); + +	return err; +} +EXPORT_SYMBOL(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/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c index 409745b949d..b10550ee1d8 100644 --- a/drivers/gpu/host1x/syncpt.c +++ b/drivers/gpu/host1x/syncpt.c @@ -30,9 +30,32 @@  #define SYNCPT_CHECK_PERIOD (2 * HZ)  #define MAX_STUCK_CHECK_COUNT 15 -static struct host1x_syncpt *_host1x_syncpt_alloc(struct host1x *host, -						  struct device *dev, -						  bool client_managed) +static struct host1x_syncpt_base * +host1x_syncpt_base_request(struct host1x *host) +{ +	struct host1x_syncpt_base *bases = host->bases; +	unsigned int i; + +	for (i = 0; i < host->info->nb_bases; i++) +		if (!bases[i].requested) +			break; + +	if (i >= host->info->nb_bases) +		return NULL; + +	bases[i].requested = true; +	return &bases[i]; +} + +static void host1x_syncpt_base_free(struct host1x_syncpt_base *base) +{ +	if (base) +		base->requested = false; +} + +static struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host, +						 struct device *dev, +						 unsigned long flags)  {  	int i;  	struct host1x_syncpt *sp = host->syncpt; @@ -44,6 +67,12 @@ static struct host1x_syncpt *_host1x_syncpt_alloc(struct host1x *host,  	if (i >= host->info->nb_pts)  		return NULL; +	if (flags & HOST1X_SYNCPT_HAS_BASE) { +		sp->base = host1x_syncpt_base_request(host); +		if (!sp->base) +			return NULL; +	} +  	name = kasprintf(GFP_KERNEL, "%02d-%s", sp->id,  			dev ? dev_name(dev) : NULL);  	if (!name) @@ -51,7 +80,11 @@ static struct host1x_syncpt *_host1x_syncpt_alloc(struct host1x *host,  	sp->dev = dev;  	sp->name = name; -	sp->client_managed = client_managed; + +	if (flags & HOST1X_SYNCPT_CLIENT_MANAGED) +		sp->client_managed = true; +	else +		sp->client_managed = false;  	return sp;  } @@ -60,6 +93,7 @@ u32 host1x_syncpt_id(struct host1x_syncpt *sp)  {  	return sp->id;  } +EXPORT_SYMBOL(host1x_syncpt_id);  /*   * Updates the value sent to hardware. @@ -68,6 +102,7 @@ u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs)  {  	return (u32)atomic_add_return(incrs, &sp->max_val);  } +EXPORT_SYMBOL(host1x_syncpt_incr_max);   /*   * Write cached syncpoint and waitbase values to hardware. @@ -135,6 +170,7 @@ int host1x_syncpt_incr(struct host1x_syncpt *sp)  {  	return host1x_hw_syncpt_cpu_incr(sp->host, sp);  } +EXPORT_SYMBOL(host1x_syncpt_incr);  /*   * Updated sync point form hardware, and returns true if syncpoint is expired, @@ -303,25 +339,35 @@ int host1x_syncpt_patch_wait(struct host1x_syncpt *sp, void *patch_addr)  int host1x_syncpt_init(struct host1x *host)  { +	struct host1x_syncpt_base *bases;  	struct host1x_syncpt *syncpt;  	int i;  	syncpt = devm_kzalloc(host->dev, sizeof(*syncpt) * host->info->nb_pts, -		GFP_KERNEL); +			      GFP_KERNEL);  	if (!syncpt)  		return -ENOMEM; -	for (i = 0; i < host->info->nb_pts; ++i) { +	bases = devm_kzalloc(host->dev, sizeof(*bases) * host->info->nb_bases, +			     GFP_KERNEL); +	if (!bases) +		return -ENOMEM; + +	for (i = 0; i < host->info->nb_pts; i++) {  		syncpt[i].id = i;  		syncpt[i].host = host;  	} +	for (i = 0; i < host->info->nb_bases; i++) +		bases[i].id = i; +  	host->syncpt = syncpt; +	host->bases = bases;  	host1x_syncpt_restore(host);  	/* Allocate sync point to use for clearing waits for expired fences */ -	host->nop_sp = _host1x_syncpt_alloc(host, NULL, false); +	host->nop_sp = host1x_syncpt_alloc(host, NULL, 0);  	if (!host->nop_sp)  		return -ENOMEM; @@ -329,22 +375,26 @@ int host1x_syncpt_init(struct host1x *host)  }  struct host1x_syncpt *host1x_syncpt_request(struct device *dev, -					    bool client_managed) +					    unsigned long flags)  {  	struct host1x *host = dev_get_drvdata(dev->parent); -	return _host1x_syncpt_alloc(host, dev, client_managed); +	return host1x_syncpt_alloc(host, dev, flags);  } +EXPORT_SYMBOL(host1x_syncpt_request);  void host1x_syncpt_free(struct host1x_syncpt *sp)  {  	if (!sp)  		return; +	host1x_syncpt_base_free(sp->base);  	kfree(sp->name); +	sp->base = NULL;  	sp->dev = NULL;  	sp->name = NULL;  	sp->client_managed = false;  } +EXPORT_SYMBOL(host1x_syncpt_free);  void host1x_syncpt_deinit(struct host1x *host)  { @@ -354,6 +404,27 @@ 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); +} +EXPORT_SYMBOL(host1x_syncpt_read_max); + +/* + * 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); +} +EXPORT_SYMBOL(host1x_syncpt_read_min); +  int host1x_syncpt_nb_pts(struct host1x *host)  {  	return host->info->nb_pts; @@ -375,3 +446,16 @@ struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, u32 id)  		return NULL;  	return host->syncpt + id;  } +EXPORT_SYMBOL(host1x_syncpt_get); + +struct host1x_syncpt_base *host1x_syncpt_get_base(struct host1x_syncpt *sp) +{ +	return sp ? sp->base : NULL; +} +EXPORT_SYMBOL(host1x_syncpt_get_base); + +u32 host1x_syncpt_base_id(struct host1x_syncpt_base *base) +{ +	return base->id; +} +EXPORT_SYMBOL(host1x_syncpt_base_id); diff --git a/drivers/gpu/host1x/syncpt.h b/drivers/gpu/host1x/syncpt.h index 267c0b9d364..9056465ecd3 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> @@ -30,6 +31,11 @@ struct host1x;  /* Reserved for replacing an expired wait with a NOP */  #define HOST1X_SYNCPT_RESERVED			0 +struct host1x_syncpt_base { +	unsigned int id; +	bool requested; +}; +  struct host1x_syncpt {  	int id;  	atomic_t min_val; @@ -39,6 +45,7 @@ struct host1x_syncpt {  	bool client_managed;  	struct host1x *host;  	struct device *dev; +	struct host1x_syncpt_base *base;  	/* interrupt data */  	struct host1x_syncpt_intr intr; @@ -50,25 +57,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 +100,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 +115,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 +127,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  | 
