ACPI / PMIC: Add support for executing PMIC MIPI sequence elements
[sfrench/cifs-2.6.git] / drivers / acpi / pmic / intel_pmic.c
index ca18e0d23df9775e0a9c342d5a22ac9257d6ee3a..471afeea87c214b8af030f6d27adb151cfd0d54e 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/export.h>
 #include <linux/acpi.h>
+#include <linux/mfd/intel_soc_pmic.h>
 #include <linux/regmap.h>
 #include <acpi/acpi_lpat.h>
 #include "intel_pmic.h"
@@ -36,6 +37,8 @@ struct intel_pmic_opregion {
        struct intel_pmic_regs_handler_ctx ctx;
 };
 
+static struct intel_pmic_opregion *intel_pmic_opregion;
+
 static int pmic_get_reg_bit(int address, struct pmic_table *table,
                            int count, int *reg, int *bit)
 {
@@ -304,6 +307,7 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
        }
 
        opregion->data = d;
+       intel_pmic_opregion = opregion;
        return 0;
 
 out_remove_thermal_handler:
@@ -319,3 +323,51 @@ out_error:
        return ret;
 }
 EXPORT_SYMBOL_GPL(intel_pmic_install_opregion_handler);
+
+/**
+ * intel_soc_pmic_exec_mipi_pmic_seq_element - Execute PMIC MIPI sequence
+ * @i2c_address:  I2C client address for the PMIC
+ * @reg_address:  PMIC register address
+ * @value:        New value for the register bits to change
+ * @mask:         Mask indicating which register bits to change
+ *
+ * DSI LCD panels describe an initialization sequence in the i915 VBT (Video
+ * BIOS Tables) using so called MIPI sequences. One possible element in these
+ * sequences is a PMIC specific element of 15 bytes.
+ *
+ * This function executes these PMIC specific elements sending the embedded
+ * commands to the PMIC.
+ *
+ * Return 0 on success, < 0 on failure.
+ */
+int intel_soc_pmic_exec_mipi_pmic_seq_element(u16 i2c_address, u32 reg_address,
+                                             u32 value, u32 mask)
+{
+       struct intel_pmic_opregion_data *d;
+       int ret;
+
+       if (!intel_pmic_opregion) {
+               pr_warn("%s: No PMIC registered\n", __func__);
+               return -ENXIO;
+       }
+
+       d = intel_pmic_opregion->data;
+
+       mutex_lock(&intel_pmic_opregion->lock);
+
+       if (d->exec_mipi_pmic_seq_element) {
+               ret = d->exec_mipi_pmic_seq_element(intel_pmic_opregion->regmap,
+                                                   i2c_address, reg_address,
+                                                   value, mask);
+       } else {
+               pr_warn("%s: Not implemented\n", __func__);
+               pr_warn("%s: i2c-addr: 0x%x reg-addr 0x%x value 0x%x mask 0x%x\n",
+                       __func__, i2c_address, reg_address, value, mask);
+               ret = -EOPNOTSUPP;
+       }
+
+       mutex_unlock(&intel_pmic_opregion->lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(intel_soc_pmic_exec_mipi_pmic_seq_element);