Snap for 10648389 from 3d019b57c4dfe7b9b8b8a5bf1df69f3bfebcfa36 to android13-msm-pixelwatch-5.15-eos-release

Change-Id: Ic17463cff606451b4a1efd958b7534767443a679
diff --git a/bl_nxp.c b/bl_nxp.c
index b6433d2..de4c94a 100644
--- a/bl_nxp.c
+++ b/bl_nxp.c
@@ -151,29 +151,39 @@
 int nanohub_bl_download_firmware(struct nanohub_data *data,
 				 const uint8_t *buffer, uint32_t size)
 {
-	const uint32_t kSpOffset = 0;
-	const uint32_t kPcOffset = 1;
-	const uint32_t kLoadOffset = 13;
+
+	uint32_t firmware_size = size;
+	uint32_t firmware_offset = 0;
+
+	// Handle signed firmware
 	const uint32_t kSignedOffset = 0x1000;
 	const uint32_t kMagicOffset = 0x400;
 	const uint8_t kMagic[] = { 'C', 'H', 'R', 'E' };
-	uint32_t *firmware;
-	uint32_t ram_addr, stack_ptr, prgm_counter;
-	int ret = 0;
-
-	// Handle signed firmware
-	if (size > kSignedOffset &&
+	if (firmware_size > kSignedOffset &&
 	    memcmp(buffer + kMagicOffset, kMagic, sizeof(kMagic)) == 0) {
-		buffer += kSignedOffset;
-		size -= kSignedOffset;
+		firmware_offset = kSignedOffset;
+		firmware_size -= kSignedOffset;
 	}
 
-	if (size < 64) {
+	if (firmware_size < 64) {
 		pr_err("nanohub: %s invalid size\n", __func__);
 		return -ETOOSMALL;
 	}
 
-	firmware = (uint32_t *)buffer;
+	return nanohub_bl_download_firmware_buffer(
+	    data, buffer + firmware_offset, firmware_size);
+}
+
+int nanohub_bl_download_firmware_buffer(struct nanohub_data *data,
+					const uint8_t *buffer,
+					uint32_t size) {
+	const uint32_t kSpOffset = 0;
+	const uint32_t kPcOffset = 1;
+	const uint32_t kLoadOffset = 13;
+	uint32_t ram_addr, stack_ptr, prgm_counter;
+	uint32_t *firmware = (uint32_t *)buffer;
+	int ret = 0;
+
 	ram_addr = firmware[kLoadOffset];
 	stack_ptr = firmware[kSpOffset];
 	prgm_counter = firmware[kPcOffset];
diff --git a/bl_nxp.h b/bl_nxp.h
index 35b733c..0ecc04c 100644
--- a/bl_nxp.h
+++ b/bl_nxp.h
@@ -46,6 +46,9 @@
 
 int nanohub_bl_download_firmware(struct nanohub_data *, const uint8_t *firmware,
 				uint32_t size);
+int nanohub_bl_download_firmware_buffer(struct nanohub_data *,
+					const uint8_t *firmware,
+					uint32_t size);
 
 #define BL_COMMAND_WRITE_MEMORY		0x04
 #define BL_COMMAND_EXECUTE		0x09
diff --git a/display.c b/display.c
index 481860b..3593e99 100644
--- a/display.c
+++ b/display.c
@@ -13,6 +13,14 @@
  */
 #include "main.h"
 #include "display.h"
+#include "nanohub_exports.h"
+#include <asm-generic/errno.h>
+
+#define NANOHUB_DISPLAY_COMMAND_VERSION 0x01
+
+static DEFINE_MUTEX(nanohub_display_mutex);
+static DECLARE_COMPLETION(message_callback);
+static int display_state;
 
 ssize_t nanohub_pin_display_select_get(struct device *dev,
                                        struct device_attribute *attr, char *buf)
@@ -36,3 +44,59 @@
 	}
 	return count;
 }
+
+ssize_t nanohub_get_display_state(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int display_state = nanohub_query_display_state();
+	return scnprintf(buf, PAGE_SIZE, "%d", display_state);
+}
+
+#define NANOHUB_DISPLAY_COMMAND_TYPE_GET_STATE 0x06
+#define NANOHUB_DISPLAY_GET_STATE_TIMEOUT_MS   100
+
+static void on_message_received(const char *buffer, size_t length)
+{
+	if (length == 3 && buffer[0] == NANOHUB_DISPLAY_COMMAND_VERSION &&
+	    buffer[1] == NANOHUB_DISPLAY_COMMAND_TYPE_GET_STATE) {
+		display_state = buffer[2];
+	}
+	complete(&message_callback);
+}
+
+int nanohub_query_display_state_internal(struct nanohub_data *data)
+{
+	const char message[] = { NANOHUB_DISPLAY_COMMAND_VERSION,
+				 NANOHUB_DISPLAY_COMMAND_TYPE_GET_STATE };
+	long ret;
+	const struct nanohub_platform_data *pdata;
+
+	if (unlikely(data == NULL))
+		return -EINVAL;
+
+	pdata = data->pdata;
+	if (gpio_get_value(pdata->display_select_gpio) == 1)
+		return MCU_DISPLAY_NONE;
+
+	mutex_lock(&nanohub_display_mutex);
+
+	nanohub_register_listener(NANOHUB_DISPLAY_KERNEL_CHANNEL_ID, on_message_received);
+	reinit_completion(&message_callback);
+	display_state = -ENODATA;
+
+	nanohub_send_message(NANOHUB_DISPLAY_CHANNEL_ID, message, sizeof(message));
+
+	ret = wait_for_completion_interruptible_timeout(
+		&message_callback, msecs_to_jiffies(NANOHUB_DISPLAY_GET_STATE_TIMEOUT_MS));
+
+	nanohub_unregister_listener(NANOHUB_DISPLAY_KERNEL_CHANNEL_ID);
+
+	mutex_unlock(&nanohub_display_mutex);
+
+	if (ret < 0)
+		return ret;
+
+	if (ret == 0)
+		return -ETIMEDOUT;
+
+	return display_state;
+}
diff --git a/display.h b/display.h
index 3ca06a7..f48e589 100644
--- a/display.h
+++ b/display.h
@@ -23,4 +23,8 @@
                                        struct device_attribute *attr,
                                        const char *buf, size_t count);
 
