Browse Source

disp: msm: add io resource collection hook to vm events

When the TUI use case starts, HLOS prepares for sharing the HW
by collecting the register io spaces and IRQ lines from all the
participating subdrivers before the switch. This change
adds necessary hook in the VM event framework, so that
subdrivers can provide their callback functions while
registering for events. It also adds necessary helpers
in the sde io util to parse and populate the IO memory
region that needs to be shared.

Change-Id: I4c0825fa76453a1c1ec421640deff36158d6ef8c
Signed-off-by: Jeykumar Sankaran <[email protected]>
Jeykumar Sankaran 5 years ago
parent
commit
bd60dce87c
3 changed files with 164 additions and 1 deletions
  1. 6 1
      include/linux/sde_io_util.h
  2. 36 0
      include/linux/sde_vm_event.h
  3. 122 0
      msm/sde_io_util.c

+ 6 - 1
include/linux/sde_io_util.h

@@ -85,7 +85,12 @@ struct dss_module_power {
 int msm_dss_ioremap_byname(struct platform_device *pdev,
 	struct dss_io_data *io_data, const char *name);
 void msm_dss_iounmap(struct dss_io_data *io_data);
-
+int msm_dss_get_io_mem(struct platform_device *pdev,
+		       struct list_head *mem_list);
+void msm_dss_clean_io_mem(struct list_head *mem_list);
+int msm_dss_get_io_irq(struct platform_device *pdev,
+		       struct list_head *irq_list, u32 label);
+void msm_dss_clean_io_irq(struct list_head *irq_list);
 int msm_dss_enable_gpio(struct dss_gpio *in_gpio, int num_gpio, int enable);
 int msm_dss_gpio_enable(struct dss_gpio *in_gpio, int num_gpio, int enable);
 

+ 36 - 0
include/linux/sde_vm_event.h

@@ -12,17 +12,53 @@
 #include <linux/platform_device.h>
 #include <drm/drm_device.h>
 
+/**
+ * struct - msm_io_irq_entry - define irq item
+ * @label: hh_irq_label for the irq
+ * @irq_num: linux mapped irq num
+ * @list: list head pointer
+ */
+struct msm_io_irq_entry {
+	u32 label;
+	u32 irq_num;
+	struct list_head list;
+};
+
+/**
+ * struct - msm_io_mem_entry - define io memory item
+ * @base: reg base
+ * @size: size of the reg range
+ * @list: list head pointer
+ */
+struct msm_io_mem_entry {
+	phys_addr_t base;
+	phys_addr_t size;
+	struct list_head list;
+};
+
+/**
+ * struct - msm_io_res - represents the hw resources for vm sharing
+ * @irq: list of IRQ's of all the dislay sub-devices
+ * @mem: list of IO memory ranges of all the display sub-devices
+ */
+struct msm_io_res {
+	struct list_head irq;
+	struct list_head mem;
+};
+
 /**
  * struct msm_vm_ops - hooks for communication with vm clients
  * @vm_pre_hw_release: invoked before releasing the HW
  * @vm_post_hw_acquire: invoked before pushing the first commit
  * @vm_check: invoked to check the readiness of the vm_clients
  *	      before releasing the HW
+ * @vm_get_io_resources: invoked to collect HW resources
  */
 struct msm_vm_ops {
 	int (*vm_pre_hw_release)(void *priv_data);
 	int (*vm_post_hw_acquire)(void *priv_data);
 	int (*vm_check)(void *priv_data);
+	int (*vm_get_io_resources)(struct msm_io_res *io_res, void *priv_data);
 };
 
 /**

+ 122 - 0
msm/sde_io_util.c

@@ -9,6 +9,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/delay.h>
 #include <linux/sde_io_util.h>
+#include <linux/sde_vm_event.h>
 
 #define MAX_I2C_CMDS  16
 void dss_reg_w(struct dss_io_data *io, u32 offset, u32 value, u32 debug)
@@ -129,6 +130,127 @@ void msm_dss_iounmap(struct dss_io_data *io_data)
 } /* msm_dss_iounmap */
 EXPORT_SYMBOL(msm_dss_iounmap);
 
+int msm_dss_get_io_mem(struct platform_device *pdev, struct list_head *mem_list)
+{
+	struct list_head temp_head;
+	struct msm_io_mem_entry *io_mem;
+	struct resource *res = NULL;
+	const char *reg_name, *exclude_reg_name;
+	int i, j, rc = 0;
+	int num_entry, num_exclude_entry;
+
+	INIT_LIST_HEAD(&temp_head);
+
+	num_entry = of_property_count_strings(pdev->dev.of_node,
+						  "reg-names");
+	if (num_entry < 0)
+		num_entry = 0;
+
+	/*
+	 * check the dt property to know whether the platform device wants
+	 * to exclude any reg ranges from the IO list
+	 */
+	num_exclude_entry = of_property_count_strings(pdev->dev.of_node,
+					  "qcom,sde-vm-exclude-reg-names");
+	if (num_exclude_entry < 0)
+		num_exclude_entry = 0;
+
+	for (i = 0; i < num_entry; i++) {
+		bool exclude = false;
+
+		of_property_read_string_index(pdev->dev.of_node,
+				"reg-names", i,	&reg_name);
+
+		for (j = 0; j < num_exclude_entry; j++) {
+			of_property_read_string_index(pdev->dev.of_node,
+				"qcom,sde-vm-exclude-reg-names", j,
+				&exclude_reg_name);
+
+			if (!strcmp(reg_name, exclude_reg_name)) {
+				exclude = true;
+				break;
+			}
+		}
+
+		if (exclude)
+			continue;
+
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   reg_name);
+		if (!res)
+			break;
+
+		io_mem = kzalloc(sizeof(*io_mem), GFP_KERNEL);
+		if (!io_mem) {
+			msm_dss_clean_io_mem(&temp_head);
+			rc = -ENOMEM;
+			goto parse_fail;
+		}
+
+		io_mem->base = res->start;
+		io_mem->size = resource_size(res);
+
+		list_add(&io_mem->list, &temp_head);
+	}
+
+	list_splice(&temp_head, mem_list);
+
+	return 0;
+
+parse_fail:
+	msm_dss_clean_io_mem(&temp_head);
+
+	return rc;
+}
+EXPORT_SYMBOL(msm_dss_get_io_mem);
+
+void msm_dss_clean_io_mem(struct list_head *mem_list)
+{
+	struct msm_io_mem_entry *pos, *tmp;
+
+	list_for_each_entry_safe(pos, tmp, mem_list, list) {
+		list_del(&pos->list);
+		kzfree(pos);
+	}
+}
+EXPORT_SYMBOL(msm_dss_clean_io_mem);
+
+int msm_dss_get_io_irq(struct platform_device *pdev, struct list_head *irq_list,
+		       u32 label)
+{
+	struct msm_io_irq_entry *io_irq;
+	int irq;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		pr_err("invalid IRQ\n");
+		return irq;
+	}
+
+	io_irq = kzalloc(sizeof(*io_irq), GFP_KERNEL);
+	if (!io_irq)
+		return -ENOMEM;
+
+	io_irq->label  = label;
+	io_irq->irq_num = irq;
+
+	list_add(&io_irq->list, irq_list);
+
+	return 0;
+}
+EXPORT_SYMBOL(msm_dss_get_io_irq);
+
+void msm_dss_clean_io_irq(struct list_head *irq_list)
+{
+	struct msm_io_irq_entry *pos, *tmp;
+
+	list_for_each_entry_safe(pos, tmp, irq_list, list) {
+		list_del(&pos->list);
+		kzfree(pos);
+	}
+}
+EXPORT_SYMBOL(msm_dss_clean_io_irq);
+
 int msm_dss_get_vreg(struct device *dev, struct dss_vreg *in_vreg,
 	int num_vreg, int enable)
 {