From 3e5254d120656ec87fc3c9f7669a4e58d4c7b4e6 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Sat, 28 Dec 2019 02:24:22 +0800 Subject: [PATCH] vpp: add vframe src_fmt struct and function [1/1] PD#SWPL-17729 Problem: In new video pipeline, vfm map is changed. So vpp can not get aux data from decode directly. It cause the format of dv or hdr10+ content is incorrect. Solution: Add src_fmt struct in vframe, and whole src_fmt interface. Let front-end updates src_fmt directly. Then vpp, dv or hdr10+ module can get the sei data from it. Verify: Verifed on AC214 Change-Id: I96b7f84fa72c51ceec9e3ec28288ea0e7a726139 Signed-off-by: Brian Zhu --- .../amdolby_vision/amdolby_vision.c | 79 ++++--- .../enhancement/amvecm/hdr/am_hdr10_plus.c | 16 +- .../media/video_processor/v4lvideo/v4lvideo.c | 180 ++++++++++++++- .../media/video_processor/v4lvideo/v4lvideo.h | 1 + drivers/amlogic/media/video_sink/video.c | 211 +++++++++++++++++- .../amlogic/media/video_sink/video_receiver.c | 7 +- include/linux/amlogic/media/vfm/vframe.h | 34 +++ 7 files changed, 478 insertions(+), 50 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c index b31da72799d2..4087634dc1ee 100644 --- a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c +++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c @@ -3990,7 +3990,7 @@ static int dvel_receiver_event_fun(int type, void *data, void *arg) setting_update_count = 0; crc_count = 0; crc_bypass_count = 0; - dolby_vision_el_disable = 0; + dolby_vision_el_disable = false; return -1; } else if (type == VFRAME_EVENT_PROVIDER_QUREY_STATE) { return RECEIVER_ACTIVE; @@ -4007,7 +4007,7 @@ static int dvel_receiver_event_fun(int type, void *data, void *arg) setting_update_count = 0; crc_count = 0; crc_bypass_count = 0; - dolby_vision_el_disable = 0; + dolby_vision_el_disable = false; } return 0; } @@ -4710,10 +4710,18 @@ bool is_dovi_frame(struct vframe_s *vf) char *p; unsigned int size = 0; unsigned int type = 0; + enum vframe_signal_fmt_e fmt; if (!vf) return false; + fmt = get_vframe_src_fmt(vf); + if (fmt == VFRAME_SIGNAL_FMT_DOVI) + return true; + + if (fmt != VFRAME_SIGNAL_FMT_INVALID) + return false; + req.vf = vf; req.bot_flag = 0; req.aux_buf = NULL; @@ -4731,9 +4739,10 @@ bool is_dovi_frame(struct vframe_s *vf) else return 0; } else if (vf->source_type == VFRAME_SOURCE_TYPE_OTHERS) { - vf_notify_provider_by_name(dv_provider, - VFRAME_EVENT_RECEIVER_GET_AUX_DATA, - (void *)&req); + vf_notify_provider_by_name( + dv_provider, + VFRAME_EVENT_RECEIVER_GET_AUX_DATA, + (void *)&req); if (req.dv_enhance_exist) return true; if (!req.aux_buf || !req.aux_size) @@ -4760,6 +4769,17 @@ EXPORT_SYMBOL(is_dovi_frame); bool is_dovi_dual_layer_frame(struct vframe_s *vf) { struct provider_aux_req_s req; + enum vframe_signal_fmt_e fmt; + + if (!vf) + return false; + + fmt = get_vframe_src_fmt(vf); + /* valid src_fmt = DOVI or invalid src_fmt will check dual layer */ + /* otherwise, it certainly is a non-dv vframe */ + if ((fmt != VFRAME_SIGNAL_FMT_DOVI) && + (fmt != VFRAME_SIGNAL_FMT_INVALID)) + return false; req.vf = vf; req.bot_flag = 0; @@ -6103,16 +6123,39 @@ int dolby_vision_parse_metadata( dolby_vision_vf_add(vf, NULL); } } else if (vf && (vf->source_type == VFRAME_SOURCE_TYPE_OTHERS)) { - /* check source format */ + enum vframe_signal_fmt_e fmt; + input_mode = INPUT_MODE_OTT; + req.vf = vf; req.bot_flag = 0; req.aux_buf = NULL; req.aux_size = 0; req.dv_enhance_exist = 0; - vf_notify_provider_by_name(dv_provider, - VFRAME_EVENT_RECEIVER_GET_AUX_DATA, - (void *)&req); + + /* check source format */ + fmt = get_vframe_src_fmt(vf); + if ((fmt == VFRAME_SIGNAL_FMT_DOVI) || + (fmt == VFRAME_SIGNAL_FMT_INVALID)) { + u32 sei_size = 0; + char *sei; + + vf_notify_provider_by_name( + dv_provider, + VFRAME_EVENT_RECEIVER_GET_AUX_DATA, + (void *)&req); + /* use aux date first, if invaild, use sei_ptr */ + if ((!req.aux_buf || !req.aux_size) && + (fmt == VFRAME_SIGNAL_FMT_DOVI)) { + sei = (char *)get_sei_from_src_fmt( + vf, &sei_size); + if (sei && sei_size) { + req.aux_buf = sei; + req.aux_size = sei_size; + } + } + } + if (debug_dolby & 1 && req.aux_buf && req.aux_size) pr_dolby_dbg("dvbldec get aux data %p %x\n", req.aux_buf, req.aux_size); @@ -6313,7 +6356,7 @@ int dolby_vision_parse_metadata( (el_flag && !mel_flag && ((dolby_vision_flags & FLAG_CERTIFICAION) == 0))) { el_flag = 0; - dolby_vision_el_disable = 1; + dolby_vision_el_disable = true; } if (src_format != FORMAT_DOVI) { el_flag = 0; @@ -6920,7 +6963,6 @@ EXPORT_SYMBOL(dolby_vision_parse_metadata); /* 3: found match el */ int dolby_vision_wait_metadata(struct vframe_s *vf) { - struct provider_aux_req_s req; struct vframe_s *el_vf; int ret = 0; unsigned int mode = dolby_vision_mode; @@ -6946,20 +6988,7 @@ int dolby_vision_wait_metadata(struct vframe_s *vf) return 1; } - if (vf) { - req.vf = vf; - req.bot_flag = 0; - req.aux_buf = NULL; - req.aux_size = 0; - req.dv_enhance_exist = 0; - - if (vf->source_type == VFRAME_SOURCE_TYPE_OTHERS) - vf_notify_provider_by_name( - dv_provider, - VFRAME_EVENT_RECEIVER_GET_AUX_DATA, - (void *)&req); - } - if (vf && req.dv_enhance_exist) { + if (is_dovi_dual_layer_frame(vf)) { el_vf = dvel_vf_peek(); while (el_vf) { if (debug_dolby & 2) diff --git a/drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus.c b/drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus.c index 81a43811d34e..7a88e1abadeb 100644 --- a/drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus.c +++ b/drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus.c @@ -672,14 +672,22 @@ void hdr10_plus_parser_metadata(struct vframe_s *vf) req.aux_size = 0; req.dv_enhance_exist = 0; req.low_latency = 0; - - vf_notify_provider_by_name("vdec.h265.00", + if (get_vframe_src_fmt(vf) == + VFRAME_SIGNAL_FMT_HDR10PLUS) { + size = 0; + req.aux_buf = (char *)get_sei_from_src_fmt(vf, &size); + req.aux_size = size; + } else { + vf_notify_provider_by_name( + "vdec.h265.00", VFRAME_EVENT_RECEIVER_GET_AUX_DATA, (void *)&req); - if (!req.aux_buf) - vf_notify_provider_by_name("decoder", + if (!req.aux_buf) + vf_notify_provider_by_name( + "decoder", VFRAME_EVENT_RECEIVER_GET_AUX_DATA, (void *)&req); + } if (req.aux_buf && req.aux_size) { p = req.aux_buf; while (p < req.aux_buf diff --git a/drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.c b/drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.c index c5abbe572570..f49e9603cfa2 100644 --- a/drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.c +++ b/drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.c @@ -34,6 +34,7 @@ #include #include #include +#include "../../common/vfm/vfm.h" #define V4LVIDEO_MODULE_NAME "v4lvideo" @@ -42,6 +43,9 @@ #define V4LVIDEO_DEVICE_NAME "v4lvideo" #define DUR2PTS(x) ((x) - ((x) >> 4)) +static atomic_t global_set_cnt = ATOMIC_INIT(0); +static u32 alloc_sei = 1; + #define V4L2_CID_USER_AMLOGIC_V4LVIDEO_BASE (V4L2_CID_USER_BASE + 0x1100) static unsigned int video_nr_base = 30; @@ -802,6 +806,78 @@ struct vframe_s *v4lvideo_get_vf(int fd) return vf; } +static s32 v4lvideo_release_sei_data(struct vframe_s *vf) +{ + void *p; + s32 ret = -2; + u32 size = 0; + + if (!vf) + return ret; + + p = get_sei_from_src_fmt(vf, &size); + if (p) { + vfree(p); + atomic_dec(&global_set_cnt); + } + ret = clear_vframe_src_fmt(vf); + return ret; +} + +static s32 v4lvideo_import_sei_data( + struct vframe_s *vf, + struct vframe_s *dup_vf, + char *provider) +{ + struct provider_aux_req_s req; + s32 ret = -2; + char *p; + + if (!vf || !dup_vf || !provider || !alloc_sei) + return ret; + + req.vf = vf; + req.bot_flag = 0; + req.aux_buf = NULL; + req.aux_size = 0; + req.dv_enhance_exist = 0; + vf_notify_provider_by_name( + provider, + VFRAME_EVENT_RECEIVER_GET_AUX_DATA, + (void *)&req); + + if (req.aux_buf && req.aux_size) { + p = vmalloc(req.aux_size); + if (p) { + memcpy(p, req.aux_buf, req.aux_size); + ret = update_vframe_src_fmt( + dup_vf, (void *)p, (u32)req.aux_size, + req.dv_enhance_exist ? true : false); + if (!ret) { + /* FIXME: work around for sei/el out of sync */ + if ((dup_vf->src_fmt.fmt == + VFRAME_SIGNAL_FMT_SDR) && + !strcmp(provider, "dvbldec")) + dup_vf->src_fmt.fmt = + VFRAME_SIGNAL_FMT_DOVI; + atomic_inc(&global_set_cnt); + } else { + vfree(p); + } + } else { + ret = update_vframe_src_fmt( + dup_vf, NULL, 0, false); + } + } else { + ret = update_vframe_src_fmt(dup_vf, NULL, 0, false); + } + if (alloc_sei & 2) + pr_info("import sei: provider:%s, vf:%p, dup_vf:%p, req.aux_buf:%p, req.aux_size:%d, req.dv_enhance_exist:%d, vf->src_fmt.fmt:%d\n", + provider, vf, dup_vf, + req.aux_buf, req.aux_size, + req.dv_enhance_exist, dup_vf->src_fmt.fmt); + return ret; +} /* ------------------------------------------------------------------ * DMA and thread functions * ------------------------------------------------------------------ @@ -818,6 +894,8 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) dprintk(dev, 2, "%s\n", __func__); + dev->provider_name = NULL; + dprintk(dev, 2, "returning from %s\n", __func__); return 0; @@ -1052,6 +1130,8 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) dprintk(dev, 1, "vidioc_qbuf: vf is NULL, at the start of playback\n"); } + + v4lvideo_release_sei_data(&file_private_data->vf); init_file_private_data(file_private_data); fput(file_vf); @@ -1070,6 +1150,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) struct file_private_data *file_private_data = NULL; u64 pts_us64 = 0; u64 pts_tmp; + char *provider_name = NULL; mutex_lock(&dev->mutex_input); buf = v4l2q_peek(&dev->input_queue); @@ -1088,6 +1169,21 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) vf = vf_get(dev->vf_receiver_name); if (!vf) return -EAGAIN; + + if (!dev->provider_name) { + provider_name = vf_get_provider_name( + dev->vf_receiver_name); + while (provider_name) { + if (!vf_get_provider_name(provider_name)) + break; + provider_name = + vf_get_provider_name(provider_name); + } + dev->provider_name = provider_name; + pr_info("v4lvideo: provider name: %s\n", + dev->provider_name ? dev->provider_name : "NULL"); + } + get_count++; vf->omx_index = dev->frame_num; dev->am_parm.signal_type = vf->signal_type; @@ -1111,6 +1207,10 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) } file_private_data->vf = *vf; file_private_data->vf_p = vf; + v4lvideo_import_sei_data( + vf, &file_private_data->vf, + dev->provider_name); + //pr_err("dqbuf: file_private_data=%p, vf=%p\n", file_private_data, vf); v4l2q_push(&dev->display_queue, file_private_data); fput(file_vf); @@ -1347,6 +1447,7 @@ static int v4lvideo_file_release(struct inode *inode, struct file *file) if (file_private_data) { if (file_private_data->is_keep) vf_free(file_private_data); + v4lvideo_release_sei_data(&file_private_data->vf); memset(file_private_data, 0, sizeof(struct file_private_data)); kfree((u8 *)file_private_data); file->private_data = NULL; @@ -1364,7 +1465,7 @@ static const struct file_operations v4lvideo_file_fops = { int v4lvideo_alloc_fd(int *fd) { struct file *file = NULL; - struct file_private_data *private_date = NULL; + struct file_private_data *private_data = NULL; int file_fd = get_unused_fd_flags(O_CLOEXEC); if (file_fd < 0) { @@ -1372,19 +1473,19 @@ int v4lvideo_alloc_fd(int *fd) return -ENODEV; } - private_date = kzalloc(sizeof(*private_date), GFP_KERNEL); - if (!private_date) { + private_data = kzalloc(sizeof(*private_data), GFP_KERNEL); + if (!private_data) { put_unused_fd(file_fd); pr_err("v4lvideo_alloc_fd: private_date fail\n"); return -ENOMEM; } - init_file_private_data(private_date); + init_file_private_data(private_data); file = anon_inode_getfile("v4lvideo_file", &v4lvideo_file_fops, - private_date, 0); + private_data, 0); if (IS_ERR(file)) { - kfree((u8 *)private_date); + kfree((u8 *)private_data); put_unused_fd(file_fd); pr_err("v4lvideo_alloc_fd: anon_inode_getfile fail\n"); return -ENODEV; @@ -1394,12 +1495,75 @@ int v4lvideo_alloc_fd(int *fd) return 0; } -static struct class_attribute ion_video_class_attrs[] = { +static ssize_t sei_cnt_show( + struct class *class, struct class_attribute *attr, char *buf) +{ + ssize_t r; + int cnt; + + cnt = atomic_read(&global_set_cnt); + r = sprintf(buf, "allocated sei buffer cnt: %d\n", cnt); + return r; +} + +static ssize_t sei_cnt_store( + struct class *class, + struct class_attribute *attr, + const char *buf, size_t count) +{ + ssize_t r; + int val; + + r = kstrtoint(buf, 0, &val); + if (r < 0) + return -EINVAL; + + pr_info("set sei_cnt val:%d\n", val); + atomic_set(&global_set_cnt, val); + return count; +} + +static ssize_t alloc_sei_show( + struct class *class, struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "alloc sei: %d\n", alloc_sei); +} + +static ssize_t alloc_sei_store( + struct class *class, + struct class_attribute *attr, + const char *buf, size_t count) +{ + ssize_t r; + int val; + + r = kstrtoint(buf, 0, &val); + if (r < 0) + return -EINVAL; + + if (val > 0) + alloc_sei = val; + else + alloc_sei = 0; + pr_info("set alloc_sei val:%d\n", alloc_sei); + return count; +} + +static struct class_attribute v4lvideo_class_attrs[] = { + __ATTR(sei_cnt, + 0664, + sei_cnt_show, + sei_cnt_store), + __ATTR(alloc_sei, + 0664, + alloc_sei_show, + alloc_sei_store), + __ATTR_NULL }; static struct class v4lvideo_class = { .name = "v4lvideo", - .class_attrs = ion_video_class_attrs, + .class_attrs = v4lvideo_class_attrs, }; static int v4lvideo_open(struct inode *inode, struct file *file) diff --git a/drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.h b/drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.h index b5c0540d7ce2..95b9bc0598c7 100644 --- a/drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.h +++ b/drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.h @@ -223,6 +223,7 @@ struct v4lvideo_dev { struct v4l2_buffer v4lvideo_input[V4LVIDEO_POOL_SIZE]; struct v4l2_amlogic_parm am_parm; u8 first_frame; + char *provider_name; }; enum vframe_source_type { diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 2bcd92bbbc91..b0023ce8f5fb 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -1351,6 +1351,7 @@ u32 last_el_status; bool has_enhanced_layer(struct vframe_s *vf) { struct provider_aux_req_s req; + enum vframe_signal_fmt_e fmt; if (is_dolby_vision_el_disable() && !for_dolby_vision_certification()) @@ -1358,11 +1359,20 @@ bool has_enhanced_layer(struct vframe_s *vf) if (!vf) return 0; + if (vf->source_type != VFRAME_SOURCE_TYPE_OTHERS) return 0; + if (!is_dolby_vision_on()) return 0; + fmt = get_vframe_src_fmt(vf); + /* valid src_fmt = DOVI or invalid src_fmt will check dual layer */ + /* otherwise, it certainly is a non-dv vframe */ + if ((fmt != VFRAME_SIGNAL_FMT_DOVI) && + (fmt != VFRAME_SIGNAL_FMT_INVALID)) + return 0; + req.vf = vf; req.bot_flag = 0; req.aux_buf = NULL; @@ -5347,11 +5357,14 @@ static int get_display_info(void *data) return 0; } -static struct vframe_s *get_dispbuf(void) +static struct vframe_s *get_dispbuf(u8 layer_id) { struct vframe_s *dispbuf = NULL; - switch (glayer_info[0].display_path_id) { + if (layer_id >= MAX_VD_LAYERS) + return NULL; + + switch (glayer_info[layer_id].display_path_id) { case VFM_PATH_DEF: case VFM_PATH_AMVIDEO: if (cur_dispbuf) @@ -5644,6 +5657,134 @@ void pause_video(unsigned char pause_flag) atomic_set(&video_pause_flag, pause_flag ? 1 : 0); } EXPORT_SYMBOL(pause_video); + +/********************************************************* + * Vframe src fmt API + *********************************************************/ +#define signal_color_primaries ((vf->signal_type >> 16) & 0xff) +#define signal_transfer_characteristic ((vf->signal_type >> 8) & 0xff) + +#define DV_SEI 0x01000000 +#define HDR10P 0x02000000 + +static int check_media_sei(char *sei, u32 sei_size, u32 sei_type) +{ + int ret = 0; + char *p; + u32 type = 0, size; + + if (!sei || (sei_size <= 8)) + return ret; + + p = sei; + while (p < sei + sei_size - 8) { + size = *p++; + size = (size << 8) | *p++; + size = (size << 8) | *p++; + size = (size << 8) | *p++; + type = *p++; + type = (type << 8) | *p++; + type = (type << 8) | *p++; + type = (type << 8) | *p++; + + if (type == sei_type) { + ret = 1; + break; + } + p += size; + } + return ret; +} + +s32 update_vframe_src_fmt( + struct vframe_s *vf, void *sei, + u32 size, bool dual_layer) +{ + if (!vf) + return -1; + + vf->src_fmt.sei_magic_code = SEI_MAGIC_CODE; + vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_INVALID; + vf->src_fmt.sei_ptr = sei; + vf->src_fmt.sei_size = size; + vf->src_fmt.dual_layer = false; + if (((signal_transfer_characteristic == 14) || + (signal_transfer_characteristic == 18)) && + (signal_color_primaries == 9)) { + vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_HLG; + } else if ((signal_transfer_characteristic == 0x30) && + ((signal_color_primaries == 9) || + (signal_color_primaries == 2))) { + if (check_media_sei(sei, size, HDR10P)) + vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_HDR10PLUS; + else /* TODO: if need switch to HDR10 */ + vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_HDR10; + } else if ((signal_transfer_characteristic == 16) && + ((signal_color_primaries == 9) || + (signal_color_primaries == 2))) { + vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_HDR10; + } else if (vf->type & VIDTYPE_MVC) { + vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_MVC; + } + if (sei && size && + (vf->src_fmt.fmt == VFRAME_SIGNAL_FMT_INVALID)) { + if (dual_layer || check_media_sei(sei, size, DV_SEI)) { + vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_DOVI; + vf->src_fmt.dual_layer = dual_layer; + } + } + if (vf->src_fmt.fmt == VFRAME_SIGNAL_FMT_INVALID) + vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_SDR; + return 0; +} +EXPORT_SYMBOL(update_vframe_src_fmt); + +void *get_sei_from_src_fmt(struct vframe_s *vf, u32 *sei_size) +{ + if (!vf || !sei_size) + return NULL; + + /* invaild src fmt case */ + if (vf->src_fmt.sei_magic_code != SEI_MAGIC_CODE) + return NULL; + + *sei_size = vf->src_fmt.sei_size; + return vf->src_fmt.sei_ptr; +} +EXPORT_SYMBOL(get_sei_from_src_fmt); + +enum vframe_signal_fmt_e get_vframe_src_fmt( + struct vframe_s *vf) +{ + if (!vf) + return VFRAME_SIGNAL_FMT_INVALID; + + /* invaild src fmt case */ + if (vf->src_fmt.sei_magic_code != SEI_MAGIC_CODE) + return VFRAME_SIGNAL_FMT_INVALID; + + return vf->src_fmt.fmt; +} +EXPORT_SYMBOL(get_vframe_src_fmt); + +s32 clear_vframe_src_fmt(struct vframe_s *vf) +{ + if (!vf) + return -1; + + /* invaild src fmt case */ + if (vf->src_fmt.sei_magic_code != SEI_MAGIC_CODE) + return -1; + + vf->src_fmt.sei_magic_code = 0; + vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_INVALID; + vf->src_fmt.sei_ptr = NULL; + vf->src_fmt.sei_size = 0; + vf->src_fmt.dual_layer = false; + return 0; +} +EXPORT_SYMBOL(clear_vframe_src_fmt); + /********************************************************* * Utilities *********************************************************/ @@ -6336,7 +6477,7 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) if (mvc_flag) process_3d_type |= MODE_3D_MVC; vd_layer[0].property_changed = true; - dispbuf = get_dispbuf(); + dispbuf = get_dispbuf(0); if ((process_3d_type & MODE_3D_FA) && dispbuf && !dispbuf->trans_fmt) @@ -7838,7 +7979,7 @@ static ssize_t threedim_mode_store(struct class *cla, process_3d_type |= MODE_3D_MVC; vd_layer[0].property_changed = true; - dispbuf = get_dispbuf(); + dispbuf = get_dispbuf(0); if ((process_3d_type & MODE_3D_FA) && dispbuf && !dispbuf->trans_fmt) /*notify di 3d mode is frame alternative mode,1*/ @@ -7876,7 +8017,7 @@ static ssize_t frame_addr_show(struct class *cla, struct class_attribute *attr, struct vframe_s *dispbuf = NULL; unsigned int canvas0Addr; - dispbuf = get_dispbuf(); + dispbuf = get_dispbuf(0); if (dispbuf) { canvas0Addr = get_layer_display_canvas(0); canvas_read(canvas0Addr & 0xff, &canvas); @@ -7951,7 +8092,7 @@ static ssize_t frame_canvas_width_show(struct class *cla, u32 width[3]; unsigned int canvas0Addr; - dispbuf = get_dispbuf(); + dispbuf = get_dispbuf(0); if (dispbuf) { canvas0Addr = get_layer_display_canvas(0); canvas_read(canvas0Addr & 0xff, &canvas); @@ -7976,7 +8117,7 @@ static ssize_t frame_canvas_height_show(struct class *cla, u32 height[3]; unsigned int canvas0Addr; - dispbuf = get_dispbuf(); + dispbuf = get_dispbuf(0); if (dispbuf) { canvas0Addr = get_layer_display_canvas(0); canvas_read(canvas0Addr & 0xff, &canvas); @@ -7999,7 +8140,7 @@ static ssize_t frame_width_show(struct class *cla, { struct vframe_s *dispbuf = NULL; - dispbuf = get_dispbuf(); + dispbuf = get_dispbuf(0); if ((hold_video == 1) && ((glayer_info[0].display_path_id == @@ -8029,7 +8170,7 @@ static ssize_t frame_height_show(struct class *cla, VFM_PATH_DEF))) return sprintf(buf, "%d\n", cur_height); - dispbuf = get_dispbuf(); + dispbuf = get_dispbuf(0); if (dispbuf) { if (dispbuf->type & VIDTYPE_COMPRESS) return sprintf(buf, "%d\n", dispbuf->compHeight); @@ -8045,7 +8186,7 @@ static ssize_t frame_format_show(struct class *cla, struct vframe_s *dispbuf = NULL; ssize_t ret = 0; - dispbuf = get_dispbuf(); + dispbuf = get_dispbuf(0); if (dispbuf) { if ((dispbuf->type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) @@ -8070,7 +8211,7 @@ static ssize_t frame_aspect_ratio_show(struct class *cla, { struct vframe_s *dispbuf = NULL; - dispbuf = get_dispbuf(); + dispbuf = get_dispbuf(0); if (dispbuf) { u32 ar = (dispbuf->ratio_control & DISP_RATIO_ASPECT_RATIO_MASK) >> @@ -8548,7 +8689,7 @@ static ssize_t pic_mode_info_show(struct class *cla, int ret = 0; struct vframe_s *dispbuf = NULL; - dispbuf = get_dispbuf(); + dispbuf = get_dispbuf(0); if (dispbuf) { u32 adapted_mode = (dispbuf->ratio_control & DISP_RATIO_ADAPTED_PICMODE) ? 1 : 0; @@ -8578,6 +8719,51 @@ static ssize_t pic_mode_info_show(struct class *cla, return sprintf(buf, "NA\n"); } +static ssize_t src_fmt_show( + struct class *cla, struct class_attribute *attr, char *buf) +{ + int ret = 0; + struct vframe_s *dispbuf = NULL; + enum vframe_signal_fmt_e fmt; + void *sei_ptr; + u32 sei_size = 0; + static const char * const fmt_str[] = { + "SDR", "HDR10", "HDR10+", "HDR Prime", "HLG", + "Dolby Vison", "Dolby Vison Low latency", "MVC" + }; + + dispbuf = get_dispbuf(0); + ret += sprintf(buf + ret, "vd1 dispbuf: %p\n", dispbuf); + if (dispbuf) { + fmt = get_vframe_src_fmt(dispbuf); + if (fmt != VFRAME_SIGNAL_FMT_INVALID) { + sei_ptr = get_sei_from_src_fmt(dispbuf, &sei_size); + ret += sprintf(buf + ret, "fmt = %s\n", + fmt_str[fmt]); + ret += sprintf(buf + ret, "sei: %p, size: %d\n", + sei_ptr, sei_size); + } else { + ret += sprintf(buf + ret, "src_fmt is invaild\n"); + } + } + dispbuf = get_dispbuf(1); + ret += sprintf(buf + ret, "vd2 dispbuf: %p\n", dispbuf); + if (dispbuf) { + fmt = get_vframe_src_fmt(dispbuf); + if (fmt != VFRAME_SIGNAL_FMT_INVALID) { + sei_size = 0; + sei_ptr = get_sei_from_src_fmt(dispbuf, &sei_size); + ret += sprintf(buf + ret, "fmt=0x%s\n", + fmt_str[fmt]); + ret += sprintf(buf + ret, "sei: %p, size: %d\n", + sei_ptr, sei_size); + } else { + ret += sprintf(buf + ret, "src_fmt is invaild\n"); + } + } + return ret; +} + static ssize_t video_inuse_show(struct class *class, struct class_attribute *attr, char *buf) { @@ -9516,6 +9702,7 @@ static struct class_attribute amvideo_class_attrs[] = { __ATTR_RO(vframe_ready_cnt), __ATTR_RO(video_layer1_state), __ATTR_RO(pic_mode_info), + __ATTR_RO(src_fmt), __ATTR(axis_pip, 0664, videopip_axis_show, diff --git a/drivers/amlogic/media/video_sink/video_receiver.c b/drivers/amlogic/media/video_sink/video_receiver.c index 1018772a9ab0..25db04de52b4 100644 --- a/drivers/amlogic/media/video_sink/video_receiver.c +++ b/drivers/amlogic/media/video_sink/video_receiver.c @@ -333,6 +333,7 @@ static struct vframe_s *recv_common_dequeue_frame( struct vframe_s *vf = NULL; struct vframe_s *toggle_vf = NULL; s32 drop_count = -1; + enum vframe_signal_fmt_e fmt; if (!ins) { pr_err("recv_common_dequeue_frame error, empty ins\n"); @@ -352,7 +353,11 @@ static struct vframe_s *recv_common_dequeue_frame( dolby_vision_check_hdr10plus(vf); dolby_vision_check_hlg(vf); } - if (vf_peek("dvel")) { + + fmt = get_vframe_src_fmt(vf); + if (((fmt == VFRAME_SIGNAL_FMT_DOVI) || + (fmt == VFRAME_SIGNAL_FMT_INVALID)) && + vf_peek("dvel")) { req.vf = NULL; req.bot_flag = 0; req.aux_buf = NULL; diff --git a/include/linux/amlogic/media/vfm/vframe.h b/include/linux/amlogic/media/vfm/vframe.h index eaf398f0cd66..99e8dafa7815 100644 --- a/include/linux/amlogic/media/vfm/vframe.h +++ b/include/linux/amlogic/media/vfm/vframe.h @@ -281,6 +281,29 @@ enum vframe_disp_mode_e { VFRAME_DISP_MODE_OK, }; +enum vframe_signal_fmt_e { + VFRAME_SIGNAL_FMT_INVALID = -1, + VFRAME_SIGNAL_FMT_SDR = 0, + VFRAME_SIGNAL_FMT_HDR10 = 1, + VFRAME_SIGNAL_FMT_HDR10PLUS = 2, + VFRAME_SIGNAL_FMT_HDR10PRIME = 3, + VFRAME_SIGNAL_FMT_HLG = 4, + VFRAME_SIGNAL_FMT_DOVI = 5, + VFRAME_SIGNAL_FMT_DOVI_LL = 6, + VFRAME_SIGNAL_FMT_MVC = 7 +}; + +#define SEI_MAGIC_CODE 0x53656920 /* SEI */ + +/* signal format and sei data */ +struct vframe_src_fmt_s { + enum vframe_signal_fmt_e fmt; + u32 sei_magic_code; + void *sei_ptr; + u32 sei_size; + bool dual_layer; +}; + enum pic_mode_provider_e { PIC_MODE_PROVIDER_DB = 0, PIC_MODE_PROVIDER_WSS, @@ -461,6 +484,9 @@ struct vframe_s { bool rendered; struct codec_mm_box_s mm_box; + + /* signal format and sei data */ + struct vframe_src_fmt_s src_fmt; } /*vframe_t */; #if 0 @@ -471,4 +497,12 @@ int get_curren_frame_para(int *top, int *left, int *bottom, int *right); u8 is_vpp_postblend(void); void pause_video(unsigned char pause_flag); + +s32 update_vframe_src_fmt( + struct vframe_s *vf, void *sei, + u32 size, bool dual_layer); +void *get_sei_from_src_fmt(struct vframe_s *vf, u32 *sei_size); +enum vframe_signal_fmt_e get_vframe_src_fmt(struct vframe_s *vf); +s32 clear_vframe_src_fmt(struct vframe_s *vf); + #endif /* VFRAME_H */ -- 2.20.1