brintos

brintos / linux-shallow public Read only

0
0
Text · 14.8 KiB · aadc947 Raw
550 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2019 Pengutronix, Michael Tretter <kernel@pengutronix.de>4 *5 * Helper functions for handling messages that are send via mailbox to the6 * 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_t44allegro_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_t88allegro_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	else120		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	else186		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	else199		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_t233allegro_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_t271allegro_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_t281allegro_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_t301allegro_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_t318allegro_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_t357allegro_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_t367allegro_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 in377	 * 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_t396allegro_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_t407allegro_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 format465 * @dst: Pointer to the memory that will be filled with data466 * @msg: The allegro message that will be encoded467 */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 on502	 * the firmware version or certain fields. Therefore, we have to503	 * 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 parsed515 *516 * The message format in the mailbox depends on the firmware. Parse the517 * different formats into a uniform message format that can be used without518 * 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