cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

allegro-mail.c (15165B)


      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[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->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}