diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c
index c7799ceb3d6d..04b7e64312be 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-core.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c
@@ -790,6 +790,48 @@ static int validate_av1_sequence(struct v4l2_ctrl_av1_sequence *s)
 	return 0;
 }
 
+static int
+validate_h264_encode_params(struct v4l2_ctrl_h264_encode_params *encode_params)
+{
+	/* Make sure we're not passed invalid flags. */
+	if (encode_params->flags & ~(V4L2_H264_ENCODE_FLAG_ENTROPY_CABAC |
+		V4L2_H264_ENCODE_FLAG_TRANSFORM_8X8_MODE |
+		V4L2_H264_ENCODE_FLAG_CONSTRAINED_INTRA_PRED |
+		V4L2_H264_ENCODE_FLAG_MARK_LONGTERM))
+		return -EINVAL;
+
+	if (encode_params->slice_type != V4L2_H264_SLICE_TYPE_I &&
+	    encode_params->slice_type != V4L2_H264_SLICE_TYPE_P &&
+	    encode_params->slice_type != V4L2_H264_SLICE_TYPE_B &&
+	    encode_params->slice_type != V4L2_H264_SLICE_TYPE_SI &&
+		encode_params->slice_type != V4L2_H264_SLICE_TYPE_SP)
+		return -EINVAL;
+
+	if (encode_params->cabac_init_idc > 2)
+		return -EINVAL;
+
+	if (encode_params->nalu_type != V4L2_H264_NAL_CODED_SLICE_NON_IDR_PIC &&
+	    encode_params->nalu_type != V4L2_H264_NAL_CODED_SLICE_IDR_PIC)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int
+validate_h264_encode_rc(struct v4l2_ctrl_h264_encode_rc *encode_rc)
+{
+	if (encode_rc->qp > 51)
+		return -EINVAL;
+
+	if (encode_rc->qp_min > 51 || encode_rc->qp_max > 51)
+		return -EINVAL;
+
+	if (encode_rc->qp_min > encode_rc->qp_max)
+		return -EINVAL;
+
+	return 0;
+}
+
 /*
  * Compound controls validation requires setting unused fields/flags to zero
  * in order to properly detect unchanged controls with v4l2_ctrl_type_op_equal's
@@ -1179,6 +1221,12 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
 			return -EINVAL;
 		break;
 
+	case V4L2_CTRL_TYPE_H264_ENCODE_PARAMS:
+		return validate_h264_encode_params(p);
+
+	case V4L2_CTRL_TYPE_H264_ENCODE_RC:
+		return validate_h264_encode_rc(p);
+
 	default:
 		return -EINVAL;
 	}
@@ -1881,6 +1929,12 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 	case V4L2_CTRL_TYPE_VP8_ENCODE_PARAMS:
 		elem_size = sizeof(struct v4l2_ctrl_vp8_encode_params);
 		break;
+	case V4L2_CTRL_TYPE_H264_ENCODE_PARAMS:
+		elem_size = sizeof(struct v4l2_ctrl_h264_encode_params);
+		break;
+	case V4L2_CTRL_TYPE_H264_ENCODE_RC:
+		elem_size = sizeof(struct v4l2_ctrl_h264_encode_rc);
+		break;
 	default:
 		if (type < V4L2_CTRL_COMPOUND_TYPES)
 			elem_size = sizeof(s32);
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
index bd26f1d89bd5..920ef552770c 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
@@ -1239,6 +1239,9 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_STATELESS_VP8_ENCODE_PARAMS:		return "VP8 Encode Parameters";
 	case V4L2_CID_STATELESS_VP8_ENCODE_QP:			return "VP8 Encode QP";
 
+	case V4L2_CID_STATELESS_H264_ENCODE_PARAMS:             return "H264 Encode Parameters";
+	case V4L2_CID_STATELESS_H264_ENCODE_RC:                 return "H264 Encode Rate-Control";
+
 	/* Colorimetry controls */
 	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
 	case V4L2_CID_COLORIMETRY_CLASS:	return "Colorimetry Controls";
@@ -1607,6 +1610,12 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY:
 		*type = V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY;
 		break;
+	case V4L2_CID_STATELESS_H264_ENCODE_PARAMS:
+		*type = V4L2_CTRL_TYPE_H264_ENCODE_PARAMS;
+		break;
+	case V4L2_CID_STATELESS_H264_ENCODE_RC:
+		*type = V4L2_CTRL_TYPE_H264_ENCODE_RC;
+		break;
 	default:
 		*type = V4L2_CTRL_TYPE_INTEGER;
 		break;
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index fdec5764e09c..c487506f21a9 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -1680,6 +1680,91 @@ struct v4l2_ctrl_h264_decode_params {
 	__u32 flags;
 };
 
+#define V4L2_H264_NAL_CODED_SLICE_NON_IDR_PIC	1
+#define V4L2_H264_NAL_CODED_SLICE_IDR_PIC	5
+
+#define V4L2_CID_STATELESS_H264_ENCODE_PARAMS  (V4L2_CID_CODEC_STATELESS_BASE + 8)
+
+/**
+ * struct v4l2_ctrl_h264_encode_params
+ * @slice_type: selects slice type. Set to one of V4L2_H264_SLICE_TYPE_{}
+ * @pic_parameter_set_id: identifies the picture parameter set that is referred to
+ * in the slice header. The value shall be in the range of 0 to 255, inclusive.
+ * @frame_num: an identifier for pictures.
+ * @idr_pic_id: identifies an IDR picture.
+ * @cabac_init_idc: index for determining the initialization table used in the
+ * initialization process for context variables. The value of cabac_init_idc
+ * shall be in the range of 0 to 2, inclusive.
+ * @disable_deblocking_filter_idc: specifies whether the operation of the
+ * deblocking filter shall be disabled across some block edges of the slice and
+ * specifies for which edges the filtering is disabled.
+ * @slice_alpha_c0_offset_div2: offset used in accessing the alpha and tC0
+ * deblocking filter tables for filtering operations controlled by the macroblocks
+ * within the slice.
+ * @slice_beta_offset_div2: offset used in accessing the beta deblocking filter
+ * table for filtering operations controlled by the macroblocks within the slice.
+ * @slice_size_mb_rows: number of macroblock rows in a slice.
+ * @pic_init_qp_minus26: initial value minus 26 of luma qp for each slice.
+ * @chroma_qp_index_offset: offset that shall be added to qp luma for addressing the
+ * table of qp chroma values for the Cb chroma component.
+ * @flags: combination of V4L2_H264_SLICE_FLAG_{} flags.
+ */
+struct v4l2_ctrl_h264_encode_params {
+	/* Slice parameters */
+
+	__u8 slice_type;
+	__u8 pic_parameter_set_id;
+	__u16 frame_num;
+	__u16 idr_pic_id;
+	__u8 cabac_init_idc;
+	__u8 disable_deblocking_filter_idc;
+	__s8 slice_alpha_c0_offset_div2;
+	__s8 slice_beta_offset_div2;
+
+	__s32 slice_size_mb_rows;
+
+	/* PPS parameters */
+
+	__s8 pic_init_qp_minus26;
+	__s8 chroma_qp_index_offset;
+
+	__u32 flags; /* V4L2_H264_ENCODE_FLAG_ */
+
+	/* Nal parameters */
+	__u8 nal_reference_idc; // 2 bit
+	__u8 nalu_type; // 5 bit
+
+	/* Reference */
+
+	__u64 reference_ts;
+};
+
+#define V4L2_H264_ENCODE_FLAG_ENTROPY_CABAC	       0x01
+#define V4L2_H264_ENCODE_FLAG_TRANSFORM_8X8_MODE       0x02
+#define V4L2_H264_ENCODE_FLAG_CONSTRAINED_INTRA_PRED   0x04
+#define V4L2_H264_ENCODE_FLAG_MARK_LONGTERM            0x08
+
+#define V4L2_CID_STATELESS_H264_ENCODE_RC      (V4L2_CID_CODEC_STATELESS_BASE + 9)
+
+/**
+ * struct v4l2_ctrl_h264_encode_rc
+ *
+ * @qp: quantization parameter for the currently encoded slice
+ *
+ * TODO: other fields likely not needed
+ */
+struct v4l2_ctrl_h264_encode_rc {
+	__u32 qp;
+	__u32 qp_min;
+	__u32 qp_max;
+	__s32 mad_qp_delta;
+	__u32 mad_threshold;
+
+	__u32 cp_distance_mbs;
+	__u32 cp_target[10];
+	__s32 cp_target_error[6];
+	__s32 cp_qp_delta[7];
+};
 
 /* Stateless FWHT control, used by the vicodec driver */
 
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index b3cbdc60b82c..082018abdd18 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -1893,6 +1893,8 @@ enum v4l2_ctrl_type {
 	V4L2_CTRL_TYPE_H264_SLICE_PARAMS    = 0x0203,
 	V4L2_CTRL_TYPE_H264_DECODE_PARAMS   = 0x0204,
 	V4L2_CTRL_TYPE_H264_PRED_WEIGHTS    = 0x0205,
+	V4L2_CTRL_TYPE_H264_ENCODE_PARAMS   = 0x0210,
+	V4L2_CTRL_TYPE_H264_ENCODE_RC       = 0x0211,
 
 	V4L2_CTRL_TYPE_FWHT_PARAMS	    = 0x0220,
 
