int atomisp_tpg_init(struct atomisp_device *isp)
{
	struct atomisp_tpg_device *tpg = &isp->tpg;
	struct v4l2_subdev *sd = &tpg->sd;
	struct media_pad *pads = tpg->pads;
	struct media_entity *me = &sd->entity;
	int ret;

	tpg->isp = isp;
	v4l2_subdev_init(sd, &tpg_ops);
	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
	strcpy(sd->name, "tpg_subdev");
	v4l2_set_subdevdata(sd, tpg);

	pads[0].flags = MEDIA_PAD_FL_SINK;
	me->function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN;

	ret = media_entity_pads_init(me, 1, pads);
	if (ret < 0)
		goto fail;
	return 0;
fail:
	atomisp_tpg_cleanup(isp);
	return ret;
}
static int atomisp_initialize_modules(struct atomisp_device *isp)
{
	int ret;

	ret = atomisp_mipi_csi2_init(isp);
	if (ret < 0) {
		v4l2_err(&atomisp_dev, "mipi csi2 initialization failed\n");
		goto error_mipi_csi2;
	}

	ret = atomisp_file_input_init(isp);
	if (ret < 0) {
		v4l2_err(&atomisp_dev,
			"file input device initialization failed\n");
		goto error_file_input;
	}

	ret = atomisp_tpg_init(isp);
	if (ret < 0) {
		v4l2_err(&atomisp_dev, "tpg initialization failed\n");
		goto error_tpg;
	}

	ret = atomisp_subdev_init(isp);
	if (ret < 0) {
		v4l2_err(&atomisp_dev, "ISP subdev initialization failed\n");
		goto error_isp_subdev;
	}

	/* connet submoduels */
	ret = media_entity_create_link(
			&isp->csi2_4p.subdev.entity,
			CSI2_PAD_SOURCE,
			&isp->isp_subdev.subdev.entity,
			ATOMISP_SUBDEV_PAD_SINK,
			0);
	if (ret < 0)
		goto error_link;
	ret = media_entity_create_link(
			&isp->csi2_1p.subdev.entity,
			CSI2_PAD_SOURCE,
			&isp->isp_subdev.subdev.entity,
			ATOMISP_SUBDEV_PAD_SINK,
			0);
	if (ret < 0)
		goto error_link;
	return 0;

error_link:
error_isp_subdev:
	atomisp_subdev_cleanup(isp);
error_tpg:
	atomisp_tpg_cleanup(isp);
error_file_input:
	atomisp_file_input_cleanup(isp);
error_mipi_csi2:
	atomisp_mipi_csi2_cleanup(isp);
	return ret;
}
static int atomisp_initialize_modules(struct atomisp_device *isp)
{
	int ret;
	unsigned int i, j;

	ret = atomisp_mipi_csi2_init(isp);
	if (ret < 0) {
		v4l2_err(&atomisp_dev, "mipi csi2 initialization failed\n");
		goto error_mipi_csi2;
	}

	ret = atomisp_file_input_init(isp);
	if (ret < 0) {
		v4l2_err(&atomisp_dev,
			"file input device initialization failed\n");
		goto error_file_input;
	}

	ret = atomisp_tpg_init(isp);
	if (ret < 0) {
		v4l2_err(&atomisp_dev, "tpg initialization failed\n");
		goto error_tpg;
	}

	ret = atomisp_subdev_init(isp);
	if (ret < 0) {
		v4l2_err(&atomisp_dev, "ISP subdev initialization failed\n");
		goto error_isp_subdev;
	}

	/* connet submoduels */
	for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) {
		for (j = 0; j < isp->num_of_streams; j++) {
			ret = media_entity_create_link(
				&isp->csi2_port[i].subdev.entity,
				CSI2_PAD_SOURCE,
				&isp->isp_subdev[j].subdev.entity,
				ATOMISP_SUBDEV_PAD_SINK,
				0);
			if (ret < 0)
				goto error_link;
		}
	}
	return 0;

error_link:
error_isp_subdev:
	atomisp_subdev_cleanup(isp);
error_tpg:
	atomisp_tpg_cleanup(isp);
error_file_input:
	atomisp_file_input_cleanup(isp);
error_mipi_csi2:
	atomisp_mipi_csi2_cleanup(isp);
	return ret;
}