1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2019 Pengutronix, Michael Tretter <kernel@pengutronix.de>
4 *
5 * Helper functions for handling messages that are send via mailbox to the
6 * Allegro VCU firmware.
7 */
8
9 #include <linux/bitfield.h>
10 #include <linux/export.h>
11 #include <linux/errno.h>
12 #include <linux/string.h>
13 #include <linux/videodev2.h>
14
15 #include "allegro-mail.h"
16
msg_type_name(enum mcu_msg_type type)17 const char *msg_type_name(enum mcu_msg_type type)
18 {
19 static char buf[9];
20
21 switch (type) {
22 case MCU_MSG_TYPE_INIT:
23 return "INIT";
24 case MCU_MSG_TYPE_CREATE_CHANNEL:
25 return "CREATE_CHANNEL";
26 case MCU_MSG_TYPE_DESTROY_CHANNEL:
27 return "DESTROY_CHANNEL";
28 case MCU_MSG_TYPE_ENCODE_FRAME:
29 return "ENCODE_FRAME";
30 case MCU_MSG_TYPE_PUT_STREAM_BUFFER:
31 return "PUT_STREAM_BUFFER";
32 case MCU_MSG_TYPE_PUSH_BUFFER_INTERMEDIATE:
33 return "PUSH_BUFFER_INTERMEDIATE";
34 case MCU_MSG_TYPE_PUSH_BUFFER_REFERENCE:
35 return "PUSH_BUFFER_REFERENCE";
36 default:
37 snprintf(buf, sizeof(buf), "(0x%04x)", type);
38 return buf;
39 }
40 }
41 EXPORT_SYMBOL(msg_type_name);
42
43 static ssize_t
allegro_enc_init(u32 * dst,struct mcu_msg_init_request * msg)44 allegro_enc_init(u32 *dst, struct mcu_msg_init_request *msg)
45 {
46 unsigned int i = 0;
47 enum mcu_msg_version version = msg->header.version;
48
49 dst[i++] = msg->reserved0;
50 dst[i++] = msg->suballoc_dma;
51 dst[i++] = msg->suballoc_size;
52 dst[i++] = msg->l2_cache[0];
53 dst[i++] = msg->l2_cache[1];
54 dst[i++] = msg->l2_cache[2];
55 if (version >= MCU_MSG_VERSION_2019_2) {
56 dst[i++] = -1;
57 dst[i++] = 0;
58 }
59
60 return i * sizeof(*dst);
61 }
62
settings_get_mcu_codec(struct create_channel_param * param)63 static inline u32 settings_get_mcu_codec(struct create_channel_param *param)
64 {
65 enum mcu_msg_version version = param->version;
66 u32 pixelformat = param->codec;
67
68 if (version < MCU_MSG_VERSION_2019_2) {
69 switch (pixelformat) {
70 case V4L2_PIX_FMT_H264:
71 default:
72 return 1;
73 }
74 } else {
75 switch (pixelformat) {
76 case V4L2_PIX_FMT_H264:
77 default:
78 return 0;
79 }
80 }
81 }
82
83 ssize_t
allegro_encode_config_blob(u32 * dst,struct create_channel_param * param)84 allegro_encode_config_blob(u32 *dst, struct create_channel_param *param)
85 {
86 enum mcu_msg_version version = param->version;
87 unsigned int i = 0;
88 unsigned int j = 0;
89 u32 val;
90 unsigned int codec = settings_get_mcu_codec(param);
91
92 if (version >= MCU_MSG_VERSION_2019_2)
93 dst[i++] = param->layer_id;
94 dst[i++] = FIELD_PREP(GENMASK(31, 16), param->height) |
95 FIELD_PREP(GENMASK(15, 0), param->width);
96 if (version >= MCU_MSG_VERSION_2019_2)
97 dst[i++] = param->videomode;
98 dst[i++] = param->format;
99 if (version < MCU_MSG_VERSION_2019_2)
100 dst[i++] = param->colorspace;
101 dst[i++] = param->src_mode;
102 if (version >= MCU_MSG_VERSION_2019_2)
103 dst[i++] = param->src_bit_depth;
104 dst[i++] = FIELD_PREP(GENMASK(31, 24), codec) |
105 FIELD_PREP(GENMASK(23, 8), param->constraint_set_flags) |
106 FIELD_PREP(GENMASK(7, 0), param->profile);
107 dst[i++] = FIELD_PREP(GENMASK(31, 16), param->tier) |
108 FIELD_PREP(GENMASK(15, 0), param->level);
109
110 val = 0;
111 val |= param->temporal_mvp_enable ? BIT(20) : 0;
112 val |= FIELD_PREP(GENMASK(7, 4), param->log2_max_frame_num) |
113 FIELD_PREP(GENMASK(3, 0), param->log2_max_poc);
114 dst[i++] = val;
115
116 val = 0;
117 val |= param->dbf_ovr_en ? BIT(2) : 0;
118 dst[i++] = val;
119
120 if (version >= MCU_MSG_VERSION_2019_2) {
121 val = 0;
122 val |= param->custom_lda ? BIT(2) : 0;
123 val |= param->rdo_cost_mode ? BIT(20) : 0;
124 dst[i++] = val;
125
126 val = 0;
127 val |= param->lf ? BIT(2) : 0;
128 val |= param->lf_x_tile ? BIT(3) : 0;
129 val |= param->lf_x_slice ? BIT(4) : 0;
130 dst[i++] = val;
131 } else {
132 val = 0;
133 dst[i++] = val;
134 }
135
136 dst[i++] = FIELD_PREP(GENMASK(15, 8), param->beta_offset) |
137 FIELD_PREP(GENMASK(7, 0), param->tc_offset);
138 dst[i++] = param->unknown11;
139 dst[i++] = param->unknown12;
140 if (version >= MCU_MSG_VERSION_2019_2)
141 dst[i++] = param->num_slices;
142 else
143 dst[i++] = FIELD_PREP(GENMASK(31, 16), param->prefetch_auto) |
144 FIELD_PREP(GENMASK(15, 0), param->num_slices);
145 dst[i++] = param->prefetch_mem_offset;
146 dst[i++] = param->prefetch_mem_size;
147 dst[i++] = FIELD_PREP(GENMASK(31, 16), param->clip_vrt_range) |
148 FIELD_PREP(GENMASK(15, 0), param->clip_hrz_range);
149 dst[i++] = FIELD_PREP(GENMASK(31, 16), param->me_range[1]) |
150 FIELD_PREP(GENMASK(15, 0), param->me_range[0]);
151 dst[i++] = FIELD_PREP(GENMASK(31, 16), param->me_range[3]) |
152 FIELD_PREP(GENMASK(15, 0), param->me_range[2]);
153 dst[i++] = FIELD_PREP(GENMASK(31, 24), param->min_tu_size) |
154 FIELD_PREP(GENMASK(23, 16), param->max_tu_size) |
155 FIELD_PREP(GENMASK(15, 8), param->min_cu_size) |
156 FIELD_PREP(GENMASK(8, 0), param->max_cu_size);
157 dst[i++] = FIELD_PREP(GENMASK(15, 8), param->max_transfo_depth_intra) |
158 FIELD_PREP(GENMASK(7, 0), param->max_transfo_depth_inter);
159 dst[i++] = param->entropy_mode;
160 dst[i++] = param->wp_mode;
161
162 dst[i++] = param->rate_control_mode;
163 dst[i++] = param->initial_rem_delay;
164 dst[i++] = param->cpb_size;
165 dst[i++] = FIELD_PREP(GENMASK(31, 16), param->clk_ratio) |
166 FIELD_PREP(GENMASK(15, 0), param->framerate);
167 dst[i++] = param->target_bitrate;
168 dst[i++] = param->max_bitrate;
169 dst[i++] = FIELD_PREP(GENMASK(31, 16), param->min_qp) |
170 FIELD_PREP(GENMASK(15, 0), param->initial_qp);
171 dst[i++] = FIELD_PREP(GENMASK(31, 16), param->ip_delta) |
172 FIELD_PREP(GENMASK(15, 0), param->max_qp);
173 dst[i++] = FIELD_PREP(GENMASK(31, 16), param->golden_ref) |
174 FIELD_PREP(GENMASK(15, 0), param->pb_delta);
175 dst[i++] = FIELD_PREP(GENMASK(31, 16), param->golden_ref_frequency) |
176 FIELD_PREP(GENMASK(15, 0), param->golden_delta);
177 if (version >= MCU_MSG_VERSION_2019_2)
178 dst[i++] = param->rate_control_option;
179 else
180 dst[i++] = 0;
181
182 if (version >= MCU_MSG_VERSION_2019_2) {
183 dst[i++] = param->num_pixel;
184 dst[i++] = FIELD_PREP(GENMASK(31, 16), param->max_pixel_value) |
185 FIELD_PREP(GENMASK(15, 0), param->max_psnr);
186 for (j = 0; j < 3; j++)
187 dst[i++] = param->maxpicturesize[j];
188 }
189
190 if (version >= MCU_MSG_VERSION_2019_2)
191 dst[i++] = param->gop_ctrl_mode;
192 else
193 dst[i++] = 0;
194
195 if (version >= MCU_MSG_VERSION_2019_2)
196 dst[i++] = FIELD_PREP(GENMASK(31, 24), param->freq_golden_ref) |
197 FIELD_PREP(GENMASK(23, 16), param->num_b) |
198 FIELD_PREP(GENMASK(15, 0), param->gop_length);
199 dst[i++] = param->freq_idr;
200 if (version >= MCU_MSG_VERSION_2019_2)
201 dst[i++] = param->enable_lt;
202 dst[i++] = param->freq_lt;
203 dst[i++] = param->gdr_mode;
204 if (version < MCU_MSG_VERSION_2019_2)
205 dst[i++] = FIELD_PREP(GENMASK(31, 24), param->freq_golden_ref) |
206 FIELD_PREP(GENMASK(23, 16), param->num_b) |
207 FIELD_PREP(GENMASK(15, 0), param->gop_length);
208
209 if (version >= MCU_MSG_VERSION_2019_2)
210 dst[i++] = param->tmpdqp;
211
212 dst[i++] = param->subframe_latency;
213 dst[i++] = param->lda_control_mode;
214 if (version < MCU_MSG_VERSION_2019_2)
215 dst[i++] = param->unknown41;
216
217 if (version >= MCU_MSG_VERSION_2019_2) {
218 for (j = 0; j < 6; j++)
219 dst[i++] = param->lda_factors[j];
220 dst[i++] = param->max_num_merge_cand;
221 }
222
223 return i * sizeof(*dst);
224 }
225
226 static ssize_t
allegro_enc_create_channel(u32 * dst,struct mcu_msg_create_channel * msg)227 allegro_enc_create_channel(u32 *dst, struct mcu_msg_create_channel *msg)
228 {
229 enum mcu_msg_version version = msg->header.version;
230 unsigned int i = 0;
231
232 dst[i++] = msg->user_id;
233
234 if (version >= MCU_MSG_VERSION_2019_2) {
235 dst[i++] = msg->blob_mcu_addr;
236 } else {
237 memcpy(&dst[i], msg->blob, msg->blob_size);
238 i += msg->blob_size / sizeof(*dst);
239 }
240
241 if (version >= MCU_MSG_VERSION_2019_2)
242 dst[i++] = msg->ep1_addr;
243
244 return i * sizeof(*dst);
245 }
246
allegro_decode_config_blob(struct create_channel_param * param,struct mcu_msg_create_channel_response * msg,u32 * src)247 ssize_t allegro_decode_config_blob(struct create_channel_param *param,
248 struct mcu_msg_create_channel_response *msg,
249 u32 *src)
250 {
251 enum mcu_msg_version version = msg->header.version;
252
253 if (version >= MCU_MSG_VERSION_2019_2) {
254 param->num_ref_idx_l0 = FIELD_GET(GENMASK(7, 4), src[9]);
255 param->num_ref_idx_l1 = FIELD_GET(GENMASK(11, 8), src[9]);
256 } else {
257 param->num_ref_idx_l0 = msg->num_ref_idx_l0;
258 param->num_ref_idx_l1 = msg->num_ref_idx_l1;
259 }
260
261 return 0;
262 }
263
264 static ssize_t
allegro_enc_destroy_channel(u32 * dst,struct mcu_msg_destroy_channel * msg)265 allegro_enc_destroy_channel(u32 *dst, struct mcu_msg_destroy_channel *msg)
266 {
267 unsigned int i = 0;
268
269 dst[i++] = msg->channel_id;
270
271 return i * sizeof(*dst);
272 }
273
274 static ssize_t
allegro_enc_push_buffers(u32 * dst,struct mcu_msg_push_buffers_internal * msg)275 allegro_enc_push_buffers(u32 *dst, struct mcu_msg_push_buffers_internal *msg)
276 {
277 unsigned int i = 0;
278 struct mcu_msg_push_buffers_internal_buffer *buffer;
279 unsigned int num_buffers = msg->num_buffers;
280 unsigned int j;
281
282 dst[i++] = msg->channel_id;
283
284 for (j = 0; j < num_buffers; j++) {
285 buffer = &msg->buffer[j];
286 dst[i++] = buffer->dma_addr;
287 dst[i++] = buffer->mcu_addr;
288 dst[i++] = buffer->size;
289 }
290
291 return i * sizeof(*dst);
292 }
293
294 static ssize_t
allegro_enc_put_stream_buffer(u32 * dst,struct mcu_msg_put_stream_buffer * msg)295 allegro_enc_put_stream_buffer(u32 *dst,
296 struct mcu_msg_put_stream_buffer *msg)
297 {
298 unsigned int i = 0;
299
300 dst[i++] = msg->channel_id;
301 dst[i++] = msg->dma_addr;
302 dst[i++] = msg->mcu_addr;
303 dst[i++] = msg->size;
304 dst[i++] = msg->offset;
305 dst[i++] = lower_32_bits(msg->stream_id);
306 dst[i++] = upper_32_bits(msg->stream_id);
307
308 return i * sizeof(*dst);
309 }
310
311 static ssize_t
allegro_enc_encode_frame(u32 * dst,struct mcu_msg_encode_frame * msg)312 allegro_enc_encode_frame(u32 *dst, struct mcu_msg_encode_frame *msg)
313 {
314 enum mcu_msg_version version = msg->header.version;
315 unsigned int i = 0;
316
317 dst[i++] = msg->channel_id;
318
319 dst[i++] = msg->reserved;
320 dst[i++] = msg->encoding_options;
321 dst[i++] = FIELD_PREP(GENMASK(31, 16), msg->padding) |
322 FIELD_PREP(GENMASK(15, 0), msg->pps_qp);
323
324 if (version >= MCU_MSG_VERSION_2019_2) {
325 dst[i++] = 0;
326 dst[i++] = 0;
327 dst[i++] = 0;
328 dst[i++] = 0;
329 }
330
331 dst[i++] = lower_32_bits(msg->user_param);
332 dst[i++] = upper_32_bits(msg->user_param);
333 dst[i++] = lower_32_bits(msg->src_handle);
334 dst[i++] = upper_32_bits(msg->src_handle);
335 dst[i++] = msg->request_options;
336 dst[i++] = msg->src_y;
337 dst[i++] = msg->src_uv;
338 if (version >= MCU_MSG_VERSION_2019_2)
339 dst[i++] = msg->is_10_bit;
340 dst[i++] = msg->stride;
341 if (version >= MCU_MSG_VERSION_2019_2)
342 dst[i++] = msg->format;
343 dst[i++] = msg->ep2;
344 dst[i++] = lower_32_bits(msg->ep2_v);
345 dst[i++] = upper_32_bits(msg->ep2_v);
346
347 return i * sizeof(*dst);
348 }
349
350 static ssize_t
allegro_dec_init(struct mcu_msg_init_response * msg,u32 * src)351 allegro_dec_init(struct mcu_msg_init_response *msg, u32 *src)
352 {
353 unsigned int i = 0;
354
355 msg->reserved0 = src[i++];
356
357 return i * sizeof(*src);
358 }
359
360 static ssize_t
allegro_dec_create_channel(struct mcu_msg_create_channel_response * msg,u32 * src)361 allegro_dec_create_channel(struct mcu_msg_create_channel_response *msg,
362 u32 *src)
363 {
364 enum mcu_msg_version version = msg->header.version;
365 unsigned int i = 0;
366
367 msg->channel_id = src[i++];
368 msg->user_id = src[i++];
369 /*
370 * Version >= MCU_MSG_VERSION_2019_2 is handled in
371 * allegro_decode_config_blob().
372 */
373 if (version < MCU_MSG_VERSION_2019_2) {
374 msg->options = src[i++];
375 msg->num_core = src[i++];
376 msg->num_ref_idx_l0 = FIELD_GET(GENMASK(7, 4), src[i]);
377 msg->num_ref_idx_l1 = FIELD_GET(GENMASK(11, 8), src[i++]);
378 }
379 msg->int_buffers_count = src[i++];
380 msg->int_buffers_size = src[i++];
381 msg->rec_buffers_count = src[i++];
382 msg->rec_buffers_size = src[i++];
383 msg->reserved = src[i++];
384 msg->error_code = src[i++];
385
386 return i * sizeof(*src);
387 }
388
389 static ssize_t
allegro_dec_destroy_channel(struct mcu_msg_destroy_channel_response * msg,u32 * src)390 allegro_dec_destroy_channel(struct mcu_msg_destroy_channel_response *msg,
391 u32 *src)
392 {
393 unsigned int i = 0;
394
395 msg->channel_id = src[i++];
396
397 return i * sizeof(*src);
398 }
399
400 static ssize_t
allegro_dec_encode_frame(struct mcu_msg_encode_frame_response * msg,u32 * src)401 allegro_dec_encode_frame(struct mcu_msg_encode_frame_response *msg, u32 *src)
402 {
403 enum mcu_msg_version version = msg->header.version;
404 unsigned int i = 0;
405 unsigned int j;
406
407 msg->channel_id = src[i++];
408
409 msg->stream_id = src[i++];
410 msg->stream_id |= (((u64)src[i++]) << 32);
411 msg->user_param = src[i++];
412 msg->user_param |= (((u64)src[i++]) << 32);
413 msg->src_handle = src[i++];
414 msg->src_handle |= (((u64)src[i++]) << 32);
415 msg->skip = FIELD_GET(GENMASK(31, 16), src[i]);
416 msg->is_ref = FIELD_GET(GENMASK(15, 0), src[i++]);
417 msg->initial_removal_delay = src[i++];
418 msg->dpb_output_delay = src[i++];
419 msg->size = src[i++];
420 msg->frame_tag_size = src[i++];
421 msg->stuffing = src[i++];
422 msg->filler = src[i++];
423 msg->num_column = FIELD_GET(GENMASK(31, 16), src[i]);
424 msg->num_row = FIELD_GET(GENMASK(15, 0), src[i++]);
425 msg->num_ref_idx_l1 = FIELD_GET(GENMASK(31, 24), src[i]);
426 msg->num_ref_idx_l0 = FIELD_GET(GENMASK(23, 16), src[i]);
427 msg->qp = FIELD_GET(GENMASK(15, 0), src[i++]);
428 msg->partition_table_offset = src[i++];
429 msg->partition_table_size = src[i++];
430 msg->sum_complex = src[i++];
431 for (j = 0; j < 4; j++)
432 msg->tile_width[j] = src[i++];
433 for (j = 0; j < 22; j++)
434 msg->tile_height[j] = src[i++];
435 msg->error_code = src[i++];
436 msg->slice_type = src[i++];
437 msg->pic_struct = src[i++];
438 msg->reserved = FIELD_GET(GENMASK(31, 24), src[i]);
439 msg->is_last_slice = FIELD_GET(GENMASK(23, 16), src[i]);
440 msg->is_first_slice = FIELD_GET(GENMASK(15, 8), src[i]);
441 msg->is_idr = FIELD_GET(GENMASK(7, 0), src[i++]);
442
443 msg->reserved1 = FIELD_GET(GENMASK(31, 16), src[i]);
444 msg->pps_qp = FIELD_GET(GENMASK(15, 0), src[i++]);
445
446 msg->reserved2 = src[i++];
447 if (version >= MCU_MSG_VERSION_2019_2) {
448 msg->reserved3 = src[i++];
449 msg->reserved4 = src[i++];
450 msg->reserved5 = src[i++];
451 msg->reserved6 = src[i++];
452 }
453
454 return i * sizeof(*src);
455 }
456
457 /**
458 * allegro_encode_mail() - Encode allegro messages to firmware format
459 * @dst: Pointer to the memory that will be filled with data
460 * @msg: The allegro message that will be encoded
461 */
allegro_encode_mail(u32 * dst,void * msg)462 ssize_t allegro_encode_mail(u32 *dst, void *msg)
463 {
464 const struct mcu_msg_header *header = msg;
465 ssize_t size;
466
467 if (!msg || !dst)
468 return -EINVAL;
469
470 switch (header->type) {
471 case MCU_MSG_TYPE_INIT:
472 size = allegro_enc_init(&dst[1], msg);
473 break;
474 case MCU_MSG_TYPE_CREATE_CHANNEL:
475 size = allegro_enc_create_channel(&dst[1], msg);
476 break;
477 case MCU_MSG_TYPE_DESTROY_CHANNEL:
478 size = allegro_enc_destroy_channel(&dst[1], msg);
479 break;
480 case MCU_MSG_TYPE_ENCODE_FRAME:
481 size = allegro_enc_encode_frame(&dst[1], msg);
482 break;
483 case MCU_MSG_TYPE_PUT_STREAM_BUFFER:
484 size = allegro_enc_put_stream_buffer(&dst[1], msg);
485 break;
486 case MCU_MSG_TYPE_PUSH_BUFFER_INTERMEDIATE:
487 case MCU_MSG_TYPE_PUSH_BUFFER_REFERENCE:
488 size = allegro_enc_push_buffers(&dst[1], msg);
489 break;
490 default:
491 return -EINVAL;
492 }
493
494 /*
495 * The encoded messages might have different length depending on
496 * the firmware version or certain fields. Therefore, we have to
497 * set the body length after encoding the message.
498 */
499 dst[0] = FIELD_PREP(GENMASK(31, 16), header->type) |
500 FIELD_PREP(GENMASK(15, 0), size);
501
502 return size + sizeof(*dst);
503 }
504
505 /**
506 * allegro_decode_mail() - Parse allegro messages from the firmware.
507 * @msg: The mcu_msg_response that will be filled with parsed values.
508 * @src: Pointer to the memory that will be parsed
509 *
510 * The message format in the mailbox depends on the firmware. Parse the
511 * different formats into a uniform message format that can be used without
512 * taking care of the firmware version.
513 */
allegro_decode_mail(void * msg,u32 * src)514 int allegro_decode_mail(void *msg, u32 *src)
515 {
516 struct mcu_msg_header *header;
517
518 if (!src || !msg)
519 return -EINVAL;
520
521 header = msg;
522 header->type = FIELD_GET(GENMASK(31, 16), src[0]);
523
524 src++;
525 switch (header->type) {
526 case MCU_MSG_TYPE_INIT:
527 allegro_dec_init(msg, src);
528 break;
529 case MCU_MSG_TYPE_CREATE_CHANNEL:
530 allegro_dec_create_channel(msg, src);
531 break;
532 case MCU_MSG_TYPE_DESTROY_CHANNEL:
533 allegro_dec_destroy_channel(msg, src);
534 break;
535 case MCU_MSG_TYPE_ENCODE_FRAME:
536 allegro_dec_encode_frame(msg, src);
537 break;
538 default:
539 return -EINVAL;
540 }
541
542 return 0;
543 }
544