From 1d5134801ecef1ec7cad5485abc8d1cd43b62c74 Mon Sep 17 00:00:00 2001 From: Ayoung Sim Date: Mon, 16 Jul 2018 16:29:52 +0900 Subject: [PATCH] [COMMON] media: mfc: support HDR10 plus SEI decoding Change-Id: Ie879b6b7824c71baf553bd2afe16efa82dbd9d62 Signed-off-by: Ayoung Sim --- .../platform/exynos/mfc/exynos_mfc_media.h | 2 + drivers/media/platform/exynos/mfc/mfc.c | 20 ++- drivers/media/platform/exynos/mfc/mfc_cmd.c | 2 + .../media/platform/exynos/mfc/mfc_common.h | 1 + .../platform/exynos/mfc/mfc_data_struct.h | 89 +++++++++- .../platform/exynos/mfc/mfc_dec_internal.h | 9 + .../media/platform/exynos/mfc/mfc_dec_v4l2.c | 21 +++ drivers/media/platform/exynos/mfc/mfc_isr.c | 12 ++ drivers/media/platform/exynos/mfc/mfc_nal_q.c | 110 +++++++++++- .../media/platform/exynos/mfc/mfc_reg_api.c | 164 ++++++++++++++++++ .../media/platform/exynos/mfc/mfc_reg_api.h | 6 + drivers/media/platform/exynos/mfc/mfc_regs.h | 34 ++++ 12 files changed, 462 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/exynos/mfc/exynos_mfc_media.h b/drivers/media/platform/exynos/mfc/exynos_mfc_media.h index 02d26f4bfec1..f75062c8a09c 100644 --- a/drivers/media/platform/exynos/mfc/exynos_mfc_media.h +++ b/drivers/media/platform/exynos/mfc/exynos_mfc_media.h @@ -258,6 +258,8 @@ enum v4l2_mpeg_video_hevc_hierarchical_coding_type { (V4L2_CID_MPEG_MFC_BASE + 107) #define V4L2_CID_MPEG_MFC_CONFIG_QP_ENABLE \ (V4L2_CID_MPEG_MFC_BASE + 108) +#define V4L2_CID_MPEG_MFC_HDR_USER_SHARED_HANDLE \ + (V4L2_CID_MPEG_MFC_BASE + 109) /* CIDs for HEVC encoding. Number gaps are for compatibility */ diff --git a/drivers/media/platform/exynos/mfc/mfc.c b/drivers/media/platform/exynos/mfc/mfc.c index 659b4f7039a2..192c8265f4cc 100644 --- a/drivers/media/platform/exynos/mfc/mfc.c +++ b/drivers/media/platform/exynos/mfc/mfc.c @@ -101,6 +101,8 @@ static void __mfc_deinit_dec_ctx(struct mfc_ctx *ctx) mfc_delete_queue(&ctx->ref_buf_queue); mfc_mem_cleanup_user_shared_handle(ctx, &dec->sh_handle); + mfc_mem_cleanup_user_shared_handle(ctx, &dec->sh_handle_hdr); + kfree(dec->hdr10_plus_info); kfree(dec->ref_info); kfree(dec); } @@ -162,6 +164,8 @@ static int __mfc_init_dec_ctx(struct mfc_ctx *ctx) dec->is_dpb_full = 0; mfc_cleanup_assigned_fd(ctx); mfc_clear_assigned_dpb(ctx); + + /* sh_handle: released dpb info */ dec->sh_handle.fd = -1; dec->ref_info = kzalloc( (sizeof(struct dec_dpb_ref_info) * MFC_MAX_DPBS), GFP_KERNEL); @@ -173,6 +177,16 @@ static int __mfc_init_dec_ctx(struct mfc_ctx *ctx) for (i = 0; i < MFC_MAX_BUFFERS; i++) dec->ref_info[i].dpb[0].fd[0] = MFC_INFO_INIT_FD; + /* sh_handle: HDR10+ HEVC SEI meta */ + dec->sh_handle_hdr.fd = -1; + dec->hdr10_plus_info = kzalloc( + (sizeof(struct hdr10_plus_meta) * MFC_MAX_DPBS), GFP_KERNEL); + if (!dec->hdr10_plus_info) { + mfc_err_dev("[HDR+] failed to allocate HDR10+ information data\n"); + ret = -ENOMEM; + goto fail_dec_init; + } + /* Init videobuf2 queue for OUTPUT */ ctx->vq_src.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; ctx->vq_src.drv_priv = ctx; @@ -972,6 +986,7 @@ static void __mfc_parse_dt(struct device_node *np, struct mfc_dev *mfc) of_property_read_u32_array(np, "static_info_dec", &pdata->static_info_dec.support, 2); of_property_read_u32_array(np, "color_aspect_enc", &pdata->color_aspect_enc.support, 2); of_property_read_u32_array(np, "static_info_enc", &pdata->static_info_enc.support, 2); + of_property_read_u32_array(np, "hdr10_plus", &pdata->hdr10_plus.support, 2); /* Default 10bit format for decoding */ of_property_read_u32(np, "P010_decoding", &pdata->P010_decoding); @@ -981,6 +996,9 @@ static void __mfc_parse_dt(struct device_node *np, struct mfc_dev *mfc) of_property_read_u32(np, "support_422", &pdata->support_422); of_property_read_u32(np, "support_rgb", &pdata->support_rgb); + /* HDR10+ num max window */ + of_property_read_u32(np, "max_hdr_win", &pdata->max_hdr_win); + /* Encoder default parameter */ of_property_read_u32(np, "enc_param_num", &pdata->enc_param_num); if (pdata->enc_param_num) { @@ -1634,7 +1652,7 @@ static const struct dev_pm_ops mfc_pm_ops = { struct mfc_ctx_buf_size mfc_ctx_buf_size = { .dev_ctx = PAGE_ALIGN(0x7800), /* 30KB */ .h264_dec_ctx = PAGE_ALIGN(0x200000), /* 1.6MB */ - .other_dec_ctx = PAGE_ALIGN(0x7800), /* 30KB */ + .other_dec_ctx = PAGE_ALIGN(0xC800), /* 50KB */ .h264_enc_ctx = PAGE_ALIGN(0x19000), /* 100KB */ .hevc_enc_ctx = PAGE_ALIGN(0xA000), /* 40KB */ .other_enc_ctx = PAGE_ALIGN(0x6400), /* 25KB */ diff --git a/drivers/media/platform/exynos/mfc/mfc_cmd.c b/drivers/media/platform/exynos/mfc/mfc_cmd.c index 5a0a1e79b5e1..c9278aa86b1f 100644 --- a/drivers/media/platform/exynos/mfc/mfc_cmd.c +++ b/drivers/media/platform/exynos/mfc/mfc_cmd.c @@ -229,6 +229,8 @@ void mfc_cmd_dec_seq_header(struct mfc_ctx *ctx) reg |= (0x1 << MFC_REG_D_SEI_ENABLE_MASTERING_DISPLAY_SHIFT); } reg |= (0x1 << MFC_REG_D_SEI_ENABLE_RECOVERY_PARSING_SHIFT); + if (MFC_FEATURE_SUPPORT(dev, dev->pdata->hdr10_plus)) + reg |= (0x1 << MFC_REG_D_SEI_ENABLE_ST_2094_40_SEI_SHIFT); MFC_WRITEL(reg, MFC_REG_D_SEI_ENABLE); mfc_debug(2, "SEI enable was set, 0x%x\n", MFC_READL(MFC_REG_D_SEI_ENABLE)); diff --git a/drivers/media/platform/exynos/mfc/mfc_common.h b/drivers/media/platform/exynos/mfc/mfc_common.h index 20bec22dfb65..497296218b37 100644 --- a/drivers/media/platform/exynos/mfc/mfc_common.h +++ b/drivers/media/platform/exynos/mfc/mfc_common.h @@ -161,6 +161,7 @@ #define DEC_SET_DYNAMIC_DPB (1 << 1) #define DEC_SET_LAST_FRAME_INFO (1 << 2) #define DEC_SET_SKYPE_FLAG (1 << 3) +#define DEC_SET_HDR10_PLUS (1 << 4) /* Extra information for Encoder */ #define ENC_SET_RGB_INPUT (1 << 0) diff --git a/drivers/media/platform/exynos/mfc/mfc_data_struct.h b/drivers/media/platform/exynos/mfc/mfc_data_struct.h index 504765aa5b61..d5d37927f134 100644 --- a/drivers/media/platform/exynos/mfc/mfc_data_struct.h +++ b/drivers/media/platform/exynos/mfc/mfc_data_struct.h @@ -48,6 +48,11 @@ #define HWFC_MAX_BUF 10 #define OTF_MAX_BUF 30 +#define HDR_MAX_WINDOWS 3 +#define HDR_MAX_SCL 3 +#define HDR_MAX_DISTRIBUTION 15 +#define HDR_MAX_BEZIER_CURVES 15 + /* Maximum number of temporal layers */ #define VIDEO_MAX_TEMPORAL_LAYERS 7 @@ -177,6 +182,7 @@ enum mfc_vb_flag { MFC_FLAG_HDR_COLOUR_DESC = 3, MFC_FLAG_HDR_VIDEO_SIGNAL_TYPE = 4, MFC_FLAG_BLACKBAR_DETECT = 5, + MFC_FLAG_HDR_PLUS = 6, MFC_FLAG_CSD = 29, MFC_FLAG_EMPTY_DATA = 30, MFC_FLAG_LAST_FRAME = 31, @@ -427,6 +433,8 @@ struct mfc_platdata { unsigned int support_10bit; unsigned int support_422; unsigned int support_rgb; + /* HDR10+ */ + unsigned int max_hdr_win; #ifdef CONFIG_MFC_USE_BUS_DEVFREQ /* QoS */ unsigned int num_qos_steps; @@ -446,6 +454,7 @@ struct mfc_platdata { struct mfc_feature static_info_dec; struct mfc_feature color_aspect_enc; struct mfc_feature static_info_enc; + struct mfc_feature hdr10_plus; #ifdef CONFIG_EXYNOS_BTS struct mfc_bw_info mfc_bw_info; #endif @@ -465,15 +474,16 @@ struct mfc_platdata { }; /************************ NAL_Q data structure ************************/ -#define NAL_Q_IN_ENTRY_SIZE 256 -#define NAL_Q_OUT_ENTRY_SIZE 256 +#define NAL_Q_IN_ENTRY_SIZE 512 +#define NAL_Q_OUT_ENTRY_SIZE 512 #define NAL_Q_IN_DEC_STR_SIZE 112 #define NAL_Q_IN_ENC_STR_SIZE 204 -#define NAL_Q_OUT_DEC_STR_SIZE 248 +#define NAL_Q_OUT_DEC_STR_SIZE 376 #define NAL_Q_OUT_ENC_STR_SIZE 64 +#define NAL_Q_DUMP_MAX_STR_SIZE 376 -/* 256*128(max instance 32 * slot 4) = 32 kbytes */ +/* 512*128(max instance 32 * slot 4) = 64 kbytes */ #define NAL_Q_IN_QUEUE_SIZE 128 #define NAL_Q_OUT_QUEUE_SIZE 128 @@ -606,8 +616,11 @@ typedef struct __DecoderOutputStr { int MasteringDisplayColourVolumeSei3; int MasteringDisplayColourVolumeSei4; int MasteringDisplayColourVolumeSei5; + int FirstPlaneDpbSize; + int SecondPlaneDpbSize; + int St2094_40sei[30]; char reserved[NAL_Q_OUT_ENTRY_SIZE - NAL_Q_OUT_DEC_STR_SIZE]; -} DecoderOutputStr; /* 62*4 = 248 bytes */ +} DecoderOutputStr; /* 94*4 = 376 bytes */ typedef struct __EncoderOutputStr { int StartCode; /* 0xBBBBBBBB; Encoder output structure marker */ @@ -1224,6 +1237,70 @@ struct mfc_raw_info { unsigned int total_plane_size; }; +/* HDR10+ ST 2094 40 Metadata HEVC SEI Message */ +struct hdr10_plus_meta_per_win { + unsigned int maxscl[HDR_MAX_SCL]; + unsigned int average_maxrgb; + unsigned char num_distribution_maxrgb_percentiles; + unsigned char distribution_maxrgb_percentages[HDR_MAX_DISTRIBUTION]; + unsigned int distribution_maxrgb_percentiles[HDR_MAX_DISTRIBUTION]; + unsigned int fraction_bright_pixels; + + unsigned short tone_mapping_flag; + unsigned short knee_point_x; + unsigned short knee_point_y; + unsigned short num_bezier_curve_anchors; + unsigned short bezier_curve_anchors[HDR_MAX_BEZIER_CURVES]; + + unsigned char color_saturation_mapping_flag; + unsigned char color_saturation_weight; + + /* + * This field is reserved for ST2094-40 SEI below or the others + * window_upper_left_corner_x + * window_upper_left_corner_y + * window_lower_right_corner_x + * window_lower_right_corner_y + * center_of_ellipse_x + * center_of_ellipse_y + * rotation_angle + * semimajor_axis_internal_ellipse + * semimajor_axis_external_ellipse + * semiminor_axis_external_ellipse + * overlap_process_option + */ + unsigned int reserved[11]; +}; + +struct hdr10_plus_meta { + unsigned int valid; + + unsigned char t35_country_code; + unsigned short t35_terminal_provider_code; + unsigned short t35_terminal_provider_oriented_code; + unsigned char application_identifier; + unsigned short application_version; + unsigned char num_windows; + + unsigned int target_maximum_luminance; + unsigned char target_actual_peak_luminance_flag; + unsigned char num_rows_target_luminance; + unsigned char num_cols_target_luminance; + + unsigned char mastering_actual_peak_luminance_flag; + unsigned char num_rows_mastering_luminance; + unsigned char num_cols_mastering_luminance; + + struct hdr10_plus_meta_per_win win_info[HDR_MAX_WINDOWS]; + + /* + * This field is reserved for ST2094-40 SEI below or the others + * targeted_system_display_actual_peak_luminance[rows][cols] + * mastering_display_actual_peak_luminance[rows][cols] + */ + unsigned int reserved[11]; +}; + struct mfc_timestamp { struct list_head list; struct timeval timestamp; @@ -1275,6 +1352,8 @@ struct mfc_dec { struct dec_dpb_ref_info *ref_info; int assigned_fd[MFC_MAX_DPBS]; struct mfc_user_shared_handle sh_handle; + struct mfc_user_shared_handle sh_handle_hdr; + struct hdr10_plus_meta *hdr10_plus_info; int has_multiframe; diff --git a/drivers/media/platform/exynos/mfc/mfc_dec_internal.h b/drivers/media/platform/exynos/mfc/mfc_dec_internal.h index e906d5e131ba..cdf8cc6952eb 100644 --- a/drivers/media/platform/exynos/mfc/mfc_dec_internal.h +++ b/drivers/media/platform/exynos/mfc/mfc_dec_internal.h @@ -535,6 +535,15 @@ static struct v4l2_queryctrl controls[] = { .step = 1, .default_value = 0, }, + { + .id = V4L2_CID_MPEG_MFC_HDR_USER_SHARED_HANDLE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Dynamic HDR10+ SEI metadata", + .minimum = INT_MIN, + .maximum = INT_MAX, + .step = 1, + .default_value = 0, + }, }; #define NUM_CTRLS ARRAY_SIZE(controls) diff --git a/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c b/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c index 6f43039edad5..3533ea28c071 100644 --- a/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c +++ b/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c @@ -739,6 +739,7 @@ static int mfc_dec_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data); struct mfc_dec *dec = ctx->dec_priv; struct dec_dpb_ref_info *dstBuf, *srcBuf; + struct hdr10_plus_meta *dst_sei_meta, *src_sei_meta; int ret; int ncount = 0; @@ -775,6 +776,14 @@ static int mfc_dec_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) memcpy(dstBuf, srcBuf, sizeof(struct dec_dpb_ref_info)); dstBuf->index = buf->index; } + + /* Memcpy from dec->hdr10_plus_info to shared memory */ + src_sei_meta = &dec->hdr10_plus_info[buf->index]; + if (dec->sh_handle_hdr.vaddr != NULL) { + dst_sei_meta = (struct hdr10_plus_meta *) + dec->sh_handle_hdr.vaddr + buf->index; + memcpy(dst_sei_meta, src_sei_meta, sizeof(struct hdr10_plus_meta)); + } } mfc_debug_leave(); return ret; @@ -865,6 +874,9 @@ static int __mfc_dec_ext_info(struct mfc_ctx *ctx) if (MFC_FEATURE_SUPPORT(dev, dev->pdata->skype)) val |= DEC_SET_SKYPE_FLAG; + if (MFC_FEATURE_SUPPORT(dev, dev->pdata->hdr10_plus)) + val |= DEC_SET_HDR10_PLUS; + mfc_debug(5, "[CTRLS] ext info val: %#x\n", val); return val; @@ -1087,6 +1099,15 @@ static int mfc_dec_s_ctrl(struct file *file, void *priv, case V4L2_CID_MPEG_VIDEO_BLACK_BAR_DETECT: dec->detect_black_bar = ctrl->value; break; + case V4L2_CID_MPEG_MFC_HDR_USER_SHARED_HANDLE: + dec->sh_handle_hdr.fd = ctrl->value; + if (mfc_mem_get_user_shared_handle(ctx, &dec->sh_handle_hdr)) { + dec->sh_handle_hdr.fd = -1; + return -EINVAL; + } + mfc_debug(2, "[MEMINFO][HDR+] shared handle fd: %d, vaddr: 0x%p\n", + dec->sh_handle_hdr.fd, dec->sh_handle_hdr.vaddr); + break; default: list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) { if (!(ctx_ctrl->type & MFC_CTRL_TYPE_SET)) diff --git a/drivers/media/platform/exynos/mfc/mfc_isr.c b/drivers/media/platform/exynos/mfc/mfc_isr.c index 0ccdf8566196..afc3ea4bfae2 100644 --- a/drivers/media/platform/exynos/mfc/mfc_isr.c +++ b/drivers/media/platform/exynos/mfc/mfc_isr.c @@ -225,6 +225,7 @@ static void __mfc_handle_frame_output_del(struct mfc_ctx *ctx, unsigned int dst_frame_status; unsigned int is_video_signal_type = 0, is_colour_description = 0; unsigned int is_content_light = 0, is_display_colour = 0; + unsigned int is_hdr10_plus_sei = 0; unsigned int i, index; if (MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_dec)) { @@ -237,6 +238,9 @@ static void __mfc_handle_frame_output_del(struct mfc_ctx *ctx, is_display_colour = mfc_get_sei_avail_mastering_display(); } + if (MFC_FEATURE_SUPPORT(dev, dev->pdata->hdr10_plus)) + is_hdr10_plus_sei = mfc_get_sei_avail_st_2094_40(); + if (MFC_FEATURE_SUPPORT(dev, dev->pdata->black_bar) && dec->detect_black_bar) __mfc_handle_black_bar_info(dev, ctx); else @@ -299,6 +303,14 @@ static void __mfc_handle_frame_output_del(struct mfc_ctx *ctx, mfc_debug(3, "[BLACKBAR] black bar detected\n"); } + if (is_hdr10_plus_sei) { + mfc_get_hdr_plus_info(ctx, &dec->hdr10_plus_info[index]); + mfc_set_vb_flag(ref_mb, MFC_FLAG_HDR_PLUS); + mfc_debug(2, "[HDR+] HDR10 plus dyanmic SEI metadata parsed\n"); + } else { + dec->hdr10_plus_info[index].valid = 0; + } + if (ctx->src_fmt->mem_planes == 1) { vb2_set_plane_payload(&ref_mb->vb.vb2_buf, 0, raw->total_plane_size); diff --git a/drivers/media/platform/exynos/mfc/mfc_nal_q.c b/drivers/media/platform/exynos/mfc/mfc_nal_q.c index 3afcfb2870d5..9a1b16d61971 100644 --- a/drivers/media/platform/exynos/mfc/mfc_nal_q.c +++ b/drivers/media/platform/exynos/mfc/mfc_nal_q.c @@ -551,6 +551,98 @@ static void __mfc_nal_q_set_slice_mode(struct mfc_ctx *ctx, EncoderInputStr *pIn } } +static void __mfc_nal_q_get_hdr_plus_info(struct mfc_ctx *ctx, DecoderOutputStr *pOutStr, + struct hdr10_plus_meta *sei_meta) +{ + struct mfc_dev *dev = ctx->dev; + unsigned int upper_value, lower_value; + int num_win, num_distribution; + int i, j; + + sei_meta->valid = 1; + + /* iru_t_t35 */ + sei_meta->t35_country_code = pOutStr->St2094_40sei[0] & 0xFF; + sei_meta->t35_terminal_provider_code = pOutStr->St2094_40sei[0] >> 8 & 0xFF; + upper_value = pOutStr->St2094_40sei[0] >> 24 & 0xFF; + lower_value = pOutStr->St2094_40sei[1] & 0xFF; + sei_meta->t35_terminal_provider_oriented_code = (upper_value << 8) | lower_value; + + /* application */ + sei_meta->application_identifier = pOutStr->St2094_40sei[1] >> 8 & 0xFF; + sei_meta->application_version = pOutStr->St2094_40sei[1] >> 16 & 0xFF; + + /* window information */ + sei_meta->num_windows = pOutStr->St2094_40sei[1] >> 24 & 0x3; + num_win = sei_meta->num_windows; + if (num_win > dev->pdata->max_hdr_win) { + mfc_err_ctx("NAL Q:[HDR+] num_window(%d) is exceeded supported max_num_window(%d)\n", + num_win, dev->pdata->max_hdr_win); + num_win = dev->pdata->max_hdr_win; + } + + /* luminance */ + sei_meta->target_maximum_luminance = pOutStr->St2094_40sei[2] & 0x7FFFFFF; + sei_meta->target_actual_peak_luminance_flag = pOutStr->St2094_40sei[2] >> 27 & 0x1; + sei_meta->mastering_actual_peak_luminance_flag = pOutStr->St2094_40sei[22] >> 10 & 0x1; + + /* per window setting */ + for (i = 0; i < num_win; i++) { + /* scl */ + for (j = 0; j < HDR_MAX_SCL; j++) { + sei_meta->win_info[i].maxscl[j] = + pOutStr->St2094_40sei[3 + j] & 0x1FFFF; + } + sei_meta->win_info[i].average_maxrgb = + pOutStr->St2094_40sei[6] & 0x1FFFF; + + /* distribution */ + sei_meta->win_info[i].num_distribution_maxrgb_percentiles = + pOutStr->St2094_40sei[6] >> 17 & 0xF; + num_distribution = sei_meta->win_info[i].num_distribution_maxrgb_percentiles; + for (j = 0; j < num_distribution; j++) { + sei_meta->win_info[i].distribution_maxrgb_percentages[j] = + pOutStr->St2094_40sei[7 + j] & 0x7F; + sei_meta->win_info[i].distribution_maxrgb_percentiles[j] = + pOutStr->St2094_40sei[7 + j] >> 7 & 0x1FFFF; + } + + /* bright pixels */ + sei_meta->win_info[i].fraction_bright_pixels = + pOutStr->St2094_40sei[22] & 0x3FF; + + /* tone mapping */ + sei_meta->win_info[i].tone_mapping_flag = + pOutStr->St2094_40sei[22] >> 11 & 0x1; + if (sei_meta->win_info[i].tone_mapping_flag) { + sei_meta->win_info[i].knee_point_x = + pOutStr->St2094_40sei[23] & 0xFFF; + sei_meta->win_info[i].knee_point_y = + pOutStr->St2094_40sei[23] >> 12 & 0xFFF; + sei_meta->win_info[i].num_bezier_curve_anchors = + pOutStr->St2094_40sei[23] >> 24 & 0xF; + for (j = 0; j < HDR_MAX_BEZIER_CURVES / 3; j++) { + sei_meta->win_info[i].bezier_curve_anchors[j * 3] = + pOutStr->St2094_40sei[24 + j] & 0x3FF; + sei_meta->win_info[i].bezier_curve_anchors[j * 3 + 1] = + pOutStr->St2094_40sei[24 + j] >> 10 & 0x3FF; + sei_meta->win_info[i].bezier_curve_anchors[j * 3 + 2] = + pOutStr->St2094_40sei[24 + j] >> 20 & 0x3FF; + } + } + + /* color saturation */ + sei_meta->win_info[i].color_saturation_mapping_flag = + pOutStr->St2094_40sei[29] & 0x1; + if (sei_meta->win_info[i].color_saturation_mapping_flag) + sei_meta->win_info[i].color_saturation_weight = + pOutStr->St2094_40sei[29] >> 1 & 0x3F; + } + + if (debug_level >= 5) + mfc_print_dec_hdr_plus_info(ctx, index); +} + static int __mfc_nal_q_run_in_buf_enc(struct mfc_ctx *ctx, EncoderInputStr *pInStr) { struct mfc_dev *dev = ctx->dev; @@ -1140,6 +1232,7 @@ static void __mfc_nal_q_handle_frame_output_del(struct mfc_ctx *ctx, unsigned int dst_frame_status; unsigned int is_video_signal_type = 0, is_colour_description = 0; unsigned int is_content_light = 0, is_display_colour = 0; + unsigned int is_hdr10_plus_sei = 0; unsigned int disp_err; int i, index; @@ -1159,6 +1252,9 @@ static void __mfc_nal_q_handle_frame_output_del(struct mfc_ctx *ctx, & MFC_REG_D_SEI_AVAIL_MASTERING_DISPLAY_MASK); } + if (MFC_FEATURE_SUPPORT(dev, dev->pdata->hdr10_plus)) + is_hdr10_plus_sei = ((pOutStr->SeiAvail >> MFC_REG_D_SEI_AVAIL_ST_2094_40_SHIFT) + & MFC_REG_D_SEI_AVAIL_ST_2094_40_MASK); if (dec->immediate_display == 1) { dspl_y_addr = pOutStr->DecodedAddr[0]; frame_type = pOutStr->DecodedFrameType & MFC_REG_DECODED_FRAME_MASK; @@ -1208,6 +1304,14 @@ static void __mfc_nal_q_handle_frame_output_del(struct mfc_ctx *ctx, mfc_debug(2, "[NALQ][HDR] color range parsed\n"); } + if (is_hdr10_plus_sei) { + __mfc_nal_q_get_hdr_plus_info(ctx, pOutStr, &dec->hdr10_plus_info[index]); + mfc_set_vb_flag(ref_mb, MFC_FLAG_HDR_PLUS); + mfc_debug(2, "[NALQ][HDR+] HDR10 plus dyanmic SEI metadata parsed\n"); + } else { + dec->hdr10_plus_info[index].valid = 0; + } + for (i = 0; i < raw->num_planes; i++) vb2_set_plane_payload(&ref_mb->vb.vb2_buf, i, raw->plane_size[i]); @@ -1680,7 +1784,8 @@ int mfc_nal_q_enqueue_in_buf(struct mfc_dev *dev, struct mfc_ctx *ctx, mfc_err_dev("[NAL-Q][DUMP][%s INPUT][c: %d] diff: %d, count: %d, exe: %d\n", ctx->type == MFCINST_ENCODER ? "ENC" : "DEC", dev->curr_ctx, input_diff, input_count, input_exe_count); - print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 32, 4, (int *)pStr, 256, false); + print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 32, 4, + (int *)pStr, NAL_Q_DUMP_MAX_STR_SIZE, false); printk("...\n"); } input_count++; @@ -1763,7 +1868,8 @@ EncoderOutputStr *mfc_nal_q_dequeue_out_buf(struct mfc_dev *dev, ctx->type == MFCINST_ENCODER ? "ENC" : "DEC", nal_q_out_handle->nal_q_ctx, output_diff, output_count, output_exe_count); - print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 32, 4, (int *)pStr, 256, false); + print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 32, 4, + (int *)pStr, NAL_Q_DUMP_MAX_STR_SIZE, false); printk("...\n"); } nal_q_out_handle->out_exe_count++; diff --git a/drivers/media/platform/exynos/mfc/mfc_reg_api.c b/drivers/media/platform/exynos/mfc/mfc_reg_api.c index 263c663dcc56..1c82ab926c78 100644 --- a/drivers/media/platform/exynos/mfc/mfc_reg_api.c +++ b/drivers/media/platform/exynos/mfc/mfc_reg_api.c @@ -514,3 +514,167 @@ void mfc_set_pixel_format(struct mfc_dev *dev, unsigned int format) mfc_debug(2, "[FRAME] pixel format: %d, mem_type_10bit for 10bit: %d (reg: %#x)\n", pix_val, mem_type_10bit, reg); } + +void mfc_print_dec_hdr_plus_info(struct mfc_ctx *ctx, int index) +{ + struct mfc_dev *dev = ctx->dev; + struct mfc_dec *dec = ctx->dec_priv; + struct hdr10_plus_meta *sei_meta; + int num_distribution; + int i, j; + + sei_meta = &dec->hdr10_plus_info[index]; + + mfc_debug(5, "[HDR+] ================================================================\n"); + mfc_debug(5, "[HDR+] valid: %#x\n", sei_meta->valid); + mfc_debug(5, "[HDR+] itu t35 country_code: %#x, provider_code %#x, oriented_code: %#x\n", + sei_meta->t35_country_code, sei_meta->t35_terminal_provider_code, + sei_meta->t35_terminal_provider_oriented_code); + mfc_debug(5, "[HDR+] application identifier: %#x, version: %#x, num_windows: %#x\n", + sei_meta->application_identifier, sei_meta->application_version, + sei_meta->num_windows); + mfc_debug(5, "[HDR+] target_maximum_luminance: %#x, target_actual_peak_luminance_flag %#x\n", + sei_meta->target_maximum_luminance, + sei_meta->target_actual_peak_luminance_flag); + mfc_debug(5, "[HDR+] mastering_actual_peak_luminance_flag %#x\n", + sei_meta->mastering_actual_peak_luminance_flag); + + for (i = 0; i < sei_meta->num_windows; i++) { + mfc_debug(5, "[HDR+] -------- window[%d] info --------\n", i); + for (j = 0; j < HDR_MAX_SCL; j++) + mfc_debug(5, "[HDR+] maxscl[%d] %#x\n", j, + sei_meta->win_info[i].maxscl[j]); + mfc_debug(5, "[HDR+] average_maxrgb %#x, num_distribution_maxrgb_percentiles %#x\n", + sei_meta->win_info[i].average_maxrgb, + sei_meta->win_info[i].num_distribution_maxrgb_percentiles); + num_distribution = sei_meta->win_info[i].num_distribution_maxrgb_percentiles; + for (j = 0; j < num_distribution; j++) + mfc_debug(5, "[HDR+] percentages[%d] %#x, percentiles[%d] %#x\n", j, + sei_meta->win_info[i].distribution_maxrgb_percentages[j], j, + sei_meta->win_info[i].distribution_maxrgb_percentiles[j]); + + mfc_debug(5, "[HDR+] fraction_bright_pixels %#x, tone_mapping_flag %#x\n", + sei_meta->win_info[i].fraction_bright_pixels, + sei_meta->win_info[i].tone_mapping_flag); + if (sei_meta->win_info[i].tone_mapping_flag) { + mfc_debug(5, "[HDR+] knee point x %#x, knee point y %#x\n", + sei_meta->win_info[i].knee_point_x, + sei_meta->win_info[i].knee_point_y); + mfc_debug(5, "[HDR+] num_bezier_curve_anchors %#x\n", + sei_meta->win_info[i].num_bezier_curve_anchors); + for (j = 0; j < HDR_MAX_BEZIER_CURVES / 3; j++) + mfc_debug(5, "[HDR+] anchors[%d] %#x, [%d] %#x, [%d] %#x\n", + j * 3, + sei_meta->win_info[i].bezier_curve_anchors[j * 3], + j * 3 + 1, + sei_meta->win_info[i].bezier_curve_anchors[j * 3 + 1], + j * 3 + 2, + sei_meta->win_info[i].bezier_curve_anchors[j * 3 + 2]); + } + mfc_debug(5, "[HDR+] color_saturation mapping_flag %#x, weight: %#x\n", + sei_meta->win_info[i].color_saturation_mapping_flag, + sei_meta->win_info[i].color_saturation_weight); + } + + mfc_debug(5, "[HDR+] ================================================================\n"); + + /* Do not need to dump register */ + if (dev->nal_q_handle) + if (dev->nal_q_handle->nal_q_state == NAL_Q_STATE_STARTED) + return; + + print_hex_dump(KERN_ERR, "[HDR+] ", DUMP_PREFIX_ADDRESS, 32, 4, + dev->regs_base + MFC_REG_D_ST_2094_40_SEI_0, 0x78, false); +} + +void mfc_get_hdr_plus_info(struct mfc_ctx *ctx, struct hdr10_plus_meta *sei_meta) +{ + struct mfc_dev *dev = ctx->dev; + unsigned int upper_value, lower_value; + int num_win, num_distribution; + int i, j; + + sei_meta->valid = 1; + + /* iru_t_t35 */ + sei_meta->t35_country_code = MFC_READL(MFC_REG_D_ST_2094_40_SEI_0) & 0xFF; + sei_meta->t35_terminal_provider_code = MFC_READL(MFC_REG_D_ST_2094_40_SEI_0) >> 8 & 0xFF; + upper_value = MFC_READL(MFC_REG_D_ST_2094_40_SEI_0) >> 24 & 0xFF; + lower_value = MFC_READL(MFC_REG_D_ST_2094_40_SEI_1) & 0xFF; + sei_meta->t35_terminal_provider_oriented_code = (upper_value << 8) | lower_value; + + /* application */ + sei_meta->application_identifier = MFC_READL(MFC_REG_D_ST_2094_40_SEI_1) >> 8 & 0xFF; + sei_meta->application_version = MFC_READL(MFC_REG_D_ST_2094_40_SEI_1) >> 16 & 0xFF; + + /* window information */ + sei_meta->num_windows = MFC_READL(MFC_REG_D_ST_2094_40_SEI_1) >> 24 & 0x3; + num_win = sei_meta->num_windows; + if (num_win > dev->pdata->max_hdr_win) { + mfc_err_ctx("[HDR+] num_window(%d) is exceeded supported max_num_window(%d)\n", + num_win, dev->pdata->max_hdr_win); + num_win = dev->pdata->max_hdr_win; + sei_meta->num_windows = num_win; + } + + /* luminance */ + sei_meta->target_maximum_luminance = MFC_READL(MFC_REG_D_ST_2094_40_SEI_2) & 0x7FFFFFF; + sei_meta->target_actual_peak_luminance_flag = MFC_READL(MFC_REG_D_ST_2094_40_SEI_2) >> 27 & 0x1; + sei_meta->mastering_actual_peak_luminance_flag = MFC_READL(MFC_REG_D_ST_2094_40_SEI_22) >> 10 & 0x1; + + /* per window setting */ + for (i = 0; i < num_win; i++) { + /* scl */ + for (j = 0; j < HDR_MAX_SCL; j++) { + sei_meta->win_info[i].maxscl[j] = + MFC_READL(MFC_REG_D_ST_2094_40_SEI_3 + (4 * j)) & 0x1FFFF; + } + sei_meta->win_info[i].average_maxrgb = + MFC_READL(MFC_REG_D_ST_2094_40_SEI_6) & 0x1FFFF; + + /* distribution */ + sei_meta->win_info[i].num_distribution_maxrgb_percentiles = + MFC_READL(MFC_REG_D_ST_2094_40_SEI_6) >> 17 & 0xF; + num_distribution = sei_meta->win_info[i].num_distribution_maxrgb_percentiles; + for (j = 0; j < num_distribution; j++) { + sei_meta->win_info[i].distribution_maxrgb_percentages[j] = + MFC_READL(MFC_REG_D_ST_2094_40_SEI_7 + (4 * j)) & 0x7F; + sei_meta->win_info[i].distribution_maxrgb_percentiles[j] = + MFC_READL(MFC_REG_D_ST_2094_40_SEI_7 + (4 * j)) >> 7 & 0x1FFFF; + } + + /* bright pixels */ + sei_meta->win_info[i].fraction_bright_pixels = + MFC_READL(MFC_REG_D_ST_2094_40_SEI_22) & 0x3FF; + + /* tone mapping */ + sei_meta->win_info[i].tone_mapping_flag = + MFC_READL(MFC_REG_D_ST_2094_40_SEI_22) >> 11 & 0x1; + if (sei_meta->win_info[i].tone_mapping_flag) { + sei_meta->win_info[i].knee_point_x = + MFC_READL(MFC_REG_D_ST_2094_40_SEI_23) & 0xFFF; + sei_meta->win_info[i].knee_point_y = + MFC_READL(MFC_REG_D_ST_2094_40_SEI_23) >> 12 & 0xFFF; + sei_meta->win_info[i].num_bezier_curve_anchors = + MFC_READL(MFC_REG_D_ST_2094_40_SEI_23) >> 24 & 0xF; + for (j = 0; j < HDR_MAX_BEZIER_CURVES / 3; j++) { + sei_meta->win_info[i].bezier_curve_anchors[j * 3] = + MFC_READL(MFC_REG_D_ST_2094_40_SEI_24 + (4 * j)) & 0x3FF; + sei_meta->win_info[i].bezier_curve_anchors[j * 3 + 1] = + MFC_READL(MFC_REG_D_ST_2094_40_SEI_24 + (4 * j)) >> 10 & 0x3FF; + sei_meta->win_info[i].bezier_curve_anchors[j * 3 + 2] = + MFC_READL(MFC_REG_D_ST_2094_40_SEI_24 + (4 * j)) >> 20 & 0x3FF; + } + } + + /* color saturation */ + sei_meta->win_info[i].color_saturation_mapping_flag = + MFC_READL(MFC_REG_D_ST_2094_40_SEI_29) & 0x1; + if (sei_meta->win_info[i].color_saturation_mapping_flag) + sei_meta->win_info[i].color_saturation_weight = + MFC_READL(MFC_REG_D_ST_2094_40_SEI_29) >> 1 & 0x3F; + } + + if (debug_level >= 5) + mfc_print_dec_hdr_plus_info(ctx, index); +} diff --git a/drivers/media/platform/exynos/mfc/mfc_reg_api.h b/drivers/media/platform/exynos/mfc/mfc_reg_api.h index 25754a8d9ff6..251904e79a8e 100644 --- a/drivers/media/platform/exynos/mfc/mfc_reg_api.h +++ b/drivers/media/platform/exynos/mfc/mfc_reg_api.h @@ -124,6 +124,9 @@ #define mfc_get_sei_avail_mastering_display() ((MFC_READL(MFC_REG_D_SEI_AVAIL) \ >> MFC_REG_D_SEI_AVAIL_MASTERING_DISPLAY_SHIFT) \ & MFC_REG_D_SEI_AVAIL_MASTERING_DISPLAY_MASK) +#define mfc_get_sei_avail_st_2094_40() ((MFC_READL(MFC_REG_D_SEI_AVAIL) \ + >> MFC_REG_D_SEI_AVAIL_ST_2094_40_SHIFT) \ + & MFC_REG_D_SEI_AVAIL_ST_2094_40_MASK) #define mfc_get_video_signal_type() ((MFC_READL(MFC_REG_D_VIDEO_SIGNAL_TYPE) \ >> MFC_REG_D_VIDEO_SIGNAL_TYPE_FLAG_SHIFT) \ & MFC_REG_D_VIDEO_SIGNAL_TYPE_FLAG_MASK) @@ -271,4 +274,7 @@ int mfc_set_dynamic_dpb(struct mfc_ctx *ctx, struct mfc_buf *dst_vb); void mfc_set_pixel_format(struct mfc_dev *dev, unsigned int format); +void mfc_print_dec_hdr_plus_info(struct mfc_ctx *ctx, int index); +void mfc_get_hdr_plus_info(struct mfc_ctx *ctx, struct hdr10_plus_meta *sei_meta); + #endif /* __MFC_REG_API_H */ diff --git a/drivers/media/platform/exynos/mfc/mfc_regs.h b/drivers/media/platform/exynos/mfc/mfc_regs.h index ee569f44849a..bb9fb73c5d95 100644 --- a/drivers/media/platform/exynos/mfc/mfc_regs.h +++ b/drivers/media/platform/exynos/mfc/mfc_regs.h @@ -422,6 +422,37 @@ #define MFC_REG_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_4 0xFE0C #define MFC_REG_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_5 0xFE10 +#define MFC_REG_D_ST_2094_40_SEI_0 0xFF00 +#define MFC_REG_D_ST_2094_40_SEI_1 0xFF04 +#define MFC_REG_D_ST_2094_40_SEI_2 0xFF08 +#define MFC_REG_D_ST_2094_40_SEI_3 0xFF0C +#define MFC_REG_D_ST_2094_40_SEI_4 0xFF10 +#define MFC_REG_D_ST_2094_40_SEI_5 0xFF14 +#define MFC_REG_D_ST_2094_40_SEI_6 0xFF18 +#define MFC_REG_D_ST_2094_40_SEI_7 0xFF1C +#define MFC_REG_D_ST_2094_40_SEI_8 0xFF20 +#define MFC_REG_D_ST_2094_40_SEI_9 0xFF24 +#define MFC_REG_D_ST_2094_40_SEI_10 0xFF28 +#define MFC_REG_D_ST_2094_40_SEI_11 0xFF2C +#define MFC_REG_D_ST_2094_40_SEI_12 0xFF30 +#define MFC_REG_D_ST_2094_40_SEI_13 0xFF34 +#define MFC_REG_D_ST_2094_40_SEI_14 0xFF38 +#define MFC_REG_D_ST_2094_40_SEI_15 0xFF3C +#define MFC_REG_D_ST_2094_40_SEI_16 0xFF40 +#define MFC_REG_D_ST_2094_40_SEI_17 0xFF44 +#define MFC_REG_D_ST_2094_40_SEI_18 0xFF48 +#define MFC_REG_D_ST_2094_40_SEI_19 0xFF4C +#define MFC_REG_D_ST_2094_40_SEI_20 0xFF50 +#define MFC_REG_D_ST_2094_40_SEI_21 0xFF54 +#define MFC_REG_D_ST_2094_40_SEI_22 0xFF58 +#define MFC_REG_D_ST_2094_40_SEI_23 0xFF5C +#define MFC_REG_D_ST_2094_40_SEI_24 0xFF60 +#define MFC_REG_D_ST_2094_40_SEI_25 0xFF64 +#define MFC_REG_D_ST_2094_40_SEI_26 0xFF68 +#define MFC_REG_D_ST_2094_40_SEI_27 0xFF6C +#define MFC_REG_D_ST_2094_40_SEI_28 0xFF70 +#define MFC_REG_D_ST_2094_40_SEI_29 0xFF74 + #define MFC_REG_REG_CLEAR_BEGIN 0xf000 #define MFC_REG_REG_CLEAR_COUNT 1024 @@ -568,6 +599,7 @@ #define MFC_REG_D_SEI_ENABLE_RECOVERY_PARSING_SHIFT 2 #define MFC_REG_D_SEI_ENABLE_CONTENT_LIGHT_SHIFT 4 #define MFC_REG_D_SEI_ENABLE_MASTERING_DISPLAY_SHIFT 5 +#define MFC_REG_D_SEI_ENABLE_ST_2094_40_SEI_SHIFT 6 /* 0xF154: MFC_REG_D_INIT_BUFFER_OPTIONS */ @@ -679,6 +711,8 @@ #define MFC_REG_D_SEI_AVAIL_CONTENT_LIGHT_SHIFT 1 #define MFC_REG_D_SEI_AVAIL_MASTERING_DISPLAY_MASK 0x1 #define MFC_REG_D_SEI_AVAIL_MASTERING_DISPLAY_SHIFT 2 +#define MFC_REG_D_SEI_AVAIL_ST_2094_40_MASK 0x1 +#define MFC_REG_D_SEI_AVAIL_ST_2094_40_SHIFT 3 /* 0xF70C: MFC_REG_D_VIDEO_SIGNAL_TYPE */ -- 2.20.1