OSDN Git Service

media: atomisp: detect the PMIC type
authorMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Sun, 10 May 2020 20:04:37 +0000 (22:04 +0200)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Wed, 20 May 2020 12:51:28 +0000 (14:51 +0200)
Sub-device's power management can be provided via different ways.

Instead of hardcoding it, add a code that would be detecting it.

This uses a code similar to what's found at the atomisp driver
inside the Intel Aero repository:

https://github.com/intel-aero/meta-intel-aero.git

(driver was removed on some commit, but it can be found on
git history).

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c

index 8fd8bba..cbdb239 100644 (file)
@@ -17,7 +17,6 @@
 
 #define MAX_SUBDEVS 8
 
-
 enum clock_rate {
        VLV2_CLK_XTAL_25_0MHz = 0,
        VLV2_CLK_PLL_19P2MHZ = 1
@@ -57,6 +56,11 @@ struct gmin_subdev {
 
 static struct gmin_subdev gmin_subdevs[MAX_SUBDEVS];
 
+/* ACPI HIDs for the PMICs that could be used by this driver */
+#define PMIC_ACPI_AXP          "INT33F4:00"    /* XPower AXP288 PMIC */
+#define PMIC_ACPI_TI           "INT33F5:00"    /* Dollar Cove TI PMIC */
+#define PMIC_ACPI_CRYSTALCOVE  "INT33FD:00"    /* Crystal Cove PMIC */
+
 static enum {
        PMIC_UNSET = 0,
        PMIC_REGULATOR,
@@ -67,13 +71,12 @@ static enum {
 
 static const char *pmic_name[] = {
        [PMIC_UNSET]            = "unset",
-       [PMIC_REGULATOR]        = "regulator",
-       [PMIC_AXP]              = "AXP",
-       [PMIC_TI]               = "TI",
-       [PMIC_CRYSTALCOVE]      = "Crystal Cove",
+       [PMIC_REGULATOR]        = "regulator driver",
+       [PMIC_AXP]              = "XPower AXP288 PMIC",
+       [PMIC_TI]               = "Dollar Cove TI PMIC",
+       [PMIC_CRYSTALCOVE]      = "Crystal Cove PMIC",
 };
 
-
 /* The atomisp uses type==0 for the end-of-list marker, so leave space. */
 static struct intel_v4l2_subdev_table pdata_subdevs[MAX_SUBDEVS + 1];
 
@@ -355,27 +358,78 @@ static const struct dmi_system_id gmin_vars[] = {
 #define GMIN_PMC_CLK_NAME 14 /* "pmc_plt_clk_[0..5]" */
 static char gmin_pmc_clk_name[GMIN_PMC_CLK_NAME];
 
+struct gmin_match_name {
+       const char *name;
+       struct device *dev;
+};
+
+static int gmin_match_one(struct device *dev, void *data)
+{
+       struct gmin_match_name *match = data;
+       const char *name = match->name;
+       struct i2c_client *client;
+
+       if (dev->type != &i2c_client_type)
+               return 0;
+
+       client = to_i2c_client(dev);
+
+       dev_info(match->dev, "found '%s' at address 0x%02x, adapter %d\n",
+                client->name, client->addr, client->adapter->nr);
+
+       return (!strcmp(name, client->name));
+}
+
+static bool gmin_i2c_dev_exists(struct device *dev, char *name)
+{
+       struct gmin_match_name match;
+       bool found;
+       int ret = 0;
+
+       match.dev = dev;
+       match.name = name;
+
+       ret = i2c_for_each_dev(&match, gmin_match_one);
+
+       found = !!ret;
+
+       if (found)
+               dev_info(dev, "%s found on I2C\n", name);
+       else
+               dev_info(dev, "%s not found on I2C\n", name);
+
+       return found;
+}
+
 static struct gmin_subdev *gmin_subdev_add(struct v4l2_subdev *subdev)
 {
        int i, ret;
        struct device *dev;
        struct i2c_client *client = v4l2_get_subdevdata(subdev);
 
-       if (!pmic_id)
-               pmic_id = PMIC_REGULATOR;
-
        if (!client)
                return NULL;
 
        dev = &client->dev;
 
+       if (!pmic_id) {
+               if (gmin_i2c_dev_exists(dev, PMIC_ACPI_TI))
+                       pmic_id = PMIC_TI;
+               else if (gmin_i2c_dev_exists(dev, PMIC_ACPI_AXP))
+                       pmic_id = PMIC_AXP;
+               else if (gmin_i2c_dev_exists(dev, PMIC_ACPI_CRYSTALCOVE))
+                       pmic_id = PMIC_CRYSTALCOVE;
+               else
+                       pmic_id = PMIC_REGULATOR;
+       }
+
        for (i = 0; i < MAX_SUBDEVS && gmin_subdevs[i].subdev; i++)
                ;
        if (i >= MAX_SUBDEVS)
                return NULL;
 
        dev_info(dev,
-                "gmin: initializing atomisp module subdev data using PMIC %s\n",
+                "gmin: power management provided via %s\n",
                 pmic_name[pmic_id]);
 
        gmin_subdevs[i].subdev = subdev;