137 lines
2.7 KiB
C
137 lines
2.7 KiB
C
/*
|
|
* Copyright (C) 2013 NVIDIA Corporation
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include "drm.h"
|
|
|
|
static DEFINE_MUTEX(clients_lock);
|
|
static LIST_HEAD(clients);
|
|
|
|
void drm_host1x_exit(struct drm_driver *driver, struct host1x_device *device)
|
|
{
|
|
struct tegra_drm *tegra = dev_get_drvdata(&device->dev);
|
|
|
|
drm_put_dev(tegra->drm);
|
|
}
|
|
|
|
|
|
int drm_host1x_init(struct drm_driver *driver, struct host1x_device *device)
|
|
{
|
|
mutex_init(&clients_lock);
|
|
INIT_LIST_HEAD(&device->clients);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int drm_host1x_register(struct host1x_client *client)
|
|
{
|
|
struct host1x_client *pos;
|
|
|
|
mutex_lock(&clients_lock);
|
|
list_for_each_entry(pos, &clients, list) {
|
|
if (pos->dev == client->dev) {
|
|
mutex_unlock(&clients_lock);
|
|
return 0;
|
|
}
|
|
}
|
|
list_add_tail(&client->list, &clients);
|
|
mutex_unlock(&clients_lock);
|
|
return 0;
|
|
}
|
|
|
|
int drm_host1x_unregister(struct host1x_client *client)
|
|
{
|
|
struct host1x_client *c;
|
|
|
|
list_for_each_entry(c, &clients, list) {
|
|
if (c == client) {
|
|
list_del(&c->list);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int drm_host1x_device_init(struct drm_device *drm, struct host1x_device *device)
|
|
{
|
|
struct host1x_client *client;
|
|
int err;
|
|
|
|
mutex_lock(&clients_lock);
|
|
list_for_each_entry(client, &clients, list) {
|
|
if (client->ops && client->ops->init) {
|
|
client->parent = drm->dev;
|
|
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(&clients_lock);
|
|
return err;
|
|
}
|
|
}
|
|
}
|
|
|
|
mutex_unlock(&clients_lock);
|
|
return 0;
|
|
}
|
|
|
|
int drm_host1x_device_exit(struct host1x_device *device)
|
|
{
|
|
struct host1x_client *client;
|
|
int err;
|
|
|
|
mutex_lock(&clients_lock);
|
|
list_for_each_entry_reverse(client, &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(&clients_lock);
|
|
return err;
|
|
}
|
|
}
|
|
}
|
|
|
|
mutex_unlock(&clients_lock);
|
|
return 0;
|
|
}
|
|
|
|
struct host1x_client *drm_host1x_get_client(struct device *dev)
|
|
{
|
|
struct host1x_client *pos;
|
|
|
|
mutex_lock(&clients_lock);
|
|
list_for_each_entry(pos, &clients, list) {
|
|
if (pos->dev == dev) {
|
|
mutex_unlock(&clients_lock);
|
|
return pos;
|
|
}
|
|
}
|
|
mutex_unlock(&clients_lock);
|
|
return NULL;
|
|
}
|
|
|
|
int drm_host1x_check_clients_probed(void)
|
|
{
|
|
struct host1x_client *pos;
|
|
|
|
mutex_lock(&clients_lock);
|
|
list_for_each_entry(pos, &clients, list) {
|
|
if (!pos->driver_probed) {
|
|
mutex_unlock(&clients_lock);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
mutex_unlock(&clients_lock);
|
|
return 1;
|
|
}
|