1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. 4 */ 5 6 #include <media/v4l2-mem2mem.h> 7 8 #include "iris_buffer.h" 9 #include "iris_instance.h" 10 #include "iris_venc.h" 11 #include "iris_vpu_buffer.h" 12 13 int iris_venc_inst_init(struct iris_inst *inst) 14 { 15 struct v4l2_format *f; 16 17 inst->fmt_src = kzalloc(sizeof(*inst->fmt_src), GFP_KERNEL); 18 inst->fmt_dst = kzalloc(sizeof(*inst->fmt_dst), GFP_KERNEL); 19 if (!inst->fmt_src || !inst->fmt_dst) { 20 kfree(inst->fmt_src); 21 kfree(inst->fmt_dst); 22 return -ENOMEM; 23 } 24 25 f = inst->fmt_dst; 26 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 27 f->fmt.pix_mp.width = DEFAULT_WIDTH; 28 f->fmt.pix_mp.height = DEFAULT_HEIGHT; 29 f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264; 30 inst->codec = f->fmt.pix_mp.pixelformat; 31 f->fmt.pix_mp.num_planes = 1; 32 f->fmt.pix_mp.plane_fmt[0].bytesperline = 0; 33 f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT); 34 f->fmt.pix_mp.field = V4L2_FIELD_NONE; 35 f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT; 36 f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT; 37 f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; 38 f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT; 39 inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); 40 inst->buffers[BUF_OUTPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage; 41 42 f = inst->fmt_src; 43 f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 44 f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12; 45 f->fmt.pix_mp.width = ALIGN(DEFAULT_WIDTH, 128); 46 f->fmt.pix_mp.height = ALIGN(DEFAULT_HEIGHT, 32); 47 f->fmt.pix_mp.num_planes = 1; 48 f->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(DEFAULT_WIDTH, 128); 49 f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT); 50 f->fmt.pix_mp.field = V4L2_FIELD_NONE; 51 f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT; 52 f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT; 53 f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; 54 f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT; 55 inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT); 56 inst->buffers[BUF_INPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage; 57 58 inst->crop.left = 0; 59 inst->crop.top = 0; 60 inst->crop.width = f->fmt.pix_mp.width; 61 inst->crop.height = f->fmt.pix_mp.height; 62 63 return 0; 64 } 65 66 void iris_venc_inst_deinit(struct iris_inst *inst) 67 { 68 kfree(inst->fmt_dst); 69 kfree(inst->fmt_src); 70 } 71 72 static const struct iris_fmt iris_venc_formats[] = { 73 [IRIS_FMT_H264] = { 74 .pixfmt = V4L2_PIX_FMT_H264, 75 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 76 }, 77 [IRIS_FMT_HEVC] = { 78 .pixfmt = V4L2_PIX_FMT_HEVC, 79 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 80 }, 81 }; 82 83 static const struct iris_fmt * 84 find_format(struct iris_inst *inst, u32 pixfmt, u32 type) 85 { 86 const struct iris_fmt *fmt = iris_venc_formats; 87 unsigned int size = ARRAY_SIZE(iris_venc_formats); 88 unsigned int i; 89 90 for (i = 0; i < size; i++) { 91 if (fmt[i].pixfmt == pixfmt) 92 break; 93 } 94 95 if (i == size || fmt[i].type != type) 96 return NULL; 97 98 return &fmt[i]; 99 } 100 101 static const struct iris_fmt * 102 find_format_by_index(struct iris_inst *inst, u32 index, u32 type) 103 { 104 const struct iris_fmt *fmt = iris_venc_formats; 105 unsigned int size = ARRAY_SIZE(iris_venc_formats); 106 107 if (index >= size || fmt[index].type != type) 108 return NULL; 109 110 return &fmt[index]; 111 } 112 113 int iris_venc_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f) 114 { 115 const struct iris_fmt *fmt; 116 117 switch (f->type) { 118 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 119 if (f->index) 120 return -EINVAL; 121 f->pixelformat = V4L2_PIX_FMT_NV12; 122 break; 123 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 124 fmt = find_format_by_index(inst, f->index, f->type); 125 if (!fmt) 126 return -EINVAL; 127 128 f->pixelformat = fmt->pixfmt; 129 f->flags = V4L2_FMT_FLAG_COMPRESSED | V4L2_FMT_FLAG_ENC_CAP_FRAME_INTERVAL; 130 break; 131 default: 132 return -EINVAL; 133 } 134 135 return 0; 136 } 137 138 int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f) 139 { 140 struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; 141 const struct iris_fmt *fmt; 142 struct v4l2_format *f_inst; 143 144 memset(pixmp->reserved, 0, sizeof(pixmp->reserved)); 145 fmt = find_format(inst, pixmp->pixelformat, f->type); 146 switch (f->type) { 147 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 148 if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) { 149 f_inst = inst->fmt_src; 150 f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width; 151 f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height; 152 f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat; 153 } 154 break; 155 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 156 if (!fmt) { 157 f_inst = inst->fmt_dst; 158 f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width; 159 f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height; 160 f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat; 161 } 162 break; 163 default: 164 return -EINVAL; 165 } 166 167 if (pixmp->field == V4L2_FIELD_ANY) 168 pixmp->field = V4L2_FIELD_NONE; 169 170 pixmp->num_planes = 1; 171 172 return 0; 173 } 174 175 static int iris_venc_s_fmt_output(struct iris_inst *inst, struct v4l2_format *f) 176 { 177 struct v4l2_format *fmt; 178 179 iris_venc_try_fmt(inst, f); 180 181 if (!(find_format(inst, f->fmt.pix_mp.pixelformat, f->type))) 182 return -EINVAL; 183 184 fmt = inst->fmt_dst; 185 fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 186 fmt->fmt.pix_mp.num_planes = 1; 187 fmt->fmt.pix_mp.plane_fmt[0].bytesperline = 0; 188 fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT); 189 190 if (f->fmt.pix_mp.colorspace != V4L2_COLORSPACE_DEFAULT && 191 f->fmt.pix_mp.colorspace != V4L2_COLORSPACE_REC709) 192 f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT; 193 fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace; 194 fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func; 195 fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; 196 fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization; 197 198 inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); 199 inst->buffers[BUF_OUTPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage; 200 fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat; 201 inst->codec = f->fmt.pix_mp.pixelformat; 202 memcpy(f, fmt, sizeof(struct v4l2_format)); 203 204 return 0; 205 } 206 207 static int iris_venc_s_fmt_input(struct iris_inst *inst, struct v4l2_format *f) 208 { 209 struct v4l2_format *fmt, *output_fmt; 210 211 iris_venc_try_fmt(inst, f); 212 213 if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) 214 return -EINVAL; 215 216 fmt = inst->fmt_src; 217 fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 218 fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, 128); 219 fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 32); 220 fmt->fmt.pix_mp.num_planes = 1; 221 fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat; 222 fmt->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(f->fmt.pix_mp.width, 128); 223 fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT); 224 225 fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace; 226 fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func; 227 fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; 228 fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization; 229 230 output_fmt = inst->fmt_dst; 231 output_fmt->fmt.pix_mp.width = fmt->fmt.pix_mp.width; 232 output_fmt->fmt.pix_mp.height = fmt->fmt.pix_mp.height; 233 output_fmt->fmt.pix_mp.colorspace = fmt->fmt.pix_mp.colorspace; 234 output_fmt->fmt.pix_mp.xfer_func = fmt->fmt.pix_mp.xfer_func; 235 output_fmt->fmt.pix_mp.ycbcr_enc = fmt->fmt.pix_mp.ycbcr_enc; 236 output_fmt->fmt.pix_mp.quantization = fmt->fmt.pix_mp.quantization; 237 238 inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT); 239 inst->buffers[BUF_INPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage; 240 241 if (f->fmt.pix_mp.width != inst->crop.width || 242 f->fmt.pix_mp.height != inst->crop.height) { 243 inst->crop.top = 0; 244 inst->crop.left = 0; 245 inst->crop.width = fmt->fmt.pix_mp.width; 246 inst->crop.height = fmt->fmt.pix_mp.height; 247 248 iris_venc_s_fmt_output(inst, output_fmt); 249 } 250 251 memcpy(f, fmt, sizeof(struct v4l2_format)); 252 253 return 0; 254 } 255 256 int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f) 257 { 258 struct vb2_queue *q; 259 260 q = v4l2_m2m_get_vq(inst->m2m_ctx, f->type); 261 if (!q) 262 return -EINVAL; 263 264 if (vb2_is_busy(q)) 265 return -EBUSY; 266 267 switch (f->type) { 268 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 269 return iris_venc_s_fmt_input(inst, f); 270 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 271 return iris_venc_s_fmt_output(inst, f); 272 default: 273 return -EINVAL; 274 } 275 } 276