On Thu, May 25, 2023 at 10:01 PM Hans de Goede <hdegoede@xxxxxxxxxx> wrote: > > Add support for using v4l2-async sensor registration. > > This has been tested with both the gc0310 and the ov2680 sensor drivers. > > Drivers must add the ACPI HIDs they match on to the supported_sensors[] > array in the same commit as that they are converted to > v4l2_async_register_subdev_sensor(). > > Sensor drivers also must check they have a fwnode graph endpoint and return > -EPROBE_DEFER from probe() if there is no endpoint yet. This guarantees > that the GPIO mappingss are in place before the driver tries to get GPIOs. mappings > For now it also is still possible to use the old atomisp_gmin_platform > based sensor drivers. This is mainly intended for testing while moving > other sensor drivers over to runtime-pm + v4l2-async. ... > +struct acpi_device; > struct atomisp_device; > -struct v4l2_device; > struct atomisp_sub_device; > +struct v4l2_device; I would group atomisp* separately struct acpi_device; struct v4l2_device; struct atomisp_device; struct atomisp_sub_device; ... > +struct atomisp_csi2_bridge { > + char csi2_node_name[14]; > + struct software_node csi2_node; Wondering if swapping these two saves some code (due to potential use of container_of() for the node member). > + u32 data_lanes[CSI2_MAX_LANES]; > + unsigned int n_sensors; > + struct atomisp_csi2_sensor sensors[ATOMISP_CAMERA_NR_PORTS]; > +}; ... > +static char *gmin_cfg_get_dsm(struct acpi_device *adev, const char *key) > +{ > + union acpi_object *obj, *key_el, *val_el; > + char *val = NULL; > + int i; > + > + obj = acpi_evaluate_dsm_typed(adev->handle, &atomisp_dsm_guid, 0, 0, > + NULL, ACPI_TYPE_PACKAGE); > + if (!obj) > + return NULL; > + > + for (i = 0; i < obj->package.count - 1; i += 2) { > + key_el = &obj->package.elements[i + 0]; > + val_el = &obj->package.elements[i + 1]; > + > + if (key_el->type != ACPI_TYPE_STRING || val_el->type != ACPI_TYPE_STRING) > + break; > + > + if (!strcmp(key_el->string.pointer, key)) { > + val = kstrdup(val_el->string.pointer, GFP_KERNEL); > + dev_info(&adev->dev, "Using DSM entry %s=%s\n", key, val); Do we really want to have "(null)" to be printed in case of the kstrdup() failure? Also this code may become a honeypot for all possible static analyzers and even if we don't care about NULL it may become noisy activity. Besides that since we have a handle, wouldn't it be better to use acpi_handle_info() here? > + break; > + } > + } > + > + ACPI_FREE(obj); > + return val; > +} ... > + dev_info(&adev->dev, "Using DMI entry %s=%s\n", key, gv->val); acpi_handle_info() ? Note, I'm fine with dev_info() in both cases, just asking. ... > + status = acpi_evaluate_object_typed(adev->handle, "_PR0", NULL, &buffer, ACPI_TYPE_PACKAGE); > + if (!ACPI_SUCCESS(status)) ACPI_FAILURE() > + return -ENOENT; ... > + /* > + * Get pmc-clock number from ACPI _PR0 method and compare this to PMC ? > + * the CsiPort 1 pmc-clock used in the CHT/BYT reference designs. Ditto. > + */ ... > + obj = acpi_evaluate_dsm_typed(adev->handle, &intel_sensor_module_guid, > + 0x00, 0x01, NULL, ACPI_TYPE_STRING); 0x01 here... > + if (obj) { > + dev_info(&adev->dev, "Sensor module id: '%s'\n", obj->string.pointer); > + ACPI_FREE(obj); > + } > + > + /* > + * First get the GPIO-settings count and then get count GPIO-settings > + * values. Note the order of these may differ from the order in which > + * the GPIOs are listed on the ACPI resources! So we first store them all > + * and then enumerate the ACPI resources and match them up by pin number. > + */ > + obj = acpi_evaluate_dsm_typed(adev->handle, > + &intel_sensor_gpio_info_guid, 0x00, 1, ...and 1 here. Wouldn't it make sense to be consistent and use either hex or decimal (looking into below code decimal looks more plausible) in both cases? > + NULL, ACPI_TYPE_INTEGER); > + if (!obj) > + return dev_err_probe(&adev->dev, -EIO, "No _DSM entry for GPIO pin count\n"); ... > + /* Since we match up by pin-number the pin-numbers must be unique */ > + for (i = 0; i < data.settings_count; i++) { > + for (j = i + 1; j < data.settings_count; j++) { > + if (INTEL_GPIO_DSM_PIN(data.settings[i]) != > + INTEL_GPIO_DSM_PIN(data.settings[j])) > + continue; Wondering if we can have pure pin numbers in some (bit)array, in that case the uniqueness can be achieved by the test_bit() call in O(1). > + return dev_err_probe(&adev->dev, -EIO, "Duplicate pin number %lu\n", > + INTEL_GPIO_DSM_PIN(data.settings[i])); > + } > + } ... > + for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) { > + if (!adev->status.enabled) > + continue; > + > + if (bridge->n_sensors >= ATOMISP_CAMERA_NR_PORTS) { > + dev_err(isp->dev, "Exceeded available CSI2 ports\n"); > + ret = -EINVAL; EOVERFLOW ? EEXIST? ENOMEM (EINVAL is fine, but to me it's too much use of the same code in the kernel) > + goto err_put_adev; > + } > + } ... > + /* > + * This function is intended to run only once and then leave > + * the created nodes attached even after a rmmod, therefor: Some spellcheckers want "therefore" here. > + * 1. The bridge memory is leaked deliberately on success > + * 2. If a secondary fwnode is already set exit early. > + */ -- With Best Regards, Andy Shevchenko