summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/platform/allegro-dvt/allegro-core.c545
-rw-r--r--drivers/media/platform/allegro-dvt/allegro-mail.c6
-rw-r--r--drivers/media/platform/allegro-dvt/allegro-mail.h1
3 files changed, 516 insertions, 36 deletions
diff --git a/drivers/media/platform/allegro-dvt/allegro-core.c b/drivers/media/platform/allegro-dvt/allegro-core.c
index f3a656ab2b06..887b492e4ad1 100644
--- a/drivers/media/platform/allegro-dvt/allegro-core.c
+++ b/drivers/media/platform/allegro-dvt/allegro-core.c
@@ -30,6 +30,7 @@
#include "allegro-mail.h"
#include "nal-h264.h"
+#include "nal-hevc.h"
/*
* Support up to 4k video streams. The hardware actually supports higher
@@ -209,6 +210,8 @@ struct allegro_channel {
bool enable_loop_filter_across_tiles;
bool enable_loop_filter_across_slices;
+ bool enable_deblocking_filter_override;
+ bool enable_reordering;
bool dbf_ovr_en;
unsigned int num_ref_idx_l0;
@@ -235,6 +238,16 @@ struct allegro_channel {
struct v4l2_ctrl *mpeg_video_h264_min_qp;
struct v4l2_ctrl *mpeg_video_h264_p_frame_qp;
struct v4l2_ctrl *mpeg_video_h264_b_frame_qp;
+
+ struct v4l2_ctrl *mpeg_video_hevc_profile;
+ struct v4l2_ctrl *mpeg_video_hevc_level;
+ struct v4l2_ctrl *mpeg_video_hevc_tier;
+ struct v4l2_ctrl *mpeg_video_hevc_i_frame_qp;
+ struct v4l2_ctrl *mpeg_video_hevc_max_qp;
+ struct v4l2_ctrl *mpeg_video_hevc_min_qp;
+ struct v4l2_ctrl *mpeg_video_hevc_p_frame_qp;
+ struct v4l2_ctrl *mpeg_video_hevc_b_frame_qp;
+
struct v4l2_ctrl *mpeg_video_frame_rc_enable;
struct { /* video bitrate mode control cluster */
struct v4l2_ctrl *mpeg_video_bitrate_mode;
@@ -267,31 +280,46 @@ struct allegro_channel {
static inline int
allegro_channel_get_i_frame_qp(struct allegro_channel *channel)
{
- return v4l2_ctrl_g_ctrl(channel->mpeg_video_h264_i_frame_qp);
+ if (channel->codec == V4L2_PIX_FMT_HEVC)
+ return v4l2_ctrl_g_ctrl(channel->mpeg_video_hevc_i_frame_qp);
+ else
+ return v4l2_ctrl_g_ctrl(channel->mpeg_video_h264_i_frame_qp);
}
static inline int
allegro_channel_get_p_frame_qp(struct allegro_channel *channel)
{
- return v4l2_ctrl_g_ctrl(channel->mpeg_video_h264_p_frame_qp);
+ if (channel->codec == V4L2_PIX_FMT_HEVC)
+ return v4l2_ctrl_g_ctrl(channel->mpeg_video_hevc_p_frame_qp);
+ else
+ return v4l2_ctrl_g_ctrl(channel->mpeg_video_h264_p_frame_qp);
}
static inline int
allegro_channel_get_b_frame_qp(struct allegro_channel *channel)
{
- return v4l2_ctrl_g_ctrl(channel->mpeg_video_h264_b_frame_qp);
+ if (channel->codec == V4L2_PIX_FMT_HEVC)
+ return v4l2_ctrl_g_ctrl(channel->mpeg_video_hevc_b_frame_qp);
+ else
+ return v4l2_ctrl_g_ctrl(channel->mpeg_video_h264_b_frame_qp);
}
static inline int
allegro_channel_get_min_qp(struct allegro_channel *channel)
{
- return v4l2_ctrl_g_ctrl(channel->mpeg_video_h264_min_qp);
+ if (channel->codec == V4L2_PIX_FMT_HEVC)
+ return v4l2_ctrl_g_ctrl(channel->mpeg_video_hevc_min_qp);
+ else
+ return v4l2_ctrl_g_ctrl(channel->mpeg_video_h264_min_qp);
}
static inline int
allegro_channel_get_max_qp(struct allegro_channel *channel)
{
- return v4l2_ctrl_g_ctrl(channel->mpeg_video_h264_max_qp);
+ if (channel->codec == V4L2_PIX_FMT_HEVC)
+ return v4l2_ctrl_g_ctrl(channel->mpeg_video_hevc_max_qp);
+ else
+ return v4l2_ctrl_g_ctrl(channel->mpeg_video_h264_max_qp);
}
struct allegro_m2m_buffer {
@@ -585,6 +613,86 @@ static unsigned int h264_maximum_cpb_size(enum v4l2_mpeg_video_h264_level level)
}
}
+static enum v4l2_mpeg_video_hevc_level
+select_minimum_hevc_level(unsigned int width, unsigned int height)
+{
+ unsigned int luma_picture_size = width * height;
+ enum v4l2_mpeg_video_hevc_level level;
+
+ if (luma_picture_size <= 36864)
+ level = V4L2_MPEG_VIDEO_HEVC_LEVEL_1;
+ else if (luma_picture_size <= 122880)
+ level = V4L2_MPEG_VIDEO_HEVC_LEVEL_2;
+ else if (luma_picture_size <= 245760)
+ level = V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1;
+ else if (luma_picture_size <= 552960)
+ level = V4L2_MPEG_VIDEO_HEVC_LEVEL_3;
+ else if (luma_picture_size <= 983040)
+ level = V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1;
+ else if (luma_picture_size <= 2228224)
+ level = V4L2_MPEG_VIDEO_HEVC_LEVEL_4;
+ else if (luma_picture_size <= 8912896)
+ level = V4L2_MPEG_VIDEO_HEVC_LEVEL_5;
+ else
+ level = V4L2_MPEG_VIDEO_HEVC_LEVEL_6;
+
+ return level;
+}
+
+static unsigned int hevc_maximum_bitrate(enum v4l2_mpeg_video_hevc_level level)
+{
+ /*
+ * See Rec. ITU-T H.265 v5 (02/2018), A.4.2 Profile-specific level
+ * limits for the video profiles.
+ */
+ switch (level) {
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_1:
+ return 128;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_2:
+ return 1500;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1:
+ return 3000;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_3:
+ return 6000;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1:
+ return 10000;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_4:
+ return 12000;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1:
+ return 20000;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_5:
+ return 25000;
+ default:
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1:
+ return 40000;
+ }
+}
+
+static unsigned int hevc_maximum_cpb_size(enum v4l2_mpeg_video_hevc_level level)
+{
+ switch (level) {
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_1:
+ return 350;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_2:
+ return 1500;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1:
+ return 3000;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_3:
+ return 6000;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1:
+ return 10000;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_4:
+ return 12000;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1:
+ return 20000;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_5:
+ return 25000;
+ default:
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1:
+ return 40000;
+ }
+}
+
static const struct fw_info *
allegro_get_firmware_info(struct allegro_dev *dev,
const struct firmware *fw,
@@ -908,6 +1016,55 @@ static u16 v4l2_level_to_mcu_level(enum v4l2_mpeg_video_h264_level level)
}
}
+static u8 hevc_profile_to_mcu_profile(enum v4l2_mpeg_video_hevc_profile profile)
+{
+ switch (profile) {
+ default:
+ case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN:
+ return 1;
+ case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10:
+ return 2;
+ case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE:
+ return 3;
+ }
+}
+
+static u16 hevc_level_to_mcu_level(enum v4l2_mpeg_video_hevc_level level)
+{
+ switch (level) {
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_1:
+ return 10;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_2:
+ return 20;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1:
+ return 21;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_3:
+ return 30;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1:
+ return 31;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_4:
+ return 40;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1:
+ return 41;
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_5:
+ return 50;
+ default:
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1:
+ return 51;
+ }
+}
+
+static u8 hevc_tier_to_mcu_tier(enum v4l2_mpeg_video_hevc_tier tier)
+{
+ switch (tier) {
+ default:
+ case V4L2_MPEG_VIDEO_HEVC_TIER_MAIN:
+ return 0;
+ case V4L2_MPEG_VIDEO_HEVC_TIER_HIGH:
+ return 1;
+ }
+}
+
static u32
v4l2_bitrate_mode_to_mcu_mode(enum v4l2_mpeg_video_bitrate_mode mode)
{
@@ -949,6 +1106,10 @@ static u32 allegro_channel_get_entropy_mode(struct allegro_channel *channel)
#define ALLEGRO_ENTROPY_MODE_CAVLC 0
#define ALLEGRO_ENTROPY_MODE_CABAC 1
+ /* HEVC always uses CABAC, but this has to be explicitly set */
+ if (channel->codec == V4L2_PIX_FMT_HEVC)
+ return ALLEGRO_ENTROPY_MODE_CABAC;
+
return ALLEGRO_ENTROPY_MODE_CAVLC;
}
@@ -960,8 +1121,6 @@ static int fill_create_channel_param(struct allegro_channel *channel,
int b_frame_qp = allegro_channel_get_b_frame_qp(channel);
int bitrate_mode = v4l2_ctrl_g_ctrl(channel->mpeg_video_bitrate_mode);
unsigned int cpb_size = v4l2_ctrl_g_ctrl(channel->mpeg_video_cpb_size);
- enum v4l2_mpeg_video_h264_profile profile;
- enum v4l2_mpeg_video_h264_level level;
param->width = channel->width;
param->height = channel->height;
@@ -971,17 +1130,37 @@ static int fill_create_channel_param(struct allegro_channel *channel,
param->src_mode = 0x0;
param->codec = channel->codec;
- profile = v4l2_ctrl_g_ctrl(channel->mpeg_video_h264_profile);
- level = v4l2_ctrl_g_ctrl(channel->mpeg_video_h264_level);
- param->profile = v4l2_profile_to_mcu_profile(profile);
- param->constraint_set_flags = BIT(1);
- param->level = v4l2_level_to_mcu_level(level);
+ if (channel->codec == V4L2_PIX_FMT_H264) {
+ enum v4l2_mpeg_video_h264_profile profile;
+ enum v4l2_mpeg_video_h264_level level;
+
+ profile = v4l2_ctrl_g_ctrl(channel->mpeg_video_h264_profile);
+ level = v4l2_ctrl_g_ctrl(channel->mpeg_video_h264_level);
+
+ param->profile = v4l2_profile_to_mcu_profile(profile);
+ param->constraint_set_flags = BIT(1);
+ param->level = v4l2_level_to_mcu_level(level);
+ } else {
+ enum v4l2_mpeg_video_hevc_profile profile;
+ enum v4l2_mpeg_video_hevc_level level;
+ enum v4l2_mpeg_video_hevc_tier tier;
+
+ profile = v4l2_ctrl_g_ctrl(channel->mpeg_video_hevc_profile);
+ level = v4l2_ctrl_g_ctrl(channel->mpeg_video_hevc_level);
+ tier = v4l2_ctrl_g_ctrl(channel->mpeg_video_hevc_tier);
+
+ param->profile = hevc_profile_to_mcu_profile(profile);
+ param->level = hevc_level_to_mcu_level(level);
+ param->tier = hevc_tier_to_mcu_tier(tier);
+ }
param->log2_max_poc = LOG2_MAX_PIC_ORDER_CNT;
param->log2_max_frame_num = channel->log2_max_frame_num;
param->temporal_mvp_enable = channel->temporal_mvp_enable;
param->dbf_ovr_en = channel->dbf_ovr_en;
+ param->override_lf = channel->enable_deblocking_filter_override;
+ param->enable_reordering = channel->enable_reordering;
param->entropy_mode = allegro_channel_get_entropy_mode(channel);
param->rdo_cost_mode = 1;
param->custom_lda = 1;
@@ -1454,6 +1633,158 @@ static void allegro_channel_eos_event(struct allegro_channel *channel)
v4l2_event_queue_fh(&channel->fh, &eos_event);
}
+static ssize_t allegro_hevc_write_vps(struct allegro_channel *channel,
+ void *dest, size_t n)
+{
+ struct allegro_dev *dev = channel->dev;
+ struct nal_hevc_vps *vps;
+ struct nal_hevc_profile_tier_level *ptl;
+ ssize_t size;
+ unsigned int num_ref_frames = channel->num_ref_idx_l0;
+ s32 profile = v4l2_ctrl_g_ctrl(channel->mpeg_video_hevc_profile);
+ s32 level = v4l2_ctrl_g_ctrl(channel->mpeg_video_hevc_level);
+ s32 tier = v4l2_ctrl_g_ctrl(channel->mpeg_video_hevc_tier);
+
+ vps = kzalloc(sizeof(*vps), GFP_KERNEL);
+ if (!vps)
+ return -ENOMEM;
+
+ vps->base_layer_internal_flag = 1;
+ vps->base_layer_available_flag = 1;
+ vps->temporal_id_nesting_flag = 1;
+
+ ptl = &vps->profile_tier_level;
+ ptl->general_profile_idc = nal_hevc_profile_from_v4l2(profile);
+ ptl->general_profile_compatibility_flag[ptl->general_profile_idc] = 1;
+ ptl->general_tier_flag = nal_hevc_tier_from_v4l2(tier);
+ ptl->general_progressive_source_flag = 1;
+ ptl->general_frame_only_constraint_flag = 1;
+ ptl->general_level_idc = nal_hevc_level_from_v4l2(level);
+
+ vps->sub_layer_ordering_info_present_flag = 0;
+ vps->max_dec_pic_buffering_minus1[0] = num_ref_frames;
+ vps->max_num_reorder_pics[0] = num_ref_frames;
+
+ size = nal_hevc_write_vps(&dev->plat_dev->dev, dest, n, vps);
+
+ kfree(vps);
+
+ return size;
+}
+
+static ssize_t allegro_hevc_write_sps(struct allegro_channel *channel,
+ void *dest, size_t n)
+{
+ struct allegro_dev *dev = channel->dev;
+ struct nal_hevc_sps *sps;
+ struct nal_hevc_profile_tier_level *ptl;
+ ssize_t size;
+ unsigned int num_ref_frames = channel->num_ref_idx_l0;
+ s32 profile = v4l2_ctrl_g_ctrl(channel->mpeg_video_hevc_profile);
+ s32 level = v4l2_ctrl_g_ctrl(channel->mpeg_video_hevc_level);
+ s32 tier = v4l2_ctrl_g_ctrl(channel->mpeg_video_hevc_tier);
+
+ sps = kzalloc(sizeof(*sps), GFP_KERNEL);
+ if (!sps)
+ return -ENOMEM;
+
+ sps->temporal_id_nesting_flag = 1;
+
+ ptl = &sps->profile_tier_level;
+ ptl->general_profile_idc = nal_hevc_profile_from_v4l2(profile);
+ ptl->general_profile_compatibility_flag[ptl->general_profile_idc] = 1;
+ ptl->general_tier_flag = nal_hevc_tier_from_v4l2(tier);
+ ptl->general_progressive_source_flag = 1;
+ ptl->general_frame_only_constraint_flag = 1;
+ ptl->general_level_idc = nal_hevc_level_from_v4l2(level);
+
+ sps->seq_parameter_set_id = 0;
+ sps->chroma_format_idc = 1; /* Only 4:2:0 sampling supported */
+ sps->pic_width_in_luma_samples = round_up(channel->width, 8);
+ sps->pic_height_in_luma_samples = round_up(channel->height, 8);
+ sps->conf_win_right_offset =
+ sps->pic_width_in_luma_samples - channel->width;
+ sps->conf_win_bottom_offset =
+ sps->pic_height_in_luma_samples - channel->height;
+ sps->conformance_window_flag =
+ sps->conf_win_right_offset || sps->conf_win_bottom_offset;
+
+ sps->log2_max_pic_order_cnt_lsb_minus4 = LOG2_MAX_PIC_ORDER_CNT - 4;
+
+ sps->sub_layer_ordering_info_present_flag = 1;
+ sps->max_dec_pic_buffering_minus1[0] = num_ref_frames;
+ sps->max_num_reorder_pics[0] = num_ref_frames;
+
+ sps->log2_min_luma_coding_block_size_minus3 =
+ channel->min_cu_size - 3;
+ sps->log2_diff_max_min_luma_coding_block_size =
+ channel->max_cu_size - channel->min_cu_size;
+ sps->log2_min_luma_transform_block_size_minus2 =
+ channel->min_tu_size - 2;
+ sps->log2_diff_max_min_luma_transform_block_size =
+ channel->max_tu_size - channel->min_tu_size;
+ sps->max_transform_hierarchy_depth_intra =
+ channel->max_transfo_depth_intra;
+ sps->max_transform_hierarchy_depth_inter =
+ channel->max_transfo_depth_inter;
+
+ sps->sps_temporal_mvp_enabled_flag = channel->temporal_mvp_enable;
+ sps->strong_intra_smoothing_enabled_flag = channel->max_cu_size > 4;
+
+ size = nal_hevc_write_sps(&dev->plat_dev->dev, dest, n, sps);
+
+ kfree(sps);
+
+ return size;
+}
+
+static ssize_t allegro_hevc_write_pps(struct allegro_channel *channel,
+ struct mcu_msg_encode_frame_response *msg,
+ void *dest, size_t n)
+{
+ struct allegro_dev *dev = channel->dev;
+ struct nal_hevc_pps *pps;
+ ssize_t size;
+ int i;
+
+ pps = kzalloc(sizeof(*pps), GFP_KERNEL);
+ if (!pps)
+ return -ENOMEM;
+
+ pps->pps_pic_parameter_set_id = 0;
+ pps->pps_seq_parameter_set_id = 0;
+
+ if (msg->num_column > 1 || msg->num_row > 1) {
+ pps->tiles_enabled_flag = 1;
+ pps->num_tile_columns_minus1 = msg->num_column - 1;
+ pps->num_tile_rows_minus1 = msg->num_row - 1;
+
+ for (i = 0; i < msg->num_column; i++)
+ pps->column_width_minus1[i] = msg->tile_width[i] - 1;
+
+ for (i = 0; i < msg->num_row; i++)
+ pps->row_height_minus1[i] = msg->tile_height[i] - 1;
+ }
+
+ pps->loop_filter_across_tiles_enabled_flag =
+ channel->enable_loop_filter_across_tiles;
+ pps->pps_loop_filter_across_slices_enabled_flag =
+ channel->enable_loop_filter_across_slices;
+ pps->deblocking_filter_control_present_flag = 1;
+ pps->deblocking_filter_override_enabled_flag =
+ channel->enable_deblocking_filter_override;
+ pps->pps_beta_offset_div2 = BETA_OFFSET_DIV_2;
+ pps->pps_tc_offset_div2 = TC_OFFSET_DIV_2;
+
+ pps->lists_modification_present_flag = channel->enable_reordering;
+
+ size = nal_hevc_write_pps(&dev->plat_dev->dev, dest, n, pps);
+
+ kfree(pps);
+
+ return size;
+}
+
static u64 allegro_put_buffer(struct allegro_channel *channel,
struct list_head *list,
struct vb2_v4l2_buffer *buffer)
@@ -1577,8 +1908,27 @@ static void allegro_channel_finish_frame(struct allegro_channel *channel,
curr = vb2_plane_vaddr(&dst_buf->vb2_buf, 0);
free = partition->offset;
+
+ if (channel->codec == V4L2_PIX_FMT_HEVC && msg->is_idr) {
+ len = allegro_hevc_write_vps(channel, curr, free);
+ if (len < 0) {
+ v4l2_err(&dev->v4l2_dev,
+ "not enough space for video parameter set: %zd left\n",
+ free);
+ goto err;
+ }
+ curr += len;
+ free -= len;
+ v4l2_dbg(1, debug, &dev->v4l2_dev,
+ "channel %d: wrote %zd byte VPS nal unit\n",
+ channel->mcu_channel_id, len);
+ }
+
if (msg->is_idr) {
- len = allegro_h264_write_sps(channel, curr, free);
+ if (channel->codec == V4L2_PIX_FMT_H264)
+ len = allegro_h264_write_sps(channel, curr, free);
+ else
+ len = allegro_hevc_write_sps(channel, curr, free);
if (len < 0) {
v4l2_err(&dev->v4l2_dev,
"not enough space for sequence parameter set: %zd left\n",
@@ -1593,7 +1943,10 @@ static void allegro_channel_finish_frame(struct allegro_channel *channel,
}
if (msg->slice_type == AL_ENC_SLICE_TYPE_I) {
- len = allegro_h264_write_pps(channel, curr, free);
+ if (channel->codec == V4L2_PIX_FMT_H264)
+ len = allegro_h264_write_pps(channel, curr, free);
+ else
+ len = allegro_hevc_write_pps(channel, msg, curr, free);
if (len < 0) {
v4l2_err(&dev->v4l2_dev,
"not enough space for picture parameter set: %zd left\n",
@@ -1611,7 +1964,10 @@ static void allegro_channel_finish_frame(struct allegro_channel *channel,
dst_buf->vb2_buf.planes[0].data_offset = free;
free = 0;
} else {
- len = nal_h264_write_filler(&dev->plat_dev->dev, curr, free);
+ if (channel->codec == V4L2_PIX_FMT_H264)
+ len = nal_h264_write_filler(&dev->plat_dev->dev, curr, free);
+ else
+ len = nal_hevc_write_filler(&dev->plat_dev->dev, curr, free);
if (len < 0) {
v4l2_err(&dev->v4l2_dev,
"failed to write %zd filler data\n", free);
@@ -2011,6 +2367,16 @@ static void allegro_destroy_channel(struct allegro_channel *channel)
v4l2_ctrl_grab(channel->mpeg_video_h264_min_qp, false);
v4l2_ctrl_grab(channel->mpeg_video_h264_p_frame_qp, false);
v4l2_ctrl_grab(channel->mpeg_video_h264_b_frame_qp, false);
+
+ v4l2_ctrl_grab(channel->mpeg_video_hevc_profile, false);
+ v4l2_ctrl_grab(channel->mpeg_video_hevc_level, false);
+ v4l2_ctrl_grab(channel->mpeg_video_hevc_tier, false);
+ v4l2_ctrl_grab(channel->mpeg_video_hevc_i_frame_qp, false);
+ v4l2_ctrl_grab(channel->mpeg_video_hevc_max_qp, false);
+ v4l2_ctrl_grab(channel->mpeg_video_hevc_min_qp, false);
+ v4l2_ctrl_grab(channel->mpeg_video_hevc_p_frame_qp, false);
+ v4l2_ctrl_grab(channel->mpeg_video_hevc_b_frame_qp, false);
+
v4l2_ctrl_grab(channel->mpeg_video_frame_rc_enable, false);
v4l2_ctrl_grab(channel->mpeg_video_bitrate_mode, false);
v4l2_ctrl_grab(channel->mpeg_video_bitrate, false);
@@ -2067,6 +2433,16 @@ static int allegro_create_channel(struct allegro_channel *channel)
v4l2_ctrl_grab(channel->mpeg_video_h264_min_qp, true);
v4l2_ctrl_grab(channel->mpeg_video_h264_p_frame_qp, true);
v4l2_ctrl_grab(channel->mpeg_video_h264_b_frame_qp, true);
+
+ v4l2_ctrl_grab(channel->mpeg_video_hevc_profile, true);
+ v4l2_ctrl_grab(channel->mpeg_video_hevc_level, true);
+ v4l2_ctrl_grab(channel->mpeg_video_hevc_tier, true);
+ v4l2_ctrl_grab(channel->mpeg_video_hevc_i_frame_qp, true);
+ v4l2_ctrl_grab(channel->mpeg_video_hevc_max_qp, true);
+ v4l2_ctrl_grab(channel->mpeg_video_hevc_min_qp, true);
+ v4l2_ctrl_grab(channel->mpeg_video_hevc_p_frame_qp, true);
+ v4l2_ctrl_grab(channel->mpeg_video_hevc_b_frame_qp, true);
+
v4l2_ctrl_grab(channel->mpeg_video_frame_rc_enable, true);
v4l2_ctrl_grab(channel->mpeg_video_bitrate_mode, true);
v4l2_ctrl_grab(channel->mpeg_video_bitrate, true);
@@ -2113,8 +2489,13 @@ static void allegro_channel_adjust(struct allegro_channel *channel)
channel->sizeimage_encoded =
estimate_stream_size(channel->width, channel->height);
- ctrl = channel->mpeg_video_h264_level;
- min = select_minimum_h264_level(channel->width, channel->height);
+ if (codec == V4L2_PIX_FMT_H264) {
+ ctrl = channel->mpeg_video_h264_level;
+ min = select_minimum_h264_level(channel->width, channel->height);
+ } else {
+ ctrl = channel->mpeg_video_hevc_level;
+ min = select_minimum_hevc_level(channel->width, channel->height);
+ }
if (ctrl->minimum > min)
v4l2_dbg(1, debug, &dev->v4l2_dev,
"%s.minimum: %lld -> %lld\n",
@@ -2125,7 +2506,10 @@ static void allegro_channel_adjust(struct allegro_channel *channel)
v4l2_ctrl_unlock(ctrl);
ctrl = channel->mpeg_video_bitrate;
- max = h264_maximum_bitrate(v4l2_ctrl_g_ctrl(channel->mpeg_video_h264_level));
+ if (codec == V4L2_PIX_FMT_H264)
+ max = h264_maximum_bitrate(v4l2_ctrl_g_ctrl(channel->mpeg_video_h264_level));
+ else
+ max = hevc_maximum_bitrate(v4l2_ctrl_g_ctrl(channel->mpeg_video_hevc_level));
if (ctrl->maximum < max)
v4l2_dbg(1, debug, &dev->v4l2_dev,
"%s: maximum: %lld -> %lld\n",
@@ -2156,21 +2540,51 @@ static void allegro_channel_adjust(struct allegro_channel *channel)
v4l2_ctrl_activate(channel->mpeg_video_h264_b_frame_qp,
codec == V4L2_PIX_FMT_H264);
- channel->log2_max_frame_num = LOG2_MAX_FRAME_NUM;
+ v4l2_ctrl_activate(channel->mpeg_video_hevc_profile,
+ codec == V4L2_PIX_FMT_HEVC);
+ v4l2_ctrl_activate(channel->mpeg_video_hevc_level,
+ codec == V4L2_PIX_FMT_HEVC);
+ v4l2_ctrl_activate(channel->mpeg_video_hevc_tier,
+ codec == V4L2_PIX_FMT_HEVC);
+ v4l2_ctrl_activate(channel->mpeg_video_hevc_i_frame_qp,
+ codec == V4L2_PIX_FMT_HEVC);
+ v4l2_ctrl_activate(channel->mpeg_video_hevc_max_qp,
+ codec == V4L2_PIX_FMT_HEVC);
+ v4l2_ctrl_activate(channel->mpeg_video_hevc_min_qp,
+ codec == V4L2_PIX_FMT_HEVC);
+ v4l2_ctrl_activate(channel->mpeg_video_hevc_p_frame_qp,
+ codec == V4L2_PIX_FMT_HEVC);
+ v4l2_ctrl_activate(channel->mpeg_video_hevc_b_frame_qp,
+ codec == V4L2_PIX_FMT_HEVC);
+
+ if (codec == V4L2_PIX_FMT_H264)
+ channel->log2_max_frame_num = LOG2_MAX_FRAME_NUM;
channel->temporal_mvp_enable = true;
-
- channel->dbf_ovr_en = true;
+ channel->dbf_ovr_en = (codec == V4L2_PIX_FMT_H264);
+ channel->enable_deblocking_filter_override = (codec == V4L2_PIX_FMT_HEVC);
+ channel->enable_reordering = (codec == V4L2_PIX_FMT_HEVC);
channel->enable_loop_filter_across_tiles = true;
channel->enable_loop_filter_across_slices = true;
- channel->b_hrz_me_range = 8;
- channel->b_vrt_me_range = 8;
- channel->p_hrz_me_range = 16;
- channel->p_vrt_me_range = 16;
- channel->max_cu_size = ilog2(16);
- channel->min_cu_size = ilog2(8);
- channel->max_tu_size = ilog2(4);
- channel->min_tu_size = ilog2(4);
+ if (codec == V4L2_PIX_FMT_H264) {
+ channel->b_hrz_me_range = 8;
+ channel->b_vrt_me_range = 8;
+ channel->p_hrz_me_range = 16;
+ channel->p_vrt_me_range = 16;
+ channel->max_cu_size = ilog2(16);
+ channel->min_cu_size = ilog2(8);
+ channel->max_tu_size = ilog2(4);
+ channel->min_tu_size = ilog2(4);
+ } else {
+ channel->b_hrz_me_range = 16;
+ channel->b_vrt_me_range = 16;
+ channel->p_hrz_me_range = 32;
+ channel->p_vrt_me_range = 32;
+ channel->max_cu_size = ilog2(32);
+ channel->min_cu_size = ilog2(8);
+ channel->max_tu_size = ilog2(32);
+ channel->min_tu_size = ilog2(4);
+ }
channel->max_transfo_depth_intra = 1;
channel->max_transfo_depth_inter = 1;
}
@@ -2525,6 +2939,51 @@ static int allegro_open(struct file *file)
&allegro_ctrl_ops,
V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP,
0, 51, 1, 30);
+
+ channel->mpeg_video_hevc_profile =
+ v4l2_ctrl_new_std_menu(handler,
+ &allegro_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_HEVC_PROFILE,
+ V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, 0x0,
+ V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN);
+ channel->mpeg_video_hevc_level =
+ v4l2_ctrl_new_std_menu(handler,
+ &allegro_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_HEVC_LEVEL,
+ V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1, 0x0,
+ V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1);
+ channel->mpeg_video_hevc_tier =
+ v4l2_ctrl_new_std_menu(handler,
+ &allegro_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_HEVC_TIER,
+ V4L2_MPEG_VIDEO_HEVC_TIER_HIGH, 0x0,
+ V4L2_MPEG_VIDEO_HEVC_TIER_MAIN);
+ channel->mpeg_video_hevc_i_frame_qp =
+ v4l2_ctrl_new_std(handler,
+ &allegro_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP,
+ 0, 51, 1, 30);
+ channel->mpeg_video_hevc_max_qp =
+ v4l2_ctrl_new_std(handler,
+ &allegro_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP,
+ 0, 51, 1, 51);
+ channel->mpeg_video_hevc_min_qp =
+ v4l2_ctrl_new_std(handler,
+ &allegro_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
+ 0, 51, 1, 0);
+ channel->mpeg_video_hevc_p_frame_qp =
+ v4l2_ctrl_new_std(handler,
+ &allegro_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP,
+ 0, 51, 1, 30);
+ channel->mpeg_video_hevc_b_frame_qp =
+ v4l2_ctrl_new_std(handler,
+ &allegro_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP,
+ 0, 51, 1, 30);
+
channel->mpeg_video_frame_rc_enable =
v4l2_ctrl_new_std(handler,
&allegro_ctrl_ops,
@@ -2537,10 +2996,17 @@ static int allegro_open(struct file *file)
V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
V4L2_MPEG_VIDEO_BITRATE_MODE_CBR);
- bitrate_max = h264_maximum_bitrate(V4L2_MPEG_VIDEO_H264_LEVEL_5_1);
- bitrate_def = h264_maximum_bitrate(V4L2_MPEG_VIDEO_H264_LEVEL_5_1);
- cpb_size_max = h264_maximum_cpb_size(V4L2_MPEG_VIDEO_H264_LEVEL_5_1);
- cpb_size_def = h264_maximum_cpb_size(V4L2_MPEG_VIDEO_H264_LEVEL_5_1);
+ if (channel->codec == V4L2_PIX_FMT_H264) {
+ bitrate_max = h264_maximum_bitrate(V4L2_MPEG_VIDEO_H264_LEVEL_5_1);
+ bitrate_def = h264_maximum_bitrate(V4L2_MPEG_VIDEO_H264_LEVEL_5_1);
+ cpb_size_max = h264_maximum_cpb_size(V4L2_MPEG_VIDEO_H264_LEVEL_5_1);
+ cpb_size_def = h264_maximum_cpb_size(V4L2_MPEG_VIDEO_H264_LEVEL_5_1);
+ } else {
+ bitrate_max = hevc_maximum_bitrate(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1);
+ bitrate_def = hevc_maximum_bitrate(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1);
+ cpb_size_max = hevc_maximum_cpb_size(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1);
+ cpb_size_def = hevc_maximum_cpb_size(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1);
+ }
channel->mpeg_video_bitrate = v4l2_ctrl_new_std(handler,
&allegro_ctrl_ops,
V4L2_CID_MPEG_VIDEO_BITRATE,
@@ -2644,9 +3110,12 @@ static int allegro_enum_fmt_vid(struct file *file, void *fh,
f->pixelformat = V4L2_PIX_FMT_NV12;
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- if (f->index >= 1)
+ if (f->index >= 2)
return -EINVAL;
- f->pixelformat = V4L2_PIX_FMT_H264;
+ if (f->index == 0)
+ f->pixelformat = V4L2_PIX_FMT_H264;
+ if (f->index == 1)
+ f->pixelformat = V4L2_PIX_FMT_HEVC;
break;
default:
return -EINVAL;
@@ -2685,7 +3154,10 @@ static int allegro_try_fmt_vid_cap(struct file *file, void *fh,
f->fmt.pix.height = clamp_t(__u32, f->fmt.pix.height,
ALLEGRO_HEIGHT_MIN, ALLEGRO_HEIGHT_MAX);
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_H264;
+ if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_HEVC &&
+ f->fmt.pix.pixelformat != V4L2_PIX_FMT_H264)
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_H264;
+
f->fmt.pix.bytesperline = 0;
f->fmt.pix.sizeimage =
estimate_stream_size(f->fmt.pix.width, f->fmt.pix.height);
@@ -2832,6 +3304,7 @@ static int allegro_enum_framesizes(struct file *file, void *fh,
struct v4l2_frmsizeenum *fsize)
{
switch (fsize->pixel_format) {
+ case V4L2_PIX_FMT_HEVC:
case V4L2_PIX_FMT_H264:
case V4L2_PIX_FMT_NV12:
break;
diff --git a/drivers/media/platform/allegro-dvt/allegro-mail.c b/drivers/media/platform/allegro-dvt/allegro-mail.c
index 5dbc1c029020..7e08c5050f2e 100644
--- a/drivers/media/platform/allegro-dvt/allegro-mail.c
+++ b/drivers/media/platform/allegro-dvt/allegro-mail.c
@@ -67,12 +67,16 @@ static inline u32 settings_get_mcu_codec(struct create_channel_param *param)
if (version < MCU_MSG_VERSION_2019_2) {
switch (pixelformat) {
+ case V4L2_PIX_FMT_HEVC:
+ return 2;
case V4L2_PIX_FMT_H264:
default:
return 1;
}
} else {
switch (pixelformat) {
+ case V4L2_PIX_FMT_HEVC:
+ return 1;
case V4L2_PIX_FMT_H264:
default:
return 0;
@@ -117,7 +121,9 @@ allegro_encode_config_blob(u32 *dst, struct create_channel_param *param)
dst[i++] = val;
val = 0;
+ val |= param->enable_reordering ? BIT(0) : 0;
val |= param->dbf_ovr_en ? BIT(2) : 0;
+ val |= param->override_lf ? BIT(12) : 0;
dst[i++] = val;
if (version >= MCU_MSG_VERSION_2019_2) {
diff --git a/drivers/media/platform/allegro-dvt/allegro-mail.h b/drivers/media/platform/allegro-dvt/allegro-mail.h
index f7485cf78c4f..2c7bc509eac3 100644
--- a/drivers/media/platform/allegro-dvt/allegro-mail.h
+++ b/drivers/media/platform/allegro-dvt/allegro-mail.h
@@ -65,6 +65,7 @@ struct create_channel_param {
u32 temporal_mvp_enable;
u32 enable_reordering;
u32 dbf_ovr_en;
+ u32 override_lf;
u32 num_ref_idx_l0;
u32 num_ref_idx_l1;
u32 custom_lda;