summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorVinu Deokaran <vinud@codeaurora.org>2015-04-03 14:19:04 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:47:05 -0700
commit3d30cc8dde2a2e12bd3c6cff18fe2b96cc0c5a80 (patch)
treea5a29d6836b2e0f82ef13c1ed81514b4b664843d /drivers
parentb01c8e984921ce649d49869dbc2ad0998819be25 (diff)
msm: add display bridge abstraction driver
Add display bridge abstraction driver to provide an abstract interface for different types of bridge chips used on MSM platforms. This interface allows driver development for bridge chips from different manufactorers while allowing users, of the funcationality provided by these bridge chips, to re-use the same code across different boards. Change-Id: I64457e3a44479a3b1be5482691d4727a86dc9b87 Signed-off-by: Vinu Deokaran <vinud@codeaurora.org> Signed-off-by: Siddharth Zaveri <szaveri@codeaurora.org> [cip@codeaurora.org: Moved file locations] Signed-off-by: Clarence Ip <cip@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/fbdev/msm/Kconfig1
-rw-r--r--drivers/video/fbdev/msm/Makefile1
-rw-r--r--drivers/video/fbdev/msm/msm_dba/Kconfig15
-rw-r--r--drivers/video/fbdev/msm/msm_dba/Makefile3
-rw-r--r--drivers/video/fbdev/msm/msm_dba/msm_dba.c146
-rw-r--r--drivers/video/fbdev/msm/msm_dba/msm_dba_debug.c299
-rw-r--r--drivers/video/fbdev/msm/msm_dba/msm_dba_helpers.c445
-rw-r--r--drivers/video/fbdev/msm/msm_dba/msm_dba_init.c131
-rw-r--r--drivers/video/fbdev/msm/msm_dba/msm_dba_internal.h317
9 files changed, 1358 insertions, 0 deletions
diff --git a/drivers/video/fbdev/msm/Kconfig b/drivers/video/fbdev/msm/Kconfig
index a4d5d5e0d637..c49ce06430be 100644
--- a/drivers/video/fbdev/msm/Kconfig
+++ b/drivers/video/fbdev/msm/Kconfig
@@ -1,3 +1,4 @@
+source "drivers/video/fbdev/msm/msm_dba/Kconfig"
if FB_MSM
diff --git a/drivers/video/fbdev/msm/Makefile b/drivers/video/fbdev/msm/Makefile
index eadf8c7191ee..ac83251cbfe6 100644
--- a/drivers/video/fbdev/msm/Makefile
+++ b/drivers/video/fbdev/msm/Makefile
@@ -1,6 +1,7 @@
ccflags-y += -I$(src) -Idrivers/staging/android
obj-$(CONFIG_FB_MSM_MDSS_MHL3) += mhl3/
+obj-$(CONFIG_MSM_DBA) += msm_dba/
mdss-mdp3-objs = mdp3.o mdp3_dma.o mdp3_ctrl.o dsi_status_v2.o
mdss-mdp3-objs += mdp3_ppp.o mdp3_ppp_hwio.o mdp3_ppp_data.o
diff --git a/drivers/video/fbdev/msm/msm_dba/Kconfig b/drivers/video/fbdev/msm/msm_dba/Kconfig
new file mode 100644
index 000000000000..a20d59c16a0d
--- /dev/null
+++ b/drivers/video/fbdev/msm/msm_dba/Kconfig
@@ -0,0 +1,15 @@
+#
+# MSM DBA
+#
+
+config MSM_DBA
+ bool "MSM Display Bridge Abstraction support"
+ depends on ARM
+ ---help---
+ Support for MSM display bridge abstraction interface. MSM display
+ drivers can use the same interface to interact with different third
+ party bridge chips. Drivers implemented for third party bridge chips
+ should support this interface to allow display driver to control the
+ bridge chip. The MSM DBA driver maintains a list of devices supported
+ on the platform and allow clients to register and access these
+ devices.
diff --git a/drivers/video/fbdev/msm/msm_dba/Makefile b/drivers/video/fbdev/msm/msm_dba/Makefile
new file mode 100644
index 000000000000..68a1adf3f88e
--- /dev/null
+++ b/drivers/video/fbdev/msm/msm_dba/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_MSM_DBA) += msm_dba.o msm_dba_init.o msm_dba_helpers.o msm_dba_debug.o
+clean:
+ rm *.o
diff --git a/drivers/video/fbdev/msm/msm_dba/msm_dba.c b/drivers/video/fbdev/msm/msm_dba/msm_dba.c
new file mode 100644
index 000000000000..7a5c9d9d873a
--- /dev/null
+++ b/drivers/video/fbdev/msm/msm_dba/msm_dba.c
@@ -0,0 +1,146 @@
+/*
+ * 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(&register_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(&register_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(&register_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(&register_mutex);
+ return ERR_PTR(rc);
+ }
+ }
+
+ mutex_unlock(&register_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(&register_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(&register_mutex);
+
+ pr_debug("%s: EXIT (%d)\n", __func__, rc);
+ return rc;
+}
+EXPORT_SYMBOL(msm_dba_deregister_client);
diff --git a/drivers/video/fbdev/msm/msm_dba/msm_dba_debug.c b/drivers/video/fbdev/msm/msm_dba/msm_dba_debug.c
new file mode 100644
index 000000000000..b59dd583b98d
--- /dev/null
+++ b/drivers/video/fbdev/msm/msm_dba/msm_dba_debug.c
@@ -0,0 +1,299 @@
+/*
+ * 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/i2c.h>
+#include <linux/list.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/stat.h>
+
+#include <video/msm_dba.h>
+#include "msm_dba_internal.h"
+
+static inline struct msm_dba_device_info *to_dba_dev(struct device *dev)
+{
+ return dev_get_drvdata(dev);
+}
+
+static ssize_t device_name_rda_attr(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct msm_dba_device_info *device = to_dba_dev(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%s:%d\n", device->chip_name,
+ device->instance_id);
+}
+
+static ssize_t client_list_rda_attr(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct msm_dba_device_info *device = to_dba_dev(dev);
+ struct msm_dba_client_info *c;
+ struct list_head *pos = NULL;
+ ssize_t bytes = 0;
+
+ mutex_lock(&device->dev_mutex);
+
+ list_for_each(pos, &device->client_list) {
+ c = list_entry(pos, struct msm_dba_client_info, list);
+ bytes += snprintf(buf + bytes, (PAGE_SIZE - bytes), "%s\n",
+ c->client_name);
+ }
+
+ mutex_unlock(&device->dev_mutex);
+
+ return bytes;
+}
+
+static ssize_t power_status_rda_attr(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct msm_dba_device_info *device = to_dba_dev(dev);
+ struct msm_dba_client_info *c;
+ struct list_head *pos = NULL;
+ ssize_t bytes = 0;
+
+ mutex_lock(&device->dev_mutex);
+ bytes = snprintf(buf, PAGE_SIZE, "power_status:%d\n",
+ device->power_status);
+
+ list_for_each(pos, &device->client_list) {
+ c = list_entry(pos, struct msm_dba_client_info, list);
+ bytes += snprintf(buf + bytes, (PAGE_SIZE - bytes),
+ "client: %s, status = %d\n",
+ c->client_name, c->power_on);
+ }
+
+ mutex_unlock(&device->dev_mutex);
+ return bytes;
+}
+
+static ssize_t video_status_rda_attr(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct msm_dba_device_info *device = to_dba_dev(dev);
+ struct msm_dba_client_info *c;
+ struct list_head *pos = NULL;
+ ssize_t bytes = 0;
+
+ mutex_lock(&device->dev_mutex);
+ bytes = snprintf(buf, PAGE_SIZE, "video_status:%d\n",
+ device->video_status);
+
+ list_for_each(pos, &device->client_list) {
+ c = list_entry(pos, struct msm_dba_client_info, list);
+ bytes += snprintf(buf + bytes, (PAGE_SIZE - bytes),
+ "client: %s, status = %d\n",
+ c->client_name, c->video_on);
+ }
+
+ mutex_unlock(&device->dev_mutex);
+ return bytes;
+}
+
+static ssize_t audio_status_rda_attr(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct msm_dba_device_info *device = to_dba_dev(dev);
+ struct msm_dba_client_info *c;
+ struct list_head *pos = NULL;
+ ssize_t bytes = 0;
+
+ mutex_lock(&device->dev_mutex);
+ bytes = snprintf(buf, PAGE_SIZE, "audio_status:%d\n",
+ device->audio_status);
+
+ list_for_each(pos, &device->client_list) {
+ c = list_entry(pos, struct msm_dba_client_info, list);
+ bytes += snprintf(buf + bytes, (PAGE_SIZE - bytes),
+ "client: %s, status = %d\n",
+ c->client_name, c->audio_on);
+ }
+
+ mutex_unlock(&device->dev_mutex);
+ return bytes;
+}
+
+static ssize_t write_reg_wta_attr(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct msm_dba_device_info *device = to_dba_dev(dev);
+ char *regstr, *valstr, *ptr;
+ char str[20];
+ long reg = 0;
+ long val = 0;
+ int rc = 0;
+ int len;
+
+ len = strlen(buf);
+ strlcpy(str, buf, 20);
+ if (len < 20)
+ str[len] = '\0';
+ else
+ str[19] = '\0';
+
+ ptr = str;
+ regstr = strsep(&ptr, ":");
+ valstr = strsep(&ptr, ":");
+
+ rc = kstrtol(regstr, 0, &reg);
+ if (rc) {
+ pr_err("%s: kstrol error %d\n", __func__, rc);
+ } else {
+ rc = kstrtol(valstr, 0, &val);
+ if (rc)
+ pr_err("%s: kstrol error for val %d\n", __func__, rc);
+ }
+
+ if (!rc) {
+ mutex_lock(&device->dev_mutex);
+
+ if (device->dev_ops.write_reg) {
+ rc = device->dev_ops.write_reg(device,
+ (u32)reg,
+ (u32)val);
+
+ if (rc) {
+ pr_err("%s: failed to write reg %d", __func__,
+ rc);
+ }
+ } else {
+ pr_err("%s: not supported\n", __func__);
+ }
+
+ mutex_unlock(&device->dev_mutex);
+ }
+
+ return count;
+}
+
+static ssize_t read_reg_rda_attr(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct msm_dba_device_info *device = to_dba_dev(dev);
+ ssize_t bytes;
+
+ mutex_lock(&device->dev_mutex);
+
+ bytes = snprintf(buf, PAGE_SIZE, "0x%x\n", device->register_val);
+
+ mutex_unlock(&device->dev_mutex);
+
+ return bytes;
+}
+
+static ssize_t read_reg_wta_attr(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct msm_dba_device_info *device = to_dba_dev(dev);
+ long reg = 0;
+ int rc = 0;
+ u32 val = 0;
+
+ rc = kstrtol(buf, 0, &reg);
+ if (rc) {
+ pr_err("%s: kstrol error %d\n", __func__, rc);
+ } else {
+ mutex_lock(&device->dev_mutex);
+
+ if (device->dev_ops.read_reg) {
+ rc = device->dev_ops.read_reg(device,
+ (u32)reg,
+ &val);
+
+ if (rc) {
+ pr_err("%s: failed to write reg %d", __func__,
+ rc);
+ } else {
+ device->register_val = val;
+ }
+ } else {
+ pr_err("%s: not supported\n", __func__);
+ }
+
+ mutex_unlock(&device->dev_mutex);
+ }
+
+ return count;
+}
+
+static ssize_t dump_info_wta_attr(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct msm_dba_device_info *device = to_dba_dev(dev);
+ int rc;
+
+ rc = device->dev_ops.dump_debug_info(device, 0x00);
+ if (rc)
+ pr_err("%s: failed to dump debug data\n", __func__);
+
+ return count;
+}
+
+static DEVICE_ATTR(device_name, S_IRUGO, device_name_rda_attr, NULL);
+static DEVICE_ATTR(client_list, S_IRUGO, client_list_rda_attr, NULL);
+static DEVICE_ATTR(power_status, S_IRUGO, power_status_rda_attr, NULL);
+static DEVICE_ATTR(video_status, S_IRUGO, video_status_rda_attr, NULL);
+static DEVICE_ATTR(audio_status, S_IRUGO, audio_status_rda_attr, NULL);
+static DEVICE_ATTR(write_reg, S_IWUSR, NULL, write_reg_wta_attr);
+static DEVICE_ATTR(read_reg, S_IRUGO | S_IWUSR, read_reg_rda_attr,
+ read_reg_wta_attr);
+static DEVICE_ATTR(dump_info, S_IWUSR, NULL, dump_info_wta_attr);
+
+static struct attribute *msm_dba_sysfs_attrs[] = {
+ &dev_attr_device_name.attr,
+ &dev_attr_client_list.attr,
+ &dev_attr_power_status.attr,
+ &dev_attr_video_status.attr,
+ &dev_attr_audio_status.attr,
+ &dev_attr_write_reg.attr,
+ &dev_attr_read_reg.attr,
+ &dev_attr_dump_info.attr,
+ NULL,
+};
+
+static struct attribute_group msm_dba_sysfs_attr_grp = {
+ .attrs = msm_dba_sysfs_attrs,
+};
+
+int msm_dba_helper_sysfs_init(struct device *dev)
+{
+ int rc = 0;
+
+ if (!dev) {
+ pr_err("%s: Invalid params\n", __func__);
+ return -EINVAL;
+ }
+
+ rc = sysfs_create_group(&dev->kobj, &msm_dba_sysfs_attr_grp);
+ if (rc)
+ pr_err("%s: sysfs group creation failed %d\n", __func__, rc);
+
+ return rc;
+}
diff --git a/drivers/video/fbdev/msm/msm_dba/msm_dba_helpers.c b/drivers/video/fbdev/msm/msm_dba/msm_dba_helpers.c
new file mode 100644
index 000000000000..f6128ae01a75
--- /dev/null
+++ b/drivers/video/fbdev/msm/msm_dba/msm_dba_helpers.c
@@ -0,0 +1,445 @@
+/*
+ * 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/i2c.h>
+#include <linux/list.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+
+#include <video/msm_dba.h>
+#include "msm_dba_internal.h"
+
+static void msm_dba_helper_hdcp_handler(struct work_struct *work)
+{
+ struct msm_dba_device_info *dev;
+ int rc = 0;
+
+ if (!work) {
+ pr_err("%s: Invalid params\n", __func__);
+ return;
+ }
+
+ dev = container_of(work, struct msm_dba_device_info, hdcp_work);
+
+ mutex_lock(&dev->dev_mutex);
+ if (dev->hdcp_status) {
+ pr_debug("%s[%s:%d] HDCP is authenticated\n", __func__,
+ dev->chip_name, dev->instance_id);
+ mutex_unlock(&dev->dev_mutex);
+ return;
+ }
+
+ if (dev->dev_ops.hdcp_reset) {
+ rc = dev->dev_ops.hdcp_reset(dev);
+ if (rc)
+ pr_err("%s[%s:%d] HDCP reset failed\n", __func__,
+ dev->chip_name, dev->instance_id);
+ }
+
+ if (dev->dev_ops.hdcp_retry) {
+ rc = dev->dev_ops.hdcp_retry(dev, MSM_DBA_ASYNC_FLAG);
+ if (rc)
+ pr_err("%s[%s:%d] HDCP retry failed\n", __func__,
+ dev->chip_name, dev->instance_id);
+ }
+ mutex_unlock(&dev->dev_mutex);
+}
+
+static void msm_dba_helper_issue_cb(struct msm_dba_device_info *dev,
+ struct msm_dba_client_info *client,
+ enum msm_dba_callback_event event)
+{
+ struct msm_dba_client_info *c;
+ struct list_head *pos = NULL;
+ u32 user_mask = 0;
+
+ list_for_each(pos, &dev->client_list) {
+ c = list_entry(pos, struct msm_dba_client_info, list);
+ if (client && client == c)
+ continue;
+
+ user_mask = c->event_mask & event;
+ if (c->cb && user_mask)
+ c->cb(c->cb_data, user_mask);
+ }
+}
+
+static irqreturn_t msm_dba_helper_irq_handler(int irq, void *dev)
+{
+ struct msm_dba_device_info *device = dev;
+ u32 mask = 0;
+ int rc = 0;
+ bool ret;
+
+ mutex_lock(&device->dev_mutex);
+ if (device->dev_ops.handle_interrupts) {
+ rc = device->dev_ops.handle_interrupts(device, &mask);
+ if (rc)
+ pr_err("%s: interrupt handler failed\n", __func__);
+ }
+
+ pr_debug("%s(%s:%d): Eventmask = 0x%x\n", __func__, device->chip_name,
+ device->instance_id, mask);
+ if (mask)
+ msm_dba_helper_issue_cb(device, NULL, mask);
+
+ if ((mask & MSM_DBA_CB_HDCP_LINK_UNAUTHENTICATED) &&
+ device->hdcp_monitor_on) {
+ ret = queue_work(device->hdcp_wq, &device->hdcp_work);
+ if (!ret)
+ pr_err("%s: queue_work failed %d\n", __func__, rc);
+ }
+
+ if (device->dev_ops.unmask_interrupts)
+ rc = device->dev_ops.unmask_interrupts(device, mask);
+
+ mutex_unlock(&device->dev_mutex);
+ return IRQ_HANDLED;
+}
+
+int msm_dba_helper_i2c_write_byte(struct i2c_client *client,
+ u8 addr,
+ u8 reg,
+ u8 val)
+{
+ int rc = 0;
+ struct i2c_msg msg;
+ u8 buf[2] = {reg, val};
+
+ if (!client) {
+ pr_err("%s: Invalid params\n", __func__);
+ return -EINVAL;
+ }
+
+ pr_debug("%s: [%s:0x02%x] : W[0x%02x, 0x%02x]\n", __func__,
+ client->name, addr, reg, val);
+ client->addr = addr;
+
+ msg.addr = addr;
+ msg.flags = 0;
+ msg.len = 2;
+ msg.buf = buf;
+
+ if (i2c_transfer(client->adapter, &msg, 1) < 1) {
+ pr_err("%s: i2c write failed\n", __func__);
+ rc = -EIO;
+ }
+
+ return rc;
+}
+
+int msm_dba_helper_i2c_write_buffer(struct i2c_client *client,
+ u8 addr,
+ u8 *buf,
+ u32 size)
+{
+ int rc = 0;
+ struct i2c_msg msg;
+
+ if (!client) {
+ pr_err("%s: Invalid params\n", __func__);
+ return -EINVAL;
+ }
+ pr_debug("%s: [%s:0x02%x] : W %d bytes\n", __func__,
+ client->name, addr, size);
+
+ client->addr = addr;
+
+ msg.addr = addr;
+ msg.flags = 0;
+ msg.len = size;
+ msg.buf = buf;
+
+ if (i2c_transfer(client->adapter, &msg, 1) != 1) {
+ pr_err("%s: i2c write failed\n", __func__);
+ rc = -EIO;
+ }
+
+ return rc;
+}
+int msm_dba_helper_i2c_read(struct i2c_client *client,
+ u8 addr,
+ u8 reg,
+ char *buf,
+ u32 size)
+{
+ int rc = 0;
+ struct i2c_msg msg[2];
+
+ if (!client || !buf) {
+ pr_err("%s: Invalid params\n", __func__);
+ return -EINVAL;
+ }
+
+ client->addr = addr;
+
+ msg[0].addr = addr;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ msg[0].buf = &reg;
+
+ msg[1].addr = addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = size;
+ msg[1].buf = buf;
+
+ if (i2c_transfer(client->adapter, msg, 2) != 2) {
+ pr_err("%s: i2c read failed\n", __func__);
+ rc = -EIO;
+ }
+
+ pr_debug("%s: [%s:0x02%x] : R[0x%02x, 0x%02x]\n", __func__,
+ client->name, addr, reg, *buf);
+ return rc;
+}
+
+int msm_dba_helper_power_on(void *client, bool on, u32 flags)
+{
+ int rc = 0;
+ struct msm_dba_client_info *c = client;
+ struct msm_dba_device_info *device;
+ struct msm_dba_client_info *node;
+ struct list_head *pos = NULL;
+ bool power_on = false;
+
+ if (!c) {
+ pr_err("%s: Invalid Params\n", __func__);
+ return -EINVAL;
+ }
+
+ device = c->dev;
+ mutex_lock(&device->dev_mutex);
+
+ /*
+ * Power on the device if atleast one client powers on the device. But
+ * power off will be done only after all the clients have called power
+ * off
+ */
+ if (on == device->power_status) {
+ c->power_on = on;
+ } else if (on) {
+ rc = device->dev_ops.dev_power_on(device, on);
+ if (rc)
+ pr_err("%s:%s: power on failed\n", device->chip_name,
+ __func__);
+ else
+ c->power_on = on;
+ } else {
+ c->power_on = false;
+
+ list_for_each(pos, &device->client_list) {
+ node = list_entry(pos, struct msm_dba_client_info,
+ list);
+ if (c->power_on) {
+ power_on = true;
+ break;
+ }
+ }
+
+ if (!power_on) {
+ rc = device->dev_ops.dev_power_on(device, false);
+ if (rc) {
+ pr_err("%s:%s: power off failed\n",
+ device->chip_name, __func__);
+ c->power_on = true;
+ }
+ }
+ }
+
+ mutex_unlock(&device->dev_mutex);
+ return rc;
+}
+
+int msm_dba_helper_video_on(void *client, bool on,
+ struct msm_dba_video_cfg *cfg, u32 flags)
+{
+ int rc = 0;
+ struct msm_dba_client_info *c = client;
+ struct msm_dba_device_info *device;
+ struct msm_dba_client_info *node;
+ struct list_head *pos = NULL;
+ bool video_on = false;
+
+ if (!c) {
+ pr_err("%s: Invalid Params\n", __func__);
+ return -EINVAL;
+ }
+
+ device = c->dev;
+ mutex_lock(&device->dev_mutex);
+
+ /*
+ * Video will be turned on if at least one client turns on video. But
+ * video off will be done only after all the clients have called video
+ * off
+ */
+ if (on == device->video_status) {
+ c->video_on = on;
+ } else if (on) {
+ rc = device->dev_ops.dev_video_on(device, cfg, on);
+ if (rc)
+ pr_err("%s:%s: video on failed\n", device->chip_name,
+ __func__);
+ else
+ c->video_on = on;
+ } else {
+ c->video_on = false;
+
+ list_for_each(pos, &device->client_list) {
+ node = list_entry(pos, struct msm_dba_client_info,
+ list);
+ if (c->video_on) {
+ video_on = true;
+ break;
+ }
+ }
+
+ if (!video_on) {
+ rc = device->dev_ops.dev_video_on(device, cfg, false);
+ if (rc) {
+ pr_err("%s:%s: video off failed\n",
+ device->chip_name, __func__);
+ c->video_on = true;
+ }
+ }
+ }
+
+ mutex_unlock(&device->dev_mutex);
+ return rc;
+}
+
+int msm_dba_helper_interrupts_enable(void *client, bool on,
+ u32 event_mask, u32 flags)
+{
+ struct msm_dba_client_info *c = client;
+ struct msm_dba_device_info *device;
+
+ if (!c) {
+ pr_err("%s: Invalid params\n", __func__);
+ return -EINVAL;
+ }
+
+ device = c->dev;
+ mutex_lock(&device->dev_mutex);
+
+ if (on)
+ c->event_mask = event_mask;
+ else
+ c->event_mask = 0;
+
+ mutex_unlock(&device->dev_mutex);
+ return 0;
+}
+
+int msm_dba_helper_register_irq(struct msm_dba_device_info *dev,
+ u32 irq, u32 irq_flags)
+{
+ int rc;
+
+ if (!dev) {
+ pr_err("%s: invalid params\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&dev->dev_mutex);
+
+ rc = request_threaded_irq(irq, NULL, msm_dba_helper_irq_handler,
+ irq_flags, dev->chip_name, dev);
+
+ if (rc)
+ pr_err("%s:%s: Failed to register irq\n", dev->chip_name,
+ __func__);
+
+ mutex_unlock(&dev->dev_mutex);
+ return rc;
+}
+
+int msm_dba_helper_get_caps(void *client, struct msm_dba_capabilities *caps)
+{
+ struct msm_dba_client_info *c = client;
+ struct msm_dba_device_info *device;
+
+ if (!c || !caps) {
+ pr_err("%s: invalid params\n", __func__);
+ return -EINVAL;
+ }
+
+ device = c->dev;
+ mutex_lock(&device->dev_mutex);
+
+ memcpy(caps, &device->caps, sizeof(*caps));
+
+ mutex_unlock(&device->dev_mutex);
+ return 0;
+}
+
+int msm_dba_register_hdcp_monitor(struct msm_dba_device_info *dev, bool enable)
+{
+ int rc = 0;
+
+ if (!dev) {
+ pr_err("%s: invalid params\n", __func__);
+ return -EINVAL;
+ }
+
+ if (enable) {
+ dev->hdcp_wq = alloc_workqueue("hdcp_monitor(%s:%d)", 0, 0,
+ dev->chip_name,
+ dev->instance_id);
+ if (!dev->hdcp_wq) {
+ pr_err("%s: failed to allocate wq\n", __func__);
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ INIT_WORK(&dev->hdcp_work, msm_dba_helper_hdcp_handler);
+ dev->hdcp_monitor_on = true;
+ } else if (!enable && dev->hdcp_wq) {
+ destroy_workqueue(dev->hdcp_wq);
+ dev->hdcp_wq = NULL;
+ dev->hdcp_monitor_on = false;
+ }
+
+fail:
+ return rc;
+}
+
+int msm_dba_helper_force_reset(void *client, u32 flags)
+{
+ struct msm_dba_client_info *c = client;
+ struct msm_dba_device_info *device;
+ int rc = 0;
+
+ if (!c) {
+ pr_err("%s: invalid params\n", __func__);
+ return -EINVAL;
+ }
+
+ device = c->dev;
+ mutex_lock(&device->dev_mutex);
+
+ msm_dba_helper_issue_cb(device, c, MSM_DBA_CB_PRE_RESET);
+
+ if (device->dev_ops.force_reset)
+ rc = device->dev_ops.force_reset(device, flags);
+
+ if (rc)
+ pr_err("%s: Force reset failed\n", __func__);
+
+ msm_dba_helper_issue_cb(device, c, MSM_DBA_CB_POST_RESET);
+
+ mutex_unlock(&device->dev_mutex);
+ return rc;
+}
diff --git a/drivers/video/fbdev/msm/msm_dba/msm_dba_init.c b/drivers/video/fbdev/msm/msm_dba/msm_dba_init.c
new file mode 100644
index 000000000000..96d0d70bccf8
--- /dev/null
+++ b/drivers/video/fbdev/msm/msm_dba/msm_dba_init.c
@@ -0,0 +1,131 @@
+/*
+ * 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"
+
+struct msm_dba_device_list {
+ struct msm_dba_device_info *dev;
+ struct list_head list;
+};
+
+static LIST_HEAD(device_list);
+static DEFINE_MUTEX(init_mutex);
+
+int msm_dba_add_probed_device(struct msm_dba_device_info *dev)
+{
+ struct msm_dba_device_list *node;
+
+ if (!dev) {
+ pr_err("%s: Invalid params\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&init_mutex);
+
+ node = kzalloc(sizeof(*node), GFP_KERNEL);
+ if (!node) {
+ mutex_unlock(&init_mutex);
+ return -ENOMEM;
+ }
+
+ memset(node, 0x0, sizeof(*node));
+ node->dev = dev;
+ list_add(&node->list, &device_list);
+
+ pr_debug("%s: Added new device (%s, %d)", __func__, dev->chip_name,
+ dev->instance_id);
+
+ mutex_unlock(&init_mutex);
+
+ return 0;
+}
+
+int msm_dba_get_probed_device(struct msm_dba_reg_info *reg,
+ struct msm_dba_device_info **dev)
+{
+ int rc = 0;
+ struct msm_dba_device_list *node;
+ struct list_head *position = NULL;
+
+ if (!reg || !dev) {
+ pr_err("%s: Invalid params\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&init_mutex);
+
+ *dev = NULL;
+ list_for_each(position, &device_list) {
+ node = list_entry(position, struct msm_dba_device_list, list);
+ if (!strcmp(reg->chip_name, node->dev->chip_name) &&
+ reg->instance_id == node->dev->instance_id) {
+ pr_debug("%s: Found device (%s, %d)\n", __func__,
+ reg->chip_name,
+ reg->instance_id);
+ *dev = node->dev;
+ break;
+ }
+ }
+
+ if (!*dev) {
+ pr_err("%s: Device not found (%s, %d)\n", __func__,
+ reg->chip_name,
+ reg->instance_id);
+ rc = -ENODEV;
+ }
+
+ mutex_unlock(&init_mutex);
+
+ return rc;
+}
+
+int msm_dba_remove_probed_device(struct msm_dba_device_info *dev)
+{
+ struct msm_dba_device_list *node;
+ struct list_head *position = NULL;
+ struct list_head *temp = NULL;
+
+ if (!dev) {
+ pr_err("%s: Invalid params\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&init_mutex);
+
+ list_for_each_safe(position, temp, &device_list) {
+ node = list_entry(position, struct msm_dba_device_list, list);
+ if (node->dev == dev) {
+ list_del(&node->list);
+ pr_debug("%s: Removed device (%s, %d)\n", __func__,
+ dev->chip_name,
+ dev->instance_id);
+ kfree(node);
+ break;
+ }
+ }
+
+ mutex_unlock(&init_mutex);
+
+ return 0;
+}
diff --git a/drivers/video/fbdev/msm/msm_dba/msm_dba_internal.h b/drivers/video/fbdev/msm/msm_dba/msm_dba_internal.h
new file mode 100644
index 000000000000..5da673bfcffb
--- /dev/null
+++ b/drivers/video/fbdev/msm/msm_dba/msm_dba_internal.h
@@ -0,0 +1,317 @@
+/*
+ * 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.
+ */
+
+#ifndef _MSM_DBA_INTERNAL_H
+#define _MSM_DBA_INTERNAL_H
+
+#include <video/msm_dba.h>
+
+struct msm_dba_client_info;
+struct msm_dba_device_info;
+
+/**
+ * struct msm_dba_device_ops - Function pointers to device specific operations
+ * @dev_power_on: Power on operation called by msm_dba_helper_power_on. Mutex
+ * protection is handled by the caller.
+ * @dev_video_on: Video on operation called by msm_dba_helper_video_on. Mutex
+ * protection is handled by the caller.
+ * @handle_interrupts: Function pointer called when an interrupt is fired. If
+ * the bridge driver uses msm_dba_helper_register_irq
+ * for handling interrupts, irq handler will call
+ * handle_interrupts to figure out the event mask.
+ * @unmask_interrupts: Function pointer called by irq handler for unmasking
+ * interrupts.
+ * @hdcp_reset: Function pointer to reset the HDCP block. This needs to be valid
+ * if HDCP monitor is used.
+ * @hdcp_retry: Function pointer to retry HDCP authentication. This needs to be
+ * valid if HDCP monitor is used.
+ * @write_reg: Function pointer to write to device specific register.
+ * @read_reg: Function pointer to read device specific register.
+ * @force_reset: Function pointer to force reset the device.
+ * @dump_debug_info: Function pointer to trigger a dump to dmesg.
+ *
+ * The device operation function pointers are used if bridge driver uses helper
+ * functions in place of some client operations. If used, the helper functions
+ * will call the device function pointers to perform device specific
+ * programming.
+ */
+struct msm_dba_device_ops {
+ int (*dev_power_on)(struct msm_dba_device_info *dev, bool on);
+ int (*dev_video_on)(struct msm_dba_device_info *dev,
+ struct msm_dba_video_cfg *cfg, bool on);
+ int (*handle_interrupts)(struct msm_dba_device_info *dev, u32 *mask);
+ int (*unmask_interrupts)(struct msm_dba_device_info *dev, u32 mask);
+ int (*hdcp_reset)(struct msm_dba_device_info *dev);
+ int (*hdcp_retry)(struct msm_dba_device_info *dev, u32 flags);
+ int (*write_reg)(struct msm_dba_device_info *dev, u32 reg, u32 val);
+ int (*read_reg)(struct msm_dba_device_info *dev, u32 reg, u32 *val);
+ int (*force_reset)(struct msm_dba_device_info *dev, u32 flags);
+ int (*dump_debug_info)(struct msm_dba_device_info *dev, u32 flags);
+};
+
+/**
+ * struct msm_dba_device_info - Device specific information
+ * @chip_name: chip name
+ * @instance_id: Instance id
+ * @caps: Capabilities of the bridge chip
+ * @dev_ops: function pointers to device specific operations
+ * @client_ops: function pointers to client operations
+ * @dev_mutex: mutex for protecting device access
+ * @hdcp_wq: HDCP workqueue for handling failures.
+ * @client_list: list head for client list
+ * @reg_fxn: Function pointer called when a client registers with dba driver
+ * @dereg_fxn: Function pointer called when a client deregisters.
+ * @power_status: current power status of device
+ * @video_status: current video status of device
+ * @audio_status: current audio status of device
+ * @hdcp_on: hdcp enable status.
+ * @enc-on: encryption enable status.
+ * @hdcp_status: hdcp link status.
+ * @hdcp_monitor_on: hdcp monitor status
+ * @register_val: debug field used to support read register.
+ *
+ * Structure containing device specific information. This structure is allocated
+ * by the bridge driver. This structure should be unique to each device.
+ *
+ */
+struct msm_dba_device_info {
+ char chip_name[MSM_DBA_CHIP_NAME_MAX_LEN];
+ u32 instance_id;
+ struct msm_dba_capabilities caps;
+ struct msm_dba_device_ops dev_ops;
+ struct msm_dba_ops client_ops;
+ struct mutex dev_mutex;
+ struct workqueue_struct *hdcp_wq;
+ struct work_struct hdcp_work;
+ struct list_head client_list;
+ int (*reg_fxn)(struct msm_dba_client_info *client);
+ int (*dereg_fxn)(struct msm_dba_client_info *client);
+
+ bool power_status;
+ bool video_status;
+ bool audio_status;
+ bool hdcp_on;
+ bool enc_on;
+ bool hdcp_status;
+ bool hdcp_monitor_on;
+
+ /* Debug info */
+ u32 register_val;
+};
+
+/**
+ * struct msm_dba_client_info - Client specific information
+ * @dev: pointer to device information
+ * @client_name: client name
+ * @power_on: client power on status
+ * @video_on: client video on status
+ * @audio_on: client audio on status
+ * @event_mask: client event mask for callbacks.
+ * @cb: callback function for the client
+ * @cb_data: callback data pointer.
+ * @list: list pointer
+ *
+ * This structure is used to uniquely identify a client for a bridge chip. The
+ * pointer to this structure is returned as a handle from
+ * msm_dba_register_client.
+ */
+struct msm_dba_client_info {
+ struct msm_dba_device_info *dev;
+ char client_name[MSM_DBA_CLIENT_NAME_LEN];
+ bool power_on;
+ bool video_on;
+ bool audio_on;
+ u32 event_mask;
+ msm_dba_cb cb;
+ void *cb_data;
+ struct list_head list;
+};
+
+/**
+ * msm_dba_add_probed_device() - Add a new device to the probed devices list.
+ * @info: Pointer to structure containing the device information. This should be
+ * allocated by the specific bridge driver and kept until
+ * msm_dba_remove_probed_device() is called.
+ *
+ * Once a bridge chip is initialized and probed, it should add its device to the
+ * existing list of all probed display bridge chips. This list is maintained by
+ * the MSM DBA driver and is checked whenever there is a client register
+ * request.
+ */
+int msm_dba_add_probed_device(struct msm_dba_device_info *info);
+
+/**
+ * msm_dba_remove_probed_device() - Remove a device from the probed devices list
+ * @info: Pointer to structure containing the device info. This should be the
+ * same pointer used for msm_dba_add_probed_device().
+ *
+ * Bridge chip driver should call this to remove device from probed list.
+ */
+int msm_dba_remove_probed_device(struct msm_dba_device_info *info);
+
+/**
+ * msm_dba_get_probed_device() - Check if a device is present in the device list
+ * @reg: Pointer to structure containing the chip info received from the client
+ * driver
+ * @info: Pointer to the device info pointer that will be returned if the device
+ * has been found in the device list
+ *
+ * When clients of the MSM DBA driver call msm_dba_register_client(), the MSM
+ * DBA driver will use this function to check if the specific device requested
+ * by the client has been probed. If probed, function will return a pointer to
+ * the device information structure.
+ */
+int msm_dba_get_probed_device(struct msm_dba_reg_info *reg,
+ struct msm_dba_device_info **info);
+
+/**
+ * msm_dba_helper_i2c_read() - perform an i2c read transaction
+ * @client: i2c client pointer
+ * @addr: i2c slave address
+ * @reg: register where the data should be read from
+ * @buf: buffer where the read data is stored.
+ * @size: bytes to read from slave. buffer should be atleast size bytes.
+ *
+ * Helper function to perform a read from an i2c slave. Internally this calls
+ * i2c_transfer().
+ */
+int msm_dba_helper_i2c_read(struct i2c_client *client,
+ u8 addr,
+ u8 reg,
+ char *buf,
+ u32 size);
+
+/**
+ * msm_dba_helper_i2c_write_buffer() - write buffer to i2c slave.
+ * @client: i2c client pointer
+ * @addr: i2c slave address
+ * @buf: buffer where the data will be read from.
+ * @size: bytes to write.
+ *
+ * Helper function to perform a write to an i2c slave. Internally this calls
+ * i2c_transfer().
+ */
+int msm_dba_helper_i2c_write_buffer(struct i2c_client *client,
+ u8 addr,
+ u8 *buf,
+ u32 size);
+
+/**
+ * msm_dba_helper_i2c_write_byte() - write to a register on an i2c slave.
+ * @client: i2c client pointer
+ * @addr: i2c slave address
+ * @reg: slave register to write to
+ * @val: data to write.
+ *
+ * Helper function to perform a write to an i2c slave. Internally this calls
+ * i2c_transfer().
+ */
+int msm_dba_helper_i2c_write_byte(struct i2c_client *client,
+ u8 addr,
+ u8 reg,
+ u8 val);
+
+/**
+ * msm_dba_helper_power_on() - power on bridge chip
+ * @client: client handle
+ * @on: on/off
+ * @flags: flags
+ *
+ * This helper function can be used as power_on() function defined in struct
+ * msm_dba_ops. Internally, this function does some bookkeeping to figure out
+ * when to actually power on/off the device. If used, bridge driver should
+ * provide a dev_power_on to do the device specific power change.
+ */
+int msm_dba_helper_power_on(void *client, bool on, u32 flags);
+
+/**
+ * msm_dba_helper_video_on() - video on bridge chip
+ * @client: client handle
+ * @on: on/off
+ * @flags: flags
+ *
+ * This helper function can be used as video_on() function defined in struct
+ * msm_dba_ops. Internally, this function does some bookkeeping to figure out
+ * when to actually video on/off the device. If used, bridge driver should
+ * provide a dev_video_on to do the device specific video change.
+ */
+int msm_dba_helper_video_on(void *client, bool on,
+ struct msm_dba_video_cfg *cfg, u32 flags);
+
+/**
+ * msm_dba_helper_interrupts_enable() - manage interrupt callbacks
+ * @client: client handle
+ * @on: on/off
+ * @events_mask: events on which callbacks are required.
+ * @flags: flags
+ *
+ * This helper function provides the functionality needed for interrupts_enable
+ * function pointer in struct msm_dba_ops.
+ */
+int msm_dba_helper_interrupts_enable(void *client, bool on,
+ u32 events_mask, u32 flags);
+
+/**
+ * msm_dba_helper_get_caps() - return device capabilities
+ * @client: client handle
+ * @flags: flags
+ *
+ * Helper function to replace get_caps function pointer in struct msm_dba_ops
+ * structure.
+ */
+int msm_dba_helper_get_caps(void *client, struct msm_dba_capabilities *caps);
+
+/**
+ * msm_dba_helper_register_irq() - register irq and handle interrupts.
+ * @dev: pointer to device structure
+ * @irq: irq number
+ * @irq_flags: irq_flags.
+ *
+ * Helper function register an irq and handling interrupts. This will attach a
+ * threaded interrupt handler to the irq provided as input. When the irq
+ * handler is triggered, handler will call handle_interrupts in the device
+ * specific functions pointers so that bridge driver can parse the interrupt
+ * status registers and return the event mask. IRQ handler will use this event
+ * mask to provide callbacks to the clients. Once the callbacks are done,
+ * handler will call unmask_interrupts() before returning,
+ */
+int msm_dba_helper_register_irq(struct msm_dba_device_info *dev,
+ u32 irq, u32 irq_flags);
+
+/**
+ * msm_dba_register_hdcp_monitor() - kicks off monitoring for hdcp failures
+ * @dev: pointer to device structure.
+ * @enable: enable/disable
+ *
+ * Helper function to enable HDCP monitoring. This should be called only if irq
+ * is handled through msm dba helper functions.
+ */
+int msm_dba_register_hdcp_monitor(struct msm_dba_device_info *dev, bool enable);
+
+/**
+ * msm_dba_helper_sysfs_init() - create sysfs attributes for debugging
+ * @dev: pointer to struct device structure.
+ *
+ */
+int msm_dba_helper_sysfs_init(struct device *dev);
+
+/**
+ * msm_dba_helper_force_reset() - force reset bridge chip
+ * @client: client handle
+ * @flags: flags
+ *
+ * Helper function to replace force_reset function pointer in struct msm_dba_ops
+ * structure. Driver should set dev_ops.force_reset to a valid function.
+ */
+int msm_dba_helper_force_reset(void *client, u32 flags);
+#endif /* _MSM_DBA_INTERNAL_H */