#define VIVID_CID_DV_TIMINGS_ASPECT_RATIO      (VIVID_CID_VIVID_BASE + 23)
 #define VIVID_CID_TSTAMP_SRC           (VIVID_CID_VIVID_BASE + 24)
 #define VIVID_CID_COLORSPACE           (VIVID_CID_VIVID_BASE + 25)
-#define VIVID_CID_LIMITED_RGB_RANGE    (VIVID_CID_VIVID_BASE + 26)
-#define VIVID_CID_ALPHA_MODE           (VIVID_CID_VIVID_BASE + 27)
-#define VIVID_CID_HAS_CROP_CAP         (VIVID_CID_VIVID_BASE + 28)
-#define VIVID_CID_HAS_COMPOSE_CAP      (VIVID_CID_VIVID_BASE + 29)
-#define VIVID_CID_HAS_SCALER_CAP       (VIVID_CID_VIVID_BASE + 30)
-#define VIVID_CID_HAS_CROP_OUT         (VIVID_CID_VIVID_BASE + 31)
-#define VIVID_CID_HAS_COMPOSE_OUT      (VIVID_CID_VIVID_BASE + 32)
-#define VIVID_CID_HAS_SCALER_OUT       (VIVID_CID_VIVID_BASE + 33)
-#define VIVID_CID_LOOP_VIDEO           (VIVID_CID_VIVID_BASE + 34)
-#define VIVID_CID_SEQ_WRAP             (VIVID_CID_VIVID_BASE + 35)
-#define VIVID_CID_TIME_WRAP            (VIVID_CID_VIVID_BASE + 36)
-#define VIVID_CID_MAX_EDID_BLOCKS      (VIVID_CID_VIVID_BASE + 37)
-#define VIVID_CID_PERCENTAGE_FILL      (VIVID_CID_VIVID_BASE + 38)
+#define VIVID_CID_YCBCR_ENC            (VIVID_CID_VIVID_BASE + 26)
+#define VIVID_CID_QUANTIZATION         (VIVID_CID_VIVID_BASE + 27)
+#define VIVID_CID_LIMITED_RGB_RANGE    (VIVID_CID_VIVID_BASE + 28)
+#define VIVID_CID_ALPHA_MODE           (VIVID_CID_VIVID_BASE + 29)
+#define VIVID_CID_HAS_CROP_CAP         (VIVID_CID_VIVID_BASE + 30)
+#define VIVID_CID_HAS_COMPOSE_CAP      (VIVID_CID_VIVID_BASE + 31)
+#define VIVID_CID_HAS_SCALER_CAP       (VIVID_CID_VIVID_BASE + 32)
+#define VIVID_CID_HAS_CROP_OUT         (VIVID_CID_VIVID_BASE + 33)
+#define VIVID_CID_HAS_COMPOSE_OUT      (VIVID_CID_VIVID_BASE + 34)
+#define VIVID_CID_HAS_SCALER_OUT       (VIVID_CID_VIVID_BASE + 35)
+#define VIVID_CID_LOOP_VIDEO           (VIVID_CID_VIVID_BASE + 36)
+#define VIVID_CID_SEQ_WRAP             (VIVID_CID_VIVID_BASE + 37)
+#define VIVID_CID_TIME_WRAP            (VIVID_CID_VIVID_BASE + 38)
+#define VIVID_CID_MAX_EDID_BLOCKS      (VIVID_CID_VIVID_BASE + 39)
+#define VIVID_CID_PERCENTAGE_FILL      (VIVID_CID_VIVID_BASE + 40)
 
 #define VIVID_CID_STD_SIGNAL_MODE      (VIVID_CID_VIVID_BASE + 60)
 #define VIVID_CID_STANDARD             (VIVID_CID_VIVID_BASE + 61)
                vivid_send_source_change(dev, HDMI);
                vivid_send_source_change(dev, WEBCAM);
                break;
