void mxr_streamer_put(struct mxr_device *mdev) { mutex_lock(&mdev->mutex); --mdev->n_streamer; mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_streamer); if (mdev->n_streamer == 0) { int ret; struct v4l2_subdev *sd = to_outsd(mdev); mxr_reg_streamoff(mdev); /* vsync applies Mixer setup */ ret = mxr_reg_wait4vsync(mdev); WARN(ret, "failed to get vsync (%d) from output\n", ret); ret = v4l2_subdev_call(sd, video, s_stream, 0); WARN(ret, "stopping stream failed for output %s\n", sd->name); } WARN(mdev->n_streamer < 0, "negative number of streamers (%d)\n", mdev->n_streamer); mutex_unlock(&mdev->mutex); mxr_reg_dump(mdev); }
static int mxr_streamer_put(struct mxr_device *mdev, struct v4l2_subdev *sd) { int i; int ret = 0; int local = 1; struct media_pad *pad; struct sub_mxr_device *sub_mxr; struct mxr_layer *layer; struct v4l2_subdev *hdmi_sd; struct v4l2_subdev *gsc_sd; struct exynos_entity_data *md_data; mutex_lock(&mdev->s_mutex); --mdev->n_streamer; mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_streamer); /* distinction number of local path */ if (mdev->mxr_data_from == FROM_GSC_SD) { local = 0; for (i = 0; i < MXR_MAX_SUB_MIXERS; ++i) { sub_mxr = &mdev->sub_mxr[i]; if (sub_mxr->local) local += sub_mxr->local; } if (local == 2) mxr_layer_sync(mdev, MXR_DISABLE); } if ((mdev->n_streamer == 0 && local == 1) || (mdev->n_streamer == 1 && 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; } } hdmi_sd = media_entity_to_v4l2_subdev(pad->entity); mxr_reg_streamoff(mdev); /* vsync applies Mixer setup */ ret = mxr_reg_wait4update(mdev); if (ret) { mxr_err(mdev, "failed to get vsync (%d) from output\n", ret); goto out; } } /* When using local path between gscaler and mixer, below stop sequence * must be processed */ if (mdev->mxr_data_from == FROM_GSC_SD) { pad = &sd->entity.pads[MXR_PAD_SINK_GSCALER]; pad = media_entity_remote_source(pad); if (pad) { gsc_sd = media_entity_to_v4l2_subdev( pad->entity); mxr_dbg(mdev, "stop from %s\n", gsc_sd->name); md_data = (struct exynos_entity_data *) gsc_sd->dev_priv; md_data->media_ops->power_off(gsc_sd); } } if ((mdev->n_streamer == 0 && local == 1) || (mdev->n_streamer == 1 && local == 2)) { ret = v4l2_subdev_call(hdmi_sd, video, s_stream, 0); if (ret) { mxr_err(mdev, "stopping stream failed for output %s\n", hdmi_sd->name); goto out; } } /* turn off connected output device through link * with mixer */ if (mdev->mxr_data_from == FROM_GSC_SD) { 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->ops.stream_set(layer, 0); layer->pipe.state = MXR_PIPELINE_IDLE; } } mxr_reg_local_path_clear(mdev); mxr_output_put(mdev); /* disable mixer clock */ mxr_power_put(mdev); } WARN(mdev->n_streamer < 0, "negative number of streamers (%d)\n", mdev->n_streamer); out: mutex_unlock(&mdev->s_mutex); mxr_reg_dump(mdev); return ret; }
static int mxr_streamer_put(struct mxr_device *mdev, struct v4l2_subdev *sd) { int i; int ret = 0; int local = 1; struct media_pad *pad; struct sub_mxr_device *sub_mxr; struct mxr_layer *layer; struct v4l2_subdev *hdmi_sd; struct v4l2_subdev *gsc_sd; struct exynos_entity_data *md_data; struct s5p_mxr_platdata *pdata = mdev->pdata; struct v4l2_control ctrl; mutex_lock(&mdev->s_mutex); --mdev->n_streamer; mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_streamer); /* distinction number of local path */ if (mdev->mxr_data_from == FROM_GSC_SD) { local = 0; for (i = 0; i < MXR_MAX_SUB_MIXERS; ++i) { sub_mxr = &mdev->sub_mxr[i]; if (sub_mxr->local) local += sub_mxr->local; } if (local == 2) mxr_layer_sync(mdev, MXR_DISABLE); /* stop gscaler --> waiting for frame done */ pad = &sd->entity.pads[MXR_PAD_SINK_GSCALER]; pad = media_entity_remote_source(pad); if (pad) { gsc_sd = media_entity_to_v4l2_subdev( pad->entity); mxr_dbg(mdev, "stop from %s\n", gsc_sd->name); md_data = (struct exynos_entity_data *) gsc_sd->dev_priv; if (is_ip_ver_5g_1 || is_ip_ver_5a_0) md_data->media_ops->power_off(gsc_sd); } /* disable video layer */ 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->ops.stream_set(layer, 0); layer->pipe.state = MXR_PIPELINE_IDLE; } } } if ((mdev->n_streamer == 0 && local == 1) || (mdev->n_streamer == 1 && 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; } } hdmi_sd = media_entity_to_v4l2_subdev(pad->entity); mxr_reg_streamoff(mdev); /* vsync applies Mixer setup */ ret = mxr_reg_wait4update(mdev); if (ret) { mxr_err(mdev, "failed to get vsync (%d) from output\n", ret); goto out; } /* stop hdmi */ ctrl.id = V4L2_CID_TV_HDMI_STATUS; ret = v4l2_subdev_call(hdmi_sd, core, g_ctrl, &ctrl); if (ret) { mxr_err(mdev, "failed to get output %s status for stop\n", hdmi_sd->name); goto out; } /* * HDMI should be turn off only when not in use. * 1. cable out * 2. suspend (blank is called at suspend) */ if (ctrl.value == (HDMI_STREAMING | HPD_LOW) || mdev->blank) { ret = v4l2_subdev_call(hdmi_sd, video, s_stream, 0); if (ret) { mxr_err(mdev, "stopping stream failed for output %s\n", hdmi_sd->name); goto out; } ret = v4l2_subdev_call(hdmi_sd, core, s_power, 0); if (ret) { mxr_err(mdev, "failed to put power for output %s\n", hdmi_sd->name); goto out; } mdev->blank = 0; } } /* disable mixer clock */ if (mdev->mxr_data_from == FROM_GSC_SD) mxr_power_put(mdev); WARN(mdev->n_streamer < 0, "negative number of streamers (%d)\n", mdev->n_streamer); out: #if defined(CONFIG_TV_USE_BUS_DEVFREQ) if ((mdev->n_streamer == 0 && local == 1) || (mdev->n_streamer == 1 && local == 2)) { if (is_ip_ver_5a) pm_qos_remove_request(&exynos5_tv_mif_qos); pm_qos_remove_request(&exynos5_tv_int_qos); } #endif mutex_unlock(&mdev->s_mutex); mxr_reg_dump(mdev); return ret; }
static int mxr_streamer_put(struct mxr_device *mdev, struct v4l2_subdev *sd) { int i; int ret = 0; int local = 1; struct media_pad *pad; struct sub_mxr_device *sub_mxr; struct mxr_layer *layer; struct v4l2_subdev *gsc_sd; struct exynos_entity_data *md_data; struct s5p_mxr_platdata *pdata = mdev->pdata; mutex_lock(&mdev->s_mutex); --mdev->n_streamer; mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_streamer); /* distinction number of local path */ if (mdev->mxr_data_from == FROM_GSC_SD) { local = 0; for (i = 0; i < MXR_MAX_SUB_MIXERS; ++i) { sub_mxr = &mdev->sub_mxr[i]; if (sub_mxr->local) local += sub_mxr->local; } if (local == 2) mxr_layer_sync(mdev, MXR_DISABLE); /* stop gscaler --> waiting for frame done */ pad = &sd->entity.pads[MXR_PAD_SINK_GSCALER]; pad = media_entity_remote_source(pad); if (pad) { gsc_sd = media_entity_to_v4l2_subdev( pad->entity); mxr_dbg(mdev, "stop from %s\n", gsc_sd->name); md_data = (struct exynos_entity_data *) gsc_sd->dev_priv; if (is_ip_ver_5g_1 || is_ip_ver_5a_0) md_data->media_ops->power_off(gsc_sd); } /* disable video layer */ 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->ops.stream_set(layer, 0); layer->pipe.state = MXR_PIPELINE_IDLE; } } } if ((mdev->n_streamer == 0 && local == 1) || (mdev->n_streamer == 1 && local == 2)) { mxr_reg_streamoff(mdev); /* vsync applies Mixer setup */ ret = mxr_reg_wait4update(mdev); if (ret) { mxr_err(mdev, "failed to get vsync (%d) from output\n", ret); goto out; } } /* disable mixer clock */ if (mdev->mxr_data_from == FROM_GSC_SD) mxr_power_put(mdev); WARN(mdev->n_streamer < 0, "negative number of streamers (%d)\n", mdev->n_streamer); out: #if defined(CONFIG_ARM_EXYNOS5410_BUS_DEVFREQ) if ((mdev->n_streamer == 0 && local == 1) || (mdev->n_streamer == 1 && local == 2)) { pm_qos_remove_request(&exynos5_tv_mif_qos); pm_qos_remove_request(&exynos5_tv_int_qos); } #endif mutex_unlock(&mdev->s_mutex); mxr_reg_dump(mdev); return ret; }