drivers/soundwire/intel_init.c

Source file repositories/reference/linux-study-clean/drivers/soundwire/intel_init.c

File Facts

System
Linux kernel
Corpus path
drivers/soundwire/intel_init.c
Extension
.c
Size
10083 bytes
Lines
404
Domain
Driver Families
Bucket
drivers/soundwire
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

if (!link->cdns) {
			dev_err(&adev->dev, "failed to get link->cdns\n");
			/*
			 * 1 will be subtracted from i in the err label, but we need to call
			 * intel_link_dev_unregister for this ldev, so plus 1 now
			 */
			i++;
			goto err;
		}
		list_add_tail(&link->list, &ctx->link_list);
		bus = &link->cdns->bus;
		/* Calculate number of slaves */
		list_for_each(node, &bus->slaves)
			num_slaves++;
	}

	ctx->peripherals = kmalloc_flex(*ctx->peripherals, array, num_slaves);
	if (!ctx->peripherals)
		goto err;
	ctx->peripherals->num_peripherals = num_slaves;
	i = 0;
	list_for_each_entry(link, &ctx->link_list, list) {
		bus = &link->cdns->bus;
		list_for_each_entry(slave, &bus->slaves, node) {
			ctx->peripherals->array[i] = slave;
			i++;
		}
	}

	return ctx;

err:
	while (i--) {
		if (!(link_mask & BIT(i)))
			continue;
		ldev = ctx->ldev[i];
		intel_link_dev_unregister(ldev);
	}
	kfree(ctx->ldev);
	kfree(ctx);
	return NULL;
}

static int
sdw_intel_startup_controller(struct sdw_intel_ctx *ctx)
{
	struct acpi_device *adev = acpi_fetch_acpi_dev(ctx->handle);
	struct sdw_intel_link_dev *ldev;
	u32 link_mask;
	int i;

	if (!adev)
		return -EINVAL;

	if (!ctx->ldev)
		return -EINVAL;

	link_mask = ctx->link_mask;

	/* Startup SDW Master devices */
	for (i = 0; i < ctx->count; i++) {
		if (!(link_mask & BIT(i)))
			continue;

		ldev = ctx->ldev[i];

		intel_link_startup(&ldev->auxdev);

		if (!ldev->link_res.clock_stop_quirks) {
			/*
			 * we need to prevent the parent PCI device
			 * from entering pm_runtime suspend, so that
			 * power rails to the SoundWire IP are not
			 * turned off.
			 */
			pm_runtime_get_noresume(ldev->link_res.dev);
		}
	}

	return 0;
}

/**
 * sdw_intel_probe() - SoundWire Intel probe routine
 * @res: resource data
 *
 * This registers an auxiliary device for each Master handled by the controller,
 * and SoundWire Master and Slave devices will be created by the auxiliary
 * device probe. All the information necessary is stored in the context, and
 * the res argument pointer can be freed after this step.

Annotation

Implementation Notes