drivers/media/platform/samsung/s3c-camif/camif-core.c

Source file repositories/reference/linux-study-clean/drivers/media/platform/samsung/s3c-camif/camif-core.c

File Facts

System
Linux kernel
Corpus path
drivers/media/platform/samsung/s3c-camif/camif-core.c
Extension
.c
Size
15330 bytes
Lines
648
Domain
Driver Families
Bucket
drivers/media
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

if (src >= tar * tmp) {
			*shift = sh;
			*ratio = tmp;
			return 0;
		}
	}
	*shift = 0;
	*ratio = 1;
	return 0;
}

int s3c_camif_get_scaler_config(struct camif_vp *vp,
				struct camif_scaler *scaler)
{
	struct v4l2_rect *camif_crop = &vp->camif->camif_crop;
	int source_x = camif_crop->width;
	int source_y = camif_crop->height;
	int target_x = vp->out_frame.rect.width;
	int target_y = vp->out_frame.rect.height;
	int ret;

	if (vp->rotation == 90 || vp->rotation == 270)
		swap(target_x, target_y);

	ret = camif_get_scaler_factor(source_x, target_x, &scaler->pre_h_ratio,
				      &scaler->h_shift);
	if (ret < 0)
		return ret;

	ret = camif_get_scaler_factor(source_y, target_y, &scaler->pre_v_ratio,
				      &scaler->v_shift);
	if (ret < 0)
		return ret;

	scaler->pre_dst_width = source_x / scaler->pre_h_ratio;
	scaler->pre_dst_height = source_y / scaler->pre_v_ratio;

	scaler->main_h_ratio = (source_x << 8) / (target_x << scaler->h_shift);
	scaler->main_v_ratio = (source_y << 8) / (target_y << scaler->v_shift);

	scaler->scaleup_h = (target_x >= source_x);
	scaler->scaleup_v = (target_y >= source_y);

	scaler->copy = 0;

	pr_debug("H: ratio: %u, shift: %u. V: ratio: %u, shift: %u.\n",
		 scaler->pre_h_ratio, scaler->h_shift,
		 scaler->pre_v_ratio, scaler->v_shift);

	pr_debug("Source: %dx%d, Target: %dx%d, scaleup_h/v: %d/%d\n",
		 source_x, source_y, target_x, target_y,
		 scaler->scaleup_h, scaler->scaleup_v);

	return 0;
}

static int camif_register_sensor(struct camif_dev *camif)
{
	struct s3c_camif_sensor_info *sensor = &camif->pdata.sensor;
	struct v4l2_device *v4l2_dev = &camif->v4l2_dev;
	struct i2c_adapter *adapter;
	struct v4l2_subdev_format format = {
		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
	};
	struct v4l2_subdev *sd;
	int ret;

	camif->sensor.sd = NULL;

	if (sensor->i2c_board_info.addr == 0)
		return -EINVAL;

	adapter = i2c_get_adapter(sensor->i2c_bus_num);
	if (adapter == NULL) {
		v4l2_warn(v4l2_dev, "failed to get I2C adapter %d\n",
			  sensor->i2c_bus_num);
		return -EPROBE_DEFER;
	}

	sd = v4l2_i2c_new_subdev_board(v4l2_dev, adapter,
				       &sensor->i2c_board_info, NULL);
	if (sd == NULL) {
		i2c_put_adapter(adapter);
		v4l2_warn(v4l2_dev, "failed to acquire subdev %s\n",
			  sensor->i2c_board_info.type);
		return -EPROBE_DEFER;
	}
	camif->sensor.sd = sd;

	v4l2_info(v4l2_dev, "registered sensor subdevice %s\n", sd->name);

Annotation

Implementation Notes