summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/media/atomisp/TODO43
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c105
2 files changed, 101 insertions, 47 deletions
diff --git a/drivers/staging/media/atomisp/TODO b/drivers/staging/media/atomisp/TODO
index e58643a9de43..6987bb2d32cf 100644
--- a/drivers/staging/media/atomisp/TODO
+++ b/drivers/staging/media/atomisp/TODO
@@ -18,48 +18,7 @@ TODO
This should be converted to the usual way, using V4L2 async subdev
framework to wait for cameras to be probed;
-2. Support for newer board-specific data (like Asus T101HA support) uses a
- DMI match table to retrieve sensor's data, using hard-coded values.
- It sounds feasible to retrieve those data directly from ACPI via _DSM
- tables (like this one, associated with CAM1 at the above mentioned
- hardware):
-
- Name (C1CD, Buffer (0x0220){})
- Method (_DSM, 4, NotSerialized) // _DSM: Device-Specific Method
- {
- If ((Arg0 == ToUUID ("dc2f6c4f-045b-4f1d-97b9-882a6860a4be")))
- {
- Local0 = Package (0x12)
- {
- "CamId",
- "ov2680",
- "CamType",
- "1",
- "CsiPort",
- "0",
- "CsiLanes",
- "1",
- "CsiFmt",
- "15",
- "CsiBayer",
- "0",
- "CamClk",
- "1",
- "Regulator1p8v",
- "0",
- "Regulator2p8v",
- "0"
- }
- Return (Local0)
- }
-
- The code there at atomisp_gmin_platform has an EFI parser, but it
- assumes that the information would be stored on a different way.
-
- As the Kernel has support for reading data from _DSM, via
- acpi_evaluate_dsm(), it sounds doable to use such infra and remove the
- DMI match, at least for some devices. This will likely allow covering
- more devices that could also be using the same EFI UUID.
+2. Use ACPI _DSM table - DONE!
3. Switch the driver to use pm_runtime stuff. Right now, it probes the
existing PMIC code and sensors call it directly.
diff --git a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c
index 5d2bfe2ea971..5f34b2be5153 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c
@@ -388,6 +388,10 @@ static const struct dmi_system_id gmin_vars[] = {
0xa9, 0x71, 0xe8, 0x77, \
0x75, 0x60, 0x68, 0xf7)
+static const guid_t atomisp_dsm_guid = GUID_INIT(0xdc2f6c4f, 0x045b, 0x4f1d,
+ 0x97, 0xb9, 0x88, 0x2a,
+ 0x68, 0x60, 0xa4, 0xbe);
+
#define CFG_VAR_NAME_MAX 64
#define GMIN_PMC_CLK_NAME 14 /* "pmc_plt_clk_[0..5]" */
@@ -455,15 +459,28 @@ static int gmin_i2c_write(struct device *dev, u16 i2c_addr, u8 reg,
static struct gmin_subdev *gmin_subdev_add(struct v4l2_subdev *subdev)
{
- int i, ret;
- struct device *dev;
struct i2c_client *power = NULL, *client = v4l2_get_subdevdata(subdev);
+ struct acpi_device *adev;
+ acpi_handle handle;
+ struct device *dev;
+ int i, ret;
if (!client)
return NULL;
dev = &client->dev;
+ handle = ACPI_HANDLE(dev);
+
+ // FIXME: may need to release resources allocated by acpi_bus_get_device()
+ if (!handle || acpi_bus_get_device(handle, &adev)) {
+ dev_err(dev, "Error could not get ACPI device\n");
+ return NULL;
+ }
+
+ dev_info(&client->dev, "%s: ACPI detected it on bus ID=%s, HID=%s\n",
+ __func__, acpi_device_bid(adev), acpi_device_hid(adev));
+
if (!pmic_id) {
if (gmin_i2c_dev_exists(dev, PMIC_ACPI_TI, &power))
pmic_id = PMIC_TI;
@@ -944,6 +961,75 @@ static int gmin_get_hardcoded_var(struct gmin_cfg_var *varlist,
return -EINVAL;
}
+
+static int gmin_get_config_dsm_var(struct device *dev,
+ const char *var,
+ char *out, size_t *out_len)
+{
+ acpi_handle handle = ACPI_HANDLE(dev);
+ union acpi_object *obj, *cur = NULL;
+ int i;
+
+ obj = acpi_evaluate_dsm(handle, &atomisp_dsm_guid, 0, 0, NULL);
+ if (!obj) {
+ dev_info_once(dev, "Didn't find ACPI _DSM table.\n");
+ return -EINVAL;
+ }
+
+#if 0 /* Just for debugging purposes */
+ for (i = 0; i < obj->package.count; i++) {
+ union acpi_object *cur = &obj->package.elements[i];
+
+ if (cur->type == ACPI_TYPE_INTEGER)
+ dev_info(dev, "object #%d, type %d, value: %lld\n",
+ i, cur->type, cur->integer.value);
+ else if (cur->type == ACPI_TYPE_STRING)
+ dev_info(dev, "object #%d, type %d, string: %s\n",
+ i, cur->type, cur->string.pointer);
+ else
+ dev_info(dev, "object #%d, type %d\n",
+ i, cur->type);
+ }
+#endif
+
+ /* Seek for the desired var */
+ for (i = 0; i < obj->package.count - 1; i += 2) {
+ if (obj->package.elements[i].type == ACPI_TYPE_STRING &&
+ !strcmp(obj->package.elements[i].string.pointer, var)) {
+ /* Next element should be the required value */
+ cur = &obj->package.elements[i + 1];
+ break;
+ }
+ }
+
+ if (!cur) {
+ dev_info(dev, "didn't found _DSM entry for '%s'\n", var);
+ ACPI_FREE(obj);
+ return -EINVAL;
+ }
+
+ /*
+ * While it could be possible to have an ACPI_TYPE_INTEGER,
+ * and read the value from cur->integer.value, the table
+ * seen so far uses the string type. So, produce a warning
+ * if it founds something different than string, letting it
+ * to fall back to the old code.
+ */
+ if (cur && cur->type != ACPI_TYPE_STRING) {
+ dev_info(dev, "found non-string _DSM entry for '%s'\n", var);
+ ACPI_FREE(obj);
+ return -EINVAL;
+ }
+
+ dev_info(dev, "found _DSM entry for '%s': %s\n", var,
+ cur->string.pointer);
+ strscpy(out, cur->string.pointer, *out_len);
+ *out_len = strlen(cur->string.pointer);
+
+ ACPI_FREE(obj);
+ return 0;
+}
+
/* Retrieves a device-specific configuration variable. The dev
* argument should be a device with an ACPI companion, as all
* configuration is based on firmware ID.
@@ -953,12 +1039,21 @@ static int gmin_get_config_var(struct device *maindev,
const char *var,
char *out, size_t *out_len)
{
- char var8[CFG_VAR_NAME_MAX];
efi_char16_t var16[CFG_VAR_NAME_MAX];
- struct efivar_entry *ev;
const struct dmi_system_id *id;
- int i, ret;
struct device *dev = maindev;
+ char var8[CFG_VAR_NAME_MAX];
+ struct efivar_entry *ev;
+ int i, ret;
+
+ /* For sensors, try first to use the _DSM table */
+ if (!is_gmin) {
+ ret = gmin_get_config_dsm_var(maindev, var, out, out_len);
+ if (!ret)
+ return 0;
+ }
+
+ /* Fall-back to other approaches */
if (!is_gmin && ACPI_COMPANION(dev))
dev = &ACPI_COMPANION(dev)->dev;