static int mxr_streamer_get(struct mxr_device *mdev, struct v4l2_subdev *sd)
{
	int i;
	int ret = 0;
	int local = 1;
	struct sub_mxr_device *sub_mxr;
	struct mxr_layer *layer;
	struct media_pad *pad;
	struct v4l2_mbus_framefmt mbus_fmt;
#if defined(CONFIG_CPU_EXYNOS4210)
	struct mxr_resources *res = &mdev->res;
#endif
	struct v4l2_control ctrl;

	mutex_lock(&mdev->s_mutex);
	++mdev->n_streamer;
	mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_streamer);
	/* If pipeline is started from Gscaler input video device,
	 * TV basic configuration must be set before running mixer */
	if (mdev->mxr_data_from == FROM_GSC_SD) {
		mxr_dbg(mdev, "%s: from gscaler\n", __func__);
		local = 0;
		/* enable mixer clock */
		ret = mxr_power_get(mdev);
		if (ret) {
			mxr_err(mdev, "power on failed\n");
			ret = -ENODEV;
			goto out;
		}
		/* turn on connected output device through link
		 * with mixer */
		mxr_output_get(mdev);

		for (i = 0; i < MXR_MAX_SUB_MIXERS; ++i) {
			sub_mxr = &mdev->sub_mxr[i];
			if (sub_mxr->local) {
				layer = sub_mxr->layer[MXR_LAYER_VIDEO];
				layer->pipe.state = MXR_PIPELINE_STREAMING;
				mxr_layer_geo_fix(layer);
				layer->ops.format_set(layer, layer->fmt,
							    &layer->geo);
				layer->ops.stream_set(layer, 1);
				local += sub_mxr->local;
			}
		}
		if (local == 2)
			mxr_layer_sync(mdev, MXR_ENABLE);

		/* Set the TVOUT register about gsc-mixer local path */
		mxr_reg_local_path_set(mdev, mdev->mxr0_gsc, mdev->mxr1_gsc,
				mdev->flags);
	}

	/* Alpha blending configuration always can be changed
	 * whenever streaming */
	mxr_set_alpha_blend(mdev);
	mxr_reg_set_color_range(mdev);
	mxr_reg_set_layer_prio(mdev);

	if ((mdev->n_streamer == 1 && local == 1) ||
	    (mdev->n_streamer == 2 && local == 2)) {
		for (i = MXR_PAD_SOURCE_GSCALER; i < MXR_PADS_NUM; ++i) {
			pad = &sd->entity.pads[i];

			/* find sink pad of output via enabled link*/
			pad = media_entity_remote_source(pad);
			if (pad)
				if (media_entity_type(pad->entity)
						== MEDIA_ENT_T_V4L2_SUBDEV)
					break;

			if (i == MXR_PAD_SOURCE_GRP1) {
				ret = -ENODEV;
				goto out;
			}
		}

		sd = media_entity_to_v4l2_subdev(pad->entity);

		mxr_dbg(mdev, "cookie of current output = (%d)\n",
			to_output(mdev)->cookie);

#if defined(CONFIG_CPU_EXYNOS4210)
		if (to_output(mdev)->cookie == 0)
			clk_set_parent(res->sclk_mixer, res->sclk_dac);
		else
			clk_set_parent(res->sclk_mixer, res->sclk_hdmi);
#endif
		mxr_reg_s_output(mdev, to_output(mdev)->cookie);

		ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mbus_fmt);
		if (ret) {
			mxr_err(mdev, "failed to get mbus_fmt for output %s\n",
					sd->name);
			goto out;
		}
		ctrl.id = V4L2_CID_TV_GET_DVI_MODE;
		ret = v4l2_subdev_call(sd, core, g_ctrl, &ctrl);
		if (ret) {
			mxr_err(mdev, "failed to get DVI or HDMI mode %s\n",
					sd->name);
			goto out;
		}

		mxr_reg_set_mbus_fmt(mdev, &mbus_fmt, ctrl.value);
		ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mbus_fmt);
		if (ret) {
			mxr_err(mdev, "failed to set mbus_fmt for output %s\n",
					sd->name);
			goto out;
		}
		mxr_reg_streamon(mdev);

		ret = v4l2_subdev_call(sd, video, s_stream, 1);
		if (ret) {
			mxr_err(mdev, "starting stream failed for output %s\n",
					sd->name);
			goto out;
		}

		ret = mxr_reg_wait4update(mdev);
		if (ret) {
			mxr_err(mdev, "failed to get vsync (%d) from output\n",
					ret);
			goto out;
		}
	}

out:
	mutex_unlock(&mdev->s_mutex);
	mxr_reg_dump(mdev);

	return ret;
}
Пример #2
0
static int mxr_streamer_get(struct mxr_device *mdev, struct v4l2_subdev *sd)
{
	int i;
	int ret = 0;
	int local = 1;
	struct sub_mxr_device *sub_mxr;
	struct mxr_layer *layer;
	struct media_pad *pad;
	struct s5p_mxr_platdata *pdata = mdev->pdata;
	struct v4l2_mbus_framefmt mbus_fmt;
	struct v4l2_control ctrl;

	mutex_lock(&mdev->s_mutex);
	++mdev->n_streamer;
	mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_streamer);

	/* If pipeline is started from Gscaler input video device,
	 * TV basic configuration must be set before running mixer */
	if (mdev->mxr_data_from == FROM_GSC_SD) {
		mxr_dbg(mdev, "%s: from gscaler\n", __func__);
		local = 0;
		/* enable mixer clock */
		ret = mxr_power_get(mdev);
		if (ret < 0) {
			mxr_err(mdev, "power on failed for video layer\n");
			ret = -ENODEV;
			goto out;
		}

		for (i = 0; i < MXR_MAX_SUB_MIXERS; ++i) {
			sub_mxr = &mdev->sub_mxr[i];
			if (sub_mxr->local) {
				layer = sub_mxr->layer[MXR_LAYER_VIDEO];
				layer->pipe.state = MXR_PIPELINE_STREAMING;
				mxr_layer_geo_fix(layer);
				layer->ops.format_set(layer, layer->fmt,
							    &layer->geo);
				layer->ops.stream_set(layer, 1);
				local += sub_mxr->local;
			}
		}
		if (local == 2)
			mxr_layer_sync(mdev, MXR_ENABLE);

		/* Set the TVOUT register about gsc-mixer local path */
		mxr_reg_local_path_set(mdev);
	}

	/* Alpha blending configuration always can be changed
	 * whenever streaming */
	mxr_set_alpha_blend(mdev);
	mxr_reg_set_color_range(mdev);
	mxr_reg_set_layer_prio(mdev);
	if (is_ip_ver_5s || is_ip_ver_5s2)
		mxr_reg_set_resolution(mdev);

	if ((mdev->n_streamer == 1 && local == 1) ||
	    (mdev->n_streamer == 2 && local == 2)) {
#if defined(CONFIG_TV_USE_BUS_DEVFREQ)
		if (is_ip_ver_5a)
			pm_qos_add_request(&exynos5_tv_mif_qos, PM_QOS_BUS_THROUGHPUT, 800000);
		pm_qos_add_request(&exynos5_tv_int_qos, PM_QOS_DEVICE_THROUGHPUT, 400000);
#endif

		for (i = MXR_PAD_SOURCE_GSCALER; i < MXR_PADS_NUM; ++i) {
			pad = &sd->entity.pads[i];

			/* find sink pad of output via enabled link*/
			pad = media_entity_remote_source(pad);
			if (pad)
				if (media_entity_type(pad->entity)
						== MEDIA_ENT_T_V4L2_SUBDEV)
					break;

			if (i == MXR_PAD_SOURCE_GRP1) {
				ret = -ENODEV;
				goto out;
			}
		}

		sd = media_entity_to_v4l2_subdev(pad->entity);

		mxr_dbg(mdev, "cookie of current output = (%d)\n",
			to_output(mdev)->cookie);

		mxr_reg_s_output(mdev, to_output(mdev)->cookie);

		ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mbus_fmt);
		if (ret) {
			mxr_err(mdev, "failed to get mbus_fmt for output %s\n",
					sd->name);
			goto out;
		}
		ctrl.id = V4L2_CID_TV_GET_DVI_MODE;
		ret = v4l2_subdev_call(sd, core, g_ctrl, &ctrl);
		if (ret) {
			mxr_err(mdev, "failed to get DVI or HDMI mode %s\n",
					sd->name);
			goto out;
		}

		mxr_reg_set_mbus_fmt(mdev, &mbus_fmt, ctrl.value);
		ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mbus_fmt);
		if (ret) {
			mxr_err(mdev, "failed to set mbus_fmt for output %s\n",
					sd->name);
			goto out;
		}
		mxr_reg_streamon(mdev);

		/* start hdmi */
		ctrl.id = V4L2_CID_TV_HDMI_STATUS;
		ret = v4l2_subdev_call(sd, core, g_ctrl, &ctrl);
		if (ret) {
			mxr_err(mdev, "failed to get output %s status for start\n",
					sd->name);
			goto out;
		}

		if (ctrl.value == (HDMI_STOP | HPD_HIGH)) {
			ret = v4l2_subdev_call(sd, core, s_power, 1);
			if (ret) {
				mxr_err(mdev, "failed to get power for output %s\n",
						sd->name);
				goto out;
			}
			ret = v4l2_subdev_call(sd, video, s_stream, 1);
			if (ret) {
				mxr_err(mdev, "starting stream failed for output %s\n",
						sd->name);
				goto out;
			}
		}

		ret = mxr_reg_wait4update(mdev);
		if (ret) {
			mxr_err(mdev, "failed to get vsync (%d) from output\n",
					ret);
			goto out;
		}
	}

out:
	mutex_unlock(&mdev->s_mutex);
	mxr_reg_dump(mdev);

	return ret;
}