Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: iris: add support for dynamic resolution change

Handle the response sent by the firmware, when a source change is
detected. Read the subscribed parameter to get the changed values. Raise
the source change event to the client and update the instance sub-state.

Mark the last buffer from before the source change with the
V4L2_BUF_FLAG_LAST flag and return to the client.

Reviewed-by: Hans Verkuil <hverkuil@xs4all.nl>
Tested-by: Stefan Schmidt <stefan.schmidt@linaro.org> # x1e80100 (Dell XPS 13 9345)
Reviewed-by: Stefan Schmidt <stefan.schmidt@linaro.org>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-HDK
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>

authored by

Dikshita Agarwal and committed by
Hans Verkuil
84e17ada 17f2a485

+676 -1
+64
drivers/media/platform/qcom/iris/iris_hfi_common.c
··· 10 10 #include "iris_hfi_common.h" 11 11 #include "iris_vpu_common.h" 12 12 13 + u32 iris_hfi_get_v4l2_color_primaries(u32 hfi_primaries) 14 + { 15 + switch (hfi_primaries) { 16 + case HFI_PRIMARIES_RESERVED: 17 + return V4L2_COLORSPACE_DEFAULT; 18 + case HFI_PRIMARIES_BT709: 19 + return V4L2_COLORSPACE_REC709; 20 + case HFI_PRIMARIES_BT470_SYSTEM_M: 21 + return V4L2_COLORSPACE_470_SYSTEM_M; 22 + case HFI_PRIMARIES_BT470_SYSTEM_BG: 23 + return V4L2_COLORSPACE_470_SYSTEM_BG; 24 + case HFI_PRIMARIES_BT601_525: 25 + return V4L2_COLORSPACE_SMPTE170M; 26 + case HFI_PRIMARIES_SMPTE_ST240M: 27 + return V4L2_COLORSPACE_SMPTE240M; 28 + case HFI_PRIMARIES_BT2020: 29 + return V4L2_COLORSPACE_BT2020; 30 + case V4L2_COLORSPACE_DCI_P3: 31 + return HFI_PRIMARIES_SMPTE_RP431_2; 32 + default: 33 + return V4L2_COLORSPACE_DEFAULT; 34 + } 35 + } 36 + 37 + u32 iris_hfi_get_v4l2_transfer_char(u32 hfi_characterstics) 38 + { 39 + switch (hfi_characterstics) { 40 + case HFI_TRANSFER_RESERVED: 41 + return V4L2_XFER_FUNC_DEFAULT; 42 + case HFI_TRANSFER_BT709: 43 + return V4L2_XFER_FUNC_709; 44 + case HFI_TRANSFER_SMPTE_ST240M: 45 + return V4L2_XFER_FUNC_SMPTE240M; 46 + case HFI_TRANSFER_SRGB_SYCC: 47 + return V4L2_XFER_FUNC_SRGB; 48 + case HFI_TRANSFER_SMPTE_ST2084_PQ: 49 + return V4L2_XFER_FUNC_SMPTE2084; 50 + default: 51 + return V4L2_XFER_FUNC_DEFAULT; 52 + } 53 + } 54 + 55 + u32 iris_hfi_get_v4l2_matrix_coefficients(u32 hfi_coefficients) 56 + { 57 + switch (hfi_coefficients) { 58 + case HFI_MATRIX_COEFF_RESERVED: 59 + return V4L2_YCBCR_ENC_DEFAULT; 60 + case HFI_MATRIX_COEFF_BT709: 61 + return V4L2_YCBCR_ENC_709; 62 + case HFI_MATRIX_COEFF_BT470_SYS_BG_OR_BT601_625: 63 + return V4L2_YCBCR_ENC_XV601; 64 + case HFI_MATRIX_COEFF_BT601_525_BT1358_525_OR_625: 65 + return V4L2_YCBCR_ENC_601; 66 + case HFI_MATRIX_COEFF_SMPTE_ST240: 67 + return V4L2_YCBCR_ENC_SMPTE240M; 68 + case HFI_MATRIX_COEFF_BT2020_NON_CONSTANT: 69 + return V4L2_YCBCR_ENC_BT2020; 70 + case HFI_MATRIX_COEFF_BT2020_CONSTANT: 71 + return V4L2_YCBCR_ENC_BT2020_CONST_LUM; 72 + default: 73 + return V4L2_YCBCR_ENC_DEFAULT; 74 + } 75 + } 76 + 13 77 int iris_hfi_core_init(struct iris_core *core) 14 78 { 15 79 const struct iris_hfi_command_ops *hfi_ops = core->hfi_ops;
+3
drivers/media/platform/qcom/iris/iris_hfi_common.h
··· 138 138 u32 level; 139 139 }; 140 140 141 + u32 iris_hfi_get_v4l2_color_primaries(u32 hfi_primaries); 142 + u32 iris_hfi_get_v4l2_transfer_char(u32 hfi_characterstics); 143 + u32 iris_hfi_get_v4l2_matrix_coefficients(u32 hfi_coefficients); 141 144 int iris_hfi_core_init(struct iris_core *core); 142 145 int iris_hfi_pm_suspend(struct iris_core *core); 143 146 int iris_hfi_pm_resume(struct iris_core *core);
+82
drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
··· 44 44 #define HFI_EVENT_SYS_ERROR 0x1 45 45 #define HFI_EVENT_SESSION_ERROR 0x2 46 46 47 + #define HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES 0x1000001 48 + #define HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES 0x1000002 49 + #define HFI_EVENT_SESSION_SEQUENCE_CHANGED 0x1000003 50 + 47 51 #define HFI_BUFFERFLAG_TIMESTAMPINVALID 0x00000100 48 52 49 53 #define HFI_FLUSH_OUTPUT 0x1000002 50 54 #define HFI_FLUSH_OUTPUT2 0x1000003 51 55 #define HFI_FLUSH_ALL 0x1000004 52 56 57 + #define HFI_INDEX_EXTRADATA_INPUT_CROP 0x0700000e 58 + 53 59 #define HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL 0x201001 54 60 #define HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO 0x201002 55 61 #define HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE 0x201008 56 62 #define HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL 0x20100c 57 63 64 + #define HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS 0x202001 65 + 58 66 #define HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER 0x1200001 67 + #define HFI_PROPERTY_PARAM_VDEC_DPB_COUNTS 0x120300e 68 + #define HFI_PROPERTY_CONFIG_VDEC_ENTROPY 0x1204004 59 69 60 70 #define HFI_BUFFER_INPUT 0x1 61 71 #define HFI_BUFFER_OUTPUT 0x2 ··· 79 69 80 70 #define HFI_PROPERTY_PARAM_FRAME_SIZE 0x1001 81 71 #define HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT 0x1003 72 + #define HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT 0x1005 82 73 #define HFI_PROPERTY_PARAM_WORK_MODE 0x1015 83 74 #define HFI_PROPERTY_PARAM_WORK_ROUTE 0x1017 84 75 #define HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE 0x2002 85 76 86 77 #define HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM 0x1003001 78 + #define HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH 0x1003007 79 + #define HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT 0x1003009 80 + #define HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE 0x100300a 87 81 #define HFI_CORE_ID_1 1 88 82 #define HFI_COLOR_FORMAT_NV12 0x02 89 83 #define HFI_COLOR_FORMAT_NV12_UBWC 0x8002 ··· 263 249 u32 enable; 264 250 }; 265 251 252 + struct hfi_profile_level { 253 + u32 profile; 254 + u32 level; 255 + }; 256 + 266 257 struct hfi_framesize { 267 258 u32 buffer_type; 268 259 u32 width; ··· 284 265 285 266 struct hfi_video_work_route { 286 267 u32 video_work_route; 268 + }; 269 + 270 + struct hfi_bit_depth { 271 + u32 buffer_type; 272 + u32 bit_depth; 273 + }; 274 + 275 + struct hfi_pic_struct { 276 + u32 progressive_only; 277 + }; 278 + 279 + struct hfi_colour_space { 280 + u32 colour_space; 281 + }; 282 + 283 + struct hfi_extradata_input_crop { 284 + u32 size; 285 + u32 version; 286 + u32 port_index; 287 + u32 left; 288 + u32 top; 289 + u32 width; 290 + u32 height; 291 + }; 292 + 293 + struct hfi_dpb_counts { 294 + u32 max_dpb_count; 295 + u32 max_ref_frames; 296 + u32 max_dec_buffering; 297 + u32 max_reorder_frames; 298 + u32 fw_min_count; 287 299 }; 288 300 289 301 struct hfi_uncompressed_format_select { ··· 349 299 struct hfi_multi_stream { 350 300 u32 buffer_type; 351 301 u32 enable; 302 + }; 303 + 304 + struct hfi_buffer_requirements { 305 + u32 type; 306 + u32 size; 307 + u32 region_size; 308 + u32 hold_count; 309 + u32 count_min; 310 + u32 count_actual; 311 + u32 contiguous; 312 + u32 alignment; 313 + }; 314 + 315 + struct hfi_event_data { 316 + u32 error; 317 + u32 height; 318 + u32 width; 319 + u32 event_type; 320 + u32 packet_buffer; 321 + u32 extradata_buffer; 322 + u32 tag; 323 + u32 profile; 324 + u32 level; 325 + u32 bit_depth; 326 + u32 pic_struct; 327 + u32 colour_space; 328 + u32 entropy_mode; 329 + u32 buf_count; 330 + struct { 331 + u32 left, top; 332 + u32 width, height; 333 + } input_crop; 352 334 }; 353 335 354 336 struct hfi_msg_session_empty_buffer_done_pkt {
+208
drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
··· 3 3 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 4 */ 5 5 6 + #include <linux/bitfield.h> 6 7 #include <media/v4l2-mem2mem.h> 7 8 8 9 #include "iris_hfi_gen1.h" 9 10 #include "iris_hfi_gen1_defines.h" 10 11 #include "iris_instance.h" 12 + #include "iris_vdec.h" 13 + #include "iris_vpu_buffer.h" 14 + 15 + static void iris_hfi_gen1_read_changed_params(struct iris_inst *inst, 16 + struct hfi_msg_event_notify_pkt *pkt) 17 + { 18 + struct v4l2_pix_format_mplane *pixmp_ip = &inst->fmt_src->fmt.pix_mp; 19 + struct v4l2_pix_format_mplane *pixmp_op = &inst->fmt_dst->fmt.pix_mp; 20 + u32 num_properties_changed = pkt->event_data2; 21 + u8 *data_ptr = (u8 *)&pkt->ext_event_data[0]; 22 + u32 primaries, matrix_coeff, transfer_char; 23 + struct hfi_dpb_counts *iris_vpu_dpb_count; 24 + struct hfi_profile_level *profile_level; 25 + struct hfi_buffer_requirements *bufreq; 26 + struct hfi_extradata_input_crop *crop; 27 + struct hfi_colour_space *colour_info; 28 + struct iris_core *core = inst->core; 29 + u32 colour_description_present_flag; 30 + u32 video_signal_type_present_flag; 31 + struct hfi_event_data event = {0}; 32 + struct hfi_bit_depth *pixel_depth; 33 + struct hfi_pic_struct *pic_struct; 34 + struct hfi_framesize *frame_sz; 35 + struct vb2_queue *dst_q; 36 + struct v4l2_ctrl *ctrl; 37 + u32 full_range, ptype; 38 + 39 + do { 40 + ptype = *((u32 *)data_ptr); 41 + switch (ptype) { 42 + case HFI_PROPERTY_PARAM_FRAME_SIZE: 43 + data_ptr += sizeof(u32); 44 + frame_sz = (struct hfi_framesize *)data_ptr; 45 + event.width = frame_sz->width; 46 + event.height = frame_sz->height; 47 + data_ptr += sizeof(*frame_sz); 48 + break; 49 + case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT: 50 + data_ptr += sizeof(u32); 51 + profile_level = (struct hfi_profile_level *)data_ptr; 52 + event.profile = profile_level->profile; 53 + event.level = profile_level->level; 54 + data_ptr += sizeof(*profile_level); 55 + break; 56 + case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH: 57 + data_ptr += sizeof(u32); 58 + pixel_depth = (struct hfi_bit_depth *)data_ptr; 59 + event.bit_depth = pixel_depth->bit_depth; 60 + data_ptr += sizeof(*pixel_depth); 61 + break; 62 + case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT: 63 + data_ptr += sizeof(u32); 64 + pic_struct = (struct hfi_pic_struct *)data_ptr; 65 + event.pic_struct = pic_struct->progressive_only; 66 + data_ptr += sizeof(*pic_struct); 67 + break; 68 + case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE: 69 + data_ptr += sizeof(u32); 70 + colour_info = (struct hfi_colour_space *)data_ptr; 71 + event.colour_space = colour_info->colour_space; 72 + data_ptr += sizeof(*colour_info); 73 + break; 74 + case HFI_PROPERTY_CONFIG_VDEC_ENTROPY: 75 + data_ptr += sizeof(u32); 76 + event.entropy_mode = *(u32 *)data_ptr; 77 + data_ptr += sizeof(u32); 78 + break; 79 + case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS: 80 + data_ptr += sizeof(u32); 81 + bufreq = (struct hfi_buffer_requirements *)data_ptr; 82 + event.buf_count = bufreq->count_min; 83 + data_ptr += sizeof(*bufreq); 84 + break; 85 + case HFI_INDEX_EXTRADATA_INPUT_CROP: 86 + data_ptr += sizeof(u32); 87 + crop = (struct hfi_extradata_input_crop *)data_ptr; 88 + event.input_crop.left = crop->left; 89 + event.input_crop.top = crop->top; 90 + event.input_crop.width = crop->width; 91 + event.input_crop.height = crop->height; 92 + data_ptr += sizeof(*crop); 93 + break; 94 + case HFI_PROPERTY_PARAM_VDEC_DPB_COUNTS: 95 + data_ptr += sizeof(u32); 96 + iris_vpu_dpb_count = (struct hfi_dpb_counts *)data_ptr; 97 + event.buf_count = iris_vpu_dpb_count->fw_min_count; 98 + data_ptr += sizeof(*iris_vpu_dpb_count); 99 + break; 100 + default: 101 + break; 102 + } 103 + num_properties_changed--; 104 + } while (num_properties_changed > 0); 105 + 106 + pixmp_ip->width = event.width; 107 + pixmp_ip->height = event.height; 108 + 109 + pixmp_op->width = ALIGN(event.width, 128); 110 + pixmp_op->height = ALIGN(event.height, 32); 111 + pixmp_op->plane_fmt[0].bytesperline = ALIGN(event.width, 128); 112 + pixmp_op->plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT); 113 + 114 + matrix_coeff = FIELD_GET(GENMASK(7, 0), event.colour_space); 115 + transfer_char = FIELD_GET(GENMASK(15, 8), event.colour_space); 116 + primaries = FIELD_GET(GENMASK(23, 16), event.colour_space); 117 + colour_description_present_flag = FIELD_GET(GENMASK(24, 24), event.colour_space); 118 + full_range = FIELD_GET(GENMASK(25, 25), event.colour_space); 119 + video_signal_type_present_flag = FIELD_GET(GENMASK(29, 29), event.colour_space); 120 + 121 + pixmp_op->colorspace = V4L2_COLORSPACE_DEFAULT; 122 + pixmp_op->xfer_func = V4L2_XFER_FUNC_DEFAULT; 123 + pixmp_op->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; 124 + pixmp_op->quantization = V4L2_QUANTIZATION_DEFAULT; 125 + 126 + if (video_signal_type_present_flag) { 127 + pixmp_op->quantization = 128 + full_range ? 129 + V4L2_QUANTIZATION_FULL_RANGE : 130 + V4L2_QUANTIZATION_LIM_RANGE; 131 + if (colour_description_present_flag) { 132 + pixmp_op->colorspace = 133 + iris_hfi_get_v4l2_color_primaries(primaries); 134 + pixmp_op->xfer_func = 135 + iris_hfi_get_v4l2_transfer_char(transfer_char); 136 + pixmp_op->ycbcr_enc = 137 + iris_hfi_get_v4l2_matrix_coefficients(matrix_coeff); 138 + } 139 + } 140 + 141 + pixmp_ip->colorspace = pixmp_op->colorspace; 142 + pixmp_ip->xfer_func = pixmp_op->xfer_func; 143 + pixmp_ip->ycbcr_enc = pixmp_op->ycbcr_enc; 144 + pixmp_ip->quantization = pixmp_op->quantization; 145 + 146 + if (event.input_crop.width > 0 && event.input_crop.height > 0) { 147 + inst->crop.left = event.input_crop.left; 148 + inst->crop.top = event.input_crop.top; 149 + inst->crop.width = event.input_crop.width; 150 + inst->crop.height = event.input_crop.height; 151 + } else { 152 + inst->crop.left = 0; 153 + inst->crop.top = 0; 154 + inst->crop.width = event.width; 155 + inst->crop.height = event.height; 156 + } 157 + 158 + inst->fw_min_count = event.buf_count; 159 + inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); 160 + inst->buffers[BUF_OUTPUT].size = pixmp_op->plane_fmt[0].sizeimage; 161 + ctrl = v4l2_ctrl_find(&inst->ctrl_handler, V4L2_CID_MIN_BUFFERS_FOR_CAPTURE); 162 + if (ctrl) 163 + v4l2_ctrl_s_ctrl(ctrl, inst->buffers[BUF_OUTPUT].min_count); 164 + 165 + dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); 166 + dst_q->min_reqbufs_allocation = inst->buffers[BUF_OUTPUT].min_count; 167 + 168 + if (event.bit_depth || !event.pic_struct) { 169 + dev_err(core->dev, "unsupported content, bit depth: %x, pic_struct = %x\n", 170 + event.bit_depth, event.pic_struct); 171 + iris_inst_change_state(inst, IRIS_INST_ERROR); 172 + } 173 + } 174 + 175 + static void iris_hfi_gen1_event_seq_changed(struct iris_inst *inst, 176 + struct hfi_msg_event_notify_pkt *pkt) 177 + { 178 + struct hfi_session_flush_pkt flush_pkt; 179 + u32 num_properties_changed; 180 + int ret; 181 + 182 + ret = iris_inst_sub_state_change_drc(inst); 183 + if (ret) 184 + return; 185 + 186 + switch (pkt->event_data1) { 187 + case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES: 188 + case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES: 189 + break; 190 + default: 191 + iris_inst_change_state(inst, IRIS_INST_ERROR); 192 + return; 193 + } 194 + 195 + num_properties_changed = pkt->event_data2; 196 + if (!num_properties_changed) { 197 + iris_inst_change_state(inst, IRIS_INST_ERROR); 198 + return; 199 + } 200 + 201 + iris_hfi_gen1_read_changed_params(inst, pkt); 202 + 203 + if (inst->state != IRIS_INST_ERROR) { 204 + reinit_completion(&inst->flush_completion); 205 + 206 + flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt); 207 + flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH; 208 + flush_pkt.shdr.session_id = inst->session_id; 209 + flush_pkt.flush_type = HFI_FLUSH_OUTPUT; 210 + iris_hfi_queue_cmd_write(inst->core, &flush_pkt, flush_pkt.shdr.hdr.size); 211 + } 212 + 213 + iris_vdec_src_change(inst); 214 + iris_inst_sub_state_change_drc_last(inst); 215 + } 11 216 12 217 static void 13 218 iris_hfi_gen1_sys_event_notify(struct iris_core *core, void *packet) ··· 270 65 switch (pkt->event_id) { 271 66 case HFI_EVENT_SESSION_ERROR: 272 67 iris_hfi_gen1_event_session_error(inst, pkt); 68 + break; 69 + case HFI_EVENT_SESSION_SEQUENCE_CHANGED: 70 + iris_hfi_gen1_event_seq_changed(inst, pkt); 273 71 break; 274 72 default: 275 73 break;
+4
drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
··· 19 19 #define HFI_CMD_STOP 0x01000006 20 20 #define HFI_CMD_BUFFER 0x01000009 21 21 #define HFI_CMD_SUBSCRIBE_MODE 0x0100000B 22 + #define HFI_CMD_SETTINGS_CHANGE 0x0100000C 22 23 #define HFI_CMD_END 0x01FFFFFF 23 24 25 + #define HFI_BITMASK_BITSTREAM_WIDTH 0xffff0000 26 + #define HFI_BITMASK_BITSTREAM_HEIGHT 0x0000ffff 24 27 #define HFI_BITMASK_FRAME_MBS_ONLY_FLAG 0x00000001 25 28 26 29 #define HFI_PROP_BEGIN 0x03000000 ··· 78 75 #define HFI_INFO_UNSUPPORTED 0x06000001 79 76 #define HFI_INFO_DATA_CORRUPT 0x06000002 80 77 #define HFI_INFO_BUFFER_OVERFLOW 0x06000004 78 + #define HFI_INFO_HFI_FLAG_PSC_LAST 0x06000007 81 79 #define HFI_INFORMATION_END 0x06FFFFFF 82 80 83 81 enum hfi_property_mode_type {
+182 -1
drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
··· 8 8 #include "iris_hfi_gen2.h" 9 9 #include "iris_hfi_gen2_defines.h" 10 10 #include "iris_hfi_gen2_packet.h" 11 + #include "iris_vdec.h" 12 + #include "iris_vpu_buffer.h" 11 13 #include "iris_vpu_common.h" 12 14 13 15 struct iris_hfi_gen2_core_hfi_range { ··· 201 199 info = "buffer overflow"; 202 200 inst_hfi_gen2->hfi_frame_info.overflow = 1; 203 201 break; 202 + case HFI_INFO_HFI_FLAG_PSC_LAST: 203 + info = "drc last flag"; 204 + ret = iris_inst_sub_state_change_drc_last(inst); 205 + break; 204 206 default: 205 207 info = "unknown"; 206 208 break; ··· 335 329 struct v4l2_m2m_buffer *m2m_buffer, *n; 336 330 struct iris_buffer *buf; 337 331 bool found = false; 332 + int ret; 333 + 334 + if (hfi_buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST) { 335 + ret = iris_inst_sub_state_change_drc_last(inst); 336 + if (ret) 337 + return ret; 338 + } 338 339 339 340 v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, m2m_buffer, n) { 340 341 buf = to_iris_buffer(&m2m_buffer->vb); ··· 453 440 return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer); 454 441 } 455 442 443 + static void iris_hfi_gen2_read_input_subcr_params(struct iris_inst *inst) 444 + { 445 + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); 446 + struct v4l2_pix_format_mplane *pixmp_ip = &inst->fmt_src->fmt.pix_mp; 447 + struct v4l2_pix_format_mplane *pixmp_op = &inst->fmt_dst->fmt.pix_mp; 448 + u32 primaries, matrix_coeff, transfer_char; 449 + struct hfi_subscription_params subsc_params; 450 + u32 colour_description_present_flag; 451 + u32 video_signal_type_present_flag; 452 + struct iris_core *core = inst->core; 453 + u32 full_range, width, height; 454 + struct vb2_queue *dst_q; 455 + struct v4l2_ctrl *ctrl; 456 + 457 + subsc_params = inst_hfi_gen2->src_subcr_params; 458 + width = (subsc_params.bitstream_resolution & 459 + HFI_BITMASK_BITSTREAM_WIDTH) >> 16; 460 + height = subsc_params.bitstream_resolution & 461 + HFI_BITMASK_BITSTREAM_HEIGHT; 462 + 463 + pixmp_ip->width = width; 464 + pixmp_ip->height = height; 465 + 466 + pixmp_op->width = ALIGN(width, 128); 467 + pixmp_op->height = ALIGN(height, 32); 468 + pixmp_op->plane_fmt[0].bytesperline = ALIGN(width, 128); 469 + pixmp_op->plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT); 470 + 471 + matrix_coeff = subsc_params.color_info & 0xFF; 472 + transfer_char = (subsc_params.color_info & 0xFF00) >> 8; 473 + primaries = (subsc_params.color_info & 0xFF0000) >> 16; 474 + colour_description_present_flag = 475 + (subsc_params.color_info & 0x1000000) >> 24; 476 + full_range = (subsc_params.color_info & 0x2000000) >> 25; 477 + video_signal_type_present_flag = 478 + (subsc_params.color_info & 0x20000000) >> 29; 479 + 480 + pixmp_op->colorspace = V4L2_COLORSPACE_DEFAULT; 481 + pixmp_op->xfer_func = V4L2_XFER_FUNC_DEFAULT; 482 + pixmp_op->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; 483 + pixmp_op->quantization = V4L2_QUANTIZATION_DEFAULT; 484 + 485 + if (video_signal_type_present_flag) { 486 + pixmp_op->quantization = 487 + full_range ? 488 + V4L2_QUANTIZATION_FULL_RANGE : 489 + V4L2_QUANTIZATION_LIM_RANGE; 490 + if (colour_description_present_flag) { 491 + pixmp_op->colorspace = 492 + iris_hfi_get_v4l2_color_primaries(primaries); 493 + pixmp_op->xfer_func = 494 + iris_hfi_get_v4l2_transfer_char(transfer_char); 495 + pixmp_op->ycbcr_enc = 496 + iris_hfi_get_v4l2_matrix_coefficients(matrix_coeff); 497 + } 498 + } 499 + 500 + pixmp_ip->colorspace = pixmp_op->colorspace; 501 + pixmp_ip->xfer_func = pixmp_op->xfer_func; 502 + pixmp_ip->ycbcr_enc = pixmp_op->ycbcr_enc; 503 + pixmp_ip->quantization = pixmp_op->quantization; 504 + 505 + inst->crop.top = subsc_params.crop_offsets[0] & 0xFFFF; 506 + inst->crop.left = (subsc_params.crop_offsets[0] >> 16) & 0xFFFF; 507 + inst->crop.height = pixmp_ip->height - 508 + (subsc_params.crop_offsets[1] & 0xFFFF) - inst->crop.top; 509 + inst->crop.width = pixmp_ip->width - 510 + ((subsc_params.crop_offsets[1] >> 16) & 0xFFFF) - inst->crop.left; 511 + 512 + inst->fw_caps[PROFILE].value = subsc_params.profile; 513 + inst->fw_caps[LEVEL].value = subsc_params.level; 514 + inst->fw_caps[POC].value = subsc_params.pic_order_cnt; 515 + 516 + if (subsc_params.bit_depth != BIT_DEPTH_8 || 517 + !(subsc_params.coded_frames & HFI_BITMASK_FRAME_MBS_ONLY_FLAG)) { 518 + dev_err(core->dev, "unsupported content, bit depth: %x, pic_struct = %x\n", 519 + subsc_params.bit_depth, subsc_params.coded_frames); 520 + iris_inst_change_state(inst, IRIS_INST_ERROR); 521 + } 522 + 523 + inst->fw_min_count = subsc_params.fw_min_count; 524 + inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); 525 + inst->buffers[BUF_OUTPUT].size = pixmp_op->plane_fmt[0].sizeimage; 526 + ctrl = v4l2_ctrl_find(&inst->ctrl_handler, V4L2_CID_MIN_BUFFERS_FOR_CAPTURE); 527 + if (ctrl) 528 + v4l2_ctrl_s_ctrl(ctrl, inst->buffers[BUF_OUTPUT].min_count); 529 + 530 + dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); 531 + dst_q->min_reqbufs_allocation = inst->buffers[BUF_OUTPUT].min_count; 532 + } 533 + 534 + static int iris_hfi_gen2_handle_src_change(struct iris_inst *inst, 535 + struct iris_hfi_packet *pkt) 536 + { 537 + int ret; 538 + 539 + if (pkt->port != HFI_PORT_BITSTREAM) 540 + return 0; 541 + 542 + ret = iris_inst_sub_state_change_drc(inst); 543 + if (ret) 544 + return ret; 545 + 546 + iris_hfi_gen2_read_input_subcr_params(inst); 547 + iris_vdec_src_change(inst); 548 + 549 + return 0; 550 + } 551 + 456 552 static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst, 457 553 struct iris_hfi_packet *pkt) 458 554 { ··· 576 454 break; 577 455 case HFI_CMD_BUFFER: 578 456 ret = iris_hfi_gen2_handle_session_buffer(inst, pkt); 457 + break; 458 + case HFI_CMD_SETTINGS_CHANGE: 459 + ret = iris_hfi_gen2_handle_src_change(inst, pkt); 579 460 break; 580 461 default: 581 462 break; ··· 713 588 return 0; 714 589 } 715 590 591 + static void iris_hfi_gen2_init_src_change_param(struct iris_inst *inst) 592 + { 593 + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); 594 + struct v4l2_pix_format_mplane *pixmp_ip = &inst->fmt_src->fmt.pix_mp; 595 + struct v4l2_pix_format_mplane *pixmp_op = &inst->fmt_dst->fmt.pix_mp; 596 + u32 bottom_offset = (pixmp_ip->height - inst->crop.height); 597 + u32 right_offset = (pixmp_ip->width - inst->crop.width); 598 + struct hfi_subscription_params *subsc_params; 599 + u32 primaries, matrix_coeff, transfer_char; 600 + u32 colour_description_present_flag = 0; 601 + u32 video_signal_type_present_flag = 0; 602 + u32 full_range, video_format = 0; 603 + u32 left_offset = inst->crop.left; 604 + u32 top_offset = inst->crop.top; 605 + 606 + subsc_params = &inst_hfi_gen2->src_subcr_params; 607 + subsc_params->bitstream_resolution = 608 + pixmp_ip->width << 16 | pixmp_ip->height; 609 + subsc_params->crop_offsets[0] = 610 + left_offset << 16 | top_offset; 611 + subsc_params->crop_offsets[1] = 612 + right_offset << 16 | bottom_offset; 613 + subsc_params->fw_min_count = inst->buffers[BUF_OUTPUT].min_count; 614 + 615 + primaries = iris_hfi_gen2_get_color_primaries(pixmp_op->colorspace); 616 + matrix_coeff = iris_hfi_gen2_get_matrix_coefficients(pixmp_op->ycbcr_enc); 617 + transfer_char = iris_hfi_gen2_get_transfer_char(pixmp_op->xfer_func); 618 + full_range = pixmp_op->quantization == V4L2_QUANTIZATION_FULL_RANGE ? 1 : 0; 619 + subsc_params->color_info = 620 + iris_hfi_gen2_get_color_info(matrix_coeff, transfer_char, primaries, 621 + colour_description_present_flag, 622 + full_range, video_format, 623 + video_signal_type_present_flag); 624 + 625 + subsc_params->profile = inst->fw_caps[PROFILE].value; 626 + subsc_params->level = inst->fw_caps[LEVEL].value; 627 + subsc_params->pic_order_cnt = inst->fw_caps[POC].value; 628 + subsc_params->bit_depth = inst->fw_caps[BIT_DEPTH].value; 629 + if (inst->fw_caps[CODED_FRAMES].value == 630 + CODED_FRAMES_PROGRESSIVE) 631 + subsc_params->coded_frames = HFI_BITMASK_FRAME_MBS_ONLY_FLAG; 632 + else 633 + subsc_params->coded_frames = 0; 634 + } 635 + 716 636 static int iris_hfi_gen2_handle_session_response(struct iris_core *core, 717 637 struct iris_hfi_header *hdr) 718 638 { 639 + u8 *pkt = (u8 *)((u8 *)hdr + sizeof(*hdr)); 719 640 struct iris_inst_hfi_gen2 *inst_hfi_gen2; 720 641 struct iris_hfi_packet *packet; 721 642 struct iris_inst *inst; 722 643 bool dequeue = false; 723 644 int ret = 0; 724 645 u32 i, j; 725 - u8 *pkt; 726 646 static const struct iris_hfi_gen2_inst_hfi_range range[] = { 727 647 {HFI_SESSION_ERROR_BEGIN, HFI_SESSION_ERROR_END, 728 648 iris_hfi_gen2_handle_session_error}, ··· 786 616 mutex_lock(&inst->lock); 787 617 inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); 788 618 memset(&inst_hfi_gen2->hfi_frame_info, 0, sizeof(struct iris_hfi_frame_info)); 619 + 620 + for (i = 0; i < hdr->num_packets; i++) { 621 + packet = (struct iris_hfi_packet *)pkt; 622 + if (packet->type == HFI_CMD_SETTINGS_CHANGE) { 623 + if (packet->port == HFI_PORT_BITSTREAM) { 624 + iris_hfi_gen2_init_src_change_param(inst); 625 + break; 626 + } 627 + } 628 + pkt += packet->size; 629 + } 789 630 790 631 pkt = (u8 *)((u8 *)hdr + sizeof(*hdr)); 791 632 for (i = 0; i < ARRAY_SIZE(range); i++) {
+2
drivers/media/platform/qcom/iris/iris_instance.h
··· 31 31 * @buffers: array of different iris buffers 32 32 * @fw_min_count: minimnum count of buffers needed by fw 33 33 * @state: instance state 34 + * @sub_state: instance sub state 34 35 * @once_per_session_set: boolean to set once per session property 35 36 * @m2m_dev: a reference to m2m device structure 36 37 * @m2m_ctx: a reference to m2m context structure ··· 58 57 struct iris_buffers buffers[BUF_TYPE_MAX]; 59 58 u32 fw_min_count; 60 59 enum iris_inst_state state; 60 + enum iris_inst_sub_state sub_state; 61 61 bool once_per_session_set; 62 62 struct v4l2_m2m_dev *m2m_dev; 63 63 struct v4l2_m2m_ctx *m2m_ctx;
+64
drivers/media/platform/qcom/iris/iris_state.c
··· 102 102 103 103 return iris_inst_change_state(inst, new_state); 104 104 } 105 + 106 + int iris_inst_change_sub_state(struct iris_inst *inst, 107 + enum iris_inst_sub_state clear_sub_state, 108 + enum iris_inst_sub_state set_sub_state) 109 + { 110 + enum iris_inst_sub_state prev_sub_state; 111 + 112 + if (inst->state == IRIS_INST_ERROR) 113 + return 0; 114 + 115 + if (!clear_sub_state && !set_sub_state) 116 + return 0; 117 + 118 + if ((clear_sub_state & set_sub_state) || 119 + set_sub_state > IRIS_INST_MAX_SUB_STATE_VALUE || 120 + clear_sub_state > IRIS_INST_MAX_SUB_STATE_VALUE) 121 + return -EINVAL; 122 + 123 + prev_sub_state = inst->sub_state; 124 + 125 + inst->sub_state |= set_sub_state; 126 + inst->sub_state &= ~clear_sub_state; 127 + 128 + if (inst->sub_state != prev_sub_state) 129 + dev_dbg(inst->core->dev, "sub_state changed from %x to %x\n", 130 + prev_sub_state, inst->sub_state); 131 + 132 + return 0; 133 + } 134 + 135 + int iris_inst_sub_state_change_drc(struct iris_inst *inst) 136 + { 137 + enum iris_inst_sub_state set_sub_state = 0; 138 + 139 + if (inst->sub_state & IRIS_INST_SUB_DRC) 140 + return -EINVAL; 141 + 142 + if (inst->state == IRIS_INST_INPUT_STREAMING || 143 + inst->state == IRIS_INST_INIT) 144 + set_sub_state = IRIS_INST_SUB_FIRST_IPSC | IRIS_INST_SUB_INPUT_PAUSE; 145 + else 146 + set_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_INPUT_PAUSE; 147 + 148 + return iris_inst_change_sub_state(inst, 0, set_sub_state); 149 + } 150 + 151 + int iris_inst_sub_state_change_drc_last(struct iris_inst *inst) 152 + { 153 + enum iris_inst_sub_state set_sub_state; 154 + 155 + if (inst->sub_state & IRIS_INST_SUB_DRC_LAST) 156 + return -EINVAL; 157 + 158 + if (!(inst->sub_state & IRIS_INST_SUB_DRC) || 159 + !(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) 160 + return -EINVAL; 161 + 162 + if (inst->sub_state & IRIS_INST_SUB_FIRST_IPSC) 163 + return 0; 164 + 165 + set_sub_state = IRIS_INST_SUB_DRC_LAST | IRIS_INST_SUB_OUTPUT_PAUSE; 166 + 167 + return iris_inst_change_sub_state(inst, 0, set_sub_state); 168 + }
+33
drivers/media/platform/qcom/iris/iris_state.h
··· 91 91 IRIS_INST_ERROR, 92 92 }; 93 93 94 + #define IRIS_INST_SUB_STATES 8 95 + #define IRIS_INST_MAX_SUB_STATE_VALUE ((1 << IRIS_INST_SUB_STATES) - 1) 96 + 97 + /** 98 + * enum iris_inst_sub_state 99 + * 100 + * @IRIS_INST_SUB_FIRST_IPSC: indicates source change is received from firmware 101 + * when output port is not yet streaming. 102 + * @IRIS_INST_SUB_DRC: indicates source change is received from firmware 103 + * when output port is streaming and source change event is 104 + * sent to client. 105 + * @IRIS_INST_SUB_DRC_LAST: indicates last buffer is received from firmware 106 + * as part of source change. 107 + * @IRIS_INST_SUB_INPUT_PAUSE: source change is received form firmware. This 108 + * indicates that firmware is paused to process 109 + * any further input frames. 110 + * @IRIS_INST_SUB_OUTPUT_PAUSE: last buffer is received form firmware as part 111 + * of drc sequence. This indicates that 112 + * firmware is paused to process any further output frames. 113 + */ 114 + enum iris_inst_sub_state { 115 + IRIS_INST_SUB_FIRST_IPSC = BIT(0), 116 + IRIS_INST_SUB_DRC = BIT(1), 117 + IRIS_INST_SUB_DRC_LAST = BIT(2), 118 + IRIS_INST_SUB_INPUT_PAUSE = BIT(3), 119 + IRIS_INST_SUB_OUTPUT_PAUSE = BIT(4), 120 + }; 121 + 94 122 int iris_inst_change_state(struct iris_inst *inst, 95 123 enum iris_inst_state request_state); 124 + int iris_inst_change_sub_state(struct iris_inst *inst, 125 + enum iris_inst_sub_state clear_sub_state, 126 + enum iris_inst_sub_state set_sub_state); 96 127 int iris_inst_state_change_streamon(struct iris_inst *inst, u32 plane); 97 128 int iris_inst_state_change_streamoff(struct iris_inst *inst, u32 plane); 129 + int iris_inst_sub_state_change_drc(struct iris_inst *inst); 130 + int iris_inst_sub_state_change_drc_last(struct iris_inst *inst); 98 131 99 132 #endif
+18
drivers/media/platform/qcom/iris/iris_vb2.c
··· 4 4 */ 5 5 6 6 #include <media/videobuf2-dma-contig.h> 7 + #include <media/v4l2-event.h> 7 8 #include <media/v4l2-mem2mem.h> 8 9 9 10 #include "iris_instance.h" ··· 181 180 182 181 void iris_vb2_buf_queue(struct vb2_buffer *vb2) 183 182 { 183 + static const struct v4l2_event eos = { .type = V4L2_EVENT_EOS }; 184 184 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); 185 185 struct v4l2_m2m_ctx *m2m_ctx; 186 186 struct iris_inst *inst; ··· 203 201 if (!vb2->planes[0].bytesused && V4L2_TYPE_IS_OUTPUT(vb2->type)) { 204 202 ret = -EINVAL; 205 203 goto exit; 204 + } 205 + 206 + if (V4L2_TYPE_IS_CAPTURE(vb2->vb2_queue->type)) { 207 + if (inst->sub_state & IRIS_INST_SUB_DRC && 208 + inst->sub_state & IRIS_INST_SUB_DRC_LAST) { 209 + vbuf->flags |= V4L2_BUF_FLAG_LAST; 210 + vbuf->sequence = inst->sequence_cap++; 211 + vbuf->field = V4L2_FIELD_NONE; 212 + vb2_set_plane_payload(vb2, 0, 0); 213 + v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE); 214 + if (!v4l2_m2m_has_stopped(m2m_ctx)) { 215 + v4l2_event_queue_fh(&inst->fh, &eos); 216 + v4l2_m2m_mark_stopped(m2m_ctx); 217 + } 218 + goto exit; 219 + } 206 220 } 207 221 208 222 v4l2_m2m_buf_queue(m2m_ctx, vbuf);
+15
drivers/media/platform/qcom/iris/iris_vdec.c
··· 223 223 return ret; 224 224 } 225 225 226 + void iris_vdec_src_change(struct iris_inst *inst) 227 + { 228 + struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; 229 + struct v4l2_event event = {0}; 230 + struct vb2_queue *src_q; 231 + 232 + src_q = v4l2_m2m_get_src_vq(m2m_ctx); 233 + if (!vb2_is_streaming(src_q)) 234 + return; 235 + 236 + event.type = V4L2_EVENT_SOURCE_CHANGE; 237 + event.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION; 238 + v4l2_event_queue_fh(&inst->fh, &event); 239 + } 240 + 226 241 static int iris_vdec_get_num_queued_buffers(struct iris_inst *inst, 227 242 enum iris_buffer_type type) 228 243 {
+1
drivers/media/platform/qcom/iris/iris_vdec.h
··· 14 14 int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f); 15 15 int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f); 16 16 int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub); 17 + void iris_vdec_src_change(struct iris_inst *inst); 17 18 int iris_vdec_streamon_input(struct iris_inst *inst); 18 19 int iris_vdec_streamon_output(struct iris_inst *inst); 19 20 int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf);