Re: [PATCH 1/9] media: v4l: Add v4l2_acpi_parse_sensor_gpios() helper function

Andy Shevchenko
2023-05-18T16:37:04Z

On Thu, May 18, 2023 at 6:32 PM Hans de Goede <hdegoede@redhat.com> wrote:
>
> On x86/ACPI platforms the GPIO resources do not provide information
> about which GPIO resource maps to which connection-id. So e.g.
> gpiod_get(devg, "reset") does not work.
>
> On devices with an Intel IPU3 or newer ISP there is a special ACPI
> INT3472 device describing the GPIOs and instantiating of the i2c_client
> for a sensor is deferred until the INT3472 driver has been bound based
> on the sensor ACPI device having a _DEP on the INT3472 ACPI device.
>
> This allows the INT3472 driver to add the necessary GPIO lookups
> without needing any special ACPI handling in the sensor driver.
>
> Unfortunately this does not work on devices with an atomisp2 ISP,
> there the _DSM describing the GPIOs is part of the sensor ACPI device
> itself, rather then being part of a separate ACPI device.

than

(not the first time I see the same typo in your commit messages :-)

> IOW there is no separate firmware-node to which we can bind to register
> the GPIO lookups (and also no way to defer creating the sensor i2c_client).
>
> This unfortunately means that all sensor drivers which may be used on
> BYT or CHT hw need some code to deal with ACPI integration.
>
> This patch adds a new v4l2_acpi_parse_sensor_gpios() helper function
> for this, which does all the necessary work. This minimizes the
> (unavoidable) change to sensor drivers for ACPI integration to just
> adding a single line calling this void function to probe().
>
> There also is a no-op stub provided for non ACPI platforms so that
> no #ifdef-s are necessary in the driver.
>
> Note v4l2_acpi_parse_sensor_gpios() is basically a copy of
> the atomisp2 v4l2_get_acpi_sensor_info() helper from:
> drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c
> minus logging the sensor module-name using a second _DSM.

> v4l2_get_acpi_sensor_info() was already reviewed by Andy,
> see the Link tag below.
>
> (this code duplication is removed in the next patch in this series)

I believe the above is not needed to be in the commit message, but
rather in the comments below (after the '---' cutter line).

...

> +/* Note this always returns 1 to continue looping so that res_count is accurate */
> +static int v4l2_acpi_handle_gpio_res(struct acpi_resource *ares, void *_data)
> +{
> + struct v4l2_acpi_gpio_parsing_data *data = _data;
> + struct acpi_resource_gpio *agpio;
> + const char *name;
> + bool active_low;
> + unsigned int i;
> + u32 settings;

> + u8 pin;

Should be u16.

> + pin = agpio->pin_table[0];
> + for (i = 0; i < data->settings_count; i++) {
> + if (INTEL_DSM_PIN(data->settings[i]) == pin) {
> + settings = data->settings[i];
> + break;
> + }
> + }
> +
> + if (i == data->settings_count) {
> + dev_warn(data->dev, "Could not find DSM GPIO settings for pin %d\n", pin);

%u

> + return 1;
> + }
> +
> + switch (INTEL_DSM_TYPE(settings)) {
> + case 0:
> + name = "reset-gpios";
> + break;
> + case 1:
> + name = "powerdown-gpios";
> + break;
> + default:
> + dev_warn(data->dev, "Unknown GPIO type 0x%02lx for pin %d\n",

%u

> + INTEL_DSM_TYPE(settings), pin);
> + return 1;
> + }
> +
> + /*
> + * Both reset and power-down need to be logical false when the sensor
> + * is on (sensor should not be in reset and not be powered-down). So
> + * when the sensor-on-value (which is the physical pin value) is high,
> + * then the signal is active-low.
> + */
> + active_low = INTEL_DSM_SENSOR_ON_VAL(settings) ? true : false;

Ternary part is redundant.

> + i = data->map_count;
> + if (i == V4L2_SENSOR_MAX_ACPI_GPIOS)
> + return 1;
> +
> + /* res_count is already incremented */
> + data->map->params[i].crs_entry_index = data->res_count - 1;
> + data->map->params[i].active_low = active_low;
> + data->map->mapping[i].name = name;
> + data->map->mapping[i].data = &data->map->params[i];
> + data->map->mapping[i].size = 1;
> + data->map_count++;
> +
> + dev_info(data->dev, "%s crs %d %s pin %d active-%s\n", name,

%u (for pin)

> + data->res_count - 1, agpio->resource_source.string_ptr,
> + pin, active_low ? "low" : "high");
> +
> + return 1;
> +}

...

> + * Note this code uses the same DSM GUID as the INT3472 discrete.c code
> + * and there is some overlap, but there are enough differences that it is
> + * difficult to share the code.

Can you add the name of the variable in that file, so likely the
source code indexing tool might add a link?

...

> + struct acpi_device *adev = ACPI_COMPANION(dev);

I would split this assignment and...

> + struct v4l2_acpi_gpio_parsing_data data = { };
> + LIST_HEAD(resource_list);
> + union acpi_object *obj;
> + unsigned int i, j;
> + int ret;
> +

...place it here.

> + if (!adev || (!soc_intel_is_byt() && !soc_intel_is_cht()))
> + return;

...

> + devm_acpi_dev_add_driver_gpios(dev, data.map->mapping);

Won't we print a warning here as well in case of error?

...

> +#ifdef CONFIG_ACPI

> +struct device;

This should be outside of previous ifdeffery as it's used in a stub.

> +/**
> + * v4l2_acpi_parse_sensor_gpios - Parse ACPI info describing sensor GPIOs.
> + *

Dunno the style of v4l2, but this line is redundant.

> + * @dev: Device to parse the ACPI info for
> + *
> + * On x86/ACPI platforms the GPIO resources do not provide information
> + * about which resource maps to which connection-id.
> + *
> + * Sensor drivers can call this function to use platform specific methods
> + * (e.g. the Intel 79234640-9e10-4fea-a5c1-b5aa8b19756f _DSM) to get
> + * information about the pins and add GPIO mappings to make standard gpiod_get()
> + * calls work.
> + *
> + * The registered mappings use devm managed memory and are automatically free-ed
> + * on remove() and on probe() failure.
> + */

Usually the kernel doc is attached to the function implementation.

> +void v4l2_acpi_parse_sensor_gpios(struct device *dev);
> +
> +#else /* ifdef CONFIG_ACPI */
> +static inline void v4l2_acpi_parse_sensor_gpios(struct device *dev) { return 0; }
> +#endif /* ifdef CONFIG_ACPI */

--
With Best Regards,
Andy Shevchenko