History

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.

Michael Tretter committed 5 years ago

Commit 98f1cbf1 parent 83cc5fd3 files · +90 −22Browse files

Unified · Split

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