static int fimc_is_isp_video_s_input(struct file *file, void *priv,
	unsigned int input)
{
	int ret = 0;
	u32 dindex;
	u32 flag;
	u32 group_id;
	u32 module, ssx_vindex, tax_vindex, rep_stream;
	struct fimc_is_video *video;
	struct fimc_is_video_ctx *vctx = file->private_data;
	struct fimc_is_core *core;
	struct fimc_is_device_ischain *device, *temp;
	struct fimc_is_device_sensor *sensor;

	BUG_ON(!vctx);
	BUG_ON(!vctx->video);

	mdbgv_isp("%s(input : %08X)\n", vctx, __func__, input);

	flag = 0;
	temp = NULL;
	device = NULL;
	sensor = NULL;
	video = vctx->video;
	core = container_of(video, struct fimc_is_core, video_isp);
	module = input & MODULE_MASK;
	ssx_vindex = (input & SSX_VINDEX_MASK) >> SSX_VINDEX_SHIFT;
	tax_vindex = (input & TAX_VINDEX_MASK) >> TAX_VINDEX_SHIFT;
	rep_stream = (input & REPROCESSING_MASK) >> REPROCESSING_SHIFT;

	device = vctx->device;
	if (!device) {
		merr("device is NULL", vctx);
		ret = -EINVAL;
		goto p_err;
	}

	/* 1. checking sensor video node to connect */
	if (ssx_vindex == FIMC_IS_VIDEO_SS0_NUM) {
		sensor = &core->sensor[0];
		info("[ISP:V:%d] <-> [SS0:V:0]\n", vctx->instance);
	} else if (ssx_vindex == FIMC_IS_VIDEO_SS1_NUM) {
		sensor = &core->sensor[1];
		info("[ISP:V:%d] <-> [SS1:V:0]\n", vctx->instance);
	} else {
		sensor = NULL;
		merr("sensor is not matched", vctx);
		ret = -EINVAL;
		goto p_err;
	}

	if (!test_bit(FIMC_IS_SENSOR_OPEN, &sensor->state)) {
		merr("sensor%d is not opened", vctx, ssx_vindex);
		ret = -EINVAL;
		goto p_err;
	}

	/* if there's only one group of isp, defines group id to 3a0 connected */
	if (GET_FIMC_IS_NUM_OF_SUBIP(core, 3a0)
			|| GET_FIMC_IS_NUM_OF_SUBIP(core, 3a1)) {

		/* 2. checking 3ax group to connect */
		if ((tax_vindex == FIMC_IS_VIDEO_3A0C_NUM) ||
			(tax_vindex == FIMC_IS_VIDEO_3A0P_NUM)) {
			group_id = GROUP_ID_3A0;
			info("[ISP:V:%d] <-> [3A0:V:0]\n", device->instance);
		} else if ((tax_vindex == FIMC_IS_VIDEO_3A1C_NUM) ||
			(tax_vindex == FIMC_IS_VIDEO_3A1P_NUM)) {
			group_id = GROUP_ID_3A1;
			info("[ISP:V:%d] <-> [3A1:V:0]\n", device->instance);
		} else {
			group_id = GROUP_ID_INVALID;
			merr("group%d is invalid", device, group_id);
			ret = -EINVAL;
			goto p_err;
		}
	} else {
		group_id = GROUP_ID_3A0;
	}

	/* 3. checking reprocessing stream */
	if (rep_stream) {
		for (dindex = 0; dindex < FIMC_IS_MAX_NODES; ++dindex) {
			temp = &core->ischain[dindex];

			if (temp == device)
				continue;

			if (!test_bit(FIMC_IS_ISCHAIN_OPEN, &temp->state))
				continue;

			if (temp->module == module) {
				flag = REPROCESSING_FLAG | dindex;
				break;
			}

#ifdef DEBUG
			info("device.module(%08X) != ischain[%d].module(%08X)\n", module,
				dindex, temp->module);
#endif
		}

		if (dindex >= FIMC_IS_MAX_NODES) {
			merr("preview stream can NOT be found", vctx);
			ret = -EINVAL;
			goto p_err;
		}

		set_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state);
	} else {
		/* connect to sensor if it's not a reprocessing stream */
		sensor->ischain = device;
		flag = 0;
	}

	/* 4. init variable */
	device->instance_sensor = sensor->instance;
	device->sensor = sensor;

	/* 5. init ischain */
	ret = fimc_is_ischain_init(device, module, group_id, tax_vindex, flag);
	if (ret)
		merr("fimc_is_device_init(%d, %d, %d) is fail", vctx, module, group_id, rep_stream);

p_err:
	return ret;
}
Пример #2
0
int fimc_is_set_dvfs(struct fimc_is_device_ischain *device, u32 scenario_id)
{
	int ret = 0;
	int int_qos, mif_qos, i2c_qos, cam_qos, disp_qos, pwm_qos = 0;
	int refcount;
	struct fimc_is_core *core;
	struct fimc_is_resourcemgr *resourcemgr;
	struct fimc_is_dvfs_ctrl *dvfs_ctrl;

	if (device == NULL) {
		err("device is NULL\n");
		return -EINVAL;
	}

	core = (struct fimc_is_core *)device->interface->core;
	resourcemgr = device->resourcemgr;
	dvfs_ctrl = &(resourcemgr->dvfs_ctrl);
	if (!GET_FIMC_IS_NUM_OF_SUBIP(core, isp))
		refcount = atomic_read(&core->video_3a0.refcount);
	else
		refcount = atomic_read(&core->video_isp.refcount);

	if (refcount < 0) {
		err("invalid ischain refcount");
		goto exit;
	}

	int_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_INT, scenario_id);
	mif_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_MIF, scenario_id);
	i2c_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_I2C, scenario_id);
	cam_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_CAM, scenario_id);
	disp_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_DISP, scenario_id);
	pwm_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_PWM, scenario_id);

	if ((int_qos < 0) || (mif_qos < 0) || (i2c_qos < 0)
	|| (cam_qos < 0) || (disp_qos < 0) || (pwm_qos < 0)) {
		err("getting qos value is failed!!\n");
		return -EINVAL;
	}

	/* check current qos */
	if (int_qos && dvfs_ctrl->cur_int_qos != int_qos) {
		if (i2c_qos) {
			ret = fimc_is_itf_i2c_lock(device, i2c_qos, true);
			if (ret) {
				err("fimc_is_itf_i2_clock fail\n");
				goto exit;
			}
		}

		if (pwm_qos) {
			fimc_is_set_pwm(device, pwm_qos);
			if (ret) {
				err("fimc_is_set_pwm fail\n");
				goto exit;
			}
		}

		pm_qos_update_request(&exynos_isp_qos_int, int_qos);
		dvfs_ctrl->cur_int_qos = int_qos;

		if (i2c_qos) {
			/* i2c unlock */
			ret = fimc_is_itf_i2c_lock(device, i2c_qos, false);
			if (ret) {
				err("fimc_is_itf_i2c_unlock fail\n");
				goto exit;
			}
		}
	}

	if (mif_qos && dvfs_ctrl->cur_mif_qos != mif_qos) {
		pm_qos_update_request(&exynos_isp_qos_mem, mif_qos);
		dvfs_ctrl->cur_mif_qos = mif_qos;
	}

	if (cam_qos && dvfs_ctrl->cur_cam_qos != cam_qos) {
		pm_qos_update_request(&exynos_isp_qos_cam, cam_qos);
		dvfs_ctrl->cur_cam_qos = cam_qos;
	}

	if (disp_qos && dvfs_ctrl->cur_disp_qos != disp_qos) {
		pm_qos_update_request(&exynos_isp_qos_disp, disp_qos);
		dvfs_ctrl->cur_disp_qos = disp_qos;
	}

	pr_info("[RSC:%d]: New QoS [INT(%d), MIF(%d), CAM(%d), DISP(%d), I2C(%d), PWM(%d)]\n",
			device->instance, int_qos, mif_qos,
			cam_qos, disp_qos, i2c_qos, pwm_qos);
exit:
	return ret;
}