+ssize_t nanohub_get_display_state(struct device *dev, struct device_attribute *attr, char *buf);
+
+int nanohub_query_display_state_internal(struct nanohub_data *data);
+
 #endif
diff --git a/main.c b/main.c
index 2f72eef..92ff055 100644
--- a/main.c
+++ b/main.c
@@ -76,6 +76,13 @@
 #define WAKEUP_ERR_CNT		4
 #define BL_MAX_SPEED_HZ		1000000
 
+#define GPIO05_INT_SET_TYPE			0x00008C11
+#define GPIO05_INT_POLARITY_HIGH		0x00008C12
+#define GPIO05_INT_EN_SET 			0x00008C15
+#define GPIO05_INT_EN_CLR 			0x00008C16
+#define GPIO05_INT_MID_SEL 			0x00008C1A
+#define GPIO05_OUTPUT_CTRL 			0x00008C44
+
 /**
  * struct gpio_config - this is a binding between platform data and driver data
  * @label:     for diagnostics
@@ -117,12 +124,14 @@
 static unsigned int nanohub_poll(struct file *, poll_table *);
 static int nanohub_release(struct inode *, struct file *);
 static int nanohub_hw_reset(struct nanohub_data *data, int boot_mode);
+static int nanohub_pmic_irq_config(struct regmap *pmic_regmap);
 
 // Kernel client support.
 static struct nanohub_data *priv_nanohub_data;
 EXPORT_SYMBOL(nanohub_send_message);
 EXPORT_SYMBOL(nanohub_register_listener);
 EXPORT_SYMBOL(nanohub_unregister_listener);
+EXPORT_SYMBOL(nanohub_query_display_state);
 
 static struct class *sensor_class;
 static int major;
@@ -887,6 +896,24 @@
 	return ret;
 }
 
+// Configure PM_GPIO_05 to function as PMIC_IRQ
+static int nanohub_pmic_irq_config(struct regmap *pmic_regmap)
+{
+	int ret;
+	// Command seqeuence provided by QCOM in Case #06209787
+	// GPIO05 kernel write permission enabled by gpar/529000
+	ret = regmap_write(pmic_regmap, GPIO05_INT_SET_TYPE, 0x1);
+	ret |= regmap_write(pmic_regmap, GPIO05_INT_POLARITY_HIGH, 0x1);
+	ret |= regmap_write(pmic_regmap, GPIO05_INT_EN_SET, 0x1);
+	ret |= regmap_write(pmic_regmap, GPIO05_INT_EN_CLR, 0x1);
+	ret |= regmap_write(pmic_regmap, GPIO05_OUTPUT_CTRL, 0x82);
+	if (ret) {
+		pr_warn("nanohob: a PMIC_IRQ write operation failed, ret=%x\n", ret);
+	}
+
+	return ret;
+}
+
 static ssize_t nanohub_try_hw_reset(struct device *dev,
 				struct device_attribute *attr,
 				const char *buf, size_t count)
@@ -1089,7 +1116,8 @@
 	struct nanohub_data *data = dev_get_drvdata(dev);
 	struct firmware_request *fw_request = &data->firmware_request;
 	char *fw_name = fw_request->fw_name;
-	int ret;
+	uint32_t* fw_image_offset = &fw_request->fw_image_offset;
+	int i, ret;
 
 	if (atomic_cmpxchg(&fw_request->state, FW_IDLE, FW_PENDING) !=
 	    FW_IDLE) {
@@ -1108,6 +1136,17 @@
 		fw_name[count - 1] = 0;
 	fw_name[count] = 0;
 
+	// Parse firmware name then firmware image offset which are expected
+	// to be separated by a space. Offset is optional.
+	*fw_image_offset = 0;
+	for (i = 0; i < strlen(fw_name); i++) {
+		if (fw_name[i] == ' ') {
+			ret = kstrtou32(fw_name + i + 1, 10, fw_image_offset);
+			fw_name[i] = 0;
+			break;
+		}
+	}
+
 	atomic_set(&fw_request->state, FW_REQUESTED);
 	nanohub_notify_thread(data);
 	wait_for_completion(&fw_request->fw_complete);
@@ -1130,6 +1169,8 @@
 	int ret;
 
 	pr_info("nanohub: firmware download: %s\n", fw_request->fw_name);
+	pr_info("nanohub: firmware image offset: %lu\n",
+		fw_request->fw_image_offset);
 
 	atomic_set(&fw_request->state, FW_IN_PROGRESS);
 	ret = request_firmware(&fw_entry, fw_request->fw_name, dev);
@@ -1147,8 +1188,14 @@
 	// FW download uses SERIAL_ISP mode 110.
 	__nanohub_hw_reset(data, 0b110);
 
-	ret = nanohub_bl_download_firmware(data, fw_entry->data,
-					   fw_entry->size);
+	if (fw_request->fw_image_offset != 0) {
+		ret = nanohub_bl_download_firmware_buffer(
+		    data, fw_entry->data + fw_request->fw_image_offset,
+		    fw_entry->size - fw_request->fw_image_offset);
+	} else {
+		ret = nanohub_bl_download_firmware(data, fw_entry->data,
+						   fw_entry->size);
+	}
 
 	mcu_wakeup_gpio_set_value(data, 1);
 	if (data->irq1)
@@ -1351,7 +1398,9 @@
 	__ATTR(boot0, 0660, nanohub_pin_boot0_get, nanohub_pin_boot0_set),
 	__ATTR(boot2, 0660, nanohub_pin_boot2_get, nanohub_pin_boot2_set),
 #ifdef CONFIG_NANOHUB_DISPLAY
-	__ATTR(display_select, 0660, nanohub_pin_display_select_get, nanohub_pin_display_select_set),
+	__ATTR(display_select, 0660, nanohub_pin_display_select_get,
+	       nanohub_pin_display_select_set),
+	__ATTR(display_state, 0440, nanohub_get_display_state, NULL),
 #endif
 #ifdef CONFIG_NANOHUB_BL_ST
 	__ATTR(lock, 0220, NULL, nanohub_lock_bl),
@@ -1361,7 +1410,8 @@
 	__ATTR(firmware_name, 0440, nanohub_firmware_name_query, NULL),
 	__ATTR(download_firmware, 0220, NULL, nanohub_download_firmware_request),
 #endif
-	__ATTR(wakeup_event_msec, 0660, nanohub_wakeup_event_msec_get, nanohub_wakeup_event_msec_set),
+	__ATTR(wakeup_event_msec, 0660, nanohub_wakeup_event_msec_get,
+	       nanohub_wakeup_event_msec_set),
 };
 
 static inline int nanohub_create_sensor(struct nanohub_data *data)
@@ -1399,18 +1449,21 @@
 {
 	int i, j, k, ret;
 	static const struct device_config device_configs[] = {
-		{"nanohub_comms", 1, false},
-		{"nanohub", ID_NANOHUB_CLIENT_NUM_IDS, false},
-		{"nanohub_audio", 1, true},
-		{"nanohub_display", 1, false},
-		{"nanohub_render", 1, false},
-		{"nanohub_debug_log", 1, false},
-		{"nanohub_metrics", 1, false},
-		{"nanohub_console", 1, false},
-		{"nanohub_rpc0", 1, false},
-		{"nanohub_rpc1", 1, false},
-		{"nanohub_brightness", 1, false},
+		{ "nanohub_comms", 1, false },
+		{ "nanohub", ID_NANOHUB_CLIENT_NUM_IDS, false },
+		{ "nanohub_audio", 1, true },
+		{ "nanohub_display", 1, false },
+		{ "nanohub_render", 1, false },
+		{ "nanohub_debug_log", 1, false },
+		{ "nanohub_metrics", 1, false },
+		{ "nanohub_console", 1, false },
+		{ "nanohub_rpc0", 1, false },
+		{ "nanohub_rpc1", 1, false },
+		{ "nanohub_brightness", 1, false },
+		{ "nanohub_touch", 1, true },
+		{ "nanohub_display_kernel", 1, true },
 	};
+	static_assert(ARRAY_SIZE(device_configs) == ID_NANOHUB_MAX - ID_NANOHUB_CLIENT_NUM_IDS + 1);
 
 	for (i = 0, j = 0; j < ID_NANOHUB_MAX - ID_NANOHUB_CLIENT_NUM_IDS + 1; ++j) {
 		struct device *dev = NULL;
@@ -1571,6 +1624,15 @@
 	io->on_message_received = NULL;
 }
 
+int nanohub_query_display_state(void)
+{
+#ifdef CONFIG_NANOHUB_DISPLAY
+	return nanohub_query_display_state_internal(priv_nanohub_data);
+#else
+	return -ENOSYS;
+#endif
+}
+
 static unsigned int nanohub_poll(struct file *file, poll_table *wait)
 {
 	struct nanohub_io *io = file->private_data;
@@ -1858,6 +1920,7 @@
 	uint32_t u, i;
 #endif
 	int ret;
+	u32 val = 0;
 
 	if (!dt)
 		return ERR_PTR(-ENODEV);
@@ -1982,6 +2045,11 @@
 		goto free_pdata;
 	}
 
+	ret = of_property_read_u32(dt, "sensorhub,pmic_irq_enable", &val);
+	if (!ret && val) {
+		nanohub_pmic_irq_config(pdata->pmic_regmap);
+	}
+
 #ifdef CONFIG_NANOHUB_BL_ST
 	/* optional (bl-max-frequency) */
 	pdata->bl_max_speed_hz = BL_MAX_SPEED_HZ;
