Merge "Merge commit '8df48570' into msm-4.9 - PC 226"
diff --git a/Documentation/devicetree/bindings/arm/msm/hidqvr-smp2p.txt b/Documentation/devicetree/bindings/arm/msm/hidqvr-smp2p.txt
new file mode 100644
index 0000000..32f1d16
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/hidqvr-smp2p.txt
@@ -0,0 +1,39 @@
+Qualcomm Technologies, Inc. HID QVR (hid-qvr) driver
+
+Required properties:
+-compatible :
+ To communicate with cdsp
+ qcom,smp2pgpio-qvrexternal-5-out (outbound)
+ qcom,smp2pgpio-qvrexternal-5-in (inbound)
+
+Example:
+ smp2pgpio_qvrexternal_5_out: qcom,smp2pgpio-qvrexternal-5-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "qvrexternal";
+ qcom,remote-pid = <5>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ smp2pgpio_qvrexternal_5_in: qcom,smp2pgpio-qvrexternal-5-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "qvrexternal";
+ qcom,remote-pid = <5>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_client_qvrexternal_5_out {
+ compatible = "qcom,smp2pgpio_client_qvrexternal_5_out";
+ gpios = <&smp2pgpio_qvrexternal_5_out 0 0>;
+ };
+
+ qcom,smp2pgpio_client_qvrexternal_5_in {
+ compatible = "qcom,smp2pgpio_client_qvrexternal_5_in";
+ gpios = <&smp2pgpio_qvrexternal_5_in 0 0>;
+ }
\ No newline at end of file
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts
index a383f3e..de5922c 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts
@@ -25,6 +25,14 @@
status = "okay";
};
+&qseecom_mem {
+ status = "okay";
+};
+
+&qseecom_ta_mem {
+ status = "okay";
+};
+
&blsp1_uart2b_hs {
status = "okay";
};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
index 7be23ee..1b1c430 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
@@ -85,14 +85,16 @@
compatible = "shared-dma-pool";
reusable;
alignment = <0x400000>;
- size = <0x1400000>;
+ size = <0x400000>;
+ status = "disabled";
};
qseecom_ta_mem: qseecom_ta_region@0 {
compatible = "shared-dma-pool";
reusable;
alignment = <0x400000>;
- size = <0x1000000>;
+ size = <0x400000>;
+ status = "disabled";
};
};
diff --git a/arch/arm/configs/msm8909w-perf_defconfig b/arch/arm/configs/msm8909w-perf_defconfig
index 6ef7915..27878b6 100644
--- a/arch/arm/configs/msm8909w-perf_defconfig
+++ b/arch/arm/configs/msm8909w-perf_defconfig
@@ -241,6 +241,7 @@
CONFIG_DM_ANDROID_VERITY_AT_MOST_ONCE_DEFAULT_ENABLED=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
+CONFIG_IFB=y
CONFIG_TUN=y
CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
diff --git a/arch/arm/configs/msm8909w_defconfig b/arch/arm/configs/msm8909w_defconfig
index 986a65c..eab8410d 100644
--- a/arch/arm/configs/msm8909w_defconfig
+++ b/arch/arm/configs/msm8909w_defconfig
@@ -230,6 +230,7 @@
CONFIG_DM_ANDROID_VERITY_AT_MOST_ONCE_DEFAULT_ENABLED=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
+CONFIG_IFB=y
CONFIG_TUN=y
CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
diff --git a/arch/arm64/boot/dts/qcom/msm-qvr-external.dtsi b/arch/arm64/boot/dts/qcom/msm-qvr-external.dtsi
new file mode 100644
index 0000000..3b3fc58
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm-qvr-external.dtsi
@@ -0,0 +1,44 @@
+/* Copyright (c) 2018, 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.
+ */
+
+&soc {
+ smp2pgpio_qvrexternal_5_in: qcom,smp2pgpio-qvrexternal-5-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "qvrexternal";
+ qcom,remote-pid = <5>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_client_qvrexternal_5_in {
+ compatible = "qcom,smp2pgpio_client_qvrexternal_5_in";
+ gpios = <&smp2pgpio_qvrexternal_5_in 0 0>;
+ };
+
+ smp2pgpio_qvrexternal_5_out: qcom,smp2pgpio-qvrexternal-5-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "qvrexternal";
+ qcom,remote-pid = <5>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_client_qvrexternal_5_out {
+ compatible = "qcom,smp2pgpio_client_qvrexternal_5_out";
+ gpios = <&smp2pgpio_qvrexternal_5_out 0 0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1130.dtsi b/arch/arm64/boot/dts/qcom/sxr1130.dtsi
index 75707b1..bfab826 100644
--- a/arch/arm64/boot/dts/qcom/sxr1130.dtsi
+++ b/arch/arm64/boot/dts/qcom/sxr1130.dtsi
@@ -12,6 +12,7 @@
*/
#include "qcs605.dtsi"
+#include "msm-qvr-external.dtsi"
/ {
model = "Qualcomm Technologies, Inc. SXR1130";
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index 9e251da..dbc94a1 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -5219,13 +5219,13 @@
mutex_lock(&display->display_lock);
+ if (display->modes)
+ goto exit;
+
rc = dsi_display_get_mode_count_no_lock(display, &total_mode_count);
if (rc)
goto error;
- /* free any previously probed modes */
- kfree(display->modes);
-
display->modes = kcalloc(total_mode_count, sizeof(*display->modes),
GFP_KERNEL);
if (!display->modes) {
@@ -5304,6 +5304,7 @@
}
}
+exit:
*out_modes = display->modes;
rc = 0;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
index 250314b..1278d59 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
@@ -602,14 +602,20 @@
{
struct drm_display_mode *drm_mode;
struct dsi_display_mode dsi_mode;
+ struct dsi_display *dsi_display;
if (!connector || !display)
return;
- list_for_each_entry(drm_mode, &connector->modes, head) {
+ list_for_each_entry(drm_mode, &connector->modes, head) {
convert_to_dsi_mode(drm_mode, &dsi_mode);
dsi_display_put_mode(display, &dsi_mode);
}
+
+ /* free the display structure modes also */
+ dsi_display = display;
+ kfree(dsi_display->modes);
+ dsi_display->modes = NULL;
}
int dsi_connector_get_modes(struct drm_connector *connector,
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 8eed456..9deed4f 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -966,6 +966,13 @@
Say Y here if you have a Alps touchpads over i2c-hid or usbhid
and want support for its special functionalities.
+config HID_QVR
+ tristate "QVR support"
+ depends on HID
+ ---help---
+ Say 'Y' or 'M' if you want to connect an external device to
+ stream IMU data for QVR support.
+
endmenu
endif # HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 86b2b57..5bcb6d2 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -78,6 +78,7 @@
obj-$(CONFIG_HID_PLANTRONICS) += hid-plantronics.o
obj-$(CONFIG_HID_PRIMAX) += hid-primax.o
+obj-$(CONFIG_HID_QVR) += hid-qvr.o
obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \
hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
hid-roccat-koneplus.o hid-roccat-konepure.o hid-roccat-kovaplus.o \
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index aea6267..350f2ba 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -2018,6 +2018,9 @@
{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
+#if IS_ENABLED(CONFIG_HID_QVR)
+ { HID_USB_DEVICE(USB_VENDOR_ID_QVR5, USB_DEVICE_ID_QVR5) },
+#endif
{ HID_USB_DEVICE(USB_VENDOR_ID_RISO_KAGAKU, USB_DEVICE_ID_RI_KA_WEBMAIL) },
#if IS_ENABLED(CONFIG_HID_ROCCAT)
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 9347b37..95934a8 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -1125,4 +1125,7 @@
#define USB_VENDOR_ID_UGTIZER 0x2179
#define USB_DEVICE_ID_UGTIZER_TABLET_GP0610 0x0053
+#define USB_VENDOR_ID_QVR5 0x045e
+#define USB_DEVICE_ID_QVR5 0x0659
+
#endif
diff --git a/drivers/hid/hid-qvr.c b/drivers/hid/hid-qvr.c
new file mode 100644
index 0000000..019dbaf
--- /dev/null
+++ b/drivers/hid/hid-qvr.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 2018, 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/kobject.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/msm_ion.h>
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/hiddev.h>
+#include <linux/hid-debug.h>
+#include <linux/hidraw.h>
+#include <linux/device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
+#include <linux/gpio.h>
+#include <linux/timekeeping.h>
+#include <linux/ion.h>
+#include "../soc/qcom/smp2p_private.h"
+#include "hid-ids.h"
+#include "hid-qvr.h"
+
+static struct ion_handle *handle;
+static struct ion_client *client;
+static void *vaddr;
+static size_t vsize;
+static uint64_t ts_base;
+static uint64_t ts_offset;
+static int msg_size = 368;
+
+struct gpio_info {
+ int gpio_base_id;
+ int irq_base_id;
+};
+
+
+/* GPIO Inbound/Outbound callback info */
+struct gpio_inout {
+ struct gpio_info in;
+ struct gpio_info out;
+};
+
+static struct gpio_inout gpio_info[SMP2P_NUM_PROCS];
+static struct gpio_info *in_gpio_info_ptr;
+static struct gpio_info *out_gpio_info_ptr;
+
+
+static struct hid_driver qvr_external_sensor_driver;
+static int fd;
+
+
+struct ion_handle {
+ struct kref ref;
+ unsigned int user_ref_count;
+ struct ion_client *client;
+ struct ion_buffer *buffer;
+ struct rb_node node;
+ unsigned int kmap_cnt;
+ int id;
+};
+
+struct qvr_buf_index {
+ int most_recent_index;
+ uint8_t padding[60];
+};
+
+struct qvr_sensor_t {
+ uint64_t gts;
+ uint64_t ats;
+ uint64_t mts;
+ s32 gx;
+ s32 gy;
+ s32 gz;
+ s32 ax;
+ s32 ay;
+ s32 az;
+ s32 mx;
+ s32 my;
+ s32 mz;
+ uint8_t padding[4];
+};
+
+
+int qvr_send_package_wrap(u8 *message, int msize, struct hid_device *hid)
+{
+ struct qvr_sensor_t *sensor_buf;
+ struct qvr_sensor_t *data;
+ static int buf_index;
+ struct external_imu_format imuData = { 0 };
+ struct qvr_buf_index *index_buf;
+
+ /*
+ * Actual message size is 369 bytes
+ * to make it 8 byte aligned we created a structure of size 368 bytes.
+ * Ignoring the first byte 'report id' (which is always 1)
+ *
+ */
+ memcpy((void *)&imuData, (void *)message + 1, msg_size);
+
+ if (!ts_base)
+ ts_base = ktime_to_ns(ktime_get_boottime());
+ if (!ts_offset)
+ ts_offset = imuData.gts0;
+ index_buf = (struct qvr_buf_index *)
+ ((uintptr_t)vaddr + (vsize / 2) + (8 * sizeof(*sensor_buf)));
+ sensor_buf = (struct qvr_sensor_t *)((uintptr_t)vaddr + (vsize / 2));
+
+ data = (struct qvr_sensor_t *)&(sensor_buf[buf_index]);
+ if (ts_offset > imuData.gts0)
+ data->ats = ts_base + ((ts_offset - imuData.gts0) * 100);
+ else
+ data->ats = ts_base + ((imuData.gts0 - ts_offset) * 100);
+ if (imuData.mts0 == 0)
+ data->mts = 0;
+ else
+ data->mts = data->ats;
+ data->gts = data->ats;
+ data->ax = -imuData.ax0;
+ data->ay = imuData.ay0;
+ data->az = -imuData.az0;
+ data->gx = -imuData.gx0;
+ data->gy = imuData.gy0;
+ data->gz = -imuData.gz0;
+ data->mx = -imuData.mx0;
+ data->my = imuData.my0;
+ data->mz = -imuData.mz0;
+
+ pr_debug("%s: gts= %llu, gx= %d, gy=%d, gz=%d", __func__,
+ data->gts, data->gx, data->gy, data->gz);
+ pr_debug("%s: ats= %llu, ax= %d, ay=%d, az=%d", __func__,
+ data->ats, data->ax, data->ay, data->az);
+ pr_debug("%s: mts= %llu, mx= %d, my=%d, mz=%d", __func__,
+ data->mts, data->mx, data->my, data->mz);
+
+ index_buf->most_recent_index = buf_index;
+ buf_index = (buf_index == (8 - 1)) ? 0 : buf_index + 1;
+ return 0;
+}
+
+static int register_smp2p(char *node_name, struct gpio_info *gpio_info_ptr)
+{
+ struct device_node *node = NULL;
+ int cnt = 0;
+ int id = 0;
+
+ node = of_find_compatible_node(NULL, NULL, node_name);
+ if (node) {
+ cnt = of_gpio_count(node);
+ if (cnt && gpio_info_ptr) {
+ id = of_get_gpio(node, 0);
+ if (id == -EPROBE_DEFER)
+ return id;
+ gpio_info_ptr->gpio_base_id = id;
+ gpio_info_ptr->irq_base_id = gpio_to_irq(id);
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+
+
+static int kernel_map_gyro_buffer(int fd)
+{
+ handle = ion_import_dma_buf_fd(client, fd);
+ if (IS_ERR(handle)) {
+ pr_err("%s: ion_import_dma_buf_fd failed\n", __func__);
+ return -EINVAL;
+ }
+
+ if (ion_handle_get_size(client, handle, &vsize)) {
+ pr_err("%s: Could not dma buf %d size\n", __func__, fd);
+ return -EINVAL;
+ }
+
+ vaddr = ion_map_kernel(client, handle);
+ if (IS_ERR_OR_NULL(vaddr)) {
+ ion_free(client, handle);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+static void kernel_unmap_gyro_buffer(void)
+{
+ if (!IS_ERR_OR_NULL(vaddr)) {
+ ion_unmap_kernel(client, handle);
+ ion_free(client, handle);
+ vaddr = NULL;
+ }
+}
+
+static ssize_t fd_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, 16, "%d\n", fd);
+}
+
+static ssize_t fd_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = kstrtoint(buf, 10, &fd);
+ if (ret < 0)
+ return ret;
+ if (fd == -1)
+ kernel_unmap_gyro_buffer();
+ else
+ kernel_map_gyro_buffer(fd);
+ ts_base = 0;
+ ts_offset = 0;
+
+ return count;
+}
+
+static ssize_t ts_base_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, 16, "%lld\n", ts_base);
+}
+
+static ssize_t ts_base_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ return 0;
+}
+
+static ssize_t ts_offset_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, 16, "%lld\n", ts_offset * 100);
+}
+
+static ssize_t ts_offset_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ return 0;
+}
+
+static struct kobj_attribute fd_attribute = __ATTR(fd, 0664,
+ fd_show,
+ fd_store);
+static struct kobj_attribute ts_base_attribute = __ATTR(ts_base, 0664,
+ ts_base_show,
+ ts_base_store);
+static struct kobj_attribute ts_offset_attribute = __ATTR(ts_offset, 0664,
+ ts_offset_show,
+ ts_offset_store);
+
+static struct attribute *attrs[] = {
+ &fd_attribute.attr,
+ &ts_base_attribute.attr,
+ &ts_offset_attribute.attr,
+ NULL,
+};
+
+static struct attribute_group attr_group = {
+ .attrs = attrs,
+};
+
+static struct kobject *qvr_external_sensor_kobj;
+
+static int qvr_external_sensor_probe(struct hid_device *hdev,
+ const struct hid_device_id *id)
+{
+ int ret;
+ char *in_node_name = "qcom,smp2pgpio_client_qvrexternal_5_in";
+ char *out_node_name = "qcom,smp2pgpio_client_qvrexternal_5_out";
+ __u8 hid_buf[255] = { 0 };
+ size_t hid_count = 64;
+
+ ret = register_smp2p(in_node_name, in_gpio_info_ptr);
+ if (ret) {
+ pr_err("%s: register_smp2p failed", __func__);
+ goto err_free;
+ }
+ ret = register_smp2p(out_node_name, out_gpio_info_ptr);
+ if (ret) {
+ pr_err("%s: register_smp2p failed", __func__);
+ goto err_free;
+ }
+ ret = hid_open_report(hdev);
+ if (ret) {
+ pr_err("%s: hid_open_report failed", __func__);
+ goto err_free;
+ }
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ if (ret) {
+ pr_err("%s: hid_hw_start failed", __func__);
+ goto err_free;
+ }
+ if (hdev->vendor == USB_VENDOR_ID_QVR5) {
+ hid_buf[0] = 2;
+ hid_buf[1] = 7;
+ ret = hid_hw_raw_request(hdev, hid_buf[0],
+ hid_buf,
+ hid_count,
+ HID_FEATURE_REPORT,
+ HID_REQ_SET_REPORT);
+ }
+ return 0;
+err_free:
+ return ret;
+
+}
+
+static int qvr_external_sensor_raw_event(struct hid_device *hid,
+ struct hid_report *report,
+ u8 *data, int size)
+{
+ int val;
+ int ret = -1;
+
+ if ((hid->vendor == USB_VENDOR_ID_QVR5) && (vaddr != NULL)) {
+ ret = qvr_send_package_wrap(data/*hid_value*/, size, hid);
+ if (ret != 0) {
+ pr_err("%s: qvr_send_package_wrap failed", __func__);
+ return ret;
+ }
+ val = 1 ^ gpio_get_value(out_gpio_info_ptr->gpio_base_id + 0);
+ gpio_set_value(out_gpio_info_ptr->gpio_base_id + 0, val);
+ ret = -1;
+ }
+ return ret;
+}
+
+static void qvr_external_sensor_device_remove(struct hid_device *hdev)
+{
+ hid_hw_stop(hdev);
+}
+
+static struct hid_device_id qvr_external_sensor_table[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_QVR5, USB_DEVICE_ID_QVR5) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, qvr_external_sensor_table);
+
+static struct hid_driver qvr_external_sensor_driver = {
+ .name = "qvr_external_sensor",
+ .id_table = qvr_external_sensor_table,
+ .probe = qvr_external_sensor_probe,
+ .raw_event = qvr_external_sensor_raw_event,
+ .remove = qvr_external_sensor_device_remove,
+};
+
+module_hid_driver(qvr_external_sensor_driver);
+
+static int __init qvr_external_sensor_init(void)
+{
+ const char *device_name = "aoe";
+ int ret = 0;
+
+ in_gpio_info_ptr = &gpio_info[SMP2P_CDSP_PROC].in;
+ in_gpio_info_ptr->gpio_base_id = -1;
+ out_gpio_info_ptr = &gpio_info[SMP2P_CDSP_PROC].out;
+ out_gpio_info_ptr->gpio_base_id = -1;
+
+
+ qvr_external_sensor_kobj =
+ kobject_create_and_add("qvr_external_sensor", kernel_kobj);
+
+ if (!qvr_external_sensor_kobj) {
+ pr_err("%s: kobject_create_and_add() fail\n", __func__);
+ return -ENOMEM;
+ }
+
+ ret = sysfs_create_group(qvr_external_sensor_kobj, &attr_group);
+ if (ret) {
+ pr_err("%s: can't register sysfs\n", __func__);
+ return -ENOMEM;
+ }
+
+ client = msm_ion_client_create(device_name);
+ if (client == NULL) {
+ pr_err("msm_ion_client_create failed in %s", __func__);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static void __exit qvr_external_sensor_exit(void)
+{
+ kobject_put(qvr_external_sensor_kobj);
+}
+
+module_init(qvr_external_sensor_init);
+module_exit(qvr_external_sensor_exit);
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/hid/hid-qvr.h b/drivers/hid/hid-qvr.h
new file mode 100644
index 0000000..3507d07
--- /dev/null
+++ b/drivers/hid/hid-qvr.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2018, 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 HID_QVR_H_FILE
+#define HID_QVR_H_FILE
+
+#define USB_VENDOR_ID_QVR5 0x045e
+#define USB_DEVICE_ID_QVR5 0x0659
+#define QVR_EXTERNAL_SENSOR_REPORT_ID 0x1
+
+struct external_imu_format {
+ s16 temp0;
+ s16 temp1;
+ s16 temp2;
+ s16 temp3;
+ u64 gts0;
+ u64 gts1;
+ u64 gts2;
+ u64 gts3;
+ s16 gx0;
+ s16 gx1;
+ s16 gx2;
+ s16 gx3;
+ s16 gx4;
+ s16 gx5;
+ s16 gx6;
+ s16 gx7;
+ s16 gx8;
+ s16 gx9;
+ s16 gx10;
+ s16 gx11;
+ s16 gx12;
+ s16 gx13;
+ s16 gx14;
+ s16 gx15;
+ s16 gx16;
+ s16 gx17;
+ s16 gx18;
+ s16 gx19;
+ s16 gx20;
+ s16 gx21;
+ s16 gx22;
+ s16 gx23;
+ s16 gx24;
+ s16 gx25;
+ s16 gx26;
+ s16 gx27;
+ s16 gx28;
+ s16 gx29;
+ s16 gx30;
+ s16 gx31;
+ s16 gy0;
+ s16 gy1;
+ s16 gy2;
+ s16 gy3;
+ s16 gy4;
+ s16 gy5;
+ s16 gy6;
+ s16 gy7;
+ s16 gy8;
+ s16 gy9;
+ s16 gy10;
+ s16 gy11;
+ s16 gy12;
+ s16 gy13;
+ s16 gy14;
+ s16 gy15;
+ s16 gy16;
+ s16 gy17;
+ s16 gy18;
+ s16 gy19;
+ s16 gy20;
+ s16 gy21;
+ s16 gy22;
+ s16 gy23;
+ s16 gy24;
+ s16 gy25;
+ s16 gy26;
+ s16 gy27;
+ s16 gy28;
+ s16 gy29;
+ s16 gy30;
+ s16 gy31;
+ s16 gz0;
+ s16 gz1;
+ s16 gz2;
+ s16 gz3;
+ s16 gz4;
+ s16 gz5;
+ s16 gz6;
+ s16 gz7;
+ s16 gz8;
+ s16 gz9;
+ s16 gz10;
+ s16 gz11;
+ s16 gz12;
+ s16 gz13;
+ s16 gz14;
+ s16 gz15;
+ s16 gz16;
+ s16 gz17;
+ s16 gz18;
+ s16 gz19;
+ s16 gz20;
+ s16 gz21;
+ s16 gz22;
+ s16 gz23;
+ s16 gz24;
+ s16 gz25;
+ s16 gz26;
+ s16 gz27;
+ s16 gz28;
+ s16 gz29;
+ s16 gz30;
+ s16 gz31;
+ u64 ats0;
+ u64 ats1;
+ u64 ats2;
+ u64 ats3;
+ s32 ax0;
+ s32 ax1;
+ s32 ax2;
+ s32 ax3;
+ s32 ay0;
+ s32 ay1;
+ s32 ay2;
+ s32 ay3;
+ s32 az0;
+ s32 az1;
+ s32 az2;
+ s32 az3;
+ u64 mts0;
+ u64 mts1;
+ u64 mts2;
+ u64 mts3;
+ s16 mx0;
+ s16 mx1;
+ s16 mx2;
+ s16 mx3;
+ s16 my0;
+ s16 my1;
+ s16 my2;
+ s16 my3;
+ s16 mz0;
+ s16 mz1;
+ s16 mz2;
+ s16 mz3;//368 bytes
+};
+
+int qvr_send_package_wrap(u8 *message, int msize, struct hid_device *hid);
+void qvr_clear_def_parmeter(void);
+void qvr_init(struct hid_device *hdev);
+int qvr_input_init(void);
+void qvr_input_remove(void);
+
+#endif
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 1916f80..8bc8faa 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -170,6 +170,7 @@
{ USB_VENDOR_ID_MULTIPLE_1781, USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_2NES2SNES, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_4NES4SNES, HID_QUIRK_MULTI_INPUT },
+ { USB_VENDOR_ID_QVR5, USB_DEVICE_ID_QVR5, HID_QUIRK_HIDINPUT_FORCE },
{ 0, 0 }
};
diff --git a/drivers/input/misc/vl53l0x/src/vl53l0x_i2c_platform.c b/drivers/input/misc/vl53l0x/src/vl53l0x_i2c_platform.c
index f8633a0..b63f880 100644
--- a/drivers/input/misc/vl53l0x/src/vl53l0x_i2c_platform.c
+++ b/drivers/input/misc/vl53l0x/src/vl53l0x_i2c_platform.c
@@ -147,7 +147,7 @@
int32_t count)
{
int32_t status = STATUS_OK;
- uint8_t *buffer;
+ uint8_t buffer[64];
#ifdef VL_LOG_ENABLE
int32_t i = 0;
@@ -166,7 +166,6 @@
#endif
if ((count + 1) > VL_MAX_I2C_XFER_SIZE)
return STATUS_FAIL;
- buffer = VL_GetLocalBuffer(dev, (count+1));
buffer[0] = index;
memcpy(&buffer[1], pdata, count);
status = VL_I2CWrite(dev, buffer, (count+1));
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index a95917c..74679b2 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -26,7 +26,7 @@
#define VFE32_EQUAL_SLICE_UB 194
#define VFE32_AXI_SLICE_UB 792
#define VFE32_WM_BASE(idx) (0x4C + 0x18 * idx)
-#define VFE32_RDI_BASE(idx) (idx ? 0x734 + 0x4 * (idx - 1) : 0x06FC)
+#define VFE32_RDI_BASE(idx) (idx ? 0x734 + 0x70 * (idx - 1) : 0x06FC)
#define VFE32_XBAR_BASE(idx) (0x40 + 0x4 * (idx / 4))
#define VFE32_XBAR_SHIFT(idx) ((idx % 4) * 8)
#define VFE32_PING_PONG_BASE(wm, ping_pong) \
diff --git a/drivers/media/platform/msm/vidc_3x/venus_hfi.c b/drivers/media/platform/msm/vidc_3x/venus_hfi.c
index c385088..1bd6ae8 100644
--- a/drivers/media/platform/msm/vidc_3x/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc_3x/venus_hfi.c
@@ -3645,6 +3645,12 @@
i < num_responses; ++i) {
struct msm_vidc_cb_info *r = &device->response_pkt[i];
+ if (!__core_in_valid_state(device)) {
+ dprintk(VIDC_ERR,
+ "Ignore responses from %d to %d as device is in invalid state",
+ (i + 1), num_responses);
+ break;
+ }
device->callback(r->response_type, &r->response);
}
diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c
index 0c07bef..4e6aaeb 100644
--- a/drivers/net/wireless/cnss2/pci.c
+++ b/drivers/net/wireless/cnss2/pci.c
@@ -1851,6 +1851,11 @@
cnss_pr_dbg("MHI status cb is called with reason %d\n", reason);
+ if (test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state)) {
+ cnss_pr_dbg("Driver unload is in progress, ignore device error\n");
+ return;
+ }
+
if (pci_priv->driver_ops && pci_priv->driver_ops->update_status)
pci_priv->driver_ops->update_status(pci_priv->pci_dev,
CNSS_FW_DOWN);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
index 2716d4a..ab54767 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
@@ -1073,26 +1073,32 @@
struct ipahal_imm_cmd_pyld *cmd_pyld;
int result = 0;
struct ipa3_nat_mem *nat_ctx = &(ipa3_ctx->nat_mem);
- struct ipa_pdn_entry *pdn_entries = nat_ctx->pdn_mem.base;
+ struct ipa_pdn_entry *pdn_entries = NULL;
IPADBG("\n");
+ mutex_lock(&nat_ctx->dev.lock);
+
if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) {
IPAERR_RL("IPA HW does not support multi PDN\n");
- return -EPERM;
+ result = -EPERM;
+ goto bail;
}
+
if (!nat_ctx->dev.is_mem_allocated) {
IPAERR_RL(
"attempt to modify a PDN entry before the PDN table memory allocation\n");
- return -EPERM;
+ result = -EPERM;
+ goto bail;
}
if (mdfy_pdn->pdn_index > (IPA_MAX_PDN_NUM - 1)) {
IPAERR_RL("pdn index out of range %d\n", mdfy_pdn->pdn_index);
- return -EPERM;
+ result = -EPERM;
+ goto bail;
}
- mutex_lock(&nat_ctx->dev.lock);
+ pdn_entries = nat_ctx->pdn_mem.base;
/* store ip in pdn entries cache array */
pdn_entries[mdfy_pdn->pdn_index].public_ip =
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 703fb24..2e300a3 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -3541,6 +3541,9 @@
hw_device_state(udc->ep0out.qh.dma);
} else {
hw_device_state(0);
+ spin_unlock_irqrestore(udc->lock, flags);
+ _gadget_stop_activity(&udc->gadget);
+ spin_lock_irqsave(udc->lock, flags);
}
spin_unlock_irqrestore(udc->lock, flags);
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index 0065c06..4cd3780 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -1083,9 +1083,11 @@
ipa_resume_work_handler(d_port);
d_port->sm_state = STATE_CONNECTED;
} else if (event == EVT_DISCONNECTED) {
+ usb_gadget_autopm_get(d_port->gadget);
ipa_disconnect_work_handler(d_port);
d_port->sm_state = STATE_INITIALIZED;
log_event_dbg("%s: ST_SUS_EVT_DIS", __func__);
+ usb_gadget_autopm_put_async(d_port->gadget);
}
break;
default: