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