drivers/media/pci/intel/ipu-bridge.c

Source file repositories/reference/linux-study-clean/drivers/media/pci/intel/ipu-bridge.c

File Facts

System
Linux kernel
Corpus path
drivers/media/pci/intel/ipu-bridge.c
Extension
.c
Size
25545 bytes
Lines
935
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct ipu_bridge_instantiate_vcm_work_data {
	struct work_struct work;
	struct device *sensor;
	char name[16];
	struct i2c_board_info board_info;
};

static void ipu_bridge_instantiate_vcm_work(struct work_struct *work)
{
	struct ipu_bridge_instantiate_vcm_work_data *data =
		container_of(work, struct ipu_bridge_instantiate_vcm_work_data,
			     work);
	struct acpi_device *adev = ACPI_COMPANION(data->sensor);
	struct i2c_client *vcm_client;
	bool put_fwnode = true;
	int ret;

	/*
	 * The client may get probed before the device_link gets added below
	 * make sure the sensor is powered-up during probe.
	 */
	ret = pm_runtime_get_sync(data->sensor);
	if (ret < 0) {
		dev_err(data->sensor, "Error %d runtime-resuming sensor, cannot instantiate VCM\n",
			ret);
		goto out_pm_put;
	}

	/*
	 * Note the client is created only once and then kept around
	 * even after a rmmod, just like the software-nodes.
	 */
	vcm_client = i2c_acpi_new_device_by_fwnode(acpi_fwnode_handle(adev),
						   1, &data->board_info);
	if (IS_ERR(vcm_client)) {
		dev_err(data->sensor, "Error instantiating VCM client: %pe\n",
			vcm_client);
		goto out_pm_put;
	}

	device_link_add(&vcm_client->dev, data->sensor, DL_FLAG_PM_RUNTIME);

	dev_info(data->sensor, "Instantiated %s VCM\n", data->board_info.type);
	put_fwnode = false; /* Ownership has passed to the i2c-client */

out_pm_put:
	pm_runtime_put(data->sensor);
	put_device(data->sensor);
	if (put_fwnode)
		fwnode_handle_put(data->board_info.fwnode);
	kfree(data);
}

int ipu_bridge_instantiate_vcm(struct device *sensor)
{
	struct ipu_bridge_instantiate_vcm_work_data *data;
	struct fwnode_handle *vcm_fwnode;
	struct i2c_client *vcm_client;
	struct acpi_device *adev;
	char *sep;

	adev = ACPI_COMPANION(sensor);
	if (!adev)
		return 0;

	vcm_fwnode = fwnode_find_reference(dev_fwnode(sensor), "lens-focus", 0);
	if (IS_ERR(vcm_fwnode))
		return 0;

	/* When reloading modules the client will already exist */
	vcm_client = i2c_find_device_by_fwnode(vcm_fwnode);
	if (vcm_client) {
		fwnode_handle_put(vcm_fwnode);
		put_device(&vcm_client->dev);
		return 0;
	}

	data = kzalloc_obj(*data);
	if (!data) {
		fwnode_handle_put(vcm_fwnode);
		return -ENOMEM;
	}

	INIT_WORK(&data->work, ipu_bridge_instantiate_vcm_work);
	data->sensor = get_device(sensor);
	snprintf(data->name, sizeof(data->name), "%s-VCM",
		 acpi_dev_name(adev));
	data->board_info.dev_name = data->name;
	data->board_info.fwnode = vcm_fwnode;
	snprintf(data->board_info.type, sizeof(data->board_info.type),

Annotation

Implementation Notes