+       case VIVID_CID_YCBCR_ENC:
+               tpg_s_ycbcr_enc(&dev->tpg, ctrl->val);
+               vivid_send_source_change(dev, TV);
+               vivid_send_source_change(dev, SVID);
+               vivid_send_source_change(dev, HDMI);
+               vivid_send_source_change(dev, WEBCAM);
+               break;
+       case VIVID_CID_QUANTIZATION:
+               tpg_s_quantization(&dev->tpg, ctrl->val);
+               vivid_send_source_change(dev, TV);
+               vivid_send_source_change(dev, SVID);
+               vivid_send_source_change(dev, HDMI);
+               vivid_send_source_change(dev, WEBCAM);
+               break;
        case V4L2_CID_DV_RX_RGB_RANGE:
                if (!vivid_is_hdmi_cap(dev))
                        break;
        .qmenu = vivid_ctrl_colorspace_strings,
 };
 
+static const char * const vivid_ctrl_ycbcr_enc_strings[] = {
+       "Default",
+       "ITU-R 601",
+       "Rec. 709",
+       "xvYCC 601",
+       "xvYCC 709",
+       "sYCC",
+       "BT.2020 Non-Constant Luminance",
+       "BT.2020 Constant Luminance",
+       "SMPTE 240M",
+       NULL,
+};
+
+static const struct v4l2_ctrl_config vivid_ctrl_ycbcr_enc = {
+       .ops = &vivid_vid_cap_ctrl_ops,
+       .id = VIVID_CID_YCBCR_ENC,
+       .name = "Y'CbCr Encoding",
+       .type = V4L2_CTRL_TYPE_MENU,
+       .max = 8,
+       .qmenu = vivid_ctrl_ycbcr_enc_strings,
+};
+
+static const char * const vivid_ctrl_quantization_strings[] = {
+       "Default",
+       "Full Range",
+       "Limited Range",
+       NULL,
+};
+
+static const struct v4l2_ctrl_config vivid_ctrl_quantization = {
+       .ops = &vivid_vid_cap_ctrl_ops,
+       .id = VIVID_CID_QUANTIZATION,
+       .name = "Quantization",
+       .type = V4L2_CTRL_TYPE_MENU,
+       .max = 2,
+       .qmenu = vivid_ctrl_quantization_strings,
+};
+
 static const struct v4l2_ctrl_config vivid_ctrl_alpha_mode = {
        .ops = &vivid_vid_cap_ctrl_ops,
        .id = VIVID_CID_ALPHA_MODE,
                                dev->colorspace_out = V4L2_COLORSPACE_SMPTE170M;
                        else
                                dev->colorspace_out = V4L2_COLORSPACE_REC709;
+                       dev->quantization_out = V4L2_QUANTIZATION_DEFAULT;
                } else {
                        dev->colorspace_out = V4L2_COLORSPACE_SRGB;
+                       dev->quantization_out = dev->dvi_d_out ?
+                                       V4L2_QUANTIZATION_LIM_RANGE :
+                                       V4L2_QUANTIZATION_DEFAULT;
                }
                if (dev->loop_video)
                        vivid_send_source_change(dev, HDMI);
                v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_tstamp_src, NULL);
                dev->colorspace = v4l2_ctrl_new_custom(hdl_vid_cap,
                        &vivid_ctrl_colorspace, NULL);
+               v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_ycbcr_enc, NULL);
+               v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_quantization, NULL);
                v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_alpha_mode, NULL);
        }
 
 
        return dev->colorspace_out;
 }
 
