1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4 */
5
6 #include <linux/bitfield.h>
7
8 #include "iris_hfi_gen2.h"
9 #include "iris_hfi_gen2_packet.h"
10
11 #define UNSPECIFIED_COLOR_FORMAT 5
12 #define NUM_SYS_INIT_PACKETS 8
13
14 #define SYS_INIT_PKT_SIZE (sizeof(struct iris_hfi_header) + \
15 NUM_SYS_INIT_PACKETS * (sizeof(struct iris_hfi_packet) + sizeof(u32)))
16
17 #define SYS_IFPC_PKT_SIZE (sizeof(struct iris_hfi_header) + \
18 sizeof(struct iris_hfi_packet) + sizeof(u32))
19
20 #define SYS_NO_PAYLOAD_PKT_SIZE (sizeof(struct iris_hfi_header) + \
21 sizeof(struct iris_hfi_packet))
22
iris_hfi_gen2_sys_init(struct iris_core * core)23 static int iris_hfi_gen2_sys_init(struct iris_core *core)
24 {
25 struct iris_hfi_header *hdr;
26 int ret;
27
28 hdr = kzalloc(SYS_INIT_PKT_SIZE, GFP_KERNEL);
29 if (!hdr)
30 return -ENOMEM;
31
32 iris_hfi_gen2_packet_sys_init(core, hdr);
33 ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size);
34
35 kfree(hdr);
36
37 return ret;
38 }
39
iris_hfi_gen2_sys_image_version(struct iris_core * core)40 static int iris_hfi_gen2_sys_image_version(struct iris_core *core)
41 {
42 struct iris_hfi_header *hdr;
43 int ret;
44
45 hdr = kzalloc(SYS_NO_PAYLOAD_PKT_SIZE, GFP_KERNEL);
46 if (!hdr)
47 return -ENOMEM;
48
49 iris_hfi_gen2_packet_image_version(core, hdr);
50 ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size);
51
52 kfree(hdr);
53
54 return ret;
55 }
56
iris_hfi_gen2_sys_interframe_powercollapse(struct iris_core * core)57 static int iris_hfi_gen2_sys_interframe_powercollapse(struct iris_core *core)
58 {
59 struct iris_hfi_header *hdr;
60 int ret;
61
62 hdr = kzalloc(SYS_IFPC_PKT_SIZE, GFP_KERNEL);
63 if (!hdr)
64 return -ENOMEM;
65
66 iris_hfi_gen2_packet_sys_interframe_powercollapse(core, hdr);
67 ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size);
68
69 kfree(hdr);
70
71 return ret;
72 }
73
iris_hfi_gen2_sys_pc_prep(struct iris_core * core)74 static int iris_hfi_gen2_sys_pc_prep(struct iris_core *core)
75 {
76 struct iris_hfi_header *hdr;
77 int ret;
78
79 hdr = kzalloc(SYS_NO_PAYLOAD_PKT_SIZE, GFP_KERNEL);
80 if (!hdr)
81 return -ENOMEM;
82
83 iris_hfi_gen2_packet_sys_pc_prep(core, hdr);
84 ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size);
85
86 kfree(hdr);
87
88 return ret;
89 }
90
iris_hfi_gen2_get_port(u32 plane)91 static u32 iris_hfi_gen2_get_port(u32 plane)
92 {
93 switch (plane) {
94 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
95 return HFI_PORT_BITSTREAM;
96 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
97 return HFI_PORT_RAW;
98 default:
99 return HFI_PORT_NONE;
100 }
101 }
102
iris_hfi_gen2_get_port_from_buf_type(enum iris_buffer_type buffer_type)103 static u32 iris_hfi_gen2_get_port_from_buf_type(enum iris_buffer_type buffer_type)
104 {
105 switch (buffer_type) {
106 case BUF_INPUT:
107 case BUF_BIN:
108 case BUF_COMV:
109 case BUF_NON_COMV:
110 case BUF_LINE:
111 return HFI_PORT_BITSTREAM;
112 case BUF_OUTPUT:
113 case BUF_DPB:
114 return HFI_PORT_RAW;
115 case BUF_PERSIST:
116 default:
117 return HFI_PORT_NONE;
118 }
119 }
120
iris_hfi_gen2_session_set_property(struct iris_inst * inst,u32 packet_type,u32 flag,u32 plane,u32 payload_type,void * payload,u32 payload_size)121 static int iris_hfi_gen2_session_set_property(struct iris_inst *inst, u32 packet_type, u32 flag,
122 u32 plane, u32 payload_type, void *payload,
123 u32 payload_size)
124 {
125 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
126
127 iris_hfi_gen2_packet_session_property(inst,
128 packet_type,
129 flag,
130 plane,
131 payload_type,
132 payload,
133 payload_size);
134
135 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
136 inst_hfi_gen2->packet->size);
137 }
138
iris_hfi_gen2_set_bitstream_resolution(struct iris_inst * inst)139 static int iris_hfi_gen2_set_bitstream_resolution(struct iris_inst *inst)
140 {
141 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
142 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
143 u32 resolution = inst->fmt_src->fmt.pix_mp.width << 16 |
144 inst->fmt_src->fmt.pix_mp.height;
145
146 inst_hfi_gen2->src_subcr_params.bitstream_resolution = resolution;
147
148 return iris_hfi_gen2_session_set_property(inst,
149 HFI_PROP_BITSTREAM_RESOLUTION,
150 HFI_HOST_FLAGS_NONE,
151 port,
152 HFI_PAYLOAD_U32,
153 &resolution,
154 sizeof(u32));
155 }
156
iris_hfi_gen2_set_crop_offsets(struct iris_inst * inst)157 static int iris_hfi_gen2_set_crop_offsets(struct iris_inst *inst)
158 {
159 u32 bottom_offset = (inst->fmt_src->fmt.pix_mp.height - inst->crop.height);
160 u32 right_offset = (inst->fmt_src->fmt.pix_mp.width - inst->crop.width);
161 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
162 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
163 u32 left_offset = inst->crop.left;
164 u32 top_offset = inst->crop.top;
165 u32 payload[2];
166
167 payload[0] = FIELD_PREP(GENMASK(31, 16), left_offset) | top_offset;
168 payload[1] = FIELD_PREP(GENMASK(31, 16), right_offset) | bottom_offset;
169 inst_hfi_gen2->src_subcr_params.crop_offsets[0] = payload[0];
170 inst_hfi_gen2->src_subcr_params.crop_offsets[1] = payload[1];
171
172 return iris_hfi_gen2_session_set_property(inst,
173 HFI_PROP_CROP_OFFSETS,
174 HFI_HOST_FLAGS_NONE,
175 port,
176 HFI_PAYLOAD_64_PACKED,
177 &payload,
178 sizeof(u64));
179 }
180
iris_hfi_gen2_set_bit_dpeth(struct iris_inst * inst)181 static int iris_hfi_gen2_set_bit_dpeth(struct iris_inst *inst)
182 {
183 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
184 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
185 u32 bitdepth = BIT_DEPTH_8;
186
187 inst_hfi_gen2->src_subcr_params.bit_depth = bitdepth;
188
189 return iris_hfi_gen2_session_set_property(inst,
190 HFI_PROP_LUMA_CHROMA_BIT_DEPTH,
191 HFI_HOST_FLAGS_NONE,
192 port,
193 HFI_PAYLOAD_U32,
194 &bitdepth,
195 sizeof(u32));
196 }
197
iris_hfi_gen2_set_coded_frames(struct iris_inst * inst)198 static int iris_hfi_gen2_set_coded_frames(struct iris_inst *inst)
199 {
200 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
201 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
202 u32 coded_frames = 0;
203
204 if (inst->fw_caps[CODED_FRAMES].value == CODED_FRAMES_PROGRESSIVE)
205 coded_frames = HFI_BITMASK_FRAME_MBS_ONLY_FLAG;
206 inst_hfi_gen2->src_subcr_params.coded_frames = coded_frames;
207
208 return iris_hfi_gen2_session_set_property(inst,
209 HFI_PROP_CODED_FRAMES,
210 HFI_HOST_FLAGS_NONE,
211 port,
212 HFI_PAYLOAD_U32,
213 &coded_frames,
214 sizeof(u32));
215 }
216
iris_hfi_gen2_set_min_output_count(struct iris_inst * inst)217 static int iris_hfi_gen2_set_min_output_count(struct iris_inst *inst)
218 {
219 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
220 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
221 u32 min_output = inst->buffers[BUF_OUTPUT].min_count;
222
223 inst_hfi_gen2->src_subcr_params.fw_min_count = min_output;
224
225 return iris_hfi_gen2_session_set_property(inst,
226 HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,
227 HFI_HOST_FLAGS_NONE,
228 port,
229 HFI_PAYLOAD_U32,
230 &min_output,
231 sizeof(u32));
232 }
233
iris_hfi_gen2_set_picture_order_count(struct iris_inst * inst)234 static int iris_hfi_gen2_set_picture_order_count(struct iris_inst *inst)
235 {
236 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
237 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
238 u32 poc = 0;
239
240 inst_hfi_gen2->src_subcr_params.pic_order_cnt = poc;
241
242 return iris_hfi_gen2_session_set_property(inst,
243 HFI_PROP_PIC_ORDER_CNT_TYPE,
244 HFI_HOST_FLAGS_NONE,
245 port,
246 HFI_PAYLOAD_U32,
247 &poc,
248 sizeof(u32));
249 }
250
iris_hfi_gen2_set_colorspace(struct iris_inst * inst)251 static int iris_hfi_gen2_set_colorspace(struct iris_inst *inst)
252 {
253 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
254 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
255 struct v4l2_pix_format_mplane *pixmp = &inst->fmt_src->fmt.pix_mp;
256 u32 video_signal_type_present_flag = 0, color_info;
257 u32 matrix_coeff = HFI_MATRIX_COEFF_RESERVED;
258 u32 video_format = UNSPECIFIED_COLOR_FORMAT;
259 u32 full_range = V4L2_QUANTIZATION_DEFAULT;
260 u32 transfer_char = HFI_TRANSFER_RESERVED;
261 u32 colour_description_present_flag = 0;
262 u32 primaries = HFI_PRIMARIES_RESERVED;
263
264 if (pixmp->colorspace != V4L2_COLORSPACE_DEFAULT ||
265 pixmp->ycbcr_enc != V4L2_YCBCR_ENC_DEFAULT ||
266 pixmp->xfer_func != V4L2_XFER_FUNC_DEFAULT) {
267 colour_description_present_flag = 1;
268 video_signal_type_present_flag = 1;
269 primaries = iris_hfi_gen2_get_color_primaries(pixmp->colorspace);
270 matrix_coeff = iris_hfi_gen2_get_matrix_coefficients(pixmp->ycbcr_enc);
271 transfer_char = iris_hfi_gen2_get_transfer_char(pixmp->xfer_func);
272 }
273
274 if (pixmp->quantization != V4L2_QUANTIZATION_DEFAULT) {
275 video_signal_type_present_flag = 1;
276 full_range = pixmp->quantization == V4L2_QUANTIZATION_FULL_RANGE ? 1 : 0;
277 }
278
279 color_info = iris_hfi_gen2_get_color_info(matrix_coeff, transfer_char, primaries,
280 colour_description_present_flag, full_range,
281 video_format, video_signal_type_present_flag);
282
283 inst_hfi_gen2->src_subcr_params.color_info = color_info;
284
285 return iris_hfi_gen2_session_set_property(inst,
286 HFI_PROP_SIGNAL_COLOR_INFO,
287 HFI_HOST_FLAGS_NONE,
288 port,
289 HFI_PAYLOAD_32_PACKED,
290 &color_info,
291 sizeof(u32));
292 }
293
iris_hfi_gen2_set_profile(struct iris_inst * inst)294 static int iris_hfi_gen2_set_profile(struct iris_inst *inst)
295 {
296 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
297 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
298 u32 profile = inst->fw_caps[PROFILE].value;
299
300 inst_hfi_gen2->src_subcr_params.profile = profile;
301
302 return iris_hfi_gen2_session_set_property(inst,
303 HFI_PROP_PROFILE,
304 HFI_HOST_FLAGS_NONE,
305 port,
306 HFI_PAYLOAD_U32_ENUM,
307 &profile,
308 sizeof(u32));
309 }
310
iris_hfi_gen2_set_level(struct iris_inst * inst)311 static int iris_hfi_gen2_set_level(struct iris_inst *inst)
312 {
313 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
314 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
315 u32 level = inst->fw_caps[LEVEL].value;
316
317 inst_hfi_gen2->src_subcr_params.level = level;
318
319 return iris_hfi_gen2_session_set_property(inst,
320 HFI_PROP_LEVEL,
321 HFI_HOST_FLAGS_NONE,
322 port,
323 HFI_PAYLOAD_U32_ENUM,
324 &level,
325 sizeof(u32));
326 }
327
iris_hfi_gen2_set_colorformat(struct iris_inst * inst)328 static int iris_hfi_gen2_set_colorformat(struct iris_inst *inst)
329 {
330 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
331 u32 hfi_colorformat, pixelformat;
332
333 pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat;
334 hfi_colorformat = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FMT_NV12 : 0;
335
336 return iris_hfi_gen2_session_set_property(inst,
337 HFI_PROP_COLOR_FORMAT,
338 HFI_HOST_FLAGS_NONE,
339 port,
340 HFI_PAYLOAD_U32,
341 &hfi_colorformat,
342 sizeof(u32));
343 }
344
iris_hfi_gen2_set_linear_stride_scanline(struct iris_inst * inst)345 static int iris_hfi_gen2_set_linear_stride_scanline(struct iris_inst *inst)
346 {
347 u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
348 u32 pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat;
349 u32 scanline_y = inst->fmt_dst->fmt.pix_mp.height;
350 u32 stride_y = inst->fmt_dst->fmt.pix_mp.width;
351 u32 scanline_uv = scanline_y / 2;
352 u32 stride_uv = stride_y;
353 u32 payload[2];
354
355 if (pixelformat != V4L2_PIX_FMT_NV12)
356 return 0;
357
358 payload[0] = stride_y << 16 | scanline_y;
359 payload[1] = stride_uv << 16 | scanline_uv;
360
361 return iris_hfi_gen2_session_set_property(inst,
362 HFI_PROP_LINEAR_STRIDE_SCANLINE,
363 HFI_HOST_FLAGS_NONE,
364 port,
365 HFI_PAYLOAD_U64,
366 &payload,
367 sizeof(u64));
368 }
369
iris_hfi_gen2_session_set_config_params(struct iris_inst * inst,u32 plane)370 static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 plane)
371 {
372 struct iris_core *core = inst->core;
373 u32 config_params_size, i, j;
374 const u32 *config_params;
375 int ret;
376
377 static const struct iris_hfi_prop_type_handle prop_type_handle_arr[] = {
378 {HFI_PROP_BITSTREAM_RESOLUTION, iris_hfi_gen2_set_bitstream_resolution },
379 {HFI_PROP_CROP_OFFSETS, iris_hfi_gen2_set_crop_offsets },
380 {HFI_PROP_CODED_FRAMES, iris_hfi_gen2_set_coded_frames },
381 {HFI_PROP_LUMA_CHROMA_BIT_DEPTH, iris_hfi_gen2_set_bit_dpeth },
382 {HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT, iris_hfi_gen2_set_min_output_count },
383 {HFI_PROP_PIC_ORDER_CNT_TYPE, iris_hfi_gen2_set_picture_order_count },
384 {HFI_PROP_SIGNAL_COLOR_INFO, iris_hfi_gen2_set_colorspace },
385 {HFI_PROP_PROFILE, iris_hfi_gen2_set_profile },
386 {HFI_PROP_LEVEL, iris_hfi_gen2_set_level },
387 {HFI_PROP_COLOR_FORMAT, iris_hfi_gen2_set_colorformat },
388 {HFI_PROP_LINEAR_STRIDE_SCANLINE, iris_hfi_gen2_set_linear_stride_scanline },
389 };
390
391 if (V4L2_TYPE_IS_OUTPUT(plane)) {
392 config_params = core->iris_platform_data->input_config_params;
393 config_params_size = core->iris_platform_data->input_config_params_size;
394 } else {
395 config_params = core->iris_platform_data->output_config_params;
396 config_params_size = core->iris_platform_data->output_config_params_size;
397 }
398
399 if (!config_params || !config_params_size)
400 return -EINVAL;
401
402 for (i = 0; i < config_params_size; i++) {
403 for (j = 0; j < ARRAY_SIZE(prop_type_handle_arr); j++) {
404 if (prop_type_handle_arr[j].type == config_params[i]) {
405 ret = prop_type_handle_arr[j].handle(inst);
406 if (ret)
407 return ret;
408 break;
409 }
410 }
411 }
412
413 return 0;
414 }
415
iris_hfi_gen2_session_set_codec(struct iris_inst * inst)416 static int iris_hfi_gen2_session_set_codec(struct iris_inst *inst)
417 {
418 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
419 u32 codec = HFI_CODEC_DECODE_AVC;
420
421 iris_hfi_gen2_packet_session_property(inst,
422 HFI_PROP_CODEC,
423 HFI_HOST_FLAGS_NONE,
424 HFI_PORT_NONE,
425 HFI_PAYLOAD_U32_ENUM,
426 &codec,
427 sizeof(u32));
428
429 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
430 inst_hfi_gen2->packet->size);
431 }
432
iris_hfi_gen2_session_set_default_header(struct iris_inst * inst)433 static int iris_hfi_gen2_session_set_default_header(struct iris_inst *inst)
434 {
435 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
436 u32 default_header = false;
437
438 iris_hfi_gen2_packet_session_property(inst,
439 HFI_PROP_DEC_DEFAULT_HEADER,
440 HFI_HOST_FLAGS_NONE,
441 HFI_PORT_BITSTREAM,
442 HFI_PAYLOAD_U32,
443 &default_header,
444 sizeof(u32));
445
446 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
447 inst_hfi_gen2->packet->size);
448 }
449
iris_hfi_gen2_session_open(struct iris_inst * inst)450 static int iris_hfi_gen2_session_open(struct iris_inst *inst)
451 {
452 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
453 int ret;
454
455 if (inst->state != IRIS_INST_DEINIT)
456 return -EALREADY;
457
458 inst_hfi_gen2->ipsc_properties_set = false;
459 inst_hfi_gen2->opsc_properties_set = false;
460
461 inst_hfi_gen2->packet = kzalloc(4096, GFP_KERNEL);
462 if (!inst_hfi_gen2->packet)
463 return -ENOMEM;
464
465 iris_hfi_gen2_packet_session_command(inst,
466 HFI_CMD_OPEN,
467 HFI_HOST_FLAGS_RESPONSE_REQUIRED |
468 HFI_HOST_FLAGS_INTR_REQUIRED,
469 HFI_PORT_NONE,
470 0,
471 HFI_PAYLOAD_U32,
472 &inst->session_id,
473 sizeof(u32));
474
475 ret = iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
476 inst_hfi_gen2->packet->size);
477 if (ret)
478 goto fail_free_packet;
479
480 ret = iris_hfi_gen2_session_set_codec(inst);
481 if (ret)
482 goto fail_free_packet;
483
484 ret = iris_hfi_gen2_session_set_default_header(inst);
485 if (ret)
486 goto fail_free_packet;
487
488 return 0;
489
490 fail_free_packet:
491 kfree(inst_hfi_gen2->packet);
492 inst_hfi_gen2->packet = NULL;
493
494 return ret;
495 }
496
iris_hfi_gen2_session_close(struct iris_inst * inst)497 static int iris_hfi_gen2_session_close(struct iris_inst *inst)
498 {
499 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
500 int ret;
501
502 if (!inst_hfi_gen2->packet)
503 return -EINVAL;
504
505 iris_hfi_gen2_packet_session_command(inst,
506 HFI_CMD_CLOSE,
507 (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
508 HFI_HOST_FLAGS_INTR_REQUIRED |
509 HFI_HOST_FLAGS_NON_DISCARDABLE),
510 HFI_PORT_NONE,
511 inst->session_id,
512 HFI_PAYLOAD_NONE,
513 NULL,
514 0);
515
516 ret = iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
517 inst_hfi_gen2->packet->size);
518
519 kfree(inst_hfi_gen2->packet);
520 inst_hfi_gen2->packet = NULL;
521
522 return ret;
523 }
524
iris_hfi_gen2_session_subscribe_mode(struct iris_inst * inst,u32 cmd,u32 plane,u32 payload_type,void * payload,u32 payload_size)525 static int iris_hfi_gen2_session_subscribe_mode(struct iris_inst *inst,
526 u32 cmd, u32 plane, u32 payload_type,
527 void *payload, u32 payload_size)
528 {
529 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
530
531 iris_hfi_gen2_packet_session_command(inst,
532 cmd,
533 (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
534 HFI_HOST_FLAGS_INTR_REQUIRED),
535 iris_hfi_gen2_get_port(plane),
536 inst->session_id,
537 payload_type,
538 payload,
539 payload_size);
540
541 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
542 inst_hfi_gen2->packet->size);
543 }
544
iris_hfi_gen2_subscribe_change_param(struct iris_inst * inst,u32 plane)545 static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plane)
546 {
547 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
548 struct hfi_subscription_params subsc_params;
549 u32 prop_type, payload_size, payload_type;
550 struct iris_core *core = inst->core;
551 const u32 *change_param;
552 u32 change_param_size;
553 u32 payload[32] = {0};
554 u32 hfi_port = 0, i;
555 int ret;
556
557 if ((V4L2_TYPE_IS_OUTPUT(plane) && inst_hfi_gen2->ipsc_properties_set) ||
558 (V4L2_TYPE_IS_CAPTURE(plane) && inst_hfi_gen2->opsc_properties_set)) {
559 dev_err(core->dev, "invalid plane\n");
560 return 0;
561 }
562
563 change_param = core->iris_platform_data->input_config_params;
564 change_param_size = core->iris_platform_data->input_config_params_size;
565
566 payload[0] = HFI_MODE_PORT_SETTINGS_CHANGE;
567
568 for (i = 0; i < change_param_size; i++)
569 payload[i + 1] = change_param[i];
570
571 ret = iris_hfi_gen2_session_subscribe_mode(inst,
572 HFI_CMD_SUBSCRIBE_MODE,
573 plane,
574 HFI_PAYLOAD_U32_ARRAY,
575 &payload[0],
576 ((change_param_size + 1) * sizeof(u32)));
577 if (ret)
578 return ret;
579
580 if (V4L2_TYPE_IS_OUTPUT(plane)) {
581 inst_hfi_gen2->ipsc_properties_set = true;
582 } else {
583 hfi_port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
584 memcpy(&inst_hfi_gen2->dst_subcr_params,
585 &inst_hfi_gen2->src_subcr_params,
586 sizeof(inst_hfi_gen2->src_subcr_params));
587 subsc_params = inst_hfi_gen2->dst_subcr_params;
588 for (i = 0; i < change_param_size; i++) {
589 payload[0] = 0;
590 payload[1] = 0;
591 payload_size = 0;
592 payload_type = 0;
593 prop_type = change_param[i];
594 switch (prop_type) {
595 case HFI_PROP_BITSTREAM_RESOLUTION:
596 payload[0] = subsc_params.bitstream_resolution;
597 payload_size = sizeof(u32);
598 payload_type = HFI_PAYLOAD_U32;
599 break;
600 case HFI_PROP_CROP_OFFSETS:
601 payload[0] = subsc_params.crop_offsets[0];
602 payload[1] = subsc_params.crop_offsets[1];
603 payload_size = sizeof(u64);
604 payload_type = HFI_PAYLOAD_64_PACKED;
605 break;
606 case HFI_PROP_CODED_FRAMES:
607 payload[0] = subsc_params.coded_frames;
608 payload_size = sizeof(u32);
609 payload_type = HFI_PAYLOAD_U32;
610 break;
611 case HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT:
612 payload[0] = subsc_params.fw_min_count;
613 payload_size = sizeof(u32);
614 payload_type = HFI_PAYLOAD_U32;
615 break;
616 case HFI_PROP_PIC_ORDER_CNT_TYPE:
617 payload[0] = subsc_params.pic_order_cnt;
618 payload_size = sizeof(u32);
619 payload_type = HFI_PAYLOAD_U32;
620 break;
621 case HFI_PROP_SIGNAL_COLOR_INFO:
622 payload[0] = subsc_params.color_info;
623 payload_size = sizeof(u32);
624 payload_type = HFI_PAYLOAD_U32;
625 break;
626 case HFI_PROP_PROFILE:
627 payload[0] = subsc_params.profile;
628 payload_size = sizeof(u32);
629 payload_type = HFI_PAYLOAD_U32;
630 break;
631 case HFI_PROP_LEVEL:
632 payload[0] = subsc_params.level;
633 payload_size = sizeof(u32);
634 payload_type = HFI_PAYLOAD_U32;
635 break;
636 default:
637 prop_type = 0;
638 ret = -EINVAL;
639 break;
640 }
641 if (prop_type) {
642 ret = iris_hfi_gen2_session_set_property(inst,
643 prop_type,
644 HFI_HOST_FLAGS_NONE,
645 hfi_port,
646 payload_type,
647 &payload,
648 payload_size);
649 if (ret)
650 return ret;
651 }
652 }
653 inst_hfi_gen2->opsc_properties_set = true;
654 }
655
656 return 0;
657 }
658
iris_hfi_gen2_subscribe_property(struct iris_inst * inst,u32 plane)659 static int iris_hfi_gen2_subscribe_property(struct iris_inst *inst, u32 plane)
660 {
661 struct iris_core *core = inst->core;
662 u32 subscribe_prop_size, i;
663 const u32 *subcribe_prop;
664 u32 payload[32] = {0};
665
666 payload[0] = HFI_MODE_PROPERTY;
667
668 if (V4L2_TYPE_IS_OUTPUT(plane)) {
669 subscribe_prop_size = core->iris_platform_data->dec_input_prop_size;
670 subcribe_prop = core->iris_platform_data->dec_input_prop;
671 } else {
672 subscribe_prop_size = core->iris_platform_data->dec_output_prop_size;
673 subcribe_prop = core->iris_platform_data->dec_output_prop;
674 }
675
676 for (i = 0; i < subscribe_prop_size; i++)
677 payload[i + 1] = subcribe_prop[i];
678
679 return iris_hfi_gen2_session_subscribe_mode(inst,
680 HFI_CMD_SUBSCRIBE_MODE,
681 plane,
682 HFI_PAYLOAD_U32_ARRAY,
683 &payload[0],
684 (subscribe_prop_size + 1) * sizeof(u32));
685 }
686
iris_hfi_gen2_session_start(struct iris_inst * inst,u32 plane)687 static int iris_hfi_gen2_session_start(struct iris_inst *inst, u32 plane)
688 {
689 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
690 int ret = 0;
691
692 ret = iris_hfi_gen2_subscribe_change_param(inst, plane);
693 if (ret)
694 return ret;
695
696 ret = iris_hfi_gen2_subscribe_property(inst, plane);
697 if (ret)
698 return ret;
699
700 iris_hfi_gen2_packet_session_command(inst,
701 HFI_CMD_START,
702 (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
703 HFI_HOST_FLAGS_INTR_REQUIRED),
704 iris_hfi_gen2_get_port(plane),
705 inst->session_id,
706 HFI_PAYLOAD_NONE,
707 NULL,
708 0);
709
710 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
711 inst_hfi_gen2->packet->size);
712 }
713
iris_hfi_gen2_session_stop(struct iris_inst * inst,u32 plane)714 static int iris_hfi_gen2_session_stop(struct iris_inst *inst, u32 plane)
715 {
716 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
717 int ret = 0;
718
719 reinit_completion(&inst->completion);
720
721 iris_hfi_gen2_packet_session_command(inst,
722 HFI_CMD_STOP,
723 (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
724 HFI_HOST_FLAGS_INTR_REQUIRED |
725 HFI_HOST_FLAGS_NON_DISCARDABLE),
726 iris_hfi_gen2_get_port(plane),
727 inst->session_id,
728 HFI_PAYLOAD_NONE,
729 NULL,
730 0);
731
732 ret = iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
733 inst_hfi_gen2->packet->size);
734 if (ret)
735 return ret;
736
737 return iris_wait_for_session_response(inst, false);
738 }
739
iris_hfi_gen2_session_pause(struct iris_inst * inst,u32 plane)740 static int iris_hfi_gen2_session_pause(struct iris_inst *inst, u32 plane)
741 {
742 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
743
744 iris_hfi_gen2_packet_session_command(inst,
745 HFI_CMD_PAUSE,
746 (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
747 HFI_HOST_FLAGS_INTR_REQUIRED),
748 iris_hfi_gen2_get_port(plane),
749 inst->session_id,
750 HFI_PAYLOAD_NONE,
751 NULL,
752 0);
753
754 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
755 inst_hfi_gen2->packet->size);
756 }
757
iris_hfi_gen2_session_resume_drc(struct iris_inst * inst,u32 plane)758 static int iris_hfi_gen2_session_resume_drc(struct iris_inst *inst, u32 plane)
759 {
760 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
761 u32 payload = HFI_CMD_SETTINGS_CHANGE;
762
763 iris_hfi_gen2_packet_session_command(inst,
764 HFI_CMD_RESUME,
765 (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
766 HFI_HOST_FLAGS_INTR_REQUIRED),
767 iris_hfi_gen2_get_port(plane),
768 inst->session_id,
769 HFI_PAYLOAD_U32,
770 &payload,
771 sizeof(u32));
772
773 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
774 inst_hfi_gen2->packet->size);
775 }
776
iris_hfi_gen2_session_resume_drain(struct iris_inst * inst,u32 plane)777 static int iris_hfi_gen2_session_resume_drain(struct iris_inst *inst, u32 plane)
778 {
779 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
780 u32 payload = HFI_CMD_DRAIN;
781
782 iris_hfi_gen2_packet_session_command(inst,
783 HFI_CMD_RESUME,
784 (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
785 HFI_HOST_FLAGS_INTR_REQUIRED),
786 iris_hfi_gen2_get_port(plane),
787 inst->session_id,
788 HFI_PAYLOAD_U32,
789 &payload,
790 sizeof(u32));
791
792 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
793 inst_hfi_gen2->packet->size);
794 }
795
iris_hfi_gen2_session_drain(struct iris_inst * inst,u32 plane)796 static int iris_hfi_gen2_session_drain(struct iris_inst *inst, u32 plane)
797 {
798 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
799
800 if (!V4L2_TYPE_IS_OUTPUT(plane))
801 return 0;
802
803 iris_hfi_gen2_packet_session_command(inst,
804 HFI_CMD_DRAIN,
805 (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
806 HFI_HOST_FLAGS_INTR_REQUIRED |
807 HFI_HOST_FLAGS_NON_DISCARDABLE),
808 iris_hfi_gen2_get_port(plane),
809 inst->session_id,
810 HFI_PAYLOAD_NONE,
811 NULL,
812 0);
813
814 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
815 inst_hfi_gen2->packet->size);
816 }
817
iris_hfi_gen2_buf_type_from_driver(enum iris_buffer_type buffer_type)818 static u32 iris_hfi_gen2_buf_type_from_driver(enum iris_buffer_type buffer_type)
819 {
820 switch (buffer_type) {
821 case BUF_INPUT:
822 return HFI_BUFFER_BITSTREAM;
823 case BUF_OUTPUT:
824 return HFI_BUFFER_RAW;
825 case BUF_BIN:
826 return HFI_BUFFER_BIN;
827 case BUF_COMV:
828 return HFI_BUFFER_COMV;
829 case BUF_NON_COMV:
830 return HFI_BUFFER_NON_COMV;
831 case BUF_LINE:
832 return HFI_BUFFER_LINE;
833 case BUF_DPB:
834 return HFI_BUFFER_DPB;
835 case BUF_PERSIST:
836 return HFI_BUFFER_PERSIST;
837 default:
838 return 0;
839 }
840 }
841
iris_set_num_comv(struct iris_inst * inst)842 static int iris_set_num_comv(struct iris_inst *inst)
843 {
844 struct platform_inst_caps *caps;
845 struct iris_core *core = inst->core;
846 u32 num_comv;
847
848 caps = core->iris_platform_data->inst_caps;
849 num_comv = caps->num_comv;
850
851 return core->hfi_ops->session_set_property(inst,
852 HFI_PROP_COMV_BUFFER_COUNT,
853 HFI_HOST_FLAGS_NONE,
854 HFI_PORT_BITSTREAM,
855 HFI_PAYLOAD_U32,
856 &num_comv, sizeof(u32));
857 }
858
iris_hfi_gen2_get_buffer(struct iris_buffer * buffer,struct iris_hfi_buffer * buf)859 static void iris_hfi_gen2_get_buffer(struct iris_buffer *buffer, struct iris_hfi_buffer *buf)
860 {
861 memset(buf, 0, sizeof(*buf));
862 buf->type = iris_hfi_gen2_buf_type_from_driver(buffer->type);
863 buf->index = buffer->index;
864 buf->base_address = buffer->device_addr;
865 buf->addr_offset = 0;
866 buf->buffer_size = buffer->buffer_size;
867
868 if (buffer->type == BUF_INPUT)
869 buf->buffer_size = ALIGN(buffer->buffer_size, 256);
870 buf->data_offset = buffer->data_offset;
871 buf->data_size = buffer->data_size;
872 if (buffer->attr & BUF_ATTR_PENDING_RELEASE)
873 buf->flags |= HFI_BUF_HOST_FLAG_RELEASE;
874 buf->flags |= HFI_BUF_HOST_FLAGS_CB_NON_SECURE;
875 buf->timestamp = buffer->timestamp;
876 }
877
iris_hfi_gen2_session_queue_buffer(struct iris_inst * inst,struct iris_buffer * buffer)878 static int iris_hfi_gen2_session_queue_buffer(struct iris_inst *inst, struct iris_buffer *buffer)
879 {
880 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
881 struct iris_hfi_buffer hfi_buffer;
882 u32 port;
883 int ret;
884
885 iris_hfi_gen2_get_buffer(buffer, &hfi_buffer);
886 if (buffer->type == BUF_COMV) {
887 ret = iris_set_num_comv(inst);
888 if (ret)
889 return ret;
890 }
891
892 port = iris_hfi_gen2_get_port_from_buf_type(buffer->type);
893 iris_hfi_gen2_packet_session_command(inst,
894 HFI_CMD_BUFFER,
895 HFI_HOST_FLAGS_INTR_REQUIRED,
896 port,
897 inst->session_id,
898 HFI_PAYLOAD_STRUCTURE,
899 &hfi_buffer,
900 sizeof(hfi_buffer));
901
902 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
903 inst_hfi_gen2->packet->size);
904 }
905
iris_hfi_gen2_session_release_buffer(struct iris_inst * inst,struct iris_buffer * buffer)906 static int iris_hfi_gen2_session_release_buffer(struct iris_inst *inst, struct iris_buffer *buffer)
907 {
908 struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
909 struct iris_hfi_buffer hfi_buffer;
910 u32 port;
911
912 iris_hfi_gen2_get_buffer(buffer, &hfi_buffer);
913 hfi_buffer.flags |= HFI_BUF_HOST_FLAG_RELEASE;
914 port = iris_hfi_gen2_get_port_from_buf_type(buffer->type);
915
916 iris_hfi_gen2_packet_session_command(inst,
917 HFI_CMD_BUFFER,
918 (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
919 HFI_HOST_FLAGS_INTR_REQUIRED),
920 port,
921 inst->session_id,
922 HFI_PAYLOAD_STRUCTURE,
923 &hfi_buffer,
924 sizeof(hfi_buffer));
925
926 return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
927 inst_hfi_gen2->packet->size);
928 }
929
930 static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = {
931 .sys_init = iris_hfi_gen2_sys_init,
932 .sys_image_version = iris_hfi_gen2_sys_image_version,
933 .sys_interframe_powercollapse = iris_hfi_gen2_sys_interframe_powercollapse,
934 .sys_pc_prep = iris_hfi_gen2_sys_pc_prep,
935 .session_open = iris_hfi_gen2_session_open,
936 .session_set_config_params = iris_hfi_gen2_session_set_config_params,
937 .session_set_property = iris_hfi_gen2_session_set_property,
938 .session_start = iris_hfi_gen2_session_start,
939 .session_queue_buf = iris_hfi_gen2_session_queue_buffer,
940 .session_release_buf = iris_hfi_gen2_session_release_buffer,
941 .session_pause = iris_hfi_gen2_session_pause,
942 .session_resume_drc = iris_hfi_gen2_session_resume_drc,
943 .session_stop = iris_hfi_gen2_session_stop,
944 .session_drain = iris_hfi_gen2_session_drain,
945 .session_resume_drain = iris_hfi_gen2_session_resume_drain,
946 .session_close = iris_hfi_gen2_session_close,
947 };
948
iris_hfi_gen2_command_ops_init(struct iris_core * core)949 void iris_hfi_gen2_command_ops_init(struct iris_core *core)
950 {
951 core->hfi_ops = &iris_hfi_gen2_command_ops;
952 }
953
iris_hfi_gen2_get_instance(void)954 struct iris_inst *iris_hfi_gen2_get_instance(void)
955 {
956 return kzalloc(sizeof(struct iris_inst_hfi_gen2), GFP_KERNEL);
957 }
958