static int mxr_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct mxr_layer *layer = video_drvdata(file); const struct mxr_format *fmt; struct v4l2_pix_format_mplane *pix; struct mxr_device *mdev = layer->mdev; struct mxr_geometry *geo = &layer->geo; mxr_dbg(mdev, "%s:%d\n", __func__, __LINE__); pix = &f->fmt.pix_mp; fmt = find_format_by_fourcc(layer, pix->pixelformat); if (fmt == NULL) { mxr_warn(mdev, "not recognized fourcc: %08x\n", pix->pixelformat); return -EINVAL; } layer->fmt = fmt; geo->src.full_width = pix->width; geo->src.width = pix->width; geo->src.full_height = pix->height; geo->src.height = pix->height; /* assure consistency of geometry */ mxr_layer_geo_fix(layer); mxr_dbg(mdev, "width=%u height=%u span=%u\n", geo->src.width, geo->src.height, geo->src.full_width); return 0; }
static int mxr_s_crop(struct file *file, void *fh, struct v4l2_crop *a) { struct mxr_layer *layer = video_drvdata(file); struct mxr_crop *crop; mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__); crop = choose_crop_by_type(&layer->geo, a->type); if (crop == NULL) return -EINVAL; crop->x_offset = a->c.left; crop->y_offset = a->c.top; crop->width = a->c.width; crop->height = a->c.height; mxr_layer_geo_fix(layer); return 0; }
static int mxr_cropcap(struct file *file, void *fh, struct v4l2_cropcap *a) { struct mxr_layer *layer = video_drvdata(file); struct mxr_crop *crop; mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__); crop = choose_crop_by_type(&layer->geo, a->type); if (crop == NULL) return -EINVAL; mxr_layer_geo_fix(layer); a->bounds.left = 0; a->bounds.top = 0; a->bounds.width = crop->full_width; a->bounds.top = crop->full_height; a->defrect = a->bounds; /* setting pixel aspect to 1/1 */ a->pixelaspect.numerator = 1; a->pixelaspect.denominator = 1; return 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 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; }
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; }