diff --git a/drivers/media/platform/rockchip/isp/isp_params_v1x.c b/drivers/media/platform/rockchip/isp/isp_params_v1x.c index a38f1b2dfcfa..6719422bf8ca 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v1x.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v1x.c @@ -2214,12 +2214,6 @@ static void rkisp1_params_first_cfg_v1x(struct rkisp_isp_params_vdev *params_vde hst_params_default_config.mode); } - /* set the range */ - if (params_vdev->quantization == V4L2_QUANTIZATION_FULL_RANGE) - ops->csm_config(params_vdev, true); - else - ops->csm_config(params_vdev, false); - /* disable color related config for grey sensor */ if (params_vdev->in_mbus_code == MEDIA_BUS_FMT_Y8_1X8 || params_vdev->in_mbus_code == MEDIA_BUS_FMT_Y10_1X10 || diff --git a/drivers/media/platform/rockchip/isp/isp_params_v21.c b/drivers/media/platform/rockchip/isp/isp_params_v21.c index c12272d5e356..0369b19693c1 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v21.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v21.c @@ -3906,8 +3906,6 @@ static void rkisp_params_first_cfg_v2x(struct rkisp_isp_params_vdev *params_vdev) { struct device *dev = params_vdev->dev->dev; - struct rkisp_isp_params_v21_ops *ops = - (struct rkisp_isp_params_v21_ops *)params_vdev->priv_ops; struct rkisp_isp_params_val_v21 *priv_val = (struct rkisp_isp_params_val_v21 *)params_vdev->priv_val; struct rkisp_hw_dev *hw = params_vdev->dev->hw_dev; @@ -3922,12 +3920,6 @@ rkisp_params_first_cfg_v2x(struct rkisp_isp_params_vdev *params_vdev) !params_vdev->isp21_params->module_en_update) dev_warn(dev, "can not get first iq setting in stream on\n"); - /* set the range */ - if (params_vdev->quantization == V4L2_QUANTIZATION_FULL_RANGE) - ops->csm_config(params_vdev, true); - else - ops->csm_config(params_vdev, false); - priv_val->dhaz_en = 0; priv_val->wdr_en = 0; priv_val->tmo_en = 0; diff --git a/drivers/media/platform/rockchip/isp/isp_params_v2x.c b/drivers/media/platform/rockchip/isp/isp_params_v2x.c index b8b1934dfb62..9d7f9beb7016 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v2x.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v2x.c @@ -4230,8 +4230,6 @@ static void rkisp_params_first_cfg_v2x(struct rkisp_isp_params_vdev *params_vdev) { struct device *dev = params_vdev->dev->dev; - struct rkisp_isp_params_v2x_ops *ops = - (struct rkisp_isp_params_v2x_ops *)params_vdev->priv_ops; struct rkisp_isp_params_val_v2x *priv_val = (struct rkisp_isp_params_val_v2x *)params_vdev->priv_val; @@ -4241,12 +4239,6 @@ rkisp_params_first_cfg_v2x(struct rkisp_isp_params_vdev *params_vdev) !params_vdev->isp2x_params->module_en_update) dev_warn(dev, "can not get first iq setting in stream on\n"); - /* set the range */ - if (params_vdev->quantization == V4L2_QUANTIZATION_FULL_RANGE) - ops->csm_config(params_vdev, true); - else - ops->csm_config(params_vdev, false); - priv_val->dhaz_en = 0; priv_val->wdr_en = 0; priv_val->tmo_en = 0; diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index f357c85cb011..6f8768befb7d 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -1029,6 +1029,67 @@ static void rkisp_monitor_init(struct rkisp_device *dev) INIT_WORK(&monitor->work, rkisp_restart_monitor); } +/* + * RGB to YUV color space, default BT601 + * BT601: + * Y = 0.299R + 0.587G + 0.114B + * CB = -0.1687R - 0.3313G + 0.5B + * CR = 0.5R - 0.4187G - 0.0813B + * BT709: + * Y = 0.2126R + 0.7152G + 0.0722B + * CB = -0.1146R - 0.3854G + 0.5B + * CR = 0.5R - 0.4542G - 0.0458B + * BT2020: + * Y = 0.2627R + 0.678G + 0.0593B + * CB = -0.1396R - 0.3604G + 0.5B + * CR = 0.5R - 0.4598G - 0.0402B + * 9 bit coeffs are signed integer values with 7 bit fractional + */ +static void rkisp_config_color_space(struct rkisp_device *dev) +{ + u16 bt601_coeff[] = { + 0x0026, 0x004b, 0x000f, + 0x01ea, 0x01d6, 0x0040, + 0x0040, 0x01ca, 0x01f6 + }; + u16 bt709_coeff[] = { + 0x001b, 0x005c, 0x0009, + 0x01f1, 0x01cf, 0x0040, + 0x0040, 0x01c6, 0x01fa + }; + u16 bt2020_coeff[] = { + 0x0022, 0x0057, 0x0008, + 0x01ee, 0x01d2, 0x0040, + 0x0040, 0x01c5, 0x01fb + }; + u16 i, *coeff; + + switch (dev->isp_sdev.colorspace) { + case V4L2_COLORSPACE_REC709: + coeff = bt709_coeff; + break; + case V4L2_COLORSPACE_BT2020: + coeff = bt2020_coeff; + break; + case V4L2_COLORSPACE_SMPTE170M: + default: + coeff = bt601_coeff; + break; + } + + for (i = 0; i < 9; i++) + rkisp_write(dev, CIF_ISP_CC_COEFF_0 + i * 4, *(coeff + i), false); + + if (dev->isp_sdev.quantization == V4L2_QUANTIZATION_FULL_RANGE) + rkisp_set_bits(dev, CIF_ISP_CTRL, 0, + CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA | + CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA, false); + else + rkisp_clear_bits(dev, CIF_ISP_CTRL, + CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA | + CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA, false); +} + /* * configure isp blocks with input format, size...... */ @@ -1168,12 +1229,13 @@ static int rkisp_config_isp(struct rkisp_device *dev) rkisp_write(dev, ISP_ISP3A_IMSC, irq_mask, true); } - if (out_fmt->fmt_type == FMT_BAYER) + if (out_fmt->fmt_type == FMT_BAYER) { rkisp_params_disable_isp(&dev->params_vdev); - else + } else { + rkisp_config_color_space(dev); rkisp_params_first_cfg(&dev->params_vdev, in_fmt, dev->isp_sdev.quantization); - + } if (!dev->hw_dev->is_single && atomic_read(&dev->hw_dev->refcnt) <= 1) { rkisp_update_regs(dev, CIF_ISP_ACQ_H_OFFS, CIF_ISP_ACQ_V_SIZE); rkisp_update_regs(dev, CIF_ISP_OUT_H_SIZE, CIF_ISP_OUT_V_SIZE); @@ -1903,6 +1965,7 @@ static int rkisp_isp_sd_get_fmt(struct v4l2_subdev *sd, mf->width = isp_sd->out_crop.width; mf->height = isp_sd->out_crop.height; mf->quantization = isp_sd->quantization; + mf->colorspace = isp_sd->colorspace; } mf->field = V4L2_FIELD_NONE; @@ -1955,13 +2018,15 @@ static int rkisp_isp_sd_set_fmt(struct v4l2_subdev *sd, mf->width = isp_sd->out_crop.width; mf->height = isp_sd->out_crop.height; /* full range by default */ - if (!mf->quantization) + if (mf->quantization == V4L2_QUANTIZATION_DEFAULT) mf->quantization = V4L2_QUANTIZATION_FULL_RANGE; - /* - * It is quantization for output, - * isp use bt601 limit-range in internal - */ + /* BT601 default */ + if (mf->colorspace != V4L2_COLORSPACE_SMPTE170M && + mf->colorspace != V4L2_COLORSPACE_REC709 && + mf->colorspace != V4L2_COLORSPACE_BT2020) + mf->colorspace = V4L2_COLORSPACE_SMPTE170M; isp_sd->quantization = mf->quantization; + isp_sd->colorspace = mf->colorspace; } mf->field = V4L2_FIELD_NONE; @@ -2488,45 +2553,44 @@ static long rkisp_compat_ioctl32(struct v4l2_subdev *sd, switch (cmd) { case RKISP_CMD_TRIGGER_READ_BACK: - ret = copy_from_user(&trigger, up, sizeof(trigger)); - if (!ret) - ret = rkisp_ioctl(sd, cmd, &trigger); + if (copy_from_user(&trigger, up, sizeof(trigger))) + return -EFAULT; + ret = rkisp_ioctl(sd, cmd, &trigger); break; case RKISP_CMD_CSI_MEMORY_MODE: - ret = copy_from_user(&mode, up, sizeof(int)); - if (!ret) - ret = rkisp_ioctl(sd, cmd, &mode); + if (copy_from_user(&mode, up, sizeof(int))) + return -EFAULT; + ret = rkisp_ioctl(sd, cmd, &mode); break; case RKISP_CMD_GET_SHARED_BUF: ret = rkisp_ioctl(sd, cmd, &resmem); - if (!ret) - ret = copy_to_user(up, &resmem, sizeof(resmem)); + if (!ret && copy_to_user(up, &resmem, sizeof(resmem))) + ret = -EFAULT; break; case RKISP_CMD_FREE_SHARED_BUF: ret = rkisp_ioctl(sd, cmd, NULL); break; case RKISP_CMD_GET_LDCHBUF_INFO: ret = rkisp_ioctl(sd, cmd, &ldchbuf); - if (!ret) - ret = copy_to_user(up, &ldchbuf, sizeof(ldchbuf)); + if (!ret && copy_to_user(up, &ldchbuf, sizeof(ldchbuf))) + ret = -EFAULT; break; case RKISP_CMD_SET_LDCHBUF_SIZE: - ret = copy_from_user(&ldchsize, up, sizeof(ldchsize)); - if (!ret) - ret = rkisp_ioctl(sd, cmd, &ldchsize); + if (copy_from_user(&ldchsize, up, sizeof(ldchsize))) + return -EFAULT; + ret = rkisp_ioctl(sd, cmd, &ldchsize); break; case RKISP_CMD_GET_SHM_BUFFD: - ret = copy_from_user(&shmem, up, sizeof(shmem)); - if (!ret) { - ret = rkisp_ioctl(sd, cmd, &shmem); - if (!ret) - ret = copy_to_user(up, &shmem, sizeof(shmem)); - } + if (copy_from_user(&shmem, up, sizeof(shmem))) + return -EFAULT; + ret = rkisp_ioctl(sd, cmd, &shmem); + if (!ret && copy_to_user(up, &shmem, sizeof(shmem))) + ret = -EFAULT; break; case RKISP_CMD_GET_FBCBUF_FD: ret = rkisp_ioctl(sd, cmd, &idxfd); - if (!ret) - ret = copy_to_user(up, &idxfd, sizeof(idxfd)); + if (!ret && copy_to_user(up, &idxfd, sizeof(idxfd))) + ret = -EFAULT; break; default: ret = -ENOIOCTLCMD; @@ -2593,6 +2657,8 @@ static void rkisp_isp_sd_init_default_fmt(struct rkisp_isp_subdev *isp_sd) /* propagate to source */ *out_crop = *in_crop; *out_fmt = rkisp_isp_output_formats[0]; + isp_sd->quantization = V4L2_QUANTIZATION_FULL_RANGE; + isp_sd->colorspace = V4L2_COLORSPACE_SMPTE170M; } int rkisp_register_isp_subdev(struct rkisp_device *isp_dev, diff --git a/drivers/media/platform/rockchip/isp/rkisp.h b/drivers/media/platform/rockchip/isp/rkisp.h index 3d7ecd50456a..39266569e14c 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.h +++ b/drivers/media/platform/rockchip/isp/rkisp.h @@ -121,6 +121,7 @@ struct rkisp_isp_subdev { bool dphy_errctrl_disabled; atomic_t frm_sync_seq; enum v4l2_quantization quantization; + enum v4l2_colorspace colorspace; u64 frm_timestamp; struct frame_debug_info dbg; };