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}