diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index e53db8ddb5f8..3f23231d4274 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -536,9 +536,43 @@ static int rkcif_sditf_attach_cifdev(struct sditf_priv *sditf) return 0; } +static int rkcif_sditf_get_ctrl(struct v4l2_ctrl *ctrl) +{ + struct sditf_priv *priv = container_of(ctrl->handler, + struct sditf_priv, + ctrl_handler); + struct v4l2_ctrl *sensor_ctrl = NULL; + + switch (ctrl->id) { + case V4L2_CID_PIXEL_RATE: + if (priv->cif_dev->terminal_sensor.sd) { + sensor_ctrl = v4l2_ctrl_find(priv->cif_dev->terminal_sensor.sd->ctrl_handler, V4L2_CID_PIXEL_RATE); + if (sensor_ctrl) { + ctrl->val = v4l2_ctrl_g_ctrl_int64(sensor_ctrl); + __v4l2_ctrl_s_ctrl_int64(priv->pixel_rate, ctrl->val); + v4l2_dbg(3, rkcif_debug, &priv->cif_dev->v4l2_dev, + "%s, %s pixel rate %d\n", + __func__, priv->cif_dev->terminal_sensor.sd->name, ctrl->val); + return 0; + } else { + return -EINVAL; + } + } + return -EINVAL; + default: + return -EINVAL; + } +} + +static const struct v4l2_ctrl_ops rkcif_sditf_ctrl_ops = { + .g_volatile_ctrl = rkcif_sditf_get_ctrl, +}; + static int rkcif_subdev_media_init(struct sditf_priv *priv) { struct rkcif_device *cif_dev = priv->cif_dev; + struct v4l2_ctrl_handler *handler = &priv->ctrl_handler; + unsigned long flags = V4L2_CTRL_FLAG_VOLATILE; int ret; priv->pads.flags = MEDIA_PAD_FL_SOURCE; @@ -547,6 +581,21 @@ static int rkcif_subdev_media_init(struct sditf_priv *priv) if (ret < 0) return ret; + ret = v4l2_ctrl_handler_init(handler, 1); + if (ret) + return ret; + priv->pixel_rate = v4l2_ctrl_new_std(handler, &rkcif_sditf_ctrl_ops, + V4L2_CID_PIXEL_RATE, + 0, SDITF_PIXEL_RATE_MAX, + 1, SDITF_PIXEL_RATE_MAX); + if (priv->pixel_rate) + priv->pixel_rate->flags |= flags; + priv->sd.ctrl_handler = handler; + if (handler->error) { + v4l2_ctrl_handler_free(handler); + return handler->error; + } + strncpy(priv->sd.name, dev_name(cif_dev->dev), sizeof(priv->sd.name)); priv->cap_info.width = 0; priv->cap_info.height = 0; diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.h b/drivers/media/platform/rockchip/cif/subdev-itf.h index a1ebbe02a820..893e5ed97e37 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.h +++ b/drivers/media/platform/rockchip/cif/subdev-itf.h @@ -28,6 +28,8 @@ #define RKCIF_TOISP_CH2 2 #define TOISP_CH_MAX 3 +#define SDITF_PIXEL_RATE_MAX (1000000000) + struct capture_info { unsigned int offset_x; unsigned int offset_y; @@ -61,6 +63,8 @@ struct sditf_priv { struct capture_info cap_info; struct rkisp_vicap_mode mode; struct toisp_info toisp_inf; + struct v4l2_ctrl *pixel_rate; + struct v4l2_ctrl_handler ctrl_handler; int buf_num; };