+static unsigned vivid_ycbcr_enc_cap(struct vivid_dev *dev)
+{
+       if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
+               return tpg_g_ycbcr_enc(&dev->tpg);
+       return dev->ycbcr_enc_out;
+}
+
+static unsigned vivid_quantization_cap(struct vivid_dev *dev)
+{
+       if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
+               return tpg_g_quantization(&dev->tpg);
+       return dev->quantization_out;
+}
+
 int vivid_g_fmt_vid_cap(struct file *file, void *priv,
                                        struct v4l2_format *f)
 {
        mp->field        = dev->field_cap;
        mp->pixelformat  = dev->fmt_cap->fourcc;
        mp->colorspace   = vivid_colorspace_cap(dev);
+       mp->ycbcr_enc    = vivid_ycbcr_enc_cap(dev);
+       mp->quantization = vivid_quantization_cap(dev);
        mp->num_planes = dev->fmt_cap->planes;
        for (p = 0; p < mp->num_planes; p++) {
                mp->plane_fmt[p].bytesperline = tpg_g_bytesperline(&dev->tpg, p);
                memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved));
        }
        mp->colorspace = vivid_colorspace_cap(dev);
+       mp->ycbcr_enc = vivid_ycbcr_enc_cap(dev);
+       mp->quantization = vivid_quantization_cap(dev);
        memset(mp->reserved, 0, sizeof(mp->reserved));
        return 0;
 }
 
                }
                break;
        }
+       dev->ycbcr_enc_out = V4L2_YCBCR_ENC_DEFAULT;
+       dev->quantization_out = V4L2_QUANTIZATION_DEFAULT;
        dev->compose_out = dev->sink_rect;
        dev->compose_bounds_out = dev->sink_rect;
        dev->crop_out = dev->compose_out;
        mp->field        = dev->field_out;
        mp->pixelformat  = dev->fmt_out->fourcc;
        mp->colorspace   = dev->colorspace_out;
+       mp->ycbcr_enc    = dev->ycbcr_enc_out;
+       mp->quantization = dev->quantization_out;
        mp->num_planes = dev->fmt_out->planes;
        for (p = 0; p < mp->num_planes; p++) {
                mp->plane_fmt[p].bytesperline = dev->bytesperline_out[p];
                pfmt[p].sizeimage = pfmt[p].bytesperline * mp->height;
                memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved));
        }
-       if (vivid_is_svid_out(dev))
+       mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+       mp->quantization = V4L2_QUANTIZATION_DEFAULT;
+       if (vivid_is_svid_out(dev)) {
                mp->colorspace = V4L2_COLORSPACE_SMPTE170M;
-       else if (dev->dvi_d_out || !(bt->standards & V4L2_DV_BT_STD_CEA861))
+       } else if (dev->dvi_d_out || !(bt->standards & V4L2_DV_BT_STD_CEA861)) {
                mp->colorspace = V4L2_COLORSPACE_SRGB;
-       else if (bt->width == 720 && bt->height <= 576)
+               if (dev->dvi_d_out)
+                       mp->quantization = V4L2_QUANTIZATION_LIM_RANGE;
+       } else if (bt->width == 720 && bt->height <= 576) {
                mp->colorspace = V4L2_COLORSPACE_SMPTE170M;
-       else if (mp->colorspace != V4L2_COLORSPACE_SMPTE170M &&
-                mp->colorspace != V4L2_COLORSPACE_REC709 &&
-                mp->colorspace != V4L2_COLORSPACE_SRGB)
+       } else if (mp->colorspace != V4L2_COLORSPACE_SMPTE170M &&
+                  mp->colorspace != V4L2_COLORSPACE_REC709 &&
+                  mp->colorspace != V4L2_COLORSPACE_ADOBERGB &&
+                  mp->colorspace != V4L2_COLORSPACE_BT2020 &&
+                  mp->colorspace != V4L2_COLORSPACE_SRGB) {
                mp->colorspace = V4L2_COLORSPACE_REC709;
+       }
        memset(mp->reserved, 0, sizeof(mp->reserved));
        return 0;
 }
 
 set_colorspace:
        dev->colorspace_out = mp->colorspace;
+       dev->ycbcr_enc_out = mp->ycbcr_enc;
+       dev->quantization_out = mp->quantization;
        if (dev->loop_video) {
                vivid_send_source_change(dev, SVID);
                vivid_send_source_change(dev, HDMI);