diff --git a/main.h b/main.h
index b956343..a70fec3 100644
--- a/main.h
+++ b/main.h
@@ -66,6 +66,7 @@
 #define FW_NAME_SIZE		64
 struct firmware_request {
 	char fw_name[FW_NAME_SIZE];
+	uint32_t fw_image_offset;
 	atomic_t state;
 	int result;
 	struct completion fw_complete;
@@ -86,7 +87,9 @@
 	#define ID_NANOHUB_RPC0 22
 	#define ID_NANOHUB_RPC1 23
 	#define ID_NANOHUB_BRIGHTNESS 24
-	#define ID_NANOHUB_MAX 25
+	#define ID_NANOHUB_TOUCH 25
+	#define ID_NANOHUB_DISPLAY_KERNEL 26
+	#define ID_NANOHUB_MAX 27
 
 	struct iio_dev *iio_dev;
 	struct nanohub_io io[ID_NANOHUB_MAX];
diff --git a/nanohub_exports.h b/nanohub_exports.h
index f09a8af..aab40c8 100644
--- a/nanohub_exports.h
+++ b/nanohub_exports.h
@@ -5,7 +5,7 @@
 //
 // Please add the exported symvers to your module's Makefile:
 // all: (MAKE) -C $(KERNEL_SRC) M=$(M) modules ...
-//      KBUILD_EXTRA_SYMBOLS="$(OUT_DIR)/../exynos-google-cw-extra/drivers/sensorhub/nanohub/Module.symvers"
+//      KBUILD_EXTRA_SYMBOLS="$(OUT_DIR)/../google-modules/nanohub/Module.symvers"
 //
 // Your module will have a module dependency on nanohub.
 
@@ -19,6 +19,8 @@
 #define NANOHUB_RPC0_CHANNEL_ID 22
 #define NANOHUB_RPC1_CHANNEL_ID 23
 #define NANOHUB_BRIGHTNESS_CHANNEL_ID 24
+#define NANOHUB_TOUCH_CHANNEL_ID 25
+#define NANOHUB_DISPLAY_KERNEL_CHANNEL_ID 26
 
 /**
  * Sends a message over a nanohub channel.
@@ -46,4 +48,24 @@
  */
 extern void nanohub_unregister_listener(int channel_id);
 
+/**
+ * MCU display power state returned from nanohub_query_display_state
+ */
+enum mcu_display_mode {
+	MCU_DISPLAY_NONE = 0,
+	MCU_DISPLAY_INIT = 1,
+	MCU_DISPLAY_SLEEP = 2,
+	MCU_DISPLAY_OFF = 3,
+	MCU_DISPLAY_IDLE = 4,
+	MCU_DISPLAY_ON = 5,
+	MCU_DISPLAY_HIGH_BRIGHTNESS = 6,
+};
+
+/**
+ * Query the display power state from MCU when display is controlled by MCU.
+ * MCU_DISPLAY_NONE, when MCU doesn't control display.
+ */
+
+extern int nanohub_query_display_state(void);
+
 #endif /* _NANOHUB_EXPORTS_H_ */