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
17const char *msg_type_name(enum mcu_msg_type type)
18{
19	static char buf[13];
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->encoder_buffer_size;
53	dst[i++] = msg->encoder_buffer_color_depth;
54	dst[i++] = msg->num_cores;
55	if (version >= MCU_MSG_VERSION_2019_2) {
56		dst[i++] = msg->clk_rate;
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	dst[i++] = param->num_slices;
150	dst[i++] = param->encoder_buffer_offset;
151	dst[i++] = param->encoder_buffer_enabled;
152
153	dst[i++] = FIELD_PREP(GENMASK(31, 16), param->clip_vrt_range) |
154		   FIELD_PREP(GENMASK(15, 0), param->clip_hrz_range);
155	dst[i++] = FIELD_PREP(GENMASK(31, 16), param->me_range[1]) |
156		   FIELD_PREP(GENMASK(15, 0), param->me_range[0]);
157	dst[i++] = FIELD_PREP(GENMASK(31, 16), param->me_range[3]) |
158		   FIELD_PREP(GENMASK(15, 0), param->me_range[2]);
159	dst[i++] = FIELD_PREP(GENMASK(31, 24), param->min_tu_size) |
160		   FIELD_PREP(GENMASK(23, 16), param->max_tu_size) |
161		   FIELD_PREP(GENMASK(15, 8), param->min_cu_size) |
162		   FIELD_PREP(GENMASK(8, 0), param->max_cu_size);
163	dst[i++] = FIELD_PREP(GENMASK(15, 8), param->max_transfo_depth_intra) |
164		   FIELD_PREP(GENMASK(7, 0), param->max_transfo_depth_inter);
165	dst[i++] = param->entropy_mode;
166	dst[i++] = param->wp_mode;
167
168	dst[i++] = param->rate_control_mode;
169	dst[i++] = param->initial_rem_delay;
170	dst[i++] = param->cpb_size;
171	dst[i++] = FIELD_PREP(GENMASK(31, 16), param->clk_ratio) |
172		   FIELD_PREP(GENMASK(15, 0), param->framerate);
173	dst[i++] = param->target_bitrate;
174	dst[i++] = param->max_bitrate;
175	dst[i++] = FIELD_PREP(GENMASK(31, 16), param->min_qp) |
176		   FIELD_PREP(GENMASK(15, 0), param->initial_qp);
177	dst[i++] = FIELD_PREP(GENMASK(31, 16), param->ip_delta) |
178		   FIELD_PREP(GENMASK(15, 0), param->max_qp);
179	dst[i++] = FIELD_PREP(GENMASK(31, 16), param->golden_ref) |
180		   FIELD_PREP(GENMASK(15, 0), param->pb_delta);
181	dst[i++] = FIELD_PREP(GENMASK(31, 16), param->golden_ref_frequency) |
182		   FIELD_PREP(GENMASK(15, 0), param->golden_delta);
183	if (version >= MCU_MSG_VERSION_2019_2)
184		dst[i++] = param->rate_control_option;
185	else
186		dst[i++] = 0;
187
188	if (version >= MCU_MSG_VERSION_2019_2) {
189		dst[i++] = param->num_pixel;
190		dst[i++] = FIELD_PREP(GENMASK(31, 16), param->max_pixel_value) |
191			FIELD_PREP(GENMASK(15, 0), param->max_psnr);
192		for (j = 0; j < 3; j++)
193			dst[i++] = param->maxpicturesize[j];
194	}
195
196	if (version >= MCU_MSG_VERSION_2019_2)
197		dst[i++] = param->gop_ctrl_mode;
198	else
199		dst[i++] = 0;
200
201	if (version >= MCU_MSG_VERSION_2019_2)
202		dst[i++] = FIELD_PREP(GENMASK(31, 24), param->freq_golden_ref) |
203			   FIELD_PREP(GENMASK(23, 16), param->num_b) |
204			   FIELD_PREP(GENMASK(15, 0), param->gop_length);
205	dst[i++] = param->freq_idr;
206	if (version >= MCU_MSG_VERSION_2019_2)
207		dst[i++] = param->enable_lt;
208	dst[i++] = param->freq_lt;
209	dst[i++] = param->gdr_mode;
210	if (version < MCU_MSG_VERSION_2019_2)
211		dst[i++] = FIELD_PREP(GENMASK(31, 24), param->freq_golden_ref) |
212			   FIELD_PREP(GENMASK(23, 16), param->num_b) |
213			   FIELD_PREP(GENMASK(15, 0), param->gop_length);
214
215	if (version >= MCU_MSG_VERSION_2019_2)
216		dst[i++] = param->tmpdqp;
217
218	dst[i++] = param->subframe_latency;
219	dst[i++] = param->lda_control_mode;
220	if (version < MCU_MSG_VERSION_2019_2)
221		dst[i++] = param->unknown41;
222
223	if (version >= MCU_MSG_VERSION_2019_2) {
224		for (j = 0; j < 6; j++)
225			dst[i++] = param->lda_factors[j];
226		dst[i++] = param->max_num_merge_cand;
227	}
228
229	return i * sizeof(*dst);
230}
231
232static ssize_t
233allegro_enc_create_channel(u32 *dst, struct mcu_msg_create_channel *msg)
234{
235	enum mcu_msg_version version = msg->header.version;
236	unsigned int i = 0;
237
238	dst[i++] = msg->user_id;
239
240	if (version >= MCU_MSG_VERSION_2019_2) {
241		dst[i++] = msg->blob_mcu_addr;
242	} else {
243		memcpy(&dst[i], msg->blob, msg->blob_size);
244		i += msg->blob_size / sizeof(*dst);
245	}
246
247	if (version >= MCU_MSG_VERSION_2019_2)
248		dst[i++] = msg->ep1_addr;
249
250	return i * sizeof(*dst);
251}
252
253ssize_t allegro_decode_config_blob(struct create_channel_param *param,
254				   struct mcu_msg_create_channel_response *msg,
255				   u32 *src)
256{
257	enum mcu_msg_version version = msg->header.version;
258
259	if (version >= MCU_MSG_VERSION_2019_2) {
260		param->num_ref_idx_l0 = FIELD_GET(GENMASK(7, 4), src[9]);
261		param->num_ref_idx_l1 = FIELD_GET(GENMASK(11, 8), src[9]);
262	} else {
263		param->num_ref_idx_l0 = msg->num_ref_idx_l0;
264		param->num_ref_idx_l1 = msg->num_ref_idx_l1;
265	}
266
267	return 0;
268}
269
270static ssize_t
271allegro_enc_destroy_channel(u32 *dst, struct mcu_msg_destroy_channel *msg)
272{
273	unsigned int i = 0;
274
275	dst[i++] = msg->channel_id;
276
277	return i * sizeof(*dst);
278}
279
280static ssize_t
281allegro_enc_push_buffers(u32 *dst, struct mcu_msg_push_buffers_internal *msg)
282{
283	unsigned int i = 0;
284	struct mcu_msg_push_buffers_internal_buffer *buffer;
285	unsigned int num_buffers = msg->num_buffers;
286	unsigned int j;
287
288	dst[i++] = msg->channel_id;
289
290	for (j = 0; j < num_buffers; j++) {
291		buffer = &msg->buffer[j];
292		dst[i++] = buffer->dma_addr;
293		dst[i++] = buffer->mcu_addr;
294		dst[i++] = buffer->size;
295	}
296
297	return i * sizeof(*dst);
298}
299
300static ssize_t
301allegro_enc_put_stream_buffer(u32 *dst,
302			      struct mcu_msg_put_stream_buffer *msg)
303{
304	unsigned int i = 0;
305
306	dst[i++] = msg->channel_id;
307	dst[i++] = msg->dma_addr;
308	dst[i++] = msg->mcu_addr;
309	dst[i++] = msg->size;
310	dst[i++] = msg->offset;
311	dst[i++] = lower_32_bits(msg->dst_handle);
312	dst[i++] = upper_32_bits(msg->dst_handle);
313
314	return i * sizeof(*dst);
315}
316
317static ssize_t
318allegro_enc_encode_frame(u32 *dst, struct mcu_msg_encode_frame *msg)
319{
320	enum mcu_msg_version version = msg->header.version;
321	unsigned int i = 0;
322
323	dst[i++] = msg->channel_id;
324
325	dst[i++] = msg->reserved;
326	dst[i++] = msg->encoding_options;
327	dst[i++] = FIELD_PREP(GENMASK(31, 16), msg->padding) |
328		   FIELD_PREP(GENMASK(15, 0), msg->pps_qp);
329
330	if (version >= MCU_MSG_VERSION_2019_2) {
331		dst[i++] = 0;
332		dst[i++] = 0;
333		dst[i++] = 0;
334		dst[i++] = 0;
335	}
336
337	dst[i++] = lower_32_bits(msg->user_param);
338	dst[i++] = upper_32_bits(msg->user_param);
339	dst[i++] = lower_32_bits(msg->src_handle);
340	dst[i++] = upper_32_bits(msg->src_handle);
341	dst[i++] = msg->request_options;
342	dst[i++] = msg->src_y;
343	dst[i++] = msg->src_uv;
344	if (version >= MCU_MSG_VERSION_2019_2)
345		dst[i++] = msg->is_10_bit;
346	dst[i++] = msg->stride;
347	if (version >= MCU_MSG_VERSION_2019_2)
348		dst[i++] = msg->format;
349	dst[i++] = msg->ep2;
350	dst[i++] = lower_32_bits(msg->ep2_v);
351	dst[i++] = upper_32_bits(msg->ep2_v);
352
353	return i * sizeof(*dst);
354}
355
356static ssize_t
357allegro_dec_init(struct mcu_msg_init_response *msg, u32 *src)
358{
359	unsigned int i = 0;
360
361	msg->reserved0 = src[i++];
362
363	return i * sizeof(*src);
364}
365
366static ssize_t
367allegro_dec_create_channel(struct mcu_msg_create_channel_response *msg,
368			   u32 *src)
369{
370	enum mcu_msg_version version = msg->header.version;
371	unsigned int i = 0;
372
373	msg->channel_id = src[i++];
374	msg->user_id = src[i++];
375	/*
376	 * Version >= MCU_MSG_VERSION_2019_2 is handled in
377	 * allegro_decode_config_blob().
378	 */
379	if (version < MCU_MSG_VERSION_2019_2) {
380		msg->options = src[i++];
381		msg->num_core = src[i++];
382		msg->num_ref_idx_l0 = FIELD_GET(GENMASK(7, 4), src[i]);
383		msg->num_ref_idx_l1 = FIELD_GET(GENMASK(11, 8), src[i++]);
384	}
385	msg->int_buffers_count = src[i++];
386	msg->int_buffers_size = src[i++];
387	msg->rec_buffers_count = src[i++];
388	msg->rec_buffers_size = src[i++];
389	msg->reserved = src[i++];
390	msg->error_code = src[i++];
391
392	return i * sizeof(*src);
393}
394
395static ssize_t
396allegro_dec_destroy_channel(struct mcu_msg_destroy_channel_response *msg,
397			    u32 *src)
398{
399	unsigned int i = 0;
400
401	msg->channel_id = src[i++];
402
403	return i * sizeof(*src);
404}
405
406static ssize_t
407allegro_dec_encode_frame(struct mcu_msg_encode_frame_response *msg, u32 *src)
408{
409	enum mcu_msg_version version = msg->header.version;
410	unsigned int i = 0;
411	unsigned int j;
412
413	msg->channel_id = src[i++];
414
415	msg->dst_handle = src[i++];
416	msg->dst_handle |= (((u64)src[i++]) << 32);
417	msg->user_param = src[i++];
418	msg->user_param |= (((u64)src[i++]) << 32);
419	msg->src_handle = src[i++];
420	msg->src_handle |= (((u64)src[i++]) << 32);
421	msg->skip = FIELD_GET(GENMASK(31, 16), src[i]);
422	msg->is_ref = FIELD_GET(GENMASK(15, 0), src[i++]);
423	msg->initial_removal_delay = src[i++];
424	msg->dpb_output_delay = src[i++];
425	msg->size = src[i++];
426	msg->frame_tag_size = src[i++];
427	msg->stuffing = src[i++];
428	msg->filler = src[i++];
429	msg->num_row = FIELD_GET(GENMASK(31, 16), src[i]);
430	msg->num_column = FIELD_GET(GENMASK(15, 0), src[i++]);
431	msg->num_ref_idx_l1 = FIELD_GET(GENMASK(31, 24), src[i]);
432	msg->num_ref_idx_l0 = FIELD_GET(GENMASK(23, 16), src[i]);
433	msg->qp = FIELD_GET(GENMASK(15, 0), src[i++]);
434	msg->partition_table_offset = src[i++];
435	msg->partition_table_size = src[i++];
436	msg->sum_complex = src[i++];
437	for (j = 0; j < 4; j++)
438		msg->tile_width[j] = src[i++];
439	for (j = 0; j < 22; j++)
440		msg->tile_height[j] = src[i++];
441	msg->error_code = src[i++];
442	msg->slice_type = src[i++];
443	msg->pic_struct = src[i++];
444	msg->reserved = FIELD_GET(GENMASK(31, 24), src[i]);
445	msg->is_last_slice = FIELD_GET(GENMASK(23, 16), src[i]);
446	msg->is_first_slice = FIELD_GET(GENMASK(15, 8), src[i]);
447	msg->is_idr = FIELD_GET(GENMASK(7, 0), src[i++]);
448
449	msg->reserved1 = FIELD_GET(GENMASK(31, 16), src[i]);
450	msg->pps_qp = FIELD_GET(GENMASK(15, 0), src[i++]);
451
452	msg->reserved2 = src[i++];
453	if (version >= MCU_MSG_VERSION_2019_2) {
454		msg->reserved3 = src[i++];
455		msg->reserved4 = src[i++];
456		msg->reserved5 = src[i++];
457		msg->reserved6 = src[i++];
458	}
459
460	return i * sizeof(*src);
461}
462
463/**
464 * allegro_encode_mail() - Encode allegro messages to firmware format
465 * @dst: Pointer to the memory that will be filled with data
466 * @msg: The allegro message that will be encoded
467 */
468ssize_t allegro_encode_mail(u32 *dst, void *msg)
469{
470	const struct mcu_msg_header *header = msg;
471	ssize_t size;
472
473	if (!msg || !dst)
474		return -EINVAL;
475
476	switch (header->type) {
477	case MCU_MSG_TYPE_INIT:
478		size = allegro_enc_init(&dst[1], msg);
479		break;
480	case MCU_MSG_TYPE_CREATE_CHANNEL:
481		size = allegro_enc_create_channel(&dst[1], msg);
482		break;
483	case MCU_MSG_TYPE_DESTROY_CHANNEL:
484		size = allegro_enc_destroy_channel(&dst[1], msg);
485		break;
486	case MCU_MSG_TYPE_ENCODE_FRAME:
487		size = allegro_enc_encode_frame(&dst[1], msg);
488		break;
489	case MCU_MSG_TYPE_PUT_STREAM_BUFFER:
490		size = allegro_enc_put_stream_buffer(&dst[1], msg);
491		break;
492	case MCU_MSG_TYPE_PUSH_BUFFER_INTERMEDIATE:
493	case MCU_MSG_TYPE_PUSH_BUFFER_REFERENCE:
494		size = allegro_enc_push_buffers(&dst[1], msg);
495		break;
496	default:
497		return -EINVAL;
498	}
499
500	/*
501	 * The encoded messages might have different length depending on
502	 * the firmware version or certain fields. Therefore, we have to
503	 * set the body length after encoding the message.
504	 */
505	dst[0] = FIELD_PREP(GENMASK(31, 16), header->type) |
506		 FIELD_PREP(GENMASK(15, 0), size);
507
508	return size + sizeof(*dst);
509}
510
511/**
512 * allegro_decode_mail() - Parse allegro messages from the firmware.
513 * @msg: The mcu_msg_response that will be filled with parsed values.
514 * @src: Pointer to the memory that will be parsed
515 *
516 * The message format in the mailbox depends on the firmware. Parse the
517 * different formats into a uniform message format that can be used without
518 * taking care of the firmware version.
519 */
520int allegro_decode_mail(void *msg, u32 *src)
521{
522	struct mcu_msg_header *header;
523
524	if (!src || !msg)
525		return -EINVAL;
526
527	header = msg;
528	header->type = FIELD_GET(GENMASK(31, 16), src[0]);
529
530	src++;
531	switch (header->type) {
532	case MCU_MSG_TYPE_INIT:
533		allegro_dec_init(msg, src);
534		break;
535	case MCU_MSG_TYPE_CREATE_CHANNEL:
536		allegro_dec_create_channel(msg, src);
537		break;
538	case MCU_MSG_TYPE_DESTROY_CHANNEL:
539		allegro_dec_destroy_channel(msg, src);
540		break;
541	case MCU_MSG_TYPE_ENCODE_FRAME:
542		allegro_dec_encode_frame(msg, src);
543		break;
544	default:
545		return -EINVAL;
546	}
547
548	return 0;
549}
550