diff --git a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0001-avutil-add-av_buffer_pool_flush.patch b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0001-avutil-add-av_buffer_pool_flush.patch index 188ab137069..6db33f9d39a 100644 --- a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0001-avutil-add-av_buffer_pool_flush.patch +++ b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0001-avutil-add-av_buffer_pool_flush.patch @@ -1,7 +1,7 @@ From e6cec3f54693e7e2c10b6b7bc8f72daa6e9a77dc Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Mon, 3 Dec 2018 23:48:04 +0100 -Subject: [PATCH] avutil: add av_buffer_pool_flush() +Subject: [PATCH 01/12] avutil: add av_buffer_pool_flush() Signed-off-by: Jonas Karlman --- @@ -49,3 +49,6 @@ index 73b6bd0b14..0678fa4bea 100644 /** * Mark the pool as being available for freeing. It will actually be freed only * once all the allocated buffers associated with the pool are released. Thus it +-- +2.24.0 + diff --git a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0002-Add-common-V4L2-request-API-code.patch b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0002-Add-common-V4L2-request-API-code.patch index 1a9b43e2400..3d879741125 100644 --- a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0002-Add-common-V4L2-request-API-code.patch +++ b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0002-Add-common-V4L2-request-API-code.patch @@ -1,16 +1,16 @@ -From b810081f898fc4faec35519c6e7e9d275bf2bbcf Mon Sep 17 00:00:00 2001 +From 457a74f059e5467f7f24f15be1b0e87a34e8cabc Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Sat, 15 Dec 2018 22:32:16 +0100 -Subject: [PATCH] Add common V4L2 request API code +Subject: [PATCH 02/12] Add common V4L2 request API code Signed-off-by: Jonas Karlman --- configure | 12 + libavcodec/Makefile | 1 + libavcodec/hwaccel.h | 2 + - libavcodec/v4l2_request.c | 919 ++++++++++++++++++++++++++++++++++++++ - libavcodec/v4l2_request.h | 69 +++ - 5 files changed, 1003 insertions(+) + libavcodec/v4l2_request.c | 943 ++++++++++++++++++++++++++++++++++++++ + libavcodec/v4l2_request.h | 72 +++ + 5 files changed, 1030 insertions(+) create mode 100644 libavcodec/v4l2_request.c create mode 100644 libavcodec/v4l2_request.h @@ -112,10 +112,10 @@ index 3aaa92571c..2eefc91e7e 100644 #endif /* AVCODEC_HWACCEL_H */ diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c new file mode 100644 -index 0000000000..bf9d049eff +index 0000000000..1dabf77689 --- /dev/null +++ b/libavcodec/v4l2_request.c -@@ -0,0 +1,919 @@ +@@ -0,0 +1,943 @@ +/* + * This file is part of FFmpeg. + * @@ -216,7 +216,7 @@ index 0000000000..bf9d049eff + return control.default_value; +} + -+static int v4l2_request_queue_buffer(V4L2RequestContext *ctx, int request_fd, V4L2RequestBuffer *buf) ++static int v4l2_request_queue_buffer(V4L2RequestContext *ctx, int request_fd, V4L2RequestBuffer *buf, uint32_t flags) +{ + struct v4l2_plane planes[1] = {}; + struct v4l2_buffer buffer = { @@ -226,7 +226,7 @@ index 0000000000..bf9d049eff + .timestamp.tv_usec = buf->index + 1, + .bytesused = buf->used, + .request_fd = request_fd, -+ .flags = (request_fd >= 0) ? V4L2_BUF_FLAG_REQUEST_FD : 0, ++ .flags = ((request_fd >= 0) ? V4L2_BUF_FLAG_REQUEST_FD : 0) | flags, + }; + + if (V4L2_TYPE_IS_MULTIPLANAR(buf->buffer.type)) { @@ -308,7 +308,7 @@ index 0000000000..bf9d049eff + return 0; +} + -+int ff_v4l2_request_decode_frame(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count) ++static int v4l2_request_queue_decode(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count, int first_slice, int last_slice) +{ + V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; + V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0]; @@ -316,7 +316,7 @@ index 0000000000..bf9d049eff + fd_set except_fds; + int ret; + -+ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p used=%u controls=%d index=%d fd=%d request_fd=%d\n", __func__, avctx, req->output.used, count, req->capture.index, req->capture.fd, req->request_fd); ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p used=%u controls=%d index=%d fd=%d request_fd=%d first_slice=%d last_slice=%d\n", __func__, avctx, req->output.used, count, req->capture.index, req->capture.fd, req->request_fd, first_slice, last_slice); + + ret = v4l2_request_set_controls(ctx, req->request_fd, control, count); + if (ret < 0) { @@ -326,16 +326,18 @@ index 0000000000..bf9d049eff + + memset(req->output.addr + req->output.used, 0, AV_INPUT_BUFFER_PADDING_SIZE); + -+ ret = v4l2_request_queue_buffer(ctx, req->request_fd, &req->output); ++ ret = v4l2_request_queue_buffer(ctx, req->request_fd, &req->output, last_slice ? 0 : V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "%s: queue output buffer %d failed for request %d, %s (%d)\n", __func__, req->output.index, req->request_fd, strerror(errno), errno); + return -1; + } + -+ ret = v4l2_request_queue_buffer(ctx, -1, &req->capture); -+ if (ret < 0) { -+ av_log(avctx, AV_LOG_ERROR, "%s: queue capture buffer %d failed for request %d, %s (%d)\n", __func__, req->capture.index, req->request_fd, strerror(errno), errno); -+ return -1; ++ if (first_slice) { ++ ret = v4l2_request_queue_buffer(ctx, -1, &req->capture, 0); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: queue capture buffer %d failed for request %d, %s (%d)\n", __func__, req->capture.index, req->request_fd, strerror(errno), errno); ++ return -1; ++ } + } + + // NOTE: do we need to dequeue when request fails/timeout? @@ -365,10 +367,12 @@ index 0000000000..bf9d049eff + return -1; + } + -+ ret = v4l2_request_dequeue_buffer(ctx, &req->capture); -+ if (ret < 0) { -+ av_log(avctx, AV_LOG_ERROR, "%s: dequeue capture buffer %d failed for request %d, %s (%d)\n", __func__, req->capture.index, req->request_fd, strerror(errno), errno); -+ return -1; ++ if (last_slice) { ++ ret = v4l2_request_dequeue_buffer(ctx, &req->capture); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: dequeue capture buffer %d failed for request %d, %s (%d)\n", __func__, req->capture.index, req->request_fd, strerror(errno), errno); ++ return -1; ++ } + } + + // TODO: check errors @@ -380,7 +384,10 @@ index 0000000000..bf9d049eff + return -1; + } + -+ return v4l2_request_set_drm_descriptor(req, &ctx->format); ++ if (last_slice) ++ return v4l2_request_set_drm_descriptor(req, &ctx->format); ++ ++ return 0; + +fail: + ret = v4l2_request_dequeue_buffer(ctx, &req->output); @@ -398,6 +405,22 @@ index 0000000000..bf9d049eff + return -1; +} + ++int ff_v4l2_request_decode_slice(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count, int first_slice, int last_slice) ++{ ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0]; ++ ++ // fall back to queue each slice as a full frame ++ if ((req->output.capabilities & V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF) != V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF) ++ return v4l2_request_queue_decode(avctx, frame, control, count, 1, 1); ++ ++ return v4l2_request_queue_decode(avctx, frame, control, count, first_slice, last_slice); ++} ++ ++int ff_v4l2_request_decode_frame(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count) ++{ ++ return v4l2_request_queue_decode(avctx, frame, control, count, 1, 1); ++} ++ +static int v4l2_request_try_format(AVCodecContext *avctx, enum v4l2_buf_type type, uint32_t pixelformat) +{ + V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; @@ -866,6 +889,7 @@ index 0000000000..bf9d049eff + } + + buf->index = buffers.index; ++ buf->capabilities = buffers.capabilities; + buf->used = 0; + + buf->buffer.type = type; @@ -1037,10 +1061,10 @@ index 0000000000..bf9d049eff +} diff --git a/libavcodec/v4l2_request.h b/libavcodec/v4l2_request.h new file mode 100644 -index 0000000000..1f45772d8b +index 0000000000..d4146bd4ee --- /dev/null +++ b/libavcodec/v4l2_request.h -@@ -0,0 +1,69 @@ +@@ -0,0 +1,72 @@ +/* + * This file is part of FFmpeg. + * @@ -1081,6 +1105,7 @@ index 0000000000..1f45772d8b + uint32_t height; + uint32_t size; + uint32_t used; ++ uint32_t capabilities; + struct v4l2_buffer buffer; +} V4L2RequestBuffer; + @@ -1101,6 +1126,8 @@ index 0000000000..1f45772d8b + +int ff_v4l2_request_query_control_default_value(AVCodecContext *avctx, uint32_t id); + ++int ff_v4l2_request_decode_slice(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count, int first_slice, int last_slice); ++ +int ff_v4l2_request_decode_frame(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count); + +int ff_v4l2_request_init(AVCodecContext *avctx, uint32_t pixelformat, uint32_t buffersize, struct v4l2_ext_control *control, int count); @@ -1110,3 +1137,6 @@ index 0000000000..1f45772d8b +int ff_v4l2_request_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx); + +#endif /* AVCODEC_V4L2_REQUEST_H */ +-- +2.24.0 + diff --git a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0003-Add-V4L2-request-API-mpeg2-hwaccel.patch b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0003-Add-V4L2-request-API-mpeg2-hwaccel.patch index fc109896e3b..6b8e805364a 100644 --- a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0003-Add-V4L2-request-API-mpeg2-hwaccel.patch +++ b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0003-Add-V4L2-request-API-mpeg2-hwaccel.patch @@ -1,7 +1,7 @@ -From f31319e29405004b84f17e30602f77dae671b53e Mon Sep 17 00:00:00 2001 +From d46c4def125a142419db249051fbaa8e743e3e53 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Sat, 15 Dec 2018 22:32:16 +0100 -Subject: [PATCH] Add V4L2 request API mpeg2 hwaccel +Subject: [PATCH 03/12] Add V4L2 request API mpeg2 hwaccel Signed-off-by: Jonas Karlman --- @@ -242,3 +242,6 @@ index 0000000000..782b9c2471 + .frame_params = ff_v4l2_request_frame_params, + .caps_internal = HWACCEL_CAP_ASYNC_SAFE, +}; +-- +2.24.0 + diff --git a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0004-Add-V4L2-request-API-h264-hwaccel.patch b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0004-Add-V4L2-request-API-h264-hwaccel.patch index 917e385a9c8..11d6588fe7b 100644 --- a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0004-Add-V4L2-request-API-h264-hwaccel.patch +++ b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0004-Add-V4L2-request-API-h264-hwaccel.patch @@ -1,7 +1,7 @@ -From 389f6557715439d5fa974f0cc55e1fa68735ec61 Mon Sep 17 00:00:00 2001 +From fb59440a268d956bffa40604e4422420453b4605 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Sat, 15 Dec 2018 22:32:16 +0100 -Subject: [PATCH] Add V4L2 request API h264 hwaccel +Subject: [PATCH 04/12] Add V4L2 request API h264 hwaccel Signed-off-by: Jernej Skrabec Signed-off-by: Jonas Karlman @@ -11,8 +11,8 @@ Signed-off-by: Jonas Karlman libavcodec/h264_slice.c | 4 + libavcodec/h264dec.c | 3 + libavcodec/hwaccels.h | 1 + - libavcodec/v4l2_request_h264.c | 420 +++++++++++++++++++++++++++++++++ - 6 files changed, 432 insertions(+) + libavcodec/v4l2_request_h264.c | 443 +++++++++++++++++++++++++++++++++ + 6 files changed, 455 insertions(+) create mode 100644 libavcodec/v4l2_request_h264.c diff --git a/configure b/configure @@ -98,10 +98,10 @@ index ef54de2a3b..003200edea 100644 extern const AVHWAccel ff_h264_videotoolbox_hwaccel; diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c new file mode 100644 -index 0000000000..fb9913922d +index 0000000000..81b3c4b092 --- /dev/null +++ b/libavcodec/v4l2_request_h264.c -@@ -0,0 +1,420 @@ +@@ -0,0 +1,443 @@ +/* + * This file is part of FFmpeg. + * @@ -130,6 +130,7 @@ index 0000000000..fb9913922d + struct v4l2_ctrl_h264_scaling_matrix scaling_matrix; + struct v4l2_ctrl_h264_decode_params decode_params; + struct v4l2_ctrl_h264_slice_params slice_params[16]; ++ int first_slice; +} V4L2RequestControlsH264; + +typedef struct V4L2RequestContextH264 { @@ -297,13 +298,22 @@ index 0000000000..fb9913922d +{ + const H264Context *h = avctx->priv_data; + const PPS *pps = h->ps.pps; ++ const SPS *sps = h->ps.sps; + V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private; + + fill_sps(&controls->sps, h); + fill_pps(&controls->pps, h); + + memcpy(controls->scaling_matrix.scaling_list_4x4, pps->scaling_matrix4, sizeof(controls->scaling_matrix.scaling_list_4x4)); -+ memcpy(controls->scaling_matrix.scaling_list_8x8, pps->scaling_matrix8, sizeof(controls->scaling_matrix.scaling_list_8x8)); ++ memcpy(controls->scaling_matrix.scaling_list_8x8[0], pps->scaling_matrix8[0], sizeof(controls->scaling_matrix.scaling_list_8x8[0])); ++ memcpy(controls->scaling_matrix.scaling_list_8x8[1], pps->scaling_matrix8[3], sizeof(controls->scaling_matrix.scaling_list_8x8[1])); ++ ++ if (sps->chroma_format_idc == 3) { ++ memcpy(controls->scaling_matrix.scaling_list_8x8[2], pps->scaling_matrix8[1], sizeof(controls->scaling_matrix.scaling_list_8x8[2])); ++ memcpy(controls->scaling_matrix.scaling_list_8x8[3], pps->scaling_matrix8[4], sizeof(controls->scaling_matrix.scaling_list_8x8[3])); ++ memcpy(controls->scaling_matrix.scaling_list_8x8[4], pps->scaling_matrix8[2], sizeof(controls->scaling_matrix.scaling_list_8x8[4])); ++ memcpy(controls->scaling_matrix.scaling_list_8x8[5], pps->scaling_matrix8[5], sizeof(controls->scaling_matrix.scaling_list_8x8[5])); ++ } + + controls->decode_params = (struct v4l2_ctrl_h264_decode_params) { + .num_slices = 0, @@ -317,13 +327,16 @@ index 0000000000..fb9913922d + + fill_dpb(&controls->decode_params, h); + ++ controls->first_slice = !FIELD_PICTURE(h) || h->first_field; ++ + return ff_v4l2_request_reset_frame(avctx, h->cur_pic_ptr->f); +} + -+static int v4l2_request_h264_end_frame(AVCodecContext *avctx) ++static int v4l2_request_h264_queue_decode(AVCodecContext *avctx, int last_slice) +{ + const H264Context *h = avctx->priv_data; + V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private; ++ V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data; + + struct v4l2_ext_control control[] = { + { @@ -353,6 +366,9 @@ index 0000000000..fb9913922d + }, + }; + ++ if (ctx->decode_mode == V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED) ++ return ff_v4l2_request_decode_slice(avctx, h->cur_pic_ptr->f, control, FF_ARRAY_ELEMS(control), controls->first_slice, last_slice); ++ + return ff_v4l2_request_decode_frame(avctx, h->cur_pic_ptr->f, control, FF_ARRAY_ELEMS(control)); +} + @@ -367,12 +383,13 @@ index 0000000000..fb9913922d + int i, ret, count, slice = FFMIN(controls->decode_params.num_slices, 15); + + if (ctx->decode_mode == V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED && slice) { -+ ret = v4l2_request_h264_end_frame(avctx); ++ ret = v4l2_request_h264_queue_decode(avctx, 0); + if (ret) + return ret; + + ff_v4l2_request_reset_frame(avctx, h->cur_pic_ptr->f); + slice = controls->decode_params.num_slices = 0; ++ controls->first_slice = 0; + } + + controls->slice_params[slice] = (struct v4l2_ctrl_h264_slice_params) { @@ -448,6 +465,12 @@ index 0000000000..fb9913922d + return 0; +} + ++static int v4l2_request_h264_end_frame(AVCodecContext *avctx) ++{ ++ const H264Context *h = avctx->priv_data; ++ return v4l2_request_h264_queue_decode(avctx, !FIELD_PICTURE(h) || !h->first_field); ++} ++ +static int v4l2_request_h264_set_controls(AVCodecContext *avctx) +{ + V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data; @@ -522,3 +545,6 @@ index 0000000000..fb9913922d + .frame_params = ff_v4l2_request_frame_params, + .caps_internal = HWACCEL_CAP_ASYNC_SAFE, +}; +-- +2.24.0 + diff --git a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0005-Add-V4L2-request-API-hevc-hwaccel.patch b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0005-Add-V4L2-request-API-hevc-hwaccel.patch index 17b2063613e..e9a806e67e6 100644 --- a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0005-Add-V4L2-request-API-hevc-hwaccel.patch +++ b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0005-Add-V4L2-request-API-hevc-hwaccel.patch @@ -1,7 +1,7 @@ -From 0cd5948e34df8acdbc84efc7ce662eee03ce88e3 Mon Sep 17 00:00:00 2001 +From 2511b50434e37a56af86bd38b76a6b5cf4d3117b Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Sat, 15 Dec 2018 22:32:16 +0100 -Subject: [PATCH] Add V4L2 request API hevc hwaccel +Subject: [PATCH 05/12] Add V4L2 request API hevc hwaccel Signed-off-by: Jernej Skrabec Signed-off-by: Jonas Karlman @@ -10,8 +10,8 @@ Signed-off-by: Jonas Karlman libavcodec/Makefile | 1 + libavcodec/hevcdec.c | 10 + libavcodec/hwaccels.h | 1 + - libavcodec/v4l2_request_hevc.c | 391 +++++++++++++++++++++++++++++++++ - 5 files changed, 406 insertions(+) + libavcodec/v4l2_request_hevc.c | 527 +++++++++++++++++++++++++++++++++ + 5 files changed, 542 insertions(+) create mode 100644 libavcodec/v4l2_request_hevc.c diff --git a/configure b/configure @@ -103,10 +103,10 @@ index 003200edea..d183675abe 100644 extern const AVHWAccel ff_hevc_videotoolbox_hwaccel; diff --git a/libavcodec/v4l2_request_hevc.c b/libavcodec/v4l2_request_hevc.c new file mode 100644 -index 0000000000..38969d77fb +index 0000000000..da1fd666d7 --- /dev/null +++ b/libavcodec/v4l2_request_hevc.c -@@ -0,0 +1,391 @@ +@@ -0,0 +1,527 @@ +/* + * This file is part of FFmpeg. + * @@ -133,9 +133,17 @@ index 0000000000..38969d77fb + struct v4l2_ctrl_hevc_sps sps; + struct v4l2_ctrl_hevc_pps pps; + struct v4l2_ctrl_hevc_scaling_matrix scaling_matrix; -+ struct v4l2_ctrl_hevc_slice_params slice_params; ++ struct v4l2_ctrl_hevc_slice_params slice_params[16]; ++ int first_slice; ++ int num_slices; //TODO: this should be in control +} V4L2RequestControlsHEVC; + ++typedef struct V4L2RequestContextHEVC { ++ V4L2RequestContext base; ++ int decode_mode; ++ int start_code; ++} V4L2RequestContextHEVC; ++ +static void v4l2_request_hevc_fill_pred_table(const HEVCContext *h, struct v4l2_hevc_pred_weight_table *table) +{ + int32_t luma_weight_denom, chroma_weight_denom; @@ -233,6 +241,9 @@ index 0000000000..38969d77fb + .bit_size = 0, + .data_bit_offset = get_bits_count(&h->HEVClc->gb), + ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ .slice_segment_addr = sh->slice_segment_addr, ++ + /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ + .nal_unit_type = h->nal_unit_type, + .nuh_temporal_id_plus1 = h->temporal_id + 1, @@ -241,27 +252,18 @@ index 0000000000..38969d77fb + .slice_type = sh->slice_type, + .colour_plane_id = sh->colour_plane_id, + .slice_pic_order_cnt = pic->poc, -+ .slice_sao_luma_flag = sh->slice_sample_adaptive_offset_flag[0], -+ .slice_sao_chroma_flag = sh->slice_sample_adaptive_offset_flag[1], -+ .slice_temporal_mvp_enabled_flag = sh->slice_temporal_mvp_enabled_flag, + .num_ref_idx_l0_active_minus1 = sh->nb_refs[L0] ? sh->nb_refs[L0] - 1 : 0, + .num_ref_idx_l1_active_minus1 = sh->nb_refs[L1] ? sh->nb_refs[L1] - 1 : 0, -+ .mvd_l1_zero_flag = sh->mvd_l1_zero_flag, -+ .cabac_init_flag = sh->cabac_init_flag, -+ .collocated_from_l0_flag = sh->collocated_list == L0 ? 1 : 0, + .collocated_ref_idx = sh->slice_temporal_mvp_enabled_flag ? sh->collocated_ref_idx : 0, + .five_minus_max_num_merge_cand = sh->slice_type == HEVC_SLICE_I ? 0 : 5 - sh->max_num_merge_cand, -+ .use_integer_mv_flag = 0, + .slice_qp_delta = sh->slice_qp_delta, + .slice_cb_qp_offset = sh->slice_cb_qp_offset, + .slice_cr_qp_offset = sh->slice_cr_qp_offset, + .slice_act_y_qp_offset = 0, + .slice_act_cb_qp_offset = 0, + .slice_act_cr_qp_offset = 0, -+ .slice_deblocking_filter_disabled_flag = sh->disable_deblocking_filter_flag, + .slice_beta_offset_div2 = sh->beta_offset / 2, + .slice_tc_offset_div2 = sh->tc_offset / 2, -+ .slice_loop_filter_across_slices_enabled_flag = sh->slice_loop_filter_across_slices_enabled_flag, + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture timing SEI message */ + .pic_struct = h->sei.picture_timing.picture_struct, @@ -270,11 +272,32 @@ index 0000000000..38969d77fb + .num_rps_poc_st_curr_before = h->rps[ST_CURR_BEF].nb_refs, + .num_rps_poc_st_curr_after = h->rps[ST_CURR_AFT].nb_refs, + .num_rps_poc_lt_curr = h->rps[LT_CURR].nb_refs, -+ -+ .slice_segment_addr = sh->slice_segment_addr, -+ .first_slice_segment_in_pic_flag = sh->first_slice_in_pic_flag, + }; + ++ if (sh->slice_sample_adaptive_offset_flag[0]) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA; ++ ++ if (sh->slice_sample_adaptive_offset_flag[1]) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA; ++ ++ if (sh->slice_temporal_mvp_enabled_flag) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED; ++ ++ if (sh->mvd_l1_zero_flag) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO; ++ ++ if (sh->cabac_init_flag) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT; ++ ++ if (sh->collocated_list == L0) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0; ++ ++ if (sh->disable_deblocking_filter_flag) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED; ++ ++ if (sh->slice_loop_filter_across_slices_enabled_flag) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED; ++ + for (i = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) { + const HEVCFrame *frame = &h->DPB[i]; + if (frame != pic && (frame->flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF))) { @@ -332,7 +355,6 @@ index 0000000000..38969d77fb + /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */ + controls->sps = (struct v4l2_ctrl_hevc_sps) { + .chroma_format_idc = sps->chroma_format_idc, -+ .separate_colour_plane_flag = sps->separate_colour_plane_flag, + .pic_width_in_luma_samples = sps->width, + .pic_height_in_luma_samples = sps->height, + .bit_depth_luma_minus8 = sps->bit_depth - 8, @@ -347,22 +369,41 @@ index 0000000000..38969d77fb + .log2_diff_max_min_luma_transform_block_size = sps->log2_max_trafo_size - sps->log2_min_tb_size, + .max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter, + .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra, -+ .scaling_list_enabled_flag = sps->scaling_list_enable_flag, -+ .amp_enabled_flag = sps->amp_enabled_flag, -+ .sample_adaptive_offset_enabled_flag = sps->sao_enabled, -+ .pcm_enabled_flag = sps->pcm_enabled_flag, + .pcm_sample_bit_depth_luma_minus1 = sps->pcm.bit_depth - 1, + .pcm_sample_bit_depth_chroma_minus1 = sps->pcm.bit_depth_chroma - 1, + .log2_min_pcm_luma_coding_block_size_minus3 = sps->pcm.log2_min_pcm_cb_size - 3, + .log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size, -+ .pcm_loop_filter_disabled_flag = sps->pcm.loop_filter_disable_flag, + .num_short_term_ref_pic_sets = sps->nb_st_rps, -+ .long_term_ref_pics_present_flag = sps->long_term_ref_pics_present_flag, + .num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps, -+ .sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag, -+ .strong_intra_smoothing_enabled_flag = sps->sps_strong_intra_smoothing_enable_flag, + }; + ++ if (sps->separate_colour_plane_flag) ++ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE; ++ ++ if (sps->scaling_list_enable_flag) ++ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED; ++ ++ if (sps->amp_enabled_flag) ++ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_AMP_ENABLED; ++ ++ if (sps->sao_enabled) ++ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET; ++ ++ if (sps->pcm_enabled_flag) ++ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_PCM_ENABLED; ++ ++ if (sps->pcm.loop_filter_disable_flag) ++ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED; ++ ++ if (sps->long_term_ref_pics_present_flag) ++ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT; ++ ++ if (sps->sps_temporal_mvp_enabled_flag) ++ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED; ++ ++ if (sps->sps_strong_intra_smoothing_enable_flag) ++ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED; ++ + if (sl) { + for (int i = 0; i < 6; i++) { + for (int j = 0; j < 16; j++) @@ -381,41 +422,79 @@ index 0000000000..38969d77fb + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */ + controls->pps = (struct v4l2_ctrl_hevc_pps) { -+ .dependent_slice_segment_flag = pps->dependent_slice_segments_enabled_flag, -+ .output_flag_present_flag = pps->output_flag_present_flag, + .num_extra_slice_header_bits = pps->num_extra_slice_header_bits, -+ .sign_data_hiding_enabled_flag = pps->sign_data_hiding_flag, -+ .cabac_init_present_flag = pps->cabac_init_present_flag, + .init_qp_minus26 = pps->pic_init_qp_minus26, -+ .constrained_intra_pred_flag = pps->constrained_intra_pred_flag, -+ .transform_skip_enabled_flag = pps->transform_skip_enabled_flag, -+ .cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag, + .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth, + .pps_cb_qp_offset = pps->cb_qp_offset, + .pps_cr_qp_offset = pps->cr_qp_offset, -+ .pps_slice_chroma_qp_offsets_present_flag = pps->pic_slice_level_chroma_qp_offsets_present_flag, -+ .weighted_pred_flag = pps->weighted_pred_flag, -+ .weighted_bipred_flag = pps->weighted_bipred_flag, -+ .transquant_bypass_enabled_flag = pps->transquant_bypass_enable_flag, -+ .tiles_enabled_flag = pps->tiles_enabled_flag, -+ .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag, -+ .loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag, -+ .pps_loop_filter_across_slices_enabled_flag = pps->seq_loop_filter_across_slices_enabled_flag, -+ .deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag, -+ .pps_disable_deblocking_filter_flag = pps->disable_dbf, + .pps_beta_offset_div2 = pps->beta_offset / 2, + .pps_tc_offset_div2 = pps->tc_offset / 2, -+ .lists_modification_present_flag = pps->lists_modification_present_flag, + .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2, -+ .slice_segment_header_extension_present_flag = pps->slice_header_extension_present_flag, -+ .scaling_list_enable_flag = pps->scaling_list_data_present_flag, // pps_scaling_list_data_present_flag + }; + ++ if (pps->dependent_slice_segments_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT; ++ ++ if (pps->output_flag_present_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT; ++ ++ if (pps->sign_data_hiding_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED; ++ ++ if (pps->cabac_init_present_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT; ++ ++ if (pps->constrained_intra_pred_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED; ++ ++ if (pps->transform_skip_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED; ++ ++ if (pps->cu_qp_delta_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED; ++ ++ if (pps->pic_slice_level_chroma_qp_offsets_present_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT; ++ ++ if (pps->weighted_pred_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED; ++ ++ if (pps->weighted_bipred_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED; ++ ++ if (pps->transquant_bypass_enable_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED; ++ ++ if (pps->tiles_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_TILES_ENABLED; ++ ++ if (pps->entropy_coding_sync_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED; ++ ++ if (pps->loop_filter_across_tiles_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED; ++ ++ if (pps->seq_loop_filter_across_slices_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED; ++ ++ if (pps->deblocking_filter_override_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED; ++ ++ if (pps->disable_dbf) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER; ++ ++ if (pps->lists_modification_present_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT; ++ ++ if (pps->slice_header_extension_present_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT; ++ + if (pps->tiles_enabled_flag) { + controls->pps.num_tile_columns_minus1 = pps->num_tile_columns - 1; + controls->pps.num_tile_rows_minus1 = pps->num_tile_rows - 1; + -+ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p tiles_enabled_flag=%d num_tile_columns=%d num_tile_rows=%d\n", __func__, avctx, pps->tiles_enabled_flag, pps->num_tile_columns, pps->num_tile_rows); ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p tiles_enabled_flag=%d num_tile_columns=%d num_tile_rows=%d\n", ++ __func__, avctx, pps->tiles_enabled_flag, pps->num_tile_columns, pps->num_tile_rows); + + for (int i = 0; i < pps->num_tile_columns; i++) + controls->pps.column_width_minus1[i] = pps->column_width[i] - 1; @@ -424,14 +503,17 @@ index 0000000000..38969d77fb + controls->pps.row_height_minus1[i] = pps->row_height[i] - 1; + } + ++ controls->first_slice = 1; ++ controls->num_slices = 0; ++ + return ff_v4l2_request_reset_frame(avctx, h->ref->frame); +} + -+static int v4l2_request_hevc_end_frame(AVCodecContext *avctx) ++static int v4l2_request_hevc_queue_decode(AVCodecContext *avctx, int last_slice) +{ + const HEVCContext *h = avctx->priv_data; + V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private; -+ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)h->ref->frame->data[0]; ++ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data; + + struct v4l2_ext_control control[] = { + { @@ -452,35 +534,89 @@ index 0000000000..38969d77fb + { + .id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS, + .ptr = &controls->slice_params, -+ .size = sizeof(controls->slice_params), ++ .size = sizeof(controls->slice_params[0]) * FFMIN(controls->num_slices, 16), + }, + }; + -+ controls->slice_params.bit_size = req->output.used * 8; ++ if (ctx->decode_mode == V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED) ++ return ff_v4l2_request_decode_slice(avctx, h->ref->frame, control, FF_ARRAY_ELEMS(control), controls->first_slice, last_slice); + + return ff_v4l2_request_decode_frame(avctx, h->ref->frame, control, FF_ARRAY_ELEMS(control)); +} + ++static int v4l2_request_hevc_end_frame(AVCodecContext *avctx) ++{ ++ return v4l2_request_hevc_queue_decode(avctx, 1); ++} ++ +static int v4l2_request_hevc_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) +{ + const HEVCContext *h = avctx->priv_data; + V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private; + V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)h->ref->frame->data[0]; ++ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data; ++ int ret, slice = FFMIN(controls->num_slices, 15); ++ ++ if (ctx->decode_mode == V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED && slice) { ++ ret = v4l2_request_hevc_queue_decode(avctx, 0); ++ if (ret) ++ return ret; ++ ++ ff_v4l2_request_reset_frame(avctx, h->ref->frame); ++ slice = controls->num_slices = 0; ++ controls->first_slice = 0; ++ } ++ ++ v4l2_request_hevc_fill_slice_params(h, &controls->slice_params[slice]); ++ ++ ret = ff_v4l2_request_append_output_buffer(avctx, h->ref->frame, buffer, size); ++ if (ret) ++ return ret; ++ ++ controls->slice_params[slice].bit_size = req->output.used * 8; //FIXME ++ controls->num_slices++; ++ ++ return 0; ++} ++ ++static int v4l2_request_hevc_set_controls(AVCodecContext *avctx) ++{ ++ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data; + -+ // HACK: trigger decode per slice -+ if (req->output.used) { -+ v4l2_request_hevc_end_frame(avctx); -+ ff_v4l2_request_reset_frame(avctx, h->ref->frame); ++ struct v4l2_ext_control control[] = { ++ { .id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE, }, ++ { .id = V4L2_CID_MPEG_VIDEO_HEVC_START_CODE, }, ++ }; ++ ++ ctx->decode_mode = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE); ++ if (ctx->decode_mode != V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED && ++ ctx->decode_mode != V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED) { ++ av_log(avctx, AV_LOG_ERROR, "%s: unsupported decode mode, %d\n", __func__, ctx->decode_mode); ++ return AVERROR(EINVAL); ++ } ++ ++ ctx->start_code = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_MPEG_VIDEO_HEVC_START_CODE); ++ if (ctx->start_code != V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE && ++ ctx->start_code != V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B) { ++ av_log(avctx, AV_LOG_ERROR, "%s: unsupported start code, %d\n", __func__, ctx->start_code); ++ return AVERROR(EINVAL); + } + -+ v4l2_request_hevc_fill_slice_params(h, &controls->slice_params); ++ control[0].value = ctx->decode_mode; ++ control[1].value = ctx->start_code; + -+ return ff_v4l2_request_append_output_buffer(avctx, h->ref->frame, buffer, size); ++ return ff_v4l2_request_set_controls(avctx, control, FF_ARRAY_ELEMS(control)); +} + +static int v4l2_request_hevc_init(AVCodecContext *avctx) +{ -+ return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_HEVC_SLICE, 3 * 1024 * 1024, NULL, 0); ++ int ret; ++ ++ ret = ff_v4l2_request_init(avctx, V4L2_PIX_FMT_HEVC_SLICE, 3 * 1024 * 1024, NULL, 0); ++ if (ret) ++ return ret; ++ ++ return v4l2_request_hevc_set_controls(avctx); +} + +const AVHWAccel ff_hevc_v4l2request_hwaccel = { @@ -494,7 +630,10 @@ index 0000000000..38969d77fb + .frame_priv_data_size = sizeof(V4L2RequestControlsHEVC), + .init = v4l2_request_hevc_init, + .uninit = ff_v4l2_request_uninit, -+ .priv_data_size = sizeof(V4L2RequestContext), ++ .priv_data_size = sizeof(V4L2RequestContextHEVC), + .frame_params = ff_v4l2_request_frame_params, + .caps_internal = HWACCEL_CAP_ASYNC_SAFE, +}; +-- +2.24.0 + diff --git a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0006-Add-V4L2-request-API-vp8-hwaccel.patch b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0006-Add-V4L2-request-API-vp8-hwaccel.patch index ffcf5ceeac3..574262453fa 100644 --- a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0006-Add-V4L2-request-API-vp8-hwaccel.patch +++ b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0006-Add-V4L2-request-API-vp8-hwaccel.patch @@ -1,7 +1,7 @@ -From 2537bdd10973c0fc3f757cab01fd71dd0ef6b1e1 Mon Sep 17 00:00:00 2001 +From 13e487a5da1f64901391b99aa094a697fd2889aa Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 22 May 2019 14:46:58 +0200 -Subject: [PATCH] Add V4L2 request API vp8 hwaccel +Subject: [PATCH 06/12] Add V4L2 request API vp8 hwaccel Need to fix the STREAMOFF/STREAMON issue in a proper way. @@ -280,3 +280,6 @@ index 62b9f8bc2d..55966b9d56 100644 #endif NULL }, +-- +2.24.0 + diff --git a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0007-Add-and-use-private-linux-headers-for-V4L2-request-A.patch b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0007-Add-and-use-private-linux-headers-for-V4L2-request-A.patch index ccd7670c68e..c0eb6596095 100644 --- a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0007-Add-and-use-private-linux-headers-for-V4L2-request-A.patch +++ b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0007-Add-and-use-private-linux-headers-for-V4L2-request-A.patch @@ -1,20 +1,21 @@ -From be39d2e3e5228cdc2cf355d85f5566205f6cb65d Mon Sep 17 00:00:00 2001 +From 23e7417b7ceb66f2ff4a98da5b1785d24994f865 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Thu, 14 Feb 2019 23:20:05 +0100 -Subject: [PATCH] Add and use private linux headers for V4L2 request API ctrls +Subject: [PATCH 07/12] Add and use private linux headers for V4L2 request API + ctrls Signed-off-by: Jernej Skrabec --- configure | 6 +- - libavcodec/h264-ctrls.h | 210 ++++++++++++++++++++++++++++++++ - libavcodec/hevc-ctrls.h | 203 ++++++++++++++++++++++++++++++ - libavcodec/mpeg2-ctrls.h | 82 +++++++++++++ + libavcodec/h264-ctrls.h | 210 +++++++++++++++++++++++++++++ + libavcodec/hevc-ctrls.h | 229 ++++++++++++++++++++++++++++++++ + libavcodec/mpeg2-ctrls.h | 82 ++++++++++++ libavcodec/v4l2_request_h264.c | 1 + libavcodec/v4l2_request_hevc.c | 1 + libavcodec/v4l2_request_mpeg2.c | 1 + libavcodec/v4l2_request_vp8.c | 1 + - libavcodec/vp8-ctrls.h | 112 +++++++++++++++++ - 9 files changed, 614 insertions(+), 3 deletions(-) + libavcodec/vp8-ctrls.h | 112 ++++++++++++++++ + 9 files changed, 640 insertions(+), 3 deletions(-) create mode 100644 libavcodec/h264-ctrls.h create mode 100644 libavcodec/hevc-ctrls.h create mode 100644 libavcodec/mpeg2-ctrls.h @@ -269,10 +270,10 @@ index 0000000000..e877bf1d53 +#endif diff --git a/libavcodec/hevc-ctrls.h b/libavcodec/hevc-ctrls.h new file mode 100644 -index 0000000000..eee4479c7a +index 0000000000..d1b094c8aa --- /dev/null +++ b/libavcodec/hevc-ctrls.h -@@ -0,0 +1,203 @@ +@@ -0,0 +1,229 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * These are the HEVC state controls for use with stateless HEVC @@ -295,6 +296,8 @@ index 0000000000..eee4479c7a +#define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_MPEG_BASE + 1009) +#define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_MPEG_BASE + 1010) +#define V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (V4L2_CID_MPEG_BASE + 1011) ++#define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (V4L2_CID_MPEG_BASE + 1015) ++#define V4L2_CID_MPEG_VIDEO_HEVC_START_CODE (V4L2_CID_MPEG_BASE + 1016) + +/* enum v4l2_ctrl_type type values */ +#define V4L2_CTRL_TYPE_HEVC_SPS 0x0120 @@ -302,15 +305,33 @@ index 0000000000..eee4479c7a +#define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0122 +#define V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX 0x0123 + ++enum v4l2_mpeg_video_hevc_decode_mode { ++ V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED, ++ V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED, ++}; ++ ++enum v4l2_mpeg_video_hevc_start_code { ++ V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE, ++ V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B, ++}; ++ +#define V4L2_HEVC_SLICE_TYPE_B 0 +#define V4L2_HEVC_SLICE_TYPE_P 1 +#define V4L2_HEVC_SLICE_TYPE_I 2 + ++#define V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE (1ULL << 0) ++#define V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED (1ULL << 1) ++#define V4L2_HEVC_SPS_FLAG_AMP_ENABLED (1ULL << 2) ++#define V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET (1ULL << 3) ++#define V4L2_HEVC_SPS_FLAG_PCM_ENABLED (1ULL << 4) ++#define V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED (1ULL << 5) ++#define V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT (1ULL << 6) ++#define V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED (1ULL << 7) ++#define V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED (1ULL << 8) ++ +/* The controls are not stable at the moment and will likely be reworked. */ +struct v4l2_ctrl_hevc_sps { + /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */ -+ __u8 chroma_format_idc; -+ __u8 separate_colour_plane_flag; + __u16 pic_width_in_luma_samples; + __u16 pic_height_in_luma_samples; + __u8 bit_depth_luma_minus8; @@ -325,56 +346,56 @@ index 0000000000..eee4479c7a + __u8 log2_diff_max_min_luma_transform_block_size; + __u8 max_transform_hierarchy_depth_inter; + __u8 max_transform_hierarchy_depth_intra; -+ __u8 scaling_list_enabled_flag; -+ __u8 amp_enabled_flag; -+ __u8 sample_adaptive_offset_enabled_flag; -+ __u8 pcm_enabled_flag; + __u8 pcm_sample_bit_depth_luma_minus1; + __u8 pcm_sample_bit_depth_chroma_minus1; + __u8 log2_min_pcm_luma_coding_block_size_minus3; + __u8 log2_diff_max_min_pcm_luma_coding_block_size; -+ __u8 pcm_loop_filter_disabled_flag; + __u8 num_short_term_ref_pic_sets; -+ __u8 long_term_ref_pics_present_flag; + __u8 num_long_term_ref_pics_sps; -+ __u8 sps_temporal_mvp_enabled_flag; -+ __u8 strong_intra_smoothing_enabled_flag; ++ __u8 chroma_format_idc; ++ ++ __u8 padding; ++ ++ __u64 flags; +}; + ++#define V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT (1ULL << 0) ++#define V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT (1ULL << 1) ++#define V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED (1ULL << 2) ++#define V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT (1ULL << 3) ++#define V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED (1ULL << 4) ++#define V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED (1ULL << 5) ++#define V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED (1ULL << 6) ++#define V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT (1ULL << 7) ++#define V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED (1ULL << 8) ++#define V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED (1ULL << 9) ++#define V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED (1ULL << 10) ++#define V4L2_HEVC_PPS_FLAG_TILES_ENABLED (1ULL << 11) ++#define V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED (1ULL << 12) ++#define V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED (1ULL << 13) ++#define V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 14) ++#define V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED (1ULL << 15) ++#define V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER (1ULL << 16) ++#define V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT (1ULL << 17) ++#define V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT (1ULL << 18) ++ +struct v4l2_ctrl_hevc_pps { + /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */ -+ __u8 dependent_slice_segment_flag; -+ __u8 output_flag_present_flag; + __u8 num_extra_slice_header_bits; -+ __u8 sign_data_hiding_enabled_flag; -+ __u8 cabac_init_present_flag; + __s8 init_qp_minus26; -+ __u8 constrained_intra_pred_flag; -+ __u8 transform_skip_enabled_flag; -+ __u8 cu_qp_delta_enabled_flag; + __u8 diff_cu_qp_delta_depth; + __s8 pps_cb_qp_offset; + __s8 pps_cr_qp_offset; -+ __u8 pps_slice_chroma_qp_offsets_present_flag; -+ __u8 weighted_pred_flag; -+ __u8 weighted_bipred_flag; -+ __u8 transquant_bypass_enabled_flag; -+ __u8 tiles_enabled_flag; -+ __u8 entropy_coding_sync_enabled_flag; + __u8 num_tile_columns_minus1; + __u8 num_tile_rows_minus1; + __u8 column_width_minus1[20]; + __u8 row_height_minus1[22]; -+ __u8 loop_filter_across_tiles_enabled_flag; -+ __u8 pps_loop_filter_across_slices_enabled_flag; -+ __u8 deblocking_filter_override_enabled_flag; -+ __u8 pps_disable_deblocking_filter_flag; + __s8 pps_beta_offset_div2; + __s8 pps_tc_offset_div2; -+ __u8 lists_modification_present_flag; + __u8 log2_parallel_merge_level_minus2; -+ __u8 slice_segment_header_extension_present_flag; -+ __u8 scaling_list_enable_flag; ++ ++ __u8 padding[4]; ++ __u64 flags; +}; + +#define V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE 0x01 @@ -392,9 +413,6 @@ index 0000000000..eee4479c7a +}; + +struct v4l2_hevc_pred_weight_table { -+ __u8 luma_log2_weight_denom; -+ __s8 delta_chroma_log2_weight_denom; -+ + __s8 delta_luma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + __s8 luma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + __s8 delta_chroma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; @@ -405,13 +423,30 @@ index 0000000000..eee4479c7a + __s8 delta_chroma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; + __s8 chroma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; + -+ __u8 padding[2]; ++ __u8 padding[6]; ++ ++ __u8 luma_log2_weight_denom; ++ __s8 delta_chroma_log2_weight_denom; +}; + ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA (1ULL << 0) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA (1ULL << 1) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED (1ULL << 2) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO (1ULL << 3) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT (1ULL << 4) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0 (1ULL << 5) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_USE_INTEGER_MV (1ULL << 6) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED (1ULL << 7) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 8) ++ +struct v4l2_ctrl_hevc_slice_params { + __u32 bit_size; + __u32 data_bit_offset; + ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ __u32 slice_segment_addr; ++ __u32 num_entry_point_offsets; ++ + /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ + __u8 nal_unit_type; + __u8 nuh_temporal_id_plus1; @@ -420,33 +455,23 @@ index 0000000000..eee4479c7a + __u8 slice_type; + __u8 colour_plane_id; + __u16 slice_pic_order_cnt; -+ __u8 slice_sao_luma_flag; -+ __u8 slice_sao_chroma_flag; -+ __u8 slice_temporal_mvp_enabled_flag; + __u8 num_ref_idx_l0_active_minus1; + __u8 num_ref_idx_l1_active_minus1; -+ __u8 mvd_l1_zero_flag; -+ __u8 cabac_init_flag; -+ __u8 collocated_from_l0_flag; + __u8 collocated_ref_idx; + __u8 five_minus_max_num_merge_cand; -+ __u8 use_integer_mv_flag; + __s8 slice_qp_delta; + __s8 slice_cb_qp_offset; + __s8 slice_cr_qp_offset; + __s8 slice_act_y_qp_offset; + __s8 slice_act_cb_qp_offset; + __s8 slice_act_cr_qp_offset; -+ __u8 slice_deblocking_filter_disabled_flag; + __s8 slice_beta_offset_div2; + __s8 slice_tc_offset_div2; -+ __u8 slice_loop_filter_across_slices_enabled_flag; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture timing SEI message */ + __u8 pic_struct; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ -+ struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + __u8 num_active_dpb_entries; + __u8 ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + __u8 ref_idx_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; @@ -455,15 +480,17 @@ index 0000000000..eee4479c7a + __u8 num_rps_poc_st_curr_after; + __u8 num_rps_poc_lt_curr; + -+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */ -+ struct v4l2_hevc_pred_weight_table pred_weight_table; ++ __u8 padding; + -+ __u32 slice_segment_addr; -+ __u32 num_entry_point_offsets; + __u32 entry_point_offset_minus1[256]; -+ __u8 first_slice_segment_in_pic_flag; + -+ __u8 padding; ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */ ++ struct v4l2_hevc_pred_weight_table pred_weight_table; ++ ++ __u64 flags; +}; + +struct v4l2_ctrl_hevc_scaling_matrix { @@ -565,7 +592,7 @@ index 0000000000..6601455b3d + +#endif diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c -index fb9913922d..b826c9d356 100644 +index 81b3c4b092..ca306b6a3f 100644 --- a/libavcodec/v4l2_request_h264.c +++ b/libavcodec/v4l2_request_h264.c @@ -19,6 +19,7 @@ @@ -577,7 +604,7 @@ index fb9913922d..b826c9d356 100644 typedef struct V4L2RequestControlsH264 { struct v4l2_ctrl_h264_sps sps; diff --git a/libavcodec/v4l2_request_hevc.c b/libavcodec/v4l2_request_hevc.c -index 38969d77fb..b73eb2ab03 100644 +index da1fd666d7..94977c5d0e 100644 --- a/libavcodec/v4l2_request_hevc.c +++ b/libavcodec/v4l2_request_hevc.c @@ -19,6 +19,7 @@ @@ -730,3 +757,6 @@ index 0000000000..53cba826e4 +}; + +#endif +-- +2.24.0 + diff --git a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0008-hwcontext_drm-do-not-require-drm-device.patch b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0008-hwcontext_drm-do-not-require-drm-device.patch index b8a4cc14ff4..fa816585955 100644 --- a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0008-hwcontext_drm-do-not-require-drm-device.patch +++ b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0008-hwcontext_drm-do-not-require-drm-device.patch @@ -1,7 +1,7 @@ -From 0c4c87e72463da1a4bf45032e4db3c2c86d6d8d8 Mon Sep 17 00:00:00 2001 +From 6b20e11c96907fb474b1bf33615223bf79eba9c0 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Mon, 29 Apr 2019 22:08:59 +0000 -Subject: [PATCH] hwcontext_drm: do not require drm device +Subject: [PATCH 08/12] hwcontext_drm: do not require drm device Signed-off-by: Jonas Karlman --- @@ -24,3 +24,6 @@ index 32cbde82eb..aa4794c5e6 100644 hwctx->fd = open(device, O_RDWR); if (hwctx->fd < 0) return AVERROR(errno); +-- +2.24.0 + diff --git a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0009-avcodec-h264-parse-idr_pic_id.patch b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0009-avcodec-h264-parse-idr_pic_id.patch index 085c87328a0..e9c3524970e 100644 --- a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0009-avcodec-h264-parse-idr_pic_id.patch +++ b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0009-avcodec-h264-parse-idr_pic_id.patch @@ -1,7 +1,7 @@ -From 3d50f433609688b6d4ffb2bcec41507f7f507dc2 Mon Sep 17 00:00:00 2001 +From 4c1ce1fde5ca6d3e80bb0d5ab44f2e05f8372db0 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Wed, 20 Feb 2019 11:18:00 -0300 -Subject: [PATCH] avcodec/h264: parse idr_pic_id +Subject: [PATCH 09/12] avcodec/h264: parse idr_pic_id Signed-off-by: Ezequiel Garcia --- @@ -37,10 +37,10 @@ index b0b42b7672..38efab5c60 100644 int chroma_qp[2]; // QPc int qp_thresh; ///< QP threshold to skip loopfilter diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c -index b826c9d356..a49773b228 100644 +index ca306b6a3f..f21c8b3508 100644 --- a/libavcodec/v4l2_request_h264.c +++ b/libavcodec/v4l2_request_h264.c -@@ -284,7 +284,7 @@ static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t * +@@ -301,7 +301,7 @@ static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t * .pic_parameter_set_id = sl->pps_id, .colour_plane_id = 0, /* what is this? */ .frame_num = h->poc.frame_num, @@ -49,3 +49,6 @@ index b826c9d356..a49773b228 100644 .pic_order_cnt_lsb = sl->poc_lsb, .delta_pic_order_cnt_bottom = sl->delta_poc_bottom, .delta_pic_order_cnt0 = sl->delta_poc[0], +-- +2.24.0 + diff --git a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0010-avcodec-h264-parse-ref_pic_marking_size_in_bits-and-.patch b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0010-avcodec-h264-parse-ref_pic_marking_size_in_bits-and-.patch index 55103f97cbc..43f72ea2d4a 100644 --- a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0010-avcodec-h264-parse-ref_pic_marking_size_in_bits-and-.patch +++ b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0010-avcodec-h264-parse-ref_pic_marking_size_in_bits-and-.patch @@ -1,7 +1,7 @@ -From 2f915e957c6bc5887cc24a8762fdadea17359f57 Mon Sep 17 00:00:00 2001 +From 0a7b4a2cffae5d37b753b3e4cc8cadd7204ef5f5 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 22 May 2019 14:44:22 +0200 -Subject: [PATCH] avcodec/h264: parse ref_pic_marking_size_in_bits and +Subject: [PATCH 10/12] avcodec/h264: parse ref_pic_marking_size_in_bits and pic_order_cnt_bit_size Signed-off-by: Boris Brezillon @@ -71,10 +71,10 @@ index 38efab5c60..8e894f565b 100644 int max_pic_num; } H264SliceContext; diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c -index a49773b228..229df6969d 100644 +index f21c8b3508..1a7fb873a0 100644 --- a/libavcodec/v4l2_request_h264.c +++ b/libavcodec/v4l2_request_h264.c -@@ -292,9 +292,9 @@ static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t * +@@ -309,9 +309,9 @@ static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t * .redundant_pic_cnt = sl->redundant_pic_count, /* Size in bits of dec_ref_pic_marking() syntax element. */ @@ -86,3 +86,6 @@ index a49773b228..229df6969d 100644 .cabac_init_idc = sl->cabac_init_idc, .slice_qp_delta = sl->qscale - pps->init_qp, +-- +2.24.0 + diff --git a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0011-HACK-add-dpb-flags-for-reference-usage-and-field-pic.patch b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0011-HACK-add-dpb-flags-for-reference-usage-and-field-pic.patch index 5c13116c3cf..7c1ae0bc8a1 100644 --- a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0011-HACK-add-dpb-flags-for-reference-usage-and-field-pic.patch +++ b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0011-HACK-add-dpb-flags-for-reference-usage-and-field-pic.patch @@ -1,7 +1,8 @@ -From 45df99d31062e068073cf899dce559e334c9127f Mon Sep 17 00:00:00 2001 +From 1a2197eea4da8f118726963e0c74647532029306 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Fri, 24 May 2019 22:58:24 +0000 -Subject: [PATCH] HACK: add dpb flags for reference usage and field picture +Subject: [PATCH 11/12] HACK: add dpb flags for reference usage and field + picture This or something similar needs to be upstreamed to kernel h264 ctrls @@ -27,10 +28,10 @@ index e877bf1d53..76020ebd1e 100644 struct v4l2_h264_dpb_entry { __u64 reference_ts; diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c -index 229df6969d..7f345b1955 100644 +index 1a7fb873a0..13fac3f6f9 100644 --- a/libavcodec/v4l2_request_h264.c +++ b/libavcodec/v4l2_request_h264.c -@@ -65,10 +65,13 @@ static void fill_dpb_entry(struct v4l2_h264_dpb_entry *entry, const H264Picture +@@ -66,10 +66,13 @@ static void fill_dpb_entry(struct v4l2_h264_dpb_entry *entry, const H264Picture entry->frame_num = pic->frame_num; entry->pic_num = pic->pic_id; entry->flags = V4L2_H264_DPB_ENTRY_FLAG_VALID; @@ -44,7 +45,7 @@ index 229df6969d..7f345b1955 100644 if (pic->field_poc[0] != INT_MAX) entry->top_field_order_cnt = pic->field_poc[0]; if (pic->field_poc[1] != INT_MAX) -@@ -108,7 +111,8 @@ static uint8_t get_dpb_index(struct v4l2_ctrl_h264_decode_params *decode, const +@@ -109,7 +112,8 @@ static uint8_t get_dpb_index(struct v4l2_ctrl_h264_decode_params *decode, const struct v4l2_h264_dpb_entry *entry = &decode->dpb[i]; if ((entry->flags & V4L2_H264_DPB_ENTRY_FLAG_VALID) && entry->reference_ts == timestamp) @@ -54,3 +55,6 @@ index 229df6969d..7f345b1955 100644 } return 0; +-- +2.24.0 + diff --git a/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0012-WIP-v4l2-request-rolling-timestamps.patch b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0012-WIP-v4l2-request-rolling-timestamps.patch new file mode 100644 index 00000000000..de901b06651 --- /dev/null +++ b/packages/multimedia/ffmpeg/patches/v4l2-request-api/ffmpeg-95.0012-WIP-v4l2-request-rolling-timestamps.patch @@ -0,0 +1,72 @@ +From a205c82e430dafd90485b804ce40c1b42cbf9edf Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 9 Nov 2019 10:02:43 +0000 +Subject: [PATCH 12/12] WIP: v4l2-request: rolling timestamps + +--- + libavcodec/v4l2_request.c | 10 +++++++--- + libavcodec/v4l2_request.h | 1 + + 2 files changed, 8 insertions(+), 3 deletions(-) + +diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c +index 1dabf77689..611c22f8b6 100644 +--- a/libavcodec/v4l2_request.c ++++ b/libavcodec/v4l2_request.c +@@ -105,12 +105,14 @@ static int v4l2_request_queue_buffer(V4L2RequestContext *ctx, int request_fd, V4 + .type = buf->buffer.type, + .memory = buf->buffer.memory, + .index = buf->index, +- .timestamp.tv_usec = buf->index + 1, ++ .timestamp.tv_usec = ctx->timestamp, + .bytesused = buf->used, + .request_fd = request_fd, + .flags = ((request_fd >= 0) ? V4L2_BUF_FLAG_REQUEST_FD : 0) | flags, + }; + ++ buf->buffer.timestamp = buffer.timestamp; ++ + if (V4L2_TYPE_IS_MULTIPLANAR(buf->buffer.type)) { + planes[0].bytesused = buf->used; + buffer.bytesused = 0; +@@ -200,6 +202,9 @@ static int v4l2_request_queue_decode(AVCodecContext *avctx, AVFrame *frame, stru + + av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p used=%u controls=%d index=%d fd=%d request_fd=%d first_slice=%d last_slice=%d\n", __func__, avctx, req->output.used, count, req->capture.index, req->capture.fd, req->request_fd, first_slice, last_slice); + ++ if (first_slice) ++ ctx->timestamp++; ++ + ret = v4l2_request_set_controls(ctx, req->request_fd, control, count); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "%s: set controls failed for request %d, %s (%d)\n", __func__, req->request_fd, strerror(errno), errno); +@@ -651,6 +656,7 @@ int ff_v4l2_request_init(AVCodecContext *avctx, uint32_t pixelformat, uint32_t b + + ctx->media_fd = -1; + ctx->video_fd = -1; ++ ctx->timestamp = 0; + + udev = udev_new(); + if (!udev) { +@@ -784,8 +790,6 @@ static int v4l2_request_buffer_alloc(AVCodecContext *avctx, V4L2RequestBuffer *b + return ret; + } + +- buf->buffer.timestamp.tv_usec = buf->index + 1; +- + if (V4L2_TYPE_IS_OUTPUT(type)) { + void *addr = mmap(NULL, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED, ctx->video_fd, V4L2_TYPE_IS_MULTIPLANAR(type) ? buf->buffer.m.planes[0].m.mem_offset : buf->buffer.m.offset); + if (addr == MAP_FAILED) { +diff --git a/libavcodec/v4l2_request.h b/libavcodec/v4l2_request.h +index d4146bd4ee..72698f6f3c 100644 +--- a/libavcodec/v4l2_request.h ++++ b/libavcodec/v4l2_request.h +@@ -28,6 +28,7 @@ typedef struct V4L2RequestContext { + int media_fd; + enum v4l2_buf_type output_type; + struct v4l2_format format; ++ int timestamp; + } V4L2RequestContext; + + typedef struct V4L2RequestBuffer { +-- +2.24.0 + diff --git a/projects/Allwinner/devices/H6/patches/linux/06-10-bit-HEVC-hack.patch b/projects/Allwinner/devices/H6/patches/linux/06-10-bit-HEVC-hack.patch index 2068b70a1e1..1f0ff96882a 100644 --- a/projects/Allwinner/devices/H6/patches/linux/06-10-bit-HEVC-hack.patch +++ b/projects/Allwinner/devices/H6/patches/linux/06-10-bit-HEVC-hack.patch @@ -1,20 +1,20 @@ -From d117460aed81ee5cd384045a1189c9de758d17c6 Mon Sep 17 00:00:00 2001 +From 60808cc1810d47f91c368de8ffb7db59cabceaf9 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Tue, 28 May 2019 21:05:34 +0200 Subject: [PATCH] 10-bit HEVC hack Signed-off-by: Jernej Skrabec --- - drivers/staging/media/sunxi/cedrus/cedrus_h265.c | 12 ++++++++++++ - drivers/staging/media/sunxi/cedrus/cedrus_regs.h | 4 ++++ - drivers/staging/media/sunxi/cedrus/cedrus_video.c | 13 +++++++++++-- - 3 files changed, 27 insertions(+), 2 deletions(-) + .../staging/media/sunxi/cedrus/cedrus_h265.c | 12 +++++++++++ + .../staging/media/sunxi/cedrus/cedrus_regs.h | 4 ++++ + .../staging/media/sunxi/cedrus/cedrus_video.c | 20 ++++++++++++++----- + 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -index 8bbbe69ae51f..04ba7d60ebcd 100644 +index 97dce6ffbbc5..d866662cd5a5 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -@@ -453,6 +453,18 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, +@@ -520,6 +520,18 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, cedrus_write(dev, VE_DEC_H265_DEC_PCM_CTRL, reg); @@ -30,14 +30,14 @@ index 8bbbe69ae51f..04ba7d60ebcd 100644 + cedrus_write(dev, VE_DEC_H265_10BIT_CONFIGURE, ALIGN(reg, 32)); + } + + /* PPS. */ + reg = VE_DEC_H265_DEC_PPS_CTRL0_PPS_CR_QP_OFFSET(pps->pps_cr_qp_offset) | - VE_DEC_H265_DEC_PPS_CTRL0_PPS_CB_QP_OFFSET(pps->pps_cb_qp_offset) | - VE_DEC_H265_DEC_PPS_CTRL0_INIT_QP_MINUS26(pps->init_qp_minus26) | diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -index d1f010ae49ef..dd69031a2779 100644 +index df1cceef8d93..150eae2d92d2 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -@@ -505,6 +505,10 @@ +@@ -498,6 +498,10 @@ #define VE_DEC_H265_LOW_ADDR (VE_ENGINE_DEC_H265 + 0x80) @@ -46,25 +46,25 @@ index d1f010ae49ef..dd69031a2779 100644 +#define VE_DEC_H265_10BIT_CONFIGURE (VE_ENGINE_DEC_H265 + 0x8c) + #define VE_DEC_H265_LOW_ADDR_PRIMARY_CHROMA(a) \ - (((a) << 24) & GENMASK(31, 24)) + SHIFT_AND_MASK_BITS(a, 31, 24) #define VE_DEC_H265_LOW_ADDR_SECONDARY_CHROMA(a) \ diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c -index d27a9e82ff91..2c2288319c9d 100644 +index 497b1199d3fe..178ad45b79d8 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c -@@ -372,6 +372,7 @@ static int cedrus_queue_setup(struct vb2_queue *vq, unsigned int *nbufs, +@@ -367,17 +367,27 @@ static int cedrus_queue_setup(struct vb2_queue *vq, unsigned int *nbufs, + { struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); - struct cedrus_dev *dev = ctx->dev; struct v4l2_pix_format *pix_fmt; + unsigned int extra_size = 0; - u32 directions; - if (V4L2_TYPE_IS_OUTPUT(vq->type)) { -@@ -380,6 +381,14 @@ static int cedrus_queue_setup(struct vb2_queue *vq, unsigned int *nbufs, - } else { - directions = CEDRUS_DECODE_DST; +- if (V4L2_TYPE_IS_OUTPUT(vq->type)) ++ if (V4L2_TYPE_IS_OUTPUT(vq->type)) { + pix_fmt = &ctx->src_fmt; +- else ++ } else { pix_fmt = &ctx->dst_fmt; -+ + + /* The HEVC decoder needs extra size on the output buffer. */ + if (ctx->src_fmt.pixelformat == V4L2_PIX_FMT_HEVC_SLICE) { + extra_size = DIV_ROUND_UP(pix_fmt->width, 4); @@ -72,20 +72,19 @@ index d27a9e82ff91..2c2288319c9d 100644 + extra_size *= ALIGN(pix_fmt->height, 16) * 3; + extra_size /= 2; + } - } - - if (!cedrus_check_format(pix_fmt->pixelformat, directions, -@@ -387,8 +396,8 @@ static int cedrus_queue_setup(struct vb2_queue *vq, unsigned int *nbufs, - return -EINVAL; - ++ } ++ if (*nplanes) { - if (sizes[0] < pix_fmt->sizeimage) - return -EINVAL; + if (sizes[0] < (pix_fmt->sizeimage + extra_size)) + sizes[0] = pix_fmt->sizeimage + extra_size; } else { - sizes[0] = pix_fmt->sizeimage; +- sizes[0] = pix_fmt->sizeimage; ++ sizes[0] = pix_fmt->sizeimage + extra_size; *nplanes = 1; + } + -- -2.21.0 +2.23.0 diff --git a/projects/Allwinner/patches/linux/0001-backport-from-5.4.patch b/projects/Allwinner/patches/linux/0001-backport-from-5.4.patch index 510b1c4de69..9f6cdc885f2 100644 --- a/projects/Allwinner/patches/linux/0001-backport-from-5.4.patch +++ b/projects/Allwinner/patches/linux/0001-backport-from-5.4.patch @@ -5800,3 +5800,845 @@ index 95c312ae94cf..7646636f2d18 100644 -- 2.23.0 +From de8145452eebe5510bd2b142b31560db548d6abb Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Thu, 11 Jul 2019 16:26:41 -0400 +Subject: [PATCH] media: v4l2-ctrl: Move compound control validation + +Rework std_validate moving the compound controls to +its own validation function. + +While here, fix the pointer math to account the index parameter. + +Signed-off-by: Ezequiel Garcia +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/v4l2-core/v4l2-ctrls.c | 126 +++++++++++++++------------ + 1 file changed, 69 insertions(+), 57 deletions(-) + +diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c +index 371537dd8cd3..739418aa9108 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -1629,10 +1629,77 @@ static void std_log(const struct v4l2_ctrl *ctrl) + }) + + /* Validate a new control */ ++static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, ++ union v4l2_ctrl_ptr ptr) ++{ ++ struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; ++ void *p = ptr.p + idx * ctrl->elem_size; ++ ++ switch ((u32)ctrl->type) { ++ case V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS: ++ p_mpeg2_slice_params = p; ++ ++ switch (p_mpeg2_slice_params->sequence.chroma_format) { ++ case 1: /* 4:2:0 */ ++ case 2: /* 4:2:2 */ ++ case 3: /* 4:4:4 */ ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ switch (p_mpeg2_slice_params->picture.intra_dc_precision) { ++ case 0: /* 8 bits */ ++ case 1: /* 9 bits */ ++ case 2: /* 10 bits */ ++ case 3: /* 11 bits */ ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ switch (p_mpeg2_slice_params->picture.picture_structure) { ++ case 1: /* interlaced top field */ ++ case 2: /* interlaced bottom field */ ++ case 3: /* progressive */ ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ switch (p_mpeg2_slice_params->picture.picture_coding_type) { ++ case V4L2_MPEG2_PICTURE_CODING_TYPE_I: ++ case V4L2_MPEG2_PICTURE_CODING_TYPE_P: ++ case V4L2_MPEG2_PICTURE_CODING_TYPE_B: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ break; ++ ++ case V4L2_CTRL_TYPE_MPEG2_QUANTIZATION: ++ break; ++ ++ case V4L2_CTRL_TYPE_FWHT_PARAMS: ++ break; ++ ++ case V4L2_CTRL_TYPE_H264_SPS: ++ case V4L2_CTRL_TYPE_H264_PPS: ++ case V4L2_CTRL_TYPE_H264_SCALING_MATRIX: ++ case V4L2_CTRL_TYPE_H264_SLICE_PARAMS: ++ case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx, + union v4l2_ctrl_ptr ptr) + { +- struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; + size_t len; + u64 offset; + s64 val; +@@ -1695,63 +1762,8 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx, + return -ERANGE; + return 0; + +- case V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS: +- p_mpeg2_slice_params = ptr.p; +- +- switch (p_mpeg2_slice_params->sequence.chroma_format) { +- case 1: /* 4:2:0 */ +- case 2: /* 4:2:2 */ +- case 3: /* 4:4:4 */ +- break; +- default: +- return -EINVAL; +- } +- +- switch (p_mpeg2_slice_params->picture.intra_dc_precision) { +- case 0: /* 8 bits */ +- case 1: /* 9 bits */ +- case 2: /* 10 bits */ +- case 3: /* 11 bits */ +- break; +- default: +- return -EINVAL; +- } +- +- switch (p_mpeg2_slice_params->picture.picture_structure) { +- case 1: /* interlaced top field */ +- case 2: /* interlaced bottom field */ +- case 3: /* progressive */ +- break; +- default: +- return -EINVAL; +- } +- +- switch (p_mpeg2_slice_params->picture.picture_coding_type) { +- case V4L2_MPEG2_PICTURE_CODING_TYPE_I: +- case V4L2_MPEG2_PICTURE_CODING_TYPE_P: +- case V4L2_MPEG2_PICTURE_CODING_TYPE_B: +- break; +- default: +- return -EINVAL; +- } +- +- return 0; +- +- case V4L2_CTRL_TYPE_MPEG2_QUANTIZATION: +- return 0; +- +- case V4L2_CTRL_TYPE_FWHT_PARAMS: +- return 0; +- +- case V4L2_CTRL_TYPE_H264_SPS: +- case V4L2_CTRL_TYPE_H264_PPS: +- case V4L2_CTRL_TYPE_H264_SCALING_MATRIX: +- case V4L2_CTRL_TYPE_H264_SLICE_PARAMS: +- case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: +- return 0; +- + default: +- return -EINVAL; ++ return std_validate_compound(ctrl, idx, ptr); + } + } + +-- +2.23.0 + +From a57d6acaf352d91e52271704f45c72e14cd2d98a Mon Sep 17 00:00:00 2001 +From: Pawel Osciak +Date: Thu, 11 Jul 2019 16:26:42 -0400 +Subject: [PATCH] media: uapi: Add VP8 stateless decoder API + +Add the parsed VP8 frame pixel format and controls, to be used +with the new stateless decoder API for VP8 to provide parameters +for accelerator (aka stateless) codecs. + +Reviewed-by: Tomasz Figa +Reviewed-by: Boris Brezillon +Reviewed-by: Nicolas Dufresne +Signed-off-by: Pawel Osciak +Signed-off-by: Ezequiel Garcia +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + Documentation/media/uapi/v4l/biblio.rst | 10 + + .../media/uapi/v4l/ext-ctrls-codec.rst | 323 ++++++++++++++++++ + .../media/uapi/v4l/pixfmt-compressed.rst | 20 ++ + drivers/media/v4l2-core/v4l2-ctrls.c | 10 + + drivers/media/v4l2-core/v4l2-ioctl.c | 1 + + include/media/v4l2-ctrls.h | 3 + + include/media/vp8-ctrls.h | 110 ++++++ + 7 files changed, 477 insertions(+) + create mode 100644 include/media/vp8-ctrls.h + +diff --git a/Documentation/media/uapi/v4l/biblio.rst b/Documentation/media/uapi/v4l/biblio.rst +index 8f4eb8823d82..ad2ff258afa8 100644 +--- a/Documentation/media/uapi/v4l/biblio.rst ++++ b/Documentation/media/uapi/v4l/biblio.rst +@@ -395,3 +395,13 @@ colimg + :title: Color Imaging: Fundamentals and Applications + + :author: Erik Reinhard et al. ++ ++.. _vp8: ++ ++VP8 ++=== ++ ++ ++:title: RFC 6386: "VP8 Data Format and Decoding Guide" ++ ++:author: J. Bankoski et al. +diff --git a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst +index d6ea2ffd65c5..c5f39dd50043 100644 +--- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst ++++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst +@@ -2234,6 +2234,329 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + Quantization parameter for a P frame for FWHT. Valid range: from 1 + to 31. + ++.. _v4l2-mpeg-vp8: ++ ++``V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER (struct)`` ++ Specifies the frame parameters for the associated VP8 parsed frame data. ++ This includes the necessary parameters for ++ configuring a stateless hardware decoding pipeline for VP8. ++ The bitstream parameters are defined according to :ref:`vp8`. ++ ++ .. note:: ++ ++ This compound control is not yet part of the public kernel API and ++ it is expected to change. ++ ++.. c:type:: v4l2_ctrl_vp8_frame_header ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{5.8cm}|p{4.8cm}|p{6.6cm}| ++ ++.. flat-table:: struct v4l2_ctrl_vp8_frame_header ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - struct :c:type:`v4l2_vp8_segment_header` ++ - ``segment_header`` ++ - Structure with segment-based adjustments metadata. ++ * - struct :c:type:`v4l2_vp8_loopfilter_header` ++ - ``loopfilter_header`` ++ - Structure with loop filter level adjustments metadata. ++ * - struct :c:type:`v4l2_vp8_quantization_header` ++ - ``quant_header`` ++ - Structure with VP8 dequantization indices metadata. ++ * - struct :c:type:`v4l2_vp8_entropy_header` ++ - ``entropy_header`` ++ - Structure with VP8 entropy coder probabilities metadata. ++ * - struct :c:type:`v4l2_vp8_entropy_coder_state` ++ - ``coder_state`` ++ - Structure with VP8 entropy coder state. ++ * - __u16 ++ - ``width`` ++ - The width of the frame. Must be set for all frames. ++ * - __u16 ++ - ``height`` ++ - The height of the frame. Must be set for all frames. ++ * - __u8 ++ - ``horizontal_scale`` ++ - Horizontal scaling factor. ++ * - __u8 ++ - ``vertical_scaling factor`` ++ - Vertical scale. ++ * - __u8 ++ - ``version`` ++ - Bitstream version. ++ * - __u8 ++ - ``prob_skip_false`` ++ - Indicates the probability that the macroblock is not skipped. ++ * - __u8 ++ - ``prob_intra`` ++ - Indicates the probability that a macroblock is intra-predicted. ++ * - __u8 ++ - ``prob_last`` ++ - Indicates the probability that the last reference frame is used ++ for inter-prediction ++ * - __u8 ++ - ``prob_gf`` ++ - Indicates the probability that the golden reference frame is used ++ for inter-prediction ++ * - __u8 ++ - ``num_dct_parts`` ++ - Number of DCT coefficients partitions. Must be one of: 1, 2, 4, or 8. ++ * - __u32 ++ - ``first_part_size`` ++ - Size of the first partition, i.e. the control partition. ++ * - __u32 ++ - ``first_part_header_bits`` ++ - Size in bits of the first partition header portion. ++ * - __u32 ++ - ``dct_part_sizes[8]`` ++ - DCT coefficients sizes. ++ * - __u64 ++ - ``last_frame_ts`` ++ - Timestamp for the V4L2 capture buffer to use as last reference frame, used ++ with inter-coded frames. The timestamp refers to the ``timestamp`` field in ++ struct :c:type:`v4l2_buffer`. Use the :c:func:`v4l2_timeval_to_ns()` ++ function to convert the struct :c:type:`timeval` in struct ++ :c:type:`v4l2_buffer` to a __u64. ++ * - __u64 ++ - ``golden_frame_ts`` ++ - Timestamp for the V4L2 capture buffer to use as last reference frame, used ++ with inter-coded frames. The timestamp refers to the ``timestamp`` field in ++ struct :c:type:`v4l2_buffer`. Use the :c:func:`v4l2_timeval_to_ns()` ++ function to convert the struct :c:type:`timeval` in struct ++ :c:type:`v4l2_buffer` to a __u64. ++ * - __u64 ++ - ``alt_frame_ts`` ++ - Timestamp for the V4L2 capture buffer to use as alternate reference frame, used ++ with inter-coded frames. The timestamp refers to the ``timestamp`` field in ++ struct :c:type:`v4l2_buffer`. Use the :c:func:`v4l2_timeval_to_ns()` ++ function to convert the struct :c:type:`timeval` in struct ++ :c:type:`v4l2_buffer` to a __u64. ++ * - __u64 ++ - ``flags`` ++ - See :ref:`Frame Header Flags ` ++ ++.. _vp8_frame_header_flags: ++ ++``Frame Header Flags`` ++ ++.. cssclass:: longtable ++ ++.. flat-table:: ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - ``V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME`` ++ - 0x01 ++ - Indicates if the frame is a key frame. ++ * - ``V4L2_VP8_FRAME_HEADER_FLAG_EXPERIMENTAL`` ++ - 0x02 ++ - Experimental bitstream. ++ * - ``V4L2_VP8_FRAME_HEADER_FLAG_SHOW_FRAME`` ++ - 0x04 ++ - Show frame flag, indicates if the frame is for display. ++ * - ``V4L2_VP8_FRAME_HEADER_FLAG_MB_NO_SKIP_COEFF`` ++ - 0x08 ++ - Enable/disable skipping of macroblocks with no non-zero coefficients. ++ * - ``V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_GOLDEN`` ++ - 0x10 ++ - Sign of motion vectors when the golden frame is referenced. ++ * - ``V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_ALT`` ++ - 0x20 ++ - Sign of motion vectors when the alt frame is referenced. ++ ++.. c:type:: v4l2_vp8_entropy_coder_state ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: struct v4l2_vp8_entropy_coder_state ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u8 ++ - ``range`` ++ - ++ * - __u8 ++ - ``value`` ++ - ++ * - __u8 ++ - ``bit_count`` ++ - ++ * - __u8 ++ - ``padding`` ++ - Applications and drivers must set this to zero. ++ ++.. c:type:: v4l2_vp8_segment_header ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: struct v4l2_vp8_segment_header ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __s8 ++ - ``quant_update[4]`` ++ - Signed quantizer value update. ++ * - __s8 ++ - ``lf_update[4]`` ++ - Signed loop filter level value update. ++ * - __u8 ++ - ``segment_probs[3]`` ++ - Segment probabilities. ++ * - __u8 ++ - ``padding`` ++ - Applications and drivers must set this to zero. ++ * - __u32 ++ - ``flags`` ++ - See :ref:`Segment Header Flags ` ++ ++.. _vp8_segment_header_flags: ++ ++``Segment Header Flags`` ++ ++.. cssclass:: longtable ++ ++.. flat-table:: ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - ``V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED`` ++ - 0x01 ++ - Enable/disable segment-based adjustments. ++ * - ``V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_MAP`` ++ - 0x02 ++ - Indicates if the macroblock segmentation map is updated in this frame. ++ * - ``V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_FEATURE_DATA`` ++ - 0x04 ++ - Indicates if the segment feature data is updated in this frame. ++ * - ``V4L2_VP8_SEGMENT_HEADER_FLAG_DELTA_VALUE_MODE`` ++ - 0x08 ++ - If is set, the segment feature data mode is delta-value. ++ If cleared, it's absolute-value. ++ ++.. c:type:: v4l2_vp8_loopfilter_header ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: struct v4l2_vp8_loopfilter_header ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __s8 ++ - ``ref_frm_delta[4]`` ++ - Reference adjustment (signed) delta value. ++ * - __s8 ++ - ``mb_mode_delta[4]`` ++ - Macroblock prediction mode adjustment (signed) delta value. ++ * - __u8 ++ - ``sharpness_level`` ++ - Sharpness level ++ * - __u8 ++ - ``level`` ++ - Filter level ++ * - __u16 ++ - ``padding`` ++ - Applications and drivers must set this to zero. ++ * - __u32 ++ - ``flags`` ++ - See :ref:`Loopfilter Header Flags ` ++ ++.. _vp8_loopfilter_header_flags: ++ ++``Loopfilter Header Flags`` ++ ++.. cssclass:: longtable ++ ++.. flat-table:: ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - ``V4L2_VP8_LF_HEADER_ADJ_ENABLE`` ++ - 0x01 ++ - Enable/disable macroblock-level loop filter adjustment. ++ * - ``V4L2_VP8_LF_HEADER_DELTA_UPDATE`` ++ - 0x02 ++ - Indicates if the delta values used in an adjustment are updated. ++ * - ``V4L2_VP8_LF_FILTER_TYPE_SIMPLE`` ++ - 0x04 ++ - If set, indicates the filter type is simple. ++ If cleared, the filter type is normal. ++ ++.. c:type:: v4l2_vp8_quantization_header ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: struct v4l2_vp8_quantization_header ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u8 ++ - ``y_ac_qi`` ++ - Luma AC coefficient table index. ++ * - __s8 ++ - ``y_dc_delta`` ++ - Luma DC delta vaue. ++ * - __s8 ++ - ``y2_dc_delta`` ++ - Y2 block DC delta value. ++ * - __s8 ++ - ``y2_ac_delta`` ++ - Y2 block AC delta value. ++ * - __s8 ++ - ``uv_dc_delta`` ++ - Chroma DC delta value. ++ * - __s8 ++ - ``uv_ac_delta`` ++ - Chroma AC delta value. ++ * - __u16 ++ - ``padding`` ++ - Applications and drivers must set this to zero. ++ ++.. c:type:: v4l2_vp8_entropy_header ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: struct v4l2_vp8_entropy_header ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u8 ++ - ``coeff_probs[4][8][3][11]`` ++ - Coefficient update probabilities. ++ * - __u8 ++ - ``y_mode_probs[4]`` ++ - Luma mode update probabilities. ++ * - __u8 ++ - ``uv_mode_probs[3]`` ++ - Chroma mode update probabilities. ++ * - __u8 ++ - ``mv_probs[2][19]`` ++ - MV decoding update probabilities. ++ * - __u8 ++ - ``padding[3]`` ++ - Applications and drivers must set this to zero. ++ + .. raw:: latex + + \normalsize +diff --git a/Documentation/media/uapi/v4l/pixfmt-compressed.rst b/Documentation/media/uapi/v4l/pixfmt-compressed.rst +index 4b701fc7653e..f52a7b67023d 100644 +--- a/Documentation/media/uapi/v4l/pixfmt-compressed.rst ++++ b/Documentation/media/uapi/v4l/pixfmt-compressed.rst +@@ -133,6 +133,26 @@ Compressed Formats + - ``V4L2_PIX_FMT_VP8`` + - 'VP80' + - VP8 video elementary stream. ++ * .. _V4L2-PIX-FMT-VP8-FRAME: ++ ++ - ``V4L2_PIX_FMT_VP8_FRAME`` ++ - 'VP8F' ++ - VP8 parsed frame, as extracted from the container. ++ This format is adapted for stateless video decoders that implement a ++ VP8 pipeline (using the :ref:`mem2mem` and :ref:`media-request-api`). ++ Metadata associated with the frame to decode is required to be passed ++ through the ``V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER`` control. ++ See the :ref:`associated Codec Control IDs `. ++ Exactly one output and one capture buffer must be provided for use with ++ this pixel format. The output buffer must contain the appropriate number ++ of macroblocks to decode a full corresponding frame to the matching ++ capture buffer. ++ ++ .. note:: ++ ++ This format is not yet part of the public kernel API and it ++ is expected to change. ++ + * .. _V4L2-PIX-FMT-VP9: + + - ``V4L2_PIX_FMT_VP9`` +diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c +index 739418aa9108..b2c9f5816c4a 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -885,6 +885,7 @@ const char *v4l2_ctrl_get_name(u32 id) + case V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP: return "VPX P-Frame QP Value"; + case V4L2_CID_MPEG_VIDEO_VP8_PROFILE: return "VP8 Profile"; + case V4L2_CID_MPEG_VIDEO_VP9_PROFILE: return "VP9 Profile"; ++ case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: return "VP8 Frame Header"; + + /* HEVC controls */ + case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: return "HEVC I-Frame QP Value"; +@@ -1345,6 +1346,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, + case V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS: + *type = V4L2_CTRL_TYPE_H264_DECODE_PARAMS; + break; ++ case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: ++ *type = V4L2_CTRL_TYPE_VP8_FRAME_HEADER; ++ break; + default: + *type = V4L2_CTRL_TYPE_INTEGER; + break; +@@ -1690,6 +1694,9 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + case V4L2_CTRL_TYPE_H264_SLICE_PARAMS: + case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: + break; ++ ++ case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: ++ break; + default: + return -EINVAL; + } +@@ -2360,6 +2367,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, + case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: + elem_size = sizeof(struct v4l2_ctrl_h264_decode_params); + break; ++ case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: ++ elem_size = sizeof(struct v4l2_ctrl_vp8_frame_header); ++ break; + default: + if (type < V4L2_CTRL_COMPOUND_TYPES) + elem_size = sizeof(s32); +diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c +index 20cc23ef730e..80efc581e3f9 100644 +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -1348,6 +1348,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) + case V4L2_PIX_FMT_VC1_ANNEX_G: descr = "VC-1 (SMPTE 412M Annex G)"; break; + case V4L2_PIX_FMT_VC1_ANNEX_L: descr = "VC-1 (SMPTE 412M Annex L)"; break; + case V4L2_PIX_FMT_VP8: descr = "VP8"; break; ++ case V4L2_PIX_FMT_VP8_FRAME: descr = "VP8 Frame"; break; + case V4L2_PIX_FMT_VP9: descr = "VP9"; break; + case V4L2_PIX_FMT_HEVC: descr = "HEVC"; break; /* aka H.265 */ + case V4L2_PIX_FMT_FWHT: descr = "FWHT"; break; /* used in vicodec */ +diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h +index b4433483af23..6e9dc9c44bb1 100644 +--- a/include/media/v4l2-ctrls.h ++++ b/include/media/v4l2-ctrls.h +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + /* forward references */ + struct file; +@@ -48,6 +49,7 @@ struct poll_table_struct; + * @p_h264_scaling_matrix: Pointer to a struct v4l2_ctrl_h264_scaling_matrix. + * @p_h264_slice_params: Pointer to a struct v4l2_ctrl_h264_slice_params. + * @p_h264_decode_params: Pointer to a struct v4l2_ctrl_h264_decode_params. ++ * @p_vp8_frame_header: Pointer to a VP8 frame header structure. + * @p: Pointer to a compound value. + */ + union v4l2_ctrl_ptr { +@@ -65,6 +67,7 @@ union v4l2_ctrl_ptr { + struct v4l2_ctrl_h264_scaling_matrix *p_h264_scaling_matrix; + struct v4l2_ctrl_h264_slice_params *p_h264_slice_params; + struct v4l2_ctrl_h264_decode_params *p_h264_decode_params; ++ struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; + void *p; + }; + +diff --git a/include/media/vp8-ctrls.h b/include/media/vp8-ctrls.h +new file mode 100644 +index 000000000000..6cc2eeea4c90 +--- /dev/null ++++ b/include/media/vp8-ctrls.h +@@ -0,0 +1,110 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * These are the VP8 state controls for use with stateless VP8 ++ * codec drivers. ++ * ++ * It turns out that these structs are not stable yet and will undergo ++ * more changes. So keep them private until they are stable and ready to ++ * become part of the official public API. ++ */ ++ ++#ifndef _VP8_CTRLS_H_ ++#define _VP8_CTRLS_H_ ++ ++#define V4L2_PIX_FMT_VP8_FRAME v4l2_fourcc('V', 'P', '8', 'F') ++ ++#define V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER (V4L2_CID_MPEG_BASE + 2000) ++#define V4L2_CTRL_TYPE_VP8_FRAME_HEADER 0x301 ++ ++#define V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED 0x01 ++#define V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_MAP 0x02 ++#define V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_FEATURE_DATA 0x04 ++#define V4L2_VP8_SEGMENT_HEADER_FLAG_DELTA_VALUE_MODE 0x08 ++ ++struct v4l2_vp8_segment_header { ++ __s8 quant_update[4]; ++ __s8 lf_update[4]; ++ __u8 segment_probs[3]; ++ __u8 padding; ++ __u32 flags; ++}; ++ ++#define V4L2_VP8_LF_HEADER_ADJ_ENABLE 0x01 ++#define V4L2_VP8_LF_HEADER_DELTA_UPDATE 0x02 ++#define V4L2_VP8_LF_FILTER_TYPE_SIMPLE 0x04 ++struct v4l2_vp8_loopfilter_header { ++ __s8 ref_frm_delta[4]; ++ __s8 mb_mode_delta[4]; ++ __u8 sharpness_level; ++ __u8 level; ++ __u16 padding; ++ __u32 flags; ++}; ++ ++struct v4l2_vp8_quantization_header { ++ __u8 y_ac_qi; ++ __s8 y_dc_delta; ++ __s8 y2_dc_delta; ++ __s8 y2_ac_delta; ++ __s8 uv_dc_delta; ++ __s8 uv_ac_delta; ++ __u16 padding; ++}; ++ ++struct v4l2_vp8_entropy_header { ++ __u8 coeff_probs[4][8][3][11]; ++ __u8 y_mode_probs[4]; ++ __u8 uv_mode_probs[3]; ++ __u8 mv_probs[2][19]; ++ __u8 padding[3]; ++}; ++ ++struct v4l2_vp8_entropy_coder_state { ++ __u8 range; ++ __u8 value; ++ __u8 bit_count; ++ __u8 padding; ++}; ++ ++#define V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME 0x01 ++#define V4L2_VP8_FRAME_HEADER_FLAG_EXPERIMENTAL 0x02 ++#define V4L2_VP8_FRAME_HEADER_FLAG_SHOW_FRAME 0x04 ++#define V4L2_VP8_FRAME_HEADER_FLAG_MB_NO_SKIP_COEFF 0x08 ++#define V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_GOLDEN 0x10 ++#define V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_ALT 0x20 ++ ++#define VP8_FRAME_IS_KEY_FRAME(hdr) \ ++ (!!((hdr)->flags & V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME)) ++ ++struct v4l2_ctrl_vp8_frame_header { ++ struct v4l2_vp8_segment_header segment_header; ++ struct v4l2_vp8_loopfilter_header lf_header; ++ struct v4l2_vp8_quantization_header quant_header; ++ struct v4l2_vp8_entropy_header entropy_header; ++ struct v4l2_vp8_entropy_coder_state coder_state; ++ ++ __u16 width; ++ __u16 height; ++ ++ __u8 horizontal_scale; ++ __u8 vertical_scale; ++ ++ __u8 version; ++ __u8 prob_skip_false; ++ __u8 prob_intra; ++ __u8 prob_last; ++ __u8 prob_gf; ++ __u8 num_dct_parts; ++ ++ __u32 first_part_size; ++ __u32 first_part_header_bits; ++ __u32 dct_part_sizes[8]; ++ ++ __u64 last_frame_ts; ++ __u64 golden_frame_ts; ++ __u64 alt_frame_ts; ++ ++ __u64 flags; ++}; ++ ++#endif +-- +2.23.0 + +From 298c62d3856111e6ef41c9c00a233aecf2d19651 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Thu, 11 Jul 2019 16:26:43 -0400 +Subject: [PATCH] media: v4l2-ctrl: Validate VP8 stateless decoder controls + +Only one field needs to be validated: 'num_dct_parts'. +This field is used to iterate over the user-provided array +'dct_part_sizes'. + +Signed-off-by: Ezequiel Garcia +[hverkuil-cisco@xs4all.nl: s -> (s) in zero_padding macro] +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/v4l2-core/v4l2-ctrls.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c +index b2c9f5816c4a..13236c191796 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -1633,10 +1633,15 @@ static void std_log(const struct v4l2_ctrl *ctrl) + }) + + /* Validate a new control */ ++ ++#define zero_padding(s) \ ++ memset(&(s).padding, 0, sizeof((s).padding)) ++ + static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + union v4l2_ctrl_ptr ptr) + { + struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; ++ struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; + void *p = ptr.p + idx * ctrl->elem_size; + + switch ((u32)ctrl->type) { +@@ -1696,6 +1701,22 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + break; + + case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: ++ p_vp8_frame_header = p; ++ ++ switch (p_vp8_frame_header->num_dct_parts) { ++ case 1: ++ case 2: ++ case 4: ++ case 8: ++ break; ++ default: ++ return -EINVAL; ++ } ++ zero_padding(p_vp8_frame_header->segment_header); ++ zero_padding(p_vp8_frame_header->lf_header); ++ zero_padding(p_vp8_frame_header->quant_header); ++ zero_padding(p_vp8_frame_header->entropy_header); ++ zero_padding(p_vp8_frame_header->coder_state); + break; + default: + return -EINVAL; +-- +2.23.0 + diff --git a/projects/Allwinner/patches/linux/0002-backport-from-5.5.patch b/projects/Allwinner/patches/linux/0002-backport-from-5.5.patch index cd1eab09a4d..8b9b5b9c365 100644 --- a/projects/Allwinner/patches/linux/0002-backport-from-5.5.patch +++ b/projects/Allwinner/patches/linux/0002-backport-from-5.5.patch @@ -478,3 +478,4651 @@ index fdc29869d75a..dbe38a54870b 100644 -- 2.23.0 +From 8ae3a0862993c09a8ef0f9abb379553370c517e3 Mon Sep 17 00:00:00 2001 +From: Ricardo Ribalda Delgado +Date: Mon, 7 Oct 2019 12:06:32 -0300 +Subject: [PATCH] media: Documentation: media: Document V4L2_CTRL_TYPE_AREA + +A struct v4l2_area containing the width and the height of a rectangular +area. + +Reviewed-by: Jacopo Mondi +Reviewed-by: Philipp Zabel +Signed-off-by: Ricardo Ribalda Delgado +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + Documentation/media/uapi/v4l/vidioc-queryctrl.rst | 6 ++++++ + Documentation/media/videodev2.h.rst.exceptions | 1 + + 2 files changed, 7 insertions(+) + +diff --git a/Documentation/media/uapi/v4l/vidioc-queryctrl.rst b/Documentation/media/uapi/v4l/vidioc-queryctrl.rst +index a3d56ffbf4cc..33aff21b7d11 100644 +--- a/Documentation/media/uapi/v4l/vidioc-queryctrl.rst ++++ b/Documentation/media/uapi/v4l/vidioc-queryctrl.rst +@@ -443,6 +443,12 @@ See also the examples in :ref:`control`. + - n/a + - A struct :c:type:`v4l2_ctrl_mpeg2_quantization`, containing MPEG-2 + quantization matrices for stateless video decoders. ++ * - ``V4L2_CTRL_TYPE_AREA`` ++ - n/a ++ - n/a ++ - n/a ++ - A struct :c:type:`v4l2_area`, containing the width and the height ++ of a rectangular area. Units depend on the use case. + * - ``V4L2_CTRL_TYPE_H264_SPS`` + - n/a + - n/a +diff --git a/Documentation/media/videodev2.h.rst.exceptions b/Documentation/media/videodev2.h.rst.exceptions +index adeb6b7a15cb..b58e381bdf7b 100644 +--- a/Documentation/media/videodev2.h.rst.exceptions ++++ b/Documentation/media/videodev2.h.rst.exceptions +@@ -141,6 +141,7 @@ replace symbol V4L2_CTRL_TYPE_H264_PPS :c:type:`v4l2_ctrl_type` + replace symbol V4L2_CTRL_TYPE_H264_SCALING_MATRIX :c:type:`v4l2_ctrl_type` + replace symbol V4L2_CTRL_TYPE_H264_SLICE_PARAMS :c:type:`v4l2_ctrl_type` + replace symbol V4L2_CTRL_TYPE_H264_DECODE_PARAMS :c:type:`v4l2_ctrl_type` ++replace symbol V4L2_CTRL_TYPE_AREA :c:type:`v4l2_ctrl_type` + + # V4L2 capability defines + replace define V4L2_CAP_VIDEO_CAPTURE device-capabilities +-- +2.23.0 + +From 61fd036d01111679b01e4b92e6bd0cdd33809aea Mon Sep 17 00:00:00 2001 +From: Ricardo Ribalda Delgado +Date: Mon, 7 Oct 2019 12:06:33 -0300 +Subject: [PATCH] media: add V4L2_CID_UNIT_CELL_SIZE control + +This control returns the unit cell size in nanometres. The struct provides +the width and the height in separated fields to take into consideration +asymmetric pixels and/or hardware binning. +This control is required for automatic calibration of sensors/cameras. + +Reviewed-by: Philipp Zabel +Signed-off-by: Ricardo Ribalda Delgado +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/v4l2-core/v4l2-ctrls.c | 5 +++++ + include/uapi/linux/v4l2-controls.h | 1 + + 2 files changed, 6 insertions(+) + +diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c +index 96cab2e173d3..bf50d37ef6c1 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -996,6 +996,7 @@ const char *v4l2_ctrl_get_name(u32 id) + case V4L2_CID_AUTO_FOCUS_RANGE: return "Auto Focus, Range"; + case V4L2_CID_PAN_SPEED: return "Pan, Speed"; + case V4L2_CID_TILT_SPEED: return "Tilt, Speed"; ++ case V4L2_CID_UNIT_CELL_SIZE: return "Unit Cell Size"; + + /* FM Radio Modulator controls */ + /* Keep the order of the 'case's the same as in v4l2-controls.h! */ +@@ -1377,6 +1378,10 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, + case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: + *type = V4L2_CTRL_TYPE_VP8_FRAME_HEADER; + break; ++ case V4L2_CID_UNIT_CELL_SIZE: ++ *type = V4L2_CTRL_TYPE_AREA; ++ *flags |= V4L2_CTRL_FLAG_READ_ONLY; ++ break; + default: + *type = V4L2_CTRL_TYPE_INTEGER; + break; +diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h +index a2669b79b294..5a7bedee2b0e 100644 +--- a/include/uapi/linux/v4l2-controls.h ++++ b/include/uapi/linux/v4l2-controls.h +@@ -1034,6 +1034,7 @@ enum v4l2_jpeg_chroma_subsampling { + #define V4L2_CID_TEST_PATTERN_GREENR (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 5) + #define V4L2_CID_TEST_PATTERN_BLUE (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 6) + #define V4L2_CID_TEST_PATTERN_GREENB (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 7) ++#define V4L2_CID_UNIT_CELL_SIZE (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 8) + + + /* Image processing controls */ +-- +2.23.0 + +From d1dc49370f8371b00e682ac409aa1987ce641e93 Mon Sep 17 00:00:00 2001 +From: Ricardo Ribalda Delgado +Date: Mon, 7 Oct 2019 12:06:31 -0300 +Subject: [PATCH] media: add V4L2_CTRL_TYPE_AREA control type + +This type contains the width and the height of a rectangular area. + +Reviewed-by: Jacopo Mondi +Signed-off-by: Ricardo Ribalda Delgado +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/v4l2-core/v4l2-ctrls.c | 21 ++++++++++++++ + include/media/v4l2-ctrls.h | 42 ++++++++++++++++++++++++++++ + include/uapi/linux/videodev2.h | 6 ++++ + 3 files changed, 69 insertions(+) + +diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c +index 219d8aeefa20..96cab2e173d3 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -1677,6 +1677,7 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + { + struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; + struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; ++ struct v4l2_area *area; + void *p = ptr.p + idx * ctrl->elem_size; + + switch ((u32)ctrl->type) { +@@ -1753,6 +1754,11 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + zero_padding(p_vp8_frame_header->entropy_header); + zero_padding(p_vp8_frame_header->coder_state); + break; ++ case V4L2_CTRL_TYPE_AREA: ++ area = p; ++ if (!area->width || !area->height) ++ return -EINVAL; ++ break; + default: + return -EINVAL; + } +@@ -2427,6 +2433,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, + case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: + elem_size = sizeof(struct v4l2_ctrl_vp8_frame_header); + break; ++ case V4L2_CTRL_TYPE_AREA: ++ elem_size = sizeof(struct v4l2_area); ++ break; + default: + if (type < V4L2_CTRL_COMPOUND_TYPES) + elem_size = sizeof(s32); +@@ -4116,6 +4125,18 @@ int __v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s) + } + EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_string); + ++int __v4l2_ctrl_s_ctrl_area(struct v4l2_ctrl *ctrl, ++ const struct v4l2_area *area) ++{ ++ lockdep_assert_held(ctrl->handler->lock); ++ ++ /* It's a driver bug if this happens. */ ++ WARN_ON(ctrl->type != V4L2_CTRL_TYPE_AREA); ++ *ctrl->p_new.p_area = *area; ++ return set_ctrl(NULL, ctrl, 0); ++} ++EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_area); ++ + void v4l2_ctrl_request_complete(struct media_request *req, + struct v4l2_ctrl_handler *main_hdl) + { +diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h +index fb0883836548..c9ca867ef32b 100644 +--- a/include/media/v4l2-ctrls.h ++++ b/include/media/v4l2-ctrls.h +@@ -50,6 +50,7 @@ struct poll_table_struct; + * @p_h264_slice_params: Pointer to a struct v4l2_ctrl_h264_slice_params. + * @p_h264_decode_params: Pointer to a struct v4l2_ctrl_h264_decode_params. + * @p_vp8_frame_header: Pointer to a VP8 frame header structure. ++ * @p_area: Pointer to an area. + * @p: Pointer to a compound value. + */ + union v4l2_ctrl_ptr { +@@ -68,6 +69,7 @@ union v4l2_ctrl_ptr { + struct v4l2_ctrl_h264_slice_params *p_h264_slice_params; + struct v4l2_ctrl_h264_decode_params *p_h264_decode_params; + struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; ++ struct v4l2_area *p_area; + void *p; + }; + +@@ -1087,6 +1089,46 @@ static inline int v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s) + return rval; + } + ++/** ++ * __v4l2_ctrl_s_ctrl_area() - Unlocked variant of v4l2_ctrl_s_ctrl_area(). ++ * ++ * @ctrl: The control. ++ * @area: The new area. ++ * ++ * This sets the control's new area safely by going through the control ++ * framework. This function assumes the control's handler is already locked, ++ * allowing it to be used from within the &v4l2_ctrl_ops functions. ++ * ++ * This function is for area type controls only. ++ */ ++int __v4l2_ctrl_s_ctrl_area(struct v4l2_ctrl *ctrl, ++ const struct v4l2_area *area); ++ ++/** ++ * v4l2_ctrl_s_ctrl_area() - Helper function to set a control's area value ++ * from within a driver. ++ * ++ * @ctrl: The control. ++ * @area: The new area. ++ * ++ * This sets the control's new area safely by going through the control ++ * framework. This function will lock the control's handler, so it cannot be ++ * used from within the &v4l2_ctrl_ops functions. ++ * ++ * This function is for area type controls only. ++ */ ++static inline int v4l2_ctrl_s_ctrl_area(struct v4l2_ctrl *ctrl, ++ const struct v4l2_area *area) ++{ ++ int rval; ++ ++ v4l2_ctrl_lock(ctrl); ++ rval = __v4l2_ctrl_s_ctrl_area(ctrl, area); ++ v4l2_ctrl_unlock(ctrl); ++ ++ return rval; ++} ++ + /* Internal helper functions that deal with control events. */ + extern const struct v4l2_subscribed_event_ops v4l2_ctrl_sub_ev_ops; + +diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h +index 530638dffd93..b3c0961b62a0 100644 +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -422,6 +422,11 @@ struct v4l2_fract { + __u32 denominator; + }; + ++struct v4l2_area { ++ __u32 width; ++ __u32 height; ++}; ++ + /** + * struct v4l2_capability - Describes V4L2 device caps returned by VIDIOC_QUERYCAP + * +@@ -1720,6 +1725,7 @@ enum v4l2_ctrl_type { + V4L2_CTRL_TYPE_U8 = 0x0100, + V4L2_CTRL_TYPE_U16 = 0x0101, + V4L2_CTRL_TYPE_U32 = 0x0102, ++ V4L2_CTRL_TYPE_AREA = 0x0106, + }; + + /* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ +-- +2.23.0 + +From 256fa3920874b0f1f4cb79ad6766493a22187153 Mon Sep 17 00:00:00 2001 +From: Paul Kocialkowski +Date: Tue, 22 Oct 2019 12:26:52 -0300 +Subject: [PATCH] media: v4l: Add definitions for HEVC stateless decoding + +This introduces the required definitions for HEVC decoding support with +stateless VPUs. The controls associated to the HEVC slice format provide +the required meta-data for decoding slices extracted from the bitstream. + +They are not exported to the public V4L2 API since reworking this API +will likely be needed for covering various use-cases and new hardware. + +Multi-slice decoding is exposed as a valid decoding mode to match current +H.264 support but it is not yet implemented. + +The interface comes with the following limitations: +* No custom quantization matrices (scaling lists); +* Support for a single temporal layer only; +* No slice entry point offsets support; +* No conformance window support; +* No VUI parameters support; +* No support for SPS extensions: range, multilayer, 3d, scc, 4 bits; +* No support for PPS extensions: range, multilayer, 3d, scc, 4 bits. + +Signed-off-by: Paul Kocialkowski +[hverkuil-cisco@xs4all.nl: use 1ULL in flags defines in hevc-ctrls.h] +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + Documentation/media/uapi/v4l/biblio.rst | 9 + + .../media/uapi/v4l/ext-ctrls-codec.rst | 553 +++++++++++++++++- + .../media/uapi/v4l/vidioc-queryctrl.rst | 18 + + .../media/videodev2.h.rst.exceptions | 3 + + drivers/media/v4l2-core/v4l2-ctrls.c | 109 +++- + drivers/media/v4l2-core/v4l2-ioctl.c | 1 + + include/media/hevc-ctrls.h | 212 +++++++ + include/media/v4l2-ctrls.h | 7 + + 8 files changed, 908 insertions(+), 4 deletions(-) + create mode 100644 include/media/hevc-ctrls.h + +diff --git a/Documentation/media/uapi/v4l/biblio.rst b/Documentation/media/uapi/v4l/biblio.rst +index ad2ff258afa8..8095f57d3d75 100644 +--- a/Documentation/media/uapi/v4l/biblio.rst ++++ b/Documentation/media/uapi/v4l/biblio.rst +@@ -131,6 +131,15 @@ ITU-T Rec. H.264 Specification (04/2017 Edition) + + :author: International Telecommunication Union (http://www.itu.ch) + ++.. _hevc: ++ ++ITU H.265/HEVC ++============== ++ ++:title: ITU-T Rec. H.265 | ISO/IEC 23008-2 "High Efficiency Video Coding" ++ ++:author: International Telecommunication Union (http://www.itu.ch), International Organisation for Standardisation (http://www.iso.ch) ++ + .. _jfif: + + JFIF +diff --git a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst +index 6bb901de0939..a1209f68c5e8 100644 +--- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst ++++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst +@@ -1985,9 +1985,9 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + - ``reference_ts`` + - Timestamp of the V4L2 capture buffer to use as reference, used + with B-coded and P-coded frames. The timestamp refers to the +- ``timestamp`` field in struct :c:type:`v4l2_buffer`. Use the +- :c:func:`v4l2_timeval_to_ns()` function to convert the struct +- :c:type:`timeval` in struct :c:type:`v4l2_buffer` to a __u64. ++ ``timestamp`` field in struct :c:type:`v4l2_buffer`. Use the ++ :c:func:`v4l2_timeval_to_ns()` function to convert the struct ++ :c:type:`timeval` in struct :c:type:`v4l2_buffer` to a __u64. + * - __u16 + - ``frame_num`` + - +@@ -3695,3 +3695,550 @@ enum v4l2_mpeg_video_hevc_size_of_length_field - + Indicates whether to generate SPS and PPS at every IDR. Setting it to 0 + disables generating SPS and PPS at every IDR. Setting it to one enables + generating SPS and PPS at every IDR. ++ ++.. _v4l2-mpeg-hevc: ++ ++``V4L2_CID_MPEG_VIDEO_HEVC_SPS (struct)`` ++ Specifies the Sequence Parameter Set fields (as extracted from the ++ bitstream) for the associated HEVC slice data. ++ These bitstream parameters are defined according to :ref:`hevc`. ++ They are described in section 7.4.3.2 "Sequence parameter set RBSP ++ semantics" of the specification. ++ ++.. c:type:: v4l2_ctrl_hevc_sps ++ ++.. cssclass:: longtable ++ ++.. flat-table:: struct v4l2_ctrl_hevc_sps ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u16 ++ - ``pic_width_in_luma_samples`` ++ - ++ * - __u16 ++ - ``pic_height_in_luma_samples`` ++ - ++ * - __u8 ++ - ``bit_depth_luma_minus8`` ++ - ++ * - __u8 ++ - ``bit_depth_chroma_minus8`` ++ - ++ * - __u8 ++ - ``log2_max_pic_order_cnt_lsb_minus4`` ++ - ++ * - __u8 ++ - ``sps_max_dec_pic_buffering_minus1`` ++ - ++ * - __u8 ++ - ``sps_max_num_reorder_pics`` ++ - ++ * - __u8 ++ - ``sps_max_latency_increase_plus1`` ++ - ++ * - __u8 ++ - ``log2_min_luma_coding_block_size_minus3`` ++ - ++ * - __u8 ++ - ``log2_diff_max_min_luma_coding_block_size`` ++ - ++ * - __u8 ++ - ``log2_min_luma_transform_block_size_minus2`` ++ - ++ * - __u8 ++ - ``log2_diff_max_min_luma_transform_block_size`` ++ - ++ * - __u8 ++ - ``max_transform_hierarchy_depth_inter`` ++ - ++ * - __u8 ++ - ``max_transform_hierarchy_depth_intra`` ++ - ++ * - __u8 ++ - ``pcm_sample_bit_depth_luma_minus1`` ++ - ++ * - __u8 ++ - ``pcm_sample_bit_depth_chroma_minus1`` ++ - ++ * - __u8 ++ - ``log2_min_pcm_luma_coding_block_size_minus3`` ++ - ++ * - __u8 ++ - ``log2_diff_max_min_pcm_luma_coding_block_size`` ++ - ++ * - __u8 ++ - ``num_short_term_ref_pic_sets`` ++ - ++ * - __u8 ++ - ``num_long_term_ref_pics_sps`` ++ - ++ * - __u8 ++ - ``chroma_format_idc`` ++ - ++ * - __u64 ++ - ``flags`` ++ - See :ref:`Sequence Parameter Set Flags ` ++ ++.. _hevc_sps_flags: ++ ++``Sequence Parameter Set Flags`` ++ ++.. cssclass:: longtable ++ ++.. flat-table:: ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - ``V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE`` ++ - 0x00000001 ++ - ++ * - ``V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED`` ++ - 0x00000002 ++ - ++ * - ``V4L2_HEVC_SPS_FLAG_AMP_ENABLED`` ++ - 0x00000004 ++ - ++ * - ``V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET`` ++ - 0x00000008 ++ - ++ * - ``V4L2_HEVC_SPS_FLAG_PCM_ENABLED`` ++ - 0x00000010 ++ - ++ * - ``V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED`` ++ - 0x00000020 ++ - ++ * - ``V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT`` ++ - 0x00000040 ++ - ++ * - ``V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED`` ++ - 0x00000080 ++ - ++ * - ``V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED`` ++ - 0x00000100 ++ - ++ ++``V4L2_CID_MPEG_VIDEO_HEVC_PPS (struct)`` ++ Specifies the Picture Parameter Set fields (as extracted from the ++ bitstream) for the associated HEVC slice data. ++ These bitstream parameters are defined according to :ref:`hevc`. ++ They are described in section 7.4.3.3 "Picture parameter set RBSP ++ semantics" of the specification. ++ ++.. c:type:: v4l2_ctrl_hevc_pps ++ ++.. cssclass:: longtable ++ ++.. flat-table:: struct v4l2_ctrl_hevc_pps ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u8 ++ - ``num_extra_slice_header_bits`` ++ - ++ * - __s8 ++ - ``init_qp_minus26`` ++ - ++ * - __u8 ++ - ``diff_cu_qp_delta_depth`` ++ - ++ * - __s8 ++ - ``pps_cb_qp_offset`` ++ - ++ * - __s8 ++ - ``pps_cr_qp_offset`` ++ - ++ * - __u8 ++ - ``num_tile_columns_minus1`` ++ - ++ * - __u8 ++ - ``num_tile_rows_minus1`` ++ - ++ * - __u8 ++ - ``column_width_minus1[20]`` ++ - ++ * - __u8 ++ - ``row_height_minus1[22]`` ++ - ++ * - __s8 ++ - ``pps_beta_offset_div2`` ++ - ++ * - __s8 ++ - ``pps_tc_offset_div2`` ++ - ++ * - __u8 ++ - ``log2_parallel_merge_level_minus2`` ++ - ++ * - __u8 ++ - ``padding[4]`` ++ - Applications and drivers must set this to zero. ++ * - __u64 ++ - ``flags`` ++ - See :ref:`Picture Parameter Set Flags ` ++ ++.. _hevc_pps_flags: ++ ++``Picture Parameter Set Flags`` ++ ++.. cssclass:: longtable ++ ++.. flat-table:: ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - ``V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT`` ++ - 0x00000001 ++ - ++ * - ``V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT`` ++ - 0x00000002 ++ - ++ * - ``V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED`` ++ - 0x00000004 ++ - ++ * - ``V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT`` ++ - 0x00000008 ++ - ++ * - ``V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED`` ++ - 0x00000010 ++ - ++ * - ``V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED`` ++ - 0x00000020 ++ - ++ * - ``V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED`` ++ - 0x00000040 ++ - ++ * - ``V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT`` ++ - 0x00000080 ++ - ++ * - ``V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED`` ++ - 0x00000100 ++ - ++ * - ``V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED`` ++ - 0x00000200 ++ - ++ * - ``V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED`` ++ - 0x00000400 ++ - ++ * - ``V4L2_HEVC_PPS_FLAG_TILES_ENABLED`` ++ - 0x00000800 ++ - ++ * - ``V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED`` ++ - 0x00001000 ++ - ++ * - ``V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED`` ++ - 0x00002000 ++ - ++ * - ``V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED`` ++ - 0x00004000 ++ - ++ * - ``V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED`` ++ - 0x00008000 ++ - ++ * - ``V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER`` ++ - 0x00010000 ++ - ++ * - ``V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT`` ++ - 0x00020000 ++ - ++ * - ``V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT`` ++ - 0x00040000 ++ - ++ ++``V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (struct)`` ++ Specifies various slice-specific parameters, especially from the NAL unit ++ header, general slice segment header and weighted prediction parameter ++ parts of the bitstream. ++ These bitstream parameters are defined according to :ref:`hevc`. ++ They are described in section 7.4.7 "General slice segment header ++ semantics" of the specification. ++ ++.. c:type:: v4l2_ctrl_hevc_slice_params ++ ++.. cssclass:: longtable ++ ++.. flat-table:: struct v4l2_ctrl_hevc_slice_params ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u32 ++ - ``bit_size`` ++ - Size (in bits) of the current slice data. ++ * - __u32 ++ - ``data_bit_offset`` ++ - Offset (in bits) to the video data in the current slice data. ++ * - __u8 ++ - ``nal_unit_type`` ++ - ++ * - __u8 ++ - ``nuh_temporal_id_plus1`` ++ - ++ * - __u8 ++ - ``slice_type`` ++ - ++ (V4L2_HEVC_SLICE_TYPE_I, V4L2_HEVC_SLICE_TYPE_P or ++ V4L2_HEVC_SLICE_TYPE_B). ++ * - __u8 ++ - ``colour_plane_id`` ++ - ++ * - __u16 ++ - ``slice_pic_order_cnt`` ++ - ++ * - __u8 ++ - ``num_ref_idx_l0_active_minus1`` ++ - ++ * - __u8 ++ - ``num_ref_idx_l1_active_minus1`` ++ - ++ * - __u8 ++ - ``collocated_ref_idx`` ++ - ++ * - __u8 ++ - ``five_minus_max_num_merge_cand`` ++ - ++ * - __s8 ++ - ``slice_qp_delta`` ++ - ++ * - __s8 ++ - ``slice_cb_qp_offset`` ++ - ++ * - __s8 ++ - ``slice_cr_qp_offset`` ++ - ++ * - __s8 ++ - ``slice_act_y_qp_offset`` ++ - ++ * - __s8 ++ - ``slice_act_cb_qp_offset`` ++ - ++ * - __s8 ++ - ``slice_act_cr_qp_offset`` ++ - ++ * - __s8 ++ - ``slice_beta_offset_div2`` ++ - ++ * - __s8 ++ - ``slice_tc_offset_div2`` ++ - ++ * - __u8 ++ - ``pic_struct`` ++ - ++ * - __u8 ++ - ``num_active_dpb_entries`` ++ - The number of entries in ``dpb``. ++ * - __u8 ++ - ``ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` ++ - The list of L0 reference elements as indices in the DPB. ++ * - __u8 ++ - ``ref_idx_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` ++ - The list of L1 reference elements as indices in the DPB. ++ * - __u8 ++ - ``num_rps_poc_st_curr_before`` ++ - The number of reference pictures in the short-term set that come before ++ the current frame. ++ * - __u8 ++ - ``num_rps_poc_st_curr_after`` ++ - The number of reference pictures in the short-term set that come after ++ the current frame. ++ * - __u8 ++ - ``num_rps_poc_lt_curr`` ++ - The number of reference pictures in the long-term set. ++ * - __u8 ++ - ``padding[7]`` ++ - Applications and drivers must set this to zero. ++ * - struct :c:type:`v4l2_hevc_dpb_entry` ++ - ``dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` ++ - The decoded picture buffer, for meta-data about reference frames. ++ * - struct :c:type:`v4l2_hevc_pred_weight_table` ++ - ``pred_weight_table`` ++ - The prediction weight coefficients for inter-picture prediction. ++ * - __u64 ++ - ``flags`` ++ - See :ref:`Slice Parameters Flags ` ++ ++.. _hevc_slice_params_flags: ++ ++``Slice Parameters Flags`` ++ ++.. cssclass:: longtable ++ ++.. flat-table:: ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - ``V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA`` ++ - 0x00000001 ++ - ++ * - ``V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA`` ++ - 0x00000002 ++ - ++ * - ``V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED`` ++ - 0x00000004 ++ - ++ * - ``V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO`` ++ - 0x00000008 ++ - ++ * - ``V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT`` ++ - 0x00000010 ++ - ++ * - ``V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0`` ++ - 0x00000020 ++ - ++ * - ``V4L2_HEVC_SLICE_PARAMS_FLAG_USE_INTEGER_MV`` ++ - 0x00000040 ++ - ++ * - ``V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED`` ++ - 0x00000080 ++ - ++ * - ``V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED`` ++ - 0x00000100 ++ - ++ ++.. c:type:: v4l2_hevc_dpb_entry ++ ++.. cssclass:: longtable ++ ++.. flat-table:: struct v4l2_hevc_dpb_entry ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u64 ++ - ``timestamp`` ++ - Timestamp of the V4L2 capture buffer to use as reference, used ++ with B-coded and P-coded frames. The timestamp refers to the ++ ``timestamp`` field in struct :c:type:`v4l2_buffer`. Use the ++ :c:func:`v4l2_timeval_to_ns()` function to convert the struct ++ :c:type:`timeval` in struct :c:type:`v4l2_buffer` to a __u64. ++ * - __u8 ++ - ``rps`` ++ - The reference set for the reference frame ++ (V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE, ++ V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_AFTER or ++ V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR) ++ * - __u8 ++ - ``field_pic`` ++ - Whether the reference is a field picture or a frame. ++ * - __u16 ++ - ``pic_order_cnt[2]`` ++ - The picture order count of the reference. Only the first element of the ++ array is used for frame pictures, while the first element identifies the ++ top field and the second the bottom field in field-coded pictures. ++ * - __u8 ++ - ``padding[2]`` ++ - Applications and drivers must set this to zero. ++ ++.. c:type:: v4l2_hevc_pred_weight_table ++ ++.. cssclass:: longtable ++ ++.. flat-table:: struct v4l2_hevc_pred_weight_table ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u8 ++ - ``luma_log2_weight_denom`` ++ - ++ * - __s8 ++ - ``delta_chroma_log2_weight_denom`` ++ - ++ * - __s8 ++ - ``delta_luma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` ++ - ++ * - __s8 ++ - ``luma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` ++ - ++ * - __s8 ++ - ``delta_chroma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]`` ++ - ++ * - __s8 ++ - ``chroma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]`` ++ - ++ * - __s8 ++ - ``delta_luma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` ++ - ++ * - __s8 ++ - ``luma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` ++ - ++ * - __s8 ++ - ``delta_chroma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]`` ++ - ++ * - __s8 ++ - ``chroma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]`` ++ - ++ * - __u8 ++ - ``padding[6]`` ++ - Applications and drivers must set this to zero. ++ ++``V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (enum)`` ++ Specifies the decoding mode to use. Currently exposes slice-based and ++ frame-based decoding but new modes might be added later on. ++ This control is used as a modifier for V4L2_PIX_FMT_HEVC_SLICE ++ pixel format. Applications that support V4L2_PIX_FMT_HEVC_SLICE ++ are required to set this control in order to specify the decoding mode ++ that is expected for the buffer. ++ Drivers may expose a single or multiple decoding modes, depending ++ on what they can support. ++ ++ .. note:: ++ ++ This menu control is not yet part of the public kernel API and ++ it is expected to change. ++ ++.. c:type:: v4l2_mpeg_video_hevc_decode_mode ++ ++.. cssclass:: longtable ++ ++.. flat-table:: ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - ``V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED`` ++ - 0 ++ - Decoding is done at the slice granularity. ++ The OUTPUT buffer must contain a single slice. ++ * - ``V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED`` ++ - 1 ++ - Decoding is done at the frame granularity. ++ The OUTPUT buffer must contain all slices needed to decode the ++ frame. The OUTPUT buffer must also contain both fields. ++ ++``V4L2_CID_MPEG_VIDEO_HEVC_START_CODE (enum)`` ++ Specifies the HEVC slice start code expected for each slice. ++ This control is used as a modifier for V4L2_PIX_FMT_HEVC_SLICE ++ pixel format. Applications that support V4L2_PIX_FMT_HEVC_SLICE ++ are required to set this control in order to specify the start code ++ that is expected for the buffer. ++ Drivers may expose a single or multiple start codes, depending ++ on what they can support. ++ ++ .. note:: ++ ++ This menu control is not yet part of the public kernel API and ++ it is expected to change. ++ ++.. c:type:: v4l2_mpeg_video_hevc_start_code ++ ++.. cssclass:: longtable ++ ++.. flat-table:: ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - ``V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE`` ++ - 0 ++ - Selecting this value specifies that HEVC slices are passed ++ to the driver without any start code. ++ * - ``V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B`` ++ - 1 ++ - Selecting this value specifies that HEVC slices are expected ++ to be prefixed by Annex B start codes. According to :ref:`hevc` ++ valid start codes can be 3-bytes 0x000001 or 4-bytes 0x00000001. +diff --git a/Documentation/media/uapi/v4l/vidioc-queryctrl.rst b/Documentation/media/uapi/v4l/vidioc-queryctrl.rst +index 33aff21b7d11..6690928e657b 100644 +--- a/Documentation/media/uapi/v4l/vidioc-queryctrl.rst ++++ b/Documentation/media/uapi/v4l/vidioc-queryctrl.rst +@@ -479,6 +479,24 @@ See also the examples in :ref:`control`. + - n/a + - A struct :c:type:`v4l2_ctrl_h264_decode_params`, containing H264 + decode parameters for stateless video decoders. ++ * - ``V4L2_CTRL_TYPE_HEVC_SPS`` ++ - n/a ++ - n/a ++ - n/a ++ - A struct :c:type:`v4l2_ctrl_hevc_sps`, containing HEVC Sequence ++ Parameter Set for stateless video decoders. ++ * - ``V4L2_CTRL_TYPE_HEVC_PPS`` ++ - n/a ++ - n/a ++ - n/a ++ - A struct :c:type:`v4l2_ctrl_hevc_pps`, containing HEVC Picture ++ Parameter Set for stateless video decoders. ++ * - ``V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS`` ++ - n/a ++ - n/a ++ - n/a ++ - A struct :c:type:`v4l2_ctrl_hevc_slice_params`, containing HEVC ++ slice parameters for stateless video decoders. + + .. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.7cm}| + +diff --git a/Documentation/media/videodev2.h.rst.exceptions b/Documentation/media/videodev2.h.rst.exceptions +index c23e5ef30c78..cb6ccf91776e 100644 +--- a/Documentation/media/videodev2.h.rst.exceptions ++++ b/Documentation/media/videodev2.h.rst.exceptions +@@ -141,6 +141,9 @@ replace symbol V4L2_CTRL_TYPE_H264_PPS :c:type:`v4l2_ctrl_type` + replace symbol V4L2_CTRL_TYPE_H264_SCALING_MATRIX :c:type:`v4l2_ctrl_type` + replace symbol V4L2_CTRL_TYPE_H264_SLICE_PARAMS :c:type:`v4l2_ctrl_type` + replace symbol V4L2_CTRL_TYPE_H264_DECODE_PARAMS :c:type:`v4l2_ctrl_type` ++replace symbol V4L2_CTRL_TYPE_HEVC_SPS :c:type:`v4l2_ctrl_type` ++replace symbol V4L2_CTRL_TYPE_HEVC_PPS :c:type:`v4l2_ctrl_type` ++replace symbol V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS :c:type:`v4l2_ctrl_type` + replace symbol V4L2_CTRL_TYPE_AREA :c:type:`v4l2_ctrl_type` + + # V4L2 capability defines +diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c +index bf50d37ef6c1..b4caf2d4d076 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -568,6 +568,16 @@ const char * const *v4l2_ctrl_get_menu(u32 id) + "Disabled at slice boundary", + "NULL", + }; ++ static const char * const hevc_decode_mode[] = { ++ "Slice-Based", ++ "Frame-Based", ++ NULL, ++ }; ++ static const char * const hevc_start_code[] = { ++ "No Start Code", ++ "Annex B Start Code", ++ NULL, ++ }; + + switch (id) { + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: +@@ -689,7 +699,10 @@ const char * const *v4l2_ctrl_get_menu(u32 id) + return hevc_tier; + case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE: + return hevc_loop_filter_mode; +- ++ case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE: ++ return hevc_decode_mode; ++ case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE: ++ return hevc_start_code; + default: + return NULL; + } +@@ -959,6 +972,11 @@ const char *v4l2_ctrl_get_name(u32 id) + case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD: return "HEVC Size of Length Field"; + case V4L2_CID_MPEG_VIDEO_REF_NUMBER_FOR_PFRAMES: return "Reference Frames for a P-Frame"; + case V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR: return "Prepend SPS and PPS to IDR"; ++ case V4L2_CID_MPEG_VIDEO_HEVC_SPS: return "HEVC Sequence Parameter Set"; ++ case V4L2_CID_MPEG_VIDEO_HEVC_PPS: return "HEVC Picture Parameter Set"; ++ case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: return "HEVC Slice Parameters"; ++ case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE: return "HEVC Decode Mode"; ++ case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE: return "HEVC Start Code"; + + /* CAMERA controls */ + /* Keep the order of the 'case's the same as in v4l2-controls.h! */ +@@ -1268,6 +1286,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, + case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD: + case V4L2_CID_MPEG_VIDEO_HEVC_TIER: + case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE: ++ case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE: ++ case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE: + *type = V4L2_CTRL_TYPE_MENU; + break; + case V4L2_CID_LINK_FREQ: +@@ -1378,6 +1398,15 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, + case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: + *type = V4L2_CTRL_TYPE_VP8_FRAME_HEADER; + break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_SPS: ++ *type = V4L2_CTRL_TYPE_HEVC_SPS; ++ break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_PPS: ++ *type = V4L2_CTRL_TYPE_HEVC_PPS; ++ break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: ++ *type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS; ++ break; + case V4L2_CID_UNIT_CELL_SIZE: + *type = V4L2_CTRL_TYPE_AREA; + *flags |= V4L2_CTRL_FLAG_READ_ONLY; +@@ -1682,8 +1711,12 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + { + struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; + struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; ++ struct v4l2_ctrl_hevc_sps *p_hevc_sps; ++ struct v4l2_ctrl_hevc_pps *p_hevc_pps; ++ struct v4l2_ctrl_hevc_slice_params *p_hevc_slice_params; + struct v4l2_area *area; + void *p = ptr.p + idx * ctrl->elem_size; ++ unsigned int i; + + switch ((u32)ctrl->type) { + case V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS: +@@ -1759,11 +1792,76 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + zero_padding(p_vp8_frame_header->entropy_header); + zero_padding(p_vp8_frame_header->coder_state); + break; ++ ++ case V4L2_CTRL_TYPE_HEVC_SPS: ++ p_hevc_sps = p; ++ ++ if (!(p_hevc_sps->flags & V4L2_HEVC_SPS_FLAG_PCM_ENABLED)) { ++ p_hevc_sps->pcm_sample_bit_depth_luma_minus1 = 0; ++ p_hevc_sps->pcm_sample_bit_depth_chroma_minus1 = 0; ++ p_hevc_sps->log2_min_pcm_luma_coding_block_size_minus3 = 0; ++ p_hevc_sps->log2_diff_max_min_pcm_luma_coding_block_size = 0; ++ } ++ ++ if (!(p_hevc_sps->flags & ++ V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT)) ++ p_hevc_sps->num_long_term_ref_pics_sps = 0; ++ break; ++ ++ case V4L2_CTRL_TYPE_HEVC_PPS: ++ p_hevc_pps = p; ++ ++ if (!(p_hevc_pps->flags & ++ V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED)) ++ p_hevc_pps->diff_cu_qp_delta_depth = 0; ++ ++ if (!(p_hevc_pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED)) { ++ p_hevc_pps->num_tile_columns_minus1 = 0; ++ p_hevc_pps->num_tile_rows_minus1 = 0; ++ memset(&p_hevc_pps->column_width_minus1, 0, ++ sizeof(p_hevc_pps->column_width_minus1)); ++ memset(&p_hevc_pps->row_height_minus1, 0, ++ sizeof(p_hevc_pps->row_height_minus1)); ++ ++ p_hevc_pps->flags &= ++ ~V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED; ++ } ++ ++ if (p_hevc_pps->flags & ++ V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER) { ++ p_hevc_pps->pps_beta_offset_div2 = 0; ++ p_hevc_pps->pps_tc_offset_div2 = 0; ++ } ++ ++ zero_padding(*p_hevc_pps); ++ break; ++ ++ case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: ++ p_hevc_slice_params = p; ++ ++ if (p_hevc_slice_params->num_active_dpb_entries > ++ V4L2_HEVC_DPB_ENTRIES_NUM_MAX) ++ return -EINVAL; ++ ++ zero_padding(p_hevc_slice_params->pred_weight_table); ++ ++ for (i = 0; i < p_hevc_slice_params->num_active_dpb_entries; ++ i++) { ++ struct v4l2_hevc_dpb_entry *dpb_entry = ++ &p_hevc_slice_params->dpb[i]; ++ ++ zero_padding(*dpb_entry); ++ } ++ ++ zero_padding(*p_hevc_slice_params); ++ break; ++ + case V4L2_CTRL_TYPE_AREA: + area = p; + if (!area->width || !area->height) + return -EINVAL; + break; ++ + default: + return -EINVAL; + } +@@ -2438,6 +2536,15 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, + case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: + elem_size = sizeof(struct v4l2_ctrl_vp8_frame_header); + break; ++ case V4L2_CTRL_TYPE_HEVC_SPS: ++ elem_size = sizeof(struct v4l2_ctrl_hevc_sps); ++ break; ++ case V4L2_CTRL_TYPE_HEVC_PPS: ++ elem_size = sizeof(struct v4l2_ctrl_hevc_pps); ++ break; ++ case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: ++ elem_size = sizeof(struct v4l2_ctrl_hevc_slice_params); ++ break; + case V4L2_CTRL_TYPE_AREA: + elem_size = sizeof(struct v4l2_area); + break; +diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c +index 2753073cf340..d26c83d4c255 100644 +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -1367,6 +1367,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) + case V4L2_PIX_FMT_VP8_FRAME: descr = "VP8 Frame"; break; + case V4L2_PIX_FMT_VP9: descr = "VP9"; break; + case V4L2_PIX_FMT_HEVC: descr = "HEVC"; break; /* aka H.265 */ ++ case V4L2_PIX_FMT_HEVC_SLICE: descr = "HEVC Parsed Slice Data"; break; + case V4L2_PIX_FMT_FWHT: descr = "FWHT"; break; /* used in vicodec */ + case V4L2_PIX_FMT_FWHT_STATELESS: descr = "FWHT Stateless"; break; /* used in vicodec */ + case V4L2_PIX_FMT_CPIA1: descr = "GSPCA CPiA YUV"; break; +diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h +new file mode 100644 +index 000000000000..1009cf0891cc +--- /dev/null ++++ b/include/media/hevc-ctrls.h +@@ -0,0 +1,212 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * These are the HEVC state controls for use with stateless HEVC ++ * codec drivers. ++ * ++ * It turns out that these structs are not stable yet and will undergo ++ * more changes. So keep them private until they are stable and ready to ++ * become part of the official public API. ++ */ ++ ++#ifndef _HEVC_CTRLS_H_ ++#define _HEVC_CTRLS_H_ ++ ++#include ++ ++/* The pixel format isn't stable at the moment and will likely be renamed. */ ++#define V4L2_PIX_FMT_HEVC_SLICE v4l2_fourcc('S', '2', '6', '5') /* HEVC parsed slices */ ++ ++#define V4L2_CID_MPEG_VIDEO_HEVC_SPS (V4L2_CID_MPEG_BASE + 1008) ++#define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_MPEG_BASE + 1009) ++#define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_MPEG_BASE + 1010) ++#define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (V4L2_CID_MPEG_BASE + 1015) ++#define V4L2_CID_MPEG_VIDEO_HEVC_START_CODE (V4L2_CID_MPEG_BASE + 1016) ++ ++/* enum v4l2_ctrl_type type values */ ++#define V4L2_CTRL_TYPE_HEVC_SPS 0x0120 ++#define V4L2_CTRL_TYPE_HEVC_PPS 0x0121 ++#define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0122 ++ ++enum v4l2_mpeg_video_hevc_decode_mode { ++ V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED, ++ V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED, ++}; ++ ++enum v4l2_mpeg_video_hevc_start_code { ++ V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE, ++ V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B, ++}; ++ ++#define V4L2_HEVC_SLICE_TYPE_B 0 ++#define V4L2_HEVC_SLICE_TYPE_P 1 ++#define V4L2_HEVC_SLICE_TYPE_I 2 ++ ++#define V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE (1ULL << 0) ++#define V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED (1ULL << 1) ++#define V4L2_HEVC_SPS_FLAG_AMP_ENABLED (1ULL << 2) ++#define V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET (1ULL << 3) ++#define V4L2_HEVC_SPS_FLAG_PCM_ENABLED (1ULL << 4) ++#define V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED (1ULL << 5) ++#define V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT (1ULL << 6) ++#define V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED (1ULL << 7) ++#define V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED (1ULL << 8) ++ ++/* The controls are not stable at the moment and will likely be reworked. */ ++struct v4l2_ctrl_hevc_sps { ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */ ++ __u16 pic_width_in_luma_samples; ++ __u16 pic_height_in_luma_samples; ++ __u8 bit_depth_luma_minus8; ++ __u8 bit_depth_chroma_minus8; ++ __u8 log2_max_pic_order_cnt_lsb_minus4; ++ __u8 sps_max_dec_pic_buffering_minus1; ++ __u8 sps_max_num_reorder_pics; ++ __u8 sps_max_latency_increase_plus1; ++ __u8 log2_min_luma_coding_block_size_minus3; ++ __u8 log2_diff_max_min_luma_coding_block_size; ++ __u8 log2_min_luma_transform_block_size_minus2; ++ __u8 log2_diff_max_min_luma_transform_block_size; ++ __u8 max_transform_hierarchy_depth_inter; ++ __u8 max_transform_hierarchy_depth_intra; ++ __u8 pcm_sample_bit_depth_luma_minus1; ++ __u8 pcm_sample_bit_depth_chroma_minus1; ++ __u8 log2_min_pcm_luma_coding_block_size_minus3; ++ __u8 log2_diff_max_min_pcm_luma_coding_block_size; ++ __u8 num_short_term_ref_pic_sets; ++ __u8 num_long_term_ref_pics_sps; ++ __u8 chroma_format_idc; ++ ++ __u8 padding; ++ ++ __u64 flags; ++}; ++ ++#define V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT (1ULL << 0) ++#define V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT (1ULL << 1) ++#define V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED (1ULL << 2) ++#define V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT (1ULL << 3) ++#define V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED (1ULL << 4) ++#define V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED (1ULL << 5) ++#define V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED (1ULL << 6) ++#define V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT (1ULL << 7) ++#define V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED (1ULL << 8) ++#define V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED (1ULL << 9) ++#define V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED (1ULL << 10) ++#define V4L2_HEVC_PPS_FLAG_TILES_ENABLED (1ULL << 11) ++#define V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED (1ULL << 12) ++#define V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED (1ULL << 13) ++#define V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 14) ++#define V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED (1ULL << 15) ++#define V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER (1ULL << 16) ++#define V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT (1ULL << 17) ++#define V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT (1ULL << 18) ++ ++struct v4l2_ctrl_hevc_pps { ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */ ++ __u8 num_extra_slice_header_bits; ++ __s8 init_qp_minus26; ++ __u8 diff_cu_qp_delta_depth; ++ __s8 pps_cb_qp_offset; ++ __s8 pps_cr_qp_offset; ++ __u8 num_tile_columns_minus1; ++ __u8 num_tile_rows_minus1; ++ __u8 column_width_minus1[20]; ++ __u8 row_height_minus1[22]; ++ __s8 pps_beta_offset_div2; ++ __s8 pps_tc_offset_div2; ++ __u8 log2_parallel_merge_level_minus2; ++ ++ __u8 padding[4]; ++ __u64 flags; ++}; ++ ++#define V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE 0x01 ++#define V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_AFTER 0x02 ++#define V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR 0x03 ++ ++#define V4L2_HEVC_DPB_ENTRIES_NUM_MAX 16 ++ ++struct v4l2_hevc_dpb_entry { ++ __u64 timestamp; ++ __u8 rps; ++ __u8 field_pic; ++ __u16 pic_order_cnt[2]; ++ __u8 padding[2]; ++}; ++ ++struct v4l2_hevc_pred_weight_table { ++ __s8 delta_luma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __s8 luma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __s8 delta_chroma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; ++ __s8 chroma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; ++ ++ __s8 delta_luma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __s8 luma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __s8 delta_chroma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; ++ __s8 chroma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; ++ ++ __u8 padding[6]; ++ ++ __u8 luma_log2_weight_denom; ++ __s8 delta_chroma_log2_weight_denom; ++}; ++ ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA (1ULL << 0) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA (1ULL << 1) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED (1ULL << 2) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO (1ULL << 3) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT (1ULL << 4) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0 (1ULL << 5) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_USE_INTEGER_MV (1ULL << 6) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED (1ULL << 7) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 8) ++ ++struct v4l2_ctrl_hevc_slice_params { ++ __u32 bit_size; ++ __u32 data_bit_offset; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ ++ __u8 nal_unit_type; ++ __u8 nuh_temporal_id_plus1; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ __u8 slice_type; ++ __u8 colour_plane_id; ++ __u16 slice_pic_order_cnt; ++ __u8 num_ref_idx_l0_active_minus1; ++ __u8 num_ref_idx_l1_active_minus1; ++ __u8 collocated_ref_idx; ++ __u8 five_minus_max_num_merge_cand; ++ __s8 slice_qp_delta; ++ __s8 slice_cb_qp_offset; ++ __s8 slice_cr_qp_offset; ++ __s8 slice_act_y_qp_offset; ++ __s8 slice_act_cb_qp_offset; ++ __s8 slice_act_cr_qp_offset; ++ __s8 slice_beta_offset_div2; ++ __s8 slice_tc_offset_div2; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture timing SEI message */ ++ __u8 pic_struct; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ __u8 num_active_dpb_entries; ++ __u8 ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __u8 ref_idx_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ ++ __u8 num_rps_poc_st_curr_before; ++ __u8 num_rps_poc_st_curr_after; ++ __u8 num_rps_poc_lt_curr; ++ ++ __u8 padding; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */ ++ struct v4l2_hevc_pred_weight_table pred_weight_table; ++ ++ __u64 flags; ++}; ++ ++#endif +diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h +index 26205ba3a0a0..e719d56fc024 100644 +--- a/include/media/v4l2-ctrls.h ++++ b/include/media/v4l2-ctrls.h +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + /* forward references */ + struct file; +@@ -50,6 +51,9 @@ struct poll_table_struct; + * @p_h264_slice_params: Pointer to a struct v4l2_ctrl_h264_slice_params. + * @p_h264_decode_params: Pointer to a struct v4l2_ctrl_h264_decode_params. + * @p_vp8_frame_header: Pointer to a VP8 frame header structure. ++ * @p_hevc_sps: Pointer to an HEVC sequence parameter set structure. ++ * @p_hevc_pps: Pointer to an HEVC picture parameter set structure. ++ * @p_hevc_slice_params: Pointer to an HEVC slice parameters structure. + * @p_area: Pointer to an area. + * @p: Pointer to a compound value. + */ +@@ -69,6 +73,9 @@ union v4l2_ctrl_ptr { + struct v4l2_ctrl_h264_slice_params *p_h264_slice_params; + struct v4l2_ctrl_h264_decode_params *p_h264_decode_params; + struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; ++ struct v4l2_ctrl_hevc_sps *p_hevc_sps; ++ struct v4l2_ctrl_hevc_pps *p_hevc_pps; ++ struct v4l2_ctrl_hevc_slice_params *p_hevc_slice_params; + struct v4l2_area *p_area; + void *p; + }; +-- +2.23.0 + +From f8cca8c97a63d77f48334cde81d15014f43530ef Mon Sep 17 00:00:00 2001 +From: Hans Verkuil +Date: Fri, 11 Oct 2019 06:32:41 -0300 +Subject: [PATCH] media: v4l2-mem2mem: support held capture buffers + +Check for held buffers that are ready to be returned to vb2 in +__v4l2_m2m_try_queue(). This avoids drivers having to handle this +case. + +Add v4l2_m2m_buf_done_and_job_finish() to correctly return source +and destination buffers and mark the job as finished while taking +a held destination buffer into account (i.e. that buffer won't be +returned). This has to be done while job_spinlock is held to avoid +race conditions. + +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/v4l2-core/v4l2-mem2mem.c | 130 ++++++++++++++++++------- + include/media/v4l2-mem2mem.h | 33 ++++++- + 2 files changed, 128 insertions(+), 35 deletions(-) + +diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c +index 19937dd3c6f6..79c3656f24f7 100644 +--- a/drivers/media/v4l2-core/v4l2-mem2mem.c ++++ b/drivers/media/v4l2-core/v4l2-mem2mem.c +@@ -284,7 +284,8 @@ static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev) + static void __v4l2_m2m_try_queue(struct v4l2_m2m_dev *m2m_dev, + struct v4l2_m2m_ctx *m2m_ctx) + { +- unsigned long flags_job, flags_out, flags_cap; ++ unsigned long flags_job; ++ struct vb2_v4l2_buffer *dst, *src; + + dprintk("Trying to schedule a job for m2m_ctx: %p\n", m2m_ctx); + +@@ -307,20 +308,30 @@ static void __v4l2_m2m_try_queue(struct v4l2_m2m_dev *m2m_dev, + goto job_unlock; + } + +- spin_lock_irqsave(&m2m_ctx->out_q_ctx.rdy_spinlock, flags_out); +- if (list_empty(&m2m_ctx->out_q_ctx.rdy_queue) +- && !m2m_ctx->out_q_ctx.buffered) { ++ src = v4l2_m2m_next_src_buf(m2m_ctx); ++ dst = v4l2_m2m_next_dst_buf(m2m_ctx); ++ if (!src && !m2m_ctx->out_q_ctx.buffered) { + dprintk("No input buffers available\n"); +- goto out_unlock; ++ goto job_unlock; + } +- spin_lock_irqsave(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags_cap); +- if (list_empty(&m2m_ctx->cap_q_ctx.rdy_queue) +- && !m2m_ctx->cap_q_ctx.buffered) { ++ if (!dst && !m2m_ctx->cap_q_ctx.buffered) { + dprintk("No output buffers available\n"); +- goto cap_unlock; ++ goto job_unlock; ++ } ++ ++ if (src && dst && ++ dst->is_held && dst->vb2_buf.copied_timestamp && ++ dst->vb2_buf.timestamp != src->vb2_buf.timestamp) { ++ dst->is_held = false; ++ v4l2_m2m_dst_buf_remove(m2m_ctx); ++ v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE); ++ dst = v4l2_m2m_next_dst_buf(m2m_ctx); ++ ++ if (!dst && !m2m_ctx->cap_q_ctx.buffered) { ++ dprintk("No output buffers available after returning held buffer\n"); ++ goto job_unlock; ++ } + } +- spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags_cap); +- spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags_out); + + if (m2m_dev->m2m_ops->job_ready + && (!m2m_dev->m2m_ops->job_ready(m2m_ctx->priv))) { +@@ -331,13 +342,6 @@ static void __v4l2_m2m_try_queue(struct v4l2_m2m_dev *m2m_dev, + list_add_tail(&m2m_ctx->queue, &m2m_dev->job_queue); + m2m_ctx->job_flags |= TRANS_QUEUED; + +- spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); +- return; +- +-cap_unlock: +- spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags_cap); +-out_unlock: +- spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags_out); + job_unlock: + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); + } +@@ -412,37 +416,97 @@ static void v4l2_m2m_cancel_job(struct v4l2_m2m_ctx *m2m_ctx) + } + } + +-void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev, +- struct v4l2_m2m_ctx *m2m_ctx) ++/* ++ * Schedule the next job, called from v4l2_m2m_job_finish() or ++ * v4l2_m2m_buf_done_and_job_finish(). ++ */ ++static void v4l2_m2m_schedule_next_job(struct v4l2_m2m_dev *m2m_dev, ++ struct v4l2_m2m_ctx *m2m_ctx) + { +- unsigned long flags; ++ /* ++ * This instance might have more buffers ready, but since we do not ++ * allow more than one job on the job_queue per instance, each has ++ * to be scheduled separately after the previous one finishes. ++ */ ++ __v4l2_m2m_try_queue(m2m_dev, m2m_ctx); + +- spin_lock_irqsave(&m2m_dev->job_spinlock, flags); ++ /* ++ * We might be running in atomic context, ++ * but the job must be run in non-atomic context. ++ */ ++ schedule_work(&m2m_dev->job_work); ++} ++ ++/* ++ * Assumes job_spinlock is held, called from v4l2_m2m_job_finish() or ++ * v4l2_m2m_buf_done_and_job_finish(). ++ */ ++static bool _v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev, ++ struct v4l2_m2m_ctx *m2m_ctx) ++{ + if (!m2m_dev->curr_ctx || m2m_dev->curr_ctx != m2m_ctx) { +- spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); + dprintk("Called by an instance not currently running\n"); +- return; ++ return false; + } + + list_del(&m2m_dev->curr_ctx->queue); + m2m_dev->curr_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING); + wake_up(&m2m_dev->curr_ctx->finished); + m2m_dev->curr_ctx = NULL; ++ return true; ++} + +- spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); +- +- /* This instance might have more buffers ready, but since we do not +- * allow more than one job on the job_queue per instance, each has +- * to be scheduled separately after the previous one finishes. */ +- __v4l2_m2m_try_queue(m2m_dev, m2m_ctx); ++void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev, ++ struct v4l2_m2m_ctx *m2m_ctx) ++{ ++ unsigned long flags; ++ bool schedule_next; + +- /* We might be running in atomic context, +- * but the job must be run in non-atomic context. ++ /* ++ * This function should not be used for drivers that support ++ * holding capture buffers. Those should use ++ * v4l2_m2m_buf_done_and_job_finish() instead. + */ +- schedule_work(&m2m_dev->job_work); ++ WARN_ON(m2m_ctx->cap_q_ctx.q.subsystem_flags & ++ VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF); ++ spin_lock_irqsave(&m2m_dev->job_spinlock, flags); ++ schedule_next = _v4l2_m2m_job_finish(m2m_dev, m2m_ctx); ++ spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); ++ ++ if (schedule_next) ++ v4l2_m2m_schedule_next_job(m2m_dev, m2m_ctx); + } + EXPORT_SYMBOL(v4l2_m2m_job_finish); + ++void v4l2_m2m_buf_done_and_job_finish(struct v4l2_m2m_dev *m2m_dev, ++ struct v4l2_m2m_ctx *m2m_ctx, ++ enum vb2_buffer_state state) ++{ ++ struct vb2_v4l2_buffer *src_buf, *dst_buf; ++ bool schedule_next = false; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&m2m_dev->job_spinlock, flags); ++ src_buf = v4l2_m2m_src_buf_remove(m2m_ctx); ++ dst_buf = v4l2_m2m_next_dst_buf(m2m_ctx); ++ ++ if (WARN_ON(!src_buf || !dst_buf)) ++ goto unlock; ++ v4l2_m2m_buf_done(src_buf, state); ++ dst_buf->is_held = src_buf->flags & V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF; ++ if (!dst_buf->is_held) { ++ v4l2_m2m_dst_buf_remove(m2m_ctx); ++ v4l2_m2m_buf_done(dst_buf, state); ++ } ++ schedule_next = _v4l2_m2m_job_finish(m2m_dev, m2m_ctx); ++unlock: ++ spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); ++ ++ if (schedule_next) ++ v4l2_m2m_schedule_next_job(m2m_dev, m2m_ctx); ++} ++EXPORT_SYMBOL(v4l2_m2m_buf_done_and_job_finish); ++ + int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + struct v4l2_requestbuffers *reqbufs) + { +diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h +index 0b9c3a287061..229d9f5d4370 100644 +--- a/include/media/v4l2-mem2mem.h ++++ b/include/media/v4l2-mem2mem.h +@@ -21,7 +21,8 @@ + * callback. + * The job does NOT have to end before this callback returns + * (and it will be the usual case). When the job finishes, +- * v4l2_m2m_job_finish() has to be called. ++ * v4l2_m2m_job_finish() or v4l2_m2m_buf_done_and_job_finish() ++ * has to be called. + * @job_ready: optional. Should return 0 if the driver does not have a job + * fully prepared to run yet (i.e. it will not be able to finish a + * transaction without sleeping). If not provided, it will be +@@ -33,7 +34,8 @@ + * stop the device safely; e.g. in the next interrupt handler), + * even if the transaction would not have been finished by then. + * After the driver performs the necessary steps, it has to call +- * v4l2_m2m_job_finish() (as if the transaction ended normally). ++ * v4l2_m2m_job_finish() or v4l2_m2m_buf_done_and_job_finish() as ++ * if the transaction ended normally. + * This function does not have to (and will usually not) wait + * until the device enters a state when it can be stopped. + */ +@@ -173,6 +175,33 @@ void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx); + void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev, + struct v4l2_m2m_ctx *m2m_ctx); + ++/** ++ * v4l2_m2m_buf_done_and_job_finish() - return source/destination buffers with ++ * state and inform the framework that a job has been finished and have it ++ * clean up ++ * ++ * @m2m_dev: opaque pointer to the internal data to handle M2M context ++ * @m2m_ctx: m2m context assigned to the instance given by struct &v4l2_m2m_ctx ++ * @state: vb2 buffer state passed to v4l2_m2m_buf_done(). ++ * ++ * Drivers that set V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF must use this ++ * function instead of job_finish() to take held buffers into account. It is ++ * optional for other drivers. ++ * ++ * This function removes the source buffer from the ready list and returns ++ * it with the given state. The same is done for the destination buffer, unless ++ * it is marked 'held'. In that case the buffer is kept on the ready list. ++ * ++ * After that the job is finished (see job_finish()). ++ * ++ * This allows for multiple output buffers to be used to fill in a single ++ * capture buffer. This is typically used by stateless decoders where ++ * multiple e.g. H.264 slices contribute to a single decoded frame. ++ */ ++void v4l2_m2m_buf_done_and_job_finish(struct v4l2_m2m_dev *m2m_dev, ++ struct v4l2_m2m_ctx *m2m_ctx, ++ enum vb2_buffer_state state); ++ + static inline void + v4l2_m2m_buf_done(struct vb2_v4l2_buffer *buf, enum vb2_buffer_state state) + { +-- +2.23.0 + +From bef41d93aac64b54c3008ca6170bec54f85784f5 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 11 Oct 2019 06:32:43 -0300 +Subject: [PATCH] media: v4l2-mem2mem: add stateless_(try_)decoder_cmd ioctl + helpers + +These helpers are used by stateless codecs when they support multiple +slices per frame and hold capture buffer flag is set. It's expected that +all such codecs will use this code. + +Signed-off-by: Jernej Skrabec +Co-developed-by: Hans Verkuil +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/v4l2-core/v4l2-mem2mem.c | 53 ++++++++++++++++++++++++++ + include/media/v4l2-mem2mem.h | 4 ++ + 2 files changed, 57 insertions(+) + +diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c +index 79c3656f24f7..b46d2c388349 100644 +--- a/drivers/media/v4l2-core/v4l2-mem2mem.c ++++ b/drivers/media/v4l2-core/v4l2-mem2mem.c +@@ -1218,6 +1218,59 @@ int v4l2_m2m_ioctl_try_decoder_cmd(struct file *file, void *fh, + } + EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_try_decoder_cmd); + ++int v4l2_m2m_ioctl_stateless_try_decoder_cmd(struct file *file, void *fh, ++ struct v4l2_decoder_cmd *dc) ++{ ++ if (dc->cmd != V4L2_DEC_CMD_FLUSH) ++ return -EINVAL; ++ ++ dc->flags = 0; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_stateless_try_decoder_cmd); ++ ++int v4l2_m2m_ioctl_stateless_decoder_cmd(struct file *file, void *priv, ++ struct v4l2_decoder_cmd *dc) ++{ ++ struct v4l2_fh *fh = file->private_data; ++ struct vb2_v4l2_buffer *out_vb, *cap_vb; ++ struct v4l2_m2m_dev *m2m_dev = fh->m2m_ctx->m2m_dev; ++ unsigned long flags; ++ int ret; ++ ++ ret = v4l2_m2m_ioctl_stateless_try_decoder_cmd(file, priv, dc); ++ if (ret < 0) ++ return ret; ++ ++ spin_lock_irqsave(&m2m_dev->job_spinlock, flags); ++ out_vb = v4l2_m2m_last_src_buf(fh->m2m_ctx); ++ cap_vb = v4l2_m2m_last_dst_buf(fh->m2m_ctx); ++ ++ /* ++ * If there is an out buffer pending, then clear any HOLD flag. ++ * ++ * By clearing this flag we ensure that when this output ++ * buffer is processed any held capture buffer will be released. ++ */ ++ if (out_vb) { ++ out_vb->flags &= ~V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF; ++ } else if (cap_vb && cap_vb->is_held) { ++ /* ++ * If there were no output buffers, but there is a ++ * capture buffer that is held, then release that ++ * buffer. ++ */ ++ cap_vb->is_held = false; ++ v4l2_m2m_dst_buf_remove(fh->m2m_ctx); ++ v4l2_m2m_buf_done(cap_vb, VB2_BUF_STATE_DONE); ++ } ++ spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_stateless_decoder_cmd); ++ + /* + * v4l2_file_operations helpers. It is assumed here same lock is used + * for the output and the capture buffer queue. +diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h +index 229d9f5d4370..3d9e48ed8817 100644 +--- a/include/media/v4l2-mem2mem.h ++++ b/include/media/v4l2-mem2mem.h +@@ -701,6 +701,10 @@ int v4l2_m2m_ioctl_try_encoder_cmd(struct file *file, void *fh, + struct v4l2_encoder_cmd *ec); + int v4l2_m2m_ioctl_try_decoder_cmd(struct file *file, void *fh, + struct v4l2_decoder_cmd *dc); ++int v4l2_m2m_ioctl_stateless_try_decoder_cmd(struct file *file, void *fh, ++ struct v4l2_decoder_cmd *dc); ++int v4l2_m2m_ioctl_stateless_decoder_cmd(struct file *file, void *priv, ++ struct v4l2_decoder_cmd *dc); + int v4l2_m2m_fop_mmap(struct file *file, struct vm_area_struct *vma); + __poll_t v4l2_m2m_fop_poll(struct file *file, poll_table *wait); + +-- +2.23.0 + +From f07602ac388723233e9e3c5a05b54baf34e0a3e9 Mon Sep 17 00:00:00 2001 +From: Hans Verkuil +Date: Fri, 11 Oct 2019 06:32:44 -0300 +Subject: [PATCH] media: v4l2-mem2mem: add new_frame detection + +Drivers that support VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF +typically want to know if a new frame is started (i.e. the first +slice is about to be processed). Add a new_frame bool to v4l2_m2m_ctx +and set it accordingly. + +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/v4l2-core/v4l2-mem2mem.c | 11 +++++++++-- + include/media/v4l2-mem2mem.h | 7 +++++++ + 2 files changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c +index b46d2c388349..db07ef3bf3d0 100644 +--- a/drivers/media/v4l2-core/v4l2-mem2mem.c ++++ b/drivers/media/v4l2-core/v4l2-mem2mem.c +@@ -319,8 +319,10 @@ static void __v4l2_m2m_try_queue(struct v4l2_m2m_dev *m2m_dev, + goto job_unlock; + } + +- if (src && dst && +- dst->is_held && dst->vb2_buf.copied_timestamp && ++ m2m_ctx->new_frame = true; ++ ++ if (src && dst && dst->is_held && ++ dst->vb2_buf.copied_timestamp && + dst->vb2_buf.timestamp != src->vb2_buf.timestamp) { + dst->is_held = false; + v4l2_m2m_dst_buf_remove(m2m_ctx); +@@ -333,6 +335,11 @@ static void __v4l2_m2m_try_queue(struct v4l2_m2m_dev *m2m_dev, + } + } + ++ if (src && dst && (m2m_ctx->cap_q_ctx.q.subsystem_flags & ++ VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF)) ++ m2m_ctx->new_frame = !dst->vb2_buf.copied_timestamp || ++ dst->vb2_buf.timestamp != src->vb2_buf.timestamp; ++ + if (m2m_dev->m2m_ops->job_ready + && (!m2m_dev->m2m_ops->job_ready(m2m_ctx->priv))) { + dprintk("Driver not ready\n"); +diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h +index 3d9e48ed8817..1d85e24791e4 100644 +--- a/include/media/v4l2-mem2mem.h ++++ b/include/media/v4l2-mem2mem.h +@@ -75,6 +75,11 @@ struct v4l2_m2m_queue_ctx { + * struct v4l2_m2m_ctx - Memory to memory context structure + * + * @q_lock: struct &mutex lock ++ * @new_frame: valid in the device_run callback: if true, then this ++ * starts a new frame; if false, then this is a new slice ++ * for an existing frame. This is always true unless ++ * V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF is set, which ++ * indicates slicing support. + * @m2m_dev: opaque pointer to the internal data to handle M2M context + * @cap_q_ctx: Capture (output to memory) queue context + * @out_q_ctx: Output (input from memory) queue context +@@ -91,6 +96,8 @@ struct v4l2_m2m_ctx { + /* optional cap/out vb2 queues lock */ + struct mutex *q_lock; + ++ bool new_frame; ++ + /* internal use only */ + struct v4l2_m2m_dev *m2m_dev; + +-- +2.23.0 + +From ae0688f659adb17ae6ae5710c886b20b5406e5c4 Mon Sep 17 00:00:00 2001 +From: Hans Verkuil +Date: Fri, 30 Aug 2019 06:26:22 -0300 +Subject: [PATCH] media: cedrus: fill in bus_info for media device + +Fixes this compliance warning: + +$ v4l2-compliance -m0 +v4l2-compliance SHA: b514d615166bdc0901a4c71261b87db31e89f464, 32 bits + +Compliance test for cedrus device /dev/media0: + +Media Driver Info: + Driver name : cedrus + Model : cedrus + Serial : + Bus info : + Media version : 5.3.0 + Hardware revision: 0x00000000 (0) + Driver version : 5.3.0 + +Required ioctls: + warn: v4l2-test-media.cpp(51): empty bus_info + test MEDIA_IOC_DEVICE_INFO: OK + +Signed-off-by: Hans Verkuil +Reviewed-by: Jernej Skrabec +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/staging/media/sunxi/cedrus/cedrus.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c +index 2d3ea8b74dfd..3439f6ad6338 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.c +@@ -357,6 +357,8 @@ static int cedrus_probe(struct platform_device *pdev) + + dev->mdev.dev = &pdev->dev; + strscpy(dev->mdev.model, CEDRUS_NAME, sizeof(dev->mdev.model)); ++ strscpy(dev->mdev.bus_info, "platform:" CEDRUS_NAME, ++ sizeof(dev->mdev.bus_info)); + + media_device_init(&dev->mdev); + dev->mdev.ops = &cedrus_m2m_media_ops; +-- +2.23.0 + +From dec555256f2cb61ee94975727ec2d4a8d592ac92 Mon Sep 17 00:00:00 2001 +From: Hans Verkuil +Date: Fri, 30 Aug 2019 06:26:23 -0300 +Subject: [PATCH] media: cedrus: choose default pixelformat in try_fmt + +If an unsupported pixelformat is passed to try_fmt, then pick +the first valid pixelformat instead. This is more standard V4L2 +behavior. + +Signed-off-by: Hans Verkuil +Reviewed-by: Jernej Skrabec +Signed-off-by: Mauro Carvalho Chehab +--- + .../staging/media/sunxi/cedrus/cedrus_video.c | 46 ++++++++----------- + 1 file changed, 20 insertions(+), 26 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +index eeee3efd247b..d69c9bcdb8e2 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +@@ -62,33 +62,30 @@ static inline struct cedrus_ctx *cedrus_file2ctx(struct file *file) + static struct cedrus_format *cedrus_find_format(u32 pixelformat, u32 directions, + unsigned int capabilities) + { ++ struct cedrus_format *first_valid_fmt = NULL; + struct cedrus_format *fmt; + unsigned int i; + + for (i = 0; i < CEDRUS_FORMATS_COUNT; i++) { + fmt = &cedrus_formats[i]; + +- if (fmt->capabilities && (fmt->capabilities & capabilities) != +- fmt->capabilities) ++ if ((fmt->capabilities & capabilities) != fmt->capabilities || ++ !(fmt->directions & directions)) + continue; + +- if (fmt->pixelformat == pixelformat && +- (fmt->directions & directions) != 0) ++ if (fmt->pixelformat == pixelformat) + break; ++ ++ if (!first_valid_fmt) ++ first_valid_fmt = fmt; + } + + if (i == CEDRUS_FORMATS_COUNT) +- return NULL; ++ return first_valid_fmt; + + return &cedrus_formats[i]; + } + +-static bool cedrus_check_format(u32 pixelformat, u32 directions, +- unsigned int capabilities) +-{ +- return cedrus_find_format(pixelformat, directions, capabilities); +-} +- + static void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt) + { + unsigned int width = pix_fmt->width; +@@ -252,11 +249,14 @@ static int cedrus_try_fmt_vid_cap(struct file *file, void *priv, + struct cedrus_ctx *ctx = cedrus_file2ctx(file); + struct cedrus_dev *dev = ctx->dev; + struct v4l2_pix_format *pix_fmt = &f->fmt.pix; ++ struct cedrus_format *fmt = ++ cedrus_find_format(pix_fmt->pixelformat, CEDRUS_DECODE_DST, ++ dev->capabilities); + +- if (!cedrus_check_format(pix_fmt->pixelformat, CEDRUS_DECODE_DST, +- dev->capabilities)) ++ if (!fmt) + return -EINVAL; + ++ pix_fmt->pixelformat = fmt->pixelformat; + cedrus_prepare_format(pix_fmt); + + return 0; +@@ -268,15 +268,18 @@ static int cedrus_try_fmt_vid_out(struct file *file, void *priv, + struct cedrus_ctx *ctx = cedrus_file2ctx(file); + struct cedrus_dev *dev = ctx->dev; + struct v4l2_pix_format *pix_fmt = &f->fmt.pix; ++ struct cedrus_format *fmt = ++ cedrus_find_format(pix_fmt->pixelformat, CEDRUS_DECODE_SRC, ++ dev->capabilities); + +- if (!cedrus_check_format(pix_fmt->pixelformat, CEDRUS_DECODE_SRC, +- dev->capabilities)) ++ if (!fmt) + return -EINVAL; + + /* Source image size has to be provided by userspace. */ + if (pix_fmt->sizeimage == 0) + return -EINVAL; + ++ pix_fmt->pixelformat = fmt->pixelformat; + cedrus_prepare_format(pix_fmt); + + return 0; +@@ -364,21 +367,12 @@ static int cedrus_queue_setup(struct vb2_queue *vq, unsigned int *nbufs, + struct device *alloc_devs[]) + { + struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); +- struct cedrus_dev *dev = ctx->dev; + struct v4l2_pix_format *pix_fmt; +- u32 directions; + +- if (V4L2_TYPE_IS_OUTPUT(vq->type)) { +- directions = CEDRUS_DECODE_SRC; ++ if (V4L2_TYPE_IS_OUTPUT(vq->type)) + pix_fmt = &ctx->src_fmt; +- } else { +- directions = CEDRUS_DECODE_DST; ++ else + pix_fmt = &ctx->dst_fmt; +- } +- +- if (!cedrus_check_format(pix_fmt->pixelformat, directions, +- dev->capabilities)) +- return -EINVAL; + + if (*nplanes) { + if (sizes[0] < pix_fmt->sizeimage) +-- +2.23.0 + +From 965c71e8adcff315e16b58c00cd312598fc0222c Mon Sep 17 00:00:00 2001 +From: Hans Verkuil +Date: Fri, 30 Aug 2019 06:26:24 -0300 +Subject: [PATCH] media: cedrus: fix various format-related compliance issues + +Initialize the context on open() with valid capture and output +formats. It is good practice to always have valid formats internally. + +This solves one vb2 warning in the kernel log where the sizeimage +value of the output format was 0 when requesting buffers, which is +not allowed. + +It also simplifies the g_fmt ioctl implementations since they no longer +have to check if a valid format was ever set. + +cedrus_prepare_format() now also validates sizeimage for the output +formats, ensuring userspace can't set it to 0 since that would cause +the same vb2 warning. + +Finally remove the sizeimage == 0 check in cedrus_try_fmt_vid_out() +since cedrus_prepare_format() will now adjust this value. + +Signed-off-by: Hans Verkuil +Reviewed-by: Jernej Skrabec +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/staging/media/sunxi/cedrus/cedrus.c | 10 +++++++ + .../staging/media/sunxi/cedrus/cedrus_video.c | 28 ++----------------- + .../staging/media/sunxi/cedrus/cedrus_video.h | 1 + + 3 files changed, 14 insertions(+), 25 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c +index 3439f6ad6338..0cf637c8a1e3 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.c +@@ -241,6 +241,16 @@ static int cedrus_open(struct file *file) + ret = PTR_ERR(ctx->fh.m2m_ctx); + goto err_ctrls; + } ++ ctx->dst_fmt.pixelformat = V4L2_PIX_FMT_SUNXI_TILED_NV12; ++ cedrus_prepare_format(&ctx->dst_fmt); ++ ctx->src_fmt.pixelformat = V4L2_PIX_FMT_MPEG2_SLICE; ++ /* ++ * TILED_NV12 has more strict requirements, so copy the width and ++ * height to src_fmt to ensure that is matches the dst_fmt resolution. ++ */ ++ ctx->src_fmt.width = ctx->dst_fmt.width; ++ ctx->src_fmt.height = ctx->dst_fmt.height; ++ cedrus_prepare_format(&ctx->src_fmt); + + v4l2_fh_add(&ctx->fh); + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +index d69c9bcdb8e2..3ec3a2db790c 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +@@ -86,7 +86,7 @@ static struct cedrus_format *cedrus_find_format(u32 pixelformat, u32 directions, + return &cedrus_formats[i]; + } + +-static void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt) ++void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt) + { + unsigned int width = pix_fmt->width; + unsigned int height = pix_fmt->height; +@@ -104,7 +104,8 @@ static void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt) + case V4L2_PIX_FMT_H264_SLICE: + /* Zero bytes per line for encoded source. */ + bytesperline = 0; +- ++ /* Choose some minimum size since this can't be 0 */ ++ sizeimage = max_t(u32, SZ_1K, sizeimage); + break; + + case V4L2_PIX_FMT_SUNXI_TILED_NV12: +@@ -211,16 +212,7 @@ static int cedrus_g_fmt_vid_cap(struct file *file, void *priv, + { + struct cedrus_ctx *ctx = cedrus_file2ctx(file); + +- /* Fall back to dummy default by lack of hardware configuration. */ +- if (!ctx->dst_fmt.width || !ctx->dst_fmt.height) { +- f->fmt.pix.pixelformat = V4L2_PIX_FMT_SUNXI_TILED_NV12; +- cedrus_prepare_format(&f->fmt.pix); +- +- return 0; +- } +- + f->fmt.pix = ctx->dst_fmt; +- + return 0; + } + +@@ -229,17 +221,7 @@ static int cedrus_g_fmt_vid_out(struct file *file, void *priv, + { + struct cedrus_ctx *ctx = cedrus_file2ctx(file); + +- /* Fall back to dummy default by lack of hardware configuration. */ +- if (!ctx->dst_fmt.width || !ctx->dst_fmt.height) { +- f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG2_SLICE; +- f->fmt.pix.sizeimage = SZ_1K; +- cedrus_prepare_format(&f->fmt.pix); +- +- return 0; +- } +- + f->fmt.pix = ctx->src_fmt; +- + return 0; + } + +@@ -275,10 +257,6 @@ static int cedrus_try_fmt_vid_out(struct file *file, void *priv, + if (!fmt) + return -EINVAL; + +- /* Source image size has to be provided by userspace. */ +- if (pix_fmt->sizeimage == 0) +- return -EINVAL; +- + pix_fmt->pixelformat = fmt->pixelformat; + cedrus_prepare_format(pix_fmt); + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.h b/drivers/staging/media/sunxi/cedrus/cedrus_video.h +index 0e4f7a8cccf2..05050c0a0921 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.h +@@ -26,5 +26,6 @@ extern const struct v4l2_ioctl_ops cedrus_ioctl_ops; + + int cedrus_queue_init(void *priv, struct vb2_queue *src_vq, + struct vb2_queue *dst_vq); ++void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt); + + #endif +-- +2.23.0 + +From eabf10e5e3009e0c7e9a9b98a7f8299e690bcc55 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 11 Oct 2019 06:32:45 -0300 +Subject: [PATCH] media: cedrus: h264: Support multiple slices per frame + +With recent changes, support for decoding multi-slice frames can be +easily added now. + +Signal VPU if current slice is first in frame or not and add information +about first macroblock coordinates. + +When frame contains multiple slices and driver works in slice mode, it's +more efficient to hold capture buffer in queue until all slices of a +same frame are decoded. + +Add support for that to Cedrus driver by exposing and implementing +V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF capability. + +Signed-off-by: Jernej Skrabec +[hverkuil-cisco@xs4all.nl: rewritten to use v4l2_m2m_buf_done_and_job_finish] +[hverkuil-cisco@xs4all.nl: removed unnecessary (u32) cast] +[hverkuil-cisco@xs4all.nl: use new_frame v4l2_m2m_ctx bool] +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 12 +++++++++++- + drivers/staging/media/sunxi/cedrus/cedrus_hw.c | 16 ++-------------- + .../staging/media/sunxi/cedrus/cedrus_video.c | 14 ++++++++++++++ + 3 files changed, 27 insertions(+), 15 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index d6a782703c9b..cd85668f9c80 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -301,6 +301,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, + dma_addr_t src_buf_addr; + u32 offset = slice->header_bit_size; + u32 len = (slice->size * 8) - offset; ++ unsigned int pic_width_in_mbs; ++ bool mbaff_pic; + u32 reg; + + cedrus_write(dev, VE_H264_VLD_LEN, len); +@@ -370,12 +372,20 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, + reg |= VE_H264_SPS_DIRECT_8X8_INFERENCE; + cedrus_write(dev, VE_H264_SPS, reg); + ++ mbaff_pic = !(slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) && ++ (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD); ++ pic_width_in_mbs = sps->pic_width_in_mbs_minus1 + 1; ++ + // slice parameters + reg = 0; ++ reg |= ((slice->first_mb_in_slice % pic_width_in_mbs) & 0xff) << 24; ++ reg |= (((slice->first_mb_in_slice / pic_width_in_mbs) * ++ (mbaff_pic + 1)) & 0xff) << 16; + reg |= decode->nal_ref_idc ? BIT(12) : 0; + reg |= (slice->slice_type & 0xf) << 8; + reg |= slice->cabac_init_idc & 0x3; +- reg |= VE_H264_SHS_FIRST_SLICE_IN_PIC; ++ if (ctx->fh.m2m_ctx->new_frame) ++ reg |= VE_H264_SHS_FIRST_SLICE_IN_PIC; + if (slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) + reg |= VE_H264_SHS_FIELD_PIC; + if (slice->flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD) +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c +index a942cd9bed57..e7e18424bab1 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c +@@ -103,7 +103,6 @@ static irqreturn_t cedrus_irq(int irq, void *data) + { + struct cedrus_dev *dev = data; + struct cedrus_ctx *ctx; +- struct vb2_v4l2_buffer *src_buf, *dst_buf; + enum vb2_buffer_state state; + enum cedrus_irq_status status; + +@@ -121,24 +120,13 @@ static irqreturn_t cedrus_irq(int irq, void *data) + dev->dec_ops[ctx->current_codec]->irq_disable(ctx); + dev->dec_ops[ctx->current_codec]->irq_clear(ctx); + +- src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); +- dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); +- +- if (!src_buf || !dst_buf) { +- v4l2_err(&dev->v4l2_dev, +- "Missing source and/or destination buffers\n"); +- return IRQ_HANDLED; +- } +- + if (status == CEDRUS_IRQ_ERROR) + state = VB2_BUF_STATE_ERROR; + else + state = VB2_BUF_STATE_DONE; + +- v4l2_m2m_buf_done(src_buf, state); +- v4l2_m2m_buf_done(dst_buf, state); +- +- v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx); ++ v4l2_m2m_buf_done_and_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx, ++ state); + + return IRQ_HANDLED; + } +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +index 3ec3a2db790c..f745f66c4440 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +@@ -303,6 +303,17 @@ static int cedrus_s_fmt_vid_out(struct file *file, void *priv, + + ctx->src_fmt = f->fmt.pix; + ++ switch (ctx->src_fmt.pixelformat) { ++ case V4L2_PIX_FMT_H264_SLICE: ++ vq->subsystem_flags |= ++ VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF; ++ break; ++ default: ++ vq->subsystem_flags &= ++ ~VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF; ++ break; ++ } ++ + /* Propagate colorspace information to capture. */ + ctx->dst_fmt.colorspace = f->fmt.pix.colorspace; + ctx->dst_fmt.xfer_func = f->fmt.pix.xfer_func; +@@ -336,6 +347,9 @@ const struct v4l2_ioctl_ops cedrus_ioctl_ops = { + .vidioc_streamon = v4l2_m2m_ioctl_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, + ++ .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_stateless_try_decoder_cmd, ++ .vidioc_decoder_cmd = v4l2_m2m_ioctl_stateless_decoder_cmd, ++ + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + }; +-- +2.23.0 + +From 06eff2150d4db991ca236f3d05a9dc0101475aea Mon Sep 17 00:00:00 2001 +From: Paul Kocialkowski +Date: Tue, 22 Oct 2019 12:26:50 -0300 +Subject: [PATCH] media: cedrus: Fix undefined shift with a SHIFT_AND_MASK_BITS + macro + +We need to shift and mask values at different occasions to fill up +cedrus registers. This was done using macros that don't explicitly +treat arguments as unsigned, leading to possibly undefined behavior. + +Introduce the SHIFT_AND_MASK_BITS macro and use it where possible. +In cases where it doesn't apply as-is, explicitly cast to unsigned +instead. + +This macro should be moved to include/linux/bits.h eventually. + +Signed-off-by: Paul Kocialkowski +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + .../staging/media/sunxi/cedrus/cedrus_regs.h | 31 ++++++++++--------- + 1 file changed, 17 insertions(+), 14 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +index ddd29788d685..f9dd8cbf3458 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +@@ -10,6 +10,9 @@ + #ifndef _CEDRUS_REGS_H_ + #define _CEDRUS_REGS_H_ + ++#define SHIFT_AND_MASK_BITS(v, h, l) \ ++ (((unsigned long)(v) << (l)) & GENMASK(h, l)) ++ + /* + * Common acronyms and contractions used in register descriptions: + * * VLD : Variable-Length Decoder +@@ -37,8 +40,8 @@ + #define VE_PRIMARY_CHROMA_BUF_LEN 0xc4 + #define VE_PRIMARY_FB_LINE_STRIDE 0xc8 + +-#define VE_PRIMARY_FB_LINE_STRIDE_CHROMA(s) (((s) << 16) & GENMASK(31, 16)) +-#define VE_PRIMARY_FB_LINE_STRIDE_LUMA(s) (((s) << 0) & GENMASK(15, 0)) ++#define VE_PRIMARY_FB_LINE_STRIDE_CHROMA(s) SHIFT_AND_MASK_BITS(s, 31, 16) ++#define VE_PRIMARY_FB_LINE_STRIDE_LUMA(s) SHIFT_AND_MASK_BITS(s, 15, 0) + + #define VE_CHROMA_BUF_LEN 0xe8 + +@@ -46,7 +49,7 @@ + #define VE_SECONDARY_OUT_FMT_EXT (0x01 << 30) + #define VE_SECONDARY_OUT_FMT_YU12 (0x02 << 30) + #define VE_SECONDARY_OUT_FMT_YV12 (0x03 << 30) +-#define VE_CHROMA_BUF_LEN_SDRT(l) ((l) & GENMASK(27, 0)) ++#define VE_CHROMA_BUF_LEN_SDRT(l) SHIFT_AND_MASK_BITS(l, 27, 0) + + #define VE_PRIMARY_OUT_FMT 0xec + +@@ -69,15 +72,15 @@ + + #define VE_DEC_MPEG_MP12HDR (VE_ENGINE_DEC_MPEG + 0x00) + +-#define VE_DEC_MPEG_MP12HDR_SLICE_TYPE(t) (((t) << 28) & GENMASK(30, 28)) ++#define VE_DEC_MPEG_MP12HDR_SLICE_TYPE(t) SHIFT_AND_MASK_BITS(t, 30, 28) + #define VE_DEC_MPEG_MP12HDR_F_CODE_SHIFT(x, y) (24 - 4 * (y) - 8 * (x)) + #define VE_DEC_MPEG_MP12HDR_F_CODE(__x, __y, __v) \ +- (((__v) & GENMASK(3, 0)) << VE_DEC_MPEG_MP12HDR_F_CODE_SHIFT(__x, __y)) ++ (((unsigned long)(__v) & GENMASK(3, 0)) << VE_DEC_MPEG_MP12HDR_F_CODE_SHIFT(__x, __y)) + + #define VE_DEC_MPEG_MP12HDR_INTRA_DC_PRECISION(p) \ +- (((p) << 10) & GENMASK(11, 10)) ++ SHIFT_AND_MASK_BITS(p, 11, 10) + #define VE_DEC_MPEG_MP12HDR_INTRA_PICTURE_STRUCTURE(s) \ +- (((s) << 8) & GENMASK(9, 8)) ++ SHIFT_AND_MASK_BITS(s, 9, 8) + #define VE_DEC_MPEG_MP12HDR_TOP_FIELD_FIRST(v) \ + ((v) ? BIT(7) : 0) + #define VE_DEC_MPEG_MP12HDR_FRAME_PRED_FRAME_DCT(v) \ +@@ -98,19 +101,19 @@ + #define VE_DEC_MPEG_PICCODEDSIZE (VE_ENGINE_DEC_MPEG + 0x08) + + #define VE_DEC_MPEG_PICCODEDSIZE_WIDTH(w) \ +- ((DIV_ROUND_UP((w), 16) << 8) & GENMASK(15, 8)) ++ SHIFT_AND_MASK_BITS(DIV_ROUND_UP((w), 16), 15, 8) + #define VE_DEC_MPEG_PICCODEDSIZE_HEIGHT(h) \ +- ((DIV_ROUND_UP((h), 16) << 0) & GENMASK(7, 0)) ++ SHIFT_AND_MASK_BITS(DIV_ROUND_UP((h), 16), 7, 0) + + #define VE_DEC_MPEG_PICBOUNDSIZE (VE_ENGINE_DEC_MPEG + 0x0c) + +-#define VE_DEC_MPEG_PICBOUNDSIZE_WIDTH(w) (((w) << 16) & GENMASK(27, 16)) +-#define VE_DEC_MPEG_PICBOUNDSIZE_HEIGHT(h) (((h) << 0) & GENMASK(11, 0)) ++#define VE_DEC_MPEG_PICBOUNDSIZE_WIDTH(w) SHIFT_AND_MASK_BITS(w, 27, 16) ++#define VE_DEC_MPEG_PICBOUNDSIZE_HEIGHT(h) SHIFT_AND_MASK_BITS(h, 11, 0) + + #define VE_DEC_MPEG_MBADDR (VE_ENGINE_DEC_MPEG + 0x10) + +-#define VE_DEC_MPEG_MBADDR_X(w) (((w) << 8) & GENMASK(15, 8)) +-#define VE_DEC_MPEG_MBADDR_Y(h) (((h) << 0) & GENMASK(7, 0)) ++#define VE_DEC_MPEG_MBADDR_X(w) SHIFT_AND_MASK_BITS(w, 15, 8) ++#define VE_DEC_MPEG_MBADDR_Y(h) SHIFT_AND_MASK_BITS(h, 7, 0) + + #define VE_DEC_MPEG_CTRL (VE_ENGINE_DEC_MPEG + 0x14) + +@@ -225,7 +228,7 @@ + #define VE_DEC_MPEG_IQMINPUT_FLAG_INTRA (0x01 << 14) + #define VE_DEC_MPEG_IQMINPUT_FLAG_NON_INTRA (0x00 << 14) + #define VE_DEC_MPEG_IQMINPUT_WEIGHT(i, v) \ +- (((v) & GENMASK(7, 0)) | (((i) << 8) & GENMASK(13, 8))) ++ (SHIFT_AND_MASK_BITS(i, 13, 8) | SHIFT_AND_MASK_BITS(v, 7, 0)) + + #define VE_DEC_MPEG_ERROR (VE_ENGINE_DEC_MPEG + 0xc4) + #define VE_DEC_MPEG_CRTMBADDR (VE_ENGINE_DEC_MPEG + 0xc8) +-- +2.23.0 + +From c3b32900fbf5178473c6b39260e891e19067edc2 Mon Sep 17 00:00:00 2001 +From: Paul Kocialkowski +Date: Tue, 22 Oct 2019 12:26:51 -0300 +Subject: [PATCH] media: cedrus: Remove unnecessary parenthesis around + DIV_ROUND_UP + +DIV_ROUND_UP's first argument doesn't need to be wrapped in parenthesis +since that is already being taken care of in the macro's definition. + +Signed-off-by: Paul Kocialkowski +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/staging/media/sunxi/cedrus/cedrus_regs.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +index f9dd8cbf3458..21676a1797f1 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +@@ -101,9 +101,9 @@ + #define VE_DEC_MPEG_PICCODEDSIZE (VE_ENGINE_DEC_MPEG + 0x08) + + #define VE_DEC_MPEG_PICCODEDSIZE_WIDTH(w) \ +- SHIFT_AND_MASK_BITS(DIV_ROUND_UP((w), 16), 15, 8) ++ SHIFT_AND_MASK_BITS(DIV_ROUND_UP(w, 16), 15, 8) + #define VE_DEC_MPEG_PICCODEDSIZE_HEIGHT(h) \ +- SHIFT_AND_MASK_BITS(DIV_ROUND_UP((h), 16), 7, 0) ++ SHIFT_AND_MASK_BITS(DIV_ROUND_UP(h, 16), 7, 0) + + #define VE_DEC_MPEG_PICBOUNDSIZE (VE_ENGINE_DEC_MPEG + 0x0c) + +-- +2.23.0 + +From 86caab29da78961d73e489554c8b2573fae523d5 Mon Sep 17 00:00:00 2001 +From: Paul Kocialkowski +Date: Tue, 22 Oct 2019 12:26:54 -0300 +Subject: [PATCH] media: cedrus: Add HEVC/H.265 decoding support + +This introduces support for HEVC/H.265 to the Cedrus VPU driver, with +both uni-directional and bi-directional prediction modes supported. + +Field-coded (interlaced) pictures, custom quantization matrices and +10-bit output are not supported at this point. + +Signed-off-by: Paul Kocialkowski +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/staging/media/sunxi/cedrus/Makefile | 2 +- + drivers/staging/media/sunxi/cedrus/cedrus.c | 52 +- + drivers/staging/media/sunxi/cedrus/cedrus.h | 18 + + .../staging/media/sunxi/cedrus/cedrus_dec.c | 9 + + .../staging/media/sunxi/cedrus/cedrus_h265.c | 616 ++++++++++++++++++ + .../staging/media/sunxi/cedrus/cedrus_hw.c | 4 + + .../staging/media/sunxi/cedrus/cedrus_regs.h | 271 ++++++++ + .../staging/media/sunxi/cedrus/cedrus_video.c | 10 + + 8 files changed, 977 insertions(+), 5 deletions(-) + create mode 100644 drivers/staging/media/sunxi/cedrus/cedrus_h265.c + +diff --git a/drivers/staging/media/sunxi/cedrus/Makefile b/drivers/staging/media/sunxi/cedrus/Makefile +index c85ac6db0302..1bce49d3e7e2 100644 +--- a/drivers/staging/media/sunxi/cedrus/Makefile ++++ b/drivers/staging/media/sunxi/cedrus/Makefile +@@ -2,4 +2,4 @@ + obj-$(CONFIG_VIDEO_SUNXI_CEDRUS) += sunxi-cedrus.o + + sunxi-cedrus-y = cedrus.o cedrus_video.o cedrus_hw.o cedrus_dec.o \ +- cedrus_mpeg2.o cedrus_h264.o ++ cedrus_mpeg2.o cedrus_h264.o cedrus_h265.o +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c +index 0cf637c8a1e3..c6ddd46eff82 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.c +@@ -95,6 +95,45 @@ static const struct cedrus_control cedrus_controls[] = { + .codec = CEDRUS_CODEC_H264, + .required = false, + }, ++ { ++ .cfg = { ++ .id = V4L2_CID_MPEG_VIDEO_HEVC_SPS, ++ }, ++ .codec = CEDRUS_CODEC_H265, ++ .required = true, ++ }, ++ { ++ .cfg = { ++ .id = V4L2_CID_MPEG_VIDEO_HEVC_PPS, ++ }, ++ .codec = CEDRUS_CODEC_H265, ++ .required = true, ++ }, ++ { ++ .cfg = { ++ .id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS, ++ }, ++ .codec = CEDRUS_CODEC_H265, ++ .required = true, ++ }, ++ { ++ .cfg = { ++ .id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE, ++ .max = V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED, ++ .def = V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED, ++ }, ++ .codec = CEDRUS_CODEC_H265, ++ .required = false, ++ }, ++ { ++ .cfg = { ++ .id = V4L2_CID_MPEG_VIDEO_HEVC_START_CODE, ++ .max = V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE, ++ .def = V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE, ++ }, ++ .codec = CEDRUS_CODEC_H265, ++ .required = false, ++ }, + }; + + #define CEDRUS_CONTROLS_COUNT ARRAY_SIZE(cedrus_controls) +@@ -340,6 +379,7 @@ static int cedrus_probe(struct platform_device *pdev) + + dev->dec_ops[CEDRUS_CODEC_MPEG2] = &cedrus_dec_ops_mpeg2; + dev->dec_ops[CEDRUS_CODEC_H264] = &cedrus_dec_ops_h264; ++ dev->dec_ops[CEDRUS_CODEC_H265] = &cedrus_dec_ops_h265; + + mutex_init(&dev->dev_mutex); + +@@ -450,22 +490,26 @@ static const struct cedrus_variant sun8i_a33_cedrus_variant = { + }; + + static const struct cedrus_variant sun8i_h3_cedrus_variant = { +- .capabilities = CEDRUS_CAPABILITY_UNTILED, ++ .capabilities = CEDRUS_CAPABILITY_UNTILED | ++ CEDRUS_CAPABILITY_H265_DEC, + .mod_rate = 402000000, + }; + + static const struct cedrus_variant sun50i_a64_cedrus_variant = { +- .capabilities = CEDRUS_CAPABILITY_UNTILED, ++ .capabilities = CEDRUS_CAPABILITY_UNTILED | ++ CEDRUS_CAPABILITY_H265_DEC, + .mod_rate = 402000000, + }; + + static const struct cedrus_variant sun50i_h5_cedrus_variant = { +- .capabilities = CEDRUS_CAPABILITY_UNTILED, ++ .capabilities = CEDRUS_CAPABILITY_UNTILED | ++ CEDRUS_CAPABILITY_H265_DEC, + .mod_rate = 402000000, + }; + + static const struct cedrus_variant sun50i_h6_cedrus_variant = { +- .capabilities = CEDRUS_CAPABILITY_UNTILED, ++ .capabilities = CEDRUS_CAPABILITY_UNTILED | ++ CEDRUS_CAPABILITY_H265_DEC, + .quirks = CEDRUS_QUIRK_NO_DMA_OFFSET, + .mod_rate = 600000000, + }; +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h +index 2f017a651848..986e059e3202 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -27,12 +27,14 @@ + #define CEDRUS_NAME "cedrus" + + #define CEDRUS_CAPABILITY_UNTILED BIT(0) ++#define CEDRUS_CAPABILITY_H265_DEC BIT(1) + + #define CEDRUS_QUIRK_NO_DMA_OFFSET BIT(0) + + enum cedrus_codec { + CEDRUS_CODEC_MPEG2, + CEDRUS_CODEC_H264, ++ CEDRUS_CODEC_H265, + CEDRUS_CODEC_LAST, + }; + +@@ -67,6 +69,12 @@ struct cedrus_mpeg2_run { + const struct v4l2_ctrl_mpeg2_quantization *quantization; + }; + ++struct cedrus_h265_run { ++ const struct v4l2_ctrl_hevc_sps *sps; ++ const struct v4l2_ctrl_hevc_pps *pps; ++ const struct v4l2_ctrl_hevc_slice_params *slice_params; ++}; ++ + struct cedrus_run { + struct vb2_v4l2_buffer *src; + struct vb2_v4l2_buffer *dst; +@@ -74,6 +82,7 @@ struct cedrus_run { + union { + struct cedrus_h264_run h264; + struct cedrus_mpeg2_run mpeg2; ++ struct cedrus_h265_run h265; + }; + }; + +@@ -110,6 +119,14 @@ struct cedrus_ctx { + void *neighbor_info_buf; + dma_addr_t neighbor_info_buf_dma; + } h264; ++ struct { ++ void *mv_col_buf; ++ dma_addr_t mv_col_buf_addr; ++ ssize_t mv_col_buf_size; ++ ssize_t mv_col_buf_unit_size; ++ void *neighbor_info_buf; ++ dma_addr_t neighbor_info_buf_addr; ++ } h265; + } codec; + }; + +@@ -155,6 +172,7 @@ struct cedrus_dev { + + extern struct cedrus_dec_ops cedrus_dec_ops_mpeg2; + extern struct cedrus_dec_ops cedrus_dec_ops_h264; ++extern struct cedrus_dec_ops cedrus_dec_ops_h265; + + static inline void cedrus_write(struct cedrus_dev *dev, u32 reg, u32 val) + { +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c +index 56ca4c9ad01c..4a2fc33a1d79 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c +@@ -59,6 +59,15 @@ void cedrus_device_run(void *priv) + V4L2_CID_MPEG_VIDEO_H264_SPS); + break; + ++ case V4L2_PIX_FMT_HEVC_SLICE: ++ run.h265.sps = cedrus_find_control_data(ctx, ++ V4L2_CID_MPEG_VIDEO_HEVC_SPS); ++ run.h265.pps = cedrus_find_control_data(ctx, ++ V4L2_CID_MPEG_VIDEO_HEVC_PPS); ++ run.h265.slice_params = cedrus_find_control_data(ctx, ++ V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS); ++ break; ++ + default: + break; + } +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +new file mode 100644 +index 000000000000..9bc921866f70 +--- /dev/null ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -0,0 +1,616 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Cedrus VPU driver ++ * ++ * Copyright (C) 2013 Jens Kuske ++ * Copyright (C) 2018 Paul Kocialkowski ++ * Copyright (C) 2018 Bootlin ++ */ ++ ++#include ++ ++#include ++ ++#include "cedrus.h" ++#include "cedrus_hw.h" ++#include "cedrus_regs.h" ++ ++/* ++ * These are the sizes for side buffers required by the hardware for storing ++ * internal decoding metadata. They match the values used by the early BSP ++ * implementations, that were initially exposed in libvdpau-sunxi. ++ * Subsequent BSP implementations seem to double the neighbor info buffer size ++ * for the H6 SoC, which may be related to 10 bit H265 support. ++ */ ++#define CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE (397 * SZ_1K) ++#define CEDRUS_H265_ENTRY_POINTS_BUF_SIZE (4 * SZ_1K) ++#define CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE 160 ++ ++struct cedrus_h265_sram_frame_info { ++ __le32 top_pic_order_cnt; ++ __le32 bottom_pic_order_cnt; ++ __le32 top_mv_col_buf_addr; ++ __le32 bottom_mv_col_buf_addr; ++ __le32 luma_addr; ++ __le32 chroma_addr; ++} __packed; ++ ++struct cedrus_h265_sram_pred_weight { ++ __s8 delta_weight; ++ __s8 offset; ++} __packed; ++ ++static enum cedrus_irq_status cedrus_h265_irq_status(struct cedrus_ctx *ctx) ++{ ++ struct cedrus_dev *dev = ctx->dev; ++ u32 reg; ++ ++ reg = cedrus_read(dev, VE_DEC_H265_STATUS); ++ reg &= VE_DEC_H265_STATUS_CHECK_MASK; ++ ++ if (reg & VE_DEC_H265_STATUS_CHECK_ERROR || ++ !(reg & VE_DEC_H265_STATUS_SUCCESS)) ++ return CEDRUS_IRQ_ERROR; ++ ++ return CEDRUS_IRQ_OK; ++} ++ ++static void cedrus_h265_irq_clear(struct cedrus_ctx *ctx) ++{ ++ struct cedrus_dev *dev = ctx->dev; ++ ++ cedrus_write(dev, VE_DEC_H265_STATUS, VE_DEC_H265_STATUS_CHECK_MASK); ++} ++ ++static void cedrus_h265_irq_disable(struct cedrus_ctx *ctx) ++{ ++ struct cedrus_dev *dev = ctx->dev; ++ u32 reg = cedrus_read(dev, VE_DEC_H265_CTRL); ++ ++ reg &= ~VE_DEC_H265_CTRL_IRQ_MASK; ++ ++ cedrus_write(dev, VE_DEC_H265_CTRL, reg); ++} ++ ++static void cedrus_h265_sram_write_offset(struct cedrus_dev *dev, u32 offset) ++{ ++ cedrus_write(dev, VE_DEC_H265_SRAM_OFFSET, offset); ++} ++ ++static void cedrus_h265_sram_write_data(struct cedrus_dev *dev, void *data, ++ unsigned int size) ++{ ++ u32 *word = data; ++ ++ while (size >= sizeof(u32)) { ++ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, *word++); ++ size -= sizeof(u32); ++ } ++} ++ ++static inline dma_addr_t ++cedrus_h265_frame_info_mv_col_buf_addr(struct cedrus_ctx *ctx, ++ unsigned int index, unsigned int field) ++{ ++ return ctx->codec.h265.mv_col_buf_addr + index * ++ ctx->codec.h265.mv_col_buf_unit_size + ++ field * ctx->codec.h265.mv_col_buf_unit_size / 2; ++} ++ ++static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx, ++ unsigned int index, ++ bool field_pic, ++ u32 pic_order_cnt[], ++ int buffer_index) ++{ ++ struct cedrus_dev *dev = ctx->dev; ++ dma_addr_t dst_luma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 0); ++ dma_addr_t dst_chroma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 1); ++ dma_addr_t mv_col_buf_addr[2] = { ++ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, 0), ++ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, ++ field_pic ? 1 : 0) ++ }; ++ u32 offset = VE_DEC_H265_SRAM_OFFSET_FRAME_INFO + ++ VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT * index; ++ struct cedrus_h265_sram_frame_info frame_info = { ++ .top_pic_order_cnt = cpu_to_le32(pic_order_cnt[0]), ++ .bottom_pic_order_cnt = cpu_to_le32(field_pic ? ++ pic_order_cnt[1] : ++ pic_order_cnt[0]), ++ .top_mv_col_buf_addr = ++ cpu_to_le32(VE_DEC_H265_SRAM_DATA_ADDR_BASE(mv_col_buf_addr[0])), ++ .bottom_mv_col_buf_addr = cpu_to_le32(field_pic ? ++ VE_DEC_H265_SRAM_DATA_ADDR_BASE(mv_col_buf_addr[1]) : ++ VE_DEC_H265_SRAM_DATA_ADDR_BASE(mv_col_buf_addr[0])), ++ .luma_addr = cpu_to_le32(VE_DEC_H265_SRAM_DATA_ADDR_BASE(dst_luma_addr)), ++ .chroma_addr = cpu_to_le32(VE_DEC_H265_SRAM_DATA_ADDR_BASE(dst_chroma_addr)), ++ }; ++ ++ cedrus_h265_sram_write_offset(dev, offset); ++ cedrus_h265_sram_write_data(dev, &frame_info, sizeof(frame_info)); ++} ++ ++static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx, ++ const struct v4l2_hevc_dpb_entry *dpb, ++ u8 num_active_dpb_entries) ++{ ++ struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, ++ V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ unsigned int i; ++ ++ for (i = 0; i < num_active_dpb_entries; i++) { ++ int buffer_index = vb2_find_timestamp(vq, dpb[i].timestamp, 0); ++ u32 pic_order_cnt[2] = { ++ dpb[i].pic_order_cnt[0], ++ dpb[i].pic_order_cnt[1] ++ }; ++ ++ cedrus_h265_frame_info_write_single(ctx, i, dpb[i].field_pic, ++ pic_order_cnt, ++ buffer_index); ++ } ++} ++ ++static void cedrus_h265_ref_pic_list_write(struct cedrus_dev *dev, ++ const struct v4l2_hevc_dpb_entry *dpb, ++ const u8 list[], ++ u8 num_ref_idx_active, ++ u32 sram_offset) ++{ ++ unsigned int i; ++ u32 word = 0; ++ ++ cedrus_h265_sram_write_offset(dev, sram_offset); ++ ++ for (i = 0; i < num_ref_idx_active; i++) { ++ unsigned int shift = (i % 4) * 8; ++ unsigned int index = list[i]; ++ u8 value = list[i]; ++ ++ if (dpb[index].rps == V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR) ++ value |= VE_DEC_H265_SRAM_REF_PIC_LIST_LT_REF; ++ ++ /* Each SRAM word gathers up to 4 references. */ ++ word |= value << shift; ++ ++ /* Write the word to SRAM and clear it for the next batch. */ ++ if ((i % 4) == 3 || i == (num_ref_idx_active - 1)) { ++ cedrus_h265_sram_write_data(dev, &word, sizeof(word)); ++ word = 0; ++ } ++ } ++} ++ ++static void cedrus_h265_pred_weight_write(struct cedrus_dev *dev, ++ const s8 delta_luma_weight[], ++ const s8 luma_offset[], ++ const s8 delta_chroma_weight[][2], ++ const s8 chroma_offset[][2], ++ u8 num_ref_idx_active, ++ u32 sram_luma_offset, ++ u32 sram_chroma_offset) ++{ ++ struct cedrus_h265_sram_pred_weight pred_weight[2] = { { 0 } }; ++ unsigned int i, j; ++ ++ cedrus_h265_sram_write_offset(dev, sram_luma_offset); ++ ++ for (i = 0; i < num_ref_idx_active; i++) { ++ unsigned int index = i % 2; ++ ++ pred_weight[index].delta_weight = delta_luma_weight[i]; ++ pred_weight[index].offset = luma_offset[i]; ++ ++ if (index == 1 || i == (num_ref_idx_active - 1)) ++ cedrus_h265_sram_write_data(dev, (u32 *)&pred_weight, ++ sizeof(pred_weight)); ++ } ++ ++ cedrus_h265_sram_write_offset(dev, sram_chroma_offset); ++ ++ for (i = 0; i < num_ref_idx_active; i++) { ++ for (j = 0; j < 2; j++) { ++ pred_weight[j].delta_weight = delta_chroma_weight[i][j]; ++ pred_weight[j].offset = chroma_offset[i][j]; ++ } ++ ++ cedrus_h265_sram_write_data(dev, &pred_weight, ++ sizeof(pred_weight)); ++ } ++} ++ ++static void cedrus_h265_setup(struct cedrus_ctx *ctx, ++ struct cedrus_run *run) ++{ ++ struct cedrus_dev *dev = ctx->dev; ++ const struct v4l2_ctrl_hevc_sps *sps; ++ const struct v4l2_ctrl_hevc_pps *pps; ++ const struct v4l2_ctrl_hevc_slice_params *slice_params; ++ const struct v4l2_hevc_pred_weight_table *pred_weight_table; ++ dma_addr_t src_buf_addr; ++ dma_addr_t src_buf_end_addr; ++ u32 chroma_log2_weight_denom; ++ u32 output_pic_list_index; ++ u32 pic_order_cnt[2]; ++ u32 reg; ++ ++ sps = run->h265.sps; ++ pps = run->h265.pps; ++ slice_params = run->h265.slice_params; ++ pred_weight_table = &slice_params->pred_weight_table; ++ ++ /* MV column buffer size and allocation. */ ++ if (!ctx->codec.h265.mv_col_buf_size) { ++ unsigned int num_buffers = ++ run->dst->vb2_buf.vb2_queue->num_buffers; ++ unsigned int log2_max_luma_coding_block_size = ++ sps->log2_min_luma_coding_block_size_minus3 + 3 + ++ sps->log2_diff_max_min_luma_coding_block_size; ++ unsigned int ctb_size_luma = ++ 1UL << log2_max_luma_coding_block_size; ++ ++ /* ++ * Each CTB requires a MV col buffer with a specific unit size. ++ * Since the address is given with missing lsb bits, 1 KiB is ++ * added to each buffer to ensure proper alignment. ++ */ ++ ctx->codec.h265.mv_col_buf_unit_size = ++ DIV_ROUND_UP(ctx->src_fmt.width, ctb_size_luma) * ++ DIV_ROUND_UP(ctx->src_fmt.height, ctb_size_luma) * ++ CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE + SZ_1K; ++ ++ ctx->codec.h265.mv_col_buf_size = num_buffers * ++ ctx->codec.h265.mv_col_buf_unit_size; ++ ++ ctx->codec.h265.mv_col_buf = ++ dma_alloc_coherent(dev->dev, ++ ctx->codec.h265.mv_col_buf_size, ++ &ctx->codec.h265.mv_col_buf_addr, ++ GFP_KERNEL); ++ if (!ctx->codec.h265.mv_col_buf) { ++ ctx->codec.h265.mv_col_buf_size = 0; ++ // TODO: Abort the process here. ++ return; ++ } ++ } ++ ++ /* Activate H265 engine. */ ++ cedrus_engine_enable(dev, CEDRUS_CODEC_H265); ++ ++ /* Source offset and length in bits. */ ++ ++ reg = slice_params->data_bit_offset; ++ cedrus_write(dev, VE_DEC_H265_BITS_OFFSET, reg); ++ ++ reg = slice_params->bit_size - slice_params->data_bit_offset; ++ cedrus_write(dev, VE_DEC_H265_BITS_LEN, reg); ++ ++ /* Source beginning and end addresses. */ ++ ++ src_buf_addr = vb2_dma_contig_plane_dma_addr(&run->src->vb2_buf, 0); ++ ++ reg = VE_DEC_H265_BITS_ADDR_BASE(src_buf_addr); ++ reg |= VE_DEC_H265_BITS_ADDR_VALID_SLICE_DATA; ++ reg |= VE_DEC_H265_BITS_ADDR_LAST_SLICE_DATA; ++ reg |= VE_DEC_H265_BITS_ADDR_FIRST_SLICE_DATA; ++ ++ cedrus_write(dev, VE_DEC_H265_BITS_ADDR, reg); ++ ++ src_buf_end_addr = src_buf_addr + ++ DIV_ROUND_UP(slice_params->bit_size, 8); ++ ++ reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_end_addr); ++ cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg); ++ ++ /* Coding tree block address: start at the beginning. */ ++ reg = VE_DEC_H265_DEC_CTB_ADDR_X(0) | VE_DEC_H265_DEC_CTB_ADDR_Y(0); ++ cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg); ++ ++ cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0); ++ cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0); ++ ++ /* Clear the number of correctly-decoded coding tree blocks. */ ++ cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0); ++ ++ /* Initialize bitstream access. */ ++ cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_INIT_SWDEC); ++ ++ /* Bitstream parameters. */ ++ ++ reg = VE_DEC_H265_DEC_NAL_HDR_NAL_UNIT_TYPE(slice_params->nal_unit_type) | ++ VE_DEC_H265_DEC_NAL_HDR_NUH_TEMPORAL_ID_PLUS1(slice_params->nuh_temporal_id_plus1); ++ ++ cedrus_write(dev, VE_DEC_H265_DEC_NAL_HDR, reg); ++ ++ /* SPS. */ ++ ++ reg = VE_DEC_H265_DEC_SPS_HDR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTRA(sps->max_transform_hierarchy_depth_intra) | ++ VE_DEC_H265_DEC_SPS_HDR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTER(sps->max_transform_hierarchy_depth_inter) | ++ VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_TRANSFORM_BLOCK_SIZE(sps->log2_diff_max_min_luma_transform_block_size) | ++ VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_TRANSFORM_BLOCK_SIZE_MINUS2(sps->log2_min_luma_transform_block_size_minus2) | ++ VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE(sps->log2_diff_max_min_luma_coding_block_size) | ++ VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_LUMA_CODING_BLOCK_SIZE_MINUS3(sps->log2_min_luma_coding_block_size_minus3) | ++ VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_CHROMA_MINUS8(sps->bit_depth_chroma_minus8) | ++ VE_DEC_H265_DEC_SPS_HDR_CHROMA_FORMAT_IDC(sps->chroma_format_idc); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_STRONG_INTRA_SMOOTHING_ENABLE, ++ V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED, ++ sps->flags); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_SPS_TEMPORAL_MVP_ENABLED, ++ V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED, ++ sps->flags); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_SAMPLE_ADAPTIVE_OFFSET_ENABLED, ++ V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET, ++ sps->flags); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_AMP_ENABLED, ++ V4L2_HEVC_SPS_FLAG_AMP_ENABLED, sps->flags); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_SEPARATE_COLOUR_PLANE, ++ V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE, ++ sps->flags); ++ ++ cedrus_write(dev, VE_DEC_H265_DEC_SPS_HDR, reg); ++ ++ reg = VE_DEC_H265_DEC_PCM_CTRL_LOG2_DIFF_MAX_MIN_PCM_LUMA_CODING_BLOCK_SIZE(sps->log2_diff_max_min_pcm_luma_coding_block_size) | ++ VE_DEC_H265_DEC_PCM_CTRL_LOG2_MIN_PCM_LUMA_CODING_BLOCK_SIZE_MINUS3(sps->log2_min_pcm_luma_coding_block_size_minus3) | ++ VE_DEC_H265_DEC_PCM_CTRL_PCM_SAMPLE_BIT_DEPTH_CHROMA_MINUS1(sps->pcm_sample_bit_depth_chroma_minus1) | ++ VE_DEC_H265_DEC_PCM_CTRL_PCM_SAMPLE_BIT_DEPTH_LUMA_MINUS1(sps->pcm_sample_bit_depth_luma_minus1); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PCM_CTRL_FLAG_PCM_ENABLED, ++ V4L2_HEVC_SPS_FLAG_PCM_ENABLED, sps->flags); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PCM_CTRL_FLAG_PCM_LOOP_FILTER_DISABLED, ++ V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED, ++ sps->flags); ++ ++ cedrus_write(dev, VE_DEC_H265_DEC_PCM_CTRL, reg); ++ ++ /* PPS. */ ++ ++ reg = VE_DEC_H265_DEC_PPS_CTRL0_PPS_CR_QP_OFFSET(pps->pps_cr_qp_offset) | ++ VE_DEC_H265_DEC_PPS_CTRL0_PPS_CB_QP_OFFSET(pps->pps_cb_qp_offset) | ++ VE_DEC_H265_DEC_PPS_CTRL0_INIT_QP_MINUS26(pps->init_qp_minus26) | ++ VE_DEC_H265_DEC_PPS_CTRL0_DIFF_CU_QP_DELTA_DEPTH(pps->diff_cu_qp_delta_depth); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_CU_QP_DELTA_ENABLED, ++ V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED, ++ pps->flags); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_TRANSFORM_SKIP_ENABLED, ++ V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED, ++ pps->flags); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_CONSTRAINED_INTRA_PRED, ++ V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED, ++ pps->flags); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_SIGN_DATA_HIDING_ENABLED, ++ V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED, ++ pps->flags); ++ ++ cedrus_write(dev, VE_DEC_H265_DEC_PPS_CTRL0, reg); ++ ++ reg = VE_DEC_H265_DEC_PPS_CTRL1_LOG2_PARALLEL_MERGE_LEVEL_MINUS2(pps->log2_parallel_merge_level_minus2); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED, ++ V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED, ++ pps->flags); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED, ++ V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED, ++ pps->flags); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_ENTROPY_CODING_SYNC_ENABLED, ++ V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED, ++ pps->flags); ++ ++ /* TODO: VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TILES_ENABLED */ ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TRANSQUANT_BYPASS_ENABLED, ++ V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED, ++ pps->flags); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_WEIGHTED_BIPRED, ++ V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED, pps->flags); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_WEIGHTED_PRED, ++ V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED, pps->flags); ++ ++ cedrus_write(dev, VE_DEC_H265_DEC_PPS_CTRL1, reg); ++ ++ /* Slice Parameters. */ ++ ++ reg = VE_DEC_H265_DEC_SLICE_HDR_INFO0_PICTURE_TYPE(slice_params->pic_struct) | ++ VE_DEC_H265_DEC_SLICE_HDR_INFO0_FIVE_MINUS_MAX_NUM_MERGE_CAND(slice_params->five_minus_max_num_merge_cand) | ++ VE_DEC_H265_DEC_SLICE_HDR_INFO0_NUM_REF_IDX_L1_ACTIVE_MINUS1(slice_params->num_ref_idx_l1_active_minus1) | ++ VE_DEC_H265_DEC_SLICE_HDR_INFO0_NUM_REF_IDX_L0_ACTIVE_MINUS1(slice_params->num_ref_idx_l0_active_minus1) | ++ VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLLOCATED_REF_IDX(slice_params->collocated_ref_idx) | ++ VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLOUR_PLANE_ID(slice_params->colour_plane_id) | ++ VE_DEC_H265_DEC_SLICE_HDR_INFO0_SLICE_TYPE(slice_params->slice_type); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_COLLOCATED_FROM_L0, ++ V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0, ++ slice_params->flags); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_CABAC_INIT, ++ V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT, ++ slice_params->flags); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_MVD_L1_ZERO, ++ V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO, ++ slice_params->flags); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_SLICE_SAO_CHROMA, ++ V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA, ++ slice_params->flags); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_SLICE_SAO_LUMA, ++ V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA, ++ slice_params->flags); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_SLICE_TEMPORAL_MVP_ENABLE, ++ V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED, ++ slice_params->flags); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_DEPENDENT_SLICE_SEGMENT, ++ V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT, ++ pps->flags); ++ ++ /* FIXME: For multi-slice support. */ ++ reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC; ++ ++ cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO0, reg); ++ ++ reg = VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_TC_OFFSET_DIV2(slice_params->slice_tc_offset_div2) | ++ VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_BETA_OFFSET_DIV2(slice_params->slice_beta_offset_div2) | ++ VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_POC_BIGEST_IN_RPS_ST(slice_params->num_rps_poc_st_curr_after == 0) | ++ VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CR_QP_OFFSET(slice_params->slice_cr_qp_offset) | ++ VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CB_QP_OFFSET(slice_params->slice_cb_qp_offset) | ++ VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_QP_DELTA(slice_params->slice_qp_delta); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO1_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED, ++ V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED, ++ slice_params->flags); ++ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO1_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED, ++ V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED, ++ slice_params->flags); ++ ++ cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO1, reg); ++ ++ chroma_log2_weight_denom = pred_weight_table->luma_log2_weight_denom + ++ pred_weight_table->delta_chroma_log2_weight_denom; ++ reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(0) | ++ VE_DEC_H265_DEC_SLICE_HDR_INFO2_CHROMA_LOG2_WEIGHT_DENOM(chroma_log2_weight_denom) | ++ VE_DEC_H265_DEC_SLICE_HDR_INFO2_LUMA_LOG2_WEIGHT_DENOM(pred_weight_table->luma_log2_weight_denom); ++ ++ cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO2, reg); ++ ++ /* Decoded picture size. */ ++ ++ reg = VE_DEC_H265_DEC_PIC_SIZE_WIDTH(ctx->src_fmt.width) | ++ VE_DEC_H265_DEC_PIC_SIZE_HEIGHT(ctx->src_fmt.height); ++ ++ cedrus_write(dev, VE_DEC_H265_DEC_PIC_SIZE, reg); ++ ++ /* Scaling list. */ ++ ++ reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT; ++ cedrus_write(dev, VE_DEC_H265_SCALING_LIST_CTRL0, reg); ++ ++ /* Neightbor information address. */ ++ reg = VE_DEC_H265_NEIGHBOR_INFO_ADDR_BASE(ctx->codec.h265.neighbor_info_buf_addr); ++ cedrus_write(dev, VE_DEC_H265_NEIGHBOR_INFO_ADDR, reg); ++ ++ /* Write decoded picture buffer in pic list. */ ++ cedrus_h265_frame_info_write_dpb(ctx, slice_params->dpb, ++ slice_params->num_active_dpb_entries); ++ ++ /* Output frame. */ ++ ++ output_pic_list_index = V4L2_HEVC_DPB_ENTRIES_NUM_MAX; ++ pic_order_cnt[0] = slice_params->slice_pic_order_cnt; ++ pic_order_cnt[1] = slice_params->slice_pic_order_cnt; ++ ++ cedrus_h265_frame_info_write_single(ctx, output_pic_list_index, ++ slice_params->pic_struct != 0, ++ pic_order_cnt, ++ run->dst->vb2_buf.index); ++ ++ cedrus_write(dev, VE_DEC_H265_OUTPUT_FRAME_IDX, output_pic_list_index); ++ ++ /* Reference picture list 0 (for P/B frames). */ ++ if (slice_params->slice_type != V4L2_HEVC_SLICE_TYPE_I) { ++ cedrus_h265_ref_pic_list_write(dev, slice_params->dpb, ++ slice_params->ref_idx_l0, ++ slice_params->num_ref_idx_l0_active_minus1 + 1, ++ VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST0); ++ ++ if ((pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED) || ++ (pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED)) ++ cedrus_h265_pred_weight_write(dev, ++ pred_weight_table->delta_luma_weight_l0, ++ pred_weight_table->luma_offset_l0, ++ pred_weight_table->delta_chroma_weight_l0, ++ pred_weight_table->chroma_offset_l0, ++ slice_params->num_ref_idx_l0_active_minus1 + 1, ++ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L0, ++ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L0); ++ } ++ ++ /* Reference picture list 1 (for B frames). */ ++ if (slice_params->slice_type == V4L2_HEVC_SLICE_TYPE_B) { ++ cedrus_h265_ref_pic_list_write(dev, slice_params->dpb, ++ slice_params->ref_idx_l1, ++ slice_params->num_ref_idx_l1_active_minus1 + 1, ++ VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST1); ++ ++ if (pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED) ++ cedrus_h265_pred_weight_write(dev, ++ pred_weight_table->delta_luma_weight_l1, ++ pred_weight_table->luma_offset_l1, ++ pred_weight_table->delta_chroma_weight_l1, ++ pred_weight_table->chroma_offset_l1, ++ slice_params->num_ref_idx_l1_active_minus1 + 1, ++ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L1, ++ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L1); ++ } ++ ++ /* Enable appropriate interruptions. */ ++ cedrus_write(dev, VE_DEC_H265_CTRL, VE_DEC_H265_CTRL_IRQ_MASK); ++} ++ ++static int cedrus_h265_start(struct cedrus_ctx *ctx) ++{ ++ struct cedrus_dev *dev = ctx->dev; ++ ++ /* The buffer size is calculated at setup time. */ ++ ctx->codec.h265.mv_col_buf_size = 0; ++ ++ ctx->codec.h265.neighbor_info_buf = ++ dma_alloc_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, ++ &ctx->codec.h265.neighbor_info_buf_addr, ++ GFP_KERNEL); ++ if (!ctx->codec.h265.neighbor_info_buf) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++static void cedrus_h265_stop(struct cedrus_ctx *ctx) ++{ ++ struct cedrus_dev *dev = ctx->dev; ++ ++ if (ctx->codec.h265.mv_col_buf_size > 0) { ++ dma_free_coherent(dev->dev, ctx->codec.h265.mv_col_buf_size, ++ ctx->codec.h265.mv_col_buf, ++ ctx->codec.h265.mv_col_buf_addr); ++ ++ ctx->codec.h265.mv_col_buf_size = 0; ++ } ++ ++ dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, ++ ctx->codec.h265.neighbor_info_buf, ++ ctx->codec.h265.neighbor_info_buf_addr); ++} ++ ++static void cedrus_h265_trigger(struct cedrus_ctx *ctx) ++{ ++ struct cedrus_dev *dev = ctx->dev; ++ ++ cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_DEC_SLICE); ++} ++ ++struct cedrus_dec_ops cedrus_dec_ops_h265 = { ++ .irq_clear = cedrus_h265_irq_clear, ++ .irq_disable = cedrus_h265_irq_disable, ++ .irq_status = cedrus_h265_irq_status, ++ .setup = cedrus_h265_setup, ++ .start = cedrus_h265_start, ++ .stop = cedrus_h265_stop, ++ .trigger = cedrus_h265_trigger, ++}; +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c +index e7e18424bab1..570a9165dd5d 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c +@@ -50,6 +50,10 @@ int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec) + reg |= VE_MODE_DEC_H264; + break; + ++ case CEDRUS_CODEC_H265: ++ reg |= VE_MODE_DEC_H265; ++ break; ++ + default: + return -EINVAL; + } +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +index 21676a1797f1..6fc28d21a6c7 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +@@ -21,10 +21,17 @@ + * * MC: Motion Compensation + * * STCD: Start Code Detect + * * SDRT: Scale Down and Rotate ++ * * WB: Writeback ++ * * BITS/BS: Bitstream ++ * * MB: Macroblock ++ * * CTU: Coding Tree Unit ++ * * CTB: Coding Tree Block ++ * * IDX: Index + */ + + #define VE_ENGINE_DEC_MPEG 0x100 + #define VE_ENGINE_DEC_H264 0x200 ++#define VE_ENGINE_DEC_H265 0x500 + + #define VE_MODE 0x00 + +@@ -235,6 +242,270 @@ + #define VE_DEC_MPEG_ROT_LUMA (VE_ENGINE_DEC_MPEG + 0xcc) + #define VE_DEC_MPEG_ROT_CHROMA (VE_ENGINE_DEC_MPEG + 0xd0) + ++#define VE_DEC_H265_DEC_NAL_HDR (VE_ENGINE_DEC_H265 + 0x00) ++ ++#define VE_DEC_H265_DEC_NAL_HDR_NUH_TEMPORAL_ID_PLUS1(v) \ ++ SHIFT_AND_MASK_BITS(v, 8, 6) ++#define VE_DEC_H265_DEC_NAL_HDR_NAL_UNIT_TYPE(v) \ ++ SHIFT_AND_MASK_BITS(v, 5, 0) ++ ++#define VE_DEC_H265_FLAG(reg_flag, ctrl_flag, flags) \ ++ (((flags) & (ctrl_flag)) ? reg_flag : 0) ++ ++#define VE_DEC_H265_DEC_SPS_HDR (VE_ENGINE_DEC_H265 + 0x04) ++ ++#define VE_DEC_H265_DEC_SPS_HDR_FLAG_STRONG_INTRA_SMOOTHING_ENABLE BIT(26) ++#define VE_DEC_H265_DEC_SPS_HDR_FLAG_SPS_TEMPORAL_MVP_ENABLED BIT(25) ++#define VE_DEC_H265_DEC_SPS_HDR_FLAG_SAMPLE_ADAPTIVE_OFFSET_ENABLED BIT(24) ++#define VE_DEC_H265_DEC_SPS_HDR_FLAG_AMP_ENABLED BIT(23) ++#define VE_DEC_H265_DEC_SPS_HDR_FLAG_SEPARATE_COLOUR_PLANE BIT(2) ++ ++#define VE_DEC_H265_DEC_SPS_HDR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTRA(v) \ ++ SHIFT_AND_MASK_BITS(v, 22, 20) ++#define VE_DEC_H265_DEC_SPS_HDR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTER(v) \ ++ SHIFT_AND_MASK_BITS(v, 19, 17) ++#define VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_TRANSFORM_BLOCK_SIZE(v) \ ++ SHIFT_AND_MASK_BITS(v, 16, 15) ++#define VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_TRANSFORM_BLOCK_SIZE_MINUS2(v) \ ++ SHIFT_AND_MASK_BITS(v, 14, 13) ++#define VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE(v) \ ++ SHIFT_AND_MASK_BITS(v, 12, 11) ++#define VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_LUMA_CODING_BLOCK_SIZE_MINUS3(v) \ ++ SHIFT_AND_MASK_BITS(v, 10, 9) ++#define VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_CHROMA_MINUS8(v) \ ++ SHIFT_AND_MASK_BITS(v, 8, 6) ++#define VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_LUMA_MINUS8(v) \ ++ SHIFT_AND_MASK_BITS(v, 5, 3) ++#define VE_DEC_H265_DEC_SPS_HDR_CHROMA_FORMAT_IDC(v) \ ++ SHIFT_AND_MASK_BITS(v, 1, 0) ++ ++#define VE_DEC_H265_DEC_PIC_SIZE (VE_ENGINE_DEC_H265 + 0x08) ++ ++#define VE_DEC_H265_DEC_PIC_SIZE_WIDTH(w) (((w) << 0) & GENMASK(13, 0)) ++#define VE_DEC_H265_DEC_PIC_SIZE_HEIGHT(h) (((h) << 16) & GENMASK(29, 16)) ++ ++#define VE_DEC_H265_DEC_PCM_CTRL (VE_ENGINE_DEC_H265 + 0x0c) ++ ++#define VE_DEC_H265_DEC_PCM_CTRL_FLAG_PCM_ENABLED BIT(15) ++#define VE_DEC_H265_DEC_PCM_CTRL_FLAG_PCM_LOOP_FILTER_DISABLED BIT(14) ++ ++#define VE_DEC_H265_DEC_PCM_CTRL_LOG2_DIFF_MAX_MIN_PCM_LUMA_CODING_BLOCK_SIZE(v) \ ++ SHIFT_AND_MASK_BITS(v, 11, 10) ++#define VE_DEC_H265_DEC_PCM_CTRL_LOG2_MIN_PCM_LUMA_CODING_BLOCK_SIZE_MINUS3(v) \ ++ SHIFT_AND_MASK_BITS(v, 9, 8) ++#define VE_DEC_H265_DEC_PCM_CTRL_PCM_SAMPLE_BIT_DEPTH_CHROMA_MINUS1(v) \ ++ SHIFT_AND_MASK_BITS(v, 7, 4) ++#define VE_DEC_H265_DEC_PCM_CTRL_PCM_SAMPLE_BIT_DEPTH_LUMA_MINUS1(v) \ ++ SHIFT_AND_MASK_BITS(v, 3, 0) ++ ++#define VE_DEC_H265_DEC_PPS_CTRL0 (VE_ENGINE_DEC_H265 + 0x10) ++ ++#define VE_DEC_H265_DEC_PPS_CTRL0_FLAG_CU_QP_DELTA_ENABLED BIT(3) ++#define VE_DEC_H265_DEC_PPS_CTRL0_FLAG_TRANSFORM_SKIP_ENABLED BIT(2) ++#define VE_DEC_H265_DEC_PPS_CTRL0_FLAG_CONSTRAINED_INTRA_PRED BIT(1) ++#define VE_DEC_H265_DEC_PPS_CTRL0_FLAG_SIGN_DATA_HIDING_ENABLED BIT(0) ++ ++#define VE_DEC_H265_DEC_PPS_CTRL0_PPS_CR_QP_OFFSET(v) \ ++ SHIFT_AND_MASK_BITS(v, 29, 24) ++#define VE_DEC_H265_DEC_PPS_CTRL0_PPS_CB_QP_OFFSET(v) \ ++ SHIFT_AND_MASK_BITS(v, 21, 16) ++#define VE_DEC_H265_DEC_PPS_CTRL0_INIT_QP_MINUS26(v) \ ++ SHIFT_AND_MASK_BITS(v, 14, 8) ++#define VE_DEC_H265_DEC_PPS_CTRL0_DIFF_CU_QP_DELTA_DEPTH(v) \ ++ SHIFT_AND_MASK_BITS(v, 5, 4) ++ ++#define VE_DEC_H265_DEC_PPS_CTRL1 (VE_ENGINE_DEC_H265 + 0x14) ++ ++#define VE_DEC_H265_DEC_PPS_CTRL1_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED BIT(6) ++#define VE_DEC_H265_DEC_PPS_CTRL1_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED BIT(5) ++#define VE_DEC_H265_DEC_PPS_CTRL1_FLAG_ENTROPY_CODING_SYNC_ENABLED BIT(4) ++#define VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TILES_ENABLED BIT(3) ++#define VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TRANSQUANT_BYPASS_ENABLED BIT(2) ++#define VE_DEC_H265_DEC_PPS_CTRL1_FLAG_WEIGHTED_BIPRED BIT(1) ++#define VE_DEC_H265_DEC_PPS_CTRL1_FLAG_WEIGHTED_PRED BIT(0) ++ ++#define VE_DEC_H265_DEC_PPS_CTRL1_LOG2_PARALLEL_MERGE_LEVEL_MINUS2(v) \ ++ SHIFT_AND_MASK_BITS(v, 10, 8) ++ ++#define VE_DEC_H265_SCALING_LIST_CTRL0 (VE_ENGINE_DEC_H265 + 0x18) ++ ++#define VE_DEC_H265_SCALING_LIST_CTRL0_FLAG_ENABLED BIT(31) ++ ++#define VE_DEC_H265_SCALING_LIST_CTRL0_SRAM (0 << 30) ++#define VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT (1 << 30) ++ ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO0 (VE_ENGINE_DEC_H265 + 0x20) ++ ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_COLLOCATED_FROM_L0 BIT(11) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_CABAC_INIT BIT(10) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_MVD_L1_ZERO BIT(9) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_SLICE_SAO_CHROMA BIT(8) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_SLICE_SAO_LUMA BIT(7) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_SLICE_TEMPORAL_MVP_ENABLE BIT(6) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_DEPENDENT_SLICE_SEGMENT BIT(1) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC BIT(0) ++ ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_PICTURE_TYPE(v) \ ++ SHIFT_AND_MASK_BITS(v, 29, 28) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_FIVE_MINUS_MAX_NUM_MERGE_CAND(v) \ ++ SHIFT_AND_MASK_BITS(v, 26, 24) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_NUM_REF_IDX_L1_ACTIVE_MINUS1(v) \ ++ SHIFT_AND_MASK_BITS(v, 23, 20) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_NUM_REF_IDX_L0_ACTIVE_MINUS1(v) \ ++ SHIFT_AND_MASK_BITS(v, 19, 16) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLLOCATED_REF_IDX(v) \ ++ SHIFT_AND_MASK_BITS(v, 15, 12) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLOUR_PLANE_ID(v) \ ++ SHIFT_AND_MASK_BITS(v, 5, 4) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_SLICE_TYPE(v) \ ++ SHIFT_AND_MASK_BITS(v, 3, 2) ++ ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO1 (VE_ENGINE_DEC_H265 + 0x24) ++ ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO1_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED BIT(23) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO1_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED BIT(22) ++ ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_TC_OFFSET_DIV2(v) \ ++ SHIFT_AND_MASK_BITS(v, 31, 28) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_BETA_OFFSET_DIV2(v) \ ++ SHIFT_AND_MASK_BITS(v, 27, 24) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_POC_BIGEST_IN_RPS_ST(v) \ ++ ((v) ? BIT(21) : 0) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CR_QP_OFFSET(v) \ ++ SHIFT_AND_MASK_BITS(v, 20, 16) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CB_QP_OFFSET(v) \ ++ SHIFT_AND_MASK_BITS(v, 12, 8) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_QP_DELTA(v) \ ++ SHIFT_AND_MASK_BITS(v, 6, 0) ++ ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO2 (VE_ENGINE_DEC_H265 + 0x28) ++ ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(v) \ ++ SHIFT_AND_MASK_BITS(v, 21, 8) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO2_CHROMA_LOG2_WEIGHT_DENOM(v) \ ++ SHIFT_AND_MASK_BITS(v, 6, 4) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO2_LUMA_LOG2_WEIGHT_DENOM(v) \ ++ SHIFT_AND_MASK_BITS(v, 2, 0) ++ ++#define VE_DEC_H265_DEC_CTB_ADDR (VE_ENGINE_DEC_H265 + 0x2c) ++ ++#define VE_DEC_H265_DEC_CTB_ADDR_Y(y) SHIFT_AND_MASK_BITS(y, 25, 16) ++#define VE_DEC_H265_DEC_CTB_ADDR_X(x) SHIFT_AND_MASK_BITS(x, 9, 0) ++ ++#define VE_DEC_H265_CTRL (VE_ENGINE_DEC_H265 + 0x30) ++ ++#define VE_DEC_H265_CTRL_DDR_CONSISTENCY_EN BIT(31) ++#define VE_DEC_H265_CTRL_STCD_EN BIT(25) ++#define VE_DEC_H265_CTRL_EPTB_DEC_BYPASS_EN BIT(24) ++#define VE_DEC_H265_CTRL_TQ_BYPASS_EN BIT(12) ++#define VE_DEC_H265_CTRL_VLD_BYPASS_EN BIT(11) ++#define VE_DEC_H265_CTRL_NCRI_CACHE_DISABLE BIT(10) ++#define VE_DEC_H265_CTRL_ROTATE_SCALE_OUT_EN BIT(9) ++#define VE_DEC_H265_CTRL_MC_NO_WRITEBACK BIT(8) ++#define VE_DEC_H265_CTRL_VLD_DATA_REQ_IRQ_EN BIT(2) ++#define VE_DEC_H265_CTRL_ERROR_IRQ_EN BIT(1) ++#define VE_DEC_H265_CTRL_FINISH_IRQ_EN BIT(0) ++#define VE_DEC_H265_CTRL_IRQ_MASK \ ++ (VE_DEC_H265_CTRL_FINISH_IRQ_EN | VE_DEC_H265_CTRL_ERROR_IRQ_EN | \ ++ VE_DEC_H265_CTRL_VLD_DATA_REQ_IRQ_EN) ++ ++#define VE_DEC_H265_TRIGGER (VE_ENGINE_DEC_H265 + 0x34) ++ ++#define VE_DEC_H265_TRIGGER_STCD_VC1 (0x02 << 4) ++#define VE_DEC_H265_TRIGGER_STCD_AVS (0x01 << 4) ++#define VE_DEC_H265_TRIGGER_STCD_HEVC (0x00 << 4) ++#define VE_DEC_H265_TRIGGER_DEC_SLICE (0x08 << 0) ++#define VE_DEC_H265_TRIGGER_INIT_SWDEC (0x07 << 0) ++#define VE_DEC_H265_TRIGGER_BYTE_ALIGN (0x06 << 0) ++#define VE_DEC_H265_TRIGGER_GET_VLCUE (0x05 << 0) ++#define VE_DEC_H265_TRIGGER_GET_VLCSE (0x04 << 0) ++#define VE_DEC_H265_TRIGGER_FLUSH_BITS (0x03 << 0) ++#define VE_DEC_H265_TRIGGER_GET_BITS (0x02 << 0) ++#define VE_DEC_H265_TRIGGER_SHOW_BITS (0x01 << 0) ++ ++#define VE_DEC_H265_STATUS (VE_ENGINE_DEC_H265 + 0x38) ++ ++#define VE_DEC_H265_STATUS_STCD BIT(24) ++#define VE_DEC_H265_STATUS_STCD_BUSY BIT(21) ++#define VE_DEC_H265_STATUS_WB_BUSY BIT(20) ++#define VE_DEC_H265_STATUS_BS_DMA_BUSY BIT(19) ++#define VE_DEC_H265_STATUS_IQIT_BUSY BIT(18) ++#define VE_DEC_H265_STATUS_INTER_BUSY BIT(17) ++#define VE_DEC_H265_STATUS_MORE_DATA BIT(16) ++#define VE_DEC_H265_STATUS_VLD_BUSY BIT(14) ++#define VE_DEC_H265_STATUS_DEBLOCKING_BUSY BIT(13) ++#define VE_DEC_H265_STATUS_DEBLOCKING_DRAM_BUSY BIT(12) ++#define VE_DEC_H265_STATUS_INTRA_BUSY BIT(11) ++#define VE_DEC_H265_STATUS_SAO_BUSY BIT(10) ++#define VE_DEC_H265_STATUS_MVP_BUSY BIT(9) ++#define VE_DEC_H265_STATUS_SWDEC_BUSY BIT(8) ++#define VE_DEC_H265_STATUS_OVER_TIME BIT(3) ++#define VE_DEC_H265_STATUS_VLD_DATA_REQ BIT(2) ++#define VE_DEC_H265_STATUS_ERROR BIT(1) ++#define VE_DEC_H265_STATUS_SUCCESS BIT(0) ++#define VE_DEC_H265_STATUS_STCD_TYPE_MASK GENMASK(23, 22) ++#define VE_DEC_H265_STATUS_CHECK_MASK \ ++ (VE_DEC_H265_STATUS_SUCCESS | VE_DEC_H265_STATUS_ERROR | \ ++ VE_DEC_H265_STATUS_VLD_DATA_REQ) ++#define VE_DEC_H265_STATUS_CHECK_ERROR \ ++ (VE_DEC_H265_STATUS_ERROR | VE_DEC_H265_STATUS_VLD_DATA_REQ) ++ ++#define VE_DEC_H265_DEC_CTB_NUM (VE_ENGINE_DEC_H265 + 0x3c) ++ ++#define VE_DEC_H265_BITS_ADDR (VE_ENGINE_DEC_H265 + 0x40) ++ ++#define VE_DEC_H265_BITS_ADDR_FIRST_SLICE_DATA BIT(30) ++#define VE_DEC_H265_BITS_ADDR_LAST_SLICE_DATA BIT(29) ++#define VE_DEC_H265_BITS_ADDR_VALID_SLICE_DATA BIT(28) ++#define VE_DEC_H265_BITS_ADDR_BASE(a) (((a) >> 8) & GENMASK(27, 0)) ++ ++#define VE_DEC_H265_BITS_OFFSET (VE_ENGINE_DEC_H265 + 0x44) ++#define VE_DEC_H265_BITS_LEN (VE_ENGINE_DEC_H265 + 0x48) ++ ++#define VE_DEC_H265_BITS_END_ADDR (VE_ENGINE_DEC_H265 + 0x4c) ++ ++#define VE_DEC_H265_BITS_END_ADDR_BASE(a) ((a) >> 8) ++ ++#define VE_DEC_H265_SDRT_CTRL (VE_ENGINE_DEC_H265 + 0x50) ++#define VE_DEC_H265_SDRT_LUMA_ADDR (VE_ENGINE_DEC_H265 + 0x54) ++#define VE_DEC_H265_SDRT_CHROMA_ADDR (VE_ENGINE_DEC_H265 + 0x58) ++ ++#define VE_DEC_H265_OUTPUT_FRAME_IDX (VE_ENGINE_DEC_H265 + 0x5c) ++ ++#define VE_DEC_H265_NEIGHBOR_INFO_ADDR (VE_ENGINE_DEC_H265 + 0x60) ++ ++#define VE_DEC_H265_NEIGHBOR_INFO_ADDR_BASE(a) ((a) >> 8) ++ ++#define VE_DEC_H265_ENTRY_POINT_OFFSET_ADDR (VE_ENGINE_DEC_H265 + 0x64) ++#define VE_DEC_H265_TILE_START_CTB (VE_ENGINE_DEC_H265 + 0x68) ++#define VE_DEC_H265_TILE_END_CTB (VE_ENGINE_DEC_H265 + 0x6c) ++ ++#define VE_DEC_H265_LOW_ADDR (VE_ENGINE_DEC_H265 + 0x80) ++ ++#define VE_DEC_H265_LOW_ADDR_PRIMARY_CHROMA(a) \ ++ SHIFT_AND_MASK_BITS(a, 31, 24) ++#define VE_DEC_H265_LOW_ADDR_SECONDARY_CHROMA(a) \ ++ SHIFT_AND_MASK_BITS(a, 23, 16) ++#define VE_DEC_H265_LOW_ADDR_ENTRY_POINTS_BUF(a) \ ++ SHIFT_AND_MASK_BITS(a, 7, 0) ++ ++#define VE_DEC_H265_SRAM_OFFSET (VE_ENGINE_DEC_H265 + 0xe0) ++ ++#define VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L0 0x00 ++#define VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L0 0x20 ++#define VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L1 0x60 ++#define VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L1 0x80 ++#define VE_DEC_H265_SRAM_OFFSET_FRAME_INFO 0x400 ++#define VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT 0x20 ++#define VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS 0x800 ++#define VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST0 0xc00 ++#define VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST1 0xc10 ++ ++#define VE_DEC_H265_SRAM_DATA (VE_ENGINE_DEC_H265 + 0xe4) ++ ++#define VE_DEC_H265_SRAM_DATA_ADDR_BASE(a) ((a) >> 8) ++#define VE_DEC_H265_SRAM_REF_PIC_LIST_LT_REF BIT(7) ++ + #define VE_H264_SPS 0x200 + #define VE_H264_SPS_MBS_ONLY BIT(18) + #define VE_H264_SPS_MB_ADAPTIVE_FRAME_FIELD BIT(17) +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +index f745f66c4440..cc15a5cf107d 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +@@ -41,6 +41,11 @@ static struct cedrus_format cedrus_formats[] = { + .pixelformat = V4L2_PIX_FMT_H264_SLICE, + .directions = CEDRUS_DECODE_SRC, + }, ++ { ++ .pixelformat = V4L2_PIX_FMT_HEVC_SLICE, ++ .directions = CEDRUS_DECODE_SRC, ++ .capabilities = CEDRUS_CAPABILITY_H265_DEC, ++ }, + { + .pixelformat = V4L2_PIX_FMT_SUNXI_TILED_NV12, + .directions = CEDRUS_DECODE_DST, +@@ -102,6 +107,7 @@ void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt) + switch (pix_fmt->pixelformat) { + case V4L2_PIX_FMT_MPEG2_SLICE: + case V4L2_PIX_FMT_H264_SLICE: ++ case V4L2_PIX_FMT_HEVC_SLICE: + /* Zero bytes per line for encoded source. */ + bytesperline = 0; + /* Choose some minimum size since this can't be 0 */ +@@ -439,6 +445,10 @@ static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count) + ctx->current_codec = CEDRUS_CODEC_H264; + break; + ++ case V4L2_PIX_FMT_HEVC_SLICE: ++ ctx->current_codec = CEDRUS_CODEC_H265; ++ break; ++ + default: + return -EINVAL; + } +-- +2.23.0 + +From 137272cdf7cc5be835f44216e6003769d1638480 Mon Sep 17 00:00:00 2001 +From: Hans Verkuil +Date: Fri, 11 Oct 2019 06:32:40 -0300 +Subject: [PATCH] media: vb2: add V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF + +This patch adds support for the V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF +flag. + +It also adds a new V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF +capability. + +Drivers should set vb2_queue->subsystem_flags to +VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF to indicate support +for this flag. + +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + Documentation/media/uapi/v4l/buffer.rst | 13 +++++++++++++ + Documentation/media/uapi/v4l/vidioc-reqbufs.rst | 6 ++++++ + drivers/media/common/videobuf2/videobuf2-v4l2.c | 12 ++++++++++-- + include/media/videobuf2-core.h | 3 +++ + include/media/videobuf2-v4l2.h | 5 +++++ + include/uapi/linux/videodev2.h | 13 ++++++++----- + 6 files changed, 45 insertions(+), 7 deletions(-) + +diff --git a/Documentation/media/uapi/v4l/buffer.rst b/Documentation/media/uapi/v4l/buffer.rst +index 1cbd9cde57f3..9149b57728e5 100644 +--- a/Documentation/media/uapi/v4l/buffer.rst ++++ b/Documentation/media/uapi/v4l/buffer.rst +@@ -607,6 +607,19 @@ Buffer Flags + applications shall use this flag for output buffers if the data in + this buffer has not been created by the CPU but by some + DMA-capable unit, in which case caches have not been used. ++ * .. _`V4L2-BUF-FLAG-M2M-HOLD-CAPTURE-BUF`: ++ ++ - ``V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF`` ++ - 0x00000200 ++ - Only valid if ``V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF`` is ++ set. It is typically used with stateless decoders where multiple ++ output buffers each decode to a slice of the decoded frame. ++ Applications can set this flag when queueing the output buffer ++ to prevent the driver from dequeueing the capture buffer after ++ the output buffer has been decoded (i.e. the capture buffer is ++ 'held'). If the timestamp of this output buffer differs from that ++ of the previous output buffer, then that indicates the start of a ++ new frame and the previously held capture buffer is dequeued. + * .. _`V4L2-BUF-FLAG-LAST`: + + - ``V4L2_BUF_FLAG_LAST`` +diff --git a/Documentation/media/uapi/v4l/vidioc-reqbufs.rst b/Documentation/media/uapi/v4l/vidioc-reqbufs.rst +index d7faef10e39b..d0c643db477a 100644 +--- a/Documentation/media/uapi/v4l/vidioc-reqbufs.rst ++++ b/Documentation/media/uapi/v4l/vidioc-reqbufs.rst +@@ -125,6 +125,7 @@ aborting or finishing any DMA in progress, an implicit + .. _V4L2-BUF-CAP-SUPPORTS-DMABUF: + .. _V4L2-BUF-CAP-SUPPORTS-REQUESTS: + .. _V4L2-BUF-CAP-SUPPORTS-ORPHANED-BUFS: ++.. _V4L2-BUF-CAP-SUPPORTS-M2M-HOLD-CAPTURE-BUF: + + .. cssclass:: longtable + +@@ -150,6 +151,11 @@ aborting or finishing any DMA in progress, an implicit + - The kernel allows calling :ref:`VIDIOC_REQBUFS` while buffers are still + mapped or exported via DMABUF. These orphaned buffers will be freed + when they are unmapped or when the exported DMABUF fds are closed. ++ * - ``V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF`` ++ - 0x00000020 ++ - Only valid for stateless decoders. If set, then userspace can set the ++ ``V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF`` flag to hold off on returning the ++ capture buffer until the OUTPUT timestamp changes. + + Return Value + ============ +diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c +index 5a9ba3846f0a..e652f4318284 100644 +--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c ++++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c +@@ -49,8 +49,11 @@ module_param(debug, int, 0644); + V4L2_BUF_FLAG_REQUEST_FD | \ + V4L2_BUF_FLAG_TIMESTAMP_MASK) + /* Output buffer flags that should be passed on to the driver */ +-#define V4L2_BUFFER_OUT_FLAGS (V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | \ +- V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_TIMECODE) ++#define V4L2_BUFFER_OUT_FLAGS (V4L2_BUF_FLAG_PFRAME | \ ++ V4L2_BUF_FLAG_BFRAME | \ ++ V4L2_BUF_FLAG_KEYFRAME | \ ++ V4L2_BUF_FLAG_TIMECODE | \ ++ V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF) + + /* + * __verify_planes_array() - verify that the planes array passed in struct +@@ -194,6 +197,7 @@ static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b + } + vbuf->sequence = 0; + vbuf->request_fd = -1; ++ vbuf->is_held = false; + + if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { + switch (b->memory) { +@@ -321,6 +325,8 @@ static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b + */ + vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE; + vbuf->field = b->field; ++ if (!(q->subsystem_flags & VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF)) ++ vbuf->flags &= ~V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF; + } else { + /* Zero any output buffer flags as this is a capture buffer */ + vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS; +@@ -654,6 +660,8 @@ static void fill_buf_caps(struct vb2_queue *q, u32 *caps) + *caps |= V4L2_BUF_CAP_SUPPORTS_USERPTR; + if (q->io_modes & VB2_DMABUF) + *caps |= V4L2_BUF_CAP_SUPPORTS_DMABUF; ++ if (q->subsystem_flags & VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF) ++ *caps |= V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF; + #ifdef CONFIG_MEDIA_CONTROLLER_REQUEST_API + if (q->supports_requests) + *caps |= V4L2_BUF_CAP_SUPPORTS_REQUESTS; +diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h +index 640aabe69450..a2b2208b02da 100644 +--- a/include/media/videobuf2-core.h ++++ b/include/media/videobuf2-core.h +@@ -505,6 +505,8 @@ struct vb2_buf_ops { + * @buf_ops: callbacks to deliver buffer information. + * between user-space and kernel-space. + * @drv_priv: driver private data. ++ * @subsystem_flags: Flags specific to the subsystem (V4L2/DVB/etc.). Not used ++ * by the vb2 core. + * @buf_struct_size: size of the driver-specific buffer structure; + * "0" indicates the driver doesn't want to use a custom buffer + * structure type. for example, ``sizeof(struct vb2_v4l2_buffer)`` +@@ -571,6 +573,7 @@ struct vb2_queue { + const struct vb2_buf_ops *buf_ops; + + void *drv_priv; ++ u32 subsystem_flags; + unsigned int buf_struct_size; + u32 timestamp_flags; + gfp_t gfp_flags; +diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h +index 8a10889dc2fd..59bf33a12648 100644 +--- a/include/media/videobuf2-v4l2.h ++++ b/include/media/videobuf2-v4l2.h +@@ -33,6 +33,7 @@ + * @timecode: frame timecode. + * @sequence: sequence count of this frame. + * @request_fd: the request_fd associated with this buffer ++ * @is_held: if true, then this capture buffer was held + * @planes: plane information (userptr/fd, length, bytesused, data_offset). + * + * Should contain enough information to be able to cover all the fields +@@ -46,9 +47,13 @@ struct vb2_v4l2_buffer { + struct v4l2_timecode timecode; + __u32 sequence; + __s32 request_fd; ++ bool is_held; + struct vb2_plane planes[VB2_MAX_PLANES]; + }; + ++/* VB2 V4L2 flags as set in vb2_queue.subsystem_flags */ ++#define VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF (1 << 0) ++ + /* + * to_vb2_v4l2_buffer() - cast struct vb2_buffer * to struct vb2_v4l2_buffer * + */ +diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h +index b3c0961b62a0..9f4e66affac4 100644 +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -920,11 +920,12 @@ struct v4l2_requestbuffers { + }; + + /* capabilities for struct v4l2_requestbuffers and v4l2_create_buffers */ +-#define V4L2_BUF_CAP_SUPPORTS_MMAP (1 << 0) +-#define V4L2_BUF_CAP_SUPPORTS_USERPTR (1 << 1) +-#define V4L2_BUF_CAP_SUPPORTS_DMABUF (1 << 2) +-#define V4L2_BUF_CAP_SUPPORTS_REQUESTS (1 << 3) +-#define V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS (1 << 4) ++#define V4L2_BUF_CAP_SUPPORTS_MMAP (1 << 0) ++#define V4L2_BUF_CAP_SUPPORTS_USERPTR (1 << 1) ++#define V4L2_BUF_CAP_SUPPORTS_DMABUF (1 << 2) ++#define V4L2_BUF_CAP_SUPPORTS_REQUESTS (1 << 3) ++#define V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS (1 << 4) ++#define V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF (1 << 5) + + /** + * struct v4l2_plane - plane info for multi-planar buffers +@@ -1046,6 +1047,8 @@ static inline __u64 v4l2_timeval_to_ns(const struct timeval *tv) + #define V4L2_BUF_FLAG_IN_REQUEST 0x00000080 + /* timecode field is valid */ + #define V4L2_BUF_FLAG_TIMECODE 0x00000100 ++/* Don't return the capture buffer until OUTPUT timestamp changes */ ++#define V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF 0x00000200 + /* Buffer is prepared for queuing */ + #define V4L2_BUF_FLAG_PREPARED 0x00000400 + /* Cache handling flags */ +-- +2.23.0 + +From bac06ec36ea2012ff0daa9767d0f77bf9c6064ec Mon Sep 17 00:00:00 2001 +From: Hans Verkuil +Date: Fri, 11 Oct 2019 06:32:42 -0300 +Subject: [PATCH] media: videodev2.h: add V4L2_DEC_CMD_FLUSH + +Add this new V4L2_DEC_CMD_FLUSH decoder command and document it. + +Reviewed-by: Boris Brezillon +Reviewed-by: Alexandre Courbot +Signed-off-by: Hans Verkuil +Signed-off-by: Jernej Skrabec +Signed-off-by: Mauro Carvalho Chehab +--- + Documentation/media/uapi/v4l/vidioc-decoder-cmd.rst | 10 +++++++++- + Documentation/media/videodev2.h.rst.exceptions | 1 + + include/uapi/linux/videodev2.h | 1 + + 3 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/Documentation/media/uapi/v4l/vidioc-decoder-cmd.rst b/Documentation/media/uapi/v4l/vidioc-decoder-cmd.rst +index 57f0066f4cff..f1a504836f31 100644 +--- a/Documentation/media/uapi/v4l/vidioc-decoder-cmd.rst ++++ b/Documentation/media/uapi/v4l/vidioc-decoder-cmd.rst +@@ -208,7 +208,15 @@ introduced in Linux 3.3. They are, however, mandatory for stateful mem2mem decod + been started yet, the driver will return an ``EPERM`` error code. When + the decoder is already running, this command does nothing. No + flags are defined for this command. +- ++ * - ``V4L2_DEC_CMD_FLUSH`` ++ - 4 ++ - Flush any held capture buffers. Only valid for stateless decoders. ++ This command is typically used when the application reached the ++ end of the stream and the last output buffer had the ++ ``V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF`` flag set. This would prevent ++ dequeueing the capture buffer containing the last decoded frame. ++ So this command can be used to explicitly flush that final decoded ++ frame. This command does nothing if there are no held capture buffers. + + Return Value + ============ +diff --git a/Documentation/media/videodev2.h.rst.exceptions b/Documentation/media/videodev2.h.rst.exceptions +index b58e381bdf7b..c23e5ef30c78 100644 +--- a/Documentation/media/videodev2.h.rst.exceptions ++++ b/Documentation/media/videodev2.h.rst.exceptions +@@ -435,6 +435,7 @@ replace define V4L2_DEC_CMD_START decoder-cmds + replace define V4L2_DEC_CMD_STOP decoder-cmds + replace define V4L2_DEC_CMD_PAUSE decoder-cmds + replace define V4L2_DEC_CMD_RESUME decoder-cmds ++replace define V4L2_DEC_CMD_FLUSH decoder-cmds + + replace define V4L2_DEC_CMD_START_MUTE_AUDIO decoder-cmds + replace define V4L2_DEC_CMD_PAUSE_TO_BLACK decoder-cmds +diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h +index 9f4e66affac4..d969842bbfe2 100644 +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -1984,6 +1984,7 @@ struct v4l2_encoder_cmd { + #define V4L2_DEC_CMD_STOP (1) + #define V4L2_DEC_CMD_PAUSE (2) + #define V4L2_DEC_CMD_RESUME (3) ++#define V4L2_DEC_CMD_FLUSH (4) + + /* Flags for V4L2_DEC_CMD_START */ + #define V4L2_DEC_CMD_START_MUTE_AUDIO (1 << 0) +-- +2.23.0 + +From d4e0f82ac840bf3d16b25d60f261b429603138a9 Mon Sep 17 00:00:00 2001 +From: Hans Verkuil +Date: Thu, 15 Aug 2019 11:44:52 -0300 +Subject: [PATCH] media: pixfmt-compressed.rst: improve H264/HEVC/MPEG1+2/VP8+9 + documentation + +The existing documentation was incorrect and did not correspond +to how actual codec drivers implemented this. + +Update the documentation to explicitly specify what is actually +expected. + +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + .../media/uapi/v4l/pixfmt-compressed.rst | 36 +++++++++++++++---- + 1 file changed, 30 insertions(+), 6 deletions(-) + +diff --git a/Documentation/media/uapi/v4l/pixfmt-compressed.rst b/Documentation/media/uapi/v4l/pixfmt-compressed.rst +index 493b6020107d..292fdc116c77 100644 +--- a/Documentation/media/uapi/v4l/pixfmt-compressed.rst ++++ b/Documentation/media/uapi/v4l/pixfmt-compressed.rst +@@ -41,7 +41,12 @@ Compressed Formats + + - ``V4L2_PIX_FMT_H264`` + - 'H264' +- - H264 video elementary stream with start codes. ++ - H264 Access Unit. ++ The decoder expects one Access Unit per buffer. ++ The encoder generates one Access Unit per buffer. ++ If :ref:`VIDIOC_ENUM_FMT` reports ``V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM`` ++ then the decoder has no requirements since it can parse all the ++ information from the raw bytestream. + * .. _V4L2-PIX-FMT-H264-NO-SC: + + - ``V4L2_PIX_FMT_H264_NO_SC`` +@@ -89,12 +94,20 @@ Compressed Formats + + - ``V4L2_PIX_FMT_MPEG1`` + - 'MPG1' +- - MPEG1 video elementary stream. ++ - MPEG1 Picture. Each buffer starts with a Picture header, followed ++ by other headers as needed and ending with the Picture data. ++ If :ref:`VIDIOC_ENUM_FMT` reports ``V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM`` ++ then the decoder has no requirements since it can parse all the ++ information from the raw bytestream. + * .. _V4L2-PIX-FMT-MPEG2: + + - ``V4L2_PIX_FMT_MPEG2`` + - 'MPG2' +- - MPEG2 video elementary stream. ++ - MPEG2 Picture. Each buffer starts with a Picture header, followed ++ by other headers as needed and ending with the Picture data. ++ If :ref:`VIDIOC_ENUM_FMT` reports ``V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM`` ++ then the decoder has no requirements since it can parse all the ++ information from the raw bytestream. + * .. _V4L2-PIX-FMT-MPEG2-SLICE: + + - ``V4L2_PIX_FMT_MPEG2_SLICE`` +@@ -135,7 +148,9 @@ Compressed Formats + + - ``V4L2_PIX_FMT_VP8`` + - 'VP80' +- - VP8 video elementary stream. ++ - VP8 compressed video frame. The encoder generates one ++ compressed frame per buffer, and the decoder requires one ++ compressed frame per buffer. + * .. _V4L2-PIX-FMT-VP8-FRAME: + + - ``V4L2_PIX_FMT_VP8_FRAME`` +@@ -160,12 +175,19 @@ Compressed Formats + + - ``V4L2_PIX_FMT_VP9`` + - 'VP90' +- - VP9 video elementary stream. ++ - VP9 compressed video frame. The encoder generates one ++ compressed frame per buffer, and the decoder requires one ++ compressed frame per buffer. + * .. _V4L2-PIX-FMT-HEVC: + + - ``V4L2_PIX_FMT_HEVC`` + - 'HEVC' +- - HEVC/H.265 video elementary stream. ++ - HEVC/H.265 Access Unit. ++ The decoder expects one Access Unit per buffer. ++ The encoder generates one Access Unit per buffer. ++ If :ref:`VIDIOC_ENUM_FMT` reports ``V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM`` ++ then the decoder has no requirements since it can parse all the ++ information from the raw bytestream. + * .. _V4L2-PIX-FMT-FWHT: + + - ``V4L2_PIX_FMT_FWHT`` +@@ -173,6 +195,8 @@ Compressed Formats + - Video elementary stream using a codec based on the Fast Walsh Hadamard + Transform. This codec is implemented by the vicodec ('Virtual Codec') + driver. See the codec-fwht.h header for more details. ++ :ref:`VIDIOC_ENUM_FMT` reports ``V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM`` ++ since the decoder can parse all the information from the raw bytestream. + * .. _V4L2-PIX-FMT-FWHT-STATELESS: + + - ``V4L2_PIX_FMT_FWHT_STATELESS`` +-- +2.23.0 + +From de06f289283298e2938445019999cec46435375c Mon Sep 17 00:00:00 2001 +From: Paul Kocialkowski +Date: Tue, 22 Oct 2019 12:26:53 -0300 +Subject: [PATCH] media: pixfmt: Document the HEVC slice pixel format + +Document the current state of the HEVC slice pixel format. +The format will need to evolve in the future, which is why it is +not part of the public API. + +Signed-off-by: Paul Kocialkowski +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + .../media/uapi/v4l/pixfmt-compressed.rst | 23 +++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/Documentation/media/uapi/v4l/pixfmt-compressed.rst b/Documentation/media/uapi/v4l/pixfmt-compressed.rst +index 55d8d690f22f..561bda112809 100644 +--- a/Documentation/media/uapi/v4l/pixfmt-compressed.rst ++++ b/Documentation/media/uapi/v4l/pixfmt-compressed.rst +@@ -192,6 +192,29 @@ Compressed Formats + If :ref:`VIDIOC_ENUM_FMT` reports ``V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM`` + then the decoder has no requirements since it can parse all the + information from the raw bytestream. ++ * .. _V4L2-PIX-FMT-HEVC-SLICE: ++ ++ - ``V4L2_PIX_FMT_HEVC_SLICE`` ++ - 'S265' ++ - HEVC parsed slice data, as extracted from the HEVC bitstream. ++ This format is adapted for stateless video decoders that implement a ++ HEVC pipeline (using the :ref:`mem2mem` and :ref:`media-request-api`). ++ This pixelformat has two modifiers that must be set at least once ++ through the ``V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE`` ++ and ``V4L2_CID_MPEG_VIDEO_HEVC_START_CODE`` controls. ++ Metadata associated with the frame to decode is required to be passed ++ through the following controls : ++ * ``V4L2_CID_MPEG_VIDEO_HEVC_SPS`` ++ * ``V4L2_CID_MPEG_VIDEO_HEVC_PPS`` ++ * ``V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS`` ++ See the :ref:`associated Codec Control IDs `. ++ Buffers associated with this pixel format must contain the appropriate ++ number of macroblocks to decode a full corresponding frame. ++ ++ .. note:: ++ ++ This format is not yet part of the public kernel API and it ++ is expected to change. + * .. _V4L2-PIX-FMT-FWHT: + + - ``V4L2_PIX_FMT_FWHT`` +-- +2.23.0 + +From b4e33e09e7938513bfaba034731c7e84e73c6a5b Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 26 Oct 2019 09:27:51 +0200 +Subject: [PATCH] media: cedrus: Fix decoding for some H264 videos + +It seems that for some H264 videos at least one bitstream parsing +trigger must be called in order to be decoded correctly. There is no +explanation why this helps, but it was observed that two sample videos +with this fix are now decoded correctly and there is no regression with +others. + +Acked-by: Paul Kocialkowski +Signed-off-by: Jernej Skrabec +Signed-off-by: Hans Verkuil +--- + .../staging/media/sunxi/cedrus/cedrus_h264.c | 30 +++++++++++++++++-- + .../staging/media/sunxi/cedrus/cedrus_regs.h | 3 ++ + 2 files changed, 30 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index cd85668f9c80..db336449c4f2 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -6,6 +6,7 @@ + * Copyright (c) 2018 Bootlin + */ + ++#include + #include + + #include +@@ -289,6 +290,28 @@ static void cedrus_write_pred_weight_table(struct cedrus_ctx *ctx, + } + } + ++/* ++ * It turns out that using VE_H264_VLD_OFFSET to skip bits is not reliable. In ++ * rare cases frame is not decoded correctly. However, setting offset to 0 and ++ * skipping appropriate amount of bits with flush bits trigger always works. ++ */ ++static void cedrus_skip_bits(struct cedrus_dev *dev, int num) ++{ ++ int count = 0; ++ ++ while (count < num) { ++ int tmp = min(num - count, 32); ++ ++ cedrus_write(dev, VE_H264_TRIGGER_TYPE, ++ VE_H264_TRIGGER_TYPE_FLUSH_BITS | ++ VE_H264_TRIGGER_TYPE_N_BITS(tmp)); ++ while (cedrus_read(dev, VE_H264_STATUS) & VE_H264_STATUS_VLD_BUSY) ++ udelay(1); ++ ++ count += tmp; ++ } ++} ++ + static void cedrus_set_params(struct cedrus_ctx *ctx, + struct cedrus_run *run) + { +@@ -299,14 +322,13 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, + struct vb2_buffer *src_buf = &run->src->vb2_buf; + struct cedrus_dev *dev = ctx->dev; + dma_addr_t src_buf_addr; +- u32 offset = slice->header_bit_size; +- u32 len = (slice->size * 8) - offset; ++ u32 len = slice->size * 8; + unsigned int pic_width_in_mbs; + bool mbaff_pic; + u32 reg; + + cedrus_write(dev, VE_H264_VLD_LEN, len); +- cedrus_write(dev, VE_H264_VLD_OFFSET, offset); ++ cedrus_write(dev, VE_H264_VLD_OFFSET, 0); + + src_buf_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0); + cedrus_write(dev, VE_H264_VLD_END, +@@ -325,6 +347,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, + cedrus_write(dev, VE_H264_TRIGGER_TYPE, + VE_H264_TRIGGER_TYPE_INIT_SWDEC); + ++ cedrus_skip_bits(dev, slice->header_bit_size); ++ + if (((pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) && + (slice->slice_type == V4L2_H264_SLICE_TYPE_P || + slice->slice_type == V4L2_H264_SLICE_TYPE_SP)) || +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +index 6fc28d21a6c7..4275a307d282 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +@@ -541,13 +541,16 @@ + VE_H264_CTRL_SLICE_DECODE_INT) + + #define VE_H264_TRIGGER_TYPE 0x224 ++#define VE_H264_TRIGGER_TYPE_N_BITS(x) (((x) & 0x3f) << 8) + #define VE_H264_TRIGGER_TYPE_AVC_SLICE_DECODE (8 << 0) + #define VE_H264_TRIGGER_TYPE_INIT_SWDEC (7 << 0) ++#define VE_H264_TRIGGER_TYPE_FLUSH_BITS (3 << 0) + + #define VE_H264_STATUS 0x228 + #define VE_H264_STATUS_VLD_DATA_REQ_INT VE_H264_CTRL_VLD_DATA_REQ_INT + #define VE_H264_STATUS_DECODE_ERR_INT VE_H264_CTRL_DECODE_ERR_INT + #define VE_H264_STATUS_SLICE_DECODE_INT VE_H264_CTRL_SLICE_DECODE_INT ++#define VE_H264_STATUS_VLD_BUSY BIT(8) + + #define VE_H264_STATUS_INT_MASK VE_H264_CTRL_INT_MASK + +-- +2.24.0 + +From 1d1d982e52956f07221d1229bcc6fbc564121da3 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 26 Oct 2019 09:27:52 +0200 +Subject: [PATCH] media: cedrus: Use helpers to access capture queue + +Accessing capture queue structue directly is not safe. Use helpers for +that. + +Acked-by: Paul Kocialkowski +Signed-off-by: Jernej Skrabec +Signed-off-by: Hans Verkuil +--- + drivers/staging/media/sunxi/cedrus/cedrus.h | 8 ++++++-- + drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 8 ++++++-- + 2 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h +index 986e059e3202..c45fb9a7ad07 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -197,12 +197,16 @@ static inline dma_addr_t cedrus_buf_addr(struct vb2_buffer *buf, + static inline dma_addr_t cedrus_dst_buf_addr(struct cedrus_ctx *ctx, + int index, unsigned int plane) + { +- struct vb2_buffer *buf; ++ struct vb2_buffer *buf = NULL; ++ struct vb2_queue *vq; + + if (index < 0) + return 0; + +- buf = ctx->fh.m2m_ctx->cap_q_ctx.q.bufs[index]; ++ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ if (vq) ++ buf = vb2_get_buffer(vq, index); ++ + return buf ? cedrus_buf_addr(buf, &ctx->dst_fmt, plane) : 0; + } + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index db336449c4f2..7487f6ab7576 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -97,7 +97,7 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, + const struct v4l2_ctrl_h264_decode_params *decode = run->h264.decode_params; + const struct v4l2_ctrl_h264_slice_params *slice = run->h264.slice_params; + const struct v4l2_ctrl_h264_sps *sps = run->h264.sps; +- struct vb2_queue *cap_q = &ctx->fh.m2m_ctx->cap_q_ctx.q; ++ struct vb2_queue *cap_q; + struct cedrus_buffer *output_buf; + struct cedrus_dev *dev = ctx->dev; + unsigned long used_dpbs = 0; +@@ -105,6 +105,8 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, + unsigned int output = 0; + unsigned int i; + ++ cap_q = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ + memset(pic_list, 0, sizeof(pic_list)); + + for (i = 0; i < ARRAY_SIZE(decode->dpb); i++) { +@@ -168,12 +170,14 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx, + enum cedrus_h264_sram_off sram) + { + const struct v4l2_ctrl_h264_decode_params *decode = run->h264.decode_params; +- struct vb2_queue *cap_q = &ctx->fh.m2m_ctx->cap_q_ctx.q; ++ struct vb2_queue *cap_q; + struct cedrus_dev *dev = ctx->dev; + u8 sram_array[CEDRUS_MAX_REF_IDX]; + unsigned int i; + size_t size; + ++ cap_q = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ + memset(sram_array, 0, sizeof(sram_array)); + + for (i = 0; i < num_ref; i++) { +-- +2.24.0 + +From e2c02ba9bd0068b00628d7874d8a8d1eb5168177 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Tue, 29 Oct 2019 00:00:52 +0000 +Subject: [PATCH] media: cedrus: Use correct H264 8x8 scaling list + +Documentation now defines the expected order of scaling lists, +change to use correct indices. + +Fixes: 6eb9b758e307 ("media: cedrus: Add H264 decoding support") +Signed-off-by: Jonas Karlman +Reviewed-by: Philipp Zabel +Signed-off-by: Hans Verkuil +--- + drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index 7487f6ab7576..74e4c5e3894e 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -245,8 +245,8 @@ static void cedrus_write_scaling_lists(struct cedrus_ctx *ctx, + sizeof(scaling->scaling_list_8x8[0])); + + cedrus_h264_write_sram(dev, CEDRUS_SRAM_H264_SCALING_LIST_8x8_1, +- scaling->scaling_list_8x8[3], +- sizeof(scaling->scaling_list_8x8[3])); ++ scaling->scaling_list_8x8[1], ++ sizeof(scaling->scaling_list_8x8[1])); + + cedrus_h264_write_sram(dev, CEDRUS_SRAM_H264_SCALING_LIST_4x4, + scaling->scaling_list_4x4, +-- +2.24.0 + +From 7119ecef4e5ec51e45e6fbe1b5da4385fcae8ded Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Wed, 6 Nov 2019 08:02:53 +0100 +Subject: [PATCH] media: v4l2-mem2mem: Fix hold buf flag checks + +Hold buf flag is set on output queue, not capture. Fix that. + +Fixes: f07602ac3887 ("media: v4l2-mem2mem: add new_frame detection") +Signed-off-by: Jernej Skrabec +Signed-off-by: Hans Verkuil +--- + drivers/media/v4l2-core/v4l2-mem2mem.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c +index db07ef3bf3d0..1afd9c6ad908 100644 +--- a/drivers/media/v4l2-core/v4l2-mem2mem.c ++++ b/drivers/media/v4l2-core/v4l2-mem2mem.c +@@ -335,7 +335,7 @@ static void __v4l2_m2m_try_queue(struct v4l2_m2m_dev *m2m_dev, + } + } + +- if (src && dst && (m2m_ctx->cap_q_ctx.q.subsystem_flags & ++ if (src && dst && (m2m_ctx->out_q_ctx.q.subsystem_flags & + VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF)) + m2m_ctx->new_frame = !dst->vb2_buf.copied_timestamp || + dst->vb2_buf.timestamp != src->vb2_buf.timestamp; +@@ -474,7 +474,7 @@ void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev, + * holding capture buffers. Those should use + * v4l2_m2m_buf_done_and_job_finish() instead. + */ +- WARN_ON(m2m_ctx->cap_q_ctx.q.subsystem_flags & ++ WARN_ON(m2m_ctx->out_q_ctx.q.subsystem_flags & + VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF); + spin_lock_irqsave(&m2m_dev->job_spinlock, flags); + schedule_next = _v4l2_m2m_job_finish(m2m_dev, m2m_ctx); +-- +2.24.0 + +From 3aef46bd5bf24a845e05d2531ed61f53ee8c7797 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sun, 10 Nov 2019 07:30:01 +0100 +Subject: [PATCH 1/3] media: cedrus: Properly signal size in mode register + +Mode register also holds information if video width is bigger than 2048 +and if it is equal to 4096. + +Rework cedrus_engine_enable() to properly signal this properties. + +Signed-off-by: Jernej Skrabec +Acked-by: Paul Kocialkowski +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 2 +- + drivers/staging/media/sunxi/cedrus/cedrus_h265.c | 2 +- + drivers/staging/media/sunxi/cedrus/cedrus_hw.c | 9 +++++++-- + drivers/staging/media/sunxi/cedrus/cedrus_hw.h | 2 +- + drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c | 2 +- + drivers/staging/media/sunxi/cedrus/cedrus_regs.h | 2 ++ + 6 files changed, 13 insertions(+), 6 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index 74e4c5e3894e..8a09a08b1af2 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -485,7 +485,7 @@ static void cedrus_h264_setup(struct cedrus_ctx *ctx, + { + struct cedrus_dev *dev = ctx->dev; + +- cedrus_engine_enable(dev, CEDRUS_CODEC_H264); ++ cedrus_engine_enable(ctx, CEDRUS_CODEC_H264); + + cedrus_write(dev, VE_H264_SDROT_CTRL, 0); + cedrus_write(dev, VE_H264_EXTRA_BUFFER1, +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +index 9bc921866f70..6945dc74e1d7 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -276,7 +276,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + } + + /* Activate H265 engine. */ +- cedrus_engine_enable(dev, CEDRUS_CODEC_H265); ++ cedrus_engine_enable(ctx, CEDRUS_CODEC_H265); + + /* Source offset and length in bits. */ + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c +index 93347d3ba360..daf5f244f93b 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c +@@ -30,7 +30,7 @@ + #include "cedrus_hw.h" + #include "cedrus_regs.h" + +-int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec) ++int cedrus_engine_enable(struct cedrus_ctx *ctx, enum cedrus_codec codec) + { + u32 reg = 0; + +@@ -58,7 +58,12 @@ int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec) + return -EINVAL; + } + +- cedrus_write(dev, VE_MODE, reg); ++ if (ctx->src_fmt.width == 4096) ++ reg |= VE_MODE_PIC_WIDTH_IS_4096; ++ if (ctx->src_fmt.width > 2048) ++ reg |= VE_MODE_PIC_WIDTH_MORE_2048; ++ ++ cedrus_write(ctx->dev, VE_MODE, reg); + + return 0; + } +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h +index 27d0882397aa..604ff932fbf5 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h +@@ -16,7 +16,7 @@ + #ifndef _CEDRUS_HW_H_ + #define _CEDRUS_HW_H_ + +-int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec); ++int cedrus_engine_enable(struct cedrus_ctx *ctx, enum cedrus_codec codec); + void cedrus_engine_disable(struct cedrus_dev *dev); + + void cedrus_dst_format_set(struct cedrus_dev *dev, +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c b/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c +index 13c34927bad5..8bcd6b8f9e2d 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c +@@ -96,7 +96,7 @@ static void cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) + quantization = run->mpeg2.quantization; + + /* Activate MPEG engine. */ +- cedrus_engine_enable(dev, CEDRUS_CODEC_MPEG2); ++ cedrus_engine_enable(ctx, CEDRUS_CODEC_MPEG2); + + /* Set intra quantization matrix. */ + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +index 4275a307d282..ace3d49fcd82 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +@@ -35,6 +35,8 @@ + + #define VE_MODE 0x00 + ++#define VE_MODE_PIC_WIDTH_IS_4096 BIT(22) ++#define VE_MODE_PIC_WIDTH_MORE_2048 BIT(21) + #define VE_MODE_REC_WR_MODE_2MB (0x01 << 20) + #define VE_MODE_REC_WR_MODE_1MB (0x00 << 20) + #define VE_MODE_DDR_MODE_BW_128 (0x03 << 16) +-- +2.24.0 + + +From 03e612e701a61aa9cc9fd8e25cd47d8d685ef675 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Wed, 6 Nov 2019 22:05:37 +0100 +Subject: [PATCH 2/3] media: cedrus: Fix H264 4k support + +H264 decoder needs additional or bigger buffers in order to decode 4k +videos. + +Signed-off-by: Jernej Skrabec +Acked-by: Paul Kocialkowski +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/staging/media/sunxi/cedrus/cedrus.h | 7 ++ + .../staging/media/sunxi/cedrus/cedrus_h264.c | 91 +++++++++++++++++-- + .../staging/media/sunxi/cedrus/cedrus_regs.h | 11 +++ + 3 files changed, 101 insertions(+), 8 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h +index c45fb9a7ad07..96765555ab8a 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -116,8 +116,15 @@ struct cedrus_ctx { + ssize_t mv_col_buf_size; + void *pic_info_buf; + dma_addr_t pic_info_buf_dma; ++ ssize_t pic_info_buf_size; + void *neighbor_info_buf; + dma_addr_t neighbor_info_buf_dma; ++ void *deblk_buf; ++ dma_addr_t deblk_buf_dma; ++ ssize_t deblk_buf_size; ++ void *intra_pred_buf; ++ dma_addr_t intra_pred_buf_dma; ++ ssize_t intra_pred_buf_size; + } h264; + struct { + void *mv_col_buf; +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index 8a09a08b1af2..bfb4a4820a67 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -39,7 +39,7 @@ struct cedrus_h264_sram_ref_pic { + #define CEDRUS_H264_FRAME_NUM 18 + + #define CEDRUS_NEIGHBOR_INFO_BUF_SIZE (16 * SZ_1K) +-#define CEDRUS_PIC_INFO_BUF_SIZE (128 * SZ_1K) ++#define CEDRUS_MIN_PIC_INFO_BUF_SIZE (130 * SZ_1K) + + static void cedrus_h264_write_sram(struct cedrus_dev *dev, + enum cedrus_h264_sram_off off, +@@ -342,6 +342,20 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, + VE_H264_VLD_ADDR_FIRST | VE_H264_VLD_ADDR_VALID | + VE_H264_VLD_ADDR_LAST); + ++ if (ctx->src_fmt.width > 2048) { ++ cedrus_write(dev, VE_BUF_CTRL, ++ VE_BUF_CTRL_INTRAPRED_MIXED_RAM | ++ VE_BUF_CTRL_DBLK_MIXED_RAM); ++ cedrus_write(dev, VE_DBLK_DRAM_BUF_ADDR, ++ ctx->codec.h264.deblk_buf_dma); ++ cedrus_write(dev, VE_INTRAPRED_DRAM_BUF_ADDR, ++ ctx->codec.h264.intra_pred_buf_dma); ++ } else { ++ cedrus_write(dev, VE_BUF_CTRL, ++ VE_BUF_CTRL_INTRAPRED_INT_SRAM | ++ VE_BUF_CTRL_DBLK_INT_SRAM); ++ } ++ + /* + * FIXME: Since the bitstream parsing is done in software, and + * in userspace, this shouldn't be needed anymore. But it +@@ -502,18 +516,30 @@ static void cedrus_h264_setup(struct cedrus_ctx *ctx, + static int cedrus_h264_start(struct cedrus_ctx *ctx) + { + struct cedrus_dev *dev = ctx->dev; ++ unsigned int pic_info_size; + unsigned int field_size; + unsigned int mv_col_size; + int ret; + ++ /* Formula for picture buffer size is taken from CedarX source. */ ++ ++ if (ctx->src_fmt.width > 2048) ++ pic_info_size = CEDRUS_H264_FRAME_NUM * 0x4000; ++ else ++ pic_info_size = CEDRUS_H264_FRAME_NUM * 0x1000; ++ + /* +- * FIXME: It seems that the H6 cedarX code is using a formula +- * here based on the size of the frame, while all the older +- * code is using a fixed size, so that might need to be +- * changed at some point. ++ * FIXME: If V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY is set, ++ * there is no need to multiply by 2. + */ ++ pic_info_size += ctx->src_fmt.height * 2 * 64; ++ ++ if (pic_info_size < CEDRUS_MIN_PIC_INFO_BUF_SIZE) ++ pic_info_size = CEDRUS_MIN_PIC_INFO_BUF_SIZE; ++ ++ ctx->codec.h264.pic_info_buf_size = pic_info_size; + ctx->codec.h264.pic_info_buf = +- dma_alloc_coherent(dev->dev, CEDRUS_PIC_INFO_BUF_SIZE, ++ dma_alloc_coherent(dev->dev, ctx->codec.h264.pic_info_buf_size, + &ctx->codec.h264.pic_info_buf_dma, + GFP_KERNEL); + if (!ctx->codec.h264.pic_info_buf) +@@ -566,15 +592,56 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx) + goto err_neighbor_buf; + } + ++ if (ctx->src_fmt.width > 2048) { ++ /* ++ * Formulas for deblock and intra prediction buffer sizes ++ * are taken from CedarX source. ++ */ ++ ++ ctx->codec.h264.deblk_buf_size = ++ ALIGN(ctx->src_fmt.width, 32) * 12; ++ ctx->codec.h264.deblk_buf = ++ dma_alloc_coherent(dev->dev, ++ ctx->codec.h264.deblk_buf_size, ++ &ctx->codec.h264.deblk_buf_dma, ++ GFP_KERNEL); ++ if (!ctx->codec.h264.deblk_buf) { ++ ret = -ENOMEM; ++ goto err_mv_col_buf; ++ } ++ ++ ctx->codec.h264.intra_pred_buf_size = ++ ALIGN(ctx->src_fmt.width, 64) * 5; ++ ctx->codec.h264.intra_pred_buf = ++ dma_alloc_coherent(dev->dev, ++ ctx->codec.h264.intra_pred_buf_size, ++ &ctx->codec.h264.intra_pred_buf_dma, ++ GFP_KERNEL); ++ if (!ctx->codec.h264.intra_pred_buf) { ++ ret = -ENOMEM; ++ goto err_deblk_buf; ++ } ++ } ++ + return 0; + ++err_deblk_buf: ++ dma_free_coherent(dev->dev, ctx->codec.h264.deblk_buf_size, ++ ctx->codec.h264.deblk_buf, ++ ctx->codec.h264.deblk_buf_dma); ++ ++err_mv_col_buf: ++ dma_free_coherent(dev->dev, ctx->codec.h264.mv_col_buf_size, ++ ctx->codec.h264.mv_col_buf, ++ ctx->codec.h264.mv_col_buf_dma); ++ + err_neighbor_buf: + dma_free_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE, + ctx->codec.h264.neighbor_info_buf, + ctx->codec.h264.neighbor_info_buf_dma); + + err_pic_buf: +- dma_free_coherent(dev->dev, CEDRUS_PIC_INFO_BUF_SIZE, ++ dma_free_coherent(dev->dev, ctx->codec.h264.pic_info_buf_size, + ctx->codec.h264.pic_info_buf, + ctx->codec.h264.pic_info_buf_dma); + return ret; +@@ -590,9 +657,17 @@ static void cedrus_h264_stop(struct cedrus_ctx *ctx) + dma_free_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE, + ctx->codec.h264.neighbor_info_buf, + ctx->codec.h264.neighbor_info_buf_dma); +- dma_free_coherent(dev->dev, CEDRUS_PIC_INFO_BUF_SIZE, ++ dma_free_coherent(dev->dev, ctx->codec.h264.pic_info_buf_size, + ctx->codec.h264.pic_info_buf, + ctx->codec.h264.pic_info_buf_dma); ++ if (ctx->codec.h264.deblk_buf_size) ++ dma_free_coherent(dev->dev, ctx->codec.h264.deblk_buf_size, ++ ctx->codec.h264.deblk_buf, ++ ctx->codec.h264.deblk_buf_dma); ++ if (ctx->codec.h264.intra_pred_buf_size) ++ dma_free_coherent(dev->dev, ctx->codec.h264.intra_pred_buf_size, ++ ctx->codec.h264.intra_pred_buf, ++ ctx->codec.h264.intra_pred_buf_dma); + } + + static void cedrus_h264_trigger(struct cedrus_ctx *ctx) +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +index ace3d49fcd82..7beb03d3bb39 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +@@ -46,6 +46,17 @@ + #define VE_MODE_DEC_H264 (0x01 << 0) + #define VE_MODE_DEC_MPEG (0x00 << 0) + ++#define VE_BUF_CTRL 0x50 ++ ++#define VE_BUF_CTRL_INTRAPRED_EXT_RAM (0x02 << 2) ++#define VE_BUF_CTRL_INTRAPRED_MIXED_RAM (0x01 << 2) ++#define VE_BUF_CTRL_INTRAPRED_INT_SRAM (0x00 << 2) ++#define VE_BUF_CTRL_DBLK_EXT_RAM (0x02 << 0) ++#define VE_BUF_CTRL_DBLK_MIXED_RAM (0x01 << 0) ++#define VE_BUF_CTRL_DBLK_INT_SRAM (0x00 << 0) ++ ++#define VE_DBLK_DRAM_BUF_ADDR 0x54 ++#define VE_INTRAPRED_DRAM_BUF_ADDR 0x58 + #define VE_PRIMARY_CHROMA_BUF_LEN 0xc4 + #define VE_PRIMARY_FB_LINE_STRIDE 0xc8 + +-- +2.24.0 + + +From 0b3e5c15f9cb8b56599c50e6bf4f46ee1c1253bc Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Wed, 6 Nov 2019 22:05:38 +0100 +Subject: [PATCH 3/3] media: cedrus: Increase maximum supported size + +There are few variations of 4k resolutions. The biggest one is +4096x2304 which is also supported by HW. It has also nice property that +both width and size are divisible by maximum HEVC CTB size, which is 64. + +Signed-off-by: Jernej Skrabec +Acked-by: Paul Kocialkowski +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/staging/media/sunxi/cedrus/cedrus_video.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +index cc15a5cf107d..15cf1f10221b 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +@@ -29,8 +29,8 @@ + + #define CEDRUS_MIN_WIDTH 16U + #define CEDRUS_MIN_HEIGHT 16U +-#define CEDRUS_MAX_WIDTH 3840U +-#define CEDRUS_MAX_HEIGHT 2160U ++#define CEDRUS_MAX_WIDTH 4096U ++#define CEDRUS_MAX_HEIGHT 2304U + + static struct cedrus_format cedrus_formats[] = { + { +-- +2.24.0 + diff --git a/projects/Allwinner/patches/linux/0005-cedrus-hevc.patch b/projects/Allwinner/patches/linux/0005-cedrus-hevc.patch deleted file mode 100644 index 81b6cc843fe..00000000000 --- a/projects/Allwinner/patches/linux/0005-cedrus-hevc.patch +++ /dev/null @@ -1,2021 +0,0 @@ -From 2a7c76208e46bd164d7e968d063d870fcb1e9314 Mon Sep 17 00:00:00 2001 -From: Paul Kocialkowski -Date: Fri, 24 May 2019 11:36:32 +0200 -Subject: [PATCH 09/12] media: v4l: Add definitions for the HEVC slice controls - -This introduces the required definitions for HEVC decoding support with -stateless VPUs. The controls associated to the HEVC slice format provide -the required meta-data for decoding slices extracted from the bitstream. - -They are not exported to the public V4L2 API since reworking this API -will be needed for covering various use-cases and new hardware. - -The interface comes with the following limitations: -* No custom quantization matrices (scaling lists); -* Support for a single temporal layer only; -* No slice entry point offsets support; -* No conformance window support; -* No VUI parameters support; -* No support for SPS extensions: range, multilayer, 3d, scc, 4 bits; -* No support for PPS extensions: range, multilayer, 3d, scc, 4 bits. - -Signed-off-by: Hans Verkuil ---- - Documentation/media/uapi/v4l/biblio.rst | 9 + - .../media/uapi/v4l/ext-ctrls-codec.rst | 429 +++++++++++++++++- - .../media/uapi/v4l/vidioc-queryctrl.rst | 18 + - .../media/videodev2.h.rst.exceptions | 3 + - drivers/media/v4l2-core/v4l2-ctrls.c | 26 ++ - drivers/media/v4l2-core/v4l2-ioctl.c | 1 + - include/media/hevc-ctrls.h | 182 ++++++++ - include/media/v4l2-ctrls.h | 7 + - 8 files changed, 672 insertions(+), 3 deletions(-) - create mode 100644 include/media/hevc-ctrls.h - -diff --git a/Documentation/media/uapi/v4l/biblio.rst b/Documentation/media/uapi/v4l/biblio.rst -index 8f4eb8823d82..e38ef5ee4209 100644 ---- a/Documentation/media/uapi/v4l/biblio.rst -+++ b/Documentation/media/uapi/v4l/biblio.rst -@@ -131,6 +131,15 @@ ITU-T Rec. H.264 Specification (04/2017 Edition) - - :author: International Telecommunication Union (http://www.itu.ch) - -+.. _hevc: -+ -+ITU H.265/HEVC -+============== -+ -+:title: ITU-T Rec. H.265 | ISO/IEC 23008-2 "High Efficiency Video Coding" -+ -+:author: International Telecommunication Union (http://www.itu.ch), International Organisation for Standardisation (http://www.iso.ch) -+ - .. _jfif: - - JFIF -diff --git a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst -index b0c178f0ff9b..19e5bfba888b 100644 ---- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst -+++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst -@@ -1981,9 +1981,9 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - - - ``reference_ts`` - - Timestamp of the V4L2 capture buffer to use as reference, used - with B-coded and P-coded frames. The timestamp refers to the -- ``timestamp`` field in struct :c:type:`v4l2_buffer`. Use the -- :c:func:`v4l2_timeval_to_ns()` function to convert the struct -- :c:type:`timeval` in struct :c:type:`v4l2_buffer` to a __u64. -+ ``timestamp`` field in struct :c:type:`v4l2_buffer`. Use the -+ :c:func:`v4l2_timeval_to_ns()` function to convert the struct -+ :c:type:`timeval` in struct :c:type:`v4l2_buffer` to a __u64. - * - __u16 - - ``frame_num`` - - -@@ -3291,3 +3291,426 @@ enum v4l2_mpeg_video_hevc_size_of_length_field - - Indicates whether to generate SPS and PPS at every IDR. Setting it to 0 - disables generating SPS and PPS at every IDR. Setting it to one enables - generating SPS and PPS at every IDR. -+ -+.. _v4l2-mpeg-hevc: -+ -+``V4L2_CID_MPEG_VIDEO_HEVC_SPS (struct)`` -+ Specifies the Sequence Parameter Set fields (as extracted from the -+ bitstream) for the associated HEVC slice data. -+ These bitstream parameters are defined according to :ref:`hevc`. -+ They are described in section 7.4.3.2 "Sequence parameter set RBSP -+ semantics" of the specification. -+ -+.. c:type:: v4l2_ctrl_hevc_sps -+ -+.. cssclass:: longtable -+ -+.. flat-table:: struct v4l2_ctrl_hevc_sps -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 1 2 -+ -+ * - __u8 -+ - ``chroma_format_idc`` -+ - -+ * - __u8 -+ - ``separate_colour_plane_flag`` -+ - -+ * - __u16 -+ - ``pic_width_in_luma_samples`` -+ - -+ * - __u16 -+ - ``pic_height_in_luma_samples`` -+ - -+ * - __u8 -+ - ``bit_depth_luma_minus8`` -+ - -+ * - __u8 -+ - ``bit_depth_chroma_minus8`` -+ - -+ * - __u8 -+ - ``log2_max_pic_order_cnt_lsb_minus4`` -+ - -+ * - __u8 -+ - ``sps_max_dec_pic_buffering_minus1`` -+ - -+ * - __u8 -+ - ``sps_max_num_reorder_pics`` -+ - -+ * - __u8 -+ - ``sps_max_latency_increase_plus1`` -+ - -+ * - __u8 -+ - ``log2_min_luma_coding_block_size_minus3`` -+ - -+ * - __u8 -+ - ``log2_diff_max_min_luma_coding_block_size`` -+ - -+ * - __u8 -+ - ``log2_min_luma_transform_block_size_minus2`` -+ - -+ * - __u8 -+ - ``log2_diff_max_min_luma_transform_block_size`` -+ - -+ * - __u8 -+ - ``max_transform_hierarchy_depth_inter`` -+ - -+ * - __u8 -+ - ``max_transform_hierarchy_depth_intra`` -+ - -+ * - __u8 -+ - ``scaling_list_enabled_flag`` -+ - -+ * - __u8 -+ - ``amp_enabled_flag`` -+ - -+ * - __u8 -+ - ``sample_adaptive_offset_enabled_flag`` -+ - -+ * - __u8 -+ - ``pcm_enabled_flag`` -+ - -+ * - __u8 -+ - ``pcm_sample_bit_depth_luma_minus1`` -+ - -+ * - __u8 -+ - ``pcm_sample_bit_depth_chroma_minus1`` -+ - -+ * - __u8 -+ - ``log2_min_pcm_luma_coding_block_size_minus3`` -+ - -+ * - __u8 -+ - ``log2_diff_max_min_pcm_luma_coding_block_size`` -+ - -+ * - __u8 -+ - ``pcm_loop_filter_disabled_flag`` -+ - -+ * - __u8 -+ - ``num_short_term_ref_pic_sets`` -+ - -+ * - __u8 -+ - ``long_term_ref_pics_present_flag`` -+ - -+ * - __u8 -+ - ``num_long_term_ref_pics_sps`` -+ - -+ * - __u8 -+ - ``sps_temporal_mvp_enabled_flag`` -+ - -+ * - __u8 -+ - ``strong_intra_smoothing_enabled_flag`` -+ - -+ -+``V4L2_CID_MPEG_VIDEO_HEVC_PPS (struct)`` -+ Specifies the Picture Parameter Set fields (as extracted from the -+ bitstream) for the associated HEVC slice data. -+ These bitstream parameters are defined according to :ref:`hevc`. -+ They are described in section 7.4.3.3 "Picture parameter set RBSP -+ semantics" of the specification. -+ -+.. c:type:: v4l2_ctrl_hevc_pps -+ -+.. cssclass:: longtable -+ -+.. flat-table:: struct v4l2_ctrl_hevc_pps -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 1 2 -+ -+ * - __u8 -+ - ``dependent_slice_segment_flag`` -+ - -+ * - __u8 -+ - ``output_flag_present_flag`` -+ - -+ * - __u8 -+ - ``num_extra_slice_header_bits`` -+ - -+ * - __u8 -+ - ``sign_data_hiding_enabled_flag`` -+ - -+ * - __u8 -+ - ``cabac_init_present_flag`` -+ - -+ * - __s8 -+ - ``init_qp_minus26`` -+ - -+ * - __u8 -+ - ``constrained_intra_pred_flag`` -+ - -+ * - __u8 -+ - ``transform_skip_enabled_flag`` -+ - -+ * - __u8 -+ - ``cu_qp_delta_enabled_flag`` -+ - -+ * - __u8 -+ - ``diff_cu_qp_delta_depth`` -+ - -+ * - __s8 -+ - ``pps_cb_qp_offset`` -+ - -+ * - __s8 -+ - ``pps_cr_qp_offset`` -+ - -+ * - __u8 -+ - ``pps_slice_chroma_qp_offsets_present_flag`` -+ - -+ * - __u8 -+ - ``weighted_pred_flag`` -+ - -+ * - __u8 -+ - ``weighted_bipred_flag`` -+ - -+ * - __u8 -+ - ``transquant_bypass_enabled_flag`` -+ - -+ * - __u8 -+ - ``tiles_enabled_flag`` -+ - -+ * - __u8 -+ - ``entropy_coding_sync_enabled_flag`` -+ - -+ * - __u8 -+ - ``num_tile_columns_minus1`` -+ - -+ * - __u8 -+ - ``num_tile_rows_minus1`` -+ - -+ * - __u8 -+ - ``column_width_minus1[20]`` -+ - -+ * - __u8 -+ - ``row_height_minus1[22]`` -+ - -+ * - __u8 -+ - ``loop_filter_across_tiles_enabled_flag`` -+ - -+ * - __u8 -+ - ``pps_loop_filter_across_slices_enabled_flag`` -+ - -+ * - __u8 -+ - ``deblocking_filter_override_enabled_flag`` -+ - -+ * - __u8 -+ - ``pps_disable_deblocking_filter_flag`` -+ - -+ * - __s8 -+ - ``pps_beta_offset_div2`` -+ - -+ * - __s8 -+ - ``pps_tc_offset_div2`` -+ - -+ * - __u8 -+ - ``lists_modification_present_flag`` -+ - -+ * - __u8 -+ - ``log2_parallel_merge_level_minus2`` -+ - -+ * - __u8 -+ - ``slice_segment_header_extension_present_flag`` -+ - -+ -+``V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (struct)`` -+ Specifies various slice-specific parameters, especially from the NAL unit -+ header, general slice segment header and weighted prediction parameter -+ parts of the bitstream. -+ These bitstream parameters are defined according to :ref:`hevc`. -+ They are described in section 7.4.7 "General slice segment header -+ semantics" of the specification. -+ -+.. c:type:: v4l2_ctrl_hevc_slice_params -+ -+.. cssclass:: longtable -+ -+.. flat-table:: struct v4l2_ctrl_hevc_slice_params -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 1 2 -+ -+ * - __u32 -+ - ``bit_size`` -+ - Size (in bits) of the current slice data. -+ * - __u32 -+ - ``data_bit_offset`` -+ - Offset (in bits) to the video data in the current slice data. -+ * - __u8 -+ - ``nal_unit_type`` -+ - -+ * - __u8 -+ - ``nuh_temporal_id_plus1`` -+ - -+ * - __u8 -+ - ``slice_type`` -+ - -+ (V4L2_HEVC_SLICE_TYPE_I, V4L2_HEVC_SLICE_TYPE_P or -+ V4L2_HEVC_SLICE_TYPE_B). -+ * - __u8 -+ - ``colour_plane_id`` -+ - -+ * - __u16 -+ - ``slice_pic_order_cnt`` -+ - -+ * - __u8 -+ - ``slice_sao_luma_flag`` -+ - -+ * - __u8 -+ - ``slice_sao_chroma_flag`` -+ - -+ * - __u8 -+ - ``slice_temporal_mvp_enabled_flag`` -+ - -+ * - __u8 -+ - ``num_ref_idx_l0_active_minus1`` -+ - -+ * - __u8 -+ - ``num_ref_idx_l1_active_minus1`` -+ - -+ * - __u8 -+ - ``mvd_l1_zero_flag`` -+ - -+ * - __u8 -+ - ``cabac_init_flag`` -+ - -+ * - __u8 -+ - ``collocated_from_l0_flag`` -+ - -+ * - __u8 -+ - ``collocated_ref_idx`` -+ - -+ * - __u8 -+ - ``five_minus_max_num_merge_cand`` -+ - -+ * - __u8 -+ - ``use_integer_mv_flag`` -+ - -+ * - __s8 -+ - ``slice_qp_delta`` -+ - -+ * - __s8 -+ - ``slice_cb_qp_offset`` -+ - -+ * - __s8 -+ - ``slice_cr_qp_offset`` -+ - -+ * - __s8 -+ - ``slice_act_y_qp_offset`` -+ - -+ * - __s8 -+ - ``slice_act_cb_qp_offset`` -+ - -+ * - __s8 -+ - ``slice_act_cr_qp_offset`` -+ - -+ * - __u8 -+ - ``slice_deblocking_filter_disabled_flag`` -+ - -+ * - __s8 -+ - ``slice_beta_offset_div2`` -+ - -+ * - __s8 -+ - ``slice_tc_offset_div2`` -+ - -+ * - __u8 -+ - ``slice_loop_filter_across_slices_enabled_flag`` -+ - -+ * - __u8 -+ - ``pic_struct`` -+ - -+ * - struct :c:type:`v4l2_hevc_dpb_entry` -+ - ``dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` -+ - The decoded picture buffer, for meta-data about reference frames. -+ * - __u8 -+ - ``num_active_dpb_entries`` -+ - The number of entries in ``dpb``. -+ * - __u8 -+ - ``ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` -+ - The list of L0 reference elements as indices in the DPB. -+ * - __u8 -+ - ``ref_idx_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` -+ - The list of L1 reference elements as indices in the DPB. -+ * - __u8 -+ - ``num_rps_poc_st_curr_before`` -+ - The number of reference pictures in the short-term set that come before -+ the current frame. -+ * - __u8 -+ - ``num_rps_poc_st_curr_after`` -+ - The number of reference pictures in the short-term set that come after -+ the current frame. -+ * - __u8 -+ - ``num_rps_poc_lt_curr`` -+ - The number of reference pictures in the long-term set. -+ * - struct :c:type:`v4l2_hevc_pred_weight_table` -+ - ``pred_weight_table`` -+ - The prediction weight coefficients for inter-picture prediction. -+ -+.. c:type:: v4l2_hevc_dpb_entry -+ -+.. cssclass:: longtable -+ -+.. flat-table:: struct v4l2_hevc_dpb_entry -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 1 2 -+ -+ * - __u64 -+ - ``timestamp`` -+ - Timestamp of the V4L2 capture buffer to use as reference, used -+ with B-coded and P-coded frames. The timestamp refers to the -+ ``timestamp`` field in struct :c:type:`v4l2_buffer`. Use the -+ :c:func:`v4l2_timeval_to_ns()` function to convert the struct -+ :c:type:`timeval` in struct :c:type:`v4l2_buffer` to a __u64. -+ * - __u8 -+ - ``rps`` -+ - The reference set for the reference frame -+ (V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE, -+ V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_AFTER or -+ V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR) -+ * - __u8 -+ - ``field_pic`` -+ - Whether the reference is a field picture or a frame. -+ * - __u16 -+ - ``pic_order_cnt[2]`` -+ - The picture order count of the reference. Only the first element of the -+ array is used for frame pictures, while the first element identifies the -+ top field and the second the bottom field in field-coded pictures. -+ -+.. c:type:: v4l2_hevc_pred_weight_table -+ -+.. cssclass:: longtable -+ -+.. flat-table:: struct v4l2_hevc_pred_weight_table -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 1 1 2 -+ -+ * - __u8 -+ - ``luma_log2_weight_denom`` -+ - -+ * - __s8 -+ - ``delta_chroma_log2_weight_denom`` -+ - -+ * - __s8 -+ - ``delta_luma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` -+ - -+ * - __s8 -+ - ``luma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` -+ - -+ * - __s8 -+ - ``delta_chroma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]`` -+ - -+ * - __s8 -+ - ``chroma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]`` -+ - -+ * - __s8 -+ - ``delta_luma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` -+ - -+ * - __s8 -+ - ``luma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` -+ - -+ * - __s8 -+ - ``delta_chroma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]`` -+ - -+ * - __s8 -+ - ``chroma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]`` -+ - -diff --git a/Documentation/media/uapi/v4l/vidioc-queryctrl.rst b/Documentation/media/uapi/v4l/vidioc-queryctrl.rst -index dc500632095d..e090ef33231c 100644 ---- a/Documentation/media/uapi/v4l/vidioc-queryctrl.rst -+++ b/Documentation/media/uapi/v4l/vidioc-queryctrl.rst -@@ -473,6 +473,24 @@ See also the examples in :ref:`control`. - - n/a - - A struct :c:type:`v4l2_ctrl_h264_decode_params`, containing H264 - decode parameters for stateless video decoders. -+ * - ``V4L2_CTRL_TYPE_HEVC_SPS`` -+ - n/a -+ - n/a -+ - n/a -+ - A struct :c:type:`v4l2_ctrl_hevc_sps`, containing HEVC Sequence -+ Parameter Set for stateless video decoders. -+ * - ``V4L2_CTRL_TYPE_HEVC_PPS`` -+ - n/a -+ - n/a -+ - n/a -+ - A struct :c:type:`v4l2_ctrl_hevc_pps`, containing HEVC Picture -+ Parameter Set for stateless video decoders. -+ * - ``V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS`` -+ - n/a -+ - n/a -+ - n/a -+ - A struct :c:type:`v4l2_ctrl_hevc_slice_params`, containing HEVC -+ slice parameters for stateless video decoders. - - .. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.7cm}| - -diff --git a/Documentation/media/videodev2.h.rst.exceptions b/Documentation/media/videodev2.h.rst.exceptions -index 55cbe324b9fc..afba7d71971a 100644 ---- a/Documentation/media/videodev2.h.rst.exceptions -+++ b/Documentation/media/videodev2.h.rst.exceptions -@@ -141,6 +141,9 @@ replace symbol V4L2_CTRL_TYPE_H264_PPS :c:type:`v4l2_ctrl_type` - replace symbol V4L2_CTRL_TYPE_H264_SCALING_MATRIX :c:type:`v4l2_ctrl_type` - replace symbol V4L2_CTRL_TYPE_H264_SLICE_PARAMS :c:type:`v4l2_ctrl_type` - replace symbol V4L2_CTRL_TYPE_H264_DECODE_PARAMS :c:type:`v4l2_ctrl_type` -+replace symbol V4L2_CTRL_TYPE_HEVC_SPS :c:type:`v4l2_ctrl_type` -+replace symbol V4L2_CTRL_TYPE_HEVC_PPS :c:type:`v4l2_ctrl_type` -+replace symbol V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS :c:type:`v4l2_ctrl_type` - - # V4L2 capability defines - replace define V4L2_CAP_VIDEO_CAPTURE device-capabilities -diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c -index b72dc54ba638..d93717697402 100644 ---- a/drivers/media/v4l2-core/v4l2-ctrls.c -+++ b/drivers/media/v4l2-core/v4l2-ctrls.c -@@ -944,6 +944,9 @@ const char *v4l2_ctrl_get_name(u32 id) - case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD: return "HEVC Size of Length Field"; - case V4L2_CID_MPEG_VIDEO_REF_NUMBER_FOR_PFRAMES: return "Reference Frames for a P-Frame"; - case V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR: return "Prepend SPS and PPS to IDR"; -+ case V4L2_CID_MPEG_VIDEO_HEVC_SPS: return "HEVC Sequence Parameter Set"; -+ case V4L2_CID_MPEG_VIDEO_HEVC_PPS: return "HEVC Picture Parameter Set"; -+ case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: return "HEVC Slice Parameters"; - - /* CAMERA controls */ - /* Keep the order of the 'case's the same as in v4l2-controls.h! */ -@@ -1357,6 +1360,15 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, - case V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS: - *type = V4L2_CTRL_TYPE_H264_DECODE_PARAMS; - break; -+ case V4L2_CID_MPEG_VIDEO_HEVC_SPS: -+ *type = V4L2_CTRL_TYPE_HEVC_SPS; -+ break; -+ case V4L2_CID_MPEG_VIDEO_HEVC_PPS: -+ *type = V4L2_CTRL_TYPE_HEVC_PPS; -+ break; -+ case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: -+ *type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS; -+ break; - default: - *type = V4L2_CTRL_TYPE_INTEGER; - break; -@@ -1733,6 +1745,11 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx, - case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: - return 0; - -+ case V4L2_CTRL_TYPE_HEVC_SPS: -+ case V4L2_CTRL_TYPE_HEVC_PPS: -+ case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: -+ return 0; -+ - default: - return -EINVAL; - } -@@ -2331,6 +2348,15 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, - case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: - elem_size = sizeof(struct v4l2_ctrl_h264_decode_params); - break; -+ case V4L2_CTRL_TYPE_HEVC_SPS: -+ elem_size = sizeof(struct v4l2_ctrl_hevc_sps); -+ break; -+ case V4L2_CTRL_TYPE_HEVC_PPS: -+ elem_size = sizeof(struct v4l2_ctrl_hevc_pps); -+ break; -+ case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: -+ elem_size = sizeof(struct v4l2_ctrl_hevc_slice_params); -+ break; - default: - if (type < V4L2_CTRL_COMPOUND_TYPES) - elem_size = sizeof(s32); -diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c -index f6e1254064d2..0960f719da5d 100644 ---- a/drivers/media/v4l2-core/v4l2-ioctl.c -+++ b/drivers/media/v4l2-core/v4l2-ioctl.c -@@ -1337,6 +1337,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) - case V4L2_PIX_FMT_VP8: descr = "VP8"; break; - case V4L2_PIX_FMT_VP9: descr = "VP9"; break; - case V4L2_PIX_FMT_HEVC: descr = "HEVC"; break; /* aka H.265 */ -+ case V4L2_PIX_FMT_HEVC_SLICE: descr = "HEVC Parsed Slice Data"; break; - case V4L2_PIX_FMT_FWHT: descr = "FWHT"; break; /* used in vicodec */ - case V4L2_PIX_FMT_FWHT_STATELESS: descr = "FWHT Stateless"; break; /* used in vicodec */ - case V4L2_PIX_FMT_CPIA1: descr = "GSPCA CPiA YUV"; break; -diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h -new file mode 100644 -index 000000000000..9ea013c88afc ---- /dev/null -+++ b/include/media/hevc-ctrls.h -@@ -0,0 +1,182 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * These are the HEVC state controls for use with stateless HEVC -+ * codec drivers. -+ * -+ * It turns out that these structs are not stable yet and will undergo -+ * more changes. So keep them private until they are stable and ready to -+ * become part of the official public API. -+ */ -+ -+#ifndef _HEVC_CTRLS_H_ -+#define _HEVC_CTRLS_H_ -+ -+#define V4L2_CID_MPEG_VIDEO_HEVC_SPS (V4L2_CID_MPEG_BASE + 1008) -+#define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_MPEG_BASE + 1009) -+#define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_MPEG_BASE + 1010) -+ -+/* enum v4l2_ctrl_type type values */ -+#define V4L2_CTRL_TYPE_HEVC_SPS 0x0120 -+#define V4L2_CTRL_TYPE_HEVC_PPS 0x0121 -+#define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0122 -+ -+#define V4L2_HEVC_SLICE_TYPE_B 0 -+#define V4L2_HEVC_SLICE_TYPE_P 1 -+#define V4L2_HEVC_SLICE_TYPE_I 2 -+ -+/* The controls are not stable at the moment and will likely be reworked. */ -+struct v4l2_ctrl_hevc_sps { -+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */ -+ __u8 chroma_format_idc; -+ __u8 separate_colour_plane_flag; -+ __u16 pic_width_in_luma_samples; -+ __u16 pic_height_in_luma_samples; -+ __u8 bit_depth_luma_minus8; -+ __u8 bit_depth_chroma_minus8; -+ __u8 log2_max_pic_order_cnt_lsb_minus4; -+ __u8 sps_max_dec_pic_buffering_minus1; -+ __u8 sps_max_num_reorder_pics; -+ __u8 sps_max_latency_increase_plus1; -+ __u8 log2_min_luma_coding_block_size_minus3; -+ __u8 log2_diff_max_min_luma_coding_block_size; -+ __u8 log2_min_luma_transform_block_size_minus2; -+ __u8 log2_diff_max_min_luma_transform_block_size; -+ __u8 max_transform_hierarchy_depth_inter; -+ __u8 max_transform_hierarchy_depth_intra; -+ __u8 scaling_list_enabled_flag; -+ __u8 amp_enabled_flag; -+ __u8 sample_adaptive_offset_enabled_flag; -+ __u8 pcm_enabled_flag; -+ __u8 pcm_sample_bit_depth_luma_minus1; -+ __u8 pcm_sample_bit_depth_chroma_minus1; -+ __u8 log2_min_pcm_luma_coding_block_size_minus3; -+ __u8 log2_diff_max_min_pcm_luma_coding_block_size; -+ __u8 pcm_loop_filter_disabled_flag; -+ __u8 num_short_term_ref_pic_sets; -+ __u8 long_term_ref_pics_present_flag; -+ __u8 num_long_term_ref_pics_sps; -+ __u8 sps_temporal_mvp_enabled_flag; -+ __u8 strong_intra_smoothing_enabled_flag; -+}; -+ -+struct v4l2_ctrl_hevc_pps { -+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */ -+ __u8 dependent_slice_segment_flag; -+ __u8 output_flag_present_flag; -+ __u8 num_extra_slice_header_bits; -+ __u8 sign_data_hiding_enabled_flag; -+ __u8 cabac_init_present_flag; -+ __s8 init_qp_minus26; -+ __u8 constrained_intra_pred_flag; -+ __u8 transform_skip_enabled_flag; -+ __u8 cu_qp_delta_enabled_flag; -+ __u8 diff_cu_qp_delta_depth; -+ __s8 pps_cb_qp_offset; -+ __s8 pps_cr_qp_offset; -+ __u8 pps_slice_chroma_qp_offsets_present_flag; -+ __u8 weighted_pred_flag; -+ __u8 weighted_bipred_flag; -+ __u8 transquant_bypass_enabled_flag; -+ __u8 tiles_enabled_flag; -+ __u8 entropy_coding_sync_enabled_flag; -+ __u8 num_tile_columns_minus1; -+ __u8 num_tile_rows_minus1; -+ __u8 column_width_minus1[20]; -+ __u8 row_height_minus1[22]; -+ __u8 loop_filter_across_tiles_enabled_flag; -+ __u8 pps_loop_filter_across_slices_enabled_flag; -+ __u8 deblocking_filter_override_enabled_flag; -+ __u8 pps_disable_deblocking_filter_flag; -+ __s8 pps_beta_offset_div2; -+ __s8 pps_tc_offset_div2; -+ __u8 lists_modification_present_flag; -+ __u8 log2_parallel_merge_level_minus2; -+ __u8 slice_segment_header_extension_present_flag; -+ __u8 padding; -+}; -+ -+#define V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE 0x01 -+#define V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_AFTER 0x02 -+#define V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR 0x03 -+ -+#define V4L2_HEVC_DPB_ENTRIES_NUM_MAX 16 -+ -+struct v4l2_hevc_dpb_entry { -+ __u64 timestamp; -+ __u8 rps; -+ __u8 field_pic; -+ __u16 pic_order_cnt[2]; -+ __u8 padding[2]; -+}; -+ -+struct v4l2_hevc_pred_weight_table { -+ __u8 luma_log2_weight_denom; -+ __s8 delta_chroma_log2_weight_denom; -+ -+ __s8 delta_luma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; -+ __s8 luma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; -+ __s8 delta_chroma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; -+ __s8 chroma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; -+ -+ __s8 delta_luma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; -+ __s8 luma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; -+ __s8 delta_chroma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; -+ __s8 chroma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; -+ -+ __u8 padding[2]; -+}; -+ -+struct v4l2_ctrl_hevc_slice_params { -+ __u32 bit_size; -+ __u32 data_bit_offset; -+ -+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ -+ __u8 nal_unit_type; -+ __u8 nuh_temporal_id_plus1; -+ -+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ -+ __u8 slice_type; -+ __u8 colour_plane_id; -+ __u16 slice_pic_order_cnt; -+ __u8 slice_sao_luma_flag; -+ __u8 slice_sao_chroma_flag; -+ __u8 slice_temporal_mvp_enabled_flag; -+ __u8 num_ref_idx_l0_active_minus1; -+ __u8 num_ref_idx_l1_active_minus1; -+ __u8 mvd_l1_zero_flag; -+ __u8 cabac_init_flag; -+ __u8 collocated_from_l0_flag; -+ __u8 collocated_ref_idx; -+ __u8 five_minus_max_num_merge_cand; -+ __u8 use_integer_mv_flag; -+ __s8 slice_qp_delta; -+ __s8 slice_cb_qp_offset; -+ __s8 slice_cr_qp_offset; -+ __s8 slice_act_y_qp_offset; -+ __s8 slice_act_cb_qp_offset; -+ __s8 slice_act_cr_qp_offset; -+ __u8 slice_deblocking_filter_disabled_flag; -+ __s8 slice_beta_offset_div2; -+ __s8 slice_tc_offset_div2; -+ __u8 slice_loop_filter_across_slices_enabled_flag; -+ -+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture timing SEI message */ -+ __u8 pic_struct; -+ -+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ -+ struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; -+ __u8 num_active_dpb_entries; -+ __u8 ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; -+ __u8 ref_idx_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; -+ -+ __u8 num_rps_poc_st_curr_before; -+ __u8 num_rps_poc_st_curr_after; -+ __u8 num_rps_poc_lt_curr; -+ -+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */ -+ struct v4l2_hevc_pred_weight_table pred_weight_table; -+ -+ __u8 padding[2]; -+}; -+ -+#endif -diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h -index a8aede26491e..630083e1936d 100644 ---- a/include/media/v4l2-ctrls.h -+++ b/include/media/v4l2-ctrls.h -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - - /* forward references */ - struct file; -@@ -57,6 +58,9 @@ struct poll_table_struct; - * @p_h264_scaling_matrix: Pointer to a struct v4l2_ctrl_h264_scaling_matrix. - * @p_h264_slice_params: Pointer to a struct v4l2_ctrl_h264_slice_params. - * @p_h264_decode_params: Pointer to a struct v4l2_ctrl_h264_decode_params. -+ * @p_hevc_sps: Pointer to an HEVC sequence parameter set structure. -+ * @p_hevc_pps: Pointer to an HEVC picture parameter set structure. -+ * @p_hevc_slice_params Pointer to an HEVC slice parameters structure. - * @p: Pointer to a compound value. - */ - union v4l2_ctrl_ptr { -@@ -74,6 +78,9 @@ union v4l2_ctrl_ptr { - struct v4l2_ctrl_h264_scaling_matrix *p_h264_scaling_matrix; - struct v4l2_ctrl_h264_slice_params *p_h264_slice_params; - struct v4l2_ctrl_h264_decode_params *p_h264_decode_params; -+ struct v4l2_ctrl_hevc_sps *p_hevc_sps; -+ struct v4l2_ctrl_hevc_pps *p_hevc_pps; -+ struct v4l2_ctrl_hevc_slice_params *p_hevc_slice_params; - void *p; - }; - --- -2.21.0 - -From dd424b21e39cd7e65a40298ddbaba468878ad1f5 Mon Sep 17 00:00:00 2001 -From: Paul Kocialkowski -Date: Fri, 24 May 2019 11:36:33 +0200 -Subject: [PATCH 10/12] media: pixfmt: Add HEVC slice pixel format - -Introduce the V4L2_PIX_FMT_HEVC_SLICE pixel format, which currently -describes an output buffer with enough appended slice data for -producing one decoded frame with a stateless video decoder. - -This will need to be reworked (along with the controls and the core) to -allow passing slice data individually, as it is the natural decoding -unit in HEVC. - -We also need to figure out the description of the possible source data: -* Compressed slice data only, with slice controls attached; -* Slice data in Annex-B format (with raw slice header), without slice - controls attached; -* Slice data in Annex-B format (with raw slice header), with slice - controls attached. - -Signed-off-by: Paul Kocialkowski -Signed-off-by: Hans Verkuil ---- - include/media/hevc-ctrls.h | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h -index 9ea013c88afc..2de83d9f6d47 100644 ---- a/include/media/hevc-ctrls.h -+++ b/include/media/hevc-ctrls.h -@@ -11,6 +11,9 @@ - #ifndef _HEVC_CTRLS_H_ - #define _HEVC_CTRLS_H_ - -+/* The pixel format isn't stable at the moment and will likely be renamed. */ -+#define V4L2_PIX_FMT_HEVC_SLICE v4l2_fourcc('S', '2', '6', '5') /* HEVC parsed slices */ -+ - #define V4L2_CID_MPEG_VIDEO_HEVC_SPS (V4L2_CID_MPEG_BASE + 1008) - #define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_MPEG_BASE + 1009) - #define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_MPEG_BASE + 1010) --- -2.21.0 - -From 256c89e4dd0621198cad6fbf0689682116cad795 Mon Sep 17 00:00:00 2001 -From: Paul Kocialkowski -Date: Fri, 24 May 2019 11:36:34 +0200 -Subject: [PATCH 11/12] media: pixfmt: Document the HEVC slice pixel format - -Document the current state of the HEVC slice pixel format. -The format will need to evolve in the future, which is why it is -not part of the public API. - -Signed-off-by: Paul Kocialkowski -Signed-off-by: Hans Verkuil ---- - .../media/uapi/v4l/pixfmt-compressed.rst | 21 +++++++++++++++++++ - 1 file changed, 21 insertions(+) - -diff --git a/Documentation/media/uapi/v4l/pixfmt-compressed.rst b/Documentation/media/uapi/v4l/pixfmt-compressed.rst -index 4b701fc7653e..9d4195723c3e 100644 ---- a/Documentation/media/uapi/v4l/pixfmt-compressed.rst -+++ b/Documentation/media/uapi/v4l/pixfmt-compressed.rst -@@ -143,6 +143,27 @@ Compressed Formats - - ``V4L2_PIX_FMT_HEVC`` - - 'HEVC' - - HEVC/H.265 video elementary stream. -+ * .. _V4L2-PIX-FMT-HEVC-SLICE: -+ -+ - ``V4L2_PIX_FMT_HEVC_SLICE`` -+ - 'S265' -+ - HEVC parsed slice data, as extracted from the HEVC bitstream. -+ This format is adapted for stateless video decoders that implement a -+ HEVC pipeline (using the :ref:`codec` and :ref:`media-request-api`). -+ Metadata associated with the frame to decode is required to be passed -+ through the following controls : -+ * ``V4L2_CID_MPEG_VIDEO_HEVC_SPS`` -+ * ``V4L2_CID_MPEG_VIDEO_HEVC_PPS`` -+ * ``V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS`` -+ See the :ref:`associated Codec Control IDs `. -+ Buffers associated with this pixel format must contain the appropriate -+ number of macroblocks to decode a full corresponding frame. -+ -+ .. note:: -+ -+ This format is not yet part of the public kernel API and it -+ is expected to change. -+ - * .. _V4L2-PIX-FMT-FWHT: - - - ``V4L2_PIX_FMT_FWHT`` --- -2.21.0 - -From ef19574101a1e649c440c43615420b7047f8f4ef Mon Sep 17 00:00:00 2001 -From: Paul Kocialkowski -Date: Fri, 24 May 2019 11:36:35 +0200 -Subject: [PATCH 12/12] media: cedrus: Add HEVC/H.265 decoding support - -This introduces support for HEVC/H.265 to the Cedrus VPU driver, with -both uni-directional and bi-directional prediction modes supported. - -Field-coded (interlaced) pictures, custom quantization matrices and -10-bit output are not supported at this point. - -Signed-off-by: Paul Kocialkowski -Signed-off-by: Hans Verkuil ---- - drivers/staging/media/sunxi/cedrus/Makefile | 2 +- - drivers/staging/media/sunxi/cedrus/cedrus.c | 31 +- - drivers/staging/media/sunxi/cedrus/cedrus.h | 18 + - .../staging/media/sunxi/cedrus/cedrus_dec.c | 9 + - .../staging/media/sunxi/cedrus/cedrus_h265.c | 532 ++++++++++++++++++ - .../staging/media/sunxi/cedrus/cedrus_hw.c | 4 + - .../staging/media/sunxi/cedrus/cedrus_regs.h | 290 ++++++++++ - .../staging/media/sunxi/cedrus/cedrus_video.c | 10 + - 8 files changed, 891 insertions(+), 5 deletions(-) - create mode 100644 drivers/staging/media/sunxi/cedrus/cedrus_h265.c - -diff --git a/drivers/staging/media/sunxi/cedrus/Makefile b/drivers/staging/media/sunxi/cedrus/Makefile -index c85ac6db0302..1bce49d3e7e2 100644 ---- a/drivers/staging/media/sunxi/cedrus/Makefile -+++ b/drivers/staging/media/sunxi/cedrus/Makefile -@@ -2,4 +2,4 @@ - obj-$(CONFIG_VIDEO_SUNXI_CEDRUS) += sunxi-cedrus.o - - sunxi-cedrus-y = cedrus.o cedrus_video.o cedrus_hw.o cedrus_dec.o \ -- cedrus_mpeg2.o cedrus_h264.o -+ cedrus_mpeg2.o cedrus_h264.o cedrus_h265.o -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c -index 370937edfc14..70642834f351 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c -@@ -70,6 +70,27 @@ static const struct cedrus_control cedrus_controls[] = { - .codec = CEDRUS_CODEC_H264, - .required = true, - }, -+ { -+ .cfg = { -+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SPS, -+ }, -+ .codec = CEDRUS_CODEC_H265, -+ .required = true, -+ }, -+ { -+ .cfg = { -+ .id = V4L2_CID_MPEG_VIDEO_HEVC_PPS, -+ }, -+ .codec = CEDRUS_CODEC_H265, -+ .required = true, -+ }, -+ { -+ .cfg = { -+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS, -+ }, -+ .codec = CEDRUS_CODEC_H265, -+ .required = true, -+ }, - }; - - #define CEDRUS_CONTROLS_COUNT ARRAY_SIZE(cedrus_controls) -@@ -309,6 +327,7 @@ static int cedrus_probe(struct platform_device *pdev) - - dev->dec_ops[CEDRUS_CODEC_MPEG2] = &cedrus_dec_ops_mpeg2; - dev->dec_ops[CEDRUS_CODEC_H264] = &cedrus_dec_ops_h264; -+ dev->dec_ops[CEDRUS_CODEC_H265] = &cedrus_dec_ops_h265; - - mutex_init(&dev->dev_mutex); - -@@ -417,22 +436,26 @@ static const struct cedrus_variant sun8i_a33_cedrus_variant = { - }; - - static const struct cedrus_variant sun8i_h3_cedrus_variant = { -- .capabilities = CEDRUS_CAPABILITY_UNTILED, -+ .capabilities = CEDRUS_CAPABILITY_UNTILED | -+ CEDRUS_CAPABILITY_H265_DEC, - .mod_rate = 402000000, - }; - - static const struct cedrus_variant sun50i_a64_cedrus_variant = { -- .capabilities = CEDRUS_CAPABILITY_UNTILED, -+ .capabilities = CEDRUS_CAPABILITY_UNTILED | -+ CEDRUS_CAPABILITY_H265_DEC, - .mod_rate = 402000000, - }; - - static const struct cedrus_variant sun50i_h5_cedrus_variant = { -- .capabilities = CEDRUS_CAPABILITY_UNTILED, -+ .capabilities = CEDRUS_CAPABILITY_UNTILED | -+ CEDRUS_CAPABILITY_H265_DEC, - .mod_rate = 402000000, - }; - - static const struct cedrus_variant sun50i_h6_cedrus_variant = { -- .capabilities = CEDRUS_CAPABILITY_UNTILED, -+ .capabilities = CEDRUS_CAPABILITY_UNTILED | -+ CEDRUS_CAPABILITY_H265_DEC, - .quirks = CEDRUS_QUIRK_NO_DMA_OFFSET, - .mod_rate = 600000000, - }; -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h -index 3f476d0fd981..f19be772d78b 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus.h -+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h -@@ -27,12 +27,14 @@ - #define CEDRUS_NAME "cedrus" - - #define CEDRUS_CAPABILITY_UNTILED BIT(0) -+#define CEDRUS_CAPABILITY_H265_DEC BIT(1) - - #define CEDRUS_QUIRK_NO_DMA_OFFSET BIT(0) - - enum cedrus_codec { - CEDRUS_CODEC_MPEG2, - CEDRUS_CODEC_H264, -+ CEDRUS_CODEC_H265, - CEDRUS_CODEC_LAST, - }; - -@@ -68,6 +70,12 @@ struct cedrus_mpeg2_run { - const struct v4l2_ctrl_mpeg2_quantization *quantization; - }; - -+struct cedrus_h265_run { -+ const struct v4l2_ctrl_hevc_sps *sps; -+ const struct v4l2_ctrl_hevc_pps *pps; -+ const struct v4l2_ctrl_hevc_slice_params *slice_params; -+}; -+ - struct cedrus_run { - struct vb2_v4l2_buffer *src; - struct vb2_v4l2_buffer *dst; -@@ -75,6 +83,7 @@ struct cedrus_run { - union { - struct cedrus_h264_run h264; - struct cedrus_mpeg2_run mpeg2; -+ struct cedrus_h265_run h265; - }; - }; - -@@ -113,6 +122,14 @@ struct cedrus_ctx { - void *neighbor_info_buf; - dma_addr_t neighbor_info_buf_dma; - } h264; -+ struct { -+ void *mv_col_buf; -+ dma_addr_t mv_col_buf_addr; -+ ssize_t mv_col_buf_size; -+ ssize_t mv_col_buf_unit_size; -+ void *neighbor_info_buf; -+ dma_addr_t neighbor_info_buf_addr; -+ } h265; - } codec; - }; - -@@ -158,6 +175,7 @@ struct cedrus_dev { - - extern struct cedrus_dec_ops cedrus_dec_ops_mpeg2; - extern struct cedrus_dec_ops cedrus_dec_ops_h264; -+extern struct cedrus_dec_ops cedrus_dec_ops_h265; - - static inline void cedrus_write(struct cedrus_dev *dev, u32 reg, u32 val) - { -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c -index bdad87eb9d79..c6d0ef66cdd0 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c -@@ -59,6 +59,15 @@ void cedrus_device_run(void *priv) - V4L2_CID_MPEG_VIDEO_H264_SPS); - break; - -+ case V4L2_PIX_FMT_HEVC_SLICE: -+ run.h265.sps = cedrus_find_control_data(ctx, -+ V4L2_CID_MPEG_VIDEO_HEVC_SPS); -+ run.h265.pps = cedrus_find_control_data(ctx, -+ V4L2_CID_MPEG_VIDEO_HEVC_PPS); -+ run.h265.slice_params = cedrus_find_control_data(ctx, -+ V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS); -+ break; -+ - default: - break; - } -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -new file mode 100644 -index 000000000000..fd4d86b02156 ---- /dev/null -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -@@ -0,0 +1,535 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * Cedrus VPU driver -+ * -+ * Copyright (C) 2013 Jens Kuske -+ * Copyright (C) 2018 Paul Kocialkowski -+ * Copyright (C) 2018 Bootlin -+ */ -+ -+#include -+ -+#include -+ -+#include "cedrus.h" -+#include "cedrus_hw.h" -+#include "cedrus_regs.h" -+ -+/* -+ * These are the sizes for side buffers required by the hardware for storing -+ * internal decoding metadata. They match the values used by the early BSP -+ * implementations, that were initially exposed in libvdpau-sunxi. -+ * Subsequent BSP implementations seem to double the neighbor info buffer size -+ * for the H6 SoC, which may be related to 10 bit H265 support. -+ */ -+#define CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE (397 * SZ_1K) -+#define CEDRUS_H265_ENTRY_POINTS_BUF_SIZE (4 * SZ_1K) -+#define CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE 160 -+ -+struct cedrus_h265_sram_frame_info { -+ __le32 top_pic_order_cnt; -+ __le32 bottom_pic_order_cnt; -+ __le32 top_mv_col_buf_addr; -+ __le32 bottom_mv_col_buf_addr; -+ __le32 luma_addr; -+ __le32 chroma_addr; -+} __packed; -+ -+struct cedrus_h265_sram_pred_weight { -+ __s8 delta_weight; -+ __s8 offset; -+} __packed; -+ -+static enum cedrus_irq_status cedrus_h265_irq_status(struct cedrus_ctx *ctx) -+{ -+ struct cedrus_dev *dev = ctx->dev; -+ u32 reg; -+ -+ reg = cedrus_read(dev, VE_DEC_H265_STATUS); -+ reg &= VE_DEC_H265_STATUS_CHECK_MASK; -+ -+ if (reg & VE_DEC_H265_STATUS_CHECK_ERROR || -+ !(reg & VE_DEC_H265_STATUS_SUCCESS)) -+ return CEDRUS_IRQ_ERROR; -+ -+ return CEDRUS_IRQ_OK; -+} -+ -+static void cedrus_h265_irq_clear(struct cedrus_ctx *ctx) -+{ -+ struct cedrus_dev *dev = ctx->dev; -+ -+ cedrus_write(dev, VE_DEC_H265_STATUS, VE_DEC_H265_STATUS_CHECK_MASK); -+} -+ -+static void cedrus_h265_irq_disable(struct cedrus_ctx *ctx) -+{ -+ struct cedrus_dev *dev = ctx->dev; -+ u32 reg = cedrus_read(dev, VE_DEC_H265_CTRL); -+ -+ reg &= ~VE_DEC_H265_CTRL_IRQ_MASK; -+ -+ cedrus_write(dev, VE_DEC_H265_CTRL, reg); -+} -+ -+static void cedrus_h265_sram_write_offset(struct cedrus_dev *dev, u32 offset) -+{ -+ cedrus_write(dev, VE_DEC_H265_SRAM_OFFSET, offset); -+} -+ -+static void cedrus_h265_sram_write_data(struct cedrus_dev *dev, void *data, -+ unsigned int size) -+{ -+ u32 *word = data; -+ -+ while (size >= sizeof(u32)) { -+ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, *word++); -+ size -= sizeof(u32); -+ } -+} -+ -+static inline dma_addr_t -+cedrus_h265_frame_info_mv_col_buf_addr(struct cedrus_ctx *ctx, -+ unsigned int index, unsigned int field) -+{ -+ return ctx->codec.h265.mv_col_buf_addr + index * -+ ctx->codec.h265.mv_col_buf_unit_size + -+ field * ctx->codec.h265.mv_col_buf_unit_size / 2; -+} -+ -+static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx, -+ unsigned int index, -+ bool field_pic, -+ u32 pic_order_cnt[], -+ int buffer_index) -+{ -+ struct cedrus_dev *dev = ctx->dev; -+ dma_addr_t dst_luma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 0); -+ dma_addr_t dst_chroma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 1); -+ dma_addr_t mv_col_buf_addr[2] = { -+ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, 0), -+ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, -+ field_pic ? 1 : 0) -+ }; -+ u32 offset = VE_DEC_H265_SRAM_OFFSET_FRAME_INFO + -+ VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT * index; -+ struct cedrus_h265_sram_frame_info frame_info = { -+ .top_pic_order_cnt = cpu_to_le32(pic_order_cnt[0]), -+ .bottom_pic_order_cnt = cpu_to_le32(field_pic ? -+ pic_order_cnt[1] : -+ pic_order_cnt[0]), -+ .top_mv_col_buf_addr = -+ cpu_to_le32(VE_DEC_H265_SRAM_DATA_ADDR_BASE(mv_col_buf_addr[0])), -+ .bottom_mv_col_buf_addr = cpu_to_le32(field_pic ? -+ VE_DEC_H265_SRAM_DATA_ADDR_BASE(mv_col_buf_addr[1]) : -+ VE_DEC_H265_SRAM_DATA_ADDR_BASE(mv_col_buf_addr[0])), -+ .luma_addr = cpu_to_le32(VE_DEC_H265_SRAM_DATA_ADDR_BASE(dst_luma_addr)), -+ .chroma_addr = cpu_to_le32(VE_DEC_H265_SRAM_DATA_ADDR_BASE(dst_chroma_addr)), -+ }; -+ -+ cedrus_h265_sram_write_offset(dev, offset); -+ cedrus_h265_sram_write_data(dev, &frame_info, sizeof(frame_info)); -+} -+ -+static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx, int fallback, -+ const struct v4l2_hevc_dpb_entry *dpb, -+ u8 num_active_dpb_entries) -+{ -+ struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, -+ V4L2_BUF_TYPE_VIDEO_CAPTURE); -+ unsigned int i; -+ -+ for (i = 0; i < num_active_dpb_entries; i++) { -+ int buffer_index = vb2_find_timestamp(vq, dpb[i].timestamp, 0); -+ u32 pic_order_cnt[2] = { -+ dpb[i].pic_order_cnt[0], -+ dpb[i].pic_order_cnt[1] -+ }; -+ -+ if (buffer_index < 0) -+ buffer_index = fallback; -+ -+ cedrus_h265_frame_info_write_single(ctx, i, dpb[i].field_pic, -+ pic_order_cnt, -+ buffer_index); -+ } -+} -+ -+static void cedrus_h265_ref_pic_list_write(struct cedrus_dev *dev, -+ const struct v4l2_hevc_dpb_entry *dpb, -+ const u8 list[], -+ u8 num_ref_idx_active, -+ u32 sram_offset) -+{ -+ unsigned int i; -+ u32 word = 0; -+ -+ cedrus_h265_sram_write_offset(dev, sram_offset); -+ -+ for (i = 0; i < num_ref_idx_active; i++) { -+ unsigned int shift = (i % 4) * 8; -+ unsigned int index = list[i]; -+ u8 value = list[i]; -+ -+ if (dpb[index].rps == V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR) -+ value |= VE_DEC_H265_SRAM_REF_PIC_LIST_LT_REF; -+ -+ /* Each SRAM word gathers up to 4 references. */ -+ word |= value << shift; -+ -+ /* Write the word to SRAM and clear it for the next batch. */ -+ if ((i % 4) == 3 || i == (num_ref_idx_active - 1)) { -+ cedrus_h265_sram_write_data(dev, &word, sizeof(word)); -+ word = 0; -+ } -+ } -+} -+ -+static void cedrus_h265_pred_weight_write(struct cedrus_dev *dev, -+ const s8 delta_luma_weight[], -+ const s8 luma_offset[], -+ const s8 delta_chroma_weight[][2], -+ const s8 chroma_offset[][2], -+ u8 num_ref_idx_active, -+ u32 sram_luma_offset, -+ u32 sram_chroma_offset) -+{ -+ struct cedrus_h265_sram_pred_weight pred_weight[2] = { { 0 } }; -+ unsigned int i, j; -+ -+ cedrus_h265_sram_write_offset(dev, sram_luma_offset); -+ -+ for (i = 0; i < num_ref_idx_active; i++) { -+ unsigned int index = i % 2; -+ -+ pred_weight[index].delta_weight = delta_luma_weight[i]; -+ pred_weight[index].offset = luma_offset[i]; -+ -+ if (index == 1 || i == (num_ref_idx_active - 1)) -+ cedrus_h265_sram_write_data(dev, (u32 *)&pred_weight, -+ sizeof(pred_weight)); -+ } -+ -+ cedrus_h265_sram_write_offset(dev, sram_chroma_offset); -+ -+ for (i = 0; i < num_ref_idx_active; i++) { -+ for (j = 0; j < 2; j++) { -+ pred_weight[j].delta_weight = delta_chroma_weight[i][j]; -+ pred_weight[j].offset = chroma_offset[i][j]; -+ } -+ -+ cedrus_h265_sram_write_data(dev, &pred_weight, -+ sizeof(pred_weight)); -+ } -+} -+ -+static void cedrus_h265_setup(struct cedrus_ctx *ctx, -+ struct cedrus_run *run) -+{ -+ struct cedrus_dev *dev = ctx->dev; -+ const struct v4l2_ctrl_hevc_sps *sps; -+ const struct v4l2_ctrl_hevc_pps *pps; -+ const struct v4l2_ctrl_hevc_slice_params *slice_params; -+ const struct v4l2_hevc_pred_weight_table *pred_weight_table; -+ dma_addr_t src_buf_addr; -+ dma_addr_t src_buf_end_addr; -+ u32 chroma_log2_weight_denom; -+ u32 output_pic_list_index; -+ u32 pic_order_cnt[2]; -+ u32 reg; -+ -+ sps = run->h265.sps; -+ pps = run->h265.pps; -+ slice_params = run->h265.slice_params; -+ pred_weight_table = &slice_params->pred_weight_table; -+ -+ /* MV column buffer size and allocation. */ -+ if (!ctx->codec.h265.mv_col_buf_size) { -+ unsigned int num_buffers = -+ run->dst->vb2_buf.vb2_queue->num_buffers; -+ unsigned int log2_max_luma_coding_block_size = -+ sps->log2_min_luma_coding_block_size_minus3 + 3 + -+ sps->log2_diff_max_min_luma_coding_block_size; -+ unsigned int ctb_size_luma = -+ 1 << log2_max_luma_coding_block_size; -+ -+ /* -+ * Each CTB requires a MV col buffer with a specific unit size. -+ * Since the address is given with missing lsb bits, 1 KiB is -+ * added to each buffer to ensure proper alignment. -+ */ -+ ctx->codec.h265.mv_col_buf_unit_size = -+ DIV_ROUND_UP(ctx->src_fmt.width, ctb_size_luma) * -+ DIV_ROUND_UP(ctx->src_fmt.height, ctb_size_luma) * -+ CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE + SZ_1K; -+ -+ ctx->codec.h265.mv_col_buf_size = num_buffers * -+ ctx->codec.h265.mv_col_buf_unit_size; -+ -+ ctx->codec.h265.mv_col_buf = -+ dma_alloc_coherent(dev->dev, -+ ctx->codec.h265.mv_col_buf_size, -+ &ctx->codec.h265.mv_col_buf_addr, -+ GFP_KERNEL); -+ if (!ctx->codec.h265.mv_col_buf) { -+ ctx->codec.h265.mv_col_buf_size = 0; -+ // TODO: Abort the process here. -+ return; -+ } -+ } -+ -+ /* Activate H265 engine. */ -+ cedrus_engine_enable(dev, CEDRUS_CODEC_H265); -+ -+ /* Source offset and length in bits. */ -+ -+ reg = slice_params->data_bit_offset; -+ cedrus_write(dev, VE_DEC_H265_BITS_OFFSET, reg); -+ -+ reg = slice_params->bit_size - slice_params->data_bit_offset; -+ cedrus_write(dev, VE_DEC_H265_BITS_LEN, reg); -+ -+ /* Source beginning and end addresses. */ -+ -+ src_buf_addr = vb2_dma_contig_plane_dma_addr(&run->src->vb2_buf, 0); -+ -+ reg = VE_DEC_H265_BITS_ADDR_BASE(src_buf_addr); -+ reg |= VE_DEC_H265_BITS_ADDR_VALID_SLICE_DATA; -+ reg |= VE_DEC_H265_BITS_ADDR_LAST_SLICE_DATA; -+ reg |= VE_DEC_H265_BITS_ADDR_FIRST_SLICE_DATA; -+ -+ cedrus_write(dev, VE_DEC_H265_BITS_ADDR, reg); -+ -+ src_buf_end_addr = src_buf_addr + -+ DIV_ROUND_UP(slice_params->bit_size, 8); -+ -+ reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_end_addr); -+ cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg); -+ -+ /* Coding tree block address: start at the beginning. */ -+ reg = VE_DEC_H265_DEC_CTB_ADDR_X(0) | VE_DEC_H265_DEC_CTB_ADDR_Y(0); -+ cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg); -+ -+ cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0); -+ cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0); -+ -+ /* Clear the number of correctly-decoded coding tree blocks. */ -+ cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0); -+ -+ /* Initialize bitstream access. */ -+ cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_INIT_SWDEC); -+ -+ /* Bitstream parameters. */ -+ -+ reg = VE_DEC_H265_DEC_NAL_HDR_NAL_UNIT_TYPE(slice_params->nal_unit_type) | -+ VE_DEC_H265_DEC_NAL_HDR_NUH_TEMPORAL_ID_PLUS1(slice_params->nuh_temporal_id_plus1); -+ -+ cedrus_write(dev, VE_DEC_H265_DEC_NAL_HDR, reg); -+ -+ reg = VE_DEC_H265_DEC_SPS_HDR_STRONG_INTRA_SMOOTHING_ENABLE_FLAG(sps->strong_intra_smoothing_enabled_flag) | -+ VE_DEC_H265_DEC_SPS_HDR_SPS_TEMPORAL_MVP_ENABLED_FLAG(sps->sps_temporal_mvp_enabled_flag) | -+ VE_DEC_H265_DEC_SPS_HDR_SAMPLE_ADAPTIVE_OFFSET_ENABLED_FLAG(sps->sample_adaptive_offset_enabled_flag) | -+ VE_DEC_H265_DEC_SPS_HDR_AMP_ENABLED_FLAG(sps->amp_enabled_flag) | -+ VE_DEC_H265_DEC_SPS_HDR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTRA(sps->max_transform_hierarchy_depth_intra) | -+ VE_DEC_H265_DEC_SPS_HDR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTER(sps->max_transform_hierarchy_depth_inter) | -+ VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_TRANSFORM_BLOCK_SIZE(sps->log2_diff_max_min_luma_transform_block_size) | -+ VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_TRANSFORM_BLOCK_SIZE_MINUS2(sps->log2_min_luma_transform_block_size_minus2) | -+ VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE(sps->log2_diff_max_min_luma_coding_block_size) | -+ VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_LUMA_CODING_BLOCK_SIZE_MINUS3(sps->log2_min_luma_coding_block_size_minus3) | -+ VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_CHROMA_MINUS8(sps->bit_depth_chroma_minus8) | -+ VE_DEC_H265_DEC_SPS_HDR_SEPARATE_COLOUR_PLANE_FLAG(sps->separate_colour_plane_flag) | -+ VE_DEC_H265_DEC_SPS_HDR_CHROMA_FORMAT_IDC(sps->chroma_format_idc); -+ -+ cedrus_write(dev, VE_DEC_H265_DEC_SPS_HDR, reg); -+ -+ reg = VE_DEC_H265_DEC_PCM_CTRL_PCM_ENABLED_FLAG(sps->pcm_enabled_flag) | -+ VE_DEC_H265_DEC_PCM_CTRL_PCM_LOOP_FILTER_DISABLED_FLAG(sps->pcm_loop_filter_disabled_flag) | -+ VE_DEC_H265_DEC_PCM_CTRL_LOG2_DIFF_MAX_MIN_PCM_LUMA_CODING_BLOCK_SIZE(sps->log2_diff_max_min_pcm_luma_coding_block_size) | -+ VE_DEC_H265_DEC_PCM_CTRL_LOG2_MIN_PCM_LUMA_CODING_BLOCK_SIZE_MINUS3(sps->log2_min_pcm_luma_coding_block_size_minus3) | -+ VE_DEC_H265_DEC_PCM_CTRL_PCM_SAMPLE_BIT_DEPTH_CHROMA_MINUS1(sps->pcm_sample_bit_depth_chroma_minus1) | -+ VE_DEC_H265_DEC_PCM_CTRL_PCM_SAMPLE_BIT_DEPTH_LUMA_MINUS1(sps->pcm_sample_bit_depth_luma_minus1); -+ -+ cedrus_write(dev, VE_DEC_H265_DEC_PCM_CTRL, reg); -+ -+ reg = VE_DEC_H265_DEC_PPS_CTRL0_PPS_CR_QP_OFFSET(pps->pps_cr_qp_offset) | -+ VE_DEC_H265_DEC_PPS_CTRL0_PPS_CB_QP_OFFSET(pps->pps_cb_qp_offset) | -+ VE_DEC_H265_DEC_PPS_CTRL0_INIT_QP_MINUS26(pps->init_qp_minus26) | -+ VE_DEC_H265_DEC_PPS_CTRL0_DIFF_CU_QP_DELTA_DEPTH(pps->diff_cu_qp_delta_depth) | -+ VE_DEC_H265_DEC_PPS_CTRL0_CU_QP_DELTA_ENABLED_FLAG(pps->cu_qp_delta_enabled_flag) | -+ VE_DEC_H265_DEC_PPS_CTRL0_TRANSFORM_SKIP_ENABLED_FLAG(pps->transform_skip_enabled_flag) | -+ VE_DEC_H265_DEC_PPS_CTRL0_CONSTRAINED_INTRA_PRED_FLAG(pps->constrained_intra_pred_flag) | -+ VE_DEC_H265_DEC_PPS_CTRL0_SIGN_DATA_HIDING_FLAG(pps->sign_data_hiding_enabled_flag); -+ -+ cedrus_write(dev, VE_DEC_H265_DEC_PPS_CTRL0, reg); -+ -+ reg = VE_DEC_H265_DEC_PPS_CTRL1_LOG2_PARALLEL_MERGE_LEVEL_MINUS2(pps->log2_parallel_merge_level_minus2) | -+ VE_DEC_H265_DEC_PPS_CTRL1_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG(pps->pps_loop_filter_across_slices_enabled_flag) | -+ VE_DEC_H265_DEC_PPS_CTRL1_LOOP_FILTER_ACROSS_TILES_ENABLED_FLAG(pps->loop_filter_across_tiles_enabled_flag) | -+ VE_DEC_H265_DEC_PPS_CTRL1_ENTROPY_CODING_SYNC_ENABLED_FLAG(pps->entropy_coding_sync_enabled_flag) | -+ VE_DEC_H265_DEC_PPS_CTRL1_TILES_ENABLED_FLAG(0) | -+ VE_DEC_H265_DEC_PPS_CTRL1_TRANSQUANT_BYPASS_ENABLE_FLAG(pps->transquant_bypass_enabled_flag) | -+ VE_DEC_H265_DEC_PPS_CTRL1_WEIGHTED_BIPRED_FLAG(pps->weighted_bipred_flag) | -+ VE_DEC_H265_DEC_PPS_CTRL1_WEIGHTED_PRED_FLAG(pps->weighted_pred_flag); -+ -+ cedrus_write(dev, VE_DEC_H265_DEC_PPS_CTRL1, reg); -+ -+ reg = VE_DEC_H265_DEC_SLICE_HDR_INFO0_PICTURE_TYPE(slice_params->pic_struct) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO0_FIVE_MINUS_MAX_NUM_MERGE_CAND(slice_params->five_minus_max_num_merge_cand) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO0_NUM_REF_IDX_L1_ACTIVE_MINUS1(slice_params->num_ref_idx_l1_active_minus1) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO0_NUM_REF_IDX_L0_ACTIVE_MINUS1(slice_params->num_ref_idx_l0_active_minus1) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLLOCATED_REF_IDX(slice_params->collocated_ref_idx) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLLOCATED_FROM_L0_FLAG(slice_params->collocated_from_l0_flag) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO0_CABAC_INIT_FLAG(slice_params->cabac_init_flag) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO0_MVD_L1_ZERO_FLAG(slice_params->mvd_l1_zero_flag) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO0_SLICE_SAO_CHROMA_FLAG(slice_params->slice_sao_chroma_flag) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO0_SLICE_SAO_LUMA_FLAG(slice_params->slice_sao_luma_flag) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO0_SLICE_TEMPORAL_MVP_ENABLE_FLAG(slice_params->slice_temporal_mvp_enabled_flag) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLOUR_PLANE_ID(slice_params->colour_plane_id) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO0_SLICE_TYPE(slice_params->slice_type) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO0_DEPENDENT_SLICE_SEGMENT_FLAG(pps->dependent_slice_segment_flag) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO0_FIRST_SLICE_SEGMENT_IN_PIC_FLAG(1); -+ -+ cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO0, reg); -+ -+ reg = VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_TC_OFFSET_DIV2(slice_params->slice_tc_offset_div2) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_BETA_OFFSET_DIV2(slice_params->slice_beta_offset_div2) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_DEBLOCKING_FILTER_DISABLED_FLAG(slice_params->slice_deblocking_filter_disabled_flag) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG(slice_params->slice_loop_filter_across_slices_enabled_flag) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_POC_BIGEST_IN_RPS_ST(slice_params->num_rps_poc_st_curr_after == 0) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CR_QP_OFFSET(slice_params->slice_cr_qp_offset) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CB_QP_OFFSET(slice_params->slice_cb_qp_offset) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_QP_DELTA(slice_params->slice_qp_delta); -+ -+ cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO1, reg); -+ -+ chroma_log2_weight_denom = pred_weight_table->luma_log2_weight_denom + -+ pred_weight_table->delta_chroma_log2_weight_denom; -+ reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(0) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO2_CHROMA_LOG2_WEIGHT_DENOM(chroma_log2_weight_denom) | -+ VE_DEC_H265_DEC_SLICE_HDR_INFO2_LUMA_LOG2_WEIGHT_DENOM(pred_weight_table->luma_log2_weight_denom); -+ -+ cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO2, reg); -+ -+ /* Decoded picture size. */ -+ -+ reg = VE_DEC_H265_DEC_PIC_SIZE_WIDTH(ctx->src_fmt.width) | -+ VE_DEC_H265_DEC_PIC_SIZE_HEIGHT(ctx->src_fmt.height); -+ -+ cedrus_write(dev, VE_DEC_H265_DEC_PIC_SIZE, reg); -+ -+ /* Scaling list. */ -+ -+ reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT; -+ cedrus_write(dev, VE_DEC_H265_SCALING_LIST_CTRL0, reg); -+ -+ /* Neightbor information address. */ -+ reg = VE_DEC_H265_NEIGHBOR_INFO_ADDR_BASE(ctx->codec.h265.neighbor_info_buf_addr); -+ cedrus_write(dev, VE_DEC_H265_NEIGHBOR_INFO_ADDR, reg); -+ -+ /* Write decoded picture buffer in pic list. */ -+ cedrus_h265_frame_info_write_dpb(ctx, run->dst->vb2_buf.index, slice_params->dpb, -+ slice_params->num_active_dpb_entries); -+ -+ /* Output frame. */ -+ -+ output_pic_list_index = V4L2_HEVC_DPB_ENTRIES_NUM_MAX; -+ pic_order_cnt[0] = slice_params->slice_pic_order_cnt; -+ pic_order_cnt[1] = slice_params->slice_pic_order_cnt; -+ -+ cedrus_h265_frame_info_write_single(ctx, output_pic_list_index, -+ slice_params->pic_struct != 0, -+ pic_order_cnt, -+ run->dst->vb2_buf.index); -+ -+ cedrus_write(dev, VE_DEC_H265_OUTPUT_FRAME_IDX, output_pic_list_index); -+ -+ /* Reference picture list 0 (for P/B frames). */ -+ if (slice_params->slice_type != V4L2_HEVC_SLICE_TYPE_I) { -+ cedrus_h265_ref_pic_list_write(dev, slice_params->dpb, -+ slice_params->ref_idx_l0, -+ slice_params->num_ref_idx_l0_active_minus1 + 1, -+ VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST0); -+ -+ if (pps->weighted_pred_flag || pps->weighted_bipred_flag) -+ cedrus_h265_pred_weight_write(dev, -+ pred_weight_table->delta_luma_weight_l0, -+ pred_weight_table->luma_offset_l0, -+ pred_weight_table->delta_chroma_weight_l0, -+ pred_weight_table->chroma_offset_l0, -+ slice_params->num_ref_idx_l0_active_minus1 + 1, -+ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L0, -+ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L0); -+ } -+ -+ /* Reference picture list 1 (for B frames). */ -+ if (slice_params->slice_type == V4L2_HEVC_SLICE_TYPE_B) { -+ cedrus_h265_ref_pic_list_write(dev, slice_params->dpb, -+ slice_params->ref_idx_l1, -+ slice_params->num_ref_idx_l1_active_minus1 + 1, -+ VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST1); -+ -+ if (pps->weighted_bipred_flag) -+ cedrus_h265_pred_weight_write(dev, -+ pred_weight_table->delta_luma_weight_l1, -+ pred_weight_table->luma_offset_l1, -+ pred_weight_table->delta_chroma_weight_l1, -+ pred_weight_table->chroma_offset_l1, -+ slice_params->num_ref_idx_l1_active_minus1 + 1, -+ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L1, -+ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L1); -+ } -+ -+ /* Enable appropriate interruptions. */ -+ cedrus_write(dev, VE_DEC_H265_CTRL, VE_DEC_H265_CTRL_IRQ_MASK); -+} -+ -+static int cedrus_h265_start(struct cedrus_ctx *ctx) -+{ -+ struct cedrus_dev *dev = ctx->dev; -+ -+ /* The buffer size is calculated at setup time. */ -+ ctx->codec.h265.mv_col_buf_size = 0; -+ -+ ctx->codec.h265.neighbor_info_buf = -+ dma_alloc_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, -+ &ctx->codec.h265.neighbor_info_buf_addr, -+ GFP_KERNEL); -+ if (!ctx->codec.h265.neighbor_info_buf) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+static void cedrus_h265_stop(struct cedrus_ctx *ctx) -+{ -+ struct cedrus_dev *dev = ctx->dev; -+ -+ if (ctx->codec.h265.mv_col_buf_size > 0) { -+ dma_free_coherent(dev->dev, ctx->codec.h265.mv_col_buf_size, -+ ctx->codec.h265.mv_col_buf, -+ ctx->codec.h265.mv_col_buf_addr); -+ -+ ctx->codec.h265.mv_col_buf_size = 0; -+ } -+ -+ dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, -+ ctx->codec.h265.neighbor_info_buf, -+ ctx->codec.h265.neighbor_info_buf_addr); -+} -+ -+static void cedrus_h265_trigger(struct cedrus_ctx *ctx) -+{ -+ struct cedrus_dev *dev = ctx->dev; -+ -+ cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_DEC_SLICE); -+} -+ -+struct cedrus_dec_ops cedrus_dec_ops_h265 = { -+ .irq_clear = cedrus_h265_irq_clear, -+ .irq_disable = cedrus_h265_irq_disable, -+ .irq_status = cedrus_h265_irq_status, -+ .setup = cedrus_h265_setup, -+ .start = cedrus_h265_start, -+ .stop = cedrus_h265_stop, -+ .trigger = cedrus_h265_trigger, -+}; -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c -index c34aec7c6e40..7d2f6eedfc28 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c -@@ -50,6 +50,10 @@ int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec) - reg |= VE_MODE_DEC_H264; - break; - -+ case CEDRUS_CODEC_H265: -+ reg |= VE_MODE_DEC_H265; -+ break; -+ - default: - return -EINVAL; - } -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -index 3e9931416e45..87651d6b6227 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -@@ -18,10 +18,17 @@ - * * MC: Motion Compensation - * * STCD: Start Code Detect - * * SDRT: Scale Down and Rotate -+ * * WB: Writeback -+ * * BITS/BS: Bitstream -+ * * MB: Macroblock -+ * * CTU: Coding Tree Unit -+ * * CTB: Coding Tree Block -+ * * IDX: Index - */ - - #define VE_ENGINE_DEC_MPEG 0x100 - #define VE_ENGINE_DEC_H264 0x200 -+#define VE_ENGINE_DEC_H265 0x500 - - #define VE_MODE 0x00 - -@@ -232,6 +239,289 @@ - #define VE_DEC_MPEG_ROT_LUMA (VE_ENGINE_DEC_MPEG + 0xcc) - #define VE_DEC_MPEG_ROT_CHROMA (VE_ENGINE_DEC_MPEG + 0xd0) - -+#define VE_DEC_H265_DEC_NAL_HDR (VE_ENGINE_DEC_H265 + 0x00) -+ -+#define VE_DEC_H265_DEC_NAL_HDR_NUH_TEMPORAL_ID_PLUS1(v) \ -+ (((v) << 6) & GENMASK(8, 6)) -+#define VE_DEC_H265_DEC_NAL_HDR_NAL_UNIT_TYPE(v) \ -+ ((v) & GENMASK(5, 0)) -+ -+#define VE_DEC_H265_DEC_SPS_HDR (VE_ENGINE_DEC_H265 + 0x04) -+ -+#define VE_DEC_H265_DEC_SPS_HDR_STRONG_INTRA_SMOOTHING_ENABLE_FLAG(v) \ -+ ((v) ? BIT(26) : 0) -+#define VE_DEC_H265_DEC_SPS_HDR_SPS_TEMPORAL_MVP_ENABLED_FLAG(v) \ -+ ((v) ? BIT(25) : 0) -+#define VE_DEC_H265_DEC_SPS_HDR_SAMPLE_ADAPTIVE_OFFSET_ENABLED_FLAG(v) \ -+ ((v) ? BIT(24) : 0) -+#define VE_DEC_H265_DEC_SPS_HDR_AMP_ENABLED_FLAG(v) \ -+ ((v) ? BIT(23) : 0) -+#define VE_DEC_H265_DEC_SPS_HDR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTRA(v) \ -+ (((v) << 20) & GENMASK(22, 20)) -+#define VE_DEC_H265_DEC_SPS_HDR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTER(v) \ -+ (((v) << 17) & GENMASK(19, 17)) -+#define VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_TRANSFORM_BLOCK_SIZE(v) \ -+ (((v) << 15) & GENMASK(16, 15)) -+#define VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_TRANSFORM_BLOCK_SIZE_MINUS2(v) \ -+ (((v) << 13) & GENMASK(14, 13)) -+#define VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE(v) \ -+ (((v) << 11) & GENMASK(12, 11)) -+#define VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_LUMA_CODING_BLOCK_SIZE_MINUS3(v) \ -+ (((v) << 9) & GENMASK(10, 9)) -+#define VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_CHROMA_MINUS8(v) \ -+ (((v) << 6) & GENMASK(8, 6)) -+#define VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_LUMA_MINUS8(v) \ -+ (((v) << 3) & GENMASK(5, 3)) -+#define VE_DEC_H265_DEC_SPS_HDR_SEPARATE_COLOUR_PLANE_FLAG(v) \ -+ ((v) ? BIT(2) : 0) -+#define VE_DEC_H265_DEC_SPS_HDR_CHROMA_FORMAT_IDC(v) \ -+ ((v) & GENMASK(1, 0)) -+ -+#define VE_DEC_H265_DEC_PIC_SIZE (VE_ENGINE_DEC_H265 + 0x08) -+ -+#define VE_DEC_H265_DEC_PIC_SIZE_WIDTH(w) (((w) << 0) & GENMASK(13, 0)) -+#define VE_DEC_H265_DEC_PIC_SIZE_HEIGHT(h) (((h) << 16) & GENMASK(29, 16)) -+ -+#define VE_DEC_H265_DEC_PCM_CTRL (VE_ENGINE_DEC_H265 + 0x0c) -+ -+#define VE_DEC_H265_DEC_PCM_CTRL_PCM_ENABLED_FLAG(v) \ -+ ((v) ? BIT(15) : 0) -+#define VE_DEC_H265_DEC_PCM_CTRL_PCM_LOOP_FILTER_DISABLED_FLAG(v) \ -+ ((v) ? BIT(14) : 0) -+#define VE_DEC_H265_DEC_PCM_CTRL_LOG2_DIFF_MAX_MIN_PCM_LUMA_CODING_BLOCK_SIZE(v) \ -+ (((v) << 10) & GENMASK(11, 10)) -+#define VE_DEC_H265_DEC_PCM_CTRL_LOG2_MIN_PCM_LUMA_CODING_BLOCK_SIZE_MINUS3(v) \ -+ (((v) << 8) & GENMASK(9, 8)) -+#define VE_DEC_H265_DEC_PCM_CTRL_PCM_SAMPLE_BIT_DEPTH_CHROMA_MINUS1(v) \ -+ (((v) << 4) & GENMASK(7, 4)) -+#define VE_DEC_H265_DEC_PCM_CTRL_PCM_SAMPLE_BIT_DEPTH_LUMA_MINUS1(v) \ -+ (((v) << 0) & GENMASK(3, 0)) -+ -+#define VE_DEC_H265_DEC_PPS_CTRL0 (VE_ENGINE_DEC_H265 + 0x10) -+ -+#define VE_DEC_H265_DEC_PPS_CTRL0_PPS_CR_QP_OFFSET(v) \ -+ (((v) << 24) & GENMASK(29, 24)) -+#define VE_DEC_H265_DEC_PPS_CTRL0_PPS_CB_QP_OFFSET(v) \ -+ (((v) << 16) & GENMASK(21, 16)) -+#define VE_DEC_H265_DEC_PPS_CTRL0_INIT_QP_MINUS26(v) \ -+ (((v) << 8) & GENMASK(14, 8)) -+#define VE_DEC_H265_DEC_PPS_CTRL0_DIFF_CU_QP_DELTA_DEPTH(v) \ -+ (((v) << 4) & GENMASK(5, 4)) -+#define VE_DEC_H265_DEC_PPS_CTRL0_CU_QP_DELTA_ENABLED_FLAG(v) \ -+ ((v) ? BIT(3) : 0) -+#define VE_DEC_H265_DEC_PPS_CTRL0_TRANSFORM_SKIP_ENABLED_FLAG(v) \ -+ ((v) ? BIT(2) : 0) -+#define VE_DEC_H265_DEC_PPS_CTRL0_CONSTRAINED_INTRA_PRED_FLAG(v) \ -+ ((v) ? BIT(1) : 0) -+#define VE_DEC_H265_DEC_PPS_CTRL0_SIGN_DATA_HIDING_FLAG(v) \ -+ ((v) ? BIT(0) : 0) -+ -+#define VE_DEC_H265_DEC_PPS_CTRL1 (VE_ENGINE_DEC_H265 + 0x14) -+ -+#define VE_DEC_H265_DEC_PPS_CTRL1_LOG2_PARALLEL_MERGE_LEVEL_MINUS2(v) \ -+ (((v) << 8) & GENMASK(10, 8)) -+#define VE_DEC_H265_DEC_PPS_CTRL1_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG(v) \ -+ ((v) ? BIT(6) : 0) -+#define VE_DEC_H265_DEC_PPS_CTRL1_LOOP_FILTER_ACROSS_TILES_ENABLED_FLAG(v) \ -+ ((v) ? BIT(5) : 0) -+#define VE_DEC_H265_DEC_PPS_CTRL1_ENTROPY_CODING_SYNC_ENABLED_FLAG(v) \ -+ ((v) ? BIT(4) : 0) -+#define VE_DEC_H265_DEC_PPS_CTRL1_TILES_ENABLED_FLAG(v) \ -+ ((v) ? BIT(3) : 0) -+#define VE_DEC_H265_DEC_PPS_CTRL1_TRANSQUANT_BYPASS_ENABLE_FLAG(v) \ -+ ((v) ? BIT(2) : 0) -+#define VE_DEC_H265_DEC_PPS_CTRL1_WEIGHTED_BIPRED_FLAG(v) \ -+ ((v) ? BIT(1) : 0) -+#define VE_DEC_H265_DEC_PPS_CTRL1_WEIGHTED_PRED_FLAG(v) \ -+ ((v) ? BIT(0) : 0) -+ -+#define VE_DEC_H265_SCALING_LIST_CTRL0 (VE_ENGINE_DEC_H265 + 0x18) -+ -+#define VE_DEC_H265_SCALING_LIST_CTRL0_ENABLED_FLAG(v) \ -+ ((v) ? BIT(31) : 0) -+#define VE_DEC_H265_SCALING_LIST_CTRL0_SRAM (0 << 30) -+#define VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT (1 << 30) -+ -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO0 (VE_ENGINE_DEC_H265 + 0x20) -+ -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_PICTURE_TYPE(v) \ -+ (((v) << 28) & GENMASK(29, 28)) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_FIVE_MINUS_MAX_NUM_MERGE_CAND(v) \ -+ (((v) << 24) & GENMASK(26, 24)) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_NUM_REF_IDX_L1_ACTIVE_MINUS1(v) \ -+ (((v) << 20) & GENMASK(23, 20)) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_NUM_REF_IDX_L0_ACTIVE_MINUS1(v) \ -+ (((v) << 16) & GENMASK(19, 16)) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLLOCATED_REF_IDX(v) \ -+ (((v) << 12) & GENMASK(15, 12)) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLLOCATED_FROM_L0_FLAG(v) \ -+ ((v) ? BIT(11) : 0) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_CABAC_INIT_FLAG(v) \ -+ ((v) ? BIT(10) : 0) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_MVD_L1_ZERO_FLAG(v) \ -+ ((v) ? BIT(9) : 0) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_SLICE_SAO_CHROMA_FLAG(v) \ -+ ((v) ? BIT(8) : 0) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_SLICE_SAO_LUMA_FLAG(v) \ -+ ((v) ? BIT(7) : 0) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_SLICE_TEMPORAL_MVP_ENABLE_FLAG(v) \ -+ ((v) ? BIT(6) : 0) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLOUR_PLANE_ID(v) \ -+ (((v) << 4) & GENMASK(5, 4)) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_SLICE_TYPE(v) \ -+ (((v) << 2) & GENMASK(3, 2)) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_DEPENDENT_SLICE_SEGMENT_FLAG(v) \ -+ ((v) ? BIT(1) : 0) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO0_FIRST_SLICE_SEGMENT_IN_PIC_FLAG(v) \ -+ ((v) ? BIT(0) : 0) -+ -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO1 (VE_ENGINE_DEC_H265 + 0x24) -+ -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_TC_OFFSET_DIV2(v) \ -+ (((v) << 28) & GENMASK(31, 28)) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_BETA_OFFSET_DIV2(v) \ -+ (((v) << 24) & GENMASK(27, 24)) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_DEBLOCKING_FILTER_DISABLED_FLAG(v) \ -+ ((v) ? BIT(23) : 0) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG(v) \ -+ ((v) ? BIT(22) : 0) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_POC_BIGEST_IN_RPS_ST(v) \ -+ ((v) ? BIT(21) : 0) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CR_QP_OFFSET(v) \ -+ (((v) << 16) & GENMASK(20, 16)) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CB_QP_OFFSET(v) \ -+ (((v) << 8) & GENMASK(12, 8)) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_QP_DELTA(v) \ -+ ((v) & GENMASK(6, 0)) -+ -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO2 (VE_ENGINE_DEC_H265 + 0x28) -+ -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(v) \ -+ (((v) << 8) & GENMASK(21, 8)) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO2_CHROMA_LOG2_WEIGHT_DENOM(v) \ -+ (((v) << 4) & GENMASK(6, 4)) -+#define VE_DEC_H265_DEC_SLICE_HDR_INFO2_LUMA_LOG2_WEIGHT_DENOM(v) \ -+ (((v) << 0) & GENMASK(2, 0)) -+ -+#define VE_DEC_H265_DEC_CTB_ADDR (VE_ENGINE_DEC_H265 + 0x2c) -+ -+#define VE_DEC_H265_DEC_CTB_ADDR_Y(y) (((y) << 16) & GENMASK(25, 16)) -+#define VE_DEC_H265_DEC_CTB_ADDR_X(x) (((x) << 0) & GENMASK(9, 0)) -+ -+#define VE_DEC_H265_CTRL (VE_ENGINE_DEC_H265 + 0x30) -+ -+#define VE_DEC_H265_CTRL_DDR_CONSISTENCY_EN BIT(31) -+#define VE_DEC_H265_CTRL_STCD_EN BIT(25) -+#define VE_DEC_H265_CTRL_EPTB_DEC_BYPASS_EN BIT(24) -+#define VE_DEC_H265_CTRL_TQ_BYPASS_EN BIT(12) -+#define VE_DEC_H265_CTRL_VLD_BYPASS_EN BIT(11) -+#define VE_DEC_H265_CTRL_NCRI_CACHE_DISABLE BIT(10) -+#define VE_DEC_H265_CTRL_ROTATE_SCALE_OUT_EN BIT(9) -+#define VE_DEC_H265_CTRL_MC_NO_WRITEBACK BIT(8) -+#define VE_DEC_H265_CTRL_VLD_DATA_REQ_IRQ_EN BIT(2) -+#define VE_DEC_H265_CTRL_ERROR_IRQ_EN BIT(1) -+#define VE_DEC_H265_CTRL_FINISH_IRQ_EN BIT(0) -+#define VE_DEC_H265_CTRL_IRQ_MASK \ -+ (VE_DEC_H265_CTRL_FINISH_IRQ_EN | VE_DEC_H265_CTRL_ERROR_IRQ_EN | \ -+ VE_DEC_H265_CTRL_VLD_DATA_REQ_IRQ_EN) -+ -+#define VE_DEC_H265_TRIGGER (VE_ENGINE_DEC_H265 + 0x34) -+ -+#define VE_DEC_H265_TRIGGER_STCD_VC1 (0x02 << 4) -+#define VE_DEC_H265_TRIGGER_STCD_AVS (0x01 << 4) -+#define VE_DEC_H265_TRIGGER_STCD_HEVC (0x00 << 4) -+#define VE_DEC_H265_TRIGGER_DEC_SLICE (0x08 << 0) -+#define VE_DEC_H265_TRIGGER_INIT_SWDEC (0x07 << 0) -+#define VE_DEC_H265_TRIGGER_BYTE_ALIGN (0x06 << 0) -+#define VE_DEC_H265_TRIGGER_GET_VLCUE (0x05 << 0) -+#define VE_DEC_H265_TRIGGER_GET_VLCSE (0x04 << 0) -+#define VE_DEC_H265_TRIGGER_FLUSH_BITS (0x03 << 0) -+#define VE_DEC_H265_TRIGGER_GET_BITS (0x02 << 0) -+#define VE_DEC_H265_TRIGGER_SHOW_BITS (0x01 << 0) -+ -+#define VE_DEC_H265_STATUS (VE_ENGINE_DEC_H265 + 0x38) -+ -+#define VE_DEC_H265_STATUS_STCD BIT(24) -+#define VE_DEC_H265_STATUS_STCD_BUSY BIT(21) -+#define VE_DEC_H265_STATUS_WB_BUSY BIT(20) -+#define VE_DEC_H265_STATUS_BS_DMA_BUSY BIT(19) -+#define VE_DEC_H265_STATUS_IQIT_BUSY BIT(18) -+#define VE_DEC_H265_STATUS_INTER_BUSY BIT(17) -+#define VE_DEC_H265_STATUS_MORE_DATA BIT(16) -+#define VE_DEC_H265_STATUS_VLD_BUSY BIT(14) -+#define VE_DEC_H265_STATUS_DEBLOCKING_BUSY BIT(13) -+#define VE_DEC_H265_STATUS_DEBLOCKING_DRAM_BUSY BIT(12) -+#define VE_DEC_H265_STATUS_INTRA_BUSY BIT(11) -+#define VE_DEC_H265_STATUS_SAO_BUSY BIT(10) -+#define VE_DEC_H265_STATUS_MVP_BUSY BIT(9) -+#define VE_DEC_H265_STATUS_SWDEC_BUSY BIT(8) -+#define VE_DEC_H265_STATUS_OVER_TIME BIT(3) -+#define VE_DEC_H265_STATUS_VLD_DATA_REQ BIT(2) -+#define VE_DEC_H265_STATUS_ERROR BIT(1) -+#define VE_DEC_H265_STATUS_SUCCESS BIT(0) -+#define VE_DEC_H265_STATUS_STCD_TYPE_MASK GENMASK(23, 22) -+#define VE_DEC_H265_STATUS_CHECK_MASK \ -+ (VE_DEC_H265_STATUS_SUCCESS | VE_DEC_H265_STATUS_ERROR | \ -+ VE_DEC_H265_STATUS_VLD_DATA_REQ) -+#define VE_DEC_H265_STATUS_CHECK_ERROR \ -+ (VE_DEC_H265_STATUS_ERROR | VE_DEC_H265_STATUS_VLD_DATA_REQ) -+ -+#define VE_DEC_H265_DEC_CTB_NUM (VE_ENGINE_DEC_H265 + 0x3c) -+ -+#define VE_DEC_H265_BITS_ADDR (VE_ENGINE_DEC_H265 + 0x40) -+ -+#define VE_DEC_H265_BITS_ADDR_FIRST_SLICE_DATA BIT(30) -+#define VE_DEC_H265_BITS_ADDR_LAST_SLICE_DATA BIT(29) -+#define VE_DEC_H265_BITS_ADDR_VALID_SLICE_DATA BIT(28) -+#define VE_DEC_H265_BITS_ADDR_BASE(a) (((a) >> 8) & GENMASK(27, 0)) -+ -+#define VE_DEC_H265_BITS_OFFSET (VE_ENGINE_DEC_H265 + 0x44) -+#define VE_DEC_H265_BITS_LEN (VE_ENGINE_DEC_H265 + 0x48) -+ -+#define VE_DEC_H265_BITS_END_ADDR (VE_ENGINE_DEC_H265 + 0x4c) -+ -+#define VE_DEC_H265_BITS_END_ADDR_BASE(a) ((a) >> 8) -+ -+#define VE_DEC_H265_SDRT_CTRL (VE_ENGINE_DEC_H265 + 0x50) -+#define VE_DEC_H265_SDRT_LUMA_ADDR (VE_ENGINE_DEC_H265 + 0x54) -+#define VE_DEC_H265_SDRT_CHROMA_ADDR (VE_ENGINE_DEC_H265 + 0x58) -+ -+#define VE_DEC_H265_OUTPUT_FRAME_IDX (VE_ENGINE_DEC_H265 + 0x5c) -+ -+#define VE_DEC_H265_NEIGHBOR_INFO_ADDR (VE_ENGINE_DEC_H265 + 0x60) -+ -+#define VE_DEC_H265_NEIGHBOR_INFO_ADDR_BASE(a) ((a) >> 8) -+ -+#define VE_DEC_H265_ENTRY_POINT_OFFSET_ADDR (VE_ENGINE_DEC_H265 + 0x64) -+#define VE_DEC_H265_TILE_START_CTB (VE_ENGINE_DEC_H265 + 0x68) -+#define VE_DEC_H265_TILE_END_CTB (VE_ENGINE_DEC_H265 + 0x6c) -+ -+#define VE_DEC_H265_LOW_ADDR (VE_ENGINE_DEC_H265 + 0x80) -+ -+#define VE_DEC_H265_LOW_ADDR_PRIMARY_CHROMA(a) \ -+ (((a) << 24) & GENMASK(31, 24)) -+#define VE_DEC_H265_LOW_ADDR_SECONDARY_CHROMA(a) \ -+ (((a) << 16) & GENMASK(23, 16)) -+#define VE_DEC_H265_LOW_ADDR_ENTRY_POINTS_BUF(a) \ -+ (((a) << 0) & GENMASK(7, 0)) -+ -+#define VE_DEC_H265_SRAM_OFFSET (VE_ENGINE_DEC_H265 + 0xe0) -+ -+#define VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L0 0x00 -+#define VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L0 0x20 -+#define VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L1 0x60 -+#define VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L1 0x80 -+#define VE_DEC_H265_SRAM_OFFSET_FRAME_INFO 0x400 -+#define VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT 0x20 -+#define VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS 0x800 -+#define VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST0 0xc00 -+#define VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST1 0xc10 -+ -+#define VE_DEC_H265_SRAM_DATA (VE_ENGINE_DEC_H265 + 0xe4) -+ -+#define VE_DEC_H265_SRAM_DATA_ADDR_BASE(a) ((a) >> 8) -+#define VE_DEC_H265_SRAM_REF_PIC_LIST_LT_REF BIT(7) -+ - #define VE_H264_SPS 0x200 - #define VE_H264_SPS_MBS_ONLY BIT(18) - #define VE_H264_SPS_MB_ADAPTIVE_FRAME_FIELD BIT(17) -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c -index e2b530b1a956..6cc65d85cf98 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c -@@ -41,6 +41,11 @@ static struct cedrus_format cedrus_formats[] = { - .pixelformat = V4L2_PIX_FMT_H264_SLICE_RAW, - .directions = CEDRUS_DECODE_SRC, - }, -+ { -+ .pixelformat = V4L2_PIX_FMT_HEVC_SLICE, -+ .directions = CEDRUS_DECODE_SRC, -+ .capabilities = CEDRUS_CAPABILITY_H265_DEC, -+ }, - { - .pixelformat = V4L2_PIX_FMT_SUNXI_TILED_NV12, - .directions = CEDRUS_DECODE_DST, -@@ -105,6 +110,7 @@ static void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt) - switch (pix_fmt->pixelformat) { - case V4L2_PIX_FMT_MPEG2_SLICE: - case V4L2_PIX_FMT_H264_SLICE: -+ case V4L2_PIX_FMT_HEVC_SLICE: - /* Zero bytes per line for encoded source. */ - bytesperline = 0; - -@@ -473,6 +479,10 @@ static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count) - ctx->current_codec = CEDRUS_CODEC_H264; - break; - -+ case V4L2_PIX_FMT_HEVC_SLICE: -+ ctx->current_codec = CEDRUS_CODEC_H265; -+ break; -+ - default: - return -EINVAL; - } --- -2.21.0 diff --git a/projects/Allwinner/patches/linux/0005-cedrus-improvements.patch b/projects/Allwinner/patches/linux/0005-cedrus-improvements.patch new file mode 100644 index 00000000000..adc90297778 --- /dev/null +++ b/projects/Allwinner/patches/linux/0005-cedrus-improvements.patch @@ -0,0 +1,1407 @@ +From 4d25b2ae236bf42f5f9ef1d57cbc2523222a4422 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 26 Oct 2019 13:55:15 +0200 +Subject: [PATCH 04/14] media: uapi: hevc: Add scaling matrix control + +HEVC has a scaling matrix concept. Add support for it. + +Signed-off-by: Jernej Skrabec +--- + .../media/uapi/v4l/ext-ctrls-codec.rst | 41 +++++++++++++++++++ + .../media/uapi/v4l/pixfmt-compressed.rst | 1 + + drivers/media/v4l2-core/v4l2-ctrls.c | 10 +++++ + include/media/hevc-ctrls.h | 11 +++++ + 4 files changed, 63 insertions(+) + +diff --git a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst +index a1209f68c5e8..382e85e16444 100644 +--- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst ++++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst +@@ -4176,6 +4176,47 @@ enum v4l2_mpeg_video_hevc_size_of_length_field - + - ``padding[6]`` + - Applications and drivers must set this to zero. + ++``V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (struct)`` ++ Specifies the scaling matrix (as extracted from the bitstream) for ++ the associated HEVC slice data. The bitstream parameters are ++ defined according to :ref:`hevc`, section 7.4.5 "Scaling list ++ data semantics". For further documentation, refer to the above ++ specification, unless there is an explicit comment stating ++ otherwise. ++ ++ .. note:: ++ ++ This compound control is not yet part of the public kernel API and ++ it is expected to change. ++ ++.. c:type:: v4l2_ctrl_hevc_scaling_matrix ++ ++.. cssclass:: longtable ++ ++.. flat-table:: struct v4l2_ctrl_hevc_scaling_matrix ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u8 ++ - ``scaling_list_4x4[6][16]`` ++ - ++ * - __u8 ++ - ``scaling_list_8x8[6][64]`` ++ - ++ * - __u8 ++ - ``scaling_list_16x16[6][64]`` ++ - ++ * - __u8 ++ - ``scaling_list_32x32[2][64]`` ++ - ++ * - __u8 ++ - ``scaling_list_dc_coef_16x16[6]`` ++ - ++ * - __u8 ++ - ``scaling_list_dc_coef_32x32[2]`` ++ - ++ + ``V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (enum)`` + Specifies the decoding mode to use. Currently exposes slice-based and + frame-based decoding but new modes might be added later on. +diff --git a/Documentation/media/uapi/v4l/pixfmt-compressed.rst b/Documentation/media/uapi/v4l/pixfmt-compressed.rst +index 561bda112809..3aabc322daa4 100644 +--- a/Documentation/media/uapi/v4l/pixfmt-compressed.rst ++++ b/Documentation/media/uapi/v4l/pixfmt-compressed.rst +@@ -207,6 +207,7 @@ Compressed Formats + * ``V4L2_CID_MPEG_VIDEO_HEVC_SPS`` + * ``V4L2_CID_MPEG_VIDEO_HEVC_PPS`` + * ``V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS`` ++ * ``V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX`` + See the :ref:`associated Codec Control IDs `. + Buffers associated with this pixel format must contain the appropriate + number of macroblocks to decode a full corresponding frame. +diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c +index b4caf2d4d076..2803165cbc6a 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -975,6 +975,7 @@ const char *v4l2_ctrl_get_name(u32 id) + case V4L2_CID_MPEG_VIDEO_HEVC_SPS: return "HEVC Sequence Parameter Set"; + case V4L2_CID_MPEG_VIDEO_HEVC_PPS: return "HEVC Picture Parameter Set"; + case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: return "HEVC Slice Parameters"; ++ case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX: return "HEVC Scaling Matrix"; + case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE: return "HEVC Decode Mode"; + case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE: return "HEVC Start Code"; + +@@ -1407,6 +1408,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, + case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: + *type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS; + break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX: ++ *type = V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX; ++ break; + case V4L2_CID_UNIT_CELL_SIZE: + *type = V4L2_CTRL_TYPE_AREA; + *flags |= V4L2_CTRL_FLAG_READ_ONLY; +@@ -1856,6 +1860,9 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + zero_padding(*p_hevc_slice_params); + break; + ++ case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX: ++ break; ++ + case V4L2_CTRL_TYPE_AREA: + area = p; + if (!area->width || !area->height) +@@ -2545,6 +2552,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, + case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: + elem_size = sizeof(struct v4l2_ctrl_hevc_slice_params); + break; ++ case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX: ++ elem_size = sizeof(struct v4l2_ctrl_hevc_scaling_matrix); ++ break; + case V4L2_CTRL_TYPE_AREA: + elem_size = sizeof(struct v4l2_area); + break; +diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h +index 1009cf0891cc..1592e52c3614 100644 +--- a/include/media/hevc-ctrls.h ++++ b/include/media/hevc-ctrls.h +@@ -19,6 +19,7 @@ + #define V4L2_CID_MPEG_VIDEO_HEVC_SPS (V4L2_CID_MPEG_BASE + 1008) + #define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_MPEG_BASE + 1009) + #define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_MPEG_BASE + 1010) ++#define V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (V4L2_CID_MPEG_BASE + 1011) + #define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (V4L2_CID_MPEG_BASE + 1015) + #define V4L2_CID_MPEG_VIDEO_HEVC_START_CODE (V4L2_CID_MPEG_BASE + 1016) + +@@ -26,6 +27,7 @@ + #define V4L2_CTRL_TYPE_HEVC_SPS 0x0120 + #define V4L2_CTRL_TYPE_HEVC_PPS 0x0121 + #define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0122 ++#define V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX 0x0123 + + enum v4l2_mpeg_video_hevc_decode_mode { + V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED, +@@ -209,4 +211,13 @@ struct v4l2_ctrl_hevc_slice_params { + __u64 flags; + }; + ++struct v4l2_ctrl_hevc_scaling_matrix { ++ __u8 scaling_list_4x4[6][16]; ++ __u8 scaling_list_8x8[6][64]; ++ __u8 scaling_list_16x16[6][64]; ++ __u8 scaling_list_32x32[2][64]; ++ __u8 scaling_list_dc_coef_16x16[6]; ++ __u8 scaling_list_dc_coef_32x32[2]; ++}; ++ + #endif +-- +2.24.0 + + +From 000a33e20cc53fa82e3bc116d411135e93d5ab95 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 26 Oct 2019 13:58:49 +0200 +Subject: [PATCH 05/14] media: cedrus: hevc: Add support for scaling matrix + +HEVC frames may use scaling list feature. Add support for it. + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus.c | 7 ++ + drivers/staging/media/sunxi/cedrus/cedrus.h | 1 + + .../staging/media/sunxi/cedrus/cedrus_dec.c | 2 + + .../staging/media/sunxi/cedrus/cedrus_h265.c | 70 ++++++++++++++++++- + .../staging/media/sunxi/cedrus/cedrus_regs.h | 2 + + 5 files changed, 81 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c +index c6ddd46eff82..bf68bc6b20c8 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.c +@@ -116,6 +116,13 @@ static const struct cedrus_control cedrus_controls[] = { + .codec = CEDRUS_CODEC_H265, + .required = true, + }, ++ { ++ .cfg = { ++ .id = V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX, ++ }, ++ .codec = CEDRUS_CODEC_H265, ++ .required = true, ++ }, + { + .cfg = { + .id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE, +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h +index 96765555ab8a..d945f4f0ff2d 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -73,6 +73,7 @@ struct cedrus_h265_run { + const struct v4l2_ctrl_hevc_sps *sps; + const struct v4l2_ctrl_hevc_pps *pps; + const struct v4l2_ctrl_hevc_slice_params *slice_params; ++ const struct v4l2_ctrl_hevc_scaling_matrix *scaling_matrix; + }; + + struct cedrus_run { +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c +index 4a2fc33a1d79..327ed6c264dc 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c +@@ -66,6 +66,8 @@ void cedrus_device_run(void *priv) + V4L2_CID_MPEG_VIDEO_HEVC_PPS); + run.h265.slice_params = cedrus_find_control_data(ctx, + V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS); ++ run.h265.scaling_matrix = cedrus_find_control_data(ctx, ++ V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX); + break; + + default: +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +index 6945dc74e1d7..888bfd5ca224 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -220,6 +220,69 @@ static void cedrus_h265_pred_weight_write(struct cedrus_dev *dev, + } + } + ++static void cedrus_h265_write_scaling_list(struct cedrus_ctx *ctx, ++ struct cedrus_run *run) ++{ ++ const struct v4l2_ctrl_hevc_scaling_matrix *scaling; ++ struct cedrus_dev *dev = ctx->dev; ++ u32 i, j, k, val; ++ ++ scaling = run->h265.scaling_matrix; ++ ++ cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF0, ++ (scaling->scaling_list_dc_coef_32x32[1] << 24) | ++ (scaling->scaling_list_dc_coef_32x32[0] << 16) | ++ (scaling->scaling_list_dc_coef_16x16[1] << 8) | ++ (scaling->scaling_list_dc_coef_16x16[0] << 0)); ++ ++ cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF1, ++ (scaling->scaling_list_dc_coef_16x16[5] << 24) | ++ (scaling->scaling_list_dc_coef_16x16[4] << 16) | ++ (scaling->scaling_list_dc_coef_16x16[3] << 8) | ++ (scaling->scaling_list_dc_coef_16x16[2] << 0)); ++ ++ cedrus_h265_sram_write_offset(dev, VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS); ++ ++ for (i = 0; i < 6; i++) ++ for (j = 0; j < 8; j++) ++ for (k = 0; k < 8; k += 4) { ++ val = ((u32)scaling->scaling_list_8x8[i][j + (k + 3) * 8] << 24) | ++ ((u32)scaling->scaling_list_8x8[i][j + (k + 2) * 8] << 16) | ++ ((u32)scaling->scaling_list_8x8[i][j + (k + 1) * 8] << 8) | ++ scaling->scaling_list_8x8[i][j + k * 8]; ++ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); ++ } ++ ++ for (i = 0; i < 2; i++) ++ for (j = 0; j < 8; j++) ++ for (k = 0; k < 8; k += 4) { ++ val = ((u32)scaling->scaling_list_32x32[i][j + (k + 3) * 8] << 24) | ++ ((u32)scaling->scaling_list_32x32[i][j + (k + 2) * 8] << 16) | ++ ((u32)scaling->scaling_list_32x32[i][j + (k + 1) * 8] << 8) | ++ scaling->scaling_list_32x32[i][j + k * 8]; ++ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); ++ } ++ ++ for (i = 0; i < 6; i++) ++ for (j = 0; j < 8; j++) ++ for (k = 0; k < 8; k += 4) { ++ val = ((u32)scaling->scaling_list_16x16[i][j + (k + 3) * 8] << 24) | ++ ((u32)scaling->scaling_list_16x16[i][j + (k + 2) * 8] << 16) | ++ ((u32)scaling->scaling_list_16x16[i][j + (k + 1) * 8] << 8) | ++ scaling->scaling_list_16x16[i][j + k * 8]; ++ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); ++ } ++ ++ for (i = 0; i < 6; i++) ++ for (j = 0; j < 4; j++) { ++ val = ((u32)scaling->scaling_list_4x4[i][j + 12] << 24) | ++ ((u32)scaling->scaling_list_4x4[i][j + 8] << 16) | ++ ((u32)scaling->scaling_list_4x4[i][j + 4] << 8) | ++ scaling->scaling_list_4x4[i][j]; ++ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); ++ } ++} ++ + static void cedrus_h265_setup(struct cedrus_ctx *ctx, + struct cedrus_run *run) + { +@@ -499,7 +562,12 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + + /* Scaling list. */ + +- reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT; ++ if (sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED) { ++ cedrus_h265_write_scaling_list(ctx, run); ++ reg = VE_DEC_H265_SCALING_LIST_CTRL0_FLAG_ENABLED; ++ } else { ++ reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT; ++ } + cedrus_write(dev, VE_DEC_H265_SCALING_LIST_CTRL0, reg); + + /* Neightbor information address. */ +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +index 7beb03d3bb39..0d9449fe2b28 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +@@ -492,6 +492,8 @@ + #define VE_DEC_H265_ENTRY_POINT_OFFSET_ADDR (VE_ENGINE_DEC_H265 + 0x64) + #define VE_DEC_H265_TILE_START_CTB (VE_ENGINE_DEC_H265 + 0x68) + #define VE_DEC_H265_TILE_END_CTB (VE_ENGINE_DEC_H265 + 0x6c) ++#define VE_DEC_H265_SCALING_LIST_DC_COEF0 (VE_ENGINE_DEC_H265 + 0x78) ++#define VE_DEC_H265_SCALING_LIST_DC_COEF1 (VE_ENGINE_DEC_H265 + 0x7c) + + #define VE_DEC_H265_LOW_ADDR (VE_ENGINE_DEC_H265 + 0x80) + +-- +2.24.0 + + +From 48f70ba58e4df3bd9b9cb9c7969ba93f95e25e75 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 26 Oct 2019 15:42:28 +0200 +Subject: [PATCH 06/14] media: uapi: hevc: Add segment address field + +If HEVC frame consists of multiple slices, segment address has to be +known in order to properly decode it. + +Add segment address field to slice parameters. + +Signed-off-by: Jernej Skrabec +--- + Documentation/media/uapi/v4l/ext-ctrls-codec.rst | 5 ++++- + include/media/hevc-ctrls.h | 5 ++++- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst +index 382e85e16444..99e4a7099614 100644 +--- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst ++++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst +@@ -3971,6 +3971,9 @@ enum v4l2_mpeg_video_hevc_size_of_length_field - + * - __u32 + - ``data_bit_offset`` + - Offset (in bits) to the video data in the current slice data. ++ * - __u32 ++ - ``slice_segment_addr`` ++ - + * - __u8 + - ``nal_unit_type`` + - +@@ -4048,7 +4051,7 @@ enum v4l2_mpeg_video_hevc_size_of_length_field - + - ``num_rps_poc_lt_curr`` + - The number of reference pictures in the long-term set. + * - __u8 +- - ``padding[7]`` ++ - ``padding[5]`` + - Applications and drivers must set this to zero. + * - struct :c:type:`v4l2_hevc_dpb_entry` + - ``dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` +diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h +index 1592e52c3614..3e2e32098312 100644 +--- a/include/media/hevc-ctrls.h ++++ b/include/media/hevc-ctrls.h +@@ -167,6 +167,9 @@ struct v4l2_ctrl_hevc_slice_params { + __u32 bit_size; + __u32 data_bit_offset; + ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ __u32 slice_segment_addr; ++ + /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ + __u8 nal_unit_type; + __u8 nuh_temporal_id_plus1; +@@ -200,7 +203,7 @@ struct v4l2_ctrl_hevc_slice_params { + __u8 num_rps_poc_st_curr_after; + __u8 num_rps_poc_lt_curr; + +- __u8 padding; ++ __u8 padding[5]; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ + struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; +-- +2.24.0 + + +From 468a7019d3475a6dbdf368519c75f9e6625f2a1a Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 26 Oct 2019 15:44:15 +0200 +Subject: [PATCH 07/14] media: cedrus: hevc: Add support for multiple slices + +Now that segment address is available, support for multi-slice frames +can be easily added. + +Signed-off-by: Jernej Skrabec +--- + .../staging/media/sunxi/cedrus/cedrus_h265.c | 26 ++++++++++++------- + .../staging/media/sunxi/cedrus/cedrus_video.c | 1 + + 2 files changed, 17 insertions(+), 10 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +index 888bfd5ca224..109d3289418c 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -291,6 +291,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + const struct v4l2_ctrl_hevc_pps *pps; + const struct v4l2_ctrl_hevc_slice_params *slice_params; + const struct v4l2_hevc_pred_weight_table *pred_weight_table; ++ unsigned int width_in_ctb_luma, ctb_size_luma; ++ unsigned int log2_max_luma_coding_block_size; + dma_addr_t src_buf_addr; + dma_addr_t src_buf_end_addr; + u32 chroma_log2_weight_denom; +@@ -303,15 +305,17 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + slice_params = run->h265.slice_params; + pred_weight_table = &slice_params->pred_weight_table; + ++ log2_max_luma_coding_block_size = ++ sps->log2_min_luma_coding_block_size_minus3 + 3 + ++ sps->log2_diff_max_min_luma_coding_block_size; ++ ctb_size_luma = 1UL << log2_max_luma_coding_block_size; ++ width_in_ctb_luma = ++ DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma); ++ + /* MV column buffer size and allocation. */ + if (!ctx->codec.h265.mv_col_buf_size) { + unsigned int num_buffers = + run->dst->vb2_buf.vb2_queue->num_buffers; +- unsigned int log2_max_luma_coding_block_size = +- sps->log2_min_luma_coding_block_size_minus3 + 3 + +- sps->log2_diff_max_min_luma_coding_block_size; +- unsigned int ctb_size_luma = +- 1UL << log2_max_luma_coding_block_size; + + /* + * Each CTB requires a MV col buffer with a specific unit size. +@@ -366,15 +370,17 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_end_addr); + cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg); + +- /* Coding tree block address: start at the beginning. */ +- reg = VE_DEC_H265_DEC_CTB_ADDR_X(0) | VE_DEC_H265_DEC_CTB_ADDR_Y(0); ++ /* Coding tree block address */ ++ reg = VE_DEC_H265_DEC_CTB_ADDR_X(slice_params->slice_segment_addr % width_in_ctb_luma); ++ reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(slice_params->slice_segment_addr / width_in_ctb_luma); + cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg); + + cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0); + cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0); + + /* Clear the number of correctly-decoded coding tree blocks. */ +- cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0); ++ if (ctx->fh.m2m_ctx->new_frame) ++ cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0); + + /* Initialize bitstream access. */ + cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_INIT_SWDEC); +@@ -523,8 +529,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT, + pps->flags); + +- /* FIXME: For multi-slice support. */ +- reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC; ++ if (ctx->fh.m2m_ctx->new_frame) ++ reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC; + + cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO0, reg); + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +index 15cf1f10221b..497b1199d3fe 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +@@ -311,6 +311,7 @@ static int cedrus_s_fmt_vid_out(struct file *file, void *priv, + + switch (ctx->src_fmt.pixelformat) { + case V4L2_PIX_FMT_H264_SLICE: ++ case V4L2_PIX_FMT_HEVC_SLICE: + vq->subsystem_flags |= + VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF; + break; +-- +2.24.0 + + +From 3be57e9b0d05bbe59aa60eb037d46b523a8a4103 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sun, 3 Nov 2019 12:36:52 +0100 +Subject: [PATCH 08/14] media: cedrus: Fix decoding for some HEVC videos + +It seems that for some HEVC videos at least one bitstream parsing +trigger must be called in order to be decoded correctly. There is no +explanation why this helps, but it was observed that several videos +with this fix are now decoded correctly and there is no regression with +others. + +Without this fix, those same videos totaly crash HEVC decoder (others +are unaffected). After decoding those problematic videos, HEVC decoder +always returns only green image (all zeros). Only complete HW reset +helps. + +This fix is similar to that for H264. + +Signed-off-by: Jernej Skrabec +--- + .../staging/media/sunxi/cedrus/cedrus_h265.c | 25 ++++++++++++++++--- + .../staging/media/sunxi/cedrus/cedrus_regs.h | 1 + + 2 files changed, 23 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +index 109d3289418c..5a207f1e137c 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -7,6 +7,7 @@ + * Copyright (C) 2018 Bootlin + */ + ++#include + #include + + #include +@@ -283,6 +284,23 @@ static void cedrus_h265_write_scaling_list(struct cedrus_ctx *ctx, + } + } + ++static void cedrus_h265_skip_bits(struct cedrus_dev *dev, int num) ++{ ++ int count = 0; ++ ++ while (count < num) { ++ int tmp = min(num - count, 32); ++ ++ cedrus_write(dev, VE_DEC_H265_TRIGGER, ++ VE_DEC_H265_TRIGGER_FLUSH_BITS | ++ VE_DEC_H265_TRIGGER_TYPE_N_BITS(tmp)); ++ while (cedrus_read(dev, VE_DEC_H265_STATUS) & VE_DEC_H265_STATUS_VLD_BUSY) ++ udelay(1); ++ ++ count += tmp; ++ } ++} ++ + static void cedrus_h265_setup(struct cedrus_ctx *ctx, + struct cedrus_run *run) + { +@@ -347,10 +365,9 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + + /* Source offset and length in bits. */ + +- reg = slice_params->data_bit_offset; +- cedrus_write(dev, VE_DEC_H265_BITS_OFFSET, reg); ++ cedrus_write(dev, VE_DEC_H265_BITS_OFFSET, 0); + +- reg = slice_params->bit_size - slice_params->data_bit_offset; ++ reg = slice_params->bit_size; + cedrus_write(dev, VE_DEC_H265_BITS_LEN, reg); + + /* Source beginning and end addresses. */ +@@ -385,6 +402,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + /* Initialize bitstream access. */ + cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_INIT_SWDEC); + ++ cedrus_h265_skip_bits(dev, slice_params->data_bit_offset); ++ + /* Bitstream parameters. */ + + reg = VE_DEC_H265_DEC_NAL_HDR_NAL_UNIT_TYPE(slice_params->nal_unit_type) | +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +index 0d9449fe2b28..df1cceef8d93 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +@@ -424,6 +424,7 @@ + + #define VE_DEC_H265_TRIGGER (VE_ENGINE_DEC_H265 + 0x34) + ++#define VE_DEC_H265_TRIGGER_TYPE_N_BITS(x) (((x) & 0x3f) << 8) + #define VE_DEC_H265_TRIGGER_STCD_VC1 (0x02 << 4) + #define VE_DEC_H265_TRIGGER_STCD_AVS (0x01 << 4) + #define VE_DEC_H265_TRIGGER_STCD_HEVC (0x00 << 4) +-- +2.24.0 + + +From cf4ceb6095f67569dc22b09a150176d42ded09a5 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 26 Oct 2019 21:23:55 +0200 +Subject: [PATCH 09/14] media: cedrus: hevc: tiles hack + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus.h | 2 + + .../staging/media/sunxi/cedrus/cedrus_h265.c | 93 +++++++++++++++++-- + include/media/hevc-ctrls.h | 5 +- + 3 files changed, 93 insertions(+), 7 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h +index d945f4f0ff2d..1204e32d83bc 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -134,6 +134,8 @@ struct cedrus_ctx { + ssize_t mv_col_buf_unit_size; + void *neighbor_info_buf; + dma_addr_t neighbor_info_buf_addr; ++ void *entry_points_buf; ++ dma_addr_t entry_points_buf_addr; + } h265; + } codec; + }; +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +index 5a207f1e137c..97dce6ffbbc5 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -284,6 +284,61 @@ static void cedrus_h265_write_scaling_list(struct cedrus_ctx *ctx, + } + } + ++static void write_entry_point_list(struct cedrus_ctx *ctx, ++ struct cedrus_run *run, ++ unsigned int ctb_addr_x, ++ unsigned int ctb_addr_y) ++{ ++ const struct v4l2_ctrl_hevc_slice_params *slice_params; ++ const struct v4l2_ctrl_hevc_pps *pps; ++ struct cedrus_dev *dev = ctx->dev; ++ int i, x, tx, y, ty; ++ u32 *entry_points; ++ ++ pps = run->h265.pps; ++ slice_params = run->h265.slice_params; ++ ++ for (x = 0, tx = 0; tx < pps->num_tile_columns_minus1 + 1; tx++) { ++ if (x + pps->column_width_minus1[tx] + 1 > ctb_addr_x) ++ break; ++ ++ x += pps->column_width_minus1[tx] + 1; ++ } ++ ++ for (y = 0, ty = 0; ty < pps->num_tile_rows_minus1 + 1; ty++) { ++ if (y + pps->row_height_minus1[ty] + 1 > ctb_addr_y) ++ break; ++ ++ y += pps->row_height_minus1[ty] + 1; ++ } ++ ++ cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, (y << 16) | (x << 0)); ++ cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, ++ ((y + pps->row_height_minus1[ty]) << 16) | ++ ((x + pps->column_width_minus1[tx]) << 0)); ++ ++ entry_points = ctx->codec.h265.entry_points_buf; ++ if (pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED) { ++ for (i = 0; i < slice_params->num_entry_point_offsets; i++) ++ entry_points[i] = slice_params->entry_point_offset_minus1[i] + 1; ++ } else { ++ for (i = 0; i < slice_params->num_entry_point_offsets; i++) { ++ if (tx + 1 >= pps->num_tile_columns_minus1 + 1) { ++ x = 0; ++ tx = 0; ++ y += pps->row_height_minus1[ty++] + 1; ++ } else { ++ x += pps->column_width_minus1[tx++] + 1; ++ } ++ ++ entry_points[i * 4 + 0] = slice_params->entry_point_offset_minus1[i] + 1; ++ entry_points[i * 4 + 1] = 0x0; ++ entry_points[i * 4 + 2] = (y << 16) | (x << 0); ++ entry_points[i * 4 + 3] = ((y + pps->row_height_minus1[ty]) << 16) | ((x + pps->column_width_minus1[tx]) << 0); ++ } ++ } ++} ++ + static void cedrus_h265_skip_bits(struct cedrus_dev *dev, int num) + { + int count = 0; +@@ -311,6 +366,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + const struct v4l2_hevc_pred_weight_table *pred_weight_table; + unsigned int width_in_ctb_luma, ctb_size_luma; + unsigned int log2_max_luma_coding_block_size; ++ unsigned int ctb_addr_x, ctb_addr_y; + dma_addr_t src_buf_addr; + dma_addr_t src_buf_end_addr; + u32 chroma_log2_weight_denom; +@@ -388,12 +444,19 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg); + + /* Coding tree block address */ +- reg = VE_DEC_H265_DEC_CTB_ADDR_X(slice_params->slice_segment_addr % width_in_ctb_luma); +- reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(slice_params->slice_segment_addr / width_in_ctb_luma); ++ ctb_addr_x = slice_params->slice_segment_addr % width_in_ctb_luma; ++ ctb_addr_y = slice_params->slice_segment_addr / width_in_ctb_luma; ++ reg = VE_DEC_H265_DEC_CTB_ADDR_X(ctb_addr_x); ++ reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(ctb_addr_y); + cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg); + +- cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0); +- cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0); ++ if ((pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED) || ++ (pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED)) { ++ write_entry_point_list(ctx, run, ctb_addr_x, ctb_addr_y); ++ } else { ++ cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0); ++ cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0); ++ } + + /* Clear the number of correctly-decoded coding tree blocks. */ + if (ctx->fh.m2m_ctx->new_frame) +@@ -496,7 +559,9 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED, + pps->flags); + +- /* TODO: VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TILES_ENABLED */ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TILES_ENABLED, ++ V4L2_HEVC_PPS_FLAG_TILES_ENABLED, ++ pps->flags); + + reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TRANSQUANT_BYPASS_ENABLED, + V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED, +@@ -572,12 +637,14 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + + chroma_log2_weight_denom = pred_weight_table->luma_log2_weight_denom + + pred_weight_table->delta_chroma_log2_weight_denom; +- reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(0) | ++ reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(slice_params->num_entry_point_offsets) | + VE_DEC_H265_DEC_SLICE_HDR_INFO2_CHROMA_LOG2_WEIGHT_DENOM(chroma_log2_weight_denom) | + VE_DEC_H265_DEC_SLICE_HDR_INFO2_LUMA_LOG2_WEIGHT_DENOM(pred_weight_table->luma_log2_weight_denom); + + cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO2, reg); + ++ cedrus_write(dev, VE_DEC_H265_ENTRY_POINT_OFFSET_ADDR, ctx->codec.h265.entry_points_buf_addr >> 8); ++ + /* Decoded picture size. */ + + reg = VE_DEC_H265_DEC_PIC_SIZE_WIDTH(ctx->src_fmt.width) | +@@ -671,6 +738,17 @@ static int cedrus_h265_start(struct cedrus_ctx *ctx) + if (!ctx->codec.h265.neighbor_info_buf) + return -ENOMEM; + ++ ctx->codec.h265.entry_points_buf = ++ dma_alloc_coherent(dev->dev, CEDRUS_H265_ENTRY_POINTS_BUF_SIZE, ++ &ctx->codec.h265.entry_points_buf_addr, ++ GFP_KERNEL); ++ if (!ctx->codec.h265.entry_points_buf) { ++ dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, ++ ctx->codec.h265.neighbor_info_buf, ++ ctx->codec.h265.neighbor_info_buf_addr); ++ return -ENOMEM; ++ } ++ + return 0; + } + +@@ -689,6 +767,9 @@ static void cedrus_h265_stop(struct cedrus_ctx *ctx) + dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, + ctx->codec.h265.neighbor_info_buf, + ctx->codec.h265.neighbor_info_buf_addr); ++ dma_free_coherent(dev->dev, CEDRUS_H265_ENTRY_POINTS_BUF_SIZE, ++ ctx->codec.h265.entry_points_buf, ++ ctx->codec.h265.entry_points_buf_addr); + } + + static void cedrus_h265_trigger(struct cedrus_ctx *ctx) +diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h +index 3e2e32098312..d1b094c8aaeb 100644 +--- a/include/media/hevc-ctrls.h ++++ b/include/media/hevc-ctrls.h +@@ -169,6 +169,7 @@ struct v4l2_ctrl_hevc_slice_params { + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ + __u32 slice_segment_addr; ++ __u32 num_entry_point_offsets; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ + __u8 nal_unit_type; +@@ -203,7 +204,9 @@ struct v4l2_ctrl_hevc_slice_params { + __u8 num_rps_poc_st_curr_after; + __u8 num_rps_poc_lt_curr; + +- __u8 padding[5]; ++ __u8 padding; ++ ++ __u32 entry_point_offset_minus1[256]; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ + struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; +-- +2.24.0 + + +From 42b71243ef0c15e1d940583ef3fce99ec79a1975 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Thu, 14 Feb 2019 22:50:12 +0100 +Subject: [PATCH 10/14] media: cedrus: H264 interlace hack + +Signed-off-by: Jernej Skrabec +--- + .../staging/media/sunxi/cedrus/cedrus_h264.c | 24 ++++++++++++------- + 1 file changed, 16 insertions(+), 8 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index ab83a6f1f921..b0ee4aed79f9 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -102,7 +102,7 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, + struct cedrus_dev *dev = ctx->dev; + unsigned long used_dpbs = 0; + unsigned int position; +- unsigned int output = 0; ++ int output = -1; + unsigned int i; + + cap_q = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +@@ -125,6 +125,11 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, + position = cedrus_buf->codec.h264.position; + used_dpbs |= BIT(position); + ++ if (run->dst->vb2_buf.timestamp == dpb->reference_ts) { ++ output = position; ++ continue; ++ } ++ + if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) + continue; + +@@ -132,13 +137,11 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, + dpb->top_field_order_cnt, + dpb->bottom_field_order_cnt, + &pic_list[position]); +- +- output = max(position, output); + } + +- position = find_next_zero_bit(&used_dpbs, CEDRUS_H264_FRAME_NUM, +- output); +- if (position >= CEDRUS_H264_FRAME_NUM) ++ if (output >= 0) ++ position = output; ++ else + position = find_first_zero_bit(&used_dpbs, CEDRUS_H264_FRAME_NUM); + + output_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf); +@@ -164,6 +167,10 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, + + #define CEDRUS_MAX_REF_IDX 32 + ++#define REF_IDX(v) (v & GENMASK(5, 0)) ++#define REF_FIELD(v) (v >> 6) ++#define REF_FIELD_BOTTOM 2 ++ + static void _cedrus_write_ref_list(struct cedrus_ctx *ctx, + struct cedrus_run *run, + const u8 *ref_list, u8 num_ref, +@@ -188,7 +195,7 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx, + int buf_idx; + u8 dpb_idx; + +- dpb_idx = ref_list[i]; ++ dpb_idx = REF_IDX(ref_list[i]); + dpb = &decode->dpb[dpb_idx]; + + if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) +@@ -203,7 +210,8 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx, + position = cedrus_buf->codec.h264.position; + + sram_array[i] |= position << 1; +- if (ref_buf->field == V4L2_FIELD_BOTTOM) ++ /* set bottom field flag when reference is to bottom field */ ++ if (REF_FIELD(ref_list[i]) == REF_FIELD_BOTTOM) + sram_array[i] |= BIT(0); + } + +-- +2.24.0 + + +From 6c1b98710d93611eec39bbcfcf07b3fc48e11459 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 9 Nov 2019 11:50:40 +0100 +Subject: [PATCH 11/14] media: cedrus: hevc: Add luma bit depth + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus_h265.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +index 97dce6ffbbc5..89e269cc066d 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -483,6 +483,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE(sps->log2_diff_max_min_luma_coding_block_size) | + VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_LUMA_CODING_BLOCK_SIZE_MINUS3(sps->log2_min_luma_coding_block_size_minus3) | + VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_CHROMA_MINUS8(sps->bit_depth_chroma_minus8) | ++ VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_LUMA_MINUS8(sps->bit_depth_luma_minus8) | + VE_DEC_H265_DEC_SPS_HDR_CHROMA_FORMAT_IDC(sps->chroma_format_idc); + + reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_STRONG_INTRA_SMOOTHING_ENABLE, +-- +2.24.0 + + +From 187e20b079317e312a1be425ff4c19f838b9e625 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 9 Nov 2019 13:06:15 +0100 +Subject: [PATCH 12/14] media: cedrus: Add callback for buffer cleanup + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus.h | 1 + + drivers/staging/media/sunxi/cedrus/cedrus_video.c | 13 +++++++++++++ + 2 files changed, 14 insertions(+) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h +index 1204e32d83bc..9298aa5f229d 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -148,6 +148,7 @@ struct cedrus_dec_ops { + int (*start)(struct cedrus_ctx *ctx); + void (*stop)(struct cedrus_ctx *ctx); + void (*trigger)(struct cedrus_ctx *ctx); ++ void (*buf_cleanup)(struct cedrus_ctx *ctx, struct cedrus_buffer *buf); + }; + + struct cedrus_variant { +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +index 497b1199d3fe..7f95216a552e 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +@@ -431,6 +431,18 @@ static int cedrus_buf_prepare(struct vb2_buffer *vb) + return 0; + } + ++static void cedrus_buf_cleanup(struct vb2_buffer *vb) ++{ ++ struct vb2_queue *vq = vb->vb2_queue; ++ struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); ++ struct cedrus_dev *dev = ctx->dev; ++ struct cedrus_dec_ops *ops = dev->dec_ops[ctx->current_codec]; ++ ++ if (!V4L2_TYPE_IS_OUTPUT(vq->type) && ops->buf_cleanup) ++ ops->buf_cleanup(ctx, ++ vb2_to_cedrus_buffer(vq->bufs[vb->index])); ++} ++ + static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count) + { + struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); +@@ -494,6 +506,7 @@ static void cedrus_buf_request_complete(struct vb2_buffer *vb) + static struct vb2_ops cedrus_qops = { + .queue_setup = cedrus_queue_setup, + .buf_prepare = cedrus_buf_prepare, ++ .buf_cleanup = cedrus_buf_cleanup, + .buf_queue = cedrus_buf_queue, + .buf_out_validate = cedrus_buf_out_validate, + .buf_request_complete = cedrus_buf_request_complete, +-- +2.24.0 + + +From 024630941ade1aa57b4c16a5577ee9cf4f62be18 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 9 Nov 2019 13:22:05 +0100 +Subject: [PATCH 13/14] media: cedrus: hevc: Improve buffer management + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus.h | 9 +- + .../staging/media/sunxi/cedrus/cedrus_h265.c | 117 ++++++++++-------- + 2 files changed, 69 insertions(+), 57 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h +index 9298aa5f229d..d8a4f8e83f94 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -95,6 +95,11 @@ struct cedrus_buffer { + unsigned int position; + enum cedrus_h264_pic_type pic_type; + } h264; ++ struct { ++ void *mv_col_buf; ++ dma_addr_t mv_col_buf_dma; ++ ssize_t mv_col_buf_size; ++ } h265; + } codec; + }; + +@@ -128,10 +133,6 @@ struct cedrus_ctx { + ssize_t intra_pred_buf_size; + } h264; + struct { +- void *mv_col_buf; +- dma_addr_t mv_col_buf_addr; +- ssize_t mv_col_buf_size; +- ssize_t mv_col_buf_unit_size; + void *neighbor_info_buf; + dma_addr_t neighbor_info_buf_addr; + void *entry_points_buf; +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +index 89e269cc066d..7c806ef6e8ef 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -91,26 +91,66 @@ static void cedrus_h265_sram_write_data(struct cedrus_dev *dev, void *data, + + static inline dma_addr_t + cedrus_h265_frame_info_mv_col_buf_addr(struct cedrus_ctx *ctx, +- unsigned int index, unsigned int field) ++ unsigned int index, ++ const struct v4l2_ctrl_hevc_sps *sps) + { +- return ctx->codec.h265.mv_col_buf_addr + index * +- ctx->codec.h265.mv_col_buf_unit_size + +- field * ctx->codec.h265.mv_col_buf_unit_size / 2; ++ struct cedrus_buffer *cedrus_buf = NULL; ++ struct vb2_buffer *buf = NULL; ++ struct vb2_queue *vq; ++ ++ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ if (vq) ++ buf = vb2_get_buffer(vq, index); ++ ++ if (buf) ++ cedrus_buf = vb2_to_cedrus_buffer(buf); ++ ++ if (!cedrus_buf) ++ return 0; ++ ++ if (!cedrus_buf->codec.h265.mv_col_buf_size) { ++ unsigned int ctb_size_luma, width_in_ctb_luma; ++ unsigned int log2_max_luma_coding_block_size; ++ ++ log2_max_luma_coding_block_size = ++ sps->log2_min_luma_coding_block_size_minus3 + 3 + ++ sps->log2_diff_max_min_luma_coding_block_size; ++ ctb_size_luma = 1 << log2_max_luma_coding_block_size; ++ width_in_ctb_luma = DIV_ROUND_UP(sps->pic_width_in_luma_samples, ++ ctb_size_luma); ++ ++ cedrus_buf->codec.h265.mv_col_buf_size = ALIGN(width_in_ctb_luma * ++ DIV_ROUND_UP(sps->pic_height_in_luma_samples, ctb_size_luma) * ++ CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE, 1024); ++ ++ cedrus_buf->codec.h265.mv_col_buf = ++ dma_alloc_coherent(ctx->dev->dev, ++ cedrus_buf->codec.h265.mv_col_buf_size, ++ &cedrus_buf->codec.h265.mv_col_buf_dma, ++ GFP_KERNEL); ++ ++ if (!cedrus_buf->codec.h265.mv_col_buf) { ++ cedrus_buf->codec.h265.mv_col_buf_size = 0; ++ cedrus_buf->codec.h265.mv_col_buf_dma = 0; ++ } ++ } ++ ++ return cedrus_buf->codec.h265.mv_col_buf_dma; + } + + static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx, + unsigned int index, + bool field_pic, + u32 pic_order_cnt[], +- int buffer_index) ++ int buffer_index, ++ const struct v4l2_ctrl_hevc_sps *sps) + { + struct cedrus_dev *dev = ctx->dev; + dma_addr_t dst_luma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 0); + dma_addr_t dst_chroma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 1); + dma_addr_t mv_col_buf_addr[2] = { +- cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, 0), +- cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, +- field_pic ? 1 : 0) ++ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, sps), ++ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, sps) + }; + u32 offset = VE_DEC_H265_SRAM_OFFSET_FRAME_INFO + + VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT * index; +@@ -134,7 +174,8 @@ static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx, + + static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx, + const struct v4l2_hevc_dpb_entry *dpb, +- u8 num_active_dpb_entries) ++ u8 num_active_dpb_entries, ++ const struct v4l2_ctrl_hevc_sps *sps) + { + struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, + V4L2_BUF_TYPE_VIDEO_CAPTURE); +@@ -149,7 +190,7 @@ static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx, + + cedrus_h265_frame_info_write_single(ctx, i, dpb[i].field_pic, + pic_order_cnt, +- buffer_index); ++ buffer_index, sps); + } + } + +@@ -386,36 +427,6 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + width_in_ctb_luma = + DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma); + +- /* MV column buffer size and allocation. */ +- if (!ctx->codec.h265.mv_col_buf_size) { +- unsigned int num_buffers = +- run->dst->vb2_buf.vb2_queue->num_buffers; +- +- /* +- * Each CTB requires a MV col buffer with a specific unit size. +- * Since the address is given with missing lsb bits, 1 KiB is +- * added to each buffer to ensure proper alignment. +- */ +- ctx->codec.h265.mv_col_buf_unit_size = +- DIV_ROUND_UP(ctx->src_fmt.width, ctb_size_luma) * +- DIV_ROUND_UP(ctx->src_fmt.height, ctb_size_luma) * +- CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE + SZ_1K; +- +- ctx->codec.h265.mv_col_buf_size = num_buffers * +- ctx->codec.h265.mv_col_buf_unit_size; +- +- ctx->codec.h265.mv_col_buf = +- dma_alloc_coherent(dev->dev, +- ctx->codec.h265.mv_col_buf_size, +- &ctx->codec.h265.mv_col_buf_addr, +- GFP_KERNEL); +- if (!ctx->codec.h265.mv_col_buf) { +- ctx->codec.h265.mv_col_buf_size = 0; +- // TODO: Abort the process here. +- return; +- } +- } +- + /* Activate H265 engine. */ + cedrus_engine_enable(ctx, CEDRUS_CODEC_H265); + +@@ -669,7 +680,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + + /* Write decoded picture buffer in pic list. */ + cedrus_h265_frame_info_write_dpb(ctx, slice_params->dpb, +- slice_params->num_active_dpb_entries); ++ slice_params->num_active_dpb_entries, sps); + + /* Output frame. */ + +@@ -680,7 +691,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + cedrus_h265_frame_info_write_single(ctx, output_pic_list_index, + slice_params->pic_struct != 0, + pic_order_cnt, +- run->dst->vb2_buf.index); ++ run->dst->vb2_buf.index, sps); + + cedrus_write(dev, VE_DEC_H265_OUTPUT_FRAME_IDX, output_pic_list_index); + +@@ -729,9 +740,6 @@ static int cedrus_h265_start(struct cedrus_ctx *ctx) + { + struct cedrus_dev *dev = ctx->dev; + +- /* The buffer size is calculated at setup time. */ +- ctx->codec.h265.mv_col_buf_size = 0; +- + ctx->codec.h265.neighbor_info_buf = + dma_alloc_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, + &ctx->codec.h265.neighbor_info_buf_addr, +@@ -757,14 +765,6 @@ static void cedrus_h265_stop(struct cedrus_ctx *ctx) + { + struct cedrus_dev *dev = ctx->dev; + +- if (ctx->codec.h265.mv_col_buf_size > 0) { +- dma_free_coherent(dev->dev, ctx->codec.h265.mv_col_buf_size, +- ctx->codec.h265.mv_col_buf, +- ctx->codec.h265.mv_col_buf_addr); +- +- ctx->codec.h265.mv_col_buf_size = 0; +- } +- + dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, + ctx->codec.h265.neighbor_info_buf, + ctx->codec.h265.neighbor_info_buf_addr); +@@ -780,6 +780,16 @@ static void cedrus_h265_trigger(struct cedrus_ctx *ctx) + cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_DEC_SLICE); + } + ++static void cedrus_h265_buf_cleanup(struct cedrus_ctx *ctx, ++ struct cedrus_buffer *buf) ++{ ++ if (buf->codec.h265.mv_col_buf_size) ++ dma_free_coherent(ctx->dev->dev, ++ buf->codec.h265.mv_col_buf_size, ++ buf->codec.h265.mv_col_buf, ++ buf->codec.h265.mv_col_buf_dma); ++} ++ + struct cedrus_dec_ops cedrus_dec_ops_h265 = { + .irq_clear = cedrus_h265_irq_clear, + .irq_disable = cedrus_h265_irq_disable, +@@ -788,4 +798,5 @@ struct cedrus_dec_ops cedrus_dec_ops_h265 = { + .start = cedrus_h265_start, + .stop = cedrus_h265_stop, + .trigger = cedrus_h265_trigger, ++ .buf_cleanup = cedrus_h265_buf_cleanup, + }; +-- +2.24.0 + + +From b38b517739880462a43a1f4b36cf9384ffdae66c Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 9 Nov 2019 14:12:42 +0100 +Subject: [PATCH 14/14] media: cedrus: h264: Improve buffer management + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus.h | 3 + + .../staging/media/sunxi/cedrus/cedrus_h264.c | 93 ++++++++----------- + 2 files changed, 44 insertions(+), 52 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h +index d8a4f8e83f94..f8264953dd04 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -94,6 +94,9 @@ struct cedrus_buffer { + struct { + unsigned int position; + enum cedrus_h264_pic_type pic_type; ++ void *mv_col_buf; ++ dma_addr_t mv_col_buf_dma; ++ ssize_t mv_col_buf_size; + } h264; + struct { + void *mv_col_buf; +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index b0ee4aed79f9..aa5bd181cdaf 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -55,16 +55,14 @@ static void cedrus_h264_write_sram(struct cedrus_dev *dev, + } + + static dma_addr_t cedrus_h264_mv_col_buf_addr(struct cedrus_ctx *ctx, +- unsigned int position, ++ struct cedrus_buffer *buf, + unsigned int field) + { +- dma_addr_t addr = ctx->codec.h264.mv_col_buf_dma; ++ dma_addr_t addr = buf->codec.h264.mv_col_buf_dma; + +- /* Adjust for the position */ +- addr += position * ctx->codec.h264.mv_col_buf_field_size * 2; +- +- /* Adjust for the field */ +- addr += field * ctx->codec.h264.mv_col_buf_field_size; ++ /* Adjust for the field */ ++ if (field) ++ addr += buf->codec.h264.mv_col_buf_size / 2; + + return addr; + } +@@ -76,7 +74,6 @@ static void cedrus_fill_ref_pic(struct cedrus_ctx *ctx, + struct cedrus_h264_sram_ref_pic *pic) + { + struct vb2_buffer *vbuf = &buf->m2m_buf.vb.vb2_buf; +- unsigned int position = buf->codec.h264.position; + + pic->top_field_order_cnt = cpu_to_le32(top_field_order_cnt); + pic->bottom_field_order_cnt = cpu_to_le32(bottom_field_order_cnt); +@@ -85,9 +82,9 @@ static void cedrus_fill_ref_pic(struct cedrus_ctx *ctx, + pic->luma_ptr = cpu_to_le32(cedrus_buf_addr(vbuf, &ctx->dst_fmt, 0)); + pic->chroma_ptr = cpu_to_le32(cedrus_buf_addr(vbuf, &ctx->dst_fmt, 1)); + pic->mv_col_top_ptr = +- cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, position, 0)); ++ cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, buf, 0)); + pic->mv_col_bot_ptr = +- cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, position, 1)); ++ cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, buf, 1)); + } + + static void cedrus_write_frame_list(struct cedrus_ctx *ctx, +@@ -147,6 +144,28 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, + output_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf); + output_buf->codec.h264.position = position; + ++ if (!output_buf->codec.h264.mv_col_buf_size) { ++ const struct v4l2_ctrl_h264_sps *sps = run->h264.sps; ++ unsigned int field_size; ++ ++ field_size = DIV_ROUND_UP(ctx->src_fmt.width, 16) * ++ DIV_ROUND_UP(ctx->src_fmt.height, 16) * 16; ++ if (!(sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE)) ++ field_size = field_size * 2; ++ if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY)) ++ field_size = field_size * 2; ++ ++ output_buf->codec.h264.mv_col_buf_size = field_size * 2; ++ output_buf->codec.h264.mv_col_buf = ++ dma_alloc_coherent(dev->dev, ++ output_buf->codec.h264.mv_col_buf_size, ++ &output_buf->codec.h264.mv_col_buf_dma, ++ GFP_KERNEL); ++ ++ if (!output_buf->codec.h264.mv_col_buf) ++ output_buf->codec.h264.mv_col_buf_size = 0; ++ } ++ + if (slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) + output_buf->codec.h264.pic_type = CEDRUS_H264_PIC_TYPE_FIELD; + else if (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD) +@@ -525,8 +544,6 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx) + { + struct cedrus_dev *dev = ctx->dev; + unsigned int pic_info_size; +- unsigned int field_size; +- unsigned int mv_col_size; + int ret; + + /* Formula for picture buffer size is taken from CedarX source. */ +@@ -569,37 +586,6 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx) + goto err_pic_buf; + } + +- field_size = DIV_ROUND_UP(ctx->src_fmt.width, 16) * +- DIV_ROUND_UP(ctx->src_fmt.height, 16) * 16; +- +- /* +- * FIXME: This is actually conditional to +- * V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE not being set, we +- * might have to rework this if memory efficiency ever is +- * something we need to work on. +- */ +- field_size = field_size * 2; +- +- /* +- * FIXME: This is actually conditional to +- * V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY not being set, we might +- * have to rework this if memory efficiency ever is something +- * we need to work on. +- */ +- field_size = field_size * 2; +- ctx->codec.h264.mv_col_buf_field_size = field_size; +- +- mv_col_size = field_size * 2 * CEDRUS_H264_FRAME_NUM; +- ctx->codec.h264.mv_col_buf_size = mv_col_size; +- ctx->codec.h264.mv_col_buf = dma_alloc_coherent(dev->dev, +- ctx->codec.h264.mv_col_buf_size, +- &ctx->codec.h264.mv_col_buf_dma, +- GFP_KERNEL); +- if (!ctx->codec.h264.mv_col_buf) { +- ret = -ENOMEM; +- goto err_neighbor_buf; +- } +- + if (ctx->src_fmt.width > 2048) { + /* + * Formulas for deblock and intra prediction buffer sizes +@@ -615,7 +601,7 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx) + GFP_KERNEL); + if (!ctx->codec.h264.deblk_buf) { + ret = -ENOMEM; +- goto err_mv_col_buf; ++ goto err_neighbor_buf; + } + + ctx->codec.h264.intra_pred_buf_size = +@@ -638,11 +624,6 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx) + ctx->codec.h264.deblk_buf, + ctx->codec.h264.deblk_buf_dma); + +-err_mv_col_buf: +- dma_free_coherent(dev->dev, ctx->codec.h264.mv_col_buf_size, +- ctx->codec.h264.mv_col_buf, +- ctx->codec.h264.mv_col_buf_dma); +- + err_neighbor_buf: + dma_free_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE, + ctx->codec.h264.neighbor_info_buf, +@@ -659,9 +640,6 @@ static void cedrus_h264_stop(struct cedrus_ctx *ctx) + { + struct cedrus_dev *dev = ctx->dev; + +- dma_free_coherent(dev->dev, ctx->codec.h264.mv_col_buf_size, +- ctx->codec.h264.mv_col_buf, +- ctx->codec.h264.mv_col_buf_dma); + dma_free_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE, + ctx->codec.h264.neighbor_info_buf, + ctx->codec.h264.neighbor_info_buf_dma); +@@ -686,6 +664,16 @@ static void cedrus_h264_trigger(struct cedrus_ctx *ctx) + VE_H264_TRIGGER_TYPE_AVC_SLICE_DECODE); + } + ++static void cedrus_h264_buf_cleanup(struct cedrus_ctx *ctx, ++ struct cedrus_buffer *buf) ++{ ++ if (buf->codec.h264.mv_col_buf_size) ++ dma_free_coherent(ctx->dev->dev, ++ buf->codec.h264.mv_col_buf_size, ++ buf->codec.h264.mv_col_buf, ++ buf->codec.h264.mv_col_buf_dma); ++} ++ + struct cedrus_dec_ops cedrus_dec_ops_h264 = { + .irq_clear = cedrus_h264_irq_clear, + .irq_disable = cedrus_h264_irq_disable, +@@ -694,4 +682,5 @@ struct cedrus_dec_ops cedrus_dec_ops_h264 = { + .start = cedrus_h264_start, + .stop = cedrus_h264_stop, + .trigger = cedrus_h264_trigger, ++ .buf_cleanup = cedrus_h264_buf_cleanup, + }; +-- +2.24.0 + diff --git a/projects/Allwinner/patches/linux/0007-media-cedrus-Fix-decoding-for-some-H264-videos.patch b/projects/Allwinner/patches/linux/0007-media-cedrus-Fix-decoding-for-some-H264-videos.patch deleted file mode 100644 index f8ba3736312..00000000000 --- a/projects/Allwinner/patches/linux/0007-media-cedrus-Fix-decoding-for-some-H264-videos.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 443ca53cf78c635aa5bebe9f115721e55fe9ca38 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Sat, 25 May 2019 12:33:05 +0200 -Subject: [PATCH] media: cedrus: Fix decoding for some H264 videos - -It seems that for some H264 videos at least one bitstream parsing -trigger must be called in order to be decoded correctly. There is no -explanation why this helps, but it was observed that two sample videos -with this fix are now decoded correctly and there is no regression with -others. - -Signed-off-by: Jernej Skrabec ---- - .../staging/media/sunxi/cedrus/cedrus_h264.c | 22 ++++++++++++++++--- - 1 file changed, 19 insertions(+), 3 deletions(-) - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c -index a30bb283f69f..fab14de1815a 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c -@@ -6,6 +6,7 @@ - * Copyright (c) 2018 Bootlin - */ - -+#include - #include - - #include -@@ -289,6 +290,20 @@ static void cedrus_write_pred_weight_table(struct cedrus_ctx *ctx, - } - } - -+static void cedrus_skip_bits(struct cedrus_dev *dev, int num) -+{ -+ for (; num > 32; num -= 32) { -+ cedrus_write(dev, VE_H264_TRIGGER_TYPE, 0x3 | (32 << 8)); -+ while (cedrus_read(dev, VE_H264_STATUS) & (1 << 8)) -+ udelay(1); -+ } -+ if (num > 0) { -+ cedrus_write(dev, VE_H264_TRIGGER_TYPE, 0x3 | (num << 8)); -+ while (cedrus_read(dev, VE_H264_STATUS) & (1 << 8)) -+ udelay(1); -+ } -+} -+ - static void cedrus_set_params(struct cedrus_ctx *ctx, - struct cedrus_run *run) - { -@@ -299,12 +314,11 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, - struct vb2_buffer *src_buf = &run->src->vb2_buf; - struct cedrus_dev *dev = ctx->dev; - dma_addr_t src_buf_addr; -- u32 offset = slice->header_bit_size; -- u32 len = (slice->size * 8) - offset; -+ u32 len = slice->size * 8; - u32 reg; - - cedrus_write(dev, VE_H264_VLD_LEN, len); -- cedrus_write(dev, VE_H264_VLD_OFFSET, offset); -+ cedrus_write(dev, VE_H264_VLD_OFFSET, 0); - - src_buf_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0); - cedrus_write(dev, VE_H264_VLD_END, -@@ -323,6 +337,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, - cedrus_write(dev, VE_H264_TRIGGER_TYPE, - VE_H264_TRIGGER_TYPE_INIT_SWDEC); - -+ cedrus_skip_bits(dev, slice->header_bit_size); -+ - if (((pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) && - (slice->slice_type == V4L2_H264_SLICE_TYPE_P || - slice->slice_type == V4L2_H264_SLICE_TYPE_SP)) || --- -2.21.0 - diff --git a/projects/Allwinner/patches/linux/0008-media-cedrus-Fix-H264-default-reference-index-count.patch b/projects/Allwinner/patches/linux/0008-media-cedrus-Fix-H264-default-reference-index-count.patch deleted file mode 100644 index 6b08bad5396..00000000000 --- a/projects/Allwinner/patches/linux/0008-media-cedrus-Fix-H264-default-reference-index-count.patch +++ /dev/null @@ -1,36 +0,0 @@ -From fce7f7e700176b402b303d2a62813cc0cdd061e0 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Sat, 25 May 2019 13:18:50 +0200 -Subject: [PATCH 2/5] media: cedrus: Fix H264 default reference index count - -Reference index count in VE_H264_PPS should come from PPS control. -However, this is not really important, because reference index count is -in our case always overridden by that from slice header. - -Signed-off-by: Jernej Skrabec ---- - drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 8 ++------ - 1 file changed, 2 insertions(+), 6 deletions(-) - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c -index fab14de1815a..d0ee3f90ff46 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c -@@ -356,12 +356,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, - - // picture parameters - reg = 0; -- /* -- * FIXME: the kernel headers are allowing the default value to -- * be passed, but the libva doesn't give us that. -- */ -- reg |= (slice->num_ref_idx_l0_active_minus1 & 0x1f) << 10; -- reg |= (slice->num_ref_idx_l1_active_minus1 & 0x1f) << 5; -+ reg |= (pps->num_ref_idx_l0_default_active_minus1 & 0x1f) << 10; -+ reg |= (pps->num_ref_idx_l1_default_active_minus1 & 0x1f) << 5; - reg |= (pps->weighted_bipred_idc & 0x3) << 2; - if (pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE) - reg |= VE_H264_PPS_ENTROPY_CODING_MODE; --- -2.21.0 - diff --git a/projects/Allwinner/patches/linux/0009-media-cedrus-WIP-H264-improvements.patch b/projects/Allwinner/patches/linux/0009-media-cedrus-WIP-H264-improvements.patch deleted file mode 100644 index 3abe59c0387..00000000000 --- a/projects/Allwinner/patches/linux/0009-media-cedrus-WIP-H264-improvements.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 9714cf1bc8c5b48f21af3500e34497621b51a4b1 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Thu, 14 Feb 2019 22:50:12 +0100 -Subject: [PATCH 3/5] media: cedrus: WIP H264 improvements - -Signed-off-by: Jernej Skrabec ---- - .../staging/media/sunxi/cedrus/cedrus_h264.c | 37 ++++++++++++++----- - 1 file changed, 27 insertions(+), 10 deletions(-) - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c -index d0ee3f90ff46..dcb8d3837869 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c -@@ -39,7 +39,7 @@ struct cedrus_h264_sram_ref_pic { - #define CEDRUS_H264_FRAME_NUM 18 - - #define CEDRUS_NEIGHBOR_INFO_BUF_SIZE (16 * SZ_1K) --#define CEDRUS_PIC_INFO_BUF_SIZE (128 * SZ_1K) -+#define CEDRUS_PIC_INFO_BUF_SIZE (336 * SZ_1K) - - static void cedrus_h264_write_sram(struct cedrus_dev *dev, - enum cedrus_h264_sram_off off, -@@ -102,7 +102,7 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, - struct cedrus_dev *dev = ctx->dev; - unsigned long used_dpbs = 0; - unsigned int position; -- unsigned int output = 0; -+ int output = -1; - unsigned int i; - - memset(pic_list, 0, sizeof(pic_list)); -@@ -123,6 +123,11 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, - position = cedrus_buf->codec.h264.position; - used_dpbs |= BIT(position); - -+ if (run->dst->vb2_buf.timestamp == dpb->reference_ts) { -+ output = position; -+ continue; -+ } -+ - if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) - continue; - -@@ -130,13 +135,11 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, - dpb->top_field_order_cnt, - dpb->bottom_field_order_cnt, - &pic_list[position]); -- -- output = max(position, output); - } - -- position = find_next_zero_bit(&used_dpbs, CEDRUS_H264_FRAME_NUM, -- output); -- if (position >= CEDRUS_H264_FRAME_NUM) -+ if (output >= 0) -+ position = output; -+ else - position = find_first_zero_bit(&used_dpbs, CEDRUS_H264_FRAME_NUM); - - output_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf); -@@ -162,6 +165,10 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, - - #define CEDRUS_MAX_REF_IDX 32 - -+#define REF_IDX(v) (v & GENMASK(5, 0)) -+#define REF_FIELD(v) (v >> 6) -+#define REF_FIELD_BOTTOM 2 -+ - static void _cedrus_write_ref_list(struct cedrus_ctx *ctx, - struct cedrus_run *run, - const u8 *ref_list, u8 num_ref, -@@ -184,7 +191,7 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx, - int buf_idx; - u8 dpb_idx; - -- dpb_idx = ref_list[i]; -+ dpb_idx = REF_IDX(ref_list[i]); - dpb = &decode->dpb[dpb_idx]; - - if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) -@@ -199,7 +206,8 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx, - position = cedrus_buf->codec.h264.position; - - sram_array[i] |= position << 1; -- if (ref_buf->field == V4L2_FIELD_BOTTOM) -+ /* set bottom field flag when reference is to bottom field */ -+ if (REF_FIELD(ref_list[i]) == REF_FIELD_BOTTOM) - sram_array[i] |= BIT(0); - } - -@@ -315,6 +323,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, - struct cedrus_dev *dev = ctx->dev; - dma_addr_t src_buf_addr; - u32 len = slice->size * 8; -+ unsigned int pic_width_in_mbs; -+ bool mbaff_picture; - u32 reg; - - cedrus_write(dev, VE_H264_VLD_LEN, len); -@@ -382,12 +392,19 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, - reg |= VE_H264_SPS_DIRECT_8X8_INFERENCE; - cedrus_write(dev, VE_H264_SPS, reg); - -+ mbaff_picture = !(slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) && -+ (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD); -+ pic_width_in_mbs = sps->pic_width_in_mbs_minus1 + 1; -+ - // slice parameters - reg = 0; -+ reg |= ((slice->first_mb_in_slice % pic_width_in_mbs) & 0xff) << 24; -+ reg |= (((slice->first_mb_in_slice / pic_width_in_mbs) * (mbaff_picture ? 2 : 1)) & 0xff) << 16; - reg |= decode->nal_ref_idc ? BIT(12) : 0; - reg |= (slice->slice_type & 0xf) << 8; - reg |= slice->cabac_init_idc & 0x3; -- reg |= VE_H264_SHS_FIRST_SLICE_IN_PIC; -+ if (decode->num_slices == 1) -+ reg |= VE_H264_SHS_FIRST_SLICE_IN_PIC; - if (slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) - reg |= VE_H264_SHS_FIELD_PIC; - if (slice->flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD) --- -2.21.0 - diff --git a/projects/Allwinner/patches/linux/0010-WIP-HEVC-improvements.patch b/projects/Allwinner/patches/linux/0010-WIP-HEVC-improvements.patch deleted file mode 100644 index c5d9febfff0..00000000000 --- a/projects/Allwinner/patches/linux/0010-WIP-HEVC-improvements.patch +++ /dev/null @@ -1,781 +0,0 @@ -From c6582c38df2f78dc9d4f8fd920780a82a01e4d8e Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Sat, 25 May 2019 13:58:17 +0200 -Subject: [PATCH 2/3] WIP: HEVC improvements - -Signed-off-by: Jernej Skrabec ---- - drivers/media/v4l2-core/v4l2-ctrls.c | 8 + - drivers/staging/media/sunxi/cedrus/cedrus.c | 6 + - drivers/staging/media/sunxi/cedrus/cedrus.h | 11 +- - .../staging/media/sunxi/cedrus/cedrus_dec.c | 2 + - .../staging/media/sunxi/cedrus/cedrus_h265.c | 348 +++++++++++++----- - .../staging/media/sunxi/cedrus/cedrus_regs.h | 3 + - .../staging/media/sunxi/cedrus/cedrus_video.c | 12 +- - include/media/hevc-ctrls.h | 20 +- - 8 files changed, 301 insertions(+), 109 deletions(-) - -diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c -index 1107698b9d06..aed7a4526193 100644 ---- a/drivers/media/v4l2-core/v4l2-ctrls.c -+++ b/drivers/media/v4l2-core/v4l2-ctrls.c -@@ -947,6 +947,7 @@ const char *v4l2_ctrl_get_name(u32 id) - case V4L2_CID_MPEG_VIDEO_HEVC_SPS: return "HEVC Sequence Parameter Set"; - case V4L2_CID_MPEG_VIDEO_HEVC_PPS: return "HEVC Picture Parameter Set"; - case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: return "HEVC Slice Parameters"; -+ case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX: return "HEVC Scaling Matrix"; - - /* CAMERA controls */ - /* Keep the order of the 'case's the same as in v4l2-controls.h! */ -@@ -1368,6 +1369,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, - case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: - *type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS; - break; -+ case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX: -+ *type = V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX; -+ break; - default: - *type = V4L2_CTRL_TYPE_INTEGER; - break; -@@ -1747,6 +1751,7 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx, - case V4L2_CTRL_TYPE_HEVC_SPS: - case V4L2_CTRL_TYPE_HEVC_PPS: - case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: -+ case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX: - return 0; - - default: -@@ -2356,6 +2361,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, - case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: - elem_size = sizeof(struct v4l2_ctrl_hevc_slice_params); - break; -+ case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX: -+ elem_size = sizeof(struct v4l2_ctrl_hevc_scaling_matrix); -+ break; - default: - if (type < V4L2_CTRL_COMPOUND_TYPES) - elem_size = sizeof(s32); -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c -index 70642834f351..01860f247aa6 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c -@@ -88,6 +88,13 @@ static const struct cedrus_control cedrus_controls[] = { - .codec = CEDRUS_CODEC_H265, - .required = true, - }, -+ { -+ .cfg = { -+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX, -+ }, -+ .codec = CEDRUS_CODEC_H265, -+ .required = true, -+ }, - }; - - #define CEDRUS_CONTROLS_COUNT ARRAY_SIZE(cedrus_controls) -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h -index f19be772d78b..b518c5613fdf 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus.h -+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h -@@ -74,6 +74,7 @@ struct cedrus_h265_run { - const struct v4l2_ctrl_hevc_sps *sps; - const struct v4l2_ctrl_hevc_pps *pps; - const struct v4l2_ctrl_hevc_slice_params *slice_params; -+ const struct v4l2_ctrl_hevc_scaling_matrix *scaling_matrix; - }; - - struct cedrus_run { -@@ -90,6 +91,10 @@ struct cedrus_run { - struct cedrus_buffer { - struct v4l2_m2m_buffer m2m_buf; - -+ void *mv_col_buf; -+ dma_addr_t mv_col_buf_dma; -+ ssize_t mv_col_buf_size; -+ - union { - struct { - unsigned int position; -@@ -123,12 +128,10 @@ struct cedrus_ctx { - dma_addr_t neighbor_info_buf_dma; - } h264; - struct { -- void *mv_col_buf; -- dma_addr_t mv_col_buf_addr; -- ssize_t mv_col_buf_size; -- ssize_t mv_col_buf_unit_size; - void *neighbor_info_buf; - dma_addr_t neighbor_info_buf_addr; -+ void *entry_points_buf; -+ dma_addr_t entry_points_buf_addr; - } h265; - } codec; - }; -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c -index c6d0ef66cdd0..104adb08492c 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c -@@ -66,6 +66,8 @@ void cedrus_device_run(void *priv) - V4L2_CID_MPEG_VIDEO_HEVC_PPS); - run.h265.slice_params = cedrus_find_control_data(ctx, - V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS); -+ run.h265.scaling_matrix = cedrus_find_control_data(ctx, -+ V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX); - break; - - default: -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -index fd4d86b02156..82d29c59b787 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -@@ -77,24 +77,32 @@ static void cedrus_h265_sram_write_offset(struct cedrus_dev *dev, u32 offset) - cedrus_write(dev, VE_DEC_H265_SRAM_OFFSET, offset); - } - --static void cedrus_h265_sram_write_data(struct cedrus_dev *dev, void *data, -+static void cedrus_h265_sram_write_data(struct cedrus_dev *dev, const void *data, - unsigned int size) - { -- u32 *word = data; -+ size_t count = DIV_ROUND_UP(size, 4); -+ const u32 *word = data; - -- while (size >= sizeof(u32)) { -+ while (count--) - cedrus_write(dev, VE_DEC_H265_SRAM_DATA, *word++); -- size -= sizeof(u32); -- } - } - - static inline dma_addr_t - cedrus_h265_frame_info_mv_col_buf_addr(struct cedrus_ctx *ctx, -- unsigned int index, unsigned int field) -+ unsigned int index) - { -- return ctx->codec.h265.mv_col_buf_addr + index * -- ctx->codec.h265.mv_col_buf_unit_size + -- field * ctx->codec.h265.mv_col_buf_unit_size / 2; -+ struct cedrus_buffer *cedrus_buf = NULL; -+ struct vb2_buffer *buf = NULL; -+ struct vb2_queue *vq; -+ -+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); -+ if (vq) -+ buf = vb2_get_buffer(vq, index); -+ -+ if (buf) -+ cedrus_buf = vb2_to_cedrus_buffer(buf); -+ -+ return cedrus_buf ? cedrus_buf->mv_col_buf_dma : 0; - } - - static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx, -@@ -107,9 +108,8 @@ static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx, - dma_addr_t dst_luma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 0); - dma_addr_t dst_chroma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 1); - dma_addr_t mv_col_buf_addr[2] = { -- cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, 0), -- cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, -- field_pic ? 1 : 0) -+ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index), -+ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index) - }; - u32 offset = VE_DEC_H265_SRAM_OFFSET_FRAME_INFO + - VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT * index; -@@ -158,28 +158,24 @@ static void cedrus_h265_ref_pic_list_write(struct cedrus_dev *dev, - u8 num_ref_idx_active, - u32 sram_offset) - { -+ u8 sram_array[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; - unsigned int i; -- u32 word = 0; -+ -+ memset(sram_array, 0, sizeof(sram_array)); -+ num_ref_idx_active = min(num_ref_idx_active, -+ (u8)V4L2_HEVC_DPB_ENTRIES_NUM_MAX); - - cedrus_h265_sram_write_offset(dev, sram_offset); - - for (i = 0; i < num_ref_idx_active; i++) { -- unsigned int shift = (i % 4) * 8; - unsigned int index = list[i]; -- u8 value = list[i]; - -+ sram_array[i] = index; - if (dpb[index].rps == V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR) -- value |= VE_DEC_H265_SRAM_REF_PIC_LIST_LT_REF; -- -- /* Each SRAM word gathers up to 4 references. */ -- word |= value << shift; -- -- /* Write the word to SRAM and clear it for the next batch. */ -- if ((i % 4) == 3 || i == (num_ref_idx_active - 1)) { -- cedrus_h265_sram_write_data(dev, &word, sizeof(word)); -- word = 0; -- } -+ sram_array[i] |= VE_DEC_H265_SRAM_REF_PIC_LIST_LT_REF; - } -+ -+ cedrus_h265_sram_write_data(dev, &sram_array, num_ref_idx_active); - } - - static void cedrus_h265_pred_weight_write(struct cedrus_dev *dev, -@@ -220,6 +216,131 @@ static void cedrus_h265_pred_weight_write(struct cedrus_dev *dev, - } - } - -+static void cedrus_h265_write_scaling_list(struct cedrus_ctx *ctx, -+ struct cedrus_run *run) -+{ -+ const struct v4l2_ctrl_hevc_scaling_matrix *scaling; -+ struct cedrus_dev *dev = ctx->dev; -+ u32 i, j, k, val; -+ -+ scaling = run->h265.scaling_matrix; -+ -+ cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF0, -+ (scaling->scaling_list_dc_coef_32x32[1] << 24) | -+ (scaling->scaling_list_dc_coef_32x32[0] << 16) | -+ (scaling->scaling_list_dc_coef_16x16[1] << 8) | -+ (scaling->scaling_list_dc_coef_16x16[0] << 0)); -+ -+ cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF1, -+ (scaling->scaling_list_dc_coef_16x16[5] << 24) | -+ (scaling->scaling_list_dc_coef_16x16[4] << 16) | -+ (scaling->scaling_list_dc_coef_16x16[3] << 8) | -+ (scaling->scaling_list_dc_coef_16x16[2] << 0)); -+ -+ cedrus_h265_sram_write_offset(dev, VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS); -+ -+ for (i = 0; i < 6; i++) -+ for (j = 0; j < 8; j++) -+ for (k = 0; k < 8; k += 4) { -+ val = ((u32)scaling->scaling_list_8x8[i][j + (k + 3) * 8] << 24) | -+ ((u32)scaling->scaling_list_8x8[i][j + (k + 2) * 8] << 16) | -+ ((u32)scaling->scaling_list_8x8[i][j + (k + 1) * 8] << 8) | -+ scaling->scaling_list_8x8[i][j + k * 8]; -+ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); -+ } -+ -+ for (i = 0; i < 2; i++) -+ for (j = 0; j < 8; j++) -+ for (k = 0; k < 8; k += 4) { -+ val = ((u32)scaling->scaling_list_32x32[i][j + (k + 3) * 8] << 24) | -+ ((u32)scaling->scaling_list_32x32[i][j + (k + 2) * 8] << 16) | -+ ((u32)scaling->scaling_list_32x32[i][j + (k + 1) * 8] << 8) | -+ scaling->scaling_list_32x32[i][j + k * 8]; -+ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); -+ } -+ -+ for (i = 0; i < 6; i++) -+ for (j = 0; j < 8; j++) -+ for (k = 0; k < 8; k += 4) { -+ val = ((u32)scaling->scaling_list_16x16[i][j + (k + 3) * 8] << 24) | -+ ((u32)scaling->scaling_list_16x16[i][j + (k + 2) * 8] << 16) | -+ ((u32)scaling->scaling_list_16x16[i][j + (k + 1) * 8] << 8) | -+ scaling->scaling_list_16x16[i][j + k * 8]; -+ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); -+ } -+ -+ for (i = 0; i < 6; i++) -+ for (j = 0; j < 4; j++) { -+ val = ((u32)scaling->scaling_list_4x4[i][j + 12] << 24) | -+ ((u32)scaling->scaling_list_4x4[i][j + 8] << 16) | -+ ((u32)scaling->scaling_list_4x4[i][j + 4] << 8) | -+ scaling->scaling_list_4x4[i][j]; -+ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); -+ } -+} -+ -+static void write_entry_point_list(struct cedrus_ctx *ctx, -+ struct cedrus_run *run) -+{ -+ const struct v4l2_ctrl_hevc_slice_params *slice_params; -+ unsigned int ctb_size_luma, width_in_ctb_luma; -+ unsigned int log2_max_luma_coding_block_size; -+ const struct v4l2_ctrl_hevc_pps *pps; -+ const struct v4l2_ctrl_hevc_sps *sps; -+ struct cedrus_dev *dev = ctx->dev; -+ uint32_t *entry_points; -+ int i, x, tx, y, ty; -+ -+ pps = run->h265.pps; -+ sps = run->h265.sps; -+ slice_params = run->h265.slice_params; -+ -+ log2_max_luma_coding_block_size = -+ sps->log2_min_luma_coding_block_size_minus3 + 3 + -+ sps->log2_diff_max_min_luma_coding_block_size; -+ ctb_size_luma = 1 << log2_max_luma_coding_block_size; -+ width_in_ctb_luma = DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma); -+ -+ for (x = 0, tx = 0; tx < pps->num_tile_columns_minus1 + 1; tx++) { -+ if (x + pps->column_width_minus1[tx] + 1 > (slice_params->slice_segment_addr % width_in_ctb_luma)) -+ break; -+ -+ x += pps->column_width_minus1[tx] + 1; -+ } -+ -+ for (y = 0, ty = 0; ty < pps->num_tile_rows_minus1 + 1; ty++) { -+ if (y + pps->row_height_minus1[ty] + 1 > (slice_params->slice_segment_addr / width_in_ctb_luma)) -+ break; -+ -+ y += pps->row_height_minus1[ty] + 1; -+ } -+ -+ cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, (y << 16) | (x << 0)); -+ cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, -+ ((y + pps->row_height_minus1[ty]) << 16) | -+ ((x + pps->column_width_minus1[tx]) << 0)); -+ -+ entry_points = ctx->codec.h265.entry_points_buf; -+ if (pps->entropy_coding_sync_enabled_flag) { -+ for (i = 0; i < slice_params->num_entry_point_offsets; i++) -+ entry_points[i] = slice_params->entry_point_offset_minus1[i] + 1; -+ } else { -+ for (i = 0; i < slice_params->num_entry_point_offsets; i++) { -+ if (tx + 1 >= pps->num_tile_columns_minus1 + 1) { -+ x = tx = 0; -+ y += pps->row_height_minus1[ty++] + 1; -+ } else { -+ x += pps->column_width_minus1[tx++] + 1; -+ } -+ -+ entry_points[i * 4 + 0] = slice_params->entry_point_offset_minus1[i] + 1; -+ entry_points[i * 4 + 1] = 0x0; -+ entry_points[i * 4 + 2] = (y << 16) | (x << 0); -+ entry_points[i * 4 + 3] = ((y + pps->row_height_minus1[ty]) << 16) | ((x + pps->column_width_minus1[tx]) << 0); -+ } -+ } -+} -+ - static void cedrus_h265_setup(struct cedrus_ctx *ctx, - struct cedrus_run *run) - { -@@ -228,6 +349,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - const struct v4l2_ctrl_hevc_pps *pps; - const struct v4l2_ctrl_hevc_slice_params *slice_params; - const struct v4l2_hevc_pred_weight_table *pred_weight_table; -+ struct cedrus_buffer *cedrus_buf; - dma_addr_t src_buf_addr; - dma_addr_t src_buf_end_addr; - u32 chroma_log2_weight_denom; -@@ -240,43 +362,10 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - slice_params = run->h265.slice_params; - pred_weight_table = &slice_params->pred_weight_table; - -- /* MV column buffer size and allocation. */ -- if (!ctx->codec.h265.mv_col_buf_size) { -- unsigned int num_buffers = -- run->dst->vb2_buf.vb2_queue->num_buffers; -- unsigned int log2_max_luma_coding_block_size = -- sps->log2_min_luma_coding_block_size_minus3 + 3 + -- sps->log2_diff_max_min_luma_coding_block_size; -- unsigned int ctb_size_luma = -- 1 << log2_max_luma_coding_block_size; -- -- /* -- * Each CTB requires a MV col buffer with a specific unit size. -- * Since the address is given with missing lsb bits, 1 KiB is -- * added to each buffer to ensure proper alignment. -- */ -- ctx->codec.h265.mv_col_buf_unit_size = -- DIV_ROUND_UP(ctx->src_fmt.width, ctb_size_luma) * -- DIV_ROUND_UP(ctx->src_fmt.height, ctb_size_luma) * -- CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE + SZ_1K; -- -- ctx->codec.h265.mv_col_buf_size = num_buffers * -- ctx->codec.h265.mv_col_buf_unit_size; -- -- ctx->codec.h265.mv_col_buf = -- dma_alloc_coherent(dev->dev, -- ctx->codec.h265.mv_col_buf_size, -- &ctx->codec.h265.mv_col_buf_addr, -- GFP_KERNEL); -- if (!ctx->codec.h265.mv_col_buf) { -- ctx->codec.h265.mv_col_buf_size = 0; -- // TODO: Abort the process here. -- return; -- } -- } -- - /* Activate H265 engine. */ - cedrus_engine_enable(dev, CEDRUS_CODEC_H265); -+ if (sps->pic_width_in_luma_samples > 2048) -+ cedrus_write(dev, VE_MODE, cedrus_read(dev, VE_MODE) | BIT(21)); - - /* Source offset and length in bits. */ - -@@ -300,18 +389,35 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - src_buf_end_addr = src_buf_addr + - DIV_ROUND_UP(slice_params->bit_size, 8); - -- reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_end_addr); -+ reg = VE_DEC_H265_BITS_END_ADDR_BASE(ALIGN(src_buf_end_addr, 1024) - 1); - cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg); - -- /* Coding tree block address: start at the beginning. */ -- reg = VE_DEC_H265_DEC_CTB_ADDR_X(0) | VE_DEC_H265_DEC_CTB_ADDR_Y(0); -- cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg); -- - cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0); - cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0); - -+ if (pps->tiles_enabled_flag || pps->entropy_coding_sync_enabled_flag) -+ write_entry_point_list(ctx, run); -+ -+ /* Coding tree block address */ -+ reg = 0; -+ if (!slice_params->first_slice_segment_in_pic_flag) { -+ unsigned int ctb_size_luma, width_in_ctb_luma; -+ unsigned int log2_max_luma_coding_block_size; -+ -+ log2_max_luma_coding_block_size = -+ sps->log2_min_luma_coding_block_size_minus3 + 3 + -+ sps->log2_diff_max_min_luma_coding_block_size; -+ ctb_size_luma = 1 << log2_max_luma_coding_block_size; -+ width_in_ctb_luma = DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma); -+ -+ reg = VE_DEC_H265_DEC_CTB_ADDR_X(slice_params->slice_segment_addr % width_in_ctb_luma); -+ reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(slice_params->slice_segment_addr / width_in_ctb_luma); -+ } -+ cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg); -+ - /* Clear the number of correctly-decoded coding tree blocks. */ -- cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0); -+ if (slice_params->first_slice_segment_in_pic_flag) -+ cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0); - - /* Initialize bitstream access. */ - cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_INIT_SWDEC); -@@ -334,6 +440,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE(sps->log2_diff_max_min_luma_coding_block_size) | - VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_LUMA_CODING_BLOCK_SIZE_MINUS3(sps->log2_min_luma_coding_block_size_minus3) | - VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_CHROMA_MINUS8(sps->bit_depth_chroma_minus8) | -+ VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_LUMA_MINUS8(sps->bit_depth_luma_minus8) | - VE_DEC_H265_DEC_SPS_HDR_SEPARATE_COLOUR_PLANE_FLAG(sps->separate_colour_plane_flag) | - VE_DEC_H265_DEC_SPS_HDR_CHROMA_FORMAT_IDC(sps->chroma_format_idc); - -@@ -363,7 +470,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - VE_DEC_H265_DEC_PPS_CTRL1_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG(pps->pps_loop_filter_across_slices_enabled_flag) | - VE_DEC_H265_DEC_PPS_CTRL1_LOOP_FILTER_ACROSS_TILES_ENABLED_FLAG(pps->loop_filter_across_tiles_enabled_flag) | - VE_DEC_H265_DEC_PPS_CTRL1_ENTROPY_CODING_SYNC_ENABLED_FLAG(pps->entropy_coding_sync_enabled_flag) | -- VE_DEC_H265_DEC_PPS_CTRL1_TILES_ENABLED_FLAG(0) | -+ VE_DEC_H265_DEC_PPS_CTRL1_TILES_ENABLED_FLAG(pps->tiles_enabled_flag) | - VE_DEC_H265_DEC_PPS_CTRL1_TRANSQUANT_BYPASS_ENABLE_FLAG(pps->transquant_bypass_enabled_flag) | - VE_DEC_H265_DEC_PPS_CTRL1_WEIGHTED_BIPRED_FLAG(pps->weighted_bipred_flag) | - VE_DEC_H265_DEC_PPS_CTRL1_WEIGHTED_PRED_FLAG(pps->weighted_pred_flag); -@@ -384,7 +491,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLOUR_PLANE_ID(slice_params->colour_plane_id) | - VE_DEC_H265_DEC_SLICE_HDR_INFO0_SLICE_TYPE(slice_params->slice_type) | - VE_DEC_H265_DEC_SLICE_HDR_INFO0_DEPENDENT_SLICE_SEGMENT_FLAG(pps->dependent_slice_segment_flag) | -- VE_DEC_H265_DEC_SLICE_HDR_INFO0_FIRST_SLICE_SEGMENT_IN_PIC_FLAG(1); -+ VE_DEC_H265_DEC_SLICE_HDR_INFO0_FIRST_SLICE_SEGMENT_IN_PIC_FLAG(slice_params->first_slice_segment_in_pic_flag); - - cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO0, reg); - -@@ -401,34 +508,68 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - - chroma_log2_weight_denom = pred_weight_table->luma_log2_weight_denom + - pred_weight_table->delta_chroma_log2_weight_denom; -- reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(0) | -+ reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(slice_params->num_entry_point_offsets) | - VE_DEC_H265_DEC_SLICE_HDR_INFO2_CHROMA_LOG2_WEIGHT_DENOM(chroma_log2_weight_denom) | - VE_DEC_H265_DEC_SLICE_HDR_INFO2_LUMA_LOG2_WEIGHT_DENOM(pred_weight_table->luma_log2_weight_denom); - - cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO2, reg); - -+ cedrus_write(dev, VE_DEC_H265_ENTRY_POINT_OFFSET_ADDR, ctx->codec.h265.entry_points_buf_addr >> 8); -+ - /* Decoded picture size. */ - -- reg = VE_DEC_H265_DEC_PIC_SIZE_WIDTH(ctx->src_fmt.width) | -- VE_DEC_H265_DEC_PIC_SIZE_HEIGHT(ctx->src_fmt.height); -+ reg = VE_DEC_H265_DEC_PIC_SIZE_WIDTH(sps->pic_width_in_luma_samples) | -+ VE_DEC_H265_DEC_PIC_SIZE_HEIGHT(sps->pic_height_in_luma_samples); - - cedrus_write(dev, VE_DEC_H265_DEC_PIC_SIZE, reg); - -- /* Scaling list. */ -+ /* Scaling list */ - -- reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT; -+ if (sps->scaling_list_enabled_flag) { -+ cedrus_h265_write_scaling_list(ctx, run); -+ reg = VE_DEC_H265_SCALING_LIST_CTRL0_ENABLED_FLAG(1); -+ } else { -+ reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT; -+ } - cedrus_write(dev, VE_DEC_H265_SCALING_LIST_CTRL0, reg); - - /* Neightbor information address. */ - reg = VE_DEC_H265_NEIGHBOR_INFO_ADDR_BASE(ctx->codec.h265.neighbor_info_buf_addr); - cedrus_write(dev, VE_DEC_H265_NEIGHBOR_INFO_ADDR, reg); - -+ cedrus_write(dev, VE_DEC_H265_LOW_ADDR, 0); -+ - /* Write decoded picture buffer in pic list. */ - cedrus_h265_frame_info_write_dpb(ctx, run->dst->vb2_buf.index, slice_params->dpb, - slice_params->num_active_dpb_entries); - - /* Output frame. */ - -+ cedrus_buf = vb2_to_cedrus_buffer(ctx->fh.m2m_ctx->cap_q_ctx.q.bufs[run->dst->vb2_buf.index]); -+ if (!cedrus_buf->mv_col_buf_size) { -+ unsigned int ctb_size_luma, width_in_ctb_luma; -+ unsigned int log2_max_luma_coding_block_size; -+ -+ log2_max_luma_coding_block_size = -+ sps->log2_min_luma_coding_block_size_minus3 + 3 + -+ sps->log2_diff_max_min_luma_coding_block_size; -+ ctb_size_luma = 1 << log2_max_luma_coding_block_size; -+ width_in_ctb_luma = DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma); -+ -+ cedrus_buf->mv_col_buf_size = ALIGN(width_in_ctb_luma * -+ DIV_ROUND_UP(sps->pic_height_in_luma_samples, ctb_size_luma) * -+ CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE, 1024); -+ -+ cedrus_buf->mv_col_buf = -+ dma_alloc_coherent(dev->dev, -+ cedrus_buf->mv_col_buf_size, -+ &cedrus_buf->mv_col_buf_dma, -+ GFP_KERNEL); -+ -+ if (!cedrus_buf->mv_col_buf) -+ cedrus_buf->mv_col_buf_size = 0; -+ } -+ - output_pic_list_index = V4L2_HEVC_DPB_ENTRIES_NUM_MAX; - pic_order_cnt[0] = slice_params->slice_pic_order_cnt; - pic_order_cnt[1] = slice_params->slice_pic_order_cnt; -@@ -444,36 +585,36 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - if (slice_params->slice_type != V4L2_HEVC_SLICE_TYPE_I) { - cedrus_h265_ref_pic_list_write(dev, slice_params->dpb, - slice_params->ref_idx_l0, -- slice_params->num_ref_idx_l0_active_minus1 + 1, -- VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST0); -+ slice_params->num_ref_idx_l0_active_minus1 + 1, -+ VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST0); - - if (pps->weighted_pred_flag || pps->weighted_bipred_flag) - cedrus_h265_pred_weight_write(dev, -- pred_weight_table->delta_luma_weight_l0, -- pred_weight_table->luma_offset_l0, -- pred_weight_table->delta_chroma_weight_l0, -- pred_weight_table->chroma_offset_l0, -- slice_params->num_ref_idx_l0_active_minus1 + 1, -- VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L0, -- VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L0); -+ pred_weight_table->delta_luma_weight_l0, -+ pred_weight_table->luma_offset_l0, -+ pred_weight_table->delta_chroma_weight_l0, -+ pred_weight_table->chroma_offset_l0, -+ slice_params->num_ref_idx_l0_active_minus1 + 1, -+ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L0, -+ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L0); - } - - /* Reference picture list 1 (for B frames). */ - if (slice_params->slice_type == V4L2_HEVC_SLICE_TYPE_B) { - cedrus_h265_ref_pic_list_write(dev, slice_params->dpb, - slice_params->ref_idx_l1, -- slice_params->num_ref_idx_l1_active_minus1 + 1, -- VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST1); -+ slice_params->num_ref_idx_l1_active_minus1 + 1, -+ VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST1); - - if (pps->weighted_bipred_flag) - cedrus_h265_pred_weight_write(dev, -- pred_weight_table->delta_luma_weight_l1, -- pred_weight_table->luma_offset_l1, -- pred_weight_table->delta_chroma_weight_l1, -- pred_weight_table->chroma_offset_l1, -- slice_params->num_ref_idx_l1_active_minus1 + 1, -- VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L1, -- VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L1); -+ pred_weight_table->delta_luma_weight_l1, -+ pred_weight_table->luma_offset_l1, -+ pred_weight_table->delta_chroma_weight_l1, -+ pred_weight_table->chroma_offset_l1, -+ slice_params->num_ref_idx_l1_active_minus1 + 1, -+ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L1, -+ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L1); - } - - /* Enable appropriate interruptions. */ -@@ -484,9 +625,6 @@ static int cedrus_h265_start(struct cedrus_ctx *ctx) - { - struct cedrus_dev *dev = ctx->dev; - -- /* The buffer size is calculated at setup time. */ -- ctx->codec.h265.mv_col_buf_size = 0; -- - ctx->codec.h265.neighbor_info_buf = - dma_alloc_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, - &ctx->codec.h265.neighbor_info_buf_addr, -@@ -494,6 +632,17 @@ static int cedrus_h265_start(struct cedrus_ctx *ctx) - if (!ctx->codec.h265.neighbor_info_buf) - return -ENOMEM; - -+ ctx->codec.h265.entry_points_buf = -+ dma_alloc_coherent(dev->dev, CEDRUS_H265_ENTRY_POINTS_BUF_SIZE, -+ &ctx->codec.h265.entry_points_buf_addr, -+ GFP_KERNEL); -+ if (!ctx->codec.h265.entry_points_buf) { -+ dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, -+ ctx->codec.h265.neighbor_info_buf, -+ ctx->codec.h265.neighbor_info_buf_addr); -+ return -ENOMEM; -+ } -+ - return 0; - } - -@@ -501,17 +650,12 @@ static void cedrus_h265_stop(struct cedrus_ctx *ctx) - { - struct cedrus_dev *dev = ctx->dev; - -- if (ctx->codec.h265.mv_col_buf_size > 0) { -- dma_free_coherent(dev->dev, ctx->codec.h265.mv_col_buf_size, -- ctx->codec.h265.mv_col_buf, -- ctx->codec.h265.mv_col_buf_addr); -- -- ctx->codec.h265.mv_col_buf_size = 0; -- } -- - dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, - ctx->codec.h265.neighbor_info_buf, - ctx->codec.h265.neighbor_info_buf_addr); -+ dma_free_coherent(dev->dev, CEDRUS_H265_ENTRY_POINTS_BUF_SIZE, -+ ctx->codec.h265.entry_points_buf, -+ ctx->codec.h265.entry_points_buf_addr); - } - - static void cedrus_h265_trigger(struct cedrus_ctx *ctx) -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -index 87651d6b6227..8d153dbe4f83 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -@@ -496,6 +496,9 @@ - #define VE_DEC_H265_TILE_START_CTB (VE_ENGINE_DEC_H265 + 0x68) - #define VE_DEC_H265_TILE_END_CTB (VE_ENGINE_DEC_H265 + 0x6c) - -+#define VE_DEC_H265_SCALING_LIST_DC_COEF0 (VE_ENGINE_DEC_H265 + 0x78) -+#define VE_DEC_H265_SCALING_LIST_DC_COEF1 (VE_ENGINE_DEC_H265 + 0x7c) -+ - #define VE_DEC_H265_LOW_ADDR (VE_ENGINE_DEC_H265 + 0x80) - - #define VE_DEC_H265_LOW_ADDR_PRIMARY_CHROMA(a) \ -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c -index dbe6f9510641..a0817cae1d69 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c -@@ -433,6 +433,24 @@ static void cedrus_queue_cleanup(struct vb2_queue *vq, u32 state) - } - } - -+static void cedrus_buf_cleanup(struct vb2_buffer *vb) -+{ -+ struct vb2_queue *vq = vb->vb2_queue; -+ struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); -+ -+ if (!V4L2_TYPE_IS_OUTPUT(vq->type)) { -+ struct cedrus_buffer *cedrus_buf; -+ -+ cedrus_buf = vb2_to_cedrus_buffer(vq->bufs[vb->index]); -+ -+ if (cedrus_buf->mv_col_buf_size) -+ dma_free_coherent(ctx->dev->dev, -+ cedrus_buf->mv_col_buf_size, -+ cedrus_buf->mv_col_buf, -+ cedrus_buf->mv_col_buf_dma); -+ } -+} -+ - static int cedrus_buf_out_validate(struct vb2_buffer *vb) - { - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); -@@ -517,6 +497,7 @@ static void cedrus_buf_request_complete(struct vb2_buffer *vb) - static struct vb2_ops cedrus_qops = { - .queue_setup = cedrus_queue_setup, - .buf_prepare = cedrus_buf_prepare, -+ .buf_cleanup = cedrus_buf_cleanup, - .buf_queue = cedrus_buf_queue, - .buf_out_validate = cedrus_buf_out_validate, - .buf_request_complete = cedrus_buf_request_complete, -diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h -index 2de83d9f6d47..19469097c6d4 100644 ---- a/include/media/hevc-ctrls.h -+++ b/include/media/hevc-ctrls.h -@@ -17,11 +17,13 @@ - #define V4L2_CID_MPEG_VIDEO_HEVC_SPS (V4L2_CID_MPEG_BASE + 1008) - #define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_MPEG_BASE + 1009) - #define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_MPEG_BASE + 1010) -+#define V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (V4L2_CID_MPEG_BASE + 1011) - - /* enum v4l2_ctrl_type type values */ - #define V4L2_CTRL_TYPE_HEVC_SPS 0x0120 - #define V4L2_CTRL_TYPE_HEVC_PPS 0x0121 - #define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0122 -+#define V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX 0x0123 - - #define V4L2_HEVC_SLICE_TYPE_B 0 - #define V4L2_HEVC_SLICE_TYPE_P 1 -@@ -95,7 +97,7 @@ struct v4l2_ctrl_hevc_pps { - __u8 lists_modification_present_flag; - __u8 log2_parallel_merge_level_minus2; - __u8 slice_segment_header_extension_present_flag; -- __u8 padding; -+ __u8 scaling_list_enable_flag; - }; - - #define V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE 0x01 -@@ -179,7 +181,21 @@ struct v4l2_ctrl_hevc_slice_params { - /* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */ - struct v4l2_hevc_pred_weight_table pred_weight_table; - -- __u8 padding[2]; -+ __u32 slice_segment_addr; -+ __u32 num_entry_point_offsets; -+ __u32 entry_point_offset_minus1[256]; -+ __u8 first_slice_segment_in_pic_flag; -+ -+ __u8 padding; -+}; -+ -+struct v4l2_ctrl_hevc_scaling_matrix { -+ __u8 scaling_list_4x4[6][16]; -+ __u8 scaling_list_8x8[6][64]; -+ __u8 scaling_list_16x16[6][64]; -+ __u8 scaling_list_32x32[2][64]; -+ __u8 scaling_list_dc_coef_16x16[6]; -+ __u8 scaling_list_dc_coef_32x32[2]; - }; - - #endif --- -2.21.0 - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h -index 2f017a651848..7ca216591c9c 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus.h -+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h -@@ -179,12 +179,16 @@ static inline dma_addr_t cedrus_buf_addr(struct vb2_buffer *buf, - static inline dma_addr_t cedrus_dst_buf_addr(struct cedrus_ctx *ctx, - int index, unsigned int plane) - { -- struct vb2_buffer *buf; -+ struct vb2_buffer *buf = NULL; -+ struct vb2_queue *vq; - - if (index < 0) - return 0; - -- buf = ctx->fh.m2m_ctx->cap_q_ctx.q.bufs[index]; -+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); -+ if (vq) -+ buf = vb2_get_buffer(vq, index); -+ - return buf ? cedrus_buf_addr(buf, &ctx->dst_fmt, plane) : 0; - } - diff --git a/projects/Allwinner/patches/linux/0011-cedrus-h264-4k.patch b/projects/Allwinner/patches/linux/0011-cedrus-h264-4k.patch deleted file mode 100644 index e2d18f2679f..00000000000 --- a/projects/Allwinner/patches/linux/0011-cedrus-h264-4k.patch +++ /dev/null @@ -1,349 +0,0 @@ -From 6a900f36a70f921886f05373846368ca6f09446e Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Sat, 25 May 2019 14:16:55 +0200 -Subject: [PATCH 5/5] cedrus h264 4k - -Signed-off-by: Jernej Skrabec ---- - drivers/staging/media/sunxi/cedrus/cedrus.h | 12 +- - .../staging/media/sunxi/cedrus/cedrus_h264.c | 117 +++++++++++------- - .../staging/media/sunxi/cedrus/cedrus_h265.c | 4 +- - .../staging/media/sunxi/cedrus/cedrus_hw.c | 11 +- - .../staging/media/sunxi/cedrus/cedrus_hw.h | 3 +- - .../staging/media/sunxi/cedrus/cedrus_mpeg2.c | 2 +- - .../staging/media/sunxi/cedrus/cedrus_regs.h | 4 + - .../staging/media/sunxi/cedrus/cedrus_video.c | 4 +- - 8 files changed, 98 insertions(+), 59 deletions(-) - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h -index b518c5613fdf..ee00449d3345 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus.h -+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h -@@ -118,14 +118,18 @@ struct cedrus_ctx { - - union { - struct { -- void *mv_col_buf; -- dma_addr_t mv_col_buf_dma; -- ssize_t mv_col_buf_field_size; -- ssize_t mv_col_buf_size; - void *pic_info_buf; - dma_addr_t pic_info_buf_dma; - void *neighbor_info_buf; - dma_addr_t neighbor_info_buf_dma; -+ -+ void *deblk_buf; -+ dma_addr_t deblk_buf_dma; -+ ssize_t deblk_buf_size; -+ -+ void *intra_pred_buf; -+ dma_addr_t intra_pred_buf_dma; -+ ssize_t intra_pred_buf_size; - } h264; - struct { - void *neighbor_info_buf; -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c -index dcb8d3837869..4fafaf2c6c0a 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c -@@ -55,16 +55,14 @@ static void cedrus_h264_write_sram(struct cedrus_dev *dev, - } - - static dma_addr_t cedrus_h264_mv_col_buf_addr(struct cedrus_ctx *ctx, -- unsigned int position, -+ struct cedrus_buffer *buf, - unsigned int field) - { -- dma_addr_t addr = ctx->codec.h264.mv_col_buf_dma; -- -- /* Adjust for the position */ -- addr += position * ctx->codec.h264.mv_col_buf_field_size * 2; -+ dma_addr_t addr = buf->mv_col_buf_dma; - - /* Adjust for the field */ -- addr += field * ctx->codec.h264.mv_col_buf_field_size; -+ if (field) -+ addr += buf->mv_col_buf_size / 2; - - return addr; - } -@@ -76,7 +74,6 @@ static void cedrus_fill_ref_pic(struct cedrus_ctx *ctx, - struct cedrus_h264_sram_ref_pic *pic) - { - struct vb2_buffer *vbuf = &buf->m2m_buf.vb.vb2_buf; -- unsigned int position = buf->codec.h264.position; - - pic->top_field_order_cnt = cpu_to_le32(top_field_order_cnt); - pic->bottom_field_order_cnt = cpu_to_le32(bottom_field_order_cnt); -@@ -85,9 +82,9 @@ static void cedrus_fill_ref_pic(struct cedrus_ctx *ctx, - pic->luma_ptr = cpu_to_le32(cedrus_buf_addr(vbuf, &ctx->dst_fmt, 0)); - pic->chroma_ptr = cpu_to_le32(cedrus_buf_addr(vbuf, &ctx->dst_fmt, 1)); - pic->mv_col_top_ptr = -- cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, position, 0)); -+ cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, buf, 0)); - pic->mv_col_bot_ptr = -- cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, position, 1)); -+ cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, buf, 1)); - } - - static void cedrus_write_frame_list(struct cedrus_ctx *ctx, -@@ -145,6 +142,28 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, - output_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf); - output_buf->codec.h264.position = position; - -+ if (!output_buf->mv_col_buf_size) { -+ const struct v4l2_ctrl_h264_sps *sps = run->h264.sps; -+ unsigned int field_size; -+ -+ field_size = DIV_ROUND_UP(ctx->src_fmt.width, 16) * -+ DIV_ROUND_UP(ctx->src_fmt.height, 16) * 16; -+ if (!(sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE)) -+ field_size = field_size * 2; -+ if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY)) -+ field_size = field_size * 2; -+ -+ output_buf->mv_col_buf_size = field_size * 2; -+ output_buf->mv_col_buf = -+ dma_alloc_coherent(dev->dev, -+ output_buf->mv_col_buf_size, -+ &output_buf->mv_col_buf_dma, -+ GFP_KERNEL); -+ -+ if (!output_buf->mv_col_buf) -+ output_buf->mv_col_buf_size = 0; -+ } -+ - if (slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) - output_buf->codec.h264.pic_type = CEDRUS_H264_PIC_TYPE_FIELD; - else if (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD) -@@ -338,6 +357,14 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, - VE_H264_VLD_ADDR_FIRST | VE_H264_VLD_ADDR_VALID | - VE_H264_VLD_ADDR_LAST); - -+ if (((sps->pic_width_in_mbs_minus1 + 1) * 16) > 2048) { -+ cedrus_write(dev, VE_DBLK_INTRAPRED_BUF_CTRL, 0x5); -+ cedrus_write(dev, VE_DBLK_DRAM_BUF_ADDR, -+ ctx->codec.h264.deblk_buf_dma); -+ cedrus_write(dev, VE_INTRAPRED_DRAM_BUF_ADDR, -+ ctx->codec.h264.intra_pred_buf_dma); -+ } -+ - /* - * FIXME: Since the bitstream parsing is done in software, and - * in userspace, this shouldn't be needed anymore. But it -@@ -476,7 +503,8 @@ static void cedrus_h264_setup(struct cedrus_ctx *ctx, - { - struct cedrus_dev *dev = ctx->dev; - -- cedrus_engine_enable(dev, CEDRUS_CODEC_H264); -+ cedrus_engine_enable(dev, CEDRUS_CODEC_H264, -+ ctx->src_fmt.width); - - cedrus_write(dev, VE_H264_SDROT_CTRL, 0); - cedrus_write(dev, VE_H264_EXTRA_BUFFER1, -@@ -493,8 +521,6 @@ static void cedrus_h264_setup(struct cedrus_ctx *ctx, - static int cedrus_h264_start(struct cedrus_ctx *ctx) - { - struct cedrus_dev *dev = ctx->dev; -- unsigned int field_size; -- unsigned int mv_col_size; - int ret; - - /* -@@ -526,44 +552,42 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx) - goto err_pic_buf; - } - -- field_size = DIV_ROUND_UP(ctx->src_fmt.width, 16) * -- DIV_ROUND_UP(ctx->src_fmt.height, 16) * 16; -- -- /* -- * FIXME: This is actually conditional to -- * V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE not being set, we -- * might have to rework this if memory efficiency ever is -- * something we need to work on. -- */ -- field_size = field_size * 2; -+ if (ctx->src_fmt.width > 2048) { -+ ctx->codec.h264.deblk_buf_size = -+ ALIGN(ctx->src_fmt.width, 32) * 12; -+ ctx->codec.h264.deblk_buf = -+ dma_alloc_coherent(dev->dev, -+ ctx->codec.h264.deblk_buf_size, -+ &ctx->codec.h264.deblk_buf_dma, -+ GFP_KERNEL); -+ if (!ctx->codec.h264.deblk_buf) { -+ ret = -ENOMEM; -+ goto err_neighbor_buf; -+ } - -- /* -- * FIXME: This is actually conditional to -- * V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY not being set, we might -- * have to rework this if memory efficiency ever is something -- * we need to work on. -- */ -- field_size = field_size * 2; -- ctx->codec.h264.mv_col_buf_field_size = field_size; -- -- mv_col_size = field_size * 2 * CEDRUS_H264_FRAME_NUM; -- ctx->codec.h264.mv_col_buf_size = mv_col_size; -- ctx->codec.h264.mv_col_buf = dma_alloc_coherent(dev->dev, -- ctx->codec.h264.mv_col_buf_size, -- &ctx->codec.h264.mv_col_buf_dma, -- GFP_KERNEL); -- if (!ctx->codec.h264.mv_col_buf) { -- ret = -ENOMEM; -- goto err_neighbor_buf; -+ ctx->codec.h264.intra_pred_buf_size = -+ ALIGN(ctx->src_fmt.width, 64) * 5; -+ ctx->codec.h264.intra_pred_buf = -+ dma_alloc_coherent(dev->dev, -+ ctx->codec.h264.intra_pred_buf_size, -+ &ctx->codec.h264.intra_pred_buf_dma, -+ GFP_KERNEL); -+ if (!ctx->codec.h264.intra_pred_buf) { -+ ret = -ENOMEM; -+ goto err_deblk_buf; -+ } - } - - return 0; - -+err_deblk_buf: -+ dma_free_coherent(dev->dev, ctx->codec.h264.deblk_buf_size, -+ ctx->codec.h264.deblk_buf, -+ ctx->codec.h264.deblk_buf_dma); - err_neighbor_buf: - dma_free_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE, - ctx->codec.h264.neighbor_info_buf, - ctx->codec.h264.neighbor_info_buf_dma); -- - err_pic_buf: - dma_free_coherent(dev->dev, CEDRUS_PIC_INFO_BUF_SIZE, - ctx->codec.h264.pic_info_buf, -@@ -575,15 +599,20 @@ static void cedrus_h264_stop(struct cedrus_ctx *ctx) - { - struct cedrus_dev *dev = ctx->dev; - -- dma_free_coherent(dev->dev, ctx->codec.h264.mv_col_buf_size, -- ctx->codec.h264.mv_col_buf, -- ctx->codec.h264.mv_col_buf_dma); - dma_free_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE, - ctx->codec.h264.neighbor_info_buf, - ctx->codec.h264.neighbor_info_buf_dma); - dma_free_coherent(dev->dev, CEDRUS_PIC_INFO_BUF_SIZE, - ctx->codec.h264.pic_info_buf, - ctx->codec.h264.pic_info_buf_dma); -+ if (ctx->codec.h264.deblk_buf_size) -+ dma_free_coherent(dev->dev, ctx->codec.h264.deblk_buf_size, -+ ctx->codec.h264.deblk_buf, -+ ctx->codec.h264.deblk_buf_dma); -+ if (ctx->codec.h264.intra_pred_buf_size) -+ dma_free_coherent(dev->dev, ctx->codec.h264.intra_pred_buf_size, -+ ctx->codec.h264.intra_pred_buf, -+ ctx->codec.h264.intra_pred_buf_dma); - } - - static void cedrus_h264_trigger(struct cedrus_ctx *ctx) -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -index 51ee459b2d21..f915429e9c88 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -@@ -337,9 +337,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - pred_weight_table = &slice_params->pred_weight_table; - - /* Activate H265 engine. */ -- cedrus_engine_enable(dev, CEDRUS_CODEC_H265); -- if (sps->pic_width_in_luma_samples > 2048) -- cedrus_write(dev, VE_MODE, cedrus_read(dev, VE_MODE) | BIT(21)); -+ cedrus_engine_enable(dev, CEDRUS_CODEC_H265, ctx->src_fmt.width); - - /* Source offset and length in bits. */ - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c -index 7d2f6eedfc28..9503d395855b 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c -@@ -30,7 +30,8 @@ - #include "cedrus_hw.h" - #include "cedrus_regs.h" - --int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec) -+int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec, -+ unsigned int width) - { - u32 reg = 0; - -@@ -58,6 +59,11 @@ int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec) - return -EINVAL; - } - -+ if (width >= 4096) -+ reg |= BIT(22); -+ if (width > 2048) -+ reg |= BIT(21); -+ - cedrus_write(dev, VE_MODE, reg); - - return 0; -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h -index 27d0882397aa..0e67c69812be 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h -@@ -16,7 +16,8 @@ - #ifndef _CEDRUS_HW_H_ - #define _CEDRUS_HW_H_ - --int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec); -+int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec, -+ unsigned int width); - void cedrus_engine_disable(struct cedrus_dev *dev); - - void cedrus_dst_format_set(struct cedrus_dev *dev, -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c b/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c -index 13c34927bad5..fc00a2cbf9bf 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c -@@ -96,7 +96,7 @@ static void cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) - quantization = run->mpeg2.quantization; - - /* Activate MPEG engine. */ -- cedrus_engine_enable(dev, CEDRUS_CODEC_MPEG2); -+ cedrus_engine_enable(dev, CEDRUS_CODEC_MPEG2, ctx->src_fmt.width); - - /* Set intra quantization matrix. */ - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -index a2931f322c7a..df000b7c99be 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -@@ -41,6 +41,10 @@ - #define VE_MODE_DEC_H264 (0x01 << 0) - #define VE_MODE_DEC_MPEG (0x00 << 0) - -+#define VE_DBLK_INTRAPRED_BUF_CTRL 0x50 -+#define VE_DBLK_DRAM_BUF_ADDR 0x54 -+#define VE_INTRAPRED_DRAM_BUF_ADDR 0x58 -+ - #define VE_PRIMARY_CHROMA_BUF_LEN 0xc4 - #define VE_PRIMARY_FB_LINE_STRIDE 0xc8 - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c -index a0817cae1d69..d27a9e82ff91 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c -@@ -29,8 +29,8 @@ - - #define CEDRUS_MIN_WIDTH 16U - #define CEDRUS_MIN_HEIGHT 16U --#define CEDRUS_MAX_WIDTH 3840U --#define CEDRUS_MAX_HEIGHT 2160U -+#define CEDRUS_MAX_WIDTH 4096U -+#define CEDRUS_MAX_HEIGHT 2768U - - static struct cedrus_format cedrus_formats[] = { - { --- -2.21.0 -