static void atomisp_unregister_entities(struct atomisp_device *isp)
{
	atomisp_subdev_unregister_entities(&isp->isp_subdev);
	atomisp_tpg_unregister_entities(&isp->tpg);
	atomisp_file_input_unregister_entities(&isp->file_dev);
	atomisp_mipi_csi2_unregister_entities(&isp->csi2_1p);
	atomisp_mipi_csi2_unregister_entities(&isp->csi2_4p);

	v4l2_device_unregister(&isp->v4l2_dev);
	media_device_unregister(&isp->media_dev);
}
static void atomisp_unregister_entities(struct atomisp_device *isp)
{
	unsigned int i;

	for (i = 0; i < isp->num_of_streams; i++)
		atomisp_subdev_unregister_entities(&isp->isp_subdev[i]);
	atomisp_tpg_unregister_entities(&isp->tpg);
	atomisp_file_input_unregister_entities(&isp->file_dev);
	for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++)
		atomisp_mipi_csi2_unregister_entities(&isp->csi2_port[i]);

	v4l2_device_unregister(&isp->v4l2_dev);
	media_device_unregister(&isp->media_dev);
}
int atomisp_tpg_register_entities(struct atomisp_tpg_device *tpg,
			struct v4l2_device *vdev)
{
	int ret;
	/* Register the subdev and video nodes. */
	ret = v4l2_device_register_subdev(vdev, &tpg->sd);
	if (ret < 0)
		goto error;

	return 0;

error:
	atomisp_tpg_unregister_entities(tpg);
	return ret;
}
static int atomisp_register_entities(struct atomisp_device *isp)
{
	int ret = 0;
	unsigned int i;

	isp->media_dev.dev = isp->dev;

	strlcpy(isp->media_dev.model, "Intel Atom ISP",
		sizeof(isp->media_dev.model));

	ret = media_device_register(&isp->media_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev, "%s: Media device registration "
			 "failed (%d)\n", __func__, ret);
		return ret;
	}

	isp->v4l2_dev.mdev = &isp->media_dev;
	ret = v4l2_device_register(isp->dev, &isp->v4l2_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev,
			"%s: V4L2 device registration failed (%d)\n",
			__func__, ret);
		goto v4l2_device_failed;
	}

	ret = atomisp_subdev_probe(isp);
	if (ret < 0)
		goto csi_and_subdev_probe_failed;

	/* Register internal entities */
	for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) {
		ret = atomisp_mipi_csi2_register_entities(&isp->csi2_port[i],
								&isp->v4l2_dev);
		if (ret == 0)
			continue;

		/* error case */
		v4l2_err(&atomisp_dev,
			"failed to register the CSI port: %d\n", i);
		/* deregister all registered CSI ports */
		while (i--)
			atomisp_mipi_csi2_unregister_entities(
							&isp->csi2_port[i]);

		goto csi_and_subdev_probe_failed;
	}

	ret =
	atomisp_file_input_register_entities(&isp->file_dev, &isp->v4l2_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev,
			"atomisp_file_input_register_entities\n");
		goto file_input_register_failed;
	}

	ret = atomisp_tpg_register_entities(&isp->tpg, &isp->v4l2_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev, "atomisp_tpg_register_entities\n");
		goto tpg_register_failed;
	}

	for (i = 0; i < isp->num_of_streams; i++) {
		ret =
		atomisp_subdev_register_entities(&isp->isp_subdev[i],
						 &isp->v4l2_dev);
		if (ret < 0) {
			v4l2_err(&atomisp_dev,
				"atomisp_subdev_register_entities fail\n");
			goto subdev_register_failed;
		}
	}

	for (i = 0; i < isp->input_cnt; i++) {
		if (isp->inputs[i].port >= ATOMISP_CAMERA_NR_PORTS) {
			v4l2_err(&atomisp_dev,
					"isp->inputs port %d not supported\n",
					isp->inputs[i].port);
			ret = -EINVAL;
			goto link_failed;
		}

		ret = media_entity_create_link(
			&isp->inputs[i].camera->entity, 0,
			&isp->csi2_port[isp->inputs[i].port].subdev.entity,
			CSI2_PAD_SINK,
			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
		if (ret < 0) {
			dev_err(isp->dev,
				"link create from sensor to csi-2 receiver failed\n");
			goto link_failed;
		}
	}

	v4l2_dbg(1, dbg_level, &atomisp_dev,
		"FILE_INPUT enable, camera_cnt: %d\n", isp->input_cnt);
	isp->inputs[isp->input_cnt].type = FILE_INPUT;
	isp->inputs[isp->input_cnt].port = -1;
	isp->inputs[isp->input_cnt].shading_table = NULL;
	isp->inputs[isp->input_cnt].morph_table = NULL;
	isp->inputs[isp->input_cnt++].camera = &isp->file_dev.sd;

	if (isp->input_cnt < ATOM_ISP_MAX_INPUTS) {
		v4l2_dbg(1, dbg_level, &atomisp_dev,
			"TPG detected, camera_cnt: %d\n", isp->input_cnt);
		isp->inputs[isp->input_cnt].type = TEST_PATTERN;
		isp->inputs[isp->input_cnt].port = -1;
		isp->inputs[isp->input_cnt].shading_table = NULL;
		isp->inputs[isp->input_cnt].morph_table = NULL;
		isp->inputs[isp->input_cnt++].camera = &isp->tpg.sd;
	} else {
		v4l2_warn(&atomisp_dev,
			"too many atomisp inputs, TPG ignored.\n");
	}

	ret = v4l2_device_register_subdev_nodes(&isp->v4l2_dev);
	if (ret < 0)
		goto link_failed;

	return ret;

link_failed:
	for (i = 0; i < isp->num_of_streams; i++)
		atomisp_subdev_unregister_entities(&isp->isp_subdev[i]);
subdev_register_failed:
	while (i--)
		atomisp_subdev_unregister_entities(&isp->isp_subdev[i]);
	atomisp_tpg_unregister_entities(&isp->tpg);
tpg_register_failed:
	atomisp_file_input_unregister_entities(&isp->file_dev);
file_input_register_failed:
	for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++)
		atomisp_mipi_csi2_unregister_entities(&isp->csi2_port[i]);
csi_and_subdev_probe_failed:
	v4l2_device_unregister(&isp->v4l2_dev);
v4l2_device_failed:
	media_device_unregister(&isp->media_dev);
	return ret;
}
static int atomisp_register_entities(struct atomisp_device *isp)
{
	int ret = 0;
	int i = 0;
	struct v4l2_subdev *subdev = NULL;
	struct media_entity *input = NULL;
	unsigned int flags;
	unsigned int pad;

	isp->media_dev.dev = isp->dev;

	strlcpy(isp->media_dev.model, "Intel Atom ISP",
		sizeof(isp->media_dev.model));

	ret = media_device_register(&isp->media_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev, "%s: Media device registration "
			 "failed (%d)\n", __func__, ret);
		return ret;
	}

	isp->v4l2_dev.mdev = &isp->media_dev;
	ret = v4l2_device_register(isp->dev, &isp->v4l2_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev,
			"%s: V4L2 device registration failed (%d)\n",
			__func__, ret);
		goto v4l2_device_failed;
	}

	/*
	 * fixing me!
	 * not sub device exists on
	 * mrfld vp
	 */
	if (!IS_MRFLD) {
		ret = atomisp_subdev_probe(isp);
		if (ret < 0)
			goto lane4_and_subdev_probe_failed;
	}

	/* Register internal entities */
	ret =
	atomisp_mipi_csi2_register_entities(&isp->csi2_4p, &isp->v4l2_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev,
			"atomisp_mipi_csi2_register_entities 4p\n");
		goto lane4_and_subdev_probe_failed;
	}

	ret =
	atomisp_mipi_csi2_register_entities(&isp->csi2_1p, &isp->v4l2_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev,
			"atomisp_mipi_csi2_register_entities 1p\n");
		goto lane1_failed;
	}

	ret =
	atomisp_file_input_register_entities(&isp->file_dev, &isp->v4l2_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev,
			"atomisp_file_input_register_entities\n");
		goto file_input_register_failed;
	}

	ret = atomisp_tpg_register_entities(&isp->tpg, &isp->v4l2_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev, "atomisp_tpg_register_entities\n");
		goto tpg_register_failed;
	}

	ret =
	atomisp_subdev_register_entities(&isp->isp_subdev, &isp->v4l2_dev);
	if (ret < 0) {
		v4l2_err(&atomisp_dev,
			"atomisp_subdev_register_entities fail\n");
		goto subdev_register_failed;
	}

	for (i = 0; i < isp->input_cnt; i++) {
		subdev = isp->inputs[i].camera;
		switch (isp->inputs[i].port) {
		case ATOMISP_CAMERA_PORT_PRIMARY:
			input = &isp->csi2_4p.subdev.entity;
			pad = CSI2_PAD_SINK;
			flags = 0;
			break;
		case ATOMISP_CAMERA_PORT_SECONDARY:
			input = &isp->csi2_1p.subdev.entity;
			pad = CSI2_PAD_SINK;
			flags = 0;
			break;
		default:
			v4l2_dbg(1, dbg_level, &atomisp_dev,
				  "isp->inputs type not supported\n");
			break;
		}
		ret = media_entity_create_link(&subdev->entity, 0,
			input, pad, flags);
		if (ret < 0) {
			v4l2_err(&atomisp_dev,
				"snr to mipi csi link failed\n");
			goto link_failed;
		}
	}

	v4l2_dbg(1, dbg_level, &atomisp_dev,
		"FILE_INPUT enable, camera_cnt: %d\n", isp->input_cnt);
	isp->inputs[isp->input_cnt].type = FILE_INPUT;
	isp->inputs[isp->input_cnt].port = -1;
	isp->inputs[isp->input_cnt].shading_table = NULL;
	isp->inputs[isp->input_cnt].morph_table = NULL;
	isp->inputs[isp->input_cnt++].camera = &isp->file_dev.sd;

	if (isp->input_cnt < ATOM_ISP_MAX_INPUTS) {
		v4l2_dbg(1, dbg_level, &atomisp_dev,
			"TPG detected, camera_cnt: %d\n", isp->input_cnt);
		isp->inputs[isp->input_cnt].type = TEST_PATTERN;
		isp->inputs[isp->input_cnt].port = -1;
		isp->inputs[isp->input_cnt].shading_table = NULL;
		isp->inputs[isp->input_cnt].morph_table = NULL;
		isp->inputs[isp->input_cnt++].camera = &isp->tpg.sd;
	} else {
		v4l2_warn(&atomisp_dev,
			"too many atomisp inputs, TPG ignored.\n");
	}

	ret = v4l2_device_register_subdev_nodes(&isp->v4l2_dev);
	if (ret < 0)
		goto link_failed;

	return ret;

link_failed:
	atomisp_subdev_unregister_entities(&isp->isp_subdev);
subdev_register_failed:
	atomisp_tpg_unregister_entities(&isp->tpg);
tpg_register_failed:
	atomisp_file_input_unregister_entities(&isp->file_dev);
file_input_register_failed:
	atomisp_mipi_csi2_unregister_entities(&isp->csi2_1p);
lane1_failed:
	atomisp_mipi_csi2_unregister_entities(&isp->csi2_4p);
lane4_and_subdev_probe_failed:
	v4l2_device_unregister(&isp->v4l2_dev);
v4l2_device_failed:
	media_device_unregister(&isp->media_dev);
	return ret;
}