drivers/staging/media/atomisp/pci/atomisp_cmd.c

Source file repositories/reference/linux-study-clean/drivers/staging/media/atomisp/pci/atomisp_cmd.c

File Facts

System
Linux kernel
Corpus path
drivers/staging/media/atomisp/pci/atomisp_cmd.c
Extension
.c
Size
136043 bytes
Lines
4671
Domain
Driver Families
Bucket
drivers/staging
Inferred role
Driver Families: implementation source
Status
source 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

while ((isp_sspm1 & ISP_FREQ_VALID_MASK) && timeout) {
			iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM1, &isp_sspm1);
			dev_dbg(isp->dev, "waiting for ISPSSPM1 valid bit to be 0.\n");
			udelay(100);
			timeout--;
		}

		if (timeout != 0)
			break;
	}

	if (timeout == 0) {
		dev_err(isp->dev, "DFS failed due to HW error.\n");
		return -EINVAL;
	}

	iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM1, &isp_sspm1);
	timeout = 10;
	while (((isp_sspm1 >> ISP_FREQ_STAT_OFFSET) != ratio) && timeout) {
		iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM1, &isp_sspm1);
		dev_dbg(isp->dev, "waiting for ISPSSPM1 status bit to be 0x%x.\n",
			new_freq);
		udelay(100);
		timeout--;
	}
	if (timeout == 0) {
		dev_err(isp->dev, "DFS target freq is rejected by HW.\n");
		return -EINVAL;
	}

	return 0;
}

int atomisp_freq_scaling(struct atomisp_device *isp,
			 enum atomisp_dfs_mode mode,
			 bool force)
{
	const struct atomisp_dfs_config *dfs;
	unsigned int new_freq;
	struct atomisp_freq_scaling_rule curr_rules;
	int i, ret;
	unsigned short fps = 0;

	dfs = isp->dfs;

	if (dfs->lowest_freq == 0 || dfs->max_freq_at_vmin == 0 ||
	    dfs->highest_freq == 0 || dfs->dfs_table_size == 0 ||
	    !dfs->dfs_table) {
		dev_err(isp->dev, "DFS configuration is invalid.\n");
		return -EINVAL;
	}

	if (mode == ATOMISP_DFS_MODE_LOW) {
		new_freq = dfs->lowest_freq;
		goto done;
	}

	if (mode == ATOMISP_DFS_MODE_MAX) {
		new_freq = dfs->highest_freq;
		goto done;
	}

	fps = atomisp_get_sensor_fps(&isp->asd);
	if (fps == 0) {
		dev_info(isp->dev,
			 "Sensor didn't report FPS. Using DFS max mode.\n");
		new_freq = dfs->highest_freq;
		goto done;
	}

	curr_rules.width = isp->asd.fmt[ATOMISP_SUBDEV_PAD_SOURCE].fmt.width;
	curr_rules.height = isp->asd.fmt[ATOMISP_SUBDEV_PAD_SOURCE].fmt.height;
	curr_rules.fps = fps;
	curr_rules.run_mode = isp->asd.run_mode->val;

	/* search for the target frequency by looping freq rules*/
	for (i = 0; i < dfs->dfs_table_size; i++) {
		if (curr_rules.width != dfs->dfs_table[i].width &&
		    dfs->dfs_table[i].width != ISP_FREQ_RULE_ANY)
			continue;
		if (curr_rules.height != dfs->dfs_table[i].height &&
		    dfs->dfs_table[i].height != ISP_FREQ_RULE_ANY)
			continue;
		if (curr_rules.fps != dfs->dfs_table[i].fps &&
		    dfs->dfs_table[i].fps != ISP_FREQ_RULE_ANY)
			continue;
		if (curr_rules.run_mode != dfs->dfs_table[i].run_mode &&
		    dfs->dfs_table[i].run_mode != ISP_FREQ_RULE_ANY)
			continue;
		break;

Annotation

Implementation Notes