From 3de16839669f60b6049734e3a9f553a2a958c4b5 Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Mon, 13 Jul 2020 16:42:20 +0200 Subject: media: allegro: add explicit mail encoding and decoding The message format in the mailboxes differ between firmware versions. Therefore, it is necessary to decouple the mailbox format of the driver from the message format of the firmware. This allows to keep a consistent message format in the driver while still supporting various firmware versions. Add an intermediate step to encode and decode message before writing the mails to the mailboxes. On the other hand, this allows to handle optional fields in the messages, which is required for advanced features of the encoder and was not possible until now. Signed-off-by: Michael Tretter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/allegro-dvt/allegro-mail.c | 364 +++++++++++++++++++++++ 1 file changed, 364 insertions(+) (limited to 'drivers/staging/media/allegro-dvt/allegro-mail.c') diff --git a/drivers/staging/media/allegro-dvt/allegro-mail.c b/drivers/staging/media/allegro-dvt/allegro-mail.c index df0d8d26a6fb..c78367d36e2e 100644 --- a/drivers/staging/media/allegro-dvt/allegro-mail.c +++ b/drivers/staging/media/allegro-dvt/allegro-mail.c @@ -6,7 +6,9 @@ * Allegro VCU firmware. */ +#include #include +#include #include "allegro-mail.h" @@ -35,3 +37,365 @@ const char *msg_type_name(enum mcu_msg_type type) } } EXPORT_SYMBOL(msg_type_name); + +static ssize_t +allegro_enc_init(u32 *dst, struct mcu_msg_init_request *msg) +{ + unsigned int i = 0; + + dst[i++] = msg->reserved0; + dst[i++] = msg->suballoc_dma; + dst[i++] = msg->suballoc_size; + dst[i++] = msg->l2_cache[0]; + dst[i++] = msg->l2_cache[1]; + dst[i++] = msg->l2_cache[2]; + + return i * sizeof(*dst); +} + +static ssize_t +allegro_encode_channel_config(u32 *dst, struct create_channel_param *param) +{ + unsigned int i = 0; + + dst[i++] = FIELD_PREP(GENMASK(31, 16), param->height) | + FIELD_PREP(GENMASK(15, 0), param->width); + dst[i++] = param->format; + dst[i++] = param->colorspace; + dst[i++] = param->src_mode; + dst[i++] = FIELD_PREP(GENMASK(31, 24), param->codec) | + FIELD_PREP(GENMASK(23, 8), param->constraint_set_flags) | + FIELD_PREP(GENMASK(7, 0), param->profile); + dst[i++] = FIELD_PREP(GENMASK(31, 16), param->tier) | + FIELD_PREP(GENMASK(15, 0), param->level); + dst[i++] = param->sps_param; + dst[i++] = param->pps_param; + dst[i++] = param->enc_option; + dst[i++] = FIELD_PREP(GENMASK(15, 8), param->beta_offset) | + FIELD_PREP(GENMASK(7, 0), param->tc_offset); + dst[i++] = param->unknown11; + dst[i++] = param->unknown12; + dst[i++] = FIELD_PREP(GENMASK(31, 16), param->prefetch_auto) | + FIELD_PREP(GENMASK(15, 0), param->num_slices); + dst[i++] = param->prefetch_mem_offset; + dst[i++] = param->prefetch_mem_size; + dst[i++] = FIELD_PREP(GENMASK(31, 16), param->clip_vrt_range) | + FIELD_PREP(GENMASK(15, 0), param->clip_hrz_range); + dst[i++] = FIELD_PREP(GENMASK(31, 16), param->me_range[1]) | + FIELD_PREP(GENMASK(15, 0), param->me_range[0]); + dst[i++] = FIELD_PREP(GENMASK(31, 16), param->me_range[3]) | + FIELD_PREP(GENMASK(15, 0), param->me_range[2]); + dst[i++] = FIELD_PREP(GENMASK(31, 24), param->min_tu_size) | + FIELD_PREP(GENMASK(23, 16), param->max_tu_size) | + FIELD_PREP(GENMASK(15, 8), param->min_cu_size) | + FIELD_PREP(GENMASK(8, 0), param->max_cu_size); + dst[i++] = FIELD_PREP(GENMASK(15, 8), param->max_transfo_depth_intra) | + FIELD_PREP(GENMASK(7, 0), param->max_transfo_depth_inter); + dst[i++] = param->entropy_mode; + dst[i++] = param->wp_mode; + + dst[i++] = param->rate_control_mode; + dst[i++] = param->initial_rem_delay; + dst[i++] = param->cpb_size; + dst[i++] = FIELD_PREP(GENMASK(31, 16), param->clk_ratio) | + FIELD_PREP(GENMASK(15, 0), param->framerate); + dst[i++] = param->target_bitrate; + dst[i++] = param->max_bitrate; + dst[i++] = FIELD_PREP(GENMASK(31, 16), param->min_qp) | + FIELD_PREP(GENMASK(15, 0), param->initial_qp); + dst[i++] = FIELD_PREP(GENMASK(31, 16), param->ip_delta) | + FIELD_PREP(GENMASK(15, 0), param->max_qp); + dst[i++] = FIELD_PREP(GENMASK(31, 16), param->golden_ref) | + FIELD_PREP(GENMASK(15, 0), param->pb_delta); + dst[i++] = FIELD_PREP(GENMASK(31, 16), param->golden_ref_frequency) | + FIELD_PREP(GENMASK(15, 0), param->golden_delta); + dst[i++] = param->rate_control_option; + + dst[i++] = param->gop_ctrl_mode; + dst[i++] = param->freq_idr; + dst[i++] = param->freq_lt; + dst[i++] = param->gdr_mode; + dst[i++] = FIELD_PREP(GENMASK(31, 24), param->freq_golden_ref) | + FIELD_PREP(GENMASK(23, 16), param->num_b) | + FIELD_PREP(GENMASK(15, 0), param->gop_length); + + dst[i++] = param->subframe_latency; + dst[i++] = param->lda_control_mode; + dst[i++] = param->unknown41; + + return i * sizeof(*dst); +} + +static ssize_t +allegro_enc_create_channel(u32 *dst, struct mcu_msg_create_channel *msg) +{ + struct create_channel_param *param = &msg->param; + ssize_t size = 0; + unsigned int i = 0; + + dst[i++] = msg->user_id; + + size = allegro_encode_channel_config(&dst[i], param); + i += size / sizeof(*dst); + + return i * sizeof(*dst); +} + +static ssize_t +allegro_enc_destroy_channel(u32 *dst, struct mcu_msg_destroy_channel *msg) +{ + unsigned int i = 0; + + dst[i++] = msg->channel_id; + + return i * sizeof(*dst); +} + +static ssize_t +allegro_enc_push_buffers(u32 *dst, struct mcu_msg_push_buffers_internal *msg) +{ + unsigned int i = 0; + struct mcu_msg_push_buffers_internal_buffer *buffer; + unsigned int num_buffers = (msg->header.length - 4) / sizeof(*buffer); + unsigned int j; + + dst[i++] = msg->channel_id; + + for (j = 0; j < num_buffers; j++) { + buffer = &msg->buffer[j]; + dst[i++] = buffer->dma_addr; + dst[i++] = buffer->mcu_addr; + dst[i++] = buffer->size; + } + + return i * sizeof(*dst); +} + +static ssize_t +allegro_enc_put_stream_buffer(u32 *dst, + struct mcu_msg_put_stream_buffer *msg) +{ + unsigned int i = 0; + + dst[i++] = msg->channel_id; + dst[i++] = msg->dma_addr; + dst[i++] = msg->mcu_addr; + dst[i++] = msg->size; + dst[i++] = msg->offset; + dst[i++] = lower_32_bits(msg->stream_id); + dst[i++] = upper_32_bits(msg->stream_id); + + return i * sizeof(*dst); +} + +static ssize_t +allegro_enc_encode_frame(u32 *dst, struct mcu_msg_encode_frame *msg) +{ + unsigned int i = 0; + + dst[i++] = msg->channel_id; + + dst[i++] = msg->reserved; + dst[i++] = msg->encoding_options; + dst[i++] = FIELD_PREP(GENMASK(31, 16), msg->padding) | + FIELD_PREP(GENMASK(15, 0), msg->pps_qp); + dst[i++] = lower_32_bits(msg->user_param); + dst[i++] = upper_32_bits(msg->user_param); + dst[i++] = lower_32_bits(msg->src_handle); + dst[i++] = upper_32_bits(msg->src_handle); + dst[i++] = msg->request_options; + dst[i++] = msg->src_y; + dst[i++] = msg->src_uv; + dst[i++] = msg->stride; + dst[i++] = msg->ep2; + dst[i++] = lower_32_bits(msg->ep2_v); + dst[i++] = upper_32_bits(msg->ep2_v); + + return i * sizeof(*dst); +} + +static ssize_t +allegro_dec_init(struct mcu_msg_init_response *msg, u32 *src) +{ + unsigned int i = 0; + + msg->header.type = FIELD_GET(GENMASK(31, 16), src[i]); + msg->header.length = FIELD_GET(GENMASK(15, 0), src[i++]); + msg->reserved0 = src[i++]; + + return i * sizeof(*src); +} + +static ssize_t +allegro_dec_create_channel(struct mcu_msg_create_channel_response *msg, + u32 *src) +{ + unsigned int i = 0; + + msg->header.type = FIELD_GET(GENMASK(31, 16), src[i]); + msg->header.length = FIELD_GET(GENMASK(15, 0), src[i++]); + msg->channel_id = src[i++]; + msg->user_id = src[i++]; + msg->options = src[i++]; + msg->num_core = src[i++]; + msg->pps_param = src[i++]; + msg->int_buffers_count = src[i++]; + msg->int_buffers_size = src[i++]; + msg->rec_buffers_count = src[i++]; + msg->rec_buffers_size = src[i++]; + msg->reserved = src[i++]; + msg->error_code = src[i++]; + + return i * sizeof(*src); +} + +static ssize_t +allegro_dec_destroy_channel(struct mcu_msg_destroy_channel_response *msg, + u32 *src) +{ + unsigned int i = 0; + + msg->header.type = FIELD_GET(GENMASK(31, 16), src[i]); + msg->header.length = FIELD_GET(GENMASK(15, 0), src[i++]); + msg->channel_id = src[i++]; + + return i * sizeof(*src); +} + +static ssize_t +allegro_dec_encode_frame(struct mcu_msg_encode_frame_response *msg, u32 *src) +{ + unsigned int i = 0; + unsigned int j; + + msg->header.type = FIELD_GET(GENMASK(31, 16), src[i]); + msg->header.length = FIELD_GET(GENMASK(15, 0), src[i++]); + msg->channel_id = src[i++]; + + msg->stream_id = src[i++]; + msg->stream_id |= (((u64)src[i++]) << 32); + msg->user_param = src[i++]; + msg->user_param |= (((u64)src[i++]) << 32); + msg->src_handle = src[i++]; + msg->src_handle |= (((u64)src[i++]) << 32); + msg->skip = FIELD_GET(GENMASK(31, 16), src[i]); + msg->is_ref = FIELD_GET(GENMASK(15, 0), src[i++]); + msg->initial_removal_delay = src[i++]; + msg->dpb_output_delay = src[i++]; + msg->size = src[i++]; + msg->frame_tag_size = src[i++]; + msg->stuffing = src[i++]; + msg->filler = src[i++]; + msg->num_column = FIELD_GET(GENMASK(31, 16), src[i]); + msg->num_row = FIELD_GET(GENMASK(15, 0), src[i++]); + msg->num_ref_idx_l1 = FIELD_GET(GENMASK(31, 24), src[i]); + msg->num_ref_idx_l0 = FIELD_GET(GENMASK(23, 16), src[i]); + msg->qp = FIELD_GET(GENMASK(15, 0), src[i++]); + msg->partition_table_offset = src[i++]; + msg->partition_table_size = src[i++]; + msg->sum_complex = src[i++]; + for (j = 0; j < 4; j++) + msg->tile_width[j] = src[i++]; + for (j = 0; j < 22; j++) + msg->tile_height[j] = src[i++]; + msg->error_code = src[i++]; + msg->slice_type = src[i++]; + msg->pic_struct = src[i++]; + msg->reserved = FIELD_GET(GENMASK(31, 24), src[i]); + msg->is_last_slice = FIELD_GET(GENMASK(23, 16), src[i]); + msg->is_first_slice = FIELD_GET(GENMASK(15, 8), src[i]); + msg->is_idr = FIELD_GET(GENMASK(7, 0), src[i++]); + + msg->reserved1 = FIELD_GET(GENMASK(31, 16), src[i]); + msg->pps_qp = FIELD_GET(GENMASK(15, 0), src[i++]); + + msg->reserved2 = src[i++]; + + return i * sizeof(*src); +} + +/** + * allegro_encode_mail() - Encode allegro messages to firmware format + * @dst: Pointer to the memory that will be filled with data + * @msg: The allegro message that will be encoded + */ +ssize_t allegro_encode_mail(u32 *dst, void *msg) +{ + const struct mcu_msg_header *header = msg; + enum mcu_msg_type type = header->type; + ssize_t size; + + if (!msg || !dst) + return -EINVAL; + + switch (type) { + case MCU_MSG_TYPE_INIT: + size = allegro_enc_init(&dst[1], msg); + break; + case MCU_MSG_TYPE_CREATE_CHANNEL: + size = allegro_enc_create_channel(&dst[1], msg); + break; + case MCU_MSG_TYPE_DESTROY_CHANNEL: + size = allegro_enc_destroy_channel(&dst[1], msg); + break; + case MCU_MSG_TYPE_ENCODE_FRAME: + size = allegro_enc_encode_frame(&dst[1], msg); + break; + case MCU_MSG_TYPE_PUT_STREAM_BUFFER: + size = allegro_enc_put_stream_buffer(&dst[1], msg); + break; + case MCU_MSG_TYPE_PUSH_BUFFER_INTERMEDIATE: + case MCU_MSG_TYPE_PUSH_BUFFER_REFERENCE: + size = allegro_enc_push_buffers(&dst[1], msg); + break; + default: + return -EINVAL; + } + + /* + * The encoded messages might have different length depending on + * the firmware version or certain fields. Therefore, we have to + * set the body length after encoding the message. + */ + dst[0] = FIELD_PREP(GENMASK(31, 16), header->type) | + FIELD_PREP(GENMASK(15, 0), size); + + return size + sizeof(*dst); +} + +/** + * allegro_decode_mail() - Parse allegro messages from the firmware. + * @msg: The mcu_msg_response that will be filled with parsed values. + * @src: Pointer to the memory that will be parsed + * + * The message format in the mailbox depends on the firmware. Parse the + * different formats into a uniform message format that can be used without + * taking care of the firmware version. + */ +int allegro_decode_mail(void *msg, u32 *src) +{ + struct mcu_msg_header *header; + + if (!src || !msg) + return -EINVAL; + + header = (struct mcu_msg_header *)src; + switch (header->type) { + case MCU_MSG_TYPE_INIT: + allegro_dec_init(msg, src); + break; + case MCU_MSG_TYPE_CREATE_CHANNEL: + allegro_dec_create_channel(msg, src); + break; + case MCU_MSG_TYPE_DESTROY_CHANNEL: + allegro_dec_destroy_channel(msg, src); + break; + case MCU_MSG_TYPE_ENCODE_FRAME: + allegro_dec_encode_frame(msg, src); + break; + default: + return -EINVAL; + } + + return 0; +} -- cgit v1.2.3 From 53c200ff49636de598b2ef5689d548c774b0373a Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Mon, 13 Jul 2020 16:42:21 +0200 Subject: media: allegro: add field for number of buffers When pushing the buffers for the intermediate and reference frames to the MCU, the driver relied on the message size to calculate the number of buffers. As it is not necessary anymore to keep the messages binary compatible to the firmware, we can just explicitly write the number of buffers into the message. Signed-off-by: Michael Tretter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/allegro-dvt/allegro-core.c | 1 + drivers/staging/media/allegro-dvt/allegro-mail.c | 2 +- drivers/staging/media/allegro-dvt/allegro-mail.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/staging/media/allegro-dvt/allegro-mail.c') diff --git a/drivers/staging/media/allegro-dvt/allegro-core.c b/drivers/staging/media/allegro-dvt/allegro-core.c index 6334b351ee3b..6745a5fa1167 100644 --- a/drivers/staging/media/allegro-dvt/allegro-core.c +++ b/drivers/staging/media/allegro-dvt/allegro-core.c @@ -1115,6 +1115,7 @@ static int allegro_mcu_push_buffer_internal(struct allegro_channel *channel, msg->header.length = size - sizeof(msg->header); msg->header.type = type; msg->channel_id = channel->mcu_channel_id; + msg->num_buffers = num_buffers; buffer = msg->buffer; list_for_each_entry(al_buffer, list, head) { diff --git a/drivers/staging/media/allegro-dvt/allegro-mail.c b/drivers/staging/media/allegro-dvt/allegro-mail.c index c78367d36e2e..ba1c3bc587c6 100644 --- a/drivers/staging/media/allegro-dvt/allegro-mail.c +++ b/drivers/staging/media/allegro-dvt/allegro-mail.c @@ -156,7 +156,7 @@ allegro_enc_push_buffers(u32 *dst, struct mcu_msg_push_buffers_internal *msg) { unsigned int i = 0; struct mcu_msg_push_buffers_internal_buffer *buffer; - unsigned int num_buffers = (msg->header.length - 4) / sizeof(*buffer); + unsigned int num_buffers = msg->num_buffers; unsigned int j; dst[i++] = msg->channel_id; diff --git a/drivers/staging/media/allegro-dvt/allegro-mail.h b/drivers/staging/media/allegro-dvt/allegro-mail.h index 457caf50ebe6..14b54eb52488 100644 --- a/drivers/staging/media/allegro-dvt/allegro-mail.h +++ b/drivers/staging/media/allegro-dvt/allegro-mail.h @@ -169,6 +169,7 @@ struct mcu_msg_push_buffers_internal_buffer { struct mcu_msg_push_buffers_internal { struct mcu_msg_header header; u32 channel_id; + size_t num_buffers; struct mcu_msg_push_buffers_internal_buffer buffer[]; } __attribute__ ((__packed__)); -- cgit v1.2.3 From 62ed97df7dc1bbb564fcd1c4f795aaa74245c63f Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Mon, 13 Jul 2020 16:42:23 +0200 Subject: media: allegro: support handling firmware dependent values Like the message format, also the identifiers in the messages differ between firmware versions. This especially affects the identifier for the codec that shall be used. As the messages used by the driver are now independent from the firmware, we can use the values defined by V4L2 as identifiers in the messages. Convert the V4L2 codec format to the respective firmware value when encoding the messages to binary format instead beforehand. Signed-off-by: Michael Tretter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/allegro-dvt/allegro-core.c | 11 +---------- drivers/staging/media/allegro-dvt/allegro-mail.c | 15 ++++++++++++++- drivers/staging/media/allegro-dvt/allegro-mail.h | 2 +- 3 files changed, 16 insertions(+), 12 deletions(-) (limited to 'drivers/staging/media/allegro-dvt/allegro-mail.c') diff --git a/drivers/staging/media/allegro-dvt/allegro-core.c b/drivers/staging/media/allegro-dvt/allegro-core.c index 6745a5fa1167..1bbb44140a6c 100644 --- a/drivers/staging/media/allegro-dvt/allegro-core.c +++ b/drivers/staging/media/allegro-dvt/allegro-core.c @@ -812,15 +812,6 @@ static u32 v4l2_colorspace_to_mcu_colorspace(enum v4l2_colorspace colorspace) } } -static s8 v4l2_pixelformat_to_mcu_codec(u32 pixelformat) -{ - switch (pixelformat) { - case V4L2_PIX_FMT_H264: - default: - return 1; - } -} - static u8 v4l2_profile_to_mcu_profile(enum v4l2_mpeg_video_h264_profile profile) { switch (profile) { @@ -919,7 +910,7 @@ static int fill_create_channel_param(struct allegro_channel *channel, param->src_mode = 0x0; param->profile = v4l2_profile_to_mcu_profile(channel->profile); param->constraint_set_flags = BIT(1); - param->codec = v4l2_pixelformat_to_mcu_codec(channel->codec); + param->codec = channel->codec; param->level = v4l2_level_to_mcu_level(channel->level); param->tier = 0; param->sps_param = BIT(20) | 0x4a; diff --git a/drivers/staging/media/allegro-dvt/allegro-mail.c b/drivers/staging/media/allegro-dvt/allegro-mail.c index ba1c3bc587c6..ce183bd2495b 100644 --- a/drivers/staging/media/allegro-dvt/allegro-mail.c +++ b/drivers/staging/media/allegro-dvt/allegro-mail.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "allegro-mail.h" @@ -53,17 +54,29 @@ allegro_enc_init(u32 *dst, struct mcu_msg_init_request *msg) return i * sizeof(*dst); } +static inline u32 settings_get_mcu_codec(struct create_channel_param *param) +{ + u32 pixelformat = param->codec; + + switch (pixelformat) { + case V4L2_PIX_FMT_H264: + default: + return 1; + } +} + static ssize_t allegro_encode_channel_config(u32 *dst, struct create_channel_param *param) { unsigned int i = 0; + unsigned int codec = settings_get_mcu_codec(param); dst[i++] = FIELD_PREP(GENMASK(31, 16), param->height) | FIELD_PREP(GENMASK(15, 0), param->width); dst[i++] = param->format; dst[i++] = param->colorspace; dst[i++] = param->src_mode; - dst[i++] = FIELD_PREP(GENMASK(31, 24), param->codec) | + dst[i++] = FIELD_PREP(GENMASK(31, 24), codec) | FIELD_PREP(GENMASK(23, 8), param->constraint_set_flags) | FIELD_PREP(GENMASK(7, 0), param->profile); dst[i++] = FIELD_PREP(GENMASK(31, 16), param->tier) | diff --git a/drivers/staging/media/allegro-dvt/allegro-mail.h b/drivers/staging/media/allegro-dvt/allegro-mail.h index ae81e94a2f2c..a92a27e270b5 100644 --- a/drivers/staging/media/allegro-dvt/allegro-mail.h +++ b/drivers/staging/media/allegro-dvt/allegro-mail.h @@ -48,7 +48,7 @@ struct create_channel_param { u32 src_mode; u8 profile; u16 constraint_set_flags; - s8 codec; + u32 codec; u16 level; u16 tier; u32 sps_param; -- cgit v1.2.3 From d30e841216411cb95ffbb56252f8431fd752c54d Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Mon, 13 Jul 2020 16:42:24 +0200 Subject: media: allegro: encode bit fields separately Even bits in bitfields do not keep their position, but move around or move to other bitfields. Therefore, the driver has to handle bitfields differently depending on the firmware version. Create separate fields for the options that have been in bitfields and handle the bitfields when encoding the message. As a side effect, this makes the messages a bit more readable. Signed-off-by: Michael Tretter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/allegro-dvt/allegro-core.c | 15 ++++++++--- drivers/staging/media/allegro-dvt/allegro-mail.c | 22 +++++++++++++--- drivers/staging/media/allegro-dvt/allegro-mail.h | 32 ++++++------------------ 3 files changed, 38 insertions(+), 31 deletions(-) (limited to 'drivers/staging/media/allegro-dvt/allegro-mail.c') diff --git a/drivers/staging/media/allegro-dvt/allegro-core.c b/drivers/staging/media/allegro-dvt/allegro-core.c index 1bbb44140a6c..e6d64151e4fe 100644 --- a/drivers/staging/media/allegro-dvt/allegro-core.c +++ b/drivers/staging/media/allegro-dvt/allegro-core.c @@ -913,10 +913,17 @@ static int fill_create_channel_param(struct allegro_channel *channel, param->codec = channel->codec; param->level = v4l2_level_to_mcu_level(channel->level); param->tier = 0; - param->sps_param = BIT(20) | 0x4a; - param->pps_param = BIT(2); - param->enc_option = AL_OPT_RDO_COST_MODE | AL_OPT_LF_X_TILE | - AL_OPT_LF_X_SLICE | AL_OPT_LF; + + param->log2_max_poc = 10; + param->log2_max_frame_num = 4; + param->temporal_mvp_enable = 1; + + param->dbf_ovr_en = 1; + param->rdo_cost_mode = 1; + param->lf = 1; + param->lf_x_tile = 1; + param->lf_x_slice = 1; + param->beta_offset = -1; param->tc_offset = -1; param->num_slices = 1; diff --git a/drivers/staging/media/allegro-dvt/allegro-mail.c b/drivers/staging/media/allegro-dvt/allegro-mail.c index ce183bd2495b..7121f128aff3 100644 --- a/drivers/staging/media/allegro-dvt/allegro-mail.c +++ b/drivers/staging/media/allegro-dvt/allegro-mail.c @@ -69,6 +69,7 @@ static ssize_t allegro_encode_channel_config(u32 *dst, struct create_channel_param *param) { unsigned int i = 0; + u32 val; unsigned int codec = settings_get_mcu_codec(param); dst[i++] = FIELD_PREP(GENMASK(31, 16), param->height) | @@ -81,9 +82,24 @@ allegro_encode_channel_config(u32 *dst, struct create_channel_param *param) FIELD_PREP(GENMASK(7, 0), param->profile); dst[i++] = FIELD_PREP(GENMASK(31, 16), param->tier) | FIELD_PREP(GENMASK(15, 0), param->level); - dst[i++] = param->sps_param; - dst[i++] = param->pps_param; - dst[i++] = param->enc_option; + + val = 0; + val |= param->temporal_mvp_enable ? BIT(20) : 0; + val |= FIELD_PREP(GENMASK(7, 4), param->log2_max_frame_num) | + FIELD_PREP(GENMASK(3, 0), param->log2_max_poc); + dst[i++] = val; + + val = 0; + val |= param->dbf_ovr_en ? BIT(2) : 0; + dst[i++] = val; + + val = 0; + val |= param->lf ? BIT(2) : 0; + val |= param->lf_x_tile ? BIT(3) : 0; + val |= param->lf_x_slice ? BIT(4) : 0; + val |= param->rdo_cost_mode ? BIT(20) : 0; + dst[i++] = val; + dst[i++] = FIELD_PREP(GENMASK(15, 8), param->beta_offset) | FIELD_PREP(GENMASK(7, 0), param->tc_offset); dst[i++] = param->unknown11; diff --git a/drivers/staging/media/allegro-dvt/allegro-mail.h b/drivers/staging/media/allegro-dvt/allegro-mail.h index a92a27e270b5..239fd8a20a69 100644 --- a/drivers/staging/media/allegro-dvt/allegro-mail.h +++ b/drivers/staging/media/allegro-dvt/allegro-mail.h @@ -51,30 +51,14 @@ struct create_channel_param { u32 codec; u16 level; u16 tier; - u32 sps_param; - u32 pps_param; - - u32 enc_option; -#define AL_OPT_WPP BIT(0) -#define AL_OPT_TILE BIT(1) -#define AL_OPT_LF BIT(2) -#define AL_OPT_LF_X_SLICE BIT(3) -#define AL_OPT_LF_X_TILE BIT(4) -#define AL_OPT_SCL_LST BIT(5) -#define AL_OPT_CONST_INTRA_PRED BIT(6) -#define AL_OPT_QP_TAB_RELATIVE BIT(7) -#define AL_OPT_FIX_PREDICTOR BIT(8) -#define AL_OPT_CUSTOM_LDA BIT(9) -#define AL_OPT_ENABLE_AUTO_QP BIT(10) -#define AL_OPT_ADAPT_AUTO_QP BIT(11) -#define AL_OPT_TRANSFO_SKIP BIT(13) -#define AL_OPT_FORCE_REC BIT(15) -#define AL_OPT_FORCE_MV_OUT BIT(16) -#define AL_OPT_FORCE_MV_CLIP BIT(17) -#define AL_OPT_LOWLAT_SYNC BIT(18) -#define AL_OPT_LOWLAT_INT BIT(19) -#define AL_OPT_RDO_COST_MODE BIT(20) - + u32 log2_max_poc; + u32 log2_max_frame_num; + u32 temporal_mvp_enable; + u32 dbf_ovr_en; + u32 rdo_cost_mode; + u32 lf; + u32 lf_x_tile; + u32 lf_x_slice; s8 beta_offset; s8 tc_offset; u16 reserved10; -- cgit v1.2.3 From c4756d8774159ef1a9a204d656589c886fcefc5b Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Mon, 13 Jul 2020 16:42:25 +0200 Subject: media: allegro: add config blob for channel Firmware versions >= 2019.2 do not configure the channel via the mailbox interface anymore, but use a separate chunk of memory that is only referenced by the message. As the configuration must be in a format that is understood by the firmware and this format can change between firmware versions, handle it similar to the message and treat is as a blob. In order to support both methods in the driver, always use a separate blob for the channel configuration and copy that blob into the mailbox if the firmware requires it and otherwise reference it. Signed-off-by: Michael Tretter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/allegro-dvt/allegro-core.c | 20 +++++++++++++++++++- drivers/staging/media/allegro-dvt/allegro-mail.c | 18 ++++++++++++------ drivers/staging/media/allegro-dvt/allegro-mail.h | 9 ++++++++- 3 files changed, 39 insertions(+), 8 deletions(-) (limited to 'drivers/staging/media/allegro-dvt/allegro-mail.c') diff --git a/drivers/staging/media/allegro-dvt/allegro-core.c b/drivers/staging/media/allegro-dvt/allegro-core.c index e6d64151e4fe..51e85cad9941 100644 --- a/drivers/staging/media/allegro-dvt/allegro-core.c +++ b/drivers/staging/media/allegro-dvt/allegro-core.c @@ -206,6 +206,8 @@ struct allegro_channel { unsigned int cpb_size; unsigned int gop_size; + struct allegro_buffer config_blob; + struct v4l2_ctrl *mpeg_video_h264_profile; struct v4l2_ctrl *mpeg_video_h264_level; struct v4l2_ctrl *mpeg_video_h264_i_frame_qp; @@ -978,6 +980,14 @@ static int allegro_mcu_send_create_channel(struct allegro_dev *dev, struct allegro_channel *channel) { struct mcu_msg_create_channel msg; + struct allegro_buffer *blob = &channel->config_blob; + struct create_channel_param param; + size_t size; + + memset(¶m, 0, sizeof(param)); + fill_create_channel_param(channel, ¶m); + allegro_alloc_buffer(dev, blob, sizeof(struct create_channel_param)); + size = allegro_encode_config_blob(blob->vaddr, ¶m); memset(&msg, 0, sizeof(msg)); @@ -986,7 +996,9 @@ static int allegro_mcu_send_create_channel(struct allegro_dev *dev, msg.user_id = channel->user_id; - fill_create_channel_param(channel, &msg.param); + msg.blob = blob->vaddr; + msg.blob_size = size; + msg.blob_mcu_addr = to_mcu_addr(dev, blob->paddr); allegro_mbox_send(dev->mbox_command, &msg); @@ -1596,6 +1608,7 @@ allegro_handle_create_channel(struct allegro_dev *dev, { struct allegro_channel *channel; int err = 0; + struct create_channel_param param; channel = allegro_find_channel_by_user_id(dev, msg->user_id); if (IS_ERR(channel)) { @@ -1621,6 +1634,11 @@ allegro_handle_create_channel(struct allegro_dev *dev, "user %d: channel has channel id %d\n", channel->user_id, channel->mcu_channel_id); + err = allegro_decode_config_blob(¶m, msg, channel->config_blob.vaddr); + allegro_free_buffer(channel->dev, &channel->config_blob); + if (err) + goto out; + v4l2_dbg(1, debug, &dev->v4l2_dev, "channel %d: intermediate buffers: %d x %d bytes\n", channel->mcu_channel_id, diff --git a/drivers/staging/media/allegro-dvt/allegro-mail.c b/drivers/staging/media/allegro-dvt/allegro-mail.c index 7121f128aff3..c55b9339f9c6 100644 --- a/drivers/staging/media/allegro-dvt/allegro-mail.c +++ b/drivers/staging/media/allegro-dvt/allegro-mail.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "allegro-mail.h" @@ -65,8 +66,8 @@ static inline u32 settings_get_mcu_codec(struct create_channel_param *param) } } -static ssize_t -allegro_encode_channel_config(u32 *dst, struct create_channel_param *param) +ssize_t +allegro_encode_config_blob(u32 *dst, struct create_channel_param *param) { unsigned int i = 0; u32 val; @@ -158,18 +159,23 @@ allegro_encode_channel_config(u32 *dst, struct create_channel_param *param) static ssize_t allegro_enc_create_channel(u32 *dst, struct mcu_msg_create_channel *msg) { - struct create_channel_param *param = &msg->param; - ssize_t size = 0; unsigned int i = 0; dst[i++] = msg->user_id; - size = allegro_encode_channel_config(&dst[i], param); - i += size / sizeof(*dst); + memcpy(&dst[i], msg->blob, msg->blob_size); + i += msg->blob_size / sizeof(*dst); return i * sizeof(*dst); } +ssize_t allegro_decode_config_blob(struct create_channel_param *param, + struct mcu_msg_create_channel_response *msg, + u32 *src) +{ + return 0; +} + static ssize_t allegro_enc_destroy_channel(u32 *dst, struct mcu_msg_destroy_channel *msg) { diff --git a/drivers/staging/media/allegro-dvt/allegro-mail.h b/drivers/staging/media/allegro-dvt/allegro-mail.h index 239fd8a20a69..07ed0a8d3de3 100644 --- a/drivers/staging/media/allegro-dvt/allegro-mail.h +++ b/drivers/staging/media/allegro-dvt/allegro-mail.h @@ -116,7 +116,9 @@ struct create_channel_param { struct mcu_msg_create_channel { struct mcu_msg_header header; u32 user_id; - struct create_channel_param param; + u32 *blob; + size_t blob_size; + u32 blob_mcu_addr; }; struct mcu_msg_create_channel_response { @@ -249,6 +251,11 @@ union mcu_msg_response { struct mcu_msg_encode_frame_response encode_frame; }; +ssize_t allegro_encode_config_blob(u32 *dst, struct create_channel_param *param); +ssize_t allegro_decode_config_blob(struct create_channel_param *param, + struct mcu_msg_create_channel_response *msg, + u32 *src); + int allegro_decode_mail(void *msg, u32 *src); ssize_t allegro_encode_mail(u32 *dst, void *msg); -- cgit v1.2.3 From c7ce107f9d899a15e4b9c24c4839abdbef88a063 Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Mon, 13 Jul 2020 16:42:26 +0200 Subject: media: allegro: set num_ref_idx using response of configured channels The firmware decides how many reference frames shall be used und returns this information via the config blob. In order to set the number of reference frames in the PPS, the driver has to read these values from the config blob after the channel has been created in the firmware. Signed-off-by: Michael Tretter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/allegro-dvt/allegro-core.c | 10 ++++++++-- drivers/staging/media/allegro-dvt/allegro-mail.c | 6 +++++- drivers/staging/media/allegro-dvt/allegro-mail.h | 5 ++++- 3 files changed, 17 insertions(+), 4 deletions(-) (limited to 'drivers/staging/media/allegro-dvt/allegro-mail.c') diff --git a/drivers/staging/media/allegro-dvt/allegro-core.c b/drivers/staging/media/allegro-dvt/allegro-core.c index 51e85cad9941..07deb5ba13dc 100644 --- a/drivers/staging/media/allegro-dvt/allegro-core.c +++ b/drivers/staging/media/allegro-dvt/allegro-core.c @@ -208,6 +208,9 @@ struct allegro_channel { struct allegro_buffer config_blob; + unsigned int num_ref_idx_l0; + unsigned int num_ref_idx_l1; + struct v4l2_ctrl *mpeg_video_h264_profile; struct v4l2_ctrl *mpeg_video_h264_level; struct v4l2_ctrl *mpeg_video_h264_i_frame_qp; @@ -1336,8 +1339,8 @@ static ssize_t allegro_h264_write_pps(struct allegro_channel *channel, pps->entropy_coding_mode_flag = 0; pps->bottom_field_pic_order_in_frame_present_flag = 0; pps->num_slice_groups_minus1 = 0; - pps->num_ref_idx_l0_default_active_minus1 = 2; - pps->num_ref_idx_l1_default_active_minus1 = 2; + pps->num_ref_idx_l0_default_active_minus1 = channel->num_ref_idx_l0 - 1; + pps->num_ref_idx_l1_default_active_minus1 = channel->num_ref_idx_l1 - 1; pps->weighted_pred_flag = 0; pps->weighted_bipred_idc = 0; pps->pic_init_qp_minus26 = 0; @@ -1639,6 +1642,9 @@ allegro_handle_create_channel(struct allegro_dev *dev, if (err) goto out; + channel->num_ref_idx_l0 = param.num_ref_idx_l0; + channel->num_ref_idx_l1 = param.num_ref_idx_l1; + v4l2_dbg(1, debug, &dev->v4l2_dev, "channel %d: intermediate buffers: %d x %d bytes\n", channel->mcu_channel_id, diff --git a/drivers/staging/media/allegro-dvt/allegro-mail.c b/drivers/staging/media/allegro-dvt/allegro-mail.c index c55b9339f9c6..bb15de080431 100644 --- a/drivers/staging/media/allegro-dvt/allegro-mail.c +++ b/drivers/staging/media/allegro-dvt/allegro-mail.c @@ -173,6 +173,9 @@ ssize_t allegro_decode_config_blob(struct create_channel_param *param, struct mcu_msg_create_channel_response *msg, u32 *src) { + param->num_ref_idx_l0 = msg->num_ref_idx_l0; + param->num_ref_idx_l1 = msg->num_ref_idx_l1; + return 0; } @@ -273,7 +276,8 @@ allegro_dec_create_channel(struct mcu_msg_create_channel_response *msg, msg->user_id = src[i++]; msg->options = src[i++]; msg->num_core = src[i++]; - msg->pps_param = src[i++]; + msg->num_ref_idx_l0 = FIELD_GET(GENMASK(7, 4), src[i]); + msg->num_ref_idx_l1 = FIELD_GET(GENMASK(11, 8), src[i++]); msg->int_buffers_count = src[i++]; msg->int_buffers_size = src[i++]; msg->rec_buffers_count = src[i++]; diff --git a/drivers/staging/media/allegro-dvt/allegro-mail.h b/drivers/staging/media/allegro-dvt/allegro-mail.h index 07ed0a8d3de3..a4d829f6f99d 100644 --- a/drivers/staging/media/allegro-dvt/allegro-mail.h +++ b/drivers/staging/media/allegro-dvt/allegro-mail.h @@ -55,6 +55,8 @@ struct create_channel_param { u32 log2_max_frame_num; u32 temporal_mvp_enable; u32 dbf_ovr_en; + u32 num_ref_idx_l0; + u32 num_ref_idx_l1; u32 rdo_cost_mode; u32 lf; u32 lf_x_tile; @@ -127,7 +129,8 @@ struct mcu_msg_create_channel_response { u32 user_id; u32 options; u32 num_core; - u32 pps_param; + u32 num_ref_idx_l0; + u32 num_ref_idx_l1; u32 int_buffers_count; u32 int_buffers_size; u32 rec_buffers_count; -- cgit v1.2.3 From d8fefda89ee292b2871ce523227e5a49d4afc6ea Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Mon, 13 Jul 2020 16:42:27 +0200 Subject: media: allegro: drop length field from message header The length of the message will be determined when the message is encoded. Writing the size of the struct into the message in the driver won't be the actual length of the message that is send to the firmware. Therefore, drop the length field from the message. Since the header is the same for all response messages, it does not make sense to read the header in each decoding function, but we can simply decode it once before dispatching to the respective functions. Signed-off-by: Michael Tretter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/allegro-dvt/allegro-core.c | 6 ------ drivers/staging/media/allegro-dvt/allegro-mail.c | 13 ++++--------- drivers/staging/media/allegro-dvt/allegro-mail.h | 3 +-- 3 files changed, 5 insertions(+), 17 deletions(-) (limited to 'drivers/staging/media/allegro-dvt/allegro-mail.c') diff --git a/drivers/staging/media/allegro-dvt/allegro-core.c b/drivers/staging/media/allegro-dvt/allegro-core.c index 07deb5ba13dc..85d2c45be9d2 100644 --- a/drivers/staging/media/allegro-dvt/allegro-core.c +++ b/drivers/staging/media/allegro-dvt/allegro-core.c @@ -776,7 +776,6 @@ static void allegro_mcu_send_init(struct allegro_dev *dev, memset(&msg, 0, sizeof(msg)); msg.header.type = MCU_MSG_TYPE_INIT; - msg.header.length = sizeof(msg) - sizeof(msg.header); msg.suballoc_dma = to_mcu_addr(dev, suballoc_dma); msg.suballoc_size = to_mcu_size(dev, suballoc_size); @@ -995,7 +994,6 @@ static int allegro_mcu_send_create_channel(struct allegro_dev *dev, memset(&msg, 0, sizeof(msg)); msg.header.type = MCU_MSG_TYPE_CREATE_CHANNEL; - msg.header.length = sizeof(msg) - sizeof(msg.header); msg.user_id = channel->user_id; @@ -1016,7 +1014,6 @@ static int allegro_mcu_send_destroy_channel(struct allegro_dev *dev, memset(&msg, 0, sizeof(msg)); msg.header.type = MCU_MSG_TYPE_DESTROY_CHANNEL; - msg.header.length = sizeof(msg) - sizeof(msg.header); msg.channel_id = channel->mcu_channel_id; @@ -1036,7 +1033,6 @@ static int allegro_mcu_send_put_stream_buffer(struct allegro_dev *dev, memset(&msg, 0, sizeof(msg)); msg.header.type = MCU_MSG_TYPE_PUT_STREAM_BUFFER; - msg.header.length = sizeof(msg) - sizeof(msg.header); msg.channel_id = channel->mcu_channel_id; msg.dma_addr = to_codec_addr(dev, paddr); @@ -1061,7 +1057,6 @@ static int allegro_mcu_send_encode_frame(struct allegro_dev *dev, memset(&msg, 0, sizeof(msg)); msg.header.type = MCU_MSG_TYPE_ENCODE_FRAME; - msg.header.length = sizeof(msg) - sizeof(msg.header); msg.channel_id = channel->mcu_channel_id; msg.encoding_options = AL_OPT_FORCE_LOAD; @@ -1125,7 +1120,6 @@ static int allegro_mcu_push_buffer_internal(struct allegro_channel *channel, if (!msg) return -ENOMEM; - msg->header.length = size - sizeof(msg->header); msg->header.type = type; msg->channel_id = channel->mcu_channel_id; msg->num_buffers = num_buffers; diff --git a/drivers/staging/media/allegro-dvt/allegro-mail.c b/drivers/staging/media/allegro-dvt/allegro-mail.c index bb15de080431..da83aa85c873 100644 --- a/drivers/staging/media/allegro-dvt/allegro-mail.c +++ b/drivers/staging/media/allegro-dvt/allegro-mail.c @@ -257,8 +257,6 @@ allegro_dec_init(struct mcu_msg_init_response *msg, u32 *src) { unsigned int i = 0; - msg->header.type = FIELD_GET(GENMASK(31, 16), src[i]); - msg->header.length = FIELD_GET(GENMASK(15, 0), src[i++]); msg->reserved0 = src[i++]; return i * sizeof(*src); @@ -270,8 +268,6 @@ allegro_dec_create_channel(struct mcu_msg_create_channel_response *msg, { unsigned int i = 0; - msg->header.type = FIELD_GET(GENMASK(31, 16), src[i]); - msg->header.length = FIELD_GET(GENMASK(15, 0), src[i++]); msg->channel_id = src[i++]; msg->user_id = src[i++]; msg->options = src[i++]; @@ -294,8 +290,6 @@ allegro_dec_destroy_channel(struct mcu_msg_destroy_channel_response *msg, { unsigned int i = 0; - msg->header.type = FIELD_GET(GENMASK(31, 16), src[i]); - msg->header.length = FIELD_GET(GENMASK(15, 0), src[i++]); msg->channel_id = src[i++]; return i * sizeof(*src); @@ -307,8 +301,6 @@ allegro_dec_encode_frame(struct mcu_msg_encode_frame_response *msg, u32 *src) unsigned int i = 0; unsigned int j; - msg->header.type = FIELD_GET(GENMASK(31, 16), src[i]); - msg->header.length = FIELD_GET(GENMASK(15, 0), src[i++]); msg->channel_id = src[i++]; msg->stream_id = src[i++]; @@ -418,7 +410,10 @@ int allegro_decode_mail(void *msg, u32 *src) if (!src || !msg) return -EINVAL; - header = (struct mcu_msg_header *)src; + header = msg; + header->type = FIELD_GET(GENMASK(31, 16), src[0]); + + src++; switch (header->type) { case MCU_MSG_TYPE_INIT: allegro_dec_init(msg, src); diff --git a/drivers/staging/media/allegro-dvt/allegro-mail.h b/drivers/staging/media/allegro-dvt/allegro-mail.h index a4d829f6f99d..397622973c19 100644 --- a/drivers/staging/media/allegro-dvt/allegro-mail.h +++ b/drivers/staging/media/allegro-dvt/allegro-mail.h @@ -23,8 +23,7 @@ enum mcu_msg_type { const char *msg_type_name(enum mcu_msg_type type); struct mcu_msg_header { - u16 length; /* length of the body in bytes */ - u16 type; + enum mcu_msg_type type; }; struct mcu_msg_init_request { -- cgit v1.2.3 From 42e50290d79475183a728d0c1d07020061f8838b Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Mon, 13 Jul 2020 16:42:29 +0200 Subject: media: allegro: add support for allegro firmware 2019.2 Encode messages as necessary for the firmware 2019.2 and, thus, support the more recent firmware version in the driver, too. Signed-off-by: Michael Tretter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/allegro-dvt/allegro-core.c | 27 +++- drivers/staging/media/allegro-dvt/allegro-mail.c | 163 +++++++++++++++++++---- drivers/staging/media/allegro-dvt/allegro-mail.h | 24 ++++ 3 files changed, 186 insertions(+), 28 deletions(-) (limited to 'drivers/staging/media/allegro-dvt/allegro-mail.c') diff --git a/drivers/staging/media/allegro-dvt/allegro-core.c b/drivers/staging/media/allegro-dvt/allegro-core.c index ada21ebf93bb..61beae1fca36 100644 --- a/drivers/staging/media/allegro-dvt/allegro-core.c +++ b/drivers/staging/media/allegro-dvt/allegro-core.c @@ -292,6 +292,15 @@ static const struct fw_info supported_firmware[] = { .mailbox_size = 0x400 - 0x8, .mailbox_version = MCU_MSG_VERSION_2018_2, .suballocator_size = SZ_16M, + }, { + .id = 14680, + .id_codec = 126572, + .version = "v2019.2", + .mailbox_cmd = 0x7000, + .mailbox_status = 0x7800, + .mailbox_size = 0x800 - 0x8, + .mailbox_version = MCU_MSG_VERSION_2019_2, + .suballocator_size = SZ_32M, }, }; @@ -930,10 +939,13 @@ static int fill_create_channel_param(struct allegro_channel *channel, param->dbf_ovr_en = 1; param->rdo_cost_mode = 1; + param->custom_lda = 1; param->lf = 1; param->lf_x_tile = 1; param->lf_x_slice = 1; + param->src_bit_depth = 8; + param->beta_offset = -1; param->tc_offset = -1; param->num_slices = 1; @@ -974,13 +986,26 @@ static int fill_create_channel_param(struct allegro_channel *channel, param->golden_ref_frequency = 10; param->rate_control_option = 0x00000000; - param->gop_ctrl_mode = 0x00000000; + param->num_pixel = channel->width + channel->height; + param->max_psnr = 4200; + param->max_pixel_value = 255; + + param->gop_ctrl_mode = 0x00000002; param->freq_idr = channel->gop_size; param->freq_lt = 0; param->gdr_mode = 0x00000000; param->gop_length = channel->gop_size; param->subframe_latency = 0x00000000; + param->lda_factors[0] = 51; + param->lda_factors[1] = 90; + param->lda_factors[2] = 151; + param->lda_factors[3] = 151; + param->lda_factors[4] = 151; + param->lda_factors[5] = 151; + + param->max_num_merge_cand = 5; + return 0; } diff --git a/drivers/staging/media/allegro-dvt/allegro-mail.c b/drivers/staging/media/allegro-dvt/allegro-mail.c index da83aa85c873..4ac65de12463 100644 --- a/drivers/staging/media/allegro-dvt/allegro-mail.c +++ b/drivers/staging/media/allegro-dvt/allegro-mail.c @@ -44,6 +44,7 @@ static ssize_t allegro_enc_init(u32 *dst, struct mcu_msg_init_request *msg) { unsigned int i = 0; + enum mcu_msg_version version = msg->header.version; dst[i++] = msg->reserved0; dst[i++] = msg->suballoc_dma; @@ -51,33 +52,55 @@ allegro_enc_init(u32 *dst, struct mcu_msg_init_request *msg) dst[i++] = msg->l2_cache[0]; dst[i++] = msg->l2_cache[1]; dst[i++] = msg->l2_cache[2]; + if (version >= MCU_MSG_VERSION_2019_2) { + dst[i++] = -1; + dst[i++] = 0; + } return i * sizeof(*dst); } static inline u32 settings_get_mcu_codec(struct create_channel_param *param) { + enum mcu_msg_version version = param->version; u32 pixelformat = param->codec; - switch (pixelformat) { - case V4L2_PIX_FMT_H264: - default: - return 1; + if (version < MCU_MSG_VERSION_2019_2) { + switch (pixelformat) { + case V4L2_PIX_FMT_H264: + default: + return 1; + } + } else { + switch (pixelformat) { + case V4L2_PIX_FMT_H264: + default: + return 0; + } } } ssize_t allegro_encode_config_blob(u32 *dst, struct create_channel_param *param) { + enum mcu_msg_version version = param->version; unsigned int i = 0; + unsigned int j = 0; u32 val; unsigned int codec = settings_get_mcu_codec(param); + if (version >= MCU_MSG_VERSION_2019_2) + dst[i++] = param->layer_id; dst[i++] = FIELD_PREP(GENMASK(31, 16), param->height) | FIELD_PREP(GENMASK(15, 0), param->width); + if (version >= MCU_MSG_VERSION_2019_2) + dst[i++] = param->videomode; dst[i++] = param->format; - dst[i++] = param->colorspace; + if (version < MCU_MSG_VERSION_2019_2) + dst[i++] = param->colorspace; dst[i++] = param->src_mode; + if (version >= MCU_MSG_VERSION_2019_2) + dst[i++] = param->src_bit_depth; dst[i++] = FIELD_PREP(GENMASK(31, 24), codec) | FIELD_PREP(GENMASK(23, 8), param->constraint_set_flags) | FIELD_PREP(GENMASK(7, 0), param->profile); @@ -94,19 +117,31 @@ allegro_encode_config_blob(u32 *dst, struct create_channel_param *param) val |= param->dbf_ovr_en ? BIT(2) : 0; dst[i++] = val; - val = 0; - val |= param->lf ? BIT(2) : 0; - val |= param->lf_x_tile ? BIT(3) : 0; - val |= param->lf_x_slice ? BIT(4) : 0; - val |= param->rdo_cost_mode ? BIT(20) : 0; - dst[i++] = val; + if (version >= MCU_MSG_VERSION_2019_2) { + val = 0; + val |= param->custom_lda ? BIT(2) : 0; + val |= param->rdo_cost_mode ? BIT(20) : 0; + dst[i++] = val; + + val = 0; + val |= param->lf ? BIT(2) : 0; + val |= param->lf_x_tile ? BIT(3) : 0; + val |= param->lf_x_slice ? BIT(4) : 0; + dst[i++] = val; + } else { + val = 0; + dst[i++] = val; + } dst[i++] = FIELD_PREP(GENMASK(15, 8), param->beta_offset) | FIELD_PREP(GENMASK(7, 0), param->tc_offset); dst[i++] = param->unknown11; dst[i++] = param->unknown12; - dst[i++] = FIELD_PREP(GENMASK(31, 16), param->prefetch_auto) | - FIELD_PREP(GENMASK(15, 0), param->num_slices); + if (version >= MCU_MSG_VERSION_2019_2) + dst[i++] = param->num_slices; + else + dst[i++] = FIELD_PREP(GENMASK(31, 16), param->prefetch_auto) | + FIELD_PREP(GENMASK(15, 0), param->num_slices); dst[i++] = param->prefetch_mem_offset; dst[i++] = param->prefetch_mem_size; dst[i++] = FIELD_PREP(GENMASK(31, 16), param->clip_vrt_range) | @@ -139,19 +174,51 @@ allegro_encode_config_blob(u32 *dst, struct create_channel_param *param) FIELD_PREP(GENMASK(15, 0), param->pb_delta); dst[i++] = FIELD_PREP(GENMASK(31, 16), param->golden_ref_frequency) | FIELD_PREP(GENMASK(15, 0), param->golden_delta); - dst[i++] = param->rate_control_option; + if (version >= MCU_MSG_VERSION_2019_2) + dst[i++] = param->rate_control_option; + else + dst[i++] = 0; + + if (version >= MCU_MSG_VERSION_2019_2) { + dst[i++] = param->num_pixel; + dst[i++] = FIELD_PREP(GENMASK(31, 16), param->max_pixel_value) | + FIELD_PREP(GENMASK(15, 0), param->max_psnr); + for (j = 0; j < 3; j++) + dst[i++] = param->maxpicturesize[j]; + } + + if (version >= MCU_MSG_VERSION_2019_2) + dst[i++] = param->gop_ctrl_mode; + else + dst[i++] = 0; - dst[i++] = param->gop_ctrl_mode; + if (version >= MCU_MSG_VERSION_2019_2) + dst[i++] = FIELD_PREP(GENMASK(31, 24), param->freq_golden_ref) | + FIELD_PREP(GENMASK(23, 16), param->num_b) | + FIELD_PREP(GENMASK(15, 0), param->gop_length); dst[i++] = param->freq_idr; + if (version >= MCU_MSG_VERSION_2019_2) + dst[i++] = param->enable_lt; dst[i++] = param->freq_lt; dst[i++] = param->gdr_mode; - dst[i++] = FIELD_PREP(GENMASK(31, 24), param->freq_golden_ref) | - FIELD_PREP(GENMASK(23, 16), param->num_b) | - FIELD_PREP(GENMASK(15, 0), param->gop_length); + if (version < MCU_MSG_VERSION_2019_2) + dst[i++] = FIELD_PREP(GENMASK(31, 24), param->freq_golden_ref) | + FIELD_PREP(GENMASK(23, 16), param->num_b) | + FIELD_PREP(GENMASK(15, 0), param->gop_length); + + if (version >= MCU_MSG_VERSION_2019_2) + dst[i++] = param->tmpdqp; dst[i++] = param->subframe_latency; dst[i++] = param->lda_control_mode; - dst[i++] = param->unknown41; + if (version < MCU_MSG_VERSION_2019_2) + dst[i++] = param->unknown41; + + if (version >= MCU_MSG_VERSION_2019_2) { + for (j = 0; j < 6; j++) + dst[i++] = param->lda_factors[j]; + dst[i++] = param->max_num_merge_cand; + } return i * sizeof(*dst); } @@ -159,12 +226,20 @@ allegro_encode_config_blob(u32 *dst, struct create_channel_param *param) static ssize_t allegro_enc_create_channel(u32 *dst, struct mcu_msg_create_channel *msg) { + enum mcu_msg_version version = msg->header.version; unsigned int i = 0; dst[i++] = msg->user_id; - memcpy(&dst[i], msg->blob, msg->blob_size); - i += msg->blob_size / sizeof(*dst); + if (version >= MCU_MSG_VERSION_2019_2) { + dst[i++] = msg->blob_mcu_addr; + } else { + memcpy(&dst[i], msg->blob, msg->blob_size); + i += msg->blob_size / sizeof(*dst); + } + + if (version >= MCU_MSG_VERSION_2019_2) + dst[i++] = msg->ep1_addr; return i * sizeof(*dst); } @@ -173,8 +248,15 @@ ssize_t allegro_decode_config_blob(struct create_channel_param *param, struct mcu_msg_create_channel_response *msg, u32 *src) { - param->num_ref_idx_l0 = msg->num_ref_idx_l0; - param->num_ref_idx_l1 = msg->num_ref_idx_l1; + enum mcu_msg_version version = msg->header.version; + + if (version >= MCU_MSG_VERSION_2019_2) { + param->num_ref_idx_l0 = FIELD_GET(GENMASK(7, 4), src[9]); + param->num_ref_idx_l1 = FIELD_GET(GENMASK(11, 8), src[9]); + } else { + param->num_ref_idx_l0 = msg->num_ref_idx_l0; + param->num_ref_idx_l1 = msg->num_ref_idx_l1; + } return 0; } @@ -229,6 +311,7 @@ allegro_enc_put_stream_buffer(u32 *dst, static ssize_t allegro_enc_encode_frame(u32 *dst, struct mcu_msg_encode_frame *msg) { + enum mcu_msg_version version = msg->header.version; unsigned int i = 0; dst[i++] = msg->channel_id; @@ -237,6 +320,14 @@ allegro_enc_encode_frame(u32 *dst, struct mcu_msg_encode_frame *msg) dst[i++] = msg->encoding_options; dst[i++] = FIELD_PREP(GENMASK(31, 16), msg->padding) | FIELD_PREP(GENMASK(15, 0), msg->pps_qp); + + if (version >= MCU_MSG_VERSION_2019_2) { + dst[i++] = 0; + dst[i++] = 0; + dst[i++] = 0; + dst[i++] = 0; + } + dst[i++] = lower_32_bits(msg->user_param); dst[i++] = upper_32_bits(msg->user_param); dst[i++] = lower_32_bits(msg->src_handle); @@ -244,7 +335,11 @@ allegro_enc_encode_frame(u32 *dst, struct mcu_msg_encode_frame *msg) dst[i++] = msg->request_options; dst[i++] = msg->src_y; dst[i++] = msg->src_uv; + if (version >= MCU_MSG_VERSION_2019_2) + dst[i++] = msg->is_10_bit; dst[i++] = msg->stride; + if (version >= MCU_MSG_VERSION_2019_2) + dst[i++] = msg->format; dst[i++] = msg->ep2; dst[i++] = lower_32_bits(msg->ep2_v); dst[i++] = upper_32_bits(msg->ep2_v); @@ -266,14 +361,21 @@ static ssize_t allegro_dec_create_channel(struct mcu_msg_create_channel_response *msg, u32 *src) { + enum mcu_msg_version version = msg->header.version; unsigned int i = 0; msg->channel_id = src[i++]; msg->user_id = src[i++]; - msg->options = src[i++]; - msg->num_core = src[i++]; - msg->num_ref_idx_l0 = FIELD_GET(GENMASK(7, 4), src[i]); - msg->num_ref_idx_l1 = FIELD_GET(GENMASK(11, 8), src[i++]); + /* + * Version >= MCU_MSG_VERSION_2019_2 is handled in + * allegro_decode_config_blob(). + */ + if (version < MCU_MSG_VERSION_2019_2) { + msg->options = src[i++]; + msg->num_core = src[i++]; + msg->num_ref_idx_l0 = FIELD_GET(GENMASK(7, 4), src[i]); + msg->num_ref_idx_l1 = FIELD_GET(GENMASK(11, 8), src[i++]); + } msg->int_buffers_count = src[i++]; msg->int_buffers_size = src[i++]; msg->rec_buffers_count = src[i++]; @@ -298,6 +400,7 @@ allegro_dec_destroy_channel(struct mcu_msg_destroy_channel_response *msg, static ssize_t allegro_dec_encode_frame(struct mcu_msg_encode_frame_response *msg, u32 *src) { + enum mcu_msg_version version = msg->header.version; unsigned int i = 0; unsigned int j; @@ -341,6 +444,12 @@ allegro_dec_encode_frame(struct mcu_msg_encode_frame_response *msg, u32 *src) msg->pps_qp = FIELD_GET(GENMASK(15, 0), src[i++]); msg->reserved2 = src[i++]; + if (version >= MCU_MSG_VERSION_2019_2) { + msg->reserved3 = src[i++]; + msg->reserved4 = src[i++]; + msg->reserved5 = src[i++]; + msg->reserved6 = src[i++]; + } return i * sizeof(*src); } diff --git a/drivers/staging/media/allegro-dvt/allegro-mail.h b/drivers/staging/media/allegro-dvt/allegro-mail.h index c095dbfcf104..486ecb12b098 100644 --- a/drivers/staging/media/allegro-dvt/allegro-mail.h +++ b/drivers/staging/media/allegro-dvt/allegro-mail.h @@ -22,6 +22,7 @@ enum mcu_msg_type { enum mcu_msg_version { MCU_MSG_VERSION_2018_2, + MCU_MSG_VERSION_2019_2, }; const char *msg_type_name(enum mcu_msg_type type); @@ -46,11 +47,14 @@ struct mcu_msg_init_response { struct create_channel_param { enum mcu_msg_version version; + u32 layer_id; u16 width; u16 height; + u32 videomode; u32 format; u32 colorspace; u32 src_mode; + u32 src_bit_depth; u8 profile; u16 constraint_set_flags; u32 codec; @@ -59,9 +63,11 @@ struct create_channel_param { u32 log2_max_poc; u32 log2_max_frame_num; u32 temporal_mvp_enable; + u32 enable_reordering; u32 dbf_ovr_en; u32 num_ref_idx_l0; u32 num_ref_idx_l1; + u32 custom_lda; u32 rdo_cost_mode; u32 lf; u32 lf_x_tile; @@ -105,6 +111,10 @@ struct create_channel_param { u16 golden_delta; u16 golden_ref_frequency; u32 rate_control_option; + u32 num_pixel; + u16 max_psnr; + u16 max_pixel_value; + u32 maxpicturesize[3]; /* gop param */ u32 gop_ctrl_mode; @@ -114,10 +124,16 @@ struct create_channel_param { u16 gop_length; u8 num_b; u8 freq_golden_ref; + u32 enable_lt; + u32 tmpdqp; u32 subframe_latency; u32 lda_control_mode; u32 unknown41; + + u32 lda_factors[6]; + + u32 max_num_merge_cand; }; struct mcu_msg_create_channel { @@ -126,6 +142,7 @@ struct mcu_msg_create_channel { u32 *blob; size_t blob_size; u32 blob_mcu_addr; + u32 ep1_addr; }; struct mcu_msg_create_channel_response { @@ -203,9 +220,12 @@ struct mcu_msg_encode_frame { /* u32 scene_change_delay (optional) */ /* rate control param (optional) */ /* gop param (optional) */ + /* dynamic resolution params (optional) */ u32 src_y; u32 src_uv; + u32 is_10_bit; u32 stride; + u32 format; u32 ep2; u64 ep2_v; }; @@ -249,6 +269,10 @@ struct mcu_msg_encode_frame_response { u16 pps_qp; u16 reserved1; u32 reserved2; + u32 reserved3; + u32 reserved4; + u32 reserved5; + u32 reserved6; }; union mcu_msg_response { -- cgit v1.2.3 From 04320b3ef90bef04df6672e3a98a266b88c35b55 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 22 Jul 2020 15:09:03 +0200 Subject: media: allegro: fix potential null dereference on header The pointer header is an alias to msg and msg is being null checked. However, if msg is null then header is also null and this can lead to a null pointer dereference on the assignment type = header->type. Fix this just using header->type after the null check and removing the need for type as it is only used once. Addresses-Coverity: ("Dereference before null check") Fixes: 3de16839669f ("media: allegro: add explicit mail encoding and decoding") Signed-off-by: Colin Ian King Reviewed-by: Michael Tretter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/allegro-dvt/allegro-mail.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/staging/media/allegro-dvt/allegro-mail.c') diff --git a/drivers/staging/media/allegro-dvt/allegro-mail.c b/drivers/staging/media/allegro-dvt/allegro-mail.c index 4ac65de12463..9286d2162377 100644 --- a/drivers/staging/media/allegro-dvt/allegro-mail.c +++ b/drivers/staging/media/allegro-dvt/allegro-mail.c @@ -462,13 +462,12 @@ allegro_dec_encode_frame(struct mcu_msg_encode_frame_response *msg, u32 *src) ssize_t allegro_encode_mail(u32 *dst, void *msg) { const struct mcu_msg_header *header = msg; - enum mcu_msg_type type = header->type; ssize_t size; if (!msg || !dst) return -EINVAL; - switch (type) { + switch (header->type) { case MCU_MSG_TYPE_INIT: size = allegro_enc_init(&dst[1], msg); break; -- cgit v1.2.3