147 lines
3.6 KiB
C
147 lines
3.6 KiB
C
/*
|
|
* Copyright (c) 2015, The Linux Foundation. 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 and
|
|
* only version 2 as published by the Free Software Foundation.
|
|
*
|
|
* 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/types.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/init.h>
|
|
#include <linux/device.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/i2c.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/err.h>
|
|
|
|
#include <video/msm_dba.h>
|
|
#include <msm_dba_internal.h>
|
|
|
|
static DEFINE_MUTEX(register_mutex);
|
|
|
|
void *msm_dba_register_client(struct msm_dba_reg_info *info,
|
|
struct msm_dba_ops *ops)
|
|
{
|
|
int rc = 0;
|
|
struct msm_dba_device_info *device = NULL;
|
|
struct msm_dba_client_info *client = NULL;
|
|
|
|
pr_debug("%s: ENTER\n", __func__);
|
|
|
|
if (!info || !ops) {
|
|
pr_err("%s: Invalid params\n", __func__);
|
|
return ERR_PTR(-EINVAL);
|
|
}
|
|
|
|
mutex_lock(®ister_mutex);
|
|
|
|
pr_debug("%s: Client(%s) Chip(%s) Instance(%d)\n", __func__,
|
|
info->client_name, info->chip_name, info->instance_id);
|
|
|
|
rc = msm_dba_get_probed_device(info, &device);
|
|
if (rc) {
|
|
pr_err("%s: Device not found (%s, %d)\n", __func__,
|
|
info->chip_name,
|
|
info->instance_id);
|
|
mutex_unlock(®ister_mutex);
|
|
return ERR_PTR(rc);
|
|
}
|
|
|
|
pr_debug("%s: Client(%s) device found\n", __func__, info->client_name);
|
|
|
|
client = kzalloc(sizeof(*client), GFP_KERNEL);
|
|
if (!client) {
|
|
mutex_unlock(®ister_mutex);
|
|
return ERR_PTR(-ENOMEM);
|
|
}
|
|
|
|
memset(client, 0x0, sizeof(*client));
|
|
client->dev = device;
|
|
strlcpy(client->client_name, info->client_name,
|
|
MSM_DBA_CLIENT_NAME_LEN);
|
|
|
|
client->cb = info->cb;
|
|
client->cb_data = info->cb_data;
|
|
|
|
mutex_lock_nested(&device->dev_mutex, SINGLE_DEPTH_NESTING);
|
|
list_add(&client->list, &device->client_list);
|
|
*ops = device->client_ops;
|
|
mutex_unlock(&device->dev_mutex);
|
|
|
|
if (device->reg_fxn) {
|
|
rc = device->reg_fxn(client);
|
|
if (rc) {
|
|
pr_err("%s: Client register failed (%s, %d)\n",
|
|
__func__, info->chip_name, info->instance_id);
|
|
kfree(client);
|
|
mutex_unlock(®ister_mutex);
|
|
return ERR_PTR(rc);
|
|
}
|
|
}
|
|
|
|
mutex_unlock(®ister_mutex);
|
|
|
|
pr_debug("%s: EXIT\n", __func__);
|
|
return client;
|
|
}
|
|
EXPORT_SYMBOL(msm_dba_register_client);
|
|
|
|
int msm_dba_deregister_client(void *client)
|
|
{
|
|
int rc = 0;
|
|
struct msm_dba_client_info *handle = client;
|
|
struct msm_dba_client_info *node = NULL;
|
|
struct list_head *tmp = NULL;
|
|
struct list_head *position = NULL;
|
|
|
|
pr_debug("%s: ENTER\n", __func__);
|
|
|
|
if (!handle) {
|
|
pr_err("%s: Invalid Params\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
mutex_lock(®ister_mutex);
|
|
|
|
pr_debug("%s: Client(%s) Chip(%s) Instance(%d)\n", __func__,
|
|
handle->client_name, handle->dev->chip_name,
|
|
handle->dev->instance_id);
|
|
|
|
if (handle->dev->dereg_fxn) {
|
|
rc = handle->dev->dereg_fxn(handle);
|
|
if (rc) {
|
|
pr_err("%s: Client deregister failed (%s)\n",
|
|
__func__, handle->client_name);
|
|
}
|
|
}
|
|
|
|
mutex_lock_nested(&handle->dev->dev_mutex, SINGLE_DEPTH_NESTING);
|
|
|
|
list_for_each_safe(position, tmp, &handle->dev->client_list) {
|
|
|
|
node = list_entry(position, struct msm_dba_client_info, list);
|
|
|
|
if (node == handle) {
|
|
list_del(&node->list);
|
|
break;
|
|
}
|
|
}
|
|
|
|
mutex_unlock(&handle->dev->dev_mutex);
|
|
|
|
kfree(handle);
|
|
|
|
mutex_unlock(®ister_mutex);
|
|
|
|
pr_debug("%s: EXIT (%d)\n", __func__, rc);
|
|
return rc;
|
|
}
|
|
EXPORT_SYMBOL(msm_dba_deregister_client);
|