Merge "sensors: Add the class device support for bmp18x sensor"
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index dde7051..9a9654f 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -255,9 +255,6 @@
VERIFY(err, 0 != (sg = ion_sg_table(clnt, buf->handle)));
if (err)
goto bail;
- VERIFY(err, 1 == sg->nents);
- if (err)
- goto bail;
buf->phys = sg_dma_address(sg->sgl);
}
bail:
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
index 642975d..3b7bf5a 100644
--- a/drivers/input/misc/mpu3050.c
+++ b/drivers/input/misc/mpu3050.c
@@ -37,6 +37,7 @@
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/input.h>
+#include <linux/sensors.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
@@ -128,6 +129,20 @@
u32 enable;
};
+static struct sensors_classdev sensors_cdev = {
+ .name = "mpu3050-gyro",
+ .vendor = "Invensense",
+ .version = 1,
+ .handle = SENSORS_GYROSCOPE_HANDLE,
+ .type = SENSOR_TYPE_GYROSCOPE,
+ .max_range = "35.0",
+ .resolution = "0.06",
+ .sensor_power = "0.2",
+ .min_delay = 2000,
+ .fifo_reserved_event_count = 0,
+ .fifo_max_event_count = 0,
+};
+
struct sensor_regulator {
struct regulator *vreg;
const char *name;
@@ -804,10 +819,16 @@
goto err_free_irq;
}
+ error = sensors_classdev_register(&client->dev, &sensors_cdev);
+ if (error < 0) {
+ dev_err(&client->dev, "failed to create class device\n");
+ goto err_input_cleanup;
+ }
+
error = create_sysfs_interfaces(&idev->dev);
if (error < 0) {
dev_err(&client->dev, "failed to create sysfs\n");
- goto err_input_cleanup;
+ goto err_class_sysfs;
}
pm_runtime_enable(&client->dev);
@@ -815,6 +836,8 @@
return 0;
+err_class_sysfs:
+ sensors_classdev_unregister(&sensors_cdev);
err_input_cleanup:
input_unregister_device(idev);
err_free_irq:
diff --git a/drivers/input/misc/stk3x1x.c b/drivers/input/misc/stk3x1x.c
index b753d55..f1b060e 100644
--- a/drivers/input/misc/stk3x1x.c
+++ b/drivers/input/misc/stk3x1x.c
@@ -32,6 +32,7 @@
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/input.h>
+#include <linux/sensors.h>
#include <linux/workqueue.h>
#include <linux/irq.h>
#include <linux/delay.h>
@@ -181,6 +182,35 @@
#define STK_FIR_LEN 16
#define MAX_FIR_LEN 32
+
+static struct sensors_classdev sensors_light_cdev = {
+ .name = "stk3x1x-light",
+ .vendor = "Sensortek",
+ .version = 1,
+ .handle = SENSORS_LIGHT_HANDLE,
+ .type = SENSOR_TYPE_LIGHT,
+ .max_range = "6500",
+ .resolution = "0.0625",
+ .sensor_power = "0.09",
+ .min_delay = 0,
+ .fifo_reserved_event_count = 0,
+ .fifo_max_event_count = 0,
+};
+
+static struct sensors_classdev sensors_proximity_cdev = {
+ .name = "stk3x1x-proximity",
+ .vendor = "Sensortek",
+ .version = 1,
+ .handle = SENSORS_PROXIMITY_HANDLE,
+ .type = SENSOR_TYPE_PROXIMITY,
+ .max_range = "5.0",
+ .resolution = "5.0",
+ .sensor_power = "0.1",
+ .min_delay = 0,
+ .fifo_reserved_event_count = 0,
+ .fifo_max_event_count = 0,
+};
+
struct data_filter {
u16 raw[MAX_FIR_LEN];
int sum;
@@ -2363,6 +2393,14 @@
ps_data->stk_early_suspend.resume = stk3x1x_late_resume;
register_early_suspend(&ps_data->stk_early_suspend);
#endif
+ /* make sure everything is ok before registering the class device */
+ err = sensors_classdev_register(&client->dev, &sensors_light_cdev);
+ if (err)
+ goto err_power_on;
+ err = sensors_classdev_register(&client->dev, &sensors_proximity_cdev);
+ if (err)
+ goto err_class_sysfs;
+
/* enable device power only when it is enabled */
err = stk3x1x_power_ctl(ps_data, false);
if (err)
@@ -2373,6 +2411,9 @@
err_init_all_setting:
stk3x1x_power_ctl(ps_data, false);
+ sensors_classdev_unregister(&sensors_proximity_cdev);
+err_class_sysfs:
+ sensors_classdev_unregister(&sensors_light_cdev);
err_power_on:
stk3x1x_power_init(ps_data, false);
err_power_init:
diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c
index 7282c2e..ad62d5e 100644
--- a/drivers/input/touchscreen/synaptics_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_fw_update.c
@@ -2054,26 +2054,26 @@
__ATTR(fw_name, S_IRUGO | S_IWUSR | S_IWGRP,
fwu_sysfs_image_name_show,
fwu_sysfs_image_name_store),
- __ATTR(force_update_fw, S_IRUGO | S_IWUSR | S_IWGRP,
- synaptics_rmi4_show_error,
+ __ATTR(force_update_fw, S_IWUSR | S_IWGRP,
+ NULL,
fwu_sysfs_force_reflash_store),
- __ATTR(update_fw, S_IRUGO | S_IWUSR | S_IWGRP,
- synaptics_rmi4_show_error,
+ __ATTR(update_fw, S_IWUSR | S_IWGRP,
+ NULL,
fwu_sysfs_do_reflash_store),
- __ATTR(writeconfig, S_IRUGO | S_IWUSR | S_IWGRP,
- synaptics_rmi4_show_error,
+ __ATTR(writeconfig, S_IWUSR | S_IWGRP,
+ NULL,
fwu_sysfs_write_config_store),
- __ATTR(writelockdown, S_IRUGO | S_IWUSR | S_IWGRP,
- synaptics_rmi4_show_error,
+ __ATTR(writelockdown, S_IWUSR | S_IWGRP,
+ NULL,
fwu_sysfs_write_lockdown_store),
- __ATTR(readconfig, S_IRUGO | S_IWUSR | S_IWGRP,
- synaptics_rmi4_show_error,
+ __ATTR(readconfig, S_IWUSR | S_IWGRP,
+ NULL,
fwu_sysfs_read_config_store),
- __ATTR(configarea, S_IRUGO | S_IWUSR | S_IWGRP,
- synaptics_rmi4_show_error,
+ __ATTR(configarea, S_IWUSR | S_IWGRP,
+ NULL,
fwu_sysfs_config_area_store),
- __ATTR(imagesize, S_IRUGO | S_IWUSR | S_IWGRP,
- synaptics_rmi4_show_error,
+ __ATTR(imagesize, S_IWUSR | S_IWGRP,
+ NULL,
fwu_sysfs_image_size_store),
__ATTR(blocksize, S_IRUGO,
fwu_sysfs_block_size_show,
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index d21b6c1..b011315 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -392,8 +392,8 @@
synaptics_rmi4_full_pm_cycle_show,
synaptics_rmi4_full_pm_cycle_store),
#endif
- __ATTR(reset, S_IRUGO | S_IWUSR | S_IWGRP,
- synaptics_rmi4_show_error,
+ __ATTR(reset, S_IWUSR | S_IWGRP,
+ NULL,
synaptics_rmi4_f01_reset_store),
__ATTR(productinfo, S_IRUGO,
synaptics_rmi4_f01_productinfo_show,
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.h b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
index ef39bb7..f77378a 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.h
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
@@ -286,14 +286,6 @@
void (*func_attn)(struct synaptics_rmi4_data *rmi4_data,
unsigned char intr_mask));
-static inline ssize_t synaptics_rmi4_show_error(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- dev_warn(dev, "%s Attempted to read from write-only attribute %s\n",
- __func__, attr->attr.name);
- return -EPERM;
-}
-
static inline ssize_t synaptics_rmi4_store_error(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
diff --git a/drivers/input/touchscreen/synaptics_rmi_dev.c b/drivers/input/touchscreen/synaptics_rmi_dev.c
index c60ca23..7abd909 100644
--- a/drivers/input/touchscreen/synaptics_rmi_dev.c
+++ b/drivers/input/touchscreen/synaptics_rmi_dev.c
@@ -73,19 +73,19 @@
};
static struct device_attribute attrs[] = {
- __ATTR(open, S_IRUGO | S_IWUSR | S_IWGRP,
- synaptics_rmi4_show_error,
+ __ATTR(open, S_IWUSR | S_IWGRP,
+ NULL,
rmidev_sysfs_open_store),
- __ATTR(release, S_IRUGO | S_IWUSR | S_IWGRP,
- synaptics_rmi4_show_error,
+ __ATTR(release, S_IWUSR | S_IWGRP,
+ NULL,
rmidev_sysfs_release_store),
- __ATTR(address, S_IRUGO | S_IWUSR | S_IWGRP,
- synaptics_rmi4_show_error,
+ __ATTR(address, S_IWUSR | S_IWGRP,
+ NULL,
rmidev_sysfs_address_store),
- __ATTR(length, S_IRUGO | S_IWUSR | S_IWGRP,
- synaptics_rmi4_show_error,
+ __ATTR(length, S_IWUSR | S_IWGRP,
+ NULL,
rmidev_sysfs_length_store),
- __ATTR(data, (S_IRUGO | S_IWUSR | S_IWGRP),
+ __ATTR(data, (S_IWUSR | S_IWGRP),
rmidev_sysfs_data_show,
rmidev_sysfs_data_store),
};
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 8ae5671..7954296 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -2761,7 +2761,7 @@
rc = of_property_read_u32(node, "qcom,duration", &val);
if (!rc)
- led->flash_cfg->duration = (((u8) val) - 10) / 10;
+ led->flash_cfg->duration = (u8)((val - 10) / 10);
else if (rc == -EINVAL)
led->flash_cfg->duration = FLASH_DURATION_200ms;
else
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_common.h b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_common.h
index 04af6b6..634beca 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_common.h
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_common.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, 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
@@ -20,7 +20,7 @@
#endif
#define JPEG_PR_ERR pr_err
-#define JPEG_DBG_HIGH pr_err
+#define JPEG_DBG_HIGH pr_debug
enum JPEG_MODE {
JPEG_MODE_DISABLE,
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
index 0a0fa04..77df737 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, 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
@@ -216,15 +216,15 @@
if (pingpong_index == 0) {
hw_cmd_p = &hw_cmd_we_ping_update[0];
hw_cmd_p->data = p_input->y_buffer_addr;
- JPEG_PR_ERR("%s Output pln0 buffer address is %x\n", __func__,
+ JPEG_DBG_HIGH("%s Output pln0 buffer address is %x\n", __func__,
p_input->y_buffer_addr);
msm_jpeg_hw_write(hw_cmd_p++, base);
hw_cmd_p->data = p_input->cbcr_buffer_addr;
- JPEG_PR_ERR("%s Output pln1 buffer address is %x\n", __func__,
+ JPEG_DBG_HIGH("%s Output pln1 buffer address is %x\n", __func__,
p_input->cbcr_buffer_addr);
msm_jpeg_hw_write(hw_cmd_p++, base);
hw_cmd_p->data = p_input->pln2_addr;
- JPEG_PR_ERR("%s Output pln2 buffer address is %x\n", __func__,
+ JPEG_DBG_HIGH("%s Output pln2 buffer address is %x\n", __func__,
p_input->pln2_addr);
msm_jpeg_hw_write(hw_cmd_p++, base);
}
diff --git a/drivers/media/platform/msm/vidc/msm_smem.h b/drivers/media/platform/msm/vidc/msm_smem.h
index 7bd6443..ca92e73 100644
--- a/drivers/media/platform/msm/vidc/msm_smem.h
+++ b/drivers/media/platform/msm/vidc/msm_smem.h
@@ -28,41 +28,6 @@
SMEM_SECURE = ION_FLAG_SECURE,
};
-/* NOTE: if you change this enum you MUST update the
- * "buffer-type-tz-usage-table" for any affected target
- * in arch/arm/boot/dts/<arch>.dtsi
- */
-enum hal_buffer {
- HAL_BUFFER_INPUT = 0x1,
- HAL_BUFFER_OUTPUT = 0x2,
- HAL_BUFFER_OUTPUT2 = 0x4,
- HAL_BUFFER_EXTRADATA_INPUT = 0x8,
- HAL_BUFFER_EXTRADATA_OUTPUT = 0x10,
- HAL_BUFFER_EXTRADATA_OUTPUT2 = 0x20,
- HAL_BUFFER_INTERNAL_SCRATCH = 0x40,
- HAL_BUFFER_INTERNAL_SCRATCH_1 = 0x80,
- HAL_BUFFER_INTERNAL_SCRATCH_2 = 0x100,
- HAL_BUFFER_INTERNAL_PERSIST = 0x200,
- HAL_BUFFER_INTERNAL_PERSIST_1 = 0x400,
- HAL_BUFFER_INTERNAL_CMD_QUEUE = 0x800,
-};
-
-struct msm_smem {
- int mem_type;
- size_t size;
- void *kvaddr;
- unsigned long device_addr;
- u32 flags;
- void *smem_priv;
- enum hal_buffer buffer_type;
-};
-
-enum smem_cache_ops {
- SMEM_CACHE_CLEAN,
- SMEM_CACHE_INVALIDATE,
- SMEM_CACHE_CLEAN_INVALIDATE,
-};
-
void *msm_smem_new_client(enum smem_type mtype,
struct msm_vidc_platform_resources *res);
struct msm_smem *msm_smem_alloc(void *clt, size_t size, u32 align, u32 flags,
@@ -73,7 +38,6 @@
enum smem_cache_ops);
struct msm_smem *msm_smem_user_to_kernel(void *clt, int fd, u32 offset,
enum hal_buffer buffer_type);
-int msm_smem_clean_invalidate(void *clt, struct msm_smem *mem);
int msm_smem_get_domain_partition(void *clt, u32 flags, enum hal_buffer
buffer_type, int *domain_num, int *partition_num);
#endif
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index efa195e..9dd4e93 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -971,6 +971,14 @@
rc = -EINVAL;
goto err_invalid_fmt;
}
+ if (!(get_hal_codec_type(fmt->fourcc) &
+ inst->core->dec_codec_supported)) {
+ dprintk(VIDC_ERR,
+ "Codec(0x%x) not supported\n",
+ get_hal_codec_type(fmt->fourcc));
+ rc = -EINVAL;
+ goto err_invalid_fmt;
+ }
inst->fmts[fmt->type] = fmt;
rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE);
if (rc) {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 6ed94e4..25917c1 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -356,7 +356,7 @@
struct v4l2_plane *p, enum hal_buffer buffer_type)
{
struct msm_smem *handle = NULL;
- handle = msm_smem_user_to_kernel(inst->mem_client,
+ handle = msm_comm_smem_user_to_kernel(inst,
p->reserved[0],
p->reserved[1],
buffer_type);
@@ -365,7 +365,7 @@
"%s: Failed to get device buffer address\n", __func__);
return NULL;
}
- if (msm_smem_cache_operations(inst->mem_client, handle,
+ if (msm_comm_smem_cache_operations(inst, handle,
SMEM_CACHE_CLEAN))
dprintk(VIDC_WARN,
"CACHE Clean failed: %d, %d, %d\n",
@@ -584,7 +584,7 @@
dprintk(VIDC_DBG,
"[UNMAP] - handle[%d] = %p fd[%d] = %d",
i, temp->handle[i], i, temp->fd[i]);
- msm_smem_free(inst->mem_client,
+ msm_comm_smem_free(inst,
temp->handle[i]);
}
@@ -660,7 +660,7 @@
for (i = 0; i < binfo->num_planes; i++) {
if (binfo->handle[i]) {
- rc = msm_smem_cache_operations(inst->mem_client,
+ rc = msm_comm_smem_cache_operations(inst,
binfo->handle[i], SMEM_CACHE_INVALIDATE);
if (rc) {
dprintk(VIDC_ERR,
@@ -745,7 +745,7 @@
list_del(&bi->list);
for (i = 0; i < bi->num_planes; i++) {
if (bi->handle[i])
- msm_smem_free(inst->mem_client,
+ msm_comm_smem_free(inst,
bi->handle[i]);
}
kfree(bi);
@@ -824,7 +824,7 @@
if ((inst->fmts[OUTPUT_PORT]->fourcc ==
V4L2_PIX_FMT_HEVC_HYBRID) && binfo->handle[i] &&
(b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) {
- rc = msm_smem_cache_operations(inst->mem_client,
+ rc = msm_comm_smem_cache_operations(inst,
binfo->handle[i], SMEM_CACHE_INVALIDATE);
if (rc) {
dprintk(VIDC_ERR,
@@ -835,7 +835,7 @@
if (binfo->handle[i] &&
(b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) {
- rc = msm_smem_cache_operations(inst->mem_client,
+ rc = msm_comm_smem_cache_operations(inst,
binfo->handle[i], SMEM_CACHE_CLEAN);
if (rc) {
dprintk(VIDC_ERR,
@@ -970,6 +970,57 @@
fsize->stepwise.step_height = capability->height.step_size;
return 0;
}
+
+struct msm_smem *msm_vidc_smem_alloc(void *instance,
+ size_t size, u32 align, u32 flags,
+ enum hal_buffer buffer_type, int map_kernel)
+{
+ return msm_comm_smem_alloc((struct msm_vidc_inst *)instance,
+ size, align, flags, buffer_type, map_kernel);
+
+}
+
+void msm_vidc_smem_free(void *instance, struct msm_smem *mem)
+{
+ msm_comm_smem_free((struct msm_vidc_inst *)instance, mem);
+}
+
+int msm_vidc_smem_cache_operations(void *instance, struct msm_smem *mem,
+ enum smem_cache_ops cache_ops)
+{
+ return msm_comm_smem_cache_operations(
+ (struct msm_vidc_inst *)instance, mem, cache_ops);
+}
+
+struct msm_smem *msm_vidc_smem_user_to_kernel(void *instance, int fd,
+ u32 offset, enum hal_buffer buffer_type)
+{
+ return msm_comm_smem_user_to_kernel(
+ (struct msm_vidc_inst *)instance,
+ fd, offset, buffer_type);
+}
+
+int msm_vidc_smem_get_domain_partition(void *instance, u32 flags,
+ enum hal_buffer buffer_type, int *domain_num,
+ int *partition_num)
+{
+ return msm_comm_smem_get_domain_partition(
+ (struct msm_vidc_inst *)instance,
+ flags, buffer_type, domain_num, partition_num);
+}
+
+void *msm_vidc_smem_get_client(void *instance)
+{
+ struct msm_vidc_inst *inst = instance;
+
+ if (!inst || !inst->mem_client) {
+ dprintk(VIDC_ERR, "%s: invalid instance or client = %p %p\n",
+ __func__, inst, inst->mem_client);
+ return NULL;
+ }
+
+ return inst->mem_client;
+}
static void *vidc_get_userptr(void *alloc_ctx, unsigned long vaddr,
unsigned long size, int write)
{
@@ -1189,7 +1240,7 @@
list);
list_del(&buf->list);
mutex_unlock(&inst->lock);
- msm_smem_free(inst->mem_client, buf->handle);
+ msm_comm_smem_free(inst, buf->handle);
kfree(buf);
mutex_lock(&inst->lock);
}
@@ -1200,7 +1251,7 @@
list);
list_del(&buf->list);
mutex_unlock(&inst->lock);
- msm_smem_free(inst->mem_client, buf->handle);
+ msm_comm_smem_free(inst, buf->handle);
kfree(buf);
mutex_lock(&inst->lock);
}
@@ -1211,14 +1262,14 @@
list);
list_del(&buf->list);
mutex_unlock(&inst->lock);
- msm_smem_free(inst->mem_client, buf->handle);
+ msm_comm_smem_free(inst, buf->handle);
kfree(buf);
mutex_lock(&inst->lock);
}
}
if (inst->extradata_handle) {
mutex_unlock(&inst->lock);
- msm_smem_free(inst->mem_client, inst->extradata_handle);
+ msm_comm_smem_free(inst, inst->extradata_handle);
mutex_lock(&inst->lock);
}
mutex_unlock(&inst->lock);
@@ -1247,8 +1298,7 @@
for (i = 0; (i < bi->num_planes)
&& (i < VIDEO_MAX_PLANES); i++) {
if (bi->handle[i])
- msm_smem_free(inst->mem_client,
- bi->handle[i]);
+ msm_comm_smem_free(inst, bi->handle[i]);
}
kfree(bi);
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index e127dc1..9387a17 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -277,14 +277,17 @@
dprintk(VIDC_ERR, "Wrong device_id received\n");
return;
}
- dprintk(VIDC_DBG, "index = %d\n", index);
- dprintk(VIDC_DBG, "ptr = %p\n", &(core->completions[index]));
- complete(&(core->completions[index]));
sys_init_msg = response->data;
if (!sys_init_msg) {
dprintk(VIDC_ERR, "sys_init_done message not proper\n");
return;
}
+ core->enc_codec_supported = sys_init_msg->enc_codec_supported;
+ core->dec_codec_supported = sys_init_msg->dec_codec_supported;
+ dprintk(VIDC_DBG, "supported_codecs: enc = 0x%x, dec = 0x%x\n",
+ core->enc_codec_supported, core->dec_codec_supported);
+ dprintk(VIDC_DBG, "ptr[%d] = %p\n", index, &(core->completions[index]));
+ complete(&(core->completions[index]));
}
static void handle_session_release_buf_done(enum command_response cmd,
@@ -1598,7 +1601,7 @@
return domain;
}
-static enum hal_video_codec get_hal_codec_type(int fourcc)
+enum hal_video_codec get_hal_codec_type(int fourcc)
{
enum hal_video_codec codec;
dprintk(VIDC_DBG, "codec is 0x%x", fourcc);
@@ -1998,7 +2001,7 @@
if (output_buf->buffer_size) {
for (i = 0; i < output_buf->buffer_count_actual;
i++) {
- handle = msm_smem_alloc(inst->mem_client,
+ handle = msm_comm_smem_alloc(inst,
buffer_size, 1, smem_flags,
buffer_type, 0);
if (!handle) {
@@ -2007,7 +2010,7 @@
rc = -ENOMEM;
goto err_no_mem;
}
- rc = msm_smem_cache_operations(inst->mem_client,
+ rc = msm_comm_smem_cache_operations(inst,
handle, SMEM_CACHE_CLEAN);
if (rc) {
dprintk(VIDC_WARN,
@@ -2052,7 +2055,7 @@
fail_set_buffers:
kfree(binfo);
fail_kzalloc:
- msm_smem_free(inst->mem_client, handle);
+ msm_comm_smem_free(inst, handle);
err_no_mem:
return rc;
}
@@ -2089,7 +2092,7 @@
if (scratch_buf->buffer_size) {
for (i = 0; i < scratch_buf->buffer_count_actual;
i++) {
- handle = msm_smem_alloc(inst->mem_client,
+ handle = msm_comm_smem_alloc(inst,
scratch_buf->buffer_size, 1, smem_flags,
buffer_type, 0);
if (!handle) {
@@ -2098,7 +2101,7 @@
rc = -ENOMEM;
goto err_no_mem;
}
- rc = msm_smem_cache_operations(inst->mem_client,
+ rc = msm_comm_smem_cache_operations(inst,
handle, SMEM_CACHE_CLEAN);
if (rc) {
dprintk(VIDC_WARN,
@@ -2134,7 +2137,7 @@
fail_set_buffers:
kfree(binfo);
fail_kzalloc:
- msm_smem_free(inst->mem_client, handle);
+ msm_comm_smem_free(inst, handle);
err_no_mem:
return rc;
}
@@ -2176,7 +2179,7 @@
if (persist_buf->buffer_size) {
for (i = 0; i < persist_buf->buffer_count_actual; i++) {
- handle = msm_smem_alloc(inst->mem_client,
+ handle = msm_comm_smem_alloc(inst,
persist_buf->buffer_size, 1, smem_flags,
buffer_type, 0);
if (!handle) {
@@ -2185,7 +2188,7 @@
rc = -ENOMEM;
goto err_no_mem;
}
- rc = msm_smem_cache_operations(inst->mem_client,
+ rc = msm_comm_smem_cache_operations(inst,
handle, SMEM_CACHE_CLEAN);
if (rc) {
dprintk(VIDC_WARN,
@@ -2221,7 +2224,7 @@
fail_set_buffers:
kfree(binfo);
fail_kzalloc:
- msm_smem_free(inst->mem_client, handle);
+ msm_comm_smem_free(inst, handle);
err_no_mem:
return rc;
}
@@ -2593,7 +2596,7 @@
}
list_del(&buf->list);
mutex_unlock(&inst->lock);
- msm_smem_free(inst->mem_client, buf->handle);
+ msm_comm_smem_free(inst, buf->handle);
kfree(buf);
mutex_lock(&inst->lock);
}
@@ -2664,7 +2667,7 @@
}
list_del(&buf->list);
mutex_unlock(&inst->lock);
- msm_smem_free(inst->mem_client, buf->handle);
+ msm_comm_smem_free(inst, buf->handle);
kfree(buf);
mutex_lock(&inst->lock);
}
@@ -2735,7 +2738,7 @@
}
list_del(&buf->list);
mutex_unlock(&inst->lock);
- msm_smem_free(inst->mem_client, buf->handle);
+ msm_comm_smem_free(inst, buf->handle);
kfree(buf);
mutex_lock(&inst->lock);
}
@@ -3343,3 +3346,85 @@
change_inst_state(inst, MSM_VIDC_CLOSE_DONE);
return rc;
}
+
+static inline int power_on_for_smem(struct msm_vidc_inst *inst)
+{
+ struct hfi_device *hdev = NULL;
+ int rc = 0;
+
+ if (!inst || !inst->core || !inst->core->device) {
+ dprintk(VIDC_ERR, "%s: invalid inst handle\n", __func__);
+ return -EINVAL;
+ }
+ hdev = inst->core->device;
+ rc = call_hfi_op(hdev, power_enable, hdev->hfi_device_data);
+ if (rc)
+ dprintk(VIDC_ERR, "%s: failed to power on fw\n", __func__);
+ return rc;
+}
+
+struct msm_smem *msm_comm_smem_alloc(struct msm_vidc_inst *inst,
+ size_t size, u32 align, u32 flags,
+ enum hal_buffer buffer_type, int map_kernel)
+{
+ if (!inst) {
+ dprintk(VIDC_ERR, "%s: invalid inst: %p\n", __func__, inst);
+ return NULL;
+ }
+ if (power_on_for_smem(inst))
+ return NULL;
+
+ return msm_smem_alloc(inst->mem_client, size, align,
+ flags, buffer_type, map_kernel);
+}
+
+void msm_comm_smem_free(struct msm_vidc_inst *inst, struct msm_smem *mem)
+{
+ if (!inst || !mem) {
+ dprintk(VIDC_ERR,
+ "%s: invalid params: %p %p\n", __func__, inst, mem);
+ return;
+ }
+ if (power_on_for_smem(inst))
+ return;
+
+ return msm_smem_free(inst->mem_client, mem);
+}
+
+int msm_comm_smem_cache_operations(struct msm_vidc_inst *inst,
+ struct msm_smem *mem, enum smem_cache_ops cache_ops)
+{
+ if (!inst || !mem) {
+ dprintk(VIDC_ERR,
+ "%s: invalid params: %p %p\n", __func__, inst, mem);
+ return -EINVAL;
+ }
+ return msm_smem_cache_operations(inst->mem_client, mem, cache_ops);
+}
+
+struct msm_smem *msm_comm_smem_user_to_kernel(struct msm_vidc_inst *inst,
+ int fd, u32 offset, enum hal_buffer buffer_type)
+{
+ if (!inst) {
+ dprintk(VIDC_ERR, "%s: invalid inst: %p\n", __func__, inst);
+ return NULL;
+ }
+ if (power_on_for_smem(inst))
+ return NULL;
+
+ return msm_smem_user_to_kernel(inst->mem_client,
+ fd, offset, buffer_type);
+}
+
+int msm_comm_smem_get_domain_partition(struct msm_vidc_inst *inst,
+ u32 flags, enum hal_buffer buffer_type,
+ int *domain_num, int *partition_num)
+{
+ if (!inst || !domain_num || !partition_num) {
+ dprintk(VIDC_ERR, "%s: invalid params: %p %p %p\n",
+ __func__, inst, domain_num, partition_num);
+ return -EINVAL;
+ }
+ return msm_smem_get_domain_partition(inst->mem_client, flags,
+ buffer_type, domain_num, partition_num);
+}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
index 195fa7e..e2f7b61 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h
@@ -52,5 +52,16 @@
int msm_comm_recover_from_session_error(struct msm_vidc_inst *inst);
enum multi_stream msm_comm_get_stream_output_mode(struct msm_vidc_inst *inst);
enum hal_buffer msm_comm_get_hal_output_buffer(struct msm_vidc_inst *inst);
-
+struct msm_smem *msm_comm_smem_alloc(struct msm_vidc_inst *inst,
+ size_t size, u32 align, u32 flags,
+ enum hal_buffer buffer_type, int map_kernel);
+void msm_comm_smem_free(struct msm_vidc_inst *inst, struct msm_smem *mem);
+int msm_comm_smem_cache_operations(struct msm_vidc_inst *inst,
+ struct msm_smem *mem, enum smem_cache_ops cache_ops);
+struct msm_smem *msm_comm_smem_user_to_kernel(struct msm_vidc_inst *inst,
+ int fd, u32 offset, enum hal_buffer buffer_type);
+int msm_comm_smem_get_domain_partition(struct msm_vidc_inst *inst,
+ u32 flags, enum hal_buffer buffer_type,
+ int *domain_num, int *partition_num);
+enum hal_video_codec get_hal_codec_type(int fourcc);
#endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index 2b1471c..e4f920f 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -207,6 +207,8 @@
struct completion completions[SYS_MSG_END - SYS_MSG_START + 1];
enum msm_vidc_hfi_type hfi_type;
struct msm_vidc_platform_resources resources;
+ u32 enc_codec_supported;
+ u32 dec_codec_supported;
};
struct msm_vidc_inst {
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 8cd3889..9d23d12 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -25,6 +25,7 @@
#include <mach/subsystem_restart.h>
#include <mach/msm_smem.h>
#include <asm/memory.h>
+#include <linux/iopoll.h>
#include "hfi_packetization.h"
#include "venus_hfi.h"
#include "vidc_hfi_io.h"
@@ -65,6 +66,9 @@
#define TZBSP_VIDEO_SET_STATE 0xa
+/* Poll interval in uS */
+#define POLL_INTERVAL_US 50
+
enum tzbsp_video_state {
TZBSP_VIDEO_STATE_SUSPEND = 0,
TZBSP_VIDEO_STATE_RESUME
@@ -75,6 +79,11 @@
u32 spare; /*reserved for future, should be zero*/
};
+
+static inline int venus_hfi_clk_gating_off(struct venus_hfi_device *device);
+
+static int venus_hfi_power_enable(void *dev);
+
static void venus_hfi_dump_packet(u8 *packet)
{
u32 c = 0, packet_size = *(u32 *)packet;
@@ -402,21 +411,24 @@
return rc;
}
-static int venus_hfi_alloc(void *mem, void *clnt, u32 size, u32 align,
- u32 flags, u32 usage)
+static int venus_hfi_alloc(struct venus_hfi_device *dev, void *mem,
+ u32 size, u32 align, u32 flags, u32 usage)
{
- struct vidc_mem_addr *vmem;
- struct msm_smem *alloc;
+ struct vidc_mem_addr *vmem = NULL;
+ struct msm_smem *alloc = NULL;
int rc = 0;
- if (!mem || !clnt || !size) {
+ if (!dev || !dev->hal_client || !mem || !size) {
dprintk(VIDC_ERR, "Invalid Params");
return -EINVAL;
}
+
vmem = (struct vidc_mem_addr *)mem;
dprintk(VIDC_INFO, "start to alloc: size:%d, Flags: %d", size, flags);
- alloc = msm_smem_alloc(clnt, size, align, flags, usage, 1);
+ venus_hfi_power_enable(dev);
+
+ alloc = msm_smem_alloc(dev->hal_client, size, align, flags, usage, 1);
dprintk(VIDC_DBG, "Alloc done");
if (!alloc) {
dprintk(VIDC_ERR, "Alloc failed\n");
@@ -425,7 +437,7 @@
}
dprintk(VIDC_DBG, "venus_hfi_alloc:ptr=%p,size=%d",
alloc->kvaddr, size);
- rc = msm_smem_cache_operations(clnt, alloc,
+ rc = msm_smem_cache_operations(dev->hal_client, alloc,
SMEM_CACHE_CLEAN);
if (rc) {
dprintk(VIDC_WARN, "Failed to clean cache\n");
@@ -440,9 +452,14 @@
return rc;
}
-static void venus_hfi_free(struct smem_client *clnt, struct msm_smem *mem)
+static void venus_hfi_free(struct venus_hfi_device *dev, struct msm_smem *mem)
{
- msm_smem_free(clnt, mem);
+ if (!dev || !mem) {
+ dprintk(VIDC_ERR, "invalid param %p %p\n", dev, mem);
+ return;
+ }
+ venus_hfi_power_enable(dev);
+ msm_smem_free(dev->hal_client, mem);
}
static void venus_hfi_write_register(struct venus_hfi_device *device, u32 reg,
@@ -865,6 +882,34 @@
static DECLARE_COMPLETION(pc_prep_done);
+static int venus_hfi_halt_axi(struct venus_hfi_device *device)
+{
+ u32 reg;
+ int rc = 0;
+ if (!device) {
+ dprintk(VIDC_ERR, "Invalid input: %p\n", device);
+ return -EINVAL;
+ }
+ if (venus_hfi_clk_gating_off(device)) {
+ dprintk(VIDC_ERR, "Failed to turn off clk gating\n");
+ return -EIO;
+ }
+ /* Halt AXI and AXI OCMEM VBIF Access */
+ reg = venus_hfi_read_register(device, VENUS_VBIF_AXI_HALT_CTRL0);
+ reg |= VENUS_VBIF_AXI_HALT_CTRL0_HALT_REQ;
+ venus_hfi_write_register(device, VENUS_VBIF_AXI_HALT_CTRL0, reg, 0);
+
+ /* Request for AXI bus port halt */
+ rc = readl_poll_timeout((u32)device->hal_data->register_base_addr
+ + VENUS_VBIF_AXI_HALT_CTRL1,
+ reg, reg & VENUS_VBIF_AXI_HALT_CTRL1_HALT_ACK,
+ POLL_INTERVAL_US,
+ VENUS_VBIF_AXI_HALT_ACK_TIMEOUT_US);
+ if (rc)
+ dprintk(VIDC_WARN, "AXI bus port halt timeout\n");
+ return rc;
+}
+
static inline int venus_hfi_power_off(struct venus_hfi_device *device)
{
int rc = 0;
@@ -972,6 +1017,22 @@
return rc;
}
+static int venus_hfi_power_enable(void *dev)
+{
+ int rc = 0;
+ struct venus_hfi_device *device = dev;
+ if (!device) {
+ dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+ return -EINVAL;
+ }
+ mutex_lock(&device->clk_pwr_lock);
+ if (!device->power_enabled)
+ rc = venus_hfi_power_on(device);
+ mutex_unlock(&device->clk_pwr_lock);
+
+ return rc;
+}
+
static void venus_hfi_pm_hndlr(struct work_struct *work);
static DECLARE_DELAYED_WORK(venus_hfi_pm_work, venus_hfi_pm_hndlr);
@@ -1217,10 +1278,10 @@
(unsigned long)(mem_map[i].virtual_addr),
domain, partition, SZ_4K);
}
- venus_hfi_free(device->hal_client, device->qdss.mem_data);
+ venus_hfi_free(device, device->qdss.mem_data);
}
- venus_hfi_free(device->hal_client, device->iface_q_table.mem_data);
- venus_hfi_free(device->hal_client, device->sfr.mem_data);
+ venus_hfi_free(device, device->iface_q_table.mem_data);
+ venus_hfi_free(device, device->sfr.mem_data);
for (i = 0; i < VIDC_IFACEQ_NUMQ; i++) {
device->iface_queues[i].q_hdr = NULL;
@@ -1296,8 +1357,8 @@
int num_entries = sizeof(venus_qdss_entries)/(2 * sizeof(u32));
int domain, partition;
mem_addr = &dev->mem_addr;
- rc = venus_hfi_alloc((void *) mem_addr,
- dev->hal_client, QUEUE_SIZE, 1, 0,
+ rc = venus_hfi_alloc(dev, (void *) mem_addr,
+ QUEUE_SIZE, 1, 0,
HAL_BUFFER_INTERNAL_CMD_QUEUE);
if (rc) {
dprintk(VIDC_ERR, "iface_q_table_alloc_fail");
@@ -1323,8 +1384,8 @@
venus_hfi_set_queue_hdr_defaults(iface_q->q_hdr);
}
- rc = venus_hfi_alloc((void *) mem_addr,
- dev->hal_client, QDSS_SIZE, 1, 0,
+ rc = venus_hfi_alloc(dev, (void *) mem_addr,
+ QDSS_SIZE, 1, 0,
HAL_BUFFER_INTERNAL_CMD_QUEUE);
if (rc) {
dprintk(VIDC_WARN,
@@ -1336,8 +1397,8 @@
dev->qdss.mem_size = QDSS_SIZE;
dev->qdss.mem_data = mem_addr->mem_data;
}
- rc = venus_hfi_alloc((void *) mem_addr,
- dev->hal_client, SFR_SIZE, 1, 0,
+ rc = venus_hfi_alloc(dev, (void *) mem_addr,
+ SFR_SIZE, 1, 0,
HAL_BUFFER_INTERNAL_CMD_QUEUE);
if (rc) {
dprintk(VIDC_WARN, "sfr_alloc_fail: SFR not will work");
@@ -1402,7 +1463,7 @@
if (rc) {
dprintk(VIDC_ERR,
"IOMMU mapping failed, Freeing qdss memdata");
- venus_hfi_free(dev->hal_client, dev->qdss.mem_data);
+ venus_hfi_free(dev, dev->qdss.mem_data);
dev->qdss.mem_data = NULL;
}
if (!IS_ERR_OR_NULL(dev->qdss.align_device_addr))
@@ -3280,15 +3341,21 @@
if (device->resources.fw.cookie) {
flush_workqueue(device->vidc_workq);
flush_workqueue(device->venus_pm_workq);
+ subsystem_put(device->resources.fw.cookie);
+ venus_hfi_interface_queues_release(dev);
+ /* IOMMU operations need to be done before AXI halt.*/
+ venus_hfi_iommu_detach(device);
+ /* Halt the AXI to make sure there are no pending transactions.
+ * Clocks should be unprepared after making sure axi is halted.
+ */
+ if(venus_hfi_halt_axi(device))
+ dprintk(VIDC_WARN, "Failed to halt AXI\n");
venus_hfi_disable_clks(device);
mutex_lock(&device->clk_pwr_lock);
- subsystem_put(device->resources.fw.cookie);
regulator_disable(device->gdsc);
device->power_enabled = 0;
--device->pwr_cnt;
mutex_unlock(&device->clk_pwr_lock);
- venus_hfi_interface_queues_release(dev);
- venus_hfi_iommu_detach(device);
device->resources.fw.cookie = NULL;
}
}
@@ -3581,6 +3648,7 @@
hdev->get_stride_scanline = venus_hfi_get_stride_scanline;
hdev->capability_check = venus_hfi_capability_check;
hdev->get_core_capabilities = venus_hfi_get_core_capabilities;
+ hdev->power_enable = venus_hfi_power_enable;
}
int venus_hfi_initialize(struct hfi_device *hdev, u32 device_id,
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index ee83eee..846171e 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -1130,6 +1130,7 @@
u32 *max_width, u32 *max_height);
int (*session_clean)(void *sess);
int (*get_core_capabilities)(void);
+ int (*power_enable)(void *dev);
};
typedef void (*hfi_cmd_response_callback) (enum command_response cmd,
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_io.h b/drivers/media/platform/msm/vidc/vidc_hfi_io.h
index 6377fbf..90163b9 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_io.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_io.h
@@ -131,6 +131,12 @@
#define VIDC_VBIF_AT_OLD_HIGH (VIDC_VBIF_BASE_OFFS + 0xC08)
#define VIDC_VBIF_AT_NEW_BASE (VIDC_VBIF_BASE_OFFS + 0xC10)
#define VIDC_VBIF_AT_NEW_HIGH (VIDC_VBIF_BASE_OFFS + 0xC18)
+#define VENUS_VBIF_AXI_HALT_CTRL0 (VIDC_VBIF_BASE_OFFS + 0x208)
+#define VENUS_VBIF_AXI_HALT_CTRL1 (VIDC_VBIF_BASE_OFFS + 0x20C)
+
+#define VENUS_VBIF_AXI_HALT_CTRL0_HALT_REQ BIT(0)
+#define VENUS_VBIF_AXI_HALT_CTRL1_HALT_ACK BIT(0)
+#define VENUS_VBIF_AXI_HALT_ACK_TIMEOUT_US 500000
#define VIDC_VENUS0_WRAPPER_VBIF_REQ_PRIORITY \
(VIDC_WRAPPER_BASE_OFFS + 0x20)
diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile
index 8f5fa26..0fc6245 100644
--- a/drivers/video/msm/mdss/Makefile
+++ b/drivers/video/msm/mdss/Makefile
@@ -19,7 +19,7 @@
dsi-v2-objs = dsi_v2.o dsi_host_v2.o dsi_io_v2.o
obj-$(CONFIG_FB_MSM_MDSS) += dsi-v2.o
-mdss-dsi-objs := mdss_dsi.o mdss_dsi_host.o
+mdss-dsi-objs := mdss_dsi.o mdss_dsi_host.o mdss_dsi_cmd.o
mdss-dsi-objs += mdss_dsi_panel.o
mdss-dsi-objs += msm_mdss_io_8974.o
obj-$(CONFIG_FB_MSM_MDSS) += mdss-dsi.o
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
index 452e63a..aa41cb2 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.c
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -31,21 +31,24 @@
#define DSI_POLL_TIMEOUT_US 16000
#define DSI_ESC_CLK_RATE 19200000
#define DSI_DMA_CMD_TIMEOUT_MS 200
+#define VSYNC_PERIOD 17
+#define DSI_MAX_PKT_SIZE 10
+#define DSI_SHORT_PKT_DATA_SIZE 2
+#define DSI_MAX_BYTES_TO_READ 16
struct dsi_host_v2_private {
- struct completion dma_comp;
- int irq_enabled;
- spinlock_t irq_lock;
-
int irq_no;
unsigned char *dsi_base;
size_t dsi_reg_size;
struct device dis_dev;
+ int clk_count;
+ int dsi_on;
void (*debug_enable_clk)(int on);
};
static struct dsi_host_v2_private *dsi_host_private;
+static int msm_dsi_clk_ctrl(struct mdss_panel_data *pdata, int enable);
int msm_dsi_init(void)
{
@@ -58,8 +61,6 @@
}
}
- init_completion(&dsi_host_private->dma_comp);
- spin_lock_init(&dsi_host_private->irq_lock);
return 0;
}
@@ -137,61 +138,98 @@
msm_dsi_dln0_phy_err(ctrl_base);
}
-void msm_dsi_enable_irq(void)
+static void msm_dsi_set_irq_mask(struct mdss_dsi_ctrl_pdata *ctrl, u32 mask)
+{
+ u32 intr_ctrl;
+ intr_ctrl = MIPI_INP(dsi_host_private->dsi_base + DSI_INT_CTRL);
+ intr_ctrl |= mask;
+ MIPI_OUTP(dsi_host_private->dsi_base + DSI_INT_CTRL, intr_ctrl);
+}
+
+static void msm_dsi_clear_irq_mask(struct mdss_dsi_ctrl_pdata *ctrl, u32 mask)
+{
+ u32 intr_ctrl;
+ intr_ctrl = MIPI_INP(dsi_host_private->dsi_base + DSI_INT_CTRL);
+ intr_ctrl &= ~mask;
+ MIPI_OUTP(dsi_host_private->dsi_base + DSI_INT_CTRL, intr_ctrl);
+}
+
+static void msm_dsi_set_irq(struct mdss_dsi_ctrl_pdata *ctrl, u32 mask)
{
unsigned long flags;
- spin_lock_irqsave(&dsi_host_private->irq_lock, flags);
- dsi_host_private->irq_enabled++;
- if (dsi_host_private->irq_enabled == 1)
+ spin_lock_irqsave(&ctrl->irq_lock, flags);
+ if (ctrl->dsi_irq_mask & mask) {
+ spin_unlock_irqrestore(&ctrl->irq_lock, flags);
+ return;
+ }
+ if (ctrl->dsi_irq_mask == 0) {
enable_irq(dsi_host_private->irq_no);
+ pr_debug("%s: IRQ Enable, mask=%x term=%x\n", __func__,
+ (int)ctrl->dsi_irq_mask, (int)mask);
+ }
- spin_unlock_irqrestore(&dsi_host_private->irq_lock, flags);
+ msm_dsi_set_irq_mask(ctrl, mask);
+ ctrl->dsi_irq_mask |= mask;
+ spin_unlock_irqrestore(&ctrl->irq_lock, flags);
}
-void msm_dsi_disable_irq(void)
+static void msm_dsi_clear_irq(struct mdss_dsi_ctrl_pdata *ctrl, u32 mask)
{
unsigned long flags;
- spin_lock_irqsave(&dsi_host_private->irq_lock, flags);
- dsi_host_private->irq_enabled--;
- if (dsi_host_private->irq_enabled == 0)
+ spin_lock_irqsave(&ctrl->irq_lock, flags);
+ if (!(ctrl->dsi_irq_mask & mask)) {
+ spin_unlock_irqrestore(&ctrl->irq_lock, flags);
+ return;
+ }
+ ctrl->dsi_irq_mask &= ~mask;
+ if (ctrl->dsi_irq_mask == 0) {
disable_irq(dsi_host_private->irq_no);
-
- spin_unlock_irqrestore(&dsi_host_private->irq_lock, flags);
+ pr_debug("%s: IRQ Disable, mask=%x term=%x\n", __func__,
+ (int)ctrl->dsi_irq_mask, (int)mask);
+ }
+ msm_dsi_clear_irq_mask(ctrl, mask);
+ spin_unlock_irqrestore(&ctrl->irq_lock, flags);
}
-void msm_dsi_disable_irq_nosync(void)
-{
- spin_lock(&dsi_host_private->irq_lock);
- dsi_host_private->irq_enabled--;
- if (dsi_host_private->irq_enabled == 0)
- disable_irq_nosync(dsi_host_private->irq_no);
- spin_unlock(&dsi_host_private->irq_lock);
-}
-
-irqreturn_t msm_dsi_isr(int irq, void *ptr)
+irqreturn_t msm_dsi_isr_handler(int irq, void *ptr)
{
u32 isr;
+ struct mdss_dsi_ctrl_pdata *ctrl =
+ (struct mdss_dsi_ctrl_pdata *)ptr;
+
isr = MIPI_INP(dsi_host_private->dsi_base + DSI_INT_CTRL);
MIPI_OUTP(dsi_host_private->dsi_base + DSI_INT_CTRL, isr);
- if (isr & DSI_INTR_ERROR)
+ pr_debug("%s: isr=%x", __func__, isr);
+
+ if (isr & DSI_INTR_ERROR) {
+ pr_err("%s: isr=%x %x", __func__, isr, (int)DSI_INTR_ERROR);
msm_dsi_error(dsi_host_private->dsi_base);
+ }
+
+ spin_lock(&ctrl->mdp_lock);
+
+ if (isr & DSI_INTR_VIDEO_DONE)
+ complete(&ctrl->video_comp);
if (isr & DSI_INTR_CMD_DMA_DONE)
- complete(&dsi_host_private->dma_comp);
+ complete(&ctrl->dma_comp);
+
+ spin_unlock(&ctrl->mdp_lock);
return IRQ_HANDLED;
}
-int msm_dsi_irq_init(struct device *dev, int irq_no)
+int msm_dsi_irq_init(struct device *dev, int irq_no,
+ struct mdss_dsi_ctrl_pdata *ctrl)
{
int ret;
- ret = devm_request_irq(dev, irq_no, msm_dsi_isr,
- IRQF_DISABLED, "DSI", NULL);
+ ret = devm_request_irq(dev, irq_no, msm_dsi_isr_handler,
+ IRQF_DISABLED, "DSI", ctrl);
if (ret) {
pr_err("msm_dsi_irq_init request_irq() failed!\n");
return ret;
@@ -201,9 +239,76 @@
return 0;
}
+static void msm_dsi_get_cmd_engine(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ unsigned char *ctrl_base = dsi_host_private->dsi_base;
+ u32 dsi_ctrl;
+
+ if (ctrl->panel_mode == DSI_VIDEO_MODE) {
+ dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
+ MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl | 0x04);
+ }
+}
+
+static void msm_dsi_release_cmd_engine(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ unsigned char *ctrl_base = dsi_host_private->dsi_base;
+ u32 dsi_ctrl;
+ if (ctrl->panel_mode == DSI_VIDEO_MODE) {
+ dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
+ dsi_ctrl &= ~0x04;
+ MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
+ }
+}
+
+static int msm_dsi_wait4video_done(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ int rc;
+ unsigned long flag;
+
+ spin_lock_irqsave(&ctrl->mdp_lock, flag);
+ INIT_COMPLETION(ctrl->video_comp);
+ msm_dsi_set_irq(ctrl, DSI_INTR_VIDEO_DONE_MASK);
+ spin_unlock_irqrestore(&ctrl->mdp_lock, flag);
+
+ rc = wait_for_completion_timeout(&ctrl->video_comp,
+ msecs_to_jiffies(VSYNC_PERIOD * 4));
+
+ if (rc == 0) {
+ pr_err("DSI wait 4 video done time out\n");
+ rc = -ETIME;
+ } else if (!IS_ERR_VALUE(rc)) {
+ rc = 0;
+ }
+
+ msm_dsi_clear_irq(ctrl, DSI_INTR_VIDEO_DONE_MASK);
+
+ return rc;
+}
+
+static int msm_dsi_wait4video_eng_busy(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ int rc = 0;
+ u32 dsi_status;
+ unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+ if (ctrl->panel_mode == DSI_CMD_MODE)
+ return rc;
+
+ dsi_status = MIPI_INP(ctrl_base + DSI_STATUS);
+ if (dsi_status & 0x08) {
+ pr_debug("dsi command in video mode wait for active region\n");
+ rc = msm_dsi_wait4video_done(ctrl);
+ /* delay 4-5 ms to skip BLLP */
+ if (!rc)
+ usleep_range(4000, 5000);
+ }
+ return rc;
+}
+
void msm_dsi_host_init(struct mipi_panel_info *pinfo)
{
- u32 dsi_ctrl, intr_ctrl, data;
+ u32 dsi_ctrl, data;
unsigned char *ctrl_base = dsi_host_private->dsi_base;
pr_debug("msm_dsi_host_init\n");
@@ -262,8 +367,6 @@
pr_err("%s: Unknown DSI mode=%d\n", __func__, pinfo->mode);
dsi_ctrl = BIT(8) | BIT(2); /* clock enable & cmd mode */
- intr_ctrl = 0;
- intr_ctrl = (DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_CMD_MDP_DONE_MASK);
if (pinfo->crc_check)
dsi_ctrl |= BIT(24);
@@ -312,9 +415,6 @@
/* DSI_ERR_INT_MASK0 */
MIPI_OUTP(ctrl_base + DSI_ERR_INT_MASK0, 0x13ff3fe0);
- intr_ctrl |= DSI_INTR_ERROR_MASK;
- MIPI_OUTP(ctrl_base + DSI_INT_CTRL, intr_ctrl);
-
/* turn esc, byte, dsi, pclk, sclk, hclk on */
MIPI_OUTP(ctrl_base + DSI_CLK_CTRL, 0x23f);
@@ -404,7 +504,7 @@
void msm_dsi_op_mode_config(int mode, struct mdss_panel_data *pdata)
{
- u32 dsi_ctrl, intr_ctrl;
+ u32 dsi_ctrl;
unsigned char *ctrl_base = dsi_host_private->dsi_base;
pr_debug("msm_dsi_op_mode_config\n");
@@ -415,46 +515,24 @@
dsi_ctrl &= ~0x06;
- if (mode == DSI_VIDEO_MODE) {
+ if (mode == DSI_VIDEO_MODE)
dsi_ctrl |= 0x02;
- intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK;
- } else { /* command mode */
+ else
dsi_ctrl |= 0x04;
- intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_ERROR_MASK |
- DSI_INTR_CMD_MDP_DONE_MASK;
- }
+ pr_debug("%s: dsi_ctrl=%x\n", __func__, dsi_ctrl);
- pr_debug("%s: dsi_ctrl=%x intr=%x\n", __func__, dsi_ctrl, intr_ctrl);
-
- MIPI_OUTP(ctrl_base + DSI_INT_CTRL, intr_ctrl);
MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
wmb();
}
-int msm_dsi_cmd_reg_tx(u32 data)
-{
- unsigned char *ctrl_base = dsi_host_private->dsi_base;
-
- MIPI_OUTP(ctrl_base + DSI_TRIG_CTRL, 0x04);/* sw trigger */
- MIPI_OUTP(ctrl_base + DSI_CTRL, 0x135);
- wmb();
-
- MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_DMA_CTRL, data);
- wmb();
- MIPI_OUTP(ctrl_base + DSI_CMD_MODE_DMA_SW_TRIGGER, 0x01);
- wmb();
-
- udelay(300); /*per spec*/
-
- return 0;
-}
-
-int msm_dsi_cmd_dma_tx(struct dsi_buf *tp)
+int msm_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl,
+ struct dsi_buf *tp)
{
int len, rc;
unsigned long size, addr;
unsigned char *ctrl_base = dsi_host_private->dsi_base;
+ unsigned long flag;
len = ALIGN(tp->len, 4);
size = ALIGN(tp->len, SZ_4K);
@@ -468,7 +546,12 @@
addr = tp->dmap;
- INIT_COMPLETION(dsi_host_private->dma_comp);
+ msm_dsi_get_cmd_engine(ctrl);
+
+ spin_lock_irqsave(&ctrl->mdp_lock, flag);
+ INIT_COMPLETION(ctrl->dma_comp);
+ msm_dsi_set_irq(ctrl, DSI_INTR_CMD_DMA_DONE_MASK);
+ spin_unlock_irqrestore(&ctrl->mdp_lock, flag);
MIPI_OUTP(ctrl_base + DSI_DMA_CMD_OFFSET, addr);
MIPI_OUTP(ctrl_base + DSI_DMA_CMD_LENGTH, len);
@@ -477,7 +560,7 @@
MIPI_OUTP(ctrl_base + DSI_CMD_MODE_DMA_SW_TRIGGER, 0x01);
wmb();
- rc = wait_for_completion_timeout(&dsi_host_private->dma_comp,
+ rc = wait_for_completion_timeout(&ctrl->dma_comp,
msecs_to_jiffies(DSI_DMA_CMD_TIMEOUT_MS));
if (rc == 0) {
pr_err("DSI command transaction time out\n");
@@ -489,10 +572,16 @@
dma_unmap_single(&dsi_host_private->dis_dev, tp->dmap, size,
DMA_TO_DEVICE);
tp->dmap = 0;
+
+ msm_dsi_clear_irq(ctrl, DSI_INTR_CMD_DMA_DONE_MASK);
+
+ msm_dsi_release_cmd_engine(ctrl);
+
return rc;
}
-int msm_dsi_cmd_dma_rx(struct dsi_buf *rp, int rlen)
+int msm_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl,
+ struct dsi_buf *rp, int rlen)
{
u32 *lp, data;
int i, off, cnt;
@@ -518,202 +607,315 @@
rp->len += sizeof(*lp);
}
- return 0;
+ return rlen;
}
-int msm_dsi_cmds_tx(struct mdss_panel_data *pdata,
- struct dsi_buf *tp, struct dsi_cmd_desc *cmds, int cnt)
+static int msm_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl,
+ struct dsi_cmd_desc *cmds, int cnt)
{
+ struct dsi_buf *tp;
struct dsi_cmd_desc *cm;
- u32 dsi_ctrl, ctrl;
- int i, video_mode, rc = 0;
- unsigned char *ctrl_base = dsi_host_private->dsi_base;
+ struct dsi_ctrl_hdr *dchdr;
+ int len;
+ int rc = 0;
- /* turn on cmd mode
- * for video mode, do not send cmds more than
- * one pixel line, since it only transmit it
- * during BLLP.
- */
- dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
- video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
- if (video_mode) {
- ctrl = dsi_ctrl | 0x04; /* CMD_MODE_EN */
- MIPI_OUTP(ctrl_base + DSI_CTRL, ctrl);
- }
- msm_dsi_enable_irq();
-
+ tp = &ctrl->tx_buf;
+ mdss_dsi_buf_init(tp);
cm = cmds;
- for (i = 0; i < cnt; i++) {
- dsi_buf_init(tp);
- dsi_cmd_dma_add(tp, cm);
- rc = msm_dsi_cmd_dma_tx(tp);
- if (IS_ERR_VALUE(rc)) {
- pr_err("%s: failed to call cmd_dma_tx\n", __func__);
- break;
+ len = 0;
+ while (cnt--) {
+ dchdr = &cm->dchdr;
+ mdss_dsi_buf_reserve(tp, len);
+ len = mdss_dsi_cmd_dma_add(tp, cm);
+ if (!len) {
+ pr_err("%s: failed to add cmd = 0x%x\n",
+ __func__, cm->payload[0]);
+ rc = -EINVAL;
+ goto dsi_cmds_tx_err;
}
- if (cm->dchdr.wait)
- msleep(cm->dchdr.wait);
+
+ if (dchdr->last) {
+ tp->data = tp->start; /* begin of buf */
+ rc = msm_dsi_wait4video_eng_busy(ctrl);
+ if (rc) {
+ pr_err("%s: wait4video_eng failed\n", __func__);
+ goto dsi_cmds_tx_err;
+
+ }
+
+ rc = msm_dsi_cmd_dma_tx(ctrl, tp);
+ if (IS_ERR_VALUE(len)) {
+ pr_err("%s: failed to call cmd_dma_tx for cmd = 0x%x\n",
+ __func__, cmds->payload[0]);
+ goto dsi_cmds_tx_err;
+ }
+
+ if (dchdr->wait)
+ usleep(dchdr->wait * 1000);
+
+ mdss_dsi_buf_init(tp);
+ len = 0;
+ }
cm++;
}
- msm_dsi_disable_irq();
-
- if (video_mode)
- MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
+dsi_cmds_tx_err:
return rc;
}
-/* MDSS_DSI_MRPS, Maximum Return Packet Size */
-static char max_pktsize[2] = {0x00, 0x00}; /* LSB tx first, 10 bytes */
-
-static struct dsi_cmd_desc pkt_size_cmd[] = {
- {{DTYPE_MAX_PKTSIZE, 1, 0, 0, 0,
- sizeof(max_pktsize)}, max_pktsize}
-};
-
-/*
- * DSI panel reply with MAX_RETURN_PACKET_SIZE bytes of data
- * plus DCS header, ECC and CRC for DCS long read response
- * mdss_dsi_controller only have 4x32 bits register ( 16 bytes) to
- * hold data per transaction.
- * MDSS_DSI_LEN equal to 8
- * len should be either 4 or 8
- * any return data more than MDSS_DSI_LEN need to be break down
- * to multiple transactions.
- *
- * ov_mutex need to be acquired before call this function.
- */
-int msm_dsi_cmds_rx(struct mdss_panel_data *pdata,
- struct dsi_buf *tp, struct dsi_buf *rp,
- struct dsi_cmd_desc *cmds, int rlen)
+static int msm_dsi_parse_rx_response(struct dsi_buf *rp)
{
- int cnt, len, diff, pkt_size, rc = 0;
- char cmd;
- unsigned char *ctrl_base = dsi_host_private->dsi_base;
- u32 dsi_ctrl, data;
- int video_mode;
-
- /* turn on cmd mode for video mode */
- dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
- video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
- if (video_mode) {
- data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
- MIPI_OUTP(ctrl_base + DSI_CTRL, data);
- }
-
- if (pdata->panel_info.mipi.no_max_pkt_size)
- rlen = ALIGN(rlen, 4); /* Only support rlen = 4*n */
-
- len = rlen;
- diff = 0;
-
- if (len <= 2) {
- cnt = 4; /* short read */
- } else {
- if (len > MDSS_DSI_LEN)
- len = MDSS_DSI_LEN; /* 8 bytes at most */
-
- len = ALIGN(len, 4); /* len 4 bytes align */
- diff = len - rlen;
- /*
- * add extra 2 bytes to len to have overall
- * packet size is multipe by 4. This also make
- * sure 4 bytes dcs headerlocates within a
- * 32 bits register after shift in.
- * after all, len should be either 6 or 10.
- */
- len += 2;
- cnt = len + 6; /* 4 bytes header + 2 bytes crc */
- }
-
- msm_dsi_enable_irq();
-
- if (!pdata->panel_info.mipi.no_max_pkt_size) {
- /* packet size need to be set at every read */
- pkt_size = len;
- max_pktsize[0] = pkt_size;
- dsi_buf_init(tp);
- dsi_cmd_dma_add(tp, pkt_size_cmd);
- rc = msm_dsi_cmd_dma_tx(tp);
- if (IS_ERR_VALUE(rc)) {
- msm_dsi_disable_irq();
- pr_err("%s: dma_tx failed\n", __func__);
- rp->len = 0;
- goto end;
- }
- pr_debug("%s: Max packet size sent\n", __func__);
- }
-
- dsi_buf_init(tp);
- dsi_cmd_dma_add(tp, cmds);
-
- /* transmit read comamnd to client */
- msm_dsi_cmd_dma_tx(tp);
- if (IS_ERR_VALUE(rc)) {
- msm_dsi_disable_irq();
- pr_err("%s: dma_tx failed\n", __func__);
- rp->len = 0;
- goto end;
- }
- /*
- * once cmd_dma_done interrupt received,
- * return data from client is ready and stored
- * at RDBK_DATA register already
- */
- dsi_buf_init(rp);
- if (pdata->panel_info.mipi.no_max_pkt_size) {
- /*
- * expect rlen = n * 4
- * short alignement for start addr
- */
- rp->data += 2;
- }
-
- msm_dsi_cmd_dma_rx(rp, cnt);
-
- msm_dsi_disable_irq();
-
- if (pdata->panel_info.mipi.no_max_pkt_size) {
- /*
- * remove extra 2 bytes from previous
- * rx transaction at shift register
- * which was inserted during copy
- * shift registers to rx buffer
- * rx payload start from long alignment addr
- */
- rp->data += 2;
- }
+ int rc = 0;
+ unsigned char cmd;
cmd = rp->data[0];
switch (cmd) {
case DTYPE_ACK_ERR_RESP:
pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__);
+ rc = -EINVAL;
break;
case DTYPE_GEN_READ1_RESP:
case DTYPE_DCS_READ1_RESP:
- dsi_short_read1_resp(rp);
+ mdss_dsi_short_read1_resp(rp);
break;
case DTYPE_GEN_READ2_RESP:
case DTYPE_DCS_READ2_RESP:
- dsi_short_read2_resp(rp);
+ mdss_dsi_short_read2_resp(rp);
break;
case DTYPE_GEN_LREAD_RESP:
case DTYPE_DCS_LREAD_RESP:
- dsi_long_read_resp(rp);
- rp->len -= 2; /* extra 2 bytes added */
- rp->len -= diff; /* align bytes */
+ mdss_dsi_long_read_resp(rp);
break;
default:
- pr_debug("%s: Unknown cmd received\n", __func__);
+ rc = -EINVAL;
+ pr_warn("%s: Unknown cmd received\n", __func__);
break;
}
- if (video_mode)
- MIPI_OUTP(ctrl_base + DSI_CTRL,
- dsi_ctrl); /* restore */
-end:
- return rp->len;
+ return rc;
+}
+
+/* MIPI_DSI_MRPS, Maximum Return Packet Size */
+static char max_pktsize[2] = {0x00, 0x00}; /* LSB tx first, 10 bytes */
+
+static struct dsi_cmd_desc pkt_size_cmd = {
+ {DTYPE_MAX_PKTSIZE, 1, 0, 0, 0, sizeof(max_pktsize)},
+ max_pktsize,
+};
+
+static int msm_dsi_set_max_packet_size(struct mdss_dsi_ctrl_pdata *ctrl,
+ int size)
+{
+ struct dsi_buf *tp;
+ int rc;
+
+ tp = &ctrl->tx_buf;
+ mdss_dsi_buf_init(tp);
+ max_pktsize[0] = size;
+
+ rc = mdss_dsi_cmd_dma_add(tp, &pkt_size_cmd);
+ if (!rc) {
+ pr_err("%s: failed to add max_pkt_size\n", __func__);
+ return -EINVAL;
+ }
+
+ rc = msm_dsi_wait4video_eng_busy(ctrl);
+ if (rc) {
+ pr_err("%s: failed to wait4video_eng\n", __func__);
+ return rc;
+ }
+
+ rc = msm_dsi_cmd_dma_tx(ctrl, tp);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("%s: failed to tx max_pkt_size\n", __func__);
+ return rc;
+ }
+ pr_debug("%s: max_pkt_size=%d sent\n", __func__, size);
+ return rc;
+}
+
+/* read data length is less than or equal to 10 bytes*/
+static int msm_dsi_cmds_rx_1(struct mdss_dsi_ctrl_pdata *ctrl,
+ struct dsi_cmd_desc *cmds, int rlen)
+{
+ int rc;
+ struct dsi_buf *tp, *rp;
+
+ tp = &ctrl->tx_buf;
+ rp = &ctrl->rx_buf;
+ mdss_dsi_buf_init(rp);
+ mdss_dsi_buf_init(tp);
+
+ rc = mdss_dsi_cmd_dma_add(tp, cmds);
+ if (!rc) {
+ pr_err("%s: dsi_cmd_dma_add failed\n", __func__);
+ rc = -EINVAL;
+ goto dsi_cmds_rx_1_error;
+ }
+
+ rc = msm_dsi_wait4video_eng_busy(ctrl);
+ if (rc) {
+ pr_err("%s: wait4video_eng failed\n", __func__);
+ goto dsi_cmds_rx_1_error;
+ }
+
+ rc = msm_dsi_cmd_dma_tx(ctrl, tp);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("%s: msm_dsi_cmd_dma_tx failed\n", __func__);
+ goto dsi_cmds_rx_1_error;
+ }
+
+ if (rlen <= DSI_SHORT_PKT_DATA_SIZE) {
+ msm_dsi_cmd_dma_rx(ctrl, rp, rlen);
+ } else {
+ msm_dsi_cmd_dma_rx(ctrl, rp, rlen + DSI_HOST_HDR_SIZE);
+ rp->len = rlen + DSI_HOST_HDR_SIZE;
+ }
+ rc = msm_dsi_parse_rx_response(rp);
+
+dsi_cmds_rx_1_error:
+ if (rc)
+ rp->len = 0;
+
+ return rc;
+}
+
+/* read data length is more than 10 bytes, which requires multiple DSI read*/
+static int msm_dsi_cmds_rx_2(struct mdss_dsi_ctrl_pdata *ctrl,
+ struct dsi_cmd_desc *cmds, int rlen)
+{
+ int rc;
+ struct dsi_buf *tp, *rp;
+ int pkt_size, data_bytes, total;
+
+ tp = &ctrl->tx_buf;
+ rp = &ctrl->rx_buf;
+ mdss_dsi_buf_init(rp);
+ pkt_size = DSI_MAX_PKT_SIZE;
+ data_bytes = MDSS_DSI_LEN;
+ total = 0;
+
+ while (true) {
+ rc = msm_dsi_set_max_packet_size(ctrl, pkt_size);
+ if (rc)
+ break;
+
+ mdss_dsi_buf_init(tp);
+ rc = mdss_dsi_cmd_dma_add(tp, cmds);
+ if (!rc) {
+ pr_err("%s: dsi_cmd_dma_add failed\n", __func__);
+ rc = -EINVAL;
+ break;
+ }
+ rc = msm_dsi_wait4video_eng_busy(ctrl);
+ if (rc) {
+ pr_err("%s: wait4video_eng failed\n", __func__);
+ break;
+ }
+
+ rc = msm_dsi_cmd_dma_tx(ctrl, tp);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("%s: msm_dsi_cmd_dma_tx failed\n", __func__);
+ break;
+ }
+
+ msm_dsi_cmd_dma_rx(ctrl, rp, DSI_MAX_BYTES_TO_READ);
+
+ rp->data += DSI_MAX_BYTES_TO_READ - DSI_HOST_HDR_SIZE;
+ total += data_bytes;
+ if (total >= rlen)
+ break;
+
+ data_bytes = DSI_MAX_BYTES_TO_READ - DSI_HOST_HDR_SIZE;
+ pkt_size += data_bytes;
+ }
+
+ if (!rc) {
+ rp->data = rp->start;
+ rp->len = rlen + DSI_HOST_HDR_SIZE;
+ rc = msm_dsi_parse_rx_response(rp);
+ }
+
+ if (rc)
+ rp->len = 0;
+
+ return rc;
+}
+
+int msm_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl,
+ struct dsi_cmd_desc *cmds, int rlen)
+{
+ int rc;
+ if (rlen <= DSI_MAX_PKT_SIZE)
+ rc = msm_dsi_cmds_rx_1(ctrl, cmds, rlen);
+ else
+ rc = msm_dsi_cmds_rx_2(ctrl, cmds, rlen);
+
+ return rc;
+}
+
+void msm_dsi_cmdlist_tx(struct mdss_dsi_ctrl_pdata *ctrl,
+ struct dcs_cmd_req *req)
+{
+ int ret;
+
+ ret = msm_dsi_cmds_tx(ctrl, req->cmds, req->cmds_cnt);
+
+ if (req->cb)
+ req->cb(ret);
+}
+
+void msm_dsi_cmdlist_rx(struct mdss_dsi_ctrl_pdata *ctrl,
+ struct dcs_cmd_req *req)
+{
+ struct dsi_buf *rp;
+ int len = 0;
+
+ if (req->rbuf) {
+ rp = &ctrl->rx_buf;
+ len = msm_dsi_cmds_rx(ctrl, req->cmds, req->rlen);
+ memcpy(req->rbuf, rp->data, rp->len);
+ } else {
+ pr_err("%s: No rx buffer provided\n", __func__);
+ }
+
+ if (req->cb)
+ req->cb(len);
+}
+void msm_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
+{
+ struct dcs_cmd_req *req;
+ int dsi_on;
+
+ mutex_lock(&ctrl->mutex);
+ dsi_on = dsi_host_private->dsi_on;
+ mutex_unlock(&ctrl->mutex);
+ if (!dsi_on) {
+ pr_err("try to send DSI commands while dsi is off\n");
+ return;
+ }
+
+ mutex_lock(&ctrl->cmd_mutex);
+ req = mdss_dsi_cmdlist_get(ctrl);
+
+ if (!req) {
+ mutex_unlock(&ctrl->cmd_mutex);
+ return;
+ }
+
+ msm_dsi_clk_ctrl(&ctrl->panel_data, 1);
+ dsi_set_tx_power_mode(0);
+
+ if (req->flags & CMD_REQ_RX)
+ msm_dsi_cmdlist_rx(ctrl, req);
+ else
+ msm_dsi_cmdlist_tx(ctrl, req);
+
+ dsi_set_tx_power_mode(1);
+ msm_dsi_clk_ctrl(&ctrl->panel_data, 0);
+
+ mutex_unlock(&ctrl->cmd_mutex);
}
static int msm_dsi_cal_clk_rate(struct mdss_panel_data *pdata,
@@ -785,11 +987,14 @@
ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
panel_data);
+ mutex_lock(&ctrl_pdata->mutex);
+
ret = msm_dss_enable_vreg(
ctrl_pdata->power_data.vreg_config,
ctrl_pdata->power_data.num_vreg, 1);
if (ret) {
pr_err("%s: DSI power on failed\n", __func__);
+ mutex_unlock(&ctrl_pdata->mutex);
return ret;
}
@@ -876,6 +1081,11 @@
msm_dsi_op_mode_config(mipi->mode, pdata);
+ msm_dsi_set_irq(ctrl_pdata, DSI_INTR_ERROR_MASK);
+ dsi_host_private->clk_count = 1;
+ dsi_host_private->dsi_on = 1;
+ mutex_unlock(&ctrl_pdata->mutex);
+
return ret;
}
@@ -894,6 +1104,8 @@
panel_data);
pr_debug("msm_dsi_off\n");
+ mutex_lock(&ctrl_pdata->mutex);
+ msm_dsi_clear_irq(ctrl_pdata, ctrl_pdata->dsi_irq_mask);
msm_dsi_controller_cfg(0);
msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, 0, 0, 0);
msm_dsi_clk_disable();
@@ -906,8 +1118,11 @@
ctrl_pdata->power_data.num_vreg, 0);
if (ret) {
pr_err("%s: Panel power off failed\n", __func__);
- return ret;
}
+ dsi_host_private->clk_count = 0;
+ dsi_host_private->dsi_on = 0;
+
+ mutex_unlock(&ctrl_pdata->mutex);
return ret;
}
@@ -931,17 +1146,23 @@
panel_data);
pinfo = &pdata->panel_info;
+ mutex_lock(&ctrl_pdata->mutex);
ret = msm_dss_enable_vreg(
ctrl_pdata->power_data.vreg_config,
ctrl_pdata->power_data.num_vreg, 1);
if (ret) {
pr_err("%s: DSI power on failed\n", __func__);
+ mutex_unlock(&ctrl_pdata->mutex);
return ret;
}
msm_dsi_ahb_ctrl(1);
msm_dsi_prepare_clocks();
msm_dsi_clk_enable();
+ msm_dsi_set_irq(ctrl_pdata, DSI_INTR_ERROR_MASK);
+ dsi_host_private->clk_count = 1;
+ dsi_host_private->dsi_on = 1;
+ mutex_unlock(&ctrl_pdata->mutex);
return 0;
}
@@ -1073,24 +1294,53 @@
static int msm_dsi_clk_ctrl(struct mdss_panel_data *pdata, int enable)
{
u32 bitclk_rate = 0, byteclk_rate = 0, pclk_rate = 0, dsiclk_rate = 0;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
pr_debug("%s:\n", __func__);
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
+
+ mutex_lock(&ctrl_pdata->mutex);
+
if (enable) {
- msm_dsi_ahb_ctrl(1);
- msm_dsi_cal_clk_rate(pdata, &bitclk_rate, &dsiclk_rate,
- &byteclk_rate, &pclk_rate);
- msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, dsiclk_rate,
- byteclk_rate, pclk_rate);
- msm_dsi_clk_enable();
+ dsi_host_private->clk_count++;
+ if (dsi_host_private->clk_count == 1) {
+ msm_dsi_ahb_ctrl(1);
+ msm_dsi_cal_clk_rate(pdata, &bitclk_rate, &dsiclk_rate,
+ &byteclk_rate, &pclk_rate);
+ msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, dsiclk_rate,
+ byteclk_rate, pclk_rate);
+ msm_dsi_clk_enable();
+ }
} else {
- msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, 0, 0, 0);
- msm_dsi_clk_disable();
- msm_dsi_ahb_ctrl(0);
+ dsi_host_private->clk_count--;
+ if (dsi_host_private->clk_count == 0) {
+ msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, 0, 0, 0);
+ msm_dsi_clk_disable();
+ msm_dsi_ahb_ctrl(0);
+ }
}
+ mutex_unlock(&ctrl_pdata->mutex);
return 0;
}
+void msm_dsi_ctrl_init(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ init_completion(&ctrl->dma_comp);
+ init_completion(&ctrl->mdp_comp);
+ init_completion(&ctrl->video_comp);
+ spin_lock_init(&ctrl->irq_lock);
+ spin_lock_init(&ctrl->mdp_lock);
+ mutex_init(&ctrl->mutex);
+ mutex_init(&ctrl->cmd_mutex);
+ complete(&ctrl->mdp_comp);
+ dsi_buf_alloc(&ctrl->tx_buf, SZ_4K);
+ dsi_buf_alloc(&ctrl->rx_buf, SZ_4K);
+ ctrl->cmdlist_commit = msm_dsi_cmdlist_commit;
+ ctrl->panel_mode = ctrl->panel_data.panel_info.mipi.mode;
+}
+
static int __devinit msm_dsi_probe(struct platform_device *pdev)
{
struct dsi_interface intf;
@@ -1151,7 +1401,8 @@
rc = -ENODEV;
goto error_irq_resource;
} else {
- rc = msm_dsi_irq_init(&pdev->dev, mdss_dsi_mres->start);
+ rc = msm_dsi_irq_init(&pdev->dev, mdss_dsi_mres->start,
+ ctrl_pdata);
if (rc) {
dev_err(&pdev->dev, "%s: failed to init irq, rc=%d\n",
__func__, rc);
@@ -1211,14 +1462,14 @@
intf.cont_on = msm_dsi_cont_on;
intf.clk_ctrl = msm_dsi_clk_ctrl;
intf.op_mode_config = msm_dsi_op_mode_config;
- intf.tx = msm_dsi_cmds_tx;
- intf.rx = msm_dsi_cmds_rx;
intf.index = 0;
intf.private = NULL;
dsi_register_interface(&intf);
msm_dsi_debug_init();
+ msm_dsi_ctrl_init(ctrl_pdata);
+
rc = dsi_panel_device_register_v2(pdev, ctrl_pdata);
if (rc) {
pr_err("%s: dsi panel dev reg failed\n", __func__);
@@ -1233,7 +1484,7 @@
error_pan_node:
of_node_put(dsi_pan_node);
error_platform_pop:
- msm_dsi_disable_irq();
+ msm_dsi_clear_irq(ctrl_pdata, ctrl_pdata->dsi_irq_mask);
error_irq_resource:
if (dsi_host_private->dsi_base) {
iounmap(dsi_host_private->dsi_base);
@@ -1255,7 +1506,7 @@
return -ENODEV;
}
- msm_dsi_disable_irq();
+ msm_dsi_clear_irq(ctrl_pdata, ctrl_pdata->dsi_irq_mask);
msm_dsi_io_deinit(pdev, &(ctrl_pdata->power_data));
dsi_ctrl_config_deinit(pdev, ctrl_pdata);
iounmap(dsi_host_private->dsi_base);
diff --git a/drivers/video/msm/mdss/dsi_v2.c b/drivers/video/msm/mdss/dsi_v2.c
index f3d0ad4..ccde545 100644
--- a/drivers/video/msm/mdss/dsi_v2.c
+++ b/drivers/video/msm/mdss/dsi_v2.c
@@ -21,7 +21,6 @@
#include "dsi_v2.h"
static struct dsi_interface dsi_intf;
-static struct dsi_buf dsi_panel_tx_buf;
static int dsi_off(struct mdss_panel_data *pdata)
{
@@ -67,21 +66,13 @@
if (enable) {
dsi_ctrl_gpio_request(ctrl_pdata);
mdss_dsi_panel_reset(pdata, 1);
-
- rc = dsi_cmds_tx_v2(pdata, &dsi_panel_tx_buf,
- ctrl_pdata->on_cmds.cmds,
- ctrl_pdata->on_cmds.cmd_cnt);
-
+ rc = ctrl_pdata->on(pdata);
if (rc)
pr_err("dsi_panel_handler panel on failed %d\n", rc);
} else {
if (dsi_intf.op_mode_config)
dsi_intf.op_mode_config(DSI_CMD_MODE, pdata);
-
- dsi_cmds_tx_v2(pdata, &dsi_panel_tx_buf,
- ctrl_pdata->off_cmds.cmds,
- ctrl_pdata->off_cmds.cmd_cnt);
-
+ rc = ctrl_pdata->off(pdata);
mdss_dsi_panel_reset(pdata, 0);
dsi_ctrl_gpio_free(ctrl_pdata);
}
@@ -572,19 +563,12 @@
ctrl_pdata->panel_data.event_handler = dsi_event_handler;
- rc = dsi_buf_alloc(&dsi_panel_tx_buf,
- ALIGN(DSI_BUF_SIZE,
- SZ_4K));
- if (rc)
- return rc;
-
/*
* register in mdp driver
*/
rc = mdss_register_panel(dev, &(ctrl_pdata->panel_data));
if (rc) {
dev_err(&dev->dev, "unable to register MIPI DSI panel\n");
- kfree(dsi_panel_tx_buf.start);
return rc;
}
@@ -597,72 +581,6 @@
dsi_intf = *intf;
}
-int dsi_cmds_tx_v2(struct mdss_panel_data *pdata,
- struct dsi_buf *tp, struct dsi_cmd_desc *cmds,
- int cnt)
-{
- int rc = 0;
-
- if (!dsi_intf.tx)
- return -EINVAL;
-
- rc = dsi_intf.tx(pdata, tp, cmds, cnt);
- return rc;
-}
-
-int dsi_cmds_rx_v2(struct mdss_panel_data *pdata,
- struct dsi_buf *tp, struct dsi_buf *rp,
- struct dsi_cmd_desc *cmds, int rlen)
-{
- int rc = 0;
-
- if (pdata == NULL) {
- pr_err("%s: Invalid input data\n", __func__);
- return -EINVAL;
- }
-
- if (!dsi_intf.rx)
- return -EINVAL;
-
- rc = dsi_intf.rx(pdata, tp, rp, cmds, rlen);
- return rc;
-}
-
-static char *dsi_buf_reserve(struct dsi_buf *dp, int len)
-{
- dp->data += len;
- return dp->data;
-}
-
-
-static char *dsi_buf_push(struct dsi_buf *dp, int len)
-{
- dp->data -= len;
- dp->len += len;
- return dp->data;
-}
-
-static char *dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen)
-{
- dp->hdr = (u32 *)dp->data;
- return dsi_buf_reserve(dp, hlen);
-}
-
-char *dsi_buf_init(struct dsi_buf *dp)
-{
- int off;
-
- dp->data = dp->start;
- off = (int)dp->data;
- /* 8 byte align */
- off &= 0x07;
- if (off)
- off = 8 - off;
- dp->data += off;
- dp->len = 0;
- return dp->data;
-}
-
int dsi_buf_alloc(struct dsi_buf *dp, int size)
{
dp->start = kmalloc(size, GFP_KERNEL);
@@ -684,507 +602,3 @@
return 0;
}
-/*
- * mipi dsi generic long write
- */
-static int dsi_generic_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- char *bp;
- u32 *hp;
- int i, len;
- struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
- bp = dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-
- /* fill up payload */
- if (cm->payload) {
- len = dchdr->dlen;
- len += 3;
- len &= ~0x03; /* multipled by 4 */
- for (i = 0; i < dchdr->dlen; i++)
- *bp++ = cm->payload[i];
-
- /* append 0xff to the end */
- for (; i < len; i++)
- *bp++ = 0xff;
-
- dp->len += len;
- }
-
- /* fill up header */
- hp = dp->hdr;
- *hp = 0;
- *hp = DSI_HDR_WC(dchdr->dlen);
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_LONG_PKT;
- *hp |= DSI_HDR_DTYPE(DTYPE_GEN_LWRITE);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len;
-}
-
-/*
- * mipi dsi generic short write with 0, 1 2 parameters
- */
-static int dsi_generic_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- u32 *hp;
- int len;
- struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
- if (dchdr->dlen && cm->payload == 0) {
- pr_err("%s: NO payload error\n", __func__);
- return 0;
- }
-
- dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- len = (dchdr->dlen > 2) ? 2 : dchdr->dlen;
-
- if (len == 1) {
- *hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE1);
- *hp |= DSI_HDR_DATA1(cm->payload[0]);
- *hp |= DSI_HDR_DATA2(0);
- } else if (len == 2) {
- *hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE2);
- *hp |= DSI_HDR_DATA1(cm->payload[0]);
- *hp |= DSI_HDR_DATA2(cm->payload[1]);
- } else {
- *hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE);
- *hp |= DSI_HDR_DATA1(0);
- *hp |= DSI_HDR_DATA2(0);
- }
-
- dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len;
-}
-
-/*
- * mipi dsi gerneric read with 0, 1 2 parameters
- */
-static int dsi_generic_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- u32 *hp;
- int len;
- struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
- if (dchdr->dlen && cm->payload == 0) {
- pr_err("%s: NO payload error\n", __func__);
- return 0;
- }
-
- dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_BTA;
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- len = (dchdr->dlen > 2) ? 2 : dchdr->dlen;
-
- if (len == 1) {
- *hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ1);
- *hp |= DSI_HDR_DATA1(cm->payload[0]);
- *hp |= DSI_HDR_DATA2(0);
- } else if (len == 2) {
- *hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ2);
- *hp |= DSI_HDR_DATA1(cm->payload[0]);
- *hp |= DSI_HDR_DATA2(cm->payload[1]);
- } else {
- *hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ);
- *hp |= DSI_HDR_DATA1(0);
- *hp |= DSI_HDR_DATA2(0);
- }
-
- dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
- return dp->len;
-}
-
-/*
- * mipi dsi dcs long write
- */
-static int dsi_dcs_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- char *bp;
- u32 *hp;
- int i, len;
- struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
- bp = dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-
- /*
- * fill up payload
- * dcs command byte (first byte) followed by payload
- */
- if (cm->payload) {
- len = dchdr->dlen;
- len += 3;
- len &= ~0x03; /* multipled by 4 */
- for (i = 0; i < dchdr->dlen; i++)
- *bp++ = cm->payload[i];
-
- /* append 0xff to the end */
- for (; i < len; i++)
- *bp++ = 0xff;
-
- dp->len += len;
- }
-
- /* fill up header */
- hp = dp->hdr;
- *hp = 0;
- *hp = DSI_HDR_WC(dchdr->dlen);
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_LONG_PKT;
- *hp |= DSI_HDR_DTYPE(DTYPE_DCS_LWRITE);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len;
-}
-
-/*
- * mipi dsi dcs short write with 0 parameters
- */
-static int dsi_dcs_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- u32 *hp;
- int len;
- struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
- if (cm->payload == 0) {
- pr_err("%s: NO payload error\n", __func__);
- return -EINVAL;
- }
-
- dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- if (dchdr->ack)
- *hp |= DSI_HDR_BTA;
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- len = (dchdr->dlen > 1) ? 1 : dchdr->dlen;
-
- *hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE);
- *hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs command byte */
- *hp |= DSI_HDR_DATA2(0);
-
- dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
- return dp->len;
-}
-
-/*
- * mipi dsi dcs short write with 1 parameters
- */
-static int dsi_dcs_swrite1(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- u32 *hp;
- struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
- if (dchdr->dlen < 2 || cm->payload == 0) {
- pr_err("%s: NO payload error\n", __func__);
- return -EINVAL;
- }
-
- dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- if (dchdr->ack)
- *hp |= DSI_HDR_BTA;
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- *hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE1);
- *hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs comamnd byte */
- *hp |= DSI_HDR_DATA2(cm->payload[1]); /* parameter */
-
- dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len;
-}
-
-/*
- * mipi dsi dcs read with 0 parameters
- */
-static int dsi_dcs_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- u32 *hp;
- struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
- if (cm->payload == 0) {
- pr_err("%s: NO payload error\n", __func__);
- return -EINVAL;
- }
-
- dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_BTA;
- *hp |= DSI_HDR_DTYPE(DTYPE_DCS_READ);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- *hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs command byte */
- *hp |= DSI_HDR_DATA2(0);
-
- dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len; /* 4 bytes */
-}
-
-static int dsi_cm_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- u32 *hp;
- struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
- dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_DTYPE(DTYPE_CM_ON);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len; /* 4 bytes */
-}
-
-static int dsi_cm_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- u32 *hp;
- struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
- dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_DTYPE(DTYPE_CM_OFF);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len; /* 4 bytes */
-}
-
-static int dsi_peripheral_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- u32 *hp;
- struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
- dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_ON);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len; /* 4 bytes */
-}
-
-static int dsi_peripheral_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- u32 *hp;
- struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
- dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_OFF);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len; /* 4 bytes */
-}
-
-static int dsi_set_max_pktsize(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- u32 *hp;
- struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
- if (cm->payload == 0) {
- pr_err("%s: NO payload error\n", __func__);
- return 0;
- }
-
- dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_DTYPE(DTYPE_MAX_PKTSIZE);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- *hp |= DSI_HDR_DATA1(cm->payload[0]);
- *hp |= DSI_HDR_DATA2(cm->payload[1]);
-
- dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len; /* 4 bytes */
-}
-
-static int dsi_null_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- u32 *hp;
- struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
- dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp = DSI_HDR_WC(dchdr->dlen);
- *hp |= DSI_HDR_LONG_PKT;
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_DTYPE(DTYPE_NULL_PKT);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len; /* 4 bytes */
-}
-
-static int dsi_blank_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- u32 *hp;
- struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
- dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp = DSI_HDR_WC(dchdr->dlen);
- *hp |= DSI_HDR_LONG_PKT;
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_DTYPE(DTYPE_BLANK_PKT);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len; /* 4 bytes */
-}
-
-/*
- * prepare cmd buffer to be txed
- */
-int dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- int len = 0;
- struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
- switch (dchdr->dtype) {
- case DTYPE_GEN_WRITE:
- case DTYPE_GEN_WRITE1:
- case DTYPE_GEN_WRITE2:
- len = dsi_generic_swrite(dp, cm);
- break;
- case DTYPE_GEN_LWRITE:
- len = dsi_generic_lwrite(dp, cm);
- break;
- case DTYPE_GEN_READ:
- case DTYPE_GEN_READ1:
- case DTYPE_GEN_READ2:
- len = dsi_generic_read(dp, cm);
- break;
- case DTYPE_DCS_LWRITE:
- len = dsi_dcs_lwrite(dp, cm);
- break;
- case DTYPE_DCS_WRITE:
- len = dsi_dcs_swrite(dp, cm);
- break;
- case DTYPE_DCS_WRITE1:
- len = dsi_dcs_swrite1(dp, cm);
- break;
- case DTYPE_DCS_READ:
- len = dsi_dcs_read(dp, cm);
- break;
- case DTYPE_MAX_PKTSIZE:
- len = dsi_set_max_pktsize(dp, cm);
- break;
- case DTYPE_NULL_PKT:
- len = dsi_null_pkt(dp, cm);
- break;
- case DTYPE_BLANK_PKT:
- len = dsi_blank_pkt(dp, cm);
- break;
- case DTYPE_CM_ON:
- len = dsi_cm_on(dp, cm);
- break;
- case DTYPE_CM_OFF:
- len = dsi_cm_off(dp, cm);
- break;
- case DTYPE_PERIPHERAL_ON:
- len = dsi_peripheral_on(dp, cm);
- break;
- case DTYPE_PERIPHERAL_OFF:
- len = dsi_peripheral_off(dp, cm);
- break;
- default:
- pr_debug("%s: dtype=%x NOT supported\n",
- __func__, dchdr->dtype);
- break;
-
- }
-
- return len;
-}
-
-/*
- * mdss_dsi_short_read1_resp: 1 parameter
- */
-int dsi_short_read1_resp(struct dsi_buf *rp)
-{
- /* strip out dcs type */
- rp->data++;
- rp->len = 1;
- return rp->len;
-}
-
-/*
- * mdss_dsi_short_read2_resp: 2 parameter
- */
-int dsi_short_read2_resp(struct dsi_buf *rp)
-{
- /* strip out dcs type */
- rp->data++;
- rp->len = 2;
- return rp->len;
-}
-
-int dsi_long_read_resp(struct dsi_buf *rp)
-{
- short len;
-
- len = rp->data[2];
- len <<= 8;
- len |= rp->data[1];
- /* strip out dcs header */
- rp->data += 4;
- rp->len -= 4;
- /* strip out 2 bytes of checksum */
- rp->len -= 2;
- return len;
-}
diff --git a/drivers/video/msm/mdss/dsi_v2.h b/drivers/video/msm/mdss/dsi_v2.h
index cb007e3..b8c91da 100644
--- a/drivers/video/msm/mdss/dsi_v2.h
+++ b/drivers/video/msm/mdss/dsi_v2.h
@@ -29,11 +29,6 @@
int (*cont_on)(struct mdss_panel_data *pdata);
int (*clk_ctrl)(struct mdss_panel_data *pdata, int enable);
void (*op_mode_config)(int mode, struct mdss_panel_data *pdata);
- int (*tx)(struct mdss_panel_data *pdata,
- struct dsi_buf *tp, struct dsi_cmd_desc *cmds, int cnt);
- int (*rx)(struct mdss_panel_data *pdata,
- struct dsi_buf *tp, struct dsi_buf *rp,
- struct dsi_cmd_desc *cmds, int len);
int index;
void *private;
};
@@ -43,26 +38,8 @@
void dsi_register_interface(struct dsi_interface *intf);
-int dsi_cmds_rx_v2(struct mdss_panel_data *pdata,
- struct dsi_buf *tp, struct dsi_buf *rp,
- struct dsi_cmd_desc *cmds, int len);
-
-int dsi_cmds_tx_v2(struct mdss_panel_data *pdata,
- struct dsi_buf *tp, struct dsi_cmd_desc *cmds,
- int cnt);
-
-char *dsi_buf_init(struct dsi_buf *dp);
-
int dsi_buf_alloc(struct dsi_buf *dp, int size);
-int dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm);
-
-int dsi_short_read1_resp(struct dsi_buf *rp);
-
-int dsi_short_read2_resp(struct dsi_buf *rp);
-
-int dsi_long_read_resp(struct dsi_buf *rp);
-
void dsi_set_tx_power_mode(int mode);
void dsi_ctrl_config_deinit(struct platform_device *pdev,
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 947923a..d743c42 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -19,6 +19,7 @@
#include "mdss_panel.h"
#include "mdss_io_util.h"
+#include "mdss_dsi_cmd.h"
#define MMSS_SERDES_BASE_PHY 0x04f01000 /* mmss (De)Serializer CFG */
@@ -194,81 +195,6 @@
u32 pre_div_func;
};
-#define DSI_HOST_HDR_SIZE 4
-#define DSI_HDR_LAST BIT(31)
-#define DSI_HDR_LONG_PKT BIT(30)
-#define DSI_HDR_BTA BIT(29)
-#define DSI_HDR_VC(vc) (((vc) & 0x03) << 22)
-#define DSI_HDR_DTYPE(dtype) (((dtype) & 0x03f) << 16)
-#define DSI_HDR_DATA2(data) (((data) & 0x0ff) << 8)
-#define DSI_HDR_DATA1(data) ((data) & 0x0ff)
-#define DSI_HDR_WC(wc) ((wc) & 0x0ffff)
-
-#define MDSS_DSI_MRPS 0x04 /* Maximum Return Packet Size */
-
-#define MDSS_DSI_LEN 8 /* 4 x 4 - 6 - 2, bytes dcs header+crc-align */
-
-struct dsi_buf {
- u32 *hdr; /* dsi host header */
- char *start; /* buffer start addr */
- char *end; /* buffer end addr */
- int size; /* size of buffer */
- char *data; /* buffer */
- int len; /* data length */
- dma_addr_t dmap; /* mapped dma addr */
-};
-
-/* dcs read/write */
-#define DTYPE_DCS_WRITE 0x05 /* short write, 0 parameter */
-#define DTYPE_DCS_WRITE1 0x15 /* short write, 1 parameter */
-#define DTYPE_DCS_READ 0x06 /* read */
-#define DTYPE_DCS_LWRITE 0x39 /* long write */
-
-/* generic read/write */
-#define DTYPE_GEN_WRITE 0x03 /* short write, 0 parameter */
-#define DTYPE_GEN_WRITE1 0x13 /* short write, 1 parameter */
-#define DTYPE_GEN_WRITE2 0x23 /* short write, 2 parameter */
-#define DTYPE_GEN_LWRITE 0x29 /* long write */
-#define DTYPE_GEN_READ 0x04 /* long read, 0 parameter */
-#define DTYPE_GEN_READ1 0x14 /* long read, 1 parameter */
-#define DTYPE_GEN_READ2 0x24 /* long read, 2 parameter */
-
-#define DTYPE_TEAR_ON 0x35 /* set tear on */
-#define DTYPE_MAX_PKTSIZE 0x37 /* set max packet size */
-#define DTYPE_NULL_PKT 0x09 /* null packet, no data */
-#define DTYPE_BLANK_PKT 0x19 /* blankiing packet, no data */
-
-#define DTYPE_CM_ON 0x02 /* color mode off */
-#define DTYPE_CM_OFF 0x12 /* color mode on */
-#define DTYPE_PERIPHERAL_OFF 0x22
-#define DTYPE_PERIPHERAL_ON 0x32
-
-/*
- * dcs response
- */
-#define DTYPE_ACK_ERR_RESP 0x02
-#define DTYPE_EOT_RESP 0x08 /* end of tx */
-#define DTYPE_GEN_READ1_RESP 0x11 /* 1 parameter, short */
-#define DTYPE_GEN_READ2_RESP 0x12 /* 2 parameter, short */
-#define DTYPE_GEN_LREAD_RESP 0x1a
-#define DTYPE_DCS_LREAD_RESP 0x1c
-#define DTYPE_DCS_READ1_RESP 0x21 /* 1 parameter, short */
-#define DTYPE_DCS_READ2_RESP 0x22 /* 2 parameter, short */
-
-
-struct dsi_ctrl_hdr {
- char dtype; /* data type */
- char last; /* last in chain */
- char vc; /* virtual chan */
- char ack; /* ask ACK from peripheral */
- char wait; /* ms */
- short dlen; /* 16 bits */
-} __packed;
-
-struct dsi_cmd_desc {
- struct dsi_ctrl_hdr dchdr;
- char *payload;
-};
struct dsi_panel_cmds {
char *buf;
@@ -278,29 +204,6 @@
int link_state;
};
-#define CMD_REQ_MAX 4
-
-#define CMD_REQ_RX 0x0001
-#define CMD_REQ_COMMIT 0x0002
-#define CMD_CLK_CTRL 0x0004
-#define CMD_REQ_NO_MAX_PKT_SIZE 0x0008
-
-struct dcs_cmd_req {
- struct dsi_cmd_desc *cmds;
- int cmds_cnt;
- u32 flags;
- int rlen; /* rx length */
- char *rbuf; /* rx buf */
- void (*cb)(int data);
-};
-
-struct dcs_cmd_list {
- int put;
- int get;
- int tot;
- struct dcs_cmd_req list[CMD_REQ_MAX];
-};
-
struct dsi_kickoff_action {
struct list_head act_entry;
void (*action) (void *);
@@ -330,6 +233,7 @@
int (*off) (struct mdss_panel_data *pdata);
int (*partial_update_fnc) (struct mdss_panel_data *pdata);
int (*check_status) (struct mdss_dsi_ctrl_pdata *pdata);
+ void (*cmdlist_commit)(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp);
struct mdss_panel_data panel_data;
unsigned char *ctrl_base;
int reg_size;
@@ -389,11 +293,6 @@
int dsi_panel_device_register(struct device_node *pan_node,
struct mdss_dsi_ctrl_pdata *ctrl_pdata);
-char *mdss_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen);
-char *mdss_dsi_buf_init(struct dsi_buf *dp);
-void mdss_dsi_init(void);
-int mdss_dsi_buf_alloc(struct dsi_buf *, int size);
-int mdss_dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm);
int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl,
struct dsi_cmd_desc *cmds, int cnt);
@@ -402,8 +301,6 @@
void mdss_dsi_host_init(struct mipi_panel_info *pinfo,
struct mdss_panel_data *pdata);
-void mdss_dsi_set_tear_on(struct mdss_dsi_ctrl_pdata *ctrl);
-void mdss_dsi_set_tear_off(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_op_mode_config(int mode,
struct mdss_panel_data *pdata);
void mdss_dsi_cmd_mode_ctrl(int enable);
@@ -440,9 +337,6 @@
void mdss_dsi_cmd_mdp_busy(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_wait4video_done(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp);
-int mdss_dsi_cmdlist_put(struct mdss_dsi_ctrl_pdata *ctrl,
- struct dcs_cmd_req *cmdreq);
-struct dcs_cmd_req *mdss_dsi_cmdlist_get(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_cmdlist_kickoff(int intf);
int mdss_dsi_bta_status_check(struct mdss_dsi_ctrl_pdata *ctrl);
diff --git a/drivers/video/msm/mdss/mdss_dsi_cmd.c b/drivers/video/msm/mdss/mdss_dsi_cmd.c
new file mode 100644
index 0000000..9a3e638
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_dsi_cmd.c
@@ -0,0 +1,689 @@
+/* Copyright (c) 2012-2013, 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/module.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/iopoll.h>
+#include <linux/kthread.h>
+
+#include <mach/iommu_domains.h>
+
+#include "mdss_dsi_cmd.h"
+#include "mdss_dsi.h"
+
+/*
+ * mipi dsi buf mechanism
+ */
+char *mdss_dsi_buf_reserve(struct dsi_buf *dp, int len)
+{
+ dp->data += len;
+ return dp->data;
+}
+
+char *mdss_dsi_buf_unreserve(struct dsi_buf *dp, int len)
+{
+ dp->data -= len;
+ return dp->data;
+}
+
+char *mdss_dsi_buf_push(struct dsi_buf *dp, int len)
+{
+ dp->data -= len;
+ dp->len += len;
+ return dp->data;
+}
+
+char *mdss_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen)
+{
+ dp->hdr = (u32 *)dp->data;
+ return mdss_dsi_buf_reserve(dp, hlen);
+}
+
+char *mdss_dsi_buf_init(struct dsi_buf *dp)
+{
+ int off;
+
+ dp->data = dp->start;
+ off = (int)dp->data;
+ /* 8 byte align */
+ off &= 0x07;
+ if (off)
+ off = 8 - off;
+ dp->data += off;
+ dp->len = 0;
+ return dp->data;
+}
+
+int mdss_dsi_buf_alloc(struct dsi_buf *dp, int size)
+{
+
+ dp->start = dma_alloc_writecombine(NULL, size, &dp->dmap, GFP_KERNEL);
+ if (dp->start == NULL) {
+ pr_err("%s:%u\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+
+ dp->end = dp->start + size;
+ dp->size = size;
+
+ if ((int)dp->start & 0x07)
+ pr_err("%s: buf NOT 8 bytes aligned\n", __func__);
+
+ dp->data = dp->start;
+ dp->len = 0;
+ return size;
+}
+
+/*
+ * mipi dsi generic long write
+ */
+static int mdss_dsi_generic_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ struct dsi_ctrl_hdr *dchdr;
+ char *bp;
+ u32 *hp;
+ int i, len = 0;
+
+ dchdr = &cm->dchdr;
+ bp = mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+
+ /* fill up payload */
+ if (cm->payload) {
+ len = dchdr->dlen;
+ len += 3;
+ len &= ~0x03; /* multipled by 4 */
+ for (i = 0; i < dchdr->dlen; i++)
+ *bp++ = cm->payload[i];
+
+ /* append 0xff to the end */
+ for (; i < len; i++)
+ *bp++ = 0xff;
+
+ dp->len += len;
+ }
+
+ /* fill up header */
+ hp = dp->hdr;
+ *hp = 0;
+ *hp = DSI_HDR_WC(dchdr->dlen);
+ *hp |= DSI_HDR_VC(dchdr->vc);
+ *hp |= DSI_HDR_LONG_PKT;
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_LWRITE);
+ if (dchdr->last)
+ *hp |= DSI_HDR_LAST;
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ len += DSI_HOST_HDR_SIZE;
+
+ return len;
+}
+
+/*
+ * mipi dsi generic short write with 0, 1 2 parameters
+ */
+static int mdss_dsi_generic_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ struct dsi_ctrl_hdr *dchdr;
+ u32 *hp;
+ int len;
+
+ dchdr = &cm->dchdr;
+ if (dchdr->dlen && cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return 0;
+ }
+
+ mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(dchdr->vc);
+ if (dchdr->last)
+ *hp |= DSI_HDR_LAST;
+
+
+ len = (dchdr->dlen > 2) ? 2 : dchdr->dlen;
+
+ if (len == 1) {
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE1);
+ *hp |= DSI_HDR_DATA1(cm->payload[0]);
+ *hp |= DSI_HDR_DATA2(0);
+ } else if (len == 2) {
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE2);
+ *hp |= DSI_HDR_DATA1(cm->payload[0]);
+ *hp |= DSI_HDR_DATA2(cm->payload[1]);
+ } else {
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE);
+ *hp |= DSI_HDR_DATA1(0);
+ *hp |= DSI_HDR_DATA2(0);
+ }
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+/*
+ * mipi dsi gerneric read with 0, 1 2 parameters
+ */
+static int mdss_dsi_generic_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ struct dsi_ctrl_hdr *dchdr;
+ u32 *hp;
+ int len;
+
+ dchdr = &cm->dchdr;
+ if (dchdr->dlen && cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return 0;
+ }
+
+ mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(dchdr->vc);
+ *hp |= DSI_HDR_BTA;
+ if (dchdr->last)
+ *hp |= DSI_HDR_LAST;
+
+ len = (dchdr->dlen > 2) ? 2 : dchdr->dlen;
+
+ if (len == 1) {
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ1);
+ *hp |= DSI_HDR_DATA1(cm->payload[0]);
+ *hp |= DSI_HDR_DATA2(0);
+ } else if (len == 2) {
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ2);
+ *hp |= DSI_HDR_DATA1(cm->payload[0]);
+ *hp |= DSI_HDR_DATA2(cm->payload[1]);
+ } else {
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ);
+ *hp |= DSI_HDR_DATA1(0);
+ *hp |= DSI_HDR_DATA2(0);
+ }
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+/*
+ * mipi dsi dcs long write
+ */
+static int mdss_dsi_dcs_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ struct dsi_ctrl_hdr *dchdr;
+ char *bp;
+ u32 *hp;
+ int i, len = 0;
+
+ dchdr = &cm->dchdr;
+ bp = mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+
+ /*
+ * fill up payload
+ * dcs command byte (first byte) followed by payload
+ */
+ if (cm->payload) {
+ len = dchdr->dlen;
+ len += 3;
+ len &= ~0x03; /* multipled by 4 */
+ for (i = 0; i < dchdr->dlen; i++)
+ *bp++ = cm->payload[i];
+
+ /* append 0xff to the end */
+ for (; i < len; i++)
+ *bp++ = 0xff;
+
+ dp->len += len;
+ }
+
+ /* fill up header */
+ hp = dp->hdr;
+ *hp = 0;
+ *hp = DSI_HDR_WC(dchdr->dlen);
+ *hp |= DSI_HDR_VC(dchdr->vc);
+ *hp |= DSI_HDR_LONG_PKT;
+ *hp |= DSI_HDR_DTYPE(DTYPE_DCS_LWRITE);
+ if (dchdr->last)
+ *hp |= DSI_HDR_LAST;
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ len += DSI_HOST_HDR_SIZE;
+ return len;
+}
+
+/*
+ * mipi dsi dcs short write with 0 parameters
+ */
+static int mdss_dsi_dcs_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ struct dsi_ctrl_hdr *dchdr;
+ u32 *hp;
+ int len;
+
+ dchdr = &cm->dchdr;
+ if (cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return -EINVAL;
+ }
+
+ mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(dchdr->vc);
+ if (dchdr->ack) /* ask ACK trigger msg from peripeheral */
+ *hp |= DSI_HDR_BTA;
+ if (dchdr->last)
+ *hp |= DSI_HDR_LAST;
+
+ len = (dchdr->dlen > 1) ? 1 : dchdr->dlen;
+
+ *hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE);
+ *hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs command byte */
+ *hp |= DSI_HDR_DATA2(0);
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+/*
+ * mipi dsi dcs short write with 1 parameters
+ */
+static int mdss_dsi_dcs_swrite1(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ struct dsi_ctrl_hdr *dchdr;
+ u32 *hp;
+
+ dchdr = &cm->dchdr;
+ if (dchdr->dlen < 2 || cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return -EINVAL;
+ }
+
+ mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(dchdr->vc);
+ if (dchdr->ack) /* ask ACK trigger msg from peripeheral */
+ *hp |= DSI_HDR_BTA;
+ if (dchdr->last)
+ *hp |= DSI_HDR_LAST;
+
+ *hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE1);
+ *hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs comamnd byte */
+ *hp |= DSI_HDR_DATA2(cm->payload[1]); /* parameter */
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+/*
+ * mipi dsi dcs read with 0 parameters
+ */
+
+static int mdss_dsi_dcs_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ struct dsi_ctrl_hdr *dchdr;
+ u32 *hp;
+
+ dchdr = &cm->dchdr;
+ if (cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return -EINVAL;
+ }
+
+ mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(dchdr->vc);
+ *hp |= DSI_HDR_BTA;
+ *hp |= DSI_HDR_DTYPE(DTYPE_DCS_READ);
+ if (dchdr->last)
+ *hp |= DSI_HDR_LAST;
+
+ *hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs command byte */
+ *hp |= DSI_HDR_DATA2(0);
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+static int mdss_dsi_cm_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ struct dsi_ctrl_hdr *dchdr;
+ u32 *hp;
+
+ dchdr = &cm->dchdr;
+ mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(dchdr->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_CM_ON);
+ if (dchdr->last)
+ *hp |= DSI_HDR_LAST;
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+static int mdss_dsi_cm_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ struct dsi_ctrl_hdr *dchdr;
+ u32 *hp;
+
+ dchdr = &cm->dchdr;
+ mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(dchdr->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_CM_OFF);
+ if (dchdr->last)
+ *hp |= DSI_HDR_LAST;
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+static int mdss_dsi_peripheral_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ struct dsi_ctrl_hdr *dchdr;
+ u32 *hp;
+
+ dchdr = &cm->dchdr;
+ mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(dchdr->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_ON);
+ if (dchdr->last)
+ *hp |= DSI_HDR_LAST;
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+static int mdss_dsi_peripheral_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ struct dsi_ctrl_hdr *dchdr;
+ u32 *hp;
+
+ dchdr = &cm->dchdr;
+ mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(dchdr->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_OFF);
+ if (dchdr->last)
+ *hp |= DSI_HDR_LAST;
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+static int mdss_dsi_set_max_pktsize(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ struct dsi_ctrl_hdr *dchdr;
+ u32 *hp;
+
+ dchdr = &cm->dchdr;
+ if (cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return 0;
+ }
+
+ mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(dchdr->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_MAX_PKTSIZE);
+ if (dchdr->last)
+ *hp |= DSI_HDR_LAST;
+
+ *hp |= DSI_HDR_DATA1(cm->payload[0]);
+ *hp |= DSI_HDR_DATA2(cm->payload[1]);
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+static int mdss_dsi_null_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ struct dsi_ctrl_hdr *dchdr;
+ u32 *hp;
+
+ dchdr = &cm->dchdr;
+ mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp = DSI_HDR_WC(dchdr->dlen);
+ *hp |= DSI_HDR_LONG_PKT;
+ *hp |= DSI_HDR_VC(dchdr->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_NULL_PKT);
+ if (dchdr->last)
+ *hp |= DSI_HDR_LAST;
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+static int mdss_dsi_blank_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ struct dsi_ctrl_hdr *dchdr;
+ u32 *hp;
+
+ dchdr = &cm->dchdr;
+ mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp = DSI_HDR_WC(dchdr->dlen);
+ *hp |= DSI_HDR_LONG_PKT;
+ *hp |= DSI_HDR_VC(dchdr->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_BLANK_PKT);
+ if (dchdr->last)
+ *hp |= DSI_HDR_LAST;
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+/*
+ * prepare cmd buffer to be txed
+ */
+int mdss_dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ struct dsi_ctrl_hdr *dchdr;
+ int len = 0;
+
+ dchdr = &cm->dchdr;
+
+ switch (dchdr->dtype) {
+ case DTYPE_GEN_WRITE:
+ case DTYPE_GEN_WRITE1:
+ case DTYPE_GEN_WRITE2:
+ len = mdss_dsi_generic_swrite(dp, cm);
+ break;
+ case DTYPE_GEN_LWRITE:
+ len = mdss_dsi_generic_lwrite(dp, cm);
+ break;
+ case DTYPE_GEN_READ:
+ case DTYPE_GEN_READ1:
+ case DTYPE_GEN_READ2:
+ len = mdss_dsi_generic_read(dp, cm);
+ break;
+ case DTYPE_DCS_LWRITE:
+ len = mdss_dsi_dcs_lwrite(dp, cm);
+ break;
+ case DTYPE_DCS_WRITE:
+ len = mdss_dsi_dcs_swrite(dp, cm);
+ break;
+ case DTYPE_DCS_WRITE1:
+ len = mdss_dsi_dcs_swrite1(dp, cm);
+ break;
+ case DTYPE_DCS_READ:
+ len = mdss_dsi_dcs_read(dp, cm);
+ break;
+ case DTYPE_MAX_PKTSIZE:
+ len = mdss_dsi_set_max_pktsize(dp, cm);
+ break;
+ case DTYPE_NULL_PKT:
+ len = mdss_dsi_null_pkt(dp, cm);
+ break;
+ case DTYPE_BLANK_PKT:
+ len = mdss_dsi_blank_pkt(dp, cm);
+ break;
+ case DTYPE_CM_ON:
+ len = mdss_dsi_cm_on(dp, cm);
+ break;
+ case DTYPE_CM_OFF:
+ len = mdss_dsi_cm_off(dp, cm);
+ break;
+ case DTYPE_PERIPHERAL_ON:
+ len = mdss_dsi_peripheral_on(dp, cm);
+ break;
+ case DTYPE_PERIPHERAL_OFF:
+ len = mdss_dsi_peripheral_off(dp, cm);
+ break;
+ default:
+ pr_debug("%s: dtype=%x NOT supported\n",
+ __func__, dchdr->dtype);
+ break;
+
+ }
+
+ return len;
+}
+
+/*
+ * mdss_dsi_short_read1_resp: 1 parameter
+ */
+int mdss_dsi_short_read1_resp(struct dsi_buf *rp)
+{
+ /* strip out dcs type */
+ rp->data++;
+ rp->len = 1;
+ return rp->len;
+}
+
+/*
+ * mdss_dsi_short_read2_resp: 2 parameter
+ */
+int mdss_dsi_short_read2_resp(struct dsi_buf *rp)
+{
+ /* strip out dcs type */
+ rp->data++;
+ rp->len = 2;
+ return rp->len;
+}
+
+int mdss_dsi_long_read_resp(struct dsi_buf *rp)
+{
+ /* strip out dcs header */
+ rp->data += 4;
+ rp->len -= 4;
+ return rp->len;
+}
+
+static char set_tear_on[2] = {0x35, 0x00};
+static struct dsi_cmd_desc dsi_tear_on_cmd = {
+ {DTYPE_DCS_WRITE1, 1, 0, 0, 0, sizeof(set_tear_on)}, set_tear_on};
+
+static char set_tear_off[2] = {0x34, 0x00};
+static struct dsi_cmd_desc dsi_tear_off_cmd = {
+ {DTYPE_DCS_WRITE, 1, 0, 0, 0, sizeof(set_tear_off)}, set_tear_off};
+
+void mdss_dsi_set_tear_on(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ struct dcs_cmd_req cmdreq;
+
+ cmdreq.cmds = &dsi_tear_on_cmd;
+ cmdreq.cmds_cnt = 1;
+ cmdreq.flags = CMD_REQ_COMMIT;
+ cmdreq.rlen = 0;
+ cmdreq.cb = NULL;
+
+ mdss_dsi_cmdlist_put(ctrl, &cmdreq);
+}
+
+void mdss_dsi_set_tear_off(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ struct dcs_cmd_req cmdreq;
+
+ cmdreq.cmds = &dsi_tear_off_cmd;
+ cmdreq.cmds_cnt = 1;
+ cmdreq.flags = CMD_REQ_COMMIT;
+ cmdreq.rlen = 0;
+ cmdreq.cb = NULL;
+
+ mdss_dsi_cmdlist_put(ctrl, &cmdreq);
+}
+
+/*
+ * mdss_dsi_cmd_get: ctrl->cmd_mutex acquired by caller
+ */
+struct dcs_cmd_req *mdss_dsi_cmdlist_get(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ struct dcs_cmd_list *clist;
+ struct dcs_cmd_req *req = NULL;
+
+ clist = &ctrl->cmdlist;
+ if (clist->get != clist->put) {
+ req = &clist->list[clist->get];
+ clist->get++;
+ clist->get %= CMD_REQ_MAX;
+ clist->tot--;
+ pr_debug("%s: tot=%d put=%d get=%d\n", __func__,
+ clist->tot, clist->put, clist->get);
+ }
+ return req;
+}
+
+int mdss_dsi_cmdlist_put(struct mdss_dsi_ctrl_pdata *ctrl,
+ struct dcs_cmd_req *cmdreq)
+{
+ struct dcs_cmd_req *req;
+ struct dcs_cmd_list *clist;
+ int ret = 0;
+
+ mutex_lock(&ctrl->cmd_mutex);
+ clist = &ctrl->cmdlist;
+ req = &clist->list[clist->put];
+ *req = *cmdreq;
+ clist->put++;
+ clist->put %= CMD_REQ_MAX;
+ clist->tot++;
+ if (clist->put == clist->get) {
+ /* drop the oldest one */
+ pr_debug("%s: DROP, tot=%d put=%d get=%d\n", __func__,
+ clist->tot, clist->put, clist->get);
+ clist->get++;
+ clist->get %= CMD_REQ_MAX;
+ clist->tot--;
+ }
+ mutex_unlock(&ctrl->cmd_mutex);
+
+ ret++;
+ pr_debug("%s: tot=%d put=%d get=%d\n", __func__,
+ clist->tot, clist->put, clist->get);
+
+ if (req->flags & CMD_REQ_COMMIT) {
+ if (!ctrl->cmdlist_commit)
+ pr_err("cmdlist_commit not implemented!\n");
+ else
+ ctrl->cmdlist_commit(ctrl, 0);
+ }
+ return ret;
+}
+
diff --git a/drivers/video/msm/mdss/mdss_dsi_cmd.h b/drivers/video/msm/mdss/mdss_dsi_cmd.h
new file mode 100644
index 0000000..c480756
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_dsi_cmd.h
@@ -0,0 +1,133 @@
+/* Copyright (c) 2012-2013, 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 MDSS_DSI_CMD_H
+#define MDSS_DSI_CMD_H
+
+#include "mdss.h"
+
+struct mdss_dsi_ctrl_pdata;
+
+#define DSI_HOST_HDR_SIZE 4
+#define DSI_HDR_LAST BIT(31)
+#define DSI_HDR_LONG_PKT BIT(30)
+#define DSI_HDR_BTA BIT(29)
+#define DSI_HDR_VC(vc) (((vc) & 0x03) << 22)
+#define DSI_HDR_DTYPE(dtype) (((dtype) & 0x03f) << 16)
+#define DSI_HDR_DATA2(data) (((data) & 0x0ff) << 8)
+#define DSI_HDR_DATA1(data) ((data) & 0x0ff)
+#define DSI_HDR_WC(wc) ((wc) & 0x0ffff)
+
+#define MDSS_DSI_MRPS 0x04 /* Maximum Return Packet Size */
+
+#define MDSS_DSI_LEN 8 /* 4 x 4 - 6 - 2, bytes dcs header+crc-align */
+
+struct dsi_buf {
+ u32 *hdr; /* dsi host header */
+ char *start; /* buffer start addr */
+ char *end; /* buffer end addr */
+ int size; /* size of buffer */
+ char *data; /* buffer */
+ int len; /* data length */
+ dma_addr_t dmap; /* mapped dma addr */
+};
+
+/* dcs read/write */
+#define DTYPE_DCS_WRITE 0x05 /* short write, 0 parameter */
+#define DTYPE_DCS_WRITE1 0x15 /* short write, 1 parameter */
+#define DTYPE_DCS_READ 0x06 /* read */
+#define DTYPE_DCS_LWRITE 0x39 /* long write */
+
+/* generic read/write */
+#define DTYPE_GEN_WRITE 0x03 /* short write, 0 parameter */
+#define DTYPE_GEN_WRITE1 0x13 /* short write, 1 parameter */
+#define DTYPE_GEN_WRITE2 0x23 /* short write, 2 parameter */
+#define DTYPE_GEN_LWRITE 0x29 /* long write */
+#define DTYPE_GEN_READ 0x04 /* long read, 0 parameter */
+#define DTYPE_GEN_READ1 0x14 /* long read, 1 parameter */
+#define DTYPE_GEN_READ2 0x24 /* long read, 2 parameter */
+
+#define DTYPE_TEAR_ON 0x35 /* set tear on */
+#define DTYPE_MAX_PKTSIZE 0x37 /* set max packet size */
+#define DTYPE_NULL_PKT 0x09 /* null packet, no data */
+#define DTYPE_BLANK_PKT 0x19 /* blankiing packet, no data */
+
+#define DTYPE_CM_ON 0x02 /* color mode off */
+#define DTYPE_CM_OFF 0x12 /* color mode on */
+#define DTYPE_PERIPHERAL_OFF 0x22
+#define DTYPE_PERIPHERAL_ON 0x32
+
+/*
+ * dcs response
+ */
+#define DTYPE_ACK_ERR_RESP 0x02
+#define DTYPE_EOT_RESP 0x08 /* end of tx */
+#define DTYPE_GEN_READ1_RESP 0x11 /* 1 parameter, short */
+#define DTYPE_GEN_READ2_RESP 0x12 /* 2 parameter, short */
+#define DTYPE_GEN_LREAD_RESP 0x1a
+#define DTYPE_DCS_LREAD_RESP 0x1c
+#define DTYPE_DCS_READ1_RESP 0x21 /* 1 parameter, short */
+#define DTYPE_DCS_READ2_RESP 0x22 /* 2 parameter, short */
+
+struct dsi_ctrl_hdr {
+ char dtype; /* data type */
+ char last; /* last in chain */
+ char vc; /* virtual chan */
+ char ack; /* ask ACK from peripheral */
+ char wait; /* ms */
+ short dlen; /* 16 bits */
+} __packed;
+
+struct dsi_cmd_desc {
+ struct dsi_ctrl_hdr dchdr;
+ char *payload;
+};
+
+#define CMD_REQ_MAX 4
+#define CMD_REQ_RX 0x0001
+#define CMD_REQ_COMMIT 0x0002
+#define CMD_CLK_CTRL 0x0004
+#define CMD_REQ_NO_MAX_PKT_SIZE 0x0008
+
+struct dcs_cmd_req {
+ struct dsi_cmd_desc *cmds;
+ int cmds_cnt;
+ u32 flags;
+ int rlen; /* rx length */
+ char *rbuf; /* rx buf */
+ void (*cb)(int data);
+};
+
+struct dcs_cmd_list {
+ int put;
+ int get;
+ int tot;
+ struct dcs_cmd_req list[CMD_REQ_MAX];
+};
+
+char *mdss_dsi_buf_reserve(struct dsi_buf *dp, int len);
+char *mdss_dsi_buf_unreserve(struct dsi_buf *dp, int len);
+char *mdss_dsi_buf_push(struct dsi_buf *dp, int len);
+char *mdss_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen);
+char *mdss_dsi_buf_init(struct dsi_buf *dp);
+int mdss_dsi_buf_alloc(struct dsi_buf *dp, int size);
+int mdss_dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm);
+int mdss_dsi_short_read1_resp(struct dsi_buf *rp);
+int mdss_dsi_short_read2_resp(struct dsi_buf *rp);
+int mdss_dsi_long_read_resp(struct dsi_buf *rp);
+void mdss_dsi_set_tear_on(struct mdss_dsi_ctrl_pdata *ctrl);
+void mdss_dsi_set_tear_off(struct mdss_dsi_ctrl_pdata *ctrl);
+struct dcs_cmd_req *mdss_dsi_cmdlist_get(struct mdss_dsi_ctrl_pdata *ctrl);
+int mdss_dsi_cmdlist_put(struct mdss_dsi_ctrl_pdata *ctrl,
+ struct dcs_cmd_req *cmdreq);
+#endif
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index 750fbf3..43065ec 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -107,6 +107,7 @@
mutex_init(&ctrl->cmd_mutex);
mdss_dsi_buf_alloc(&ctrl->tx_buf, SZ_4K);
mdss_dsi_buf_alloc(&ctrl->rx_buf, SZ_4K);
+ ctrl->cmdlist_commit = mdss_dsi_cmdlist_commit;
if (dsi_event.inited == 0) {
@@ -199,576 +200,6 @@
spin_unlock(&ctrl->irq_lock);
}
-/*
- * mipi dsi buf mechanism
- */
-char *mdss_dsi_buf_reserve(struct dsi_buf *dp, int len)
-{
- dp->data += len;
- return dp->data;
-}
-
-char *mdss_dsi_buf_unreserve(struct dsi_buf *dp, int len)
-{
- dp->data -= len;
- return dp->data;
-}
-
-char *mdss_dsi_buf_push(struct dsi_buf *dp, int len)
-{
- dp->data -= len;
- dp->len += len;
- return dp->data;
-}
-
-char *mdss_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen)
-{
- dp->hdr = (u32 *)dp->data;
- return mdss_dsi_buf_reserve(dp, hlen);
-}
-
-char *mdss_dsi_buf_init(struct dsi_buf *dp)
-{
- int off;
-
- dp->data = dp->start;
- off = (int)dp->data;
- /* 8 byte align */
- off &= 0x07;
- if (off)
- off = 8 - off;
- dp->data += off;
- dp->len = 0;
- return dp->data;
-}
-
-int mdss_dsi_buf_alloc(struct dsi_buf *dp, int size)
-{
-
- dp->start = dma_alloc_writecombine(NULL, size, &dp->dmap, GFP_KERNEL);
- if (dp->start == NULL) {
- pr_err("%s:%u\n", __func__, __LINE__);
- return -ENOMEM;
- }
-
- dp->end = dp->start + size;
- dp->size = size;
-
- if ((int)dp->start & 0x07)
- pr_err("%s: buf NOT 8 bytes aligned\n", __func__);
-
- dp->data = dp->start;
- dp->len = 0;
- return size;
-}
-
-/*
- * mipi dsi generic long write
- */
-static int mdss_dsi_generic_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- struct dsi_ctrl_hdr *dchdr;
- char *bp;
- u32 *hp;
- int i, len = 0;
-
- dchdr = &cm->dchdr;
- bp = mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-
- /* fill up payload */
- if (cm->payload) {
- len = dchdr->dlen;
- len += 3;
- len &= ~0x03; /* multipled by 4 */
- for (i = 0; i < dchdr->dlen; i++)
- *bp++ = cm->payload[i];
-
- /* append 0xff to the end */
- for (; i < len; i++)
- *bp++ = 0xff;
-
- dp->len += len;
- }
-
- /* fill up header */
- hp = dp->hdr;
- *hp = 0;
- *hp = DSI_HDR_WC(dchdr->dlen);
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_LONG_PKT;
- *hp |= DSI_HDR_DTYPE(DTYPE_GEN_LWRITE);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
- len += DSI_HOST_HDR_SIZE;
-
- return len;
-}
-
-/*
- * mipi dsi generic short write with 0, 1 2 parameters
- */
-static int mdss_dsi_generic_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- struct dsi_ctrl_hdr *dchdr;
- u32 *hp;
- int len;
-
- dchdr = &cm->dchdr;
- if (dchdr->dlen && cm->payload == 0) {
- pr_err("%s: NO payload error\n", __func__);
- return 0;
- }
-
- mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
-
- len = (dchdr->dlen > 2) ? 2 : dchdr->dlen;
-
- if (len == 1) {
- *hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE1);
- *hp |= DSI_HDR_DATA1(cm->payload[0]);
- *hp |= DSI_HDR_DATA2(0);
- } else if (len == 2) {
- *hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE2);
- *hp |= DSI_HDR_DATA1(cm->payload[0]);
- *hp |= DSI_HDR_DATA2(cm->payload[1]);
- } else {
- *hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE);
- *hp |= DSI_HDR_DATA1(0);
- *hp |= DSI_HDR_DATA2(0);
- }
-
- mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
- return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-/*
- * mipi dsi gerneric read with 0, 1 2 parameters
- */
-static int mdss_dsi_generic_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- struct dsi_ctrl_hdr *dchdr;
- u32 *hp;
- int len;
-
- dchdr = &cm->dchdr;
- if (dchdr->dlen && cm->payload == 0) {
- pr_err("%s: NO payload error\n", __func__);
- return 0;
- }
-
- mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_BTA;
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- len = (dchdr->dlen > 2) ? 2 : dchdr->dlen;
-
- if (len == 1) {
- *hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ1);
- *hp |= DSI_HDR_DATA1(cm->payload[0]);
- *hp |= DSI_HDR_DATA2(0);
- } else if (len == 2) {
- *hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ2);
- *hp |= DSI_HDR_DATA1(cm->payload[0]);
- *hp |= DSI_HDR_DATA2(cm->payload[1]);
- } else {
- *hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ);
- *hp |= DSI_HDR_DATA1(0);
- *hp |= DSI_HDR_DATA2(0);
- }
-
- mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
- return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-/*
- * mipi dsi dcs long write
- */
-static int mdss_dsi_dcs_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- struct dsi_ctrl_hdr *dchdr;
- char *bp;
- u32 *hp;
- int i, len = 0;
-
- dchdr = &cm->dchdr;
- bp = mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-
- /*
- * fill up payload
- * dcs command byte (first byte) followed by payload
- */
- if (cm->payload) {
- len = dchdr->dlen;
- len += 3;
- len &= ~0x03; /* multipled by 4 */
- for (i = 0; i < dchdr->dlen; i++)
- *bp++ = cm->payload[i];
-
- /* append 0xff to the end */
- for (; i < len; i++)
- *bp++ = 0xff;
-
- dp->len += len;
- }
-
- /* fill up header */
- hp = dp->hdr;
- *hp = 0;
- *hp = DSI_HDR_WC(dchdr->dlen);
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_LONG_PKT;
- *hp |= DSI_HDR_DTYPE(DTYPE_DCS_LWRITE);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- len += DSI_HOST_HDR_SIZE;
- return len;
-}
-
-/*
- * mipi dsi dcs short write with 0 parameters
- */
-static int mdss_dsi_dcs_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- struct dsi_ctrl_hdr *dchdr;
- u32 *hp;
- int len;
-
- dchdr = &cm->dchdr;
- if (cm->payload == 0) {
- pr_err("%s: NO payload error\n", __func__);
- return -EINVAL;
- }
-
- mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- if (dchdr->ack) /* ask ACK trigger msg from peripeheral */
- *hp |= DSI_HDR_BTA;
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- len = (dchdr->dlen > 1) ? 1 : dchdr->dlen;
-
- *hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE);
- *hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs command byte */
- *hp |= DSI_HDR_DATA2(0);
-
- mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
- return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-/*
- * mipi dsi dcs short write with 1 parameters
- */
-static int mdss_dsi_dcs_swrite1(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- struct dsi_ctrl_hdr *dchdr;
- u32 *hp;
-
- dchdr = &cm->dchdr;
- if (dchdr->dlen < 2 || cm->payload == 0) {
- pr_err("%s: NO payload error\n", __func__);
- return -EINVAL;
- }
-
- mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- if (dchdr->ack) /* ask ACK trigger msg from peripeheral */
- *hp |= DSI_HDR_BTA;
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- *hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE1);
- *hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs comamnd byte */
- *hp |= DSI_HDR_DATA2(cm->payload[1]); /* parameter */
-
- mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
- return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-/*
- * mipi dsi dcs read with 0 parameters
- */
-
-static int mdss_dsi_dcs_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- struct dsi_ctrl_hdr *dchdr;
- u32 *hp;
-
- dchdr = &cm->dchdr;
- if (cm->payload == 0) {
- pr_err("%s: NO payload error\n", __func__);
- return -EINVAL;
- }
-
- mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_BTA;
- *hp |= DSI_HDR_DTYPE(DTYPE_DCS_READ);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- *hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs command byte */
- *hp |= DSI_HDR_DATA2(0);
-
- mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
- return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-static int mdss_dsi_cm_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- struct dsi_ctrl_hdr *dchdr;
- u32 *hp;
-
- dchdr = &cm->dchdr;
- mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_DTYPE(DTYPE_CM_ON);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
- return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-static int mdss_dsi_cm_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- struct dsi_ctrl_hdr *dchdr;
- u32 *hp;
-
- dchdr = &cm->dchdr;
- mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_DTYPE(DTYPE_CM_OFF);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
- return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-static int mdss_dsi_peripheral_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- struct dsi_ctrl_hdr *dchdr;
- u32 *hp;
-
- dchdr = &cm->dchdr;
- mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_ON);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
- return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-static int mdss_dsi_peripheral_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- struct dsi_ctrl_hdr *dchdr;
- u32 *hp;
-
- dchdr = &cm->dchdr;
- mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_OFF);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
- return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-static int mdss_dsi_set_max_pktsize(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- struct dsi_ctrl_hdr *dchdr;
- u32 *hp;
-
- dchdr = &cm->dchdr;
- if (cm->payload == 0) {
- pr_err("%s: NO payload error\n", __func__);
- return 0;
- }
-
- mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_DTYPE(DTYPE_MAX_PKTSIZE);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- *hp |= DSI_HDR_DATA1(cm->payload[0]);
- *hp |= DSI_HDR_DATA2(cm->payload[1]);
-
- mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
- return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-static int mdss_dsi_null_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- struct dsi_ctrl_hdr *dchdr;
- u32 *hp;
-
- dchdr = &cm->dchdr;
- mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp = DSI_HDR_WC(dchdr->dlen);
- *hp |= DSI_HDR_LONG_PKT;
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_DTYPE(DTYPE_NULL_PKT);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
- return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-static int mdss_dsi_blank_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- struct dsi_ctrl_hdr *dchdr;
- u32 *hp;
-
- dchdr = &cm->dchdr;
- mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
- hp = dp->hdr;
- *hp = 0;
- *hp = DSI_HDR_WC(dchdr->dlen);
- *hp |= DSI_HDR_LONG_PKT;
- *hp |= DSI_HDR_VC(dchdr->vc);
- *hp |= DSI_HDR_DTYPE(DTYPE_BLANK_PKT);
- if (dchdr->last)
- *hp |= DSI_HDR_LAST;
-
- mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
- return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-/*
- * prepare cmd buffer to be txed
- */
-int mdss_dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
- struct dsi_ctrl_hdr *dchdr;
- int len = 0;
-
- dchdr = &cm->dchdr;
-
- switch (dchdr->dtype) {
- case DTYPE_GEN_WRITE:
- case DTYPE_GEN_WRITE1:
- case DTYPE_GEN_WRITE2:
- len = mdss_dsi_generic_swrite(dp, cm);
- break;
- case DTYPE_GEN_LWRITE:
- len = mdss_dsi_generic_lwrite(dp, cm);
- break;
- case DTYPE_GEN_READ:
- case DTYPE_GEN_READ1:
- case DTYPE_GEN_READ2:
- len = mdss_dsi_generic_read(dp, cm);
- break;
- case DTYPE_DCS_LWRITE:
- len = mdss_dsi_dcs_lwrite(dp, cm);
- break;
- case DTYPE_DCS_WRITE:
- len = mdss_dsi_dcs_swrite(dp, cm);
- break;
- case DTYPE_DCS_WRITE1:
- len = mdss_dsi_dcs_swrite1(dp, cm);
- break;
- case DTYPE_DCS_READ:
- len = mdss_dsi_dcs_read(dp, cm);
- break;
- case DTYPE_MAX_PKTSIZE:
- len = mdss_dsi_set_max_pktsize(dp, cm);
- break;
- case DTYPE_NULL_PKT:
- len = mdss_dsi_null_pkt(dp, cm);
- break;
- case DTYPE_BLANK_PKT:
- len = mdss_dsi_blank_pkt(dp, cm);
- break;
- case DTYPE_CM_ON:
- len = mdss_dsi_cm_on(dp, cm);
- break;
- case DTYPE_CM_OFF:
- len = mdss_dsi_cm_off(dp, cm);
- break;
- case DTYPE_PERIPHERAL_ON:
- len = mdss_dsi_peripheral_on(dp, cm);
- break;
- case DTYPE_PERIPHERAL_OFF:
- len = mdss_dsi_peripheral_off(dp, cm);
- break;
- default:
- pr_debug("%s: dtype=%x NOT supported\n",
- __func__, dchdr->dtype);
- break;
-
- }
-
- return len;
-}
-
-/*
- * mdss_dsi_short_read1_resp: 1 parameter
- */
-static int mdss_dsi_short_read1_resp(struct dsi_buf *rp)
-{
- /* strip out dcs type */
- rp->data++;
- rp->len = 1;
- return rp->len;
-}
-
-/*
- * mdss_dsi_short_read2_resp: 2 parameter
- */
-static int mdss_dsi_short_read2_resp(struct dsi_buf *rp)
-{
- /* strip out dcs type */
- rp->data++;
- rp->len = 2;
- return rp->len;
-}
-
-static int mdss_dsi_long_read_resp(struct dsi_buf *rp)
-{
- /* strip out dcs header */
- rp->data += 4;
- rp->len -= 4;
- return rp->len;
-}
-
void mdss_dsi_cmd_test_pattern(struct mdss_panel_data *pdata)
{
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
@@ -1202,40 +633,6 @@
return ret;
}
-static char set_tear_on[2] = {0x35, 0x00};
-static struct dsi_cmd_desc dsi_tear_on_cmd = {
- {DTYPE_DCS_WRITE1, 1, 0, 0, 0, sizeof(set_tear_on)}, set_tear_on};
-
-static char set_tear_off[2] = {0x34, 0x00};
-static struct dsi_cmd_desc dsi_tear_off_cmd = {
- {DTYPE_DCS_WRITE, 1, 0, 0, 0, sizeof(set_tear_off)}, set_tear_off};
-
-void mdss_dsi_set_tear_on(struct mdss_dsi_ctrl_pdata *ctrl)
-{
- struct dcs_cmd_req cmdreq;
-
- cmdreq.cmds = &dsi_tear_on_cmd;
- cmdreq.cmds_cnt = 1;
- cmdreq.flags = CMD_REQ_COMMIT;
- cmdreq.rlen = 0;
- cmdreq.cb = NULL;
-
- mdss_dsi_cmdlist_put(ctrl, &cmdreq);
-}
-
-void mdss_dsi_set_tear_off(struct mdss_dsi_ctrl_pdata *ctrl)
-{
- struct dcs_cmd_req cmdreq;
-
- cmdreq.cmds = &dsi_tear_off_cmd;
- cmdreq.cmds_cnt = 1;
- cmdreq.flags = CMD_REQ_COMMIT;
- cmdreq.rlen = 0;
- cmdreq.cb = NULL;
-
- mdss_dsi_cmdlist_put(ctrl, &cmdreq);
-}
-
int mdss_dsi_cmd_reg_tx(u32 data,
unsigned char *ctrl_base)
{
@@ -1765,7 +1162,6 @@
if (req->cb)
req->cb(ret);
-
}
void mdss_dsi_cmdlist_rx(struct mdss_dsi_ctrl_pdata *ctrl,
@@ -1828,61 +1224,6 @@
mutex_unlock(&ctrl->cmd_mutex);
}
-/*
- * mdss_dsi_cmd_get: ctrl->cmd_mutex acquired by caller
- */
-struct dcs_cmd_req *mdss_dsi_cmdlist_get(struct mdss_dsi_ctrl_pdata *ctrl)
-{
- struct dcs_cmd_list *clist;
- struct dcs_cmd_req *req = NULL;
-
- clist = &ctrl->cmdlist;
- if (clist->get != clist->put) {
- req = &clist->list[clist->get];
- clist->get++;
- clist->get %= CMD_REQ_MAX;
- clist->tot--;
- pr_debug("%s: tot=%d put=%d get=%d\n", __func__,
- clist->tot, clist->put, clist->get);
- }
- return req;
-}
-
-int mdss_dsi_cmdlist_put(struct mdss_dsi_ctrl_pdata *ctrl,
- struct dcs_cmd_req *cmdreq)
-{
- struct dcs_cmd_req *req;
- struct dcs_cmd_list *clist;
- int ret = 0;
-
- mutex_lock(&ctrl->cmd_mutex);
- clist = &ctrl->cmdlist;
- req = &clist->list[clist->put];
- *req = *cmdreq;
- clist->put++;
- clist->put %= CMD_REQ_MAX;
- clist->tot++;
- if (clist->put == clist->get) {
- /* drop the oldest one */
- pr_debug("%s: DROP, tot=%d put=%d get=%d\n", __func__,
- clist->tot, clist->put, clist->get);
- clist->get++;
- clist->get %= CMD_REQ_MAX;
- clist->tot--;
- }
- mutex_unlock(&ctrl->cmd_mutex);
-
- ret++;
- pr_debug("%s: tot=%d put=%d get=%d\n", __func__,
- clist->tot, clist->put, clist->get);
-
- if (req->flags & CMD_REQ_COMMIT)
- mdss_dsi_cmdlist_commit(ctrl, 0);
-
- return ret;
-}
-
-
static void dsi_send_events(struct mdss_dsi_ctrl_pdata *ctrl, u32 events)
{
struct dsi_event_q *evq;
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index c15c02b..5408bc3 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -1172,7 +1172,6 @@
pr_err("unable to start display thread %d\n",
mfd->index);
result = PTR_ERR(mfd->disp_thread);
- mfd->disp_thread = NULL;
goto thread_error;
}
@@ -1192,7 +1191,6 @@
blank_error:
kthread_stop(mfd->disp_thread);
- mfd->disp_thread = NULL;
thread_error:
if (pinfo && !pinfo->ref_cnt) {
@@ -1244,10 +1242,8 @@
pm_runtime_put(info->dev);
} while (release_all && pinfo->ref_cnt);
- if (release_all && mfd->disp_thread) {
+ if (release_all)
kthread_stop(mfd->disp_thread);
- mfd->disp_thread = NULL;
- }
if (pinfo->ref_cnt == 0) {
list_del(&pinfo->list);
@@ -1285,10 +1281,7 @@
}
if (!mfd->ref_cnt) {
- if (mfd->disp_thread) {
- kthread_stop(mfd->disp_thread);
- mfd->disp_thread = NULL;
- }
+ kthread_stop(mfd->disp_thread);
ret = mdss_fb_blank_sub(FB_BLANK_POWERDOWN, info,
mfd->op_enable);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 87b7526..4a51987 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -63,8 +63,11 @@
/* Supported HDMI Audio channels */
#define MSM_HDMI_AUDIO_CHANNEL_2 2
+#define MSM_HDMI_AUDIO_CHANNEL_3 3
#define MSM_HDMI_AUDIO_CHANNEL_4 4
+#define MSM_HDMI_AUDIO_CHANNEL_5 5
#define MSM_HDMI_AUDIO_CHANNEL_6 6
+#define MSM_HDMI_AUDIO_CHANNEL_7 7
#define MSM_HDMI_AUDIO_CHANNEL_8 8
enum msm_hdmi_supported_audio_sample_rates {
@@ -2051,12 +2054,15 @@
switch (num_of_channels) {
case MSM_HDMI_AUDIO_CHANNEL_2:
break;
+ case MSM_HDMI_AUDIO_CHANNEL_3:
case MSM_HDMI_AUDIO_CHANNEL_4:
channel_count = 3;
break;
+ case MSM_HDMI_AUDIO_CHANNEL_5:
case MSM_HDMI_AUDIO_CHANNEL_6:
channel_count = 5;
break;
+ case MSM_HDMI_AUDIO_CHANNEL_7:
case MSM_HDMI_AUDIO_CHANNEL_8:
channel_count = 7;
break;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 8dc6c56..0448063 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -1551,6 +1551,8 @@
ret);
goto exit;
}
+ if (mdata->nad_cfgs == 0)
+ valid_mixers = false;
for (i = 0; i < mixer_cnt && valid_mixers; i++) {
if (mixer_id[i] > mdata->nad_cfgs)
valid_mixers = false;
diff --git a/include/media/msm_vidc.h b/include/media/msm_vidc.h
index ef7d118..bc85ebb 100644
--- a/include/media/msm_vidc.h
+++ b/include/media/msm_vidc.h
@@ -18,6 +18,41 @@
MSM_VIDC_MAX_DEVICES,
};
+/* NOTE: if you change this enum you MUST update the
+ * "buffer-type-tz-usage-table" for any affected target
+ * in arch/arm/boot/dts/<arch>.dtsi
+ */
+enum hal_buffer {
+ HAL_BUFFER_INPUT = 0x1,
+ HAL_BUFFER_OUTPUT = 0x2,
+ HAL_BUFFER_OUTPUT2 = 0x4,
+ HAL_BUFFER_EXTRADATA_INPUT = 0x8,
+ HAL_BUFFER_EXTRADATA_OUTPUT = 0x10,
+ HAL_BUFFER_EXTRADATA_OUTPUT2 = 0x20,
+ HAL_BUFFER_INTERNAL_SCRATCH = 0x40,
+ HAL_BUFFER_INTERNAL_SCRATCH_1 = 0x80,
+ HAL_BUFFER_INTERNAL_SCRATCH_2 = 0x100,
+ HAL_BUFFER_INTERNAL_PERSIST = 0x200,
+ HAL_BUFFER_INTERNAL_PERSIST_1 = 0x400,
+ HAL_BUFFER_INTERNAL_CMD_QUEUE = 0x800,
+};
+
+struct msm_smem {
+ int mem_type;
+ size_t size;
+ void *kvaddr;
+ unsigned long device_addr;
+ u32 flags;
+ void *smem_priv;
+ enum hal_buffer buffer_type;
+};
+
+enum smem_cache_ops {
+ SMEM_CACHE_CLEAN,
+ SMEM_CACHE_INVALIDATE,
+ SMEM_CACHE_CLEAN_INVALIDATE,
+};
+
void *msm_vidc_open(int core_id, int session_type);
int msm_vidc_close(void *instance);
int msm_vidc_querycap(void *instance, struct v4l2_capability *cap);
@@ -47,6 +82,18 @@
int msm_vidc_wait(void *instance);
int msm_vidc_s_parm(void *instance, struct v4l2_streamparm *a);
int msm_vidc_enum_framesizes(void *instance, struct v4l2_frmsizeenum *fsize);
+struct msm_smem *msm_vidc_smem_alloc(void *instance,
+ size_t size, u32 align, u32 flags,
+ enum hal_buffer buffer_type, int map_kernel);
+void msm_vidc_smem_free(void *instance, struct msm_smem *mem);
+int msm_vidc_smem_cache_operations(void *instance,
+ struct msm_smem *mem, enum smem_cache_ops);
+struct msm_smem *msm_vidc_smem_user_to_kernel(void *instance,
+ int fd, u32 offset, enum hal_buffer buffer_type);
+int msm_vidc_smem_get_domain_partition(void *instance,
+ u32 flags, enum hal_buffer buffer_type,
+ int *domain_num, int *partition_num);
+void *msm_vidc_smem_get_client(void *instance);
#endif
struct msm_vidc_interlace_payload {
unsigned int format;
diff --git a/lib/idr.c b/lib/idr.c
index 4046e29..e90d2d0 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -625,7 +625,14 @@
return p;
}
- id += 1 << n;
+ /*
+ * Proceed to the next layer at the current level. Unlike
+ * idr_for_each(), @id isn't guaranteed to be aligned to
+ * layer boundary at this point and adding 1 << n may
+ * incorrectly skip IDs. Make sure we jump to the
+ * beginning of the next layer using round_up().
+ */
+ id = round_up(id + 1, 1 << n);
while (n < fls(id)) {
n += IDR_BITS;
p = *--paa;
diff --git a/sound/soc/codecs/msm_hdmi_codec_rx.c b/sound/soc/codecs/msm_hdmi_codec_rx.c
index e5d5c32..ae6bfbe 100644
--- a/sound/soc/codecs/msm_hdmi_codec_rx.c
+++ b/sound/soc/codecs/msm_hdmi_codec_rx.c
@@ -93,13 +93,26 @@
struct msm_hdmi_audio_codec_rx_data *codec_data =
dev_get_drvdata(dai->codec->dev);
+ /*refer to HDMI spec CEA-861-E: Table 28 Audio InfoFrame Data Byte 4*/
switch (num_channels) {
case 2:
channel_allocation = 0;
break;
+ case 3:
+ channel_allocation = 0x02;//default to FL/FR/FC
+ break;
+ case 4:
+ channel_allocation = 0x06;//default to FL/FR/FC/RC
+ break;
+ case 5:
+ channel_allocation = 0x0A;//default to FL/FR/FC/RR/RL
+ break;
case 6:
channel_allocation = 0x0B;
break;
+ case 7:
+ channel_allocation = 0x12;//default to FL/FR/FC/RL/RR/RRC/RLC
+ break;
case 8:
channel_allocation = 0x13;
break;
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index caae9c6..6de310a 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -42,6 +42,8 @@
#define TAPAN_HPH_PA_SETTLE_COMP_ON 3000
#define TAPAN_HPH_PA_SETTLE_COMP_OFF 13000
+#define DAPM_MICBIAS2_EXTERNAL_STANDALONE "MIC BIAS2 External Standalone"
+
#define TAPAN_VDD_CX_OPTIMAL_UA 10000
#define TAPAN_VDD_CX_SLEEP_UA 2000
@@ -281,6 +283,8 @@
s32 dmic_1_2_clk_cnt;
s32 dmic_3_4_clk_cnt;
s32 dmic_5_6_clk_cnt;
+ s32 ldo_h_users;
+ s32 micb_2_users;
u32 anc_slot;
bool anc_func;
@@ -2146,38 +2150,37 @@
{
struct snd_soc_codec *codec = w->codec;
struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
- u16 micb_int_reg;
+ u16 micb_int_reg = 0, micb_ctl_reg = 0;
u8 cfilt_sel_val = 0;
char *internal1_text = "Internal1";
char *internal2_text = "Internal2";
char *internal3_text = "Internal3";
enum wcd9xxx_notify_event e_post_off, e_pre_on, e_post_on;
- dev_dbg(codec->dev, "%s %d\n", __func__, event);
- switch (w->reg) {
- case TAPAN_A_MICB_1_CTL:
+ pr_debug("%s: w->name %s event %d\n", __func__, w->name, event);
+ if (strnstr(w->name, "MIC BIAS1", sizeof("MIC BIAS1"))) {
+ micb_ctl_reg = TAPAN_A_MICB_1_CTL;
micb_int_reg = TAPAN_A_MICB_1_INT_RBIAS;
cfilt_sel_val = tapan->resmgr.pdata->micbias.bias1_cfilt_sel;
e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_1_ON;
e_post_on = WCD9XXX_EVENT_POST_MICBIAS_1_ON;
e_post_off = WCD9XXX_EVENT_POST_MICBIAS_1_OFF;
- break;
- case TAPAN_A_MICB_2_CTL:
+ } else if (strnstr(w->name, "MIC BIAS2", sizeof("MIC BIAS2"))) {
+ micb_ctl_reg = TAPAN_A_MICB_2_CTL;
micb_int_reg = TAPAN_A_MICB_2_INT_RBIAS;
cfilt_sel_val = tapan->resmgr.pdata->micbias.bias2_cfilt_sel;
e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_2_ON;
e_post_on = WCD9XXX_EVENT_POST_MICBIAS_2_ON;
e_post_off = WCD9XXX_EVENT_POST_MICBIAS_2_OFF;
- break;
- case TAPAN_A_MICB_3_CTL:
+ } else if (strnstr(w->name, "MIC BIAS3", sizeof("MIC BIAS3"))) {
+ micb_ctl_reg = TAPAN_A_MICB_3_CTL;
micb_int_reg = TAPAN_A_MICB_3_INT_RBIAS;
cfilt_sel_val = tapan->resmgr.pdata->micbias.bias3_cfilt_sel;
e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_3_ON;
e_post_on = WCD9XXX_EVENT_POST_MICBIAS_3_ON;
e_post_off = WCD9XXX_EVENT_POST_MICBIAS_3_OFF;
- break;
- default:
- pr_err("%s: Error, invalid micbias register\n", __func__);
+ } else {
+ pr_err("%s: Error, invalid micbias %s\n", __func__, w->name);
return -EINVAL;
}
@@ -2196,6 +2199,20 @@
else if (strnstr(w->name, internal3_text, 30))
snd_soc_update_bits(codec, micb_int_reg, 0x3, 0x3);
+ if (micb_ctl_reg == TAPAN_A_MICB_2_CTL) {
+ if (++tapan->micb_2_users == 1)
+ wcd9xxx_resmgr_add_cond_update_bits(
+ &tapan->resmgr,
+ WCD9XXX_COND_HPH_MIC,
+ micb_ctl_reg, w->shift,
+ false);
+ pr_debug("%s: micb_2_users %d\n", __func__,
+ tapan->micb_2_users);
+ } else
+ snd_soc_update_bits(codec, micb_ctl_reg, 1 << w->shift,
+ 1 << w->shift);
+
+
break;
case SND_SOC_DAPM_POST_PMU:
usleep_range(20000, 20000);
@@ -2203,6 +2220,22 @@
wcd9xxx_resmgr_notifier_call(&tapan->resmgr, e_post_on);
break;
case SND_SOC_DAPM_POST_PMD:
+ if (micb_ctl_reg == TAPAN_A_MICB_2_CTL) {
+ if (--tapan->micb_2_users == 0)
+ wcd9xxx_resmgr_rm_cond_update_bits(
+ &tapan->resmgr,
+ WCD9XXX_COND_HPH_MIC,
+ micb_ctl_reg, 7,
+ false);
+ pr_debug("%s: micb_2_users %d\n", __func__,
+ tapan->micb_2_users);
+ WARN(tapan->micb_2_users < 0,
+ "Unexpected micbias users %d\n",
+ tapan->micb_2_users);
+ } else
+ snd_soc_update_bits(codec, micb_ctl_reg, 1 << w->shift,
+ 0);
+
/* Let MBHC module know so micbias switch to be off */
wcd9xxx_resmgr_notifier_call(&tapan->resmgr, e_post_off);
@@ -2221,6 +2254,23 @@
return 0;
}
+/* called under codec_resource_lock acquisition */
+static int tapan_enable_mbhc_micbias(struct snd_soc_codec *codec, bool enable)
+{
+ int rc;
+
+ if (enable)
+ rc = snd_soc_dapm_force_enable_pin(&codec->dapm,
+ DAPM_MICBIAS2_EXTERNAL_STANDALONE);
+ else
+ rc = snd_soc_dapm_disable_pin(&codec->dapm,
+ DAPM_MICBIAS2_EXTERNAL_STANDALONE);
+ if (!rc)
+ snd_soc_dapm_sync(&codec->dapm);
+ pr_debug("%s: leave ret %d\n", __func__, rc);
+ return rc;
+}
+
static void tx_hpf_corner_freq_callback(struct work_struct *work)
{
struct delayed_work *hpf_delayed_work;
@@ -2435,16 +2485,66 @@
return 0;
}
+/* called under codec_resource_lock acquisition */
+static int __tapan_codec_enable_ldo_h(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct tapan_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+ pr_debug("%s: enter\n", __func__);
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /*
+ * ldo_h_users is protected by codec->mutex, don't need
+ * additional mutex
+ */
+ if (++priv->ldo_h_users == 1) {
+ WCD9XXX_BG_CLK_LOCK(&priv->resmgr);
+ wcd9xxx_resmgr_get_bandgap(&priv->resmgr,
+ WCD9XXX_BANDGAP_AUDIO_MODE);
+ wcd9xxx_resmgr_get_clk_block(&priv->resmgr,
+ WCD9XXX_CLK_RCO);
+ snd_soc_update_bits(codec, TAPAN_A_LDO_H_MODE_1, 1 << 7,
+ 1 << 7);
+ wcd9xxx_resmgr_put_clk_block(&priv->resmgr,
+ WCD9XXX_CLK_RCO);
+ WCD9XXX_BG_CLK_UNLOCK(&priv->resmgr);
+ pr_debug("%s: ldo_h_users %d\n", __func__,
+ priv->ldo_h_users);
+ /* LDO enable requires 1ms to settle down */
+ usleep_range(1000, 1010);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ if (--priv->ldo_h_users == 0) {
+ WCD9XXX_BG_CLK_LOCK(&priv->resmgr);
+ wcd9xxx_resmgr_get_clk_block(&priv->resmgr,
+ WCD9XXX_CLK_RCO);
+ snd_soc_update_bits(codec, TAPAN_A_LDO_H_MODE_1, 1 << 7,
+ 0);
+ wcd9xxx_resmgr_put_clk_block(&priv->resmgr,
+ WCD9XXX_CLK_RCO);
+ wcd9xxx_resmgr_put_bandgap(&priv->resmgr,
+ WCD9XXX_BANDGAP_AUDIO_MODE);
+ WCD9XXX_BG_CLK_UNLOCK(&priv->resmgr);
+ pr_debug("%s: ldo_h_users %d\n", __func__,
+ priv->ldo_h_users);
+ }
+ WARN(priv->ldo_h_users < 0, "Unexpected ldo_h users %d\n",
+ priv->ldo_h_users);
+ break;
+ }
+ pr_debug("%s: leave\n", __func__);
+ return 0;
+}
+
static int tapan_codec_enable_ldo_h(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
- switch (event) {
- case SND_SOC_DAPM_POST_PMU:
- case SND_SOC_DAPM_POST_PMD:
- usleep_range(1000, 1000);
- break;
- }
- return 0;
+ int rc;
+ rc = __tapan_codec_enable_ldo_h(w, kcontrol, event);
+ return rc;
}
static int tapan_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
@@ -3017,6 +3117,7 @@
{"MIC BIAS2 Internal2", NULL, "LDO_H"},
{"MIC BIAS2 Internal3", NULL, "LDO_H"},
{"MIC BIAS2 External", NULL, "LDO_H"},
+ {DAPM_MICBIAS2_EXTERNAL_STANDALONE, NULL, "LDO_H Standalone"},
};
static const struct snd_soc_dapm_route wcd9302_map[] = {
@@ -4233,13 +4334,13 @@
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", TAPAN_A_MICB_3_CTL, 7, 0,
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", SND_SOC_NOPM, 7, 0,
tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", TAPAN_A_MICB_3_CTL, 7, 0,
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", SND_SOC_NOPM, 7, 0,
tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", TAPAN_A_MICB_3_CTL, 7, 0,
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", SND_SOC_NOPM, 7, 0,
tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
@@ -4462,17 +4563,27 @@
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_SUPPLY("LDO_H", TAPAN_A_LDO_H_MODE_1, 7, 0,
- tapan_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_SUPPLY("LDO_H", SND_SOC_NOPM, 7, 0,
+ tapan_codec_enable_ldo_h,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /*
+ * DAPM 'LDO_H Standalone' is to be powered by mbhc driver after
+ * acquring codec_resource lock.
+ * So call __tapan_codec_enable_ldo_h instead and avoid deadlock.
+ */
+ SND_SOC_DAPM_SUPPLY("LDO_H Standalone", SND_SOC_NOPM, 7, 0,
+ __tapan_codec_enable_ldo_h,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_INPUT("AMIC1"),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TAPAN_A_MICB_1_CTL, 7, 0,
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", SND_SOC_NOPM, 7, 0,
tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", TAPAN_A_MICB_1_CTL, 7, 0,
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", SND_SOC_NOPM, 7, 0,
tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", TAPAN_A_MICB_1_CTL, 7, 0,
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", SND_SOC_NOPM, 7, 0,
tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
@@ -4494,19 +4605,24 @@
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_INPUT("AMIC2"),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", TAPAN_A_MICB_2_CTL, 7, 0,
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", SND_SOC_NOPM, 7, 0,
tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", TAPAN_A_MICB_2_CTL, 7, 0,
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", SND_SOC_NOPM, 7, 0,
tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", TAPAN_A_MICB_2_CTL, 7, 0,
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", SND_SOC_NOPM, 7, 0,
tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", TAPAN_A_MICB_2_CTL, 7, 0,
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", SND_SOC_NOPM, 7, 0,
tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS2_EXTERNAL_STANDALONE, SND_SOC_NOPM,
+ 7, 0, tapan_codec_enable_micbias,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
SND_SOC_DAPM_AIF_OUT_E("AIF1 CAP", "AIF1 Capture", 0, SND_SOC_NOPM,
AIF1_CAP, 0, tapan_codec_enable_slimtx,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
@@ -5504,7 +5620,8 @@
else
rco_clk_rate = TAPAN_MCLK_CLK_9P6MHZ;
- ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, NULL,
+ ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec,
+ tapan_enable_mbhc_micbias,
&mbhc_cb, &cdc_intr_ids, rco_clk_rate,
TAPAN_CDC_ZDET_SUPPORTED);
if (ret)
@@ -5711,7 +5828,8 @@
else
rco_clk_rate = TAPAN_MCLK_CLK_9P6MHZ;
- ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, NULL,
+ ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec,
+ tapan_enable_mbhc_micbias,
&mbhc_cb, &cdc_intr_ids, rco_clk_rate,
TAPAN_CDC_ZDET_SUPPORTED);
@@ -5729,6 +5847,8 @@
tapan->aux_pga_cnt = 0;
tapan->aux_l_gain = 0x1F;
tapan->aux_r_gain = 0x1F;
+ tapan->ldo_h_users = 0;
+ tapan->micb_2_users = 0;
tapan_update_reg_defaults(codec);
tapan_update_reg_mclk_rate(wcd9xxx);
tapan_codec_init_reg(codec);
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index 61ae859..28d4c84 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -3746,6 +3746,7 @@
gain = wcd9xxx_mbhc_cal_btn_det_mp(btn_det, MBHC_BTN_DET_GAIN);
snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B2_CTL, 0x78,
gain[idx] << 3);
+ snd_soc_update_bits(codec, WCD9XXX_A_MICB_2_MBHC, 0x04, 0x04);
pr_debug("%s: leave\n", __func__);
}
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
index 0cf044c..9de15d9 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
@@ -129,13 +129,26 @@
break;
}
+ /*refer to HDMI spec CEA-861-E: Table 28 Audio InfoFrame Data Byte 4*/
switch (dai_data->channels) {
case 2:
dai_data->port_config.hdmi_multi_ch.channel_allocation = 0;
break;
+ case 3:
+ dai_data->port_config.hdmi_multi_ch.channel_allocation = 0x02;
+ break;
+ case 4:
+ dai_data->port_config.hdmi_multi_ch.channel_allocation = 0x06;
+ break;
+ case 5:
+ dai_data->port_config.hdmi_multi_ch.channel_allocation = 0x0A;
+ break;
case 6:
dai_data->port_config.hdmi_multi_ch.channel_allocation = 0x0B;
break;
+ case 7:
+ dai_data->port_config.hdmi_multi_ch.channel_allocation = 0x12;
+ break;
case 8:
dai_data->port_config.hdmi_multi_ch.channel_allocation = 0x13;
break;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 121c2ea..8a9a877 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -3354,6 +3354,9 @@
{"QUAT_MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
{"QUAT_MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
{"QUAT_MI2S_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+ {"QUAT_MI2S_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
+ {"QUAT_MI2S_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
+ {"QUAT_MI2S_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
{"QUAT_MI2S_RX", NULL, "QUAT_MI2S_RX Audio Mixer"},
{"TERT_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index 3ee6f6e..6cb7ce1 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -1160,10 +1160,10 @@
} else if (channel_mode == 6) {
open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
- open.dev_channel_mapping[2] = PCM_CHANNEL_FC;
- open.dev_channel_mapping[3] = PCM_CHANNEL_LFE;
- open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
- open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
+ open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+ open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
+ open.dev_channel_mapping[4] = PCM_CHANNEL_LS;
+ open.dev_channel_mapping[5] = PCM_CHANNEL_RS;
} else if (channel_mode == 8) {
open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
@@ -1171,8 +1171,8 @@
open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
- open.dev_channel_mapping[6] = PCM_CHANNEL_RLC;
- open.dev_channel_mapping[7] = PCM_CHANNEL_RRC;
+ open.dev_channel_mapping[6] = PCM_CHANNEL_FLC;
+ open.dev_channel_mapping[7] = PCM_CHANNEL_FRC;
} else {
pr_err("%s invalid num_chan %d\n", __func__,
channel_mode);
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index d9353c2..95114e0 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -2276,21 +2276,21 @@
lchannel_mapping[3] = PCM_CHANNEL_LB;
lchannel_mapping[4] = PCM_CHANNEL_RB;
} else if (channels == 6) {
- lchannel_mapping[0] = PCM_CHANNEL_FC;
- lchannel_mapping[1] = PCM_CHANNEL_FL;
- lchannel_mapping[2] = PCM_CHANNEL_FR;
- lchannel_mapping[3] = PCM_CHANNEL_LB;
- lchannel_mapping[4] = PCM_CHANNEL_RB;
- lchannel_mapping[5] = PCM_CHANNEL_LFE;
+ lchannel_mapping[0] = PCM_CHANNEL_FL;
+ lchannel_mapping[1] = PCM_CHANNEL_FR;
+ lchannel_mapping[2] = PCM_CHANNEL_FC;
+ lchannel_mapping[3] = PCM_CHANNEL_LFE;
+ lchannel_mapping[4] = PCM_CHANNEL_LS;
+ lchannel_mapping[5] = PCM_CHANNEL_RS;
} else if (channels == 8) {
lchannel_mapping[0] = PCM_CHANNEL_FL;
lchannel_mapping[1] = PCM_CHANNEL_FR;
- lchannel_mapping[2] = PCM_CHANNEL_LFE;
- lchannel_mapping[3] = PCM_CHANNEL_FC;
+ lchannel_mapping[2] = PCM_CHANNEL_FC;
+ lchannel_mapping[3] = PCM_CHANNEL_LFE;
lchannel_mapping[4] = PCM_CHANNEL_LB;
lchannel_mapping[5] = PCM_CHANNEL_RB;
- lchannel_mapping[6] = PCM_CHANNEL_RLC;
- lchannel_mapping[7] = PCM_CHANNEL_RRC;
+ lchannel_mapping[6] = PCM_CHANNEL_FLC;
+ lchannel_mapping[7] = PCM_CHANNEL_FRC;
} else {
pr_err("%s: ERROR.unsupported num_ch = %u\n",
__func__, channels);