linux/drivers/media/platform/allegro-dvt/allegro-mail.c
<<
>>
Prefs
   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->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         * Version >= MCU_MSG_VERSION_2019_2 is handled in
 380         * allegro_decode_config_blob().
 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 * allegro_encode_mail() - Encode allegro messages to firmware format
 468 * @dst: Pointer to the memory that will be filled with data
 469 * @msg: The allegro message that will be encoded
 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         * The encoded messages might have different length depending on
 505         * the firmware version or certain fields. Therefore, we have to
 506         * set the body length after encoding the message.
 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 * allegro_decode_mail() - Parse allegro messages from the firmware.
 516 * @msg: The mcu_msg_response that will be filled with parsed values.
 517 * @src: Pointer to the memory that will be parsed
 518 *
 519 * The message format in the mailbox depends on the firmware. Parse the
 520 * different formats into a uniform message format that can be used without
 521 * taking care of the firmware version.
 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