Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: allegro: add encoder buffer support

The encoder buffer serves as a cache for reference frames during the
encoding process. The encoder buffer significantly reduces the bandwidth
requirement for read accesses on the AXI ports of the VCU, but slightly
reduces the quality of the encoded video.

The encoder buffer must be configured as a whole during the firmware
initialization and later explicitly enabled for every channel that shall
use the encoder buffer.

Prior to firmware version 2019.2, it was necessary to explicitly set the
size of the encoder buffer for every channel. Since 2019.2 it is
sufficient to enable the encoder buffer and leave the rest to the
firmware. Therefore, only support the encoder buffer for firmware 2019.2
and later.

Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

authored by

Michael Tretter and committed by
Mauro Carvalho Chehab
98f1cbf6 83cc5fd9

+90 -22
+76 -7
drivers/media/platform/allegro-dvt/allegro-core.c
··· 129 129 struct mutex lock; 130 130 }; 131 131 132 + struct allegro_encoder_buffer { 133 + unsigned int size; 134 + unsigned int color_depth; 135 + unsigned int num_cores; 136 + unsigned int clk_rate; 137 + }; 138 + 132 139 struct allegro_dev { 133 140 struct v4l2_device v4l2_dev; 134 141 struct video_device video_dev; ··· 155 148 const struct fw_info *fw_info; 156 149 struct allegro_buffer firmware; 157 150 struct allegro_buffer suballocator; 151 + bool has_encoder_buffer; 152 + struct allegro_encoder_buffer encoder_buffer; 158 153 159 154 struct completion init_complete; 160 155 bool initialized; ··· 939 930 kfree(msg); 940 931 } 941 932 933 + static int allegro_encoder_buffer_init(struct allegro_dev *dev, 934 + struct allegro_encoder_buffer *buffer) 935 + { 936 + int err; 937 + struct regmap *settings = dev->settings; 938 + unsigned int supports_10_bit; 939 + unsigned int memory_depth; 940 + unsigned int num_cores; 941 + unsigned int color_depth; 942 + unsigned long clk_rate; 943 + 944 + /* We don't support the encoder buffer pre Firmware version 2019.2 */ 945 + if (dev->fw_info->mailbox_version < MCU_MSG_VERSION_2019_2) 946 + return -ENODEV; 947 + 948 + if (!settings) 949 + return -EINVAL; 950 + 951 + err = regmap_read(settings, VCU_ENC_COLOR_DEPTH, &supports_10_bit); 952 + if (err < 0) 953 + return err; 954 + err = regmap_read(settings, VCU_MEMORY_DEPTH, &memory_depth); 955 + if (err < 0) 956 + return err; 957 + err = regmap_read(settings, VCU_NUM_CORE, &num_cores); 958 + if (err < 0) 959 + return err; 960 + 961 + clk_rate = clk_get_rate(dev->clk_core); 962 + if (clk_rate == 0) 963 + return -EINVAL; 964 + 965 + color_depth = supports_10_bit ? 10 : 8; 966 + /* The firmware expects the encoder buffer size in bits. */ 967 + buffer->size = color_depth * 32 * memory_depth; 968 + buffer->color_depth = color_depth; 969 + buffer->num_cores = num_cores; 970 + buffer->clk_rate = clk_rate; 971 + 972 + v4l2_dbg(1, debug, &dev->v4l2_dev, 973 + "using %d bits encoder buffer with %d-bit color depth\n", 974 + buffer->size, color_depth); 975 + 976 + return 0; 977 + } 978 + 942 979 static void allegro_mcu_send_init(struct allegro_dev *dev, 943 980 dma_addr_t suballoc_dma, size_t suballoc_size) 944 981 { ··· 998 943 msg.suballoc_dma = to_mcu_addr(dev, suballoc_dma); 999 944 msg.suballoc_size = to_mcu_size(dev, suballoc_size); 1000 945 1001 - /* disable L2 cache */ 1002 - msg.l2_cache[0] = -1; 1003 - msg.l2_cache[1] = -1; 1004 - msg.l2_cache[2] = -1; 946 + if (dev->has_encoder_buffer) { 947 + msg.encoder_buffer_size = dev->encoder_buffer.size; 948 + msg.encoder_buffer_color_depth = dev->encoder_buffer.color_depth; 949 + msg.num_cores = dev->encoder_buffer.num_cores; 950 + msg.clk_rate = dev->encoder_buffer.clk_rate; 951 + } else { 952 + msg.encoder_buffer_size = -1; 953 + msg.encoder_buffer_color_depth = -1; 954 + msg.num_cores = -1; 955 + msg.clk_rate = -1; 956 + } 1005 957 1006 958 allegro_mbox_send(dev->mbox_command, &msg); 1007 959 } ··· 1255 1193 param->max_transfo_depth_intra = channel->max_transfo_depth_intra; 1256 1194 param->max_transfo_depth_inter = channel->max_transfo_depth_inter; 1257 1195 1258 - param->prefetch_auto = 0; 1259 - param->prefetch_mem_offset = 0; 1260 - param->prefetch_mem_size = 0; 1196 + param->encoder_buffer_enabled = channel->dev->has_encoder_buffer; 1197 + param->encoder_buffer_offset = 0; 1261 1198 1262 1199 param->rate_control_mode = channel->frame_rc_enable ? 1263 1200 v4l2_bitrate_mode_to_mcu_mode(bitrate_mode) : 0; ··· 1381 1320 u64 src_handle) 1382 1321 { 1383 1322 struct mcu_msg_encode_frame msg; 1323 + bool use_encoder_buffer = channel->dev->has_encoder_buffer; 1384 1324 1385 1325 memset(&msg, 0, sizeof(msg)); 1386 1326 ··· 1390 1328 1391 1329 msg.channel_id = channel->mcu_channel_id; 1392 1330 msg.encoding_options = AL_OPT_FORCE_LOAD; 1331 + if (use_encoder_buffer) 1332 + msg.encoding_options |= AL_OPT_USE_L2; 1393 1333 msg.pps_qp = 26; /* qp are relative to 26 */ 1394 1334 msg.user_param = 0; /* copied to mcu_msg_encode_frame_response */ 1395 1335 /* src_handle is copied to mcu_msg_encode_frame_response */ ··· 3585 3521 "failed to initialize mailboxes\n"); 3586 3522 return -EIO; 3587 3523 } 3524 + 3525 + err = allegro_encoder_buffer_init(dev, &dev->encoder_buffer); 3526 + dev->has_encoder_buffer = (err == 0); 3527 + if (!dev->has_encoder_buffer) 3528 + v4l2_info(&dev->v4l2_dev, "encoder buffer not available\n"); 3588 3529 3589 3530 allegro_mcu_enable_interrupts(dev); 3590 3531
+8 -11
drivers/media/platform/allegro-dvt/allegro-mail.c
··· 49 49 dst[i++] = msg->reserved0; 50 50 dst[i++] = msg->suballoc_dma; 51 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]; 52 + dst[i++] = msg->encoder_buffer_size; 53 + dst[i++] = msg->encoder_buffer_color_depth; 54 + dst[i++] = msg->num_cores; 55 55 if (version >= MCU_MSG_VERSION_2019_2) { 56 - dst[i++] = -1; 56 + dst[i++] = msg->clk_rate; 57 57 dst[i++] = 0; 58 58 } 59 59 ··· 146 146 FIELD_PREP(GENMASK(7, 0), param->tc_offset); 147 147 dst[i++] = param->unknown11; 148 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; 149 + dst[i++] = param->num_slices; 150 + dst[i++] = param->encoder_buffer_offset; 151 + dst[i++] = param->encoder_buffer_enabled; 152 + 156 153 dst[i++] = FIELD_PREP(GENMASK(31, 16), param->clip_vrt_range) | 157 154 FIELD_PREP(GENMASK(15, 0), param->clip_hrz_range); 158 155 dst[i++] = FIELD_PREP(GENMASK(31, 16), param->me_range[1]) |
+6 -4
drivers/media/platform/allegro-dvt/allegro-mail.h
··· 37 37 u32 reserved0; /* maybe a unused channel id */ 38 38 u32 suballoc_dma; 39 39 u32 suballoc_size; 40 - s32 l2_cache[3]; 40 + s32 encoder_buffer_size; 41 + s32 encoder_buffer_color_depth; 42 + s32 num_cores; 43 + s32 clk_rate; 41 44 }; 42 45 43 46 struct mcu_msg_init_response { ··· 82 79 u32 unknown11; 83 80 u32 unknown12; 84 81 u16 num_slices; 85 - u16 prefetch_auto; 86 - u32 prefetch_mem_offset; 87 - u32 prefetch_mem_size; 82 + u32 encoder_buffer_offset; 83 + u32 encoder_buffer_enabled; 88 84 u16 clip_hrz_range; 89 85 u16 clip_vrt_range; 90 86 u16 me_range[4];