diff options
author | Mauro Carvalho Chehab <mchehab@kernel.org> | 2022-03-14 12:43:10 +0100 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@kernel.org> | 2022-03-18 05:58:34 +0100 |
commit | e7b8153e2a4f0c9c8d1450aa7328d54ea64fe8b2 (patch) | |
tree | 66b31cbad2bcee3f115a8c910cfebefcb9f4e048 /drivers/media/platform/sti/hva | |
parent | 43ecec16c4face9a59e81771e7cbff4671c62117 (diff) |
media: platform: place stm32/ and sti/ under st/ dir
As the end goal is to have platform drivers split by vendor,
move both stm32/ and sti/ for them to be inside st/ directory.
Acked-by: Hugues Fruchet <hugues.fruchet@st.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Diffstat (limited to 'drivers/media/platform/sti/hva')
-rw-r--r-- | drivers/media/platform/sti/hva/Kconfig | 26 | ||||
-rw-r--r-- | drivers/media/platform/sti/hva/Makefile | 4 | ||||
-rw-r--r-- | drivers/media/platform/sti/hva/hva-debugfs.c | 396 | ||||
-rw-r--r-- | drivers/media/platform/sti/hva/hva-h264.c | 1063 | ||||
-rw-r--r-- | drivers/media/platform/sti/hva/hva-hw.c | 585 | ||||
-rw-r--r-- | drivers/media/platform/sti/hva/hva-hw.h | 45 | ||||
-rw-r--r-- | drivers/media/platform/sti/hva/hva-mem.c | 62 | ||||
-rw-r--r-- | drivers/media/platform/sti/hva/hva-mem.h | 34 | ||||
-rw-r--r-- | drivers/media/platform/sti/hva/hva-v4l2.c | 1476 | ||||
-rw-r--r-- | drivers/media/platform/sti/hva/hva.h | 409 |
10 files changed, 0 insertions, 4100 deletions
diff --git a/drivers/media/platform/sti/hva/Kconfig b/drivers/media/platform/sti/hva/Kconfig deleted file mode 100644 index 5651667bcc54..000000000000 --- a/drivers/media/platform/sti/hva/Kconfig +++ /dev/null @@ -1,26 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -config VIDEO_STI_HVA - tristate "STMicroelectronics HVA multi-format video encoder V4L2 driver" - depends on V4L_MEM2MEM_DRIVERS - depends on VIDEO_DEV && VIDEO_V4L2 - depends on ARCH_STI || COMPILE_TEST - select VIDEOBUF2_DMA_CONTIG - select V4L2_MEM2MEM_DEV - help - This V4L2 driver enables HVA (Hardware Video Accelerator) multi-format - video encoder of STMicroelectronics SoC, allowing hardware encoding of - raw uncompressed formats in various compressed video bitstreams format. - - To compile this driver as a module, choose M here: - the module will be called st-hva. - -config VIDEO_STI_HVA_DEBUGFS - bool "Export STMicroelectronics HVA internals in debugfs" - depends on VIDEO_STI_HVA - depends on DEBUG_FS - help - Select this to see information about the internal state and the last - operation of STMicroelectronics HVA multi-format video encoder in - debugfs. - - Choose N unless you know you need this. diff --git a/drivers/media/platform/sti/hva/Makefile b/drivers/media/platform/sti/hva/Makefile deleted file mode 100644 index b5a5478bdd01..000000000000 --- a/drivers/media/platform/sti/hva/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_VIDEO_STI_HVA) += st-hva.o -st-hva-y := hva-v4l2.o hva-hw.o hva-mem.o hva-h264.o -st-hva-$(CONFIG_VIDEO_STI_HVA_DEBUGFS) += hva-debugfs.o diff --git a/drivers/media/platform/sti/hva/hva-debugfs.c b/drivers/media/platform/sti/hva/hva-debugfs.c deleted file mode 100644 index a86a07b6fbc7..000000000000 --- a/drivers/media/platform/sti/hva/hva-debugfs.c +++ /dev/null @@ -1,396 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) STMicroelectronics SA 2015 - * Authors: Yannick Fertre <yannick.fertre@st.com> - * Hugues Fruchet <hugues.fruchet@st.com> - */ - -#include <linux/debugfs.h> - -#include "hva.h" -#include "hva-hw.h" - -static void format_ctx(struct seq_file *s, struct hva_ctx *ctx) -{ - struct hva_streaminfo *stream = &ctx->streaminfo; - struct hva_frameinfo *frame = &ctx->frameinfo; - struct hva_controls *ctrls = &ctx->ctrls; - struct hva_ctx_dbg *dbg = &ctx->dbg; - u32 bitrate_mode, aspect, entropy, vui_sar, sei_fp; - - seq_printf(s, "|-%s\n |\n", ctx->name); - - seq_printf(s, " |-[%sframe info]\n", - ctx->flags & HVA_FLAG_FRAMEINFO ? "" : "default "); - seq_printf(s, " | |- pixel format=%4.4s\n" - " | |- wxh=%dx%d\n" - " | |- wxh (w/ encoder alignment constraint)=%dx%d\n" - " |\n", - (char *)&frame->pixelformat, - frame->width, frame->height, - frame->aligned_width, frame->aligned_height); - - seq_printf(s, " |-[%sstream info]\n", - ctx->flags & HVA_FLAG_STREAMINFO ? "" : "default "); - seq_printf(s, " | |- stream format=%4.4s\n" - " | |- wxh=%dx%d\n" - " | |- %s\n" - " | |- %s\n" - " |\n", - (char *)&stream->streamformat, - stream->width, stream->height, - stream->profile, stream->level); - - bitrate_mode = V4L2_CID_MPEG_VIDEO_BITRATE_MODE; - aspect = V4L2_CID_MPEG_VIDEO_ASPECT; - seq_puts(s, " |-[parameters]\n"); - seq_printf(s, " | |- %s\n" - " | |- bitrate=%d bps\n" - " | |- GOP size=%d\n" - " | |- video aspect=%s\n" - " | |- framerate=%d/%d\n", - v4l2_ctrl_get_menu(bitrate_mode)[ctrls->bitrate_mode], - ctrls->bitrate, - ctrls->gop_size, - v4l2_ctrl_get_menu(aspect)[ctrls->aspect], - ctrls->time_per_frame.denominator, - ctrls->time_per_frame.numerator); - - entropy = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE; - vui_sar = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC; - sei_fp = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE; - if (stream->streamformat == V4L2_PIX_FMT_H264) { - seq_printf(s, " | |- %s entropy mode\n" - " | |- CPB size=%d kB\n" - " | |- DCT8x8 enable=%s\n" - " | |- qpmin=%d\n" - " | |- qpmax=%d\n" - " | |- PAR enable=%s\n" - " | |- PAR id=%s\n" - " | |- SEI frame packing enable=%s\n" - " | |- SEI frame packing type=%s\n", - v4l2_ctrl_get_menu(entropy)[ctrls->entropy_mode], - ctrls->cpb_size, - ctrls->dct8x8 ? "true" : "false", - ctrls->qpmin, - ctrls->qpmax, - ctrls->vui_sar ? "true" : "false", - v4l2_ctrl_get_menu(vui_sar)[ctrls->vui_sar_idc], - ctrls->sei_fp ? "true" : "false", - v4l2_ctrl_get_menu(sei_fp)[ctrls->sei_fp_type]); - } - - if (ctx->sys_errors || ctx->encode_errors || ctx->frame_errors) { - seq_puts(s, " |\n |-[errors]\n"); - seq_printf(s, " | |- system=%d\n" - " | |- encoding=%d\n" - " | |- frame=%d\n", - ctx->sys_errors, - ctx->encode_errors, - ctx->frame_errors); - } - - seq_puts(s, " |\n |-[performances]\n"); - seq_printf(s, " | |- frames encoded=%d\n" - " | |- avg HW processing duration (0.1ms)=%d [min=%d, max=%d]\n" - " | |- avg encoding period (0.1ms)=%d [min=%d, max=%d]\n" - " | |- avg fps (0.1Hz)=%d\n" - " | |- max reachable fps (0.1Hz)=%d\n" - " | |- avg bitrate (kbps)=%d [min=%d, max=%d]\n" - " | |- last bitrate (kbps)=%d\n", - dbg->cnt_duration, - dbg->avg_duration, - dbg->min_duration, - dbg->max_duration, - dbg->avg_period, - dbg->min_period, - dbg->max_period, - dbg->avg_fps, - dbg->max_fps, - dbg->avg_bitrate, - dbg->min_bitrate, - dbg->max_bitrate, - dbg->last_bitrate); -} - -/* - * performance debug info - */ -void hva_dbg_perf_begin(struct hva_ctx *ctx) -{ - u64 div; - u32 period; - u32 bitrate; - struct hva_ctx_dbg *dbg = &ctx->dbg; - ktime_t prev = dbg->begin; - - dbg->begin = ktime_get(); - - if (dbg->is_valid_period) { - /* encoding period */ - div = (u64)ktime_us_delta(dbg->begin, prev); - do_div(div, 100); - period = (u32)div; - dbg->min_period = min(period, dbg->min_period); - dbg->max_period = max(period, dbg->max_period); - dbg->total_period += period; - dbg->cnt_period++; - - /* - * minimum and maximum bitrates are based on the - * encoding period values upon a window of 32 samples - */ - dbg->window_duration += period; - dbg->cnt_window++; - if (dbg->cnt_window >= 32) { - /* - * bitrate in kbps = (size * 8 / 1000) / - * (duration / 10000) - * = size * 80 / duration - */ - if (dbg->window_duration > 0) { - div = (u64)dbg->window_stream_size * 80; - do_div(div, dbg->window_duration); - bitrate = (u32)div; - dbg->last_bitrate = bitrate; - dbg->min_bitrate = min(bitrate, - dbg->min_bitrate); - dbg->max_bitrate = max(bitrate, - dbg->max_bitrate); - } - dbg->window_stream_size = 0; - dbg->window_duration = 0; - dbg->cnt_window = 0; - } - } - - /* - * filter sequences valid for performance: - * - begin/begin (no stream available) is an invalid sequence - * - begin/end is a valid sequence - */ - dbg->is_valid_period = false; -} - -void hva_dbg_perf_end(struct hva_ctx *ctx, struct hva_stream *stream) -{ - struct device *dev = ctx_to_dev(ctx); - u64 div; - u32 duration; - u32 bytesused; - u32 timestamp; - struct hva_ctx_dbg *dbg = &ctx->dbg; - ktime_t end = ktime_get(); - - /* stream bytesused and timestamp in us */ - bytesused = vb2_get_plane_payload(&stream->vbuf.vb2_buf, 0); - div = stream->vbuf.vb2_buf.timestamp; - do_div(div, 1000); - timestamp = (u32)div; - - /* encoding duration */ - div = (u64)ktime_us_delta(end, dbg->begin); - - dev_dbg(dev, - "%s perf stream[%d] dts=%d encoded using %d bytes in %d us", - ctx->name, - stream->vbuf.sequence, - timestamp, - bytesused, (u32)div); - - do_div(div, 100); - duration = (u32)div; - - dbg->min_duration = min(duration, dbg->min_duration); - dbg->max_duration = max(duration, dbg->max_duration); - dbg->total_duration += duration; - dbg->cnt_duration++; - - /* - * the average bitrate is based on the total stream size - * and the total encoding periods - */ - dbg->total_stream_size += bytesused; - dbg->window_stream_size += bytesused; - - dbg->is_valid_period = true; -} - -static void hva_dbg_perf_compute(struct hva_ctx *ctx) -{ - u64 div; - struct hva_ctx_dbg *dbg = &ctx->dbg; - - if (dbg->cnt_duration > 0) { - div = (u64)dbg->total_duration; - do_div(div, dbg->cnt_duration); - dbg->avg_duration = (u32)div; - } else { - dbg->avg_duration = 0; - } - - if (dbg->total_duration > 0) { - div = (u64)dbg->cnt_duration * 100000; - do_div(div, dbg->total_duration); - dbg->max_fps = (u32)div; - } else { - dbg->max_fps = 0; - } - - if (dbg->cnt_period > 0) { - div = (u64)dbg->total_period; - do_div(div, dbg->cnt_period); - dbg->avg_period = (u32)div; - } else { - dbg->avg_period = 0; - } - - if (dbg->total_period > 0) { - div = (u64)dbg->cnt_period * 100000; - do_div(div, dbg->total_period); - dbg->avg_fps = (u32)div; - } else { - dbg->avg_fps = 0; - } - - if (dbg->total_period > 0) { - /* - * bitrate in kbps = (video size * 8 / 1000) / - * (video duration / 10000) - * = video size * 80 / video duration - */ - div = (u64)dbg->total_stream_size * 80; - do_div(div, dbg->total_period); - dbg->avg_bitrate = (u32)div; - } else { - dbg->avg_bitrate = 0; - } -} - -/* - * device debug info - */ - -static int device_show(struct seq_file *s, void *data) -{ - struct hva_dev *hva = s->private; - - seq_printf(s, "[%s]\n", hva->v4l2_dev.name); - seq_printf(s, "registered as /dev/video%d\n", hva->vdev->num); - - return 0; -} - -static int encoders_show(struct seq_file *s, void *data) -{ - struct hva_dev *hva = s->private; - unsigned int i = 0; - - seq_printf(s, "[encoders]\n|- %d registered encoders:\n", - hva->nb_of_encoders); - - while (hva->encoders[i]) { - seq_printf(s, "|- %s: %4.4s => %4.4s\n", hva->encoders[i]->name, - (char *)&hva->encoders[i]->pixelformat, - (char *)&hva->encoders[i]->streamformat); - i++; - } - - return 0; -} - -static int last_show(struct seq_file *s, void *data) -{ - struct hva_dev *hva = s->private; - struct hva_ctx *last_ctx = &hva->dbg.last_ctx; - - if (last_ctx->flags & HVA_FLAG_STREAMINFO) { - seq_puts(s, "[last encoding]\n"); - - hva_dbg_perf_compute(last_ctx); - format_ctx(s, last_ctx); - } else { - seq_puts(s, "[no information recorded about last encoding]\n"); - } - - return 0; -} - -static int regs_show(struct seq_file *s, void *data) -{ - struct hva_dev *hva = s->private; - - hva_hw_dump_regs(hva, s); - - return 0; -} - -#define hva_dbg_create_entry(name) \ - debugfs_create_file(#name, 0444, hva->dbg.debugfs_entry, hva, \ - &name##_fops) - -DEFINE_SHOW_ATTRIBUTE(device); -DEFINE_SHOW_ATTRIBUTE(encoders); -DEFINE_SHOW_ATTRIBUTE(last); -DEFINE_SHOW_ATTRIBUTE(regs); - -void hva_debugfs_create(struct hva_dev *hva) -{ - hva->dbg.debugfs_entry = debugfs_create_dir(HVA_NAME, NULL); - - hva_dbg_create_entry(device); - hva_dbg_create_entry(encoders); - hva_dbg_create_entry(last); - hva_dbg_create_entry(regs); -} - -void hva_debugfs_remove(struct hva_dev *hva) -{ - debugfs_remove_recursive(hva->dbg.debugfs_entry); - hva->dbg.debugfs_entry = NULL; -} - -/* - * context (instance) debug info - */ - -static int ctx_show(struct seq_file *s, void *data) -{ - struct hva_ctx *ctx = s->private; - - seq_printf(s, "[running encoding %d]\n", ctx->id); - - hva_dbg_perf_compute(ctx); - format_ctx(s, ctx); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ctx); - -void hva_dbg_ctx_create(struct hva_ctx *ctx) -{ - struct hva_dev *hva = ctx->hva_dev; - char name[4] = ""; - - ctx->dbg.min_duration = UINT_MAX; - ctx->dbg.min_period = UINT_MAX; - ctx->dbg.min_bitrate = UINT_MAX; - - snprintf(name, sizeof(name), "%d", hva->instance_id); - - ctx->dbg.debugfs_entry = debugfs_create_file(name, 0444, - hva->dbg.debugfs_entry, - ctx, &ctx_fops); -} - -void hva_dbg_ctx_remove(struct hva_ctx *ctx) -{ - struct hva_dev *hva = ctx->hva_dev; - - if (ctx->flags & HVA_FLAG_STREAMINFO) - /* save context before removing */ - memcpy(&hva->dbg.last_ctx, ctx, sizeof(*ctx)); - - debugfs_remove(ctx->dbg.debugfs_entry); -} diff --git a/drivers/media/platform/sti/hva/hva-h264.c b/drivers/media/platform/sti/hva/hva-h264.c deleted file mode 100644 index 98cb00d2d868..000000000000 --- a/drivers/media/platform/sti/hva/hva-h264.c +++ /dev/null @@ -1,1063 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) STMicroelectronics SA 2015 - * Authors: Yannick Fertre <yannick.fertre@st.com> - * Hugues Fruchet <hugues.fruchet@st.com> - */ - -#include "hva.h" -#include "hva-hw.h" - -#define MAX_SPS_PPS_SIZE 128 - -#define BITSTREAM_OFFSET_MASK 0x7F - -/* video max size*/ -#define H264_MAX_SIZE_W 1920 -#define H264_MAX_SIZE_H 1920 - -/* macroBlocs number (width & height) */ -#define MB_W(w) ((w + 0xF) / 0x10) -#define MB_H(h) ((h + 0xF) / 0x10) - -/* formula to get temporal or spatial data size */ -#define DATA_SIZE(w, h) (MB_W(w) * MB_H(h) * 16) - -#define SEARCH_WINDOW_BUFFER_MAX_SIZE(w) ((4 * MB_W(w) + 42) * 256 * 3 / 2) -#define CABAC_CONTEXT_BUFFER_MAX_SIZE(w) (MB_W(w) * 16) -#define CTX_MB_BUFFER_MAX_SIZE(w) (MB_W(w) * 16 * 8) -#define SLICE_HEADER_SIZE (4 * 16) -#define BRC_DATA_SIZE (5 * 16) - -/* source buffer copy in YUV 420 MB-tiled format with size=16*256*3/2 */ -#define CURRENT_WINDOW_BUFFER_MAX_SIZE (16 * 256 * 3 / 2) - -/* - * 4 lines of pixels (in Luma, Chroma blue and Chroma red) of top MB - * for deblocking with size=4*16*MBx*2 - */ -#define LOCAL_RECONSTRUCTED_BUFFER_MAX_SIZE(w) (4 * 16 * MB_W(w) * 2) - -/* factor for bitrate and cpb buffer size max values if profile >= high */ -#define H264_FACTOR_HIGH 1200 - -/* factor for bitrate and cpb buffer size max values if profile < high */ -#define H264_FACTOR_BASELINE 1000 - -/* number of bytes for NALU_TYPE_FILLER_DATA header and footer */ -#define H264_FILLER_DATA_SIZE 6 - -struct h264_profile { - enum v4l2_mpeg_video_h264_level level; - u32 max_mb_per_seconds; - u32 max_frame_size; - u32 max_bitrate; - u32 max_cpb_size; - u32 min_comp_ratio; -}; - -static const struct h264_profile h264_infos_list[] = { - {V4L2_MPEG_VIDEO_H264_LEVEL_1_0, 1485, 99, 64, 175, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_1B, 1485, 99, 128, 350, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_1_1, 3000, 396, 192, 500, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_1_2, 6000, 396, 384, 1000, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_1_3, 11880, 396, 768, 2000, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_2_0, 11880, 396, 2000, 2000, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_2_1, 19800, 792, 4000, 4000, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_2_2, 20250, 1620, 4000, 4000, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_3_0, 40500, 1620, 10000, 10000, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_3_1, 108000, 3600, 14000, 14000, 4}, - {V4L2_MPEG_VIDEO_H264_LEVEL_3_2, 216000, 5120, 20000, 20000, 4}, - {V4L2_MPEG_VIDEO_H264_LEVEL_4_0, 245760, 8192, 20000, 25000, 4}, - {V4L2_MPEG_VIDEO_H264_LEVEL_4_1, 245760, 8192, 50000, 62500, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_4_2, 522240, 8704, 50000, 62500, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_5_0, 589824, 22080, 135000, 135000, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_5_1, 983040, 36864, 240000, 240000, 2} -}; - -enum hva_brc_type { - BRC_TYPE_NONE = 0, - BRC_TYPE_CBR = 1, - BRC_TYPE_VBR = 2, - BRC_TYPE_VBR_LOW_DELAY = 3 -}; - -enum hva_entropy_coding_mode { - CAVLC = 0, - CABAC = 1 -}; - -enum hva_picture_coding_type { - PICTURE_CODING_TYPE_I = 0, - PICTURE_CODING_TYPE_P = 1, - PICTURE_CODING_TYPE_B = 2 -}; - -enum hva_h264_sampling_mode { - SAMPLING_MODE_NV12 = 0, - SAMPLING_MODE_UYVY = 1, - SAMPLING_MODE_RGB3 = 3, - SAMPLING_MODE_XRGB4 = 4, - SAMPLING_MODE_NV21 = 8, - SAMPLING_MODE_VYUY = 9, - SAMPLING_MODE_BGR3 = 11, - SAMPLING_MODE_XBGR4 = 12, - SAMPLING_MODE_RGBX4 = 20, - SAMPLING_MODE_BGRX4 = 28 -}; - -enum hva_h264_nalu_type { - NALU_TYPE_UNKNOWN = 0, - NALU_TYPE_SLICE = 1, - NALU_TYPE_SLICE_DPA = 2, - NALU_TYPE_SLICE_DPB = 3, - NALU_TYPE_SLICE_DPC = 4, - NALU_TYPE_SLICE_IDR = 5, - NALU_TYPE_SEI = 6, - NALU_TYPE_SPS = 7, - NALU_TYPE_PPS = 8, - NALU_TYPE_AU_DELIMITER = 9, - NALU_TYPE_SEQ_END = 10, - NALU_TYPE_STREAM_END = 11, - NALU_TYPE_FILLER_DATA = 12, - NALU_TYPE_SPS_EXT = 13, - NALU_TYPE_PREFIX_UNIT = 14, - NALU_TYPE_SUBSET_SPS = 15, - NALU_TYPE_SLICE_AUX = 19, - NALU_TYPE_SLICE_EXT = 20 -}; - -enum hva_h264_sei_payload_type { - SEI_BUFFERING_PERIOD = 0, - SEI_PICTURE_TIMING = 1, - SEI_STEREO_VIDEO_INFO = 21, - SEI_FRAME_PACKING_ARRANGEMENT = 45 -}; - -/* - * stereo Video Info struct - */ -struct hva_h264_stereo_video_sei { - u8 field_views_flag; - u8 top_field_is_left_view_flag; - u8 current_frame_is_left_view_flag; - u8 next_frame_is_second_view_flag; - u8 left_view_self_contained_flag; - u8 right_view_self_contained_flag; -}; - -/* - * struct hva_h264_td - * - * @frame_width: width in pixels of the buffer containing the input frame - * @frame_height: height in pixels of the buffer containing the input frame - * @frame_num: the parameter to be written in the slice header - * @picture_coding_type: type I, P or B - * @pic_order_cnt_type: POC mode, as defined in H264 std : can be 0,1,2 - * @first_picture_in_sequence: flag telling to encoder that this is the - * first picture in a video sequence. - * Used for VBR - * @slice_size_type: 0 = no constraint to close the slice - * 1= a slice is closed as soon as the slice_mb_size limit - * is reached - * 2= a slice is closed as soon as the slice_byte_size limit - * is reached - * 3= a slice is closed as soon as either the slice_byte_size - * limit or the slice_mb_size limit is reached - * @slice_mb_size: defines the slice size in number of macroblocks - * (used when slice_size_type=1 or slice_size_type=3) - * @ir_param_option: defines the number of macroblocks per frame to be - * refreshed by AIR algorithm OR the refresh period - * by CIR algorithm - * @intra_refresh_type: enables the adaptive intra refresh algorithm. - * Disable=0 / Adaptative=1 and Cycle=2 as intra refresh - * @use_constrained_intra_flag: constrained_intra_pred_flag from PPS - * @transform_mode: controls the use of 4x4/8x8 transform mode - * @disable_deblocking_filter_idc: - * 0: specifies that all luma and chroma block edges of - * the slice are filtered. - * 1: specifies that deblocking is disabled for all block - * edges of the slice. - * 2: specifies that all luma and chroma block edges of - * the slice are filtered with exception of the block edges - * that coincide with slice boundaries - * @slice_alpha_c0_offset_div2: to be written in slice header, - * controls deblocking - * @slice_beta_offset_div2: to be written in slice header, - * controls deblocking - * @encoder_complexity: encoder complexity control (IME). - * 0 = I_16x16, P_16x16, Full ME Complexity - * 1 = I_16x16, I_NxN, P_16x16, Full ME Complexity - * 2 = I_16x16, I_NXN, P_16x16, P_WxH, Full ME Complexity - * 4 = I_16x16, P_16x16, Reduced ME Complexity - * 5 = I_16x16, I_NxN, P_16x16, Reduced ME Complexity - * 6 = I_16x16, I_NXN, P_16x16, P_WxH, Reduced ME Complexity - * @chroma_qp_index_offset: coming from picture parameter set - * (PPS see [H.264 STD] 7.4.2.2) - * @entropy_coding_mode: entropy coding mode. - * 0 = CAVLC - * 1 = CABAC - * @brc_type: selects the bit-rate control algorithm - * 0 = constant Qp, (no BRC) - * 1 = CBR - * 2 = VBR - * @quant: Quantization param used in case of fix QP encoding (no BRC) - * @non_VCL_NALU_Size: size of non-VCL NALUs (SPS, PPS, filler), - * used by BRC - * @cpb_buffer_size: size of Coded Picture Buffer, used by BRC - * @bit_rate: target bitrate, for BRC - * @qp_min: min QP threshold - * @qp_max: max QP threshold - * @framerate_num: target framerate numerator , used by BRC - * @framerate_den: target framerate denomurator , used by BRC - * @delay: End-to-End Initial Delay - * @strict_HRD_compliancy: flag for HDR compliancy (1) - * May impact quality encoding - * @addr_source_buffer: address of input frame buffer for current frame - * @addr_fwd_Ref_Buffer: address of reference frame buffer - * @addr_rec_buffer: address of reconstructed frame buffer - * @addr_output_bitstream_start: output bitstream start address - * @addr_output_bitstream_end: output bitstream end address - * @addr_external_sw : address of external search window - * @addr_lctx : address of context picture buffer - * @addr_local_rec_buffer: address of local reconstructed buffer - * @addr_spatial_context: address of spatial context buffer - * @bitstream_offset: offset in bits between aligned bitstream start - * address and first bit to be written by HVA. - * Range value is [0..63] - * @sampling_mode: Input picture format . - * 0: YUV420 semi_planar Interleaved - * 1: YUV422 raster Interleaved - * @addr_param_out: address of output parameters structure - * @addr_scaling_matrix: address to the coefficient of - * the inverse scaling matrix - * @addr_scaling_matrix_dir: address to the coefficient of - * the direct scaling matrix - * @addr_cabac_context_buffer: address of cabac context buffer - * @GmvX: Input information about the horizontal global displacement of - * the encoded frame versus the previous one - * @GmvY: Input information about the vertical global displacement of - * the encoded frame versus the previous one - * @window_width: width in pixels of the window to be encoded inside - * the input frame - * @window_height: width in pixels of the window to be encoded inside - * the input frame - * @window_horizontal_offset: horizontal offset in pels for input window - * within input frame - * @window_vertical_offset: vertical offset in pels for input window - * within input frame - * @addr_roi: Map of QP offset for the Region of Interest algorithm and - * also used for Error map. - * Bit 0-6 used for qp offset (value -64 to 63). - * Bit 7 used to force intra - * @addr_slice_header: address to slice header - * @slice_header_size_in_bits: size in bits of the Slice header - * @slice_header_offset0: Slice header offset where to insert - * first_Mb_in_slice - * @slice_header_offset1: Slice header offset where to insert - * slice_qp_delta - * @slice_header_offset2: Slice header offset where to insert - * num_MBs_in_slice - * @slice_synchro_enable: enable "slice ready" interrupt after each slice - * @max_slice_number: Maximum number of slice in a frame - * (0 is strictly forbidden) - * @rgb2_yuv_y_coeff: Four coefficients (C0C1C2C3) to convert from RGB to - * YUV for the Y component. - * Y = C0*R + C1*G + C2*B + C3 (C0 is on byte 0) - * @rgb2_yuv_u_coeff: four coefficients (C0C1C2C3) to convert from RGB to - * YUV for the Y component. - * Y = C0*R + C1*G + C2*B + C3 (C0 is on byte 0) - * @rgb2_yuv_v_coeff: Four coefficients (C0C1C2C3) to convert from RGB to - * YUV for the U (Cb) component. - * U = C0*R + C1*G + C2*B + C3 (C0 is on byte 0) - * @slice_byte_size: maximum slice size in bytes - * (used when slice_size_type=2 or slice_size_type=3) - * @max_air_intra_mb_nb: Maximum number of intra macroblock in a frame - * for the AIR algorithm - * @brc_no_skip: Disable skipping in the Bitrate Controller - * @addr_brc_in_out_parameter: address of static buffer for BRC parameters - */ -struct hva_h264_td { - u16 frame_width; - u16 frame_height; - u32 frame_num; - u16 picture_coding_type; - u16 reserved1; - u16 pic_order_cnt_type; - u16 first_picture_in_sequence; - u16 slice_size_type; - u16 reserved2; - u32 slice_mb_size; - u16 ir_param_option; - u16 intra_refresh_type; - u16 use_constrained_intra_flag; - u16 transform_mode; - u16 disable_deblocking_filter_idc; - s16 slice_alpha_c0_offset_div2; - s16 slice_beta_offset_div2; - u16 encoder_complexity; - s16 chroma_qp_index_offset; - u16 entropy_coding_mode; - u16 brc_type; - u16 quant; - u32 non_vcl_nalu_size; - u32 cpb_buffer_size; - u32 bit_rate; - u16 qp_min; - u16 qp_max; - u16 framerate_num; - u16 framerate_den; - u16 delay; - u16 strict_hrd_compliancy; - u32 addr_source_buffer; - u32 addr_fwd_ref_buffer; - u32 addr_rec_buffer; - u32 addr_output_bitstream_start; - u32 addr_output_bitstream_end; - u32 addr_external_sw; - u32 addr_lctx; - u32 addr_local_rec_buffer; - u32 addr_spatial_context; - u16 bitstream_offset; - u16 sampling_mode; - u32 addr_param_out; - u32 addr_scaling_matrix; - u32 addr_scaling_matrix_dir; - u32 addr_cabac_context_buffer; - u32 reserved3; - u32 reserved4; - s16 gmv_x; - s16 gmv_y; - u16 window_width; - u16 window_height; - u16 window_horizontal_offset; - u16 window_vertical_offset; - u32 addr_roi; - u32 addr_slice_header; - u16 slice_header_size_in_bits; - u16 slice_header_offset0; - u16 slice_header_offset1; - u16 slice_header_offset2; - u32 reserved5; - u32 reserved6; - u16 reserved7; - u16 reserved8; - u16 slice_synchro_enable; - u16 max_slice_number; - u32 rgb2_yuv_y_coeff; - u32 rgb2_yuv_u_coeff; - u32 rgb2_yuv_v_coeff; - u32 slice_byte_size; - u16 max_air_intra_mb_nb; - u16 brc_no_skip; - u32 addr_temporal_context; - u32 addr_brc_in_out_parameter; -}; - -/* - * struct hva_h264_slice_po - * - * @ slice_size: slice size - * @ slice_start_time: start time - * @ slice_stop_time: stop time - * @ slice_num: slice number - */ -struct hva_h264_slice_po { - u32 slice_size; - u32 slice_start_time; - u32 slice_end_time; - u32 slice_num; -}; - -/* - * struct hva_h264_po - * - * @ bitstream_size: bitstream size - * @ dct_bitstream_size: dtc bitstream size - * @ stuffing_bits: number of stuffing bits inserted by the encoder - * @ removal_time: removal time of current frame (nb of ticks 1/framerate) - * @ hvc_start_time: hvc start time - * @ hvc_stop_time: hvc stop time - * @ slice_count: slice count - */ -struct hva_h264_po { - u32 bitstream_size; - u32 dct_bitstream_size; - u32 stuffing_bits; - u32 removal_time; - u32 hvc_start_time; - u32 hvc_stop_time; - u32 slice_count; - u32 reserved0; - struct hva_h264_slice_po slice_params[16]; -}; - -struct hva_h264_task { - struct hva_h264_td td; - struct hva_h264_po po; -}; - -/* - * struct hva_h264_ctx - * - * @seq_info: sequence information buffer - * @ref_frame: reference frame buffer - * @rec_frame: reconstructed frame buffer - * @task: task descriptor - */ -struct hva_h264_ctx { - struct hva_buffer *seq_info; - struct hva_buffer *ref_frame; - struct hva_buffer *rec_frame; - struct hva_buffer *task; -}; - -static int hva_h264_fill_slice_header(struct hva_ctx *pctx, - u8 *slice_header_addr, - struct hva_controls *ctrls, - int frame_num, - u16 *header_size, - u16 *header_offset0, - u16 *header_offset1, - u16 *header_offset2) -{ - /* - * with this HVA hardware version, part of the slice header is computed - * on host and part by hardware. - * The part of host is precomputed and available through this array. - */ - struct device *dev = ctx_to_dev(pctx); - int cabac = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC; - static const unsigned char slice_header[] = { - 0x00, 0x00, 0x00, 0x01, - 0x41, 0x34, 0x07, 0x00 - }; - int idr_pic_id = frame_num % 2; - enum hva_picture_coding_type type; - u32 frame_order = frame_num % ctrls->gop_size; - - if (!(frame_num % ctrls->gop_size)) - type = PICTURE_CODING_TYPE_I; - else - type = PICTURE_CODING_TYPE_P; - - memcpy(slice_header_addr, slice_header, sizeof(slice_header)); - - *header_size = 56; - *header_offset0 = 40; - *header_offset1 = 13; - *header_offset2 = 0; - - if (type == PICTURE_CODING_TYPE_I) { - slice_header_addr[4] = 0x65; - slice_header_addr[5] = 0x11; - - /* toggle the I frame */ - if ((frame_num / ctrls->gop_size) % 2) { - *header_size += 4; - *header_offset1 += 4; - slice_header_addr[6] = 0x04; - slice_header_addr[7] = 0x70; - - } else { - *header_size += 2; - *header_offset1 += 2; - slice_header_addr[6] = 0x09; - slice_header_addr[7] = 0xC0; - } - } else { - if (ctrls->entropy_mode == cabac) { - *header_size += 1; - *header_offset1 += 1; - slice_header_addr[7] = 0x80; - } - /* - * update slice header with P frame order - * frame order is limited to 16 (coded on 4bits only) - */ - slice_header_addr[5] += ((frame_order & 0x0C) >> 2); - slice_header_addr[6] += ((frame_order & 0x03) << 6); - } - - dev_dbg(dev, - "%s %s slice header order %d idrPicId %d header size %d\n", - pctx->name, __func__, frame_order, idr_pic_id, *header_size); - return 0; -} - -static int hva_h264_fill_data_nal(struct hva_ctx *pctx, - unsigned int stuffing_bytes, u8 *addr, - unsigned int stream_size, unsigned int *size) -{ - struct device *dev = ctx_to_dev(pctx); - static const u8 start[] = { 0x00, 0x00, 0x00, 0x01 }; - - dev_dbg(dev, "%s %s stuffing bytes %d\n", pctx->name, __func__, - stuffing_bytes); - - if ((*size + stuffing_bytes + H264_FILLER_DATA_SIZE) > stream_size) { - dev_dbg(dev, "%s %s too many stuffing bytes %d\n", - pctx->name, __func__, stuffing_bytes); - return 0; - } - - /* start code */ - memcpy(addr + *size, start, sizeof(start)); - *size += sizeof(start); - - /* nal_unit_type */ - addr[*size] = NALU_TYPE_FILLER_DATA; - *size += 1; - - memset(addr + *size, 0xff, stuffing_bytes); - *size += stuffing_bytes; - - addr[*size] = 0x80; - *size += 1; - - return 0; -} - -static int hva_h264_fill_sei_nal(struct hva_ctx *pctx, - enum hva_h264_sei_payload_type type, - u8 *addr, u32 *size) -{ - struct device *dev = ctx_to_dev(pctx); - static const u8 start[] = { 0x00, 0x00, 0x00, 0x01 }; - struct hva_h264_stereo_video_sei info; - u8 offset = 7; - u8 msg = 0; - - /* start code */ - memcpy(addr + *size, start, sizeof(start)); - *size += sizeof(start); - - /* nal_unit_type */ - addr[*size] = NALU_TYPE_SEI; - *size += 1; - - /* payload type */ - addr[*size] = type; - *size += 1; - - switch (type) { - case SEI_STEREO_VIDEO_INFO: - memset(&info, 0, sizeof(info)); - - /* set to top/bottom frame packing arrangement */ - info.field_views_flag = 1; - info.top_field_is_left_view_flag = 1; - - /* payload size */ - addr[*size] = 1; - *size += 1; - - /* payload */ - msg = info.field_views_flag << offset--; - - if (info.field_views_flag) { - msg |= info.top_field_is_left_view_flag << - offset--; - } else { - msg |= info.current_frame_is_left_view_flag << - offset--; - msg |= info.next_frame_is_second_view_flag << - offset--; - } - msg |= info.left_view_self_contained_flag << offset--; - msg |= info.right_view_self_contained_flag << offset--; - - addr[*size] = msg; - *size += 1; - - addr[*size] = 0x80; - *size += 1; - - return 0; - case SEI_BUFFERING_PERIOD: - case SEI_PICTURE_TIMING: - case SEI_FRAME_PACKING_ARRANGEMENT: - default: - dev_err(dev, "%s sei nal type not supported %d\n", - pctx->name, type); - return -EINVAL; - } -} - -static int hva_h264_prepare_task(struct hva_ctx *pctx, - struct hva_h264_task *task, - struct hva_frame *frame, - struct hva_stream *stream) -{ - struct hva_dev *hva = ctx_to_hdev(pctx); - struct device *dev = ctx_to_dev(pctx); - struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv; - struct hva_buffer *seq_info = ctx->seq_info; - struct hva_buffer *fwd_ref_frame = ctx->ref_frame; - struct hva_buffer *loc_rec_frame = ctx->rec_frame; - struct hva_h264_td *td = &task->td; - struct hva_controls *ctrls = &pctx->ctrls; - struct v4l2_fract *time_per_frame = &pctx->ctrls.time_per_frame; - int cavlc = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC; - u32 frame_num = pctx->stream_num; - u32 addr_esram = hva->esram_addr; - enum v4l2_mpeg_video_h264_level level; - dma_addr_t paddr = 0; - u8 *slice_header_vaddr; - u32 frame_width = frame->info.aligned_width; - u32 frame_height = frame->info.aligned_height; - u32 max_cpb_buffer_size; - unsigned int payload = stream->bytesused; - u32 max_bitrate; - - /* check width and height parameters */ - if ((frame_width > max(H264_MAX_SIZE_W, H264_MAX_SIZE_H)) || - (frame_height > max(H264_MAX_SIZE_W, H264_MAX_SIZE_H))) { - dev_err(dev, - "%s width(%d) or height(%d) exceeds limits (%dx%d)\n", - pctx->name, frame_width, frame_height, - H264_MAX_SIZE_W, H264_MAX_SIZE_H); - pctx->frame_errors++; - return -EINVAL; - } - - level = ctrls->level; - - memset(td, 0, sizeof(struct hva_h264_td)); - - td->frame_width = frame_width; - td->frame_height = frame_height; - - /* set frame alignment */ - td->window_width = frame_width; - td->window_height = frame_height; - td->window_horizontal_offset = 0; - td->window_vertical_offset = 0; - - td->first_picture_in_sequence = (!frame_num) ? 1 : 0; - - /* pic_order_cnt_type hard coded to '2' as only I & P frames */ - td->pic_order_cnt_type = 2; - - /* useConstrainedIntraFlag set to false for better coding efficiency */ - td->use_constrained_intra_flag = false; - td->brc_type = (ctrls->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) - ? BRC_TYPE_CBR : BRC_TYPE_VBR; - - td->entropy_coding_mode = (ctrls->entropy_mode == cavlc) ? CAVLC : - CABAC; - - td->bit_rate = ctrls->bitrate; - - /* set framerate, framerate = 1 n/ time per frame */ - if (time_per_frame->numerator >= 536) { - /* - * due to a hardware bug, framerate denominator can't exceed - * 536 (BRC overflow). Compute nearest framerate - */ - td->framerate_den = 1; - td->framerate_num = (time_per_frame->denominator + - (time_per_frame->numerator >> 1) - 1) / - time_per_frame->numerator; - - /* - * update bitrate to introduce a correction due to - * the new framerate - * new bitrate = (old bitrate * new framerate) / old framerate - */ - td->bit_rate /= time_per_frame->numerator; - td->bit_rate *= time_per_frame->denominator; - td->bit_rate /= td->framerate_num; - } else { - td->framerate_den = time_per_frame->numerator; - td->framerate_num = time_per_frame->denominator; - } - - /* compute maximum bitrate depending on profile */ - if (ctrls->profile >= V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) - max_bitrate = h264_infos_list[level].max_bitrate * - H264_FACTOR_HIGH; - else - max_bitrate = h264_infos_list[level].max_bitrate * - H264_FACTOR_BASELINE; - - /* check if bitrate doesn't exceed max size */ - if (td->bit_rate > max_bitrate) { - dev_dbg(dev, - "%s bitrate (%d) larger than level and profile allow, clip to %d\n", - pctx->name, td->bit_rate, max_bitrate); - td->bit_rate = max_bitrate; - } - - /* convert cpb_buffer_size in bits */ - td->cpb_buffer_size = ctrls->cpb_size * 8000; - - /* compute maximum cpb buffer size depending on profile */ - if (ctrls->profile >= V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) - max_cpb_buffer_size = - h264_infos_list[level].max_cpb_size * H264_FACTOR_HIGH; - else - max_cpb_buffer_size = - h264_infos_list[level].max_cpb_size * H264_FACTOR_BASELINE; - - /* check if cpb buffer size doesn't exceed max size */ - if (td->cpb_buffer_size > max_cpb_buffer_size) { - dev_dbg(dev, - "%s cpb size larger than level %d allows, clip to %d\n", - pctx->name, td->cpb_buffer_size, max_cpb_buffer_size); - td->cpb_buffer_size = max_cpb_buffer_size; - } - - /* enable skipping in the Bitrate Controller */ - td->brc_no_skip = 0; - - /* initial delay */ - if ((ctrls->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) && - td->bit_rate) - td->delay = 1000 * (td->cpb_buffer_size / td->bit_rate); - else - td->delay = 0; - - switch (frame->info.pixelformat) { - case V4L2_PIX_FMT_NV12: - td->sampling_mode = SAMPLING_MODE_NV12; - break; - case V4L2_PIX_FMT_NV21: - td->sampling_mode = SAMPLING_MODE_NV21; - break; - default: - dev_err(dev, "%s invalid source pixel format\n", - pctx->name); - pctx->frame_errors++; - return -EINVAL; - } - - /* - * fill matrix color converter (RGB to YUV) - * Y = 0,299 R + 0,587 G + 0,114 B - * Cb = -0,1687 R -0,3313 G + 0,5 B + 128 - * Cr = 0,5 R - 0,4187 G - 0,0813 B + 128 - */ - td->rgb2_yuv_y_coeff = 0x12031008; - td->rgb2_yuv_u_coeff = 0x800EF7FB; - td->rgb2_yuv_v_coeff = 0x80FEF40E; - - /* enable/disable transform mode */ - td->transform_mode = ctrls->dct8x8; - - /* encoder complexity fix to 2, ENCODE_I_16x16_I_NxN_P_16x16_P_WxH */ - td->encoder_complexity = 2; - - /* quant fix to 28, default VBR value */ - td->quant = 28; - - if (td->framerate_den == 0) { - dev_err(dev, "%s invalid framerate\n", pctx->name); - pctx->frame_errors++; - return -EINVAL; - } - - /* if automatic framerate, deactivate bitrate controller */ - if (td->framerate_num == 0) - td->brc_type = 0; - - /* compliancy fix to true */ - td->strict_hrd_compliancy = 1; - - /* set minimum & maximum quantizers */ - td->qp_min = clamp_val(ctrls->qpmin, 0, 51); - td->qp_max = clamp_val(ctrls->qpmax, 0, 51); - - td->addr_source_buffer = frame->paddr; - td->addr_fwd_ref_buffer = fwd_ref_frame->paddr; - td->addr_rec_buffer = loc_rec_frame->paddr; - - td->addr_output_bitstream_end = (u32)stream->paddr + stream->size; - - td->addr_output_bitstream_start = (u32)stream->paddr; - td->bitstream_offset = (((u32)stream->paddr & 0xF) << 3) & - BITSTREAM_OFFSET_MASK; - - td->addr_param_out = (u32)ctx->task->paddr + - offsetof(struct hva_h264_task, po); - - /* swap spatial and temporal context */ - if (frame_num % 2) { - paddr = seq_info->paddr; - td->addr_spatial_context = ALIGN(paddr, 0x100); - paddr = seq_info->paddr + DATA_SIZE(frame_width, - frame_height); - td->addr_temporal_context = ALIGN(paddr, 0x100); - } else { - paddr = seq_info->paddr; - td->addr_temporal_context = ALIGN(paddr, 0x100); - paddr = seq_info->paddr + DATA_SIZE(frame_width, - frame_height); - td->addr_spatial_context = ALIGN(paddr, 0x100); - } - - paddr = seq_info->paddr + 2 * DATA_SIZE(frame_width, frame_height); - - td->addr_brc_in_out_parameter = ALIGN(paddr, 0x100); - - paddr = td->addr_brc_in_out_parameter + BRC_DATA_SIZE; - td->addr_slice_header = ALIGN(paddr, 0x100); - td->addr_external_sw = ALIGN(addr_esram, 0x100); - - addr_esram += SEARCH_WINDOW_BUFFER_MAX_SIZE(frame_width); - td->addr_local_rec_buffer = ALIGN(addr_esram, 0x100); - - addr_esram += LOCAL_RECONSTRUCTED_BUFFER_MAX_SIZE(frame_width); - td->addr_lctx = ALIGN(addr_esram, 0x100); - - addr_esram += CTX_MB_BUFFER_MAX_SIZE(max(frame_width, frame_height)); - td->addr_cabac_context_buffer = ALIGN(addr_esram, 0x100); - - if (!(frame_num % ctrls->gop_size)) { - td->picture_coding_type = PICTURE_CODING_TYPE_I; - stream->vbuf.flags |= V4L2_BUF_FLAG_KEYFRAME; - } else { - td->picture_coding_type = PICTURE_CODING_TYPE_P; - stream->vbuf.flags &= ~V4L2_BUF_FLAG_KEYFRAME; - } - - /* fill the slice header part */ - slice_header_vaddr = seq_info->vaddr + (td->addr_slice_header - - seq_info->paddr); - - hva_h264_fill_slice_header(pctx, slice_header_vaddr, ctrls, frame_num, - &td->slice_header_size_in_bits, - &td->slice_header_offset0, - &td->slice_header_offset1, - &td->slice_header_offset2); - - td->chroma_qp_index_offset = 2; - td->slice_synchro_enable = 0; - td->max_slice_number = 1; - - /* - * check the sps/pps header size for key frame only - * sps/pps header was previously fill by libv4l - * during qbuf of stream buffer - */ - if ((stream->vbuf.flags == V4L2_BUF_FLAG_KEYFRAME) && - (payload > MAX_SPS_PPS_SIZE)) { - dev_err(dev, "%s invalid sps/pps size %d\n", pctx->name, - payload); - pctx->frame_errors++; - return -EINVAL; - } - - if (stream->vbuf.flags != V4L2_BUF_FLAG_KEYFRAME) - payload = 0; - - /* add SEI nal (video stereo info) */ - if (ctrls->sei_fp && hva_h264_fill_sei_nal(pctx, SEI_STEREO_VIDEO_INFO, - (u8 *)stream->vaddr, - &payload)) { - dev_err(dev, "%s fail to get SEI nal\n", pctx->name); - pctx->frame_errors++; - return -EINVAL; - } - - /* fill size of non-VCL NAL units (SPS, PPS, filler and SEI) */ - td->non_vcl_nalu_size = payload * 8; - - /* compute bitstream offset & new start address of bitstream */ - td->addr_output_bitstream_start += ((payload >> 4) << 4); - td->bitstream_offset += (payload - ((payload >> 4) << 4)) * 8; - - stream->bytesused = payload; - - return 0; -} - -static unsigned int hva_h264_get_stream_size(struct hva_h264_task *task) -{ - struct hva_h264_po *po = &task->po; - - return po->bitstream_size; -} - -static u32 hva_h264_get_stuffing_bytes(struct hva_h264_task *task) -{ - struct hva_h264_po *po = &task->po; - - return po->stuffing_bits >> 3; -} - -static int hva_h264_open(struct hva_ctx *pctx) -{ - struct device *dev = ctx_to_dev(pctx); - struct hva_h264_ctx *ctx; - struct hva_dev *hva = ctx_to_hdev(pctx); - u32 frame_width = pctx->frameinfo.aligned_width; - u32 frame_height = pctx->frameinfo.aligned_height; - u32 size; - int ret; - - /* check esram size necessary to encode a frame */ - size = SEARCH_WINDOW_BUFFER_MAX_SIZE(frame_width) + - LOCAL_RECONSTRUCTED_BUFFER_MAX_SIZE(frame_width) + - CTX_MB_BUFFER_MAX_SIZE(max(frame_width, frame_height)) + - CABAC_CONTEXT_BUFFER_MAX_SIZE(frame_width); - - if (hva->esram_size < size) { - dev_err(dev, "%s not enough esram (max:%d request:%d)\n", - pctx->name, hva->esram_size, size); - ret = -EINVAL; - goto err; - } - - /* allocate context for codec */ - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) { - ret = -ENOMEM; - goto err; - } - - /* allocate sequence info buffer */ - ret = hva_mem_alloc(pctx, - 2 * DATA_SIZE(frame_width, frame_height) + - SLICE_HEADER_SIZE + - BRC_DATA_SIZE, - "hva sequence info", - &ctx->seq_info); - if (ret) { - dev_err(dev, - "%s failed to allocate sequence info buffer\n", - pctx->name); - goto err_ctx; - } - - /* allocate reference frame buffer */ - ret = hva_mem_alloc(pctx, - frame_width * frame_height * 3 / 2, - "hva reference frame", - &ctx->ref_frame); - if (ret) { - dev_err(dev, "%s failed to allocate reference frame buffer\n", - pctx->name); - goto err_seq_info; - } - - /* allocate reconstructed frame buffer */ - ret = hva_mem_alloc(pctx, - frame_width * frame_height * 3 / 2, - "hva reconstructed frame", - &ctx->rec_frame); - if (ret) { - dev_err(dev, - "%s failed to allocate reconstructed frame buffer\n", - pctx->name); - goto err_ref_frame; - } - - /* allocate task descriptor */ - ret = hva_mem_alloc(pctx, - sizeof(struct hva_h264_task), - "hva task descriptor", - &ctx->task); - if (ret) { - dev_err(dev, - "%s failed to allocate task descriptor\n", - pctx->name); - goto err_rec_frame; - } - - pctx->priv = (void *)ctx; - - return 0; - -err_rec_frame: - hva_mem_free(pctx, ctx->rec_frame); -err_ref_frame: - hva_mem_free(pctx, ctx->ref_frame); -err_seq_info: - hva_mem_free(pctx, ctx->seq_info); -err_ctx: - devm_kfree(dev, ctx); -err: - pctx->sys_errors++; - return ret; -} - -static int hva_h264_close(struct hva_ctx *pctx) -{ - struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv; - struct device *dev = ctx_to_dev(pctx); - - if (ctx->seq_info) - hva_mem_free(pctx, ctx->seq_info); - - if (ctx->ref_frame) - hva_mem_free(pctx, ctx->ref_frame); - - if (ctx->rec_frame) - hva_mem_free(pctx, ctx->rec_frame); - - if (ctx->task) - hva_mem_free(pctx, ctx->task); - - devm_kfree(dev, ctx); - - return 0; -} - -static int hva_h264_encode(struct hva_ctx *pctx, struct hva_frame *frame, - struct hva_stream *stream) -{ - struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv; - struct hva_h264_task *task = (struct hva_h264_task *)ctx->task->vaddr; - u32 stuffing_bytes = 0; - int ret = 0; - - ret = hva_h264_prepare_task(pctx, task, frame, stream); - if (ret) - goto err; - - ret = hva_hw_execute_task(pctx, H264_ENC, ctx->task); - if (ret) - goto err; - - pctx->stream_num++; - stream->bytesused += hva_h264_get_stream_size(task); - - stuffing_bytes = hva_h264_get_stuffing_bytes(task); - - if (stuffing_bytes) - hva_h264_fill_data_nal(pctx, stuffing_bytes, - (u8 *)stream->vaddr, - stream->size, - &stream->bytesused); - - /* switch reference & reconstructed frame */ - swap(ctx->ref_frame, ctx->rec_frame); - - return 0; -err: - stream->bytesused = 0; - return ret; -} - -const struct hva_enc nv12h264enc = { - .name = "H264(NV12)", - .pixelformat = V4L2_PIX_FMT_NV12, - .streamformat = V4L2_PIX_FMT_H264, - .max_width = H264_MAX_SIZE_W, - .max_height = H264_MAX_SIZE_H, - .open = hva_h264_open, - .close = hva_h264_close, - .encode = hva_h264_encode, -}; - -const struct hva_enc nv21h264enc = { - .name = "H264(NV21)", - .pixelformat = V4L2_PIX_FMT_NV21, - .streamformat = V4L2_PIX_FMT_H264, - .max_width = H264_MAX_SIZE_W, - .max_height = H264_MAX_SIZE_H, - .open = hva_h264_open, - .close = hva_h264_close, - .encode = hva_h264_encode, -}; diff --git a/drivers/media/platform/sti/hva/hva-hw.c b/drivers/media/platform/sti/hva/hva-hw.c deleted file mode 100644 index fe4ea2e7f37e..000000000000 --- a/drivers/media/platform/sti/hva/hva-hw.c +++ /dev/null @@ -1,585 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) STMicroelectronics SA 2015 - * Authors: Yannick Fertre <yannick.fertre@st.com> - * Hugues Fruchet <hugues.fruchet@st.com> - */ - -#include <linux/clk.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> -#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS -#include <linux/seq_file.h> -#endif - -#include "hva.h" -#include "hva-hw.h" - -/* HVA register offsets */ -#define HVA_HIF_REG_RST 0x0100U -#define HVA_HIF_REG_RST_ACK 0x0104U -#define HVA_HIF_REG_MIF_CFG 0x0108U -#define HVA_HIF_REG_HEC_MIF_CFG 0x010CU -#define HVA_HIF_REG_CFL 0x0110U -#define HVA_HIF_FIFO_CMD 0x0114U -#define HVA_HIF_FIFO_STS 0x0118U -#define HVA_HIF_REG_SFL 0x011CU -#define HVA_HIF_REG_IT_ACK 0x0120U -#define HVA_HIF_REG_ERR_IT_ACK 0x0124U -#define HVA_HIF_REG_LMI_ERR 0x0128U -#define HVA_HIF_REG_EMI_ERR 0x012CU -#define HVA_HIF_REG_HEC_MIF_ERR 0x0130U -#define HVA_HIF_REG_HEC_STS 0x0134U -#define HVA_HIF_REG_HVC_STS 0x0138U -#define HVA_HIF_REG_HJE_STS 0x013CU -#define HVA_HIF_REG_CNT 0x0140U -#define HVA_HIF_REG_HEC_CHKSYN_DIS 0x0144U -#define HVA_HIF_REG_CLK_GATING 0x0148U -#define HVA_HIF_REG_VERSION 0x014CU -#define HVA_HIF_REG_BSM 0x0150U - -/* define value for version id register (HVA_HIF_REG_VERSION) */ -#define VERSION_ID_MASK 0x0000FFFF - -/* define values for BSM register (HVA_HIF_REG_BSM) */ -#define BSM_CFG_VAL1 0x0003F000 -#define BSM_CFG_VAL2 0x003F0000 - -/* define values for memory interface register (HVA_HIF_REG_MIF_CFG) */ -#define MIF_CFG_VAL1 0x04460446 -#define MIF_CFG_VAL2 0x04460806 -#define MIF_CFG_VAL3 0x00000000 - -/* define value for HEC memory interface register (HVA_HIF_REG_MIF_CFG) */ -#define HEC_MIF_CFG_VAL 0x000000C4 - -/* Bits definition for clock gating register (HVA_HIF_REG_CLK_GATING) */ -#define CLK_GATING_HVC BIT(0) -#define CLK_GATING_HEC BIT(1) -#define CLK_GATING_HJE BIT(2) - -/* fix hva clock rate */ -#define CLK_RATE 300000000 - -/* fix delay for pmruntime */ -#define AUTOSUSPEND_DELAY_MS 3 - -/* - * hw encode error values - * NO_ERROR: Success, Task OK - * H264_BITSTREAM_OVERSIZE: VECH264 Bitstream size > bitstream buffer - * H264_FRAME_SKIPPED: VECH264 Frame skipped (refers to CPB Buffer Size) - * H264_SLICE_LIMIT_SIZE: VECH264 MB > slice limit size - * H264_MAX_SLICE_NUMBER: VECH264 max slice number reached - * H264_SLICE_READY: VECH264 Slice ready - * TASK_LIST_FULL: HVA/FPC task list full - (discard latest transform command) - * UNKNOWN_COMMAND: Transform command not known by HVA/FPC - * WRONG_CODEC_OR_RESOLUTION: Wrong Codec or Resolution Selection - * NO_INT_COMPLETION: Time-out on interrupt completion - * LMI_ERR: Local Memory Interface Error - * EMI_ERR: External Memory Interface Error - * HECMI_ERR: HEC Memory Interface Error - */ -enum hva_hw_error { - NO_ERROR = 0x0, - H264_BITSTREAM_OVERSIZE = 0x2, - H264_FRAME_SKIPPED = 0x4, - H264_SLICE_LIMIT_SIZE = 0x5, - H264_MAX_SLICE_NUMBER = 0x7, - H264_SLICE_READY = 0x8, - TASK_LIST_FULL = 0xF0, - UNKNOWN_COMMAND = 0xF1, - WRONG_CODEC_OR_RESOLUTION = 0xF4, - NO_INT_COMPLETION = 0x100, - LMI_ERR = 0x101, - EMI_ERR = 0x102, - HECMI_ERR = 0x103, -}; - -static irqreturn_t hva_hw_its_interrupt(int irq, void *data) -{ - struct hva_dev *hva = data; - - /* read status registers */ - hva->sts_reg = readl_relaxed(hva->regs + HVA_HIF_FIFO_STS); - hva->sfl_reg = readl_relaxed(hva->regs + HVA_HIF_REG_SFL); - - /* acknowledge interruption */ - writel_relaxed(0x1, hva->regs + HVA_HIF_REG_IT_ACK); - - return IRQ_WAKE_THREAD; -} - -static irqreturn_t hva_hw_its_irq_thread(int irq, void *arg) -{ - struct hva_dev *hva = arg; - struct device *dev = hva_to_dev(hva); - u32 status = hva->sts_reg & 0xFF; - u8 ctx_id = 0; - struct hva_ctx *ctx = NULL; - - dev_dbg(dev, "%s %s: status: 0x%02x fifo level: 0x%02x\n", - HVA_PREFIX, __func__, hva->sts_reg & 0xFF, hva->sfl_reg & 0xF); - - /* - * status: task_id[31:16] client_id[15:8] status[7:0] - * the context identifier is retrieved from the client identifier - */ - ctx_id = (hva->sts_reg & 0xFF00) >> 8; - if (ctx_id >= HVA_MAX_INSTANCES) { - dev_err(dev, "%s %s: bad context identifier: %d\n", - HVA_PREFIX, __func__, ctx_id); - goto out; - } - - ctx = hva->instances[ctx_id]; - if (!ctx) - goto out; - - switch (status) { - case NO_ERROR: - dev_dbg(dev, "%s %s: no error\n", - ctx->name, __func__); - ctx->hw_err = false; - break; - case H264_SLICE_READY: - dev_dbg(dev, "%s %s: h264 slice ready\n", - ctx->name, __func__); - ctx->hw_err = false; - break; - case H264_FRAME_SKIPPED: - dev_dbg(dev, "%s %s: h264 frame skipped\n", - ctx->name, __func__); - ctx->hw_err = false; - break; - case H264_BITSTREAM_OVERSIZE: - dev_err(dev, "%s %s:h264 bitstream oversize\n", - ctx->name, __func__); - ctx->hw_err = true; - break; - case H264_SLICE_LIMIT_SIZE: - dev_err(dev, "%s %s: h264 slice limit size is reached\n", - ctx->name, __func__); - ctx->hw_err = true; - break; - case H264_MAX_SLICE_NUMBER: - dev_err(dev, "%s %s: h264 max slice number is reached\n", - ctx->name, __func__); - ctx->hw_err = true; - break; - case TASK_LIST_FULL: - dev_err(dev, "%s %s:task list full\n", - ctx->name, __func__); - ctx->hw_err = true; - break; - case UNKNOWN_COMMAND: - dev_err(dev, "%s %s: command not known\n", - ctx->name, __func__); - ctx->hw_err = true; - break; - case WRONG_CODEC_OR_RESOLUTION: - dev_err(dev, "%s %s: wrong codec or resolution\n", - ctx->name, __func__); - ctx->hw_err = true; - break; - default: - dev_err(dev, "%s %s: status not recognized\n", - ctx->name, __func__); - ctx->hw_err = true; - break; - } -out: - complete(&hva->interrupt); - - return IRQ_HANDLED; -} - -static irqreturn_t hva_hw_err_interrupt(int irq, void *data) -{ - struct hva_dev *hva = data; - - /* read status registers */ - hva->sts_reg = readl_relaxed(hva->regs + HVA_HIF_FIFO_STS); - hva->sfl_reg = readl_relaxed(hva->regs + HVA_HIF_REG_SFL); - - /* read error registers */ - hva->lmi_err_reg = readl_relaxed(hva->regs + HVA_HIF_REG_LMI_ERR); - hva->emi_err_reg = readl_relaxed(hva->regs + HVA_HIF_REG_EMI_ERR); - hva->hec_mif_err_reg = readl_relaxed(hva->regs + - HVA_HIF_REG_HEC_MIF_ERR); - - /* acknowledge interruption */ - writel_relaxed(0x1, hva->regs + HVA_HIF_REG_IT_ACK); - - return IRQ_WAKE_THREAD; -} - -static irqreturn_t hva_hw_err_irq_thread(int irq, void *arg) -{ - struct hva_dev *hva = arg; - struct device *dev = hva_to_dev(hva); - u8 ctx_id = 0; - struct hva_ctx *ctx; - - dev_dbg(dev, "%s status: 0x%02x fifo level: 0x%02x\n", - HVA_PREFIX, hva->sts_reg & 0xFF, hva->sfl_reg & 0xF); - - /* - * status: task_id[31:16] client_id[15:8] status[7:0] - * the context identifier is retrieved from the client identifier - */ - ctx_id = (hva->sts_reg & 0xFF00) >> 8; - if (ctx_id >= HVA_MAX_INSTANCES) { - dev_err(dev, "%s bad context identifier: %d\n", HVA_PREFIX, - ctx_id); - goto out; - } - - ctx = hva->instances[ctx_id]; - if (!ctx) - goto out; - - if (hva->lmi_err_reg) { - dev_err(dev, "%s local memory interface error: 0x%08x\n", - ctx->name, hva->lmi_err_reg); - ctx->hw_err = true; - } - - if (hva->emi_err_reg) { - dev_err(dev, "%s external memory interface error: 0x%08x\n", - ctx->name, hva->emi_err_reg); - ctx->hw_err = true; - } - - if (hva->hec_mif_err_reg) { - dev_err(dev, "%s hec memory interface error: 0x%08x\n", - ctx->name, hva->hec_mif_err_reg); - ctx->hw_err = true; - } -out: - complete(&hva->interrupt); - - return IRQ_HANDLED; -} - -static unsigned long int hva_hw_get_ip_version(struct hva_dev *hva) -{ - struct device *dev = hva_to_dev(hva); - unsigned long int version; - - if (pm_runtime_resume_and_get(dev) < 0) { - dev_err(dev, "%s failed to get pm_runtime\n", HVA_PREFIX); - mutex_unlock(&hva->protect_mutex); - return -EFAULT; - } - - version = readl_relaxed(hva->regs + HVA_HIF_REG_VERSION) & - VERSION_ID_MASK; - - pm_runtime_put_autosuspend(dev); - - switch (version) { - case HVA_VERSION_V400: - dev_dbg(dev, "%s IP hardware version 0x%lx\n", - HVA_PREFIX, version); - break; - default: - dev_err(dev, "%s unknown IP hardware version 0x%lx\n", - HVA_PREFIX, version); - version = HVA_VERSION_UNKNOWN; - break; - } - - return version; -} - -int hva_hw_probe(struct platform_device *pdev, struct hva_dev *hva) -{ - struct device *dev = &pdev->dev; - struct resource *esram; - int ret; - - WARN_ON(!hva); - - /* get memory for registers */ - hva->regs = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(hva->regs)) { - dev_err(dev, "%s failed to get regs\n", HVA_PREFIX); - return PTR_ERR(hva->regs); - } - - /* get memory for esram */ - esram = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!esram) { - dev_err(dev, "%s failed to get esram\n", HVA_PREFIX); - return -ENODEV; - } - hva->esram_addr = esram->start; - hva->esram_size = resource_size(esram); - - dev_info(dev, "%s esram reserved for address: 0x%x size:%d\n", - HVA_PREFIX, hva->esram_addr, hva->esram_size); - - /* get clock resource */ - hva->clk = devm_clk_get(dev, "clk_hva"); - if (IS_ERR(hva->clk)) { - dev_err(dev, "%s failed to get clock\n", HVA_PREFIX); - return PTR_ERR(hva->clk); - } - - ret = clk_prepare(hva->clk); - if (ret < 0) { - dev_err(dev, "%s failed to prepare clock\n", HVA_PREFIX); - hva->clk = ERR_PTR(-EINVAL); - return ret; - } - - /* get status interruption resource */ - ret = platform_get_irq(pdev, 0); - if (ret < 0) - goto err_clk; - hva->irq_its = ret; - - ret = devm_request_threaded_irq(dev, hva->irq_its, hva_hw_its_interrupt, - hva_hw_its_irq_thread, - IRQF_ONESHOT, - "hva_its_irq", hva); - if (ret) { - dev_err(dev, "%s failed to install status IRQ 0x%x\n", - HVA_PREFIX, hva->irq_its); - goto err_clk; - } - disable_irq(hva->irq_its); - - /* get error interruption resource */ - ret = platform_get_irq(pdev, 1); - if (ret < 0) - goto err_clk; - hva->irq_err = ret; - - ret = devm_request_threaded_irq(dev, hva->irq_err, hva_hw_err_interrupt, - hva_hw_err_irq_thread, - IRQF_ONESHOT, - "hva_err_irq", hva); - if (ret) { - dev_err(dev, "%s failed to install error IRQ 0x%x\n", - HVA_PREFIX, hva->irq_err); - goto err_clk; - } - disable_irq(hva->irq_err); - - /* initialise protection mutex */ - mutex_init(&hva->protect_mutex); - - /* initialise completion signal */ - init_completion(&hva->interrupt); - - /* initialise runtime power management */ - pm_runtime_set_autosuspend_delay(dev, AUTOSUSPEND_DELAY_MS); - pm_runtime_use_autosuspend(dev); - pm_runtime_set_suspended(dev); - pm_runtime_enable(dev); - - ret = pm_runtime_resume_and_get(dev); - if (ret < 0) { - dev_err(dev, "%s failed to set PM\n", HVA_PREFIX); - goto err_disable; - } - - /* check IP hardware version */ - hva->ip_version = hva_hw_get_ip_version(hva); - - if (hva->ip_version == HVA_VERSION_UNKNOWN) { - ret = -EINVAL; - goto err_pm; - } - - dev_info(dev, "%s found hva device (version 0x%lx)\n", HVA_PREFIX, - hva->ip_version); - - return 0; - -err_pm: - pm_runtime_put(dev); -err_disable: - pm_runtime_disable(dev); -err_clk: - if (hva->clk) - clk_unprepare(hva->clk); - - return ret; -} - -void hva_hw_remove(struct hva_dev *hva) -{ - struct device *dev = hva_to_dev(hva); - - disable_irq(hva->irq_its); - disable_irq(hva->irq_err); - - pm_runtime_put_autosuspend(dev); - pm_runtime_disable(dev); -} - -int hva_hw_runtime_suspend(struct device *dev) -{ - struct hva_dev *hva = dev_get_drvdata(dev); - - clk_disable_unprepare(hva->clk); - - return 0; -} - -int hva_hw_runtime_resume(struct device *dev) -{ - struct hva_dev *hva = dev_get_drvdata(dev); - - if (clk_prepare_enable(hva->clk)) { - dev_err(hva->dev, "%s failed to prepare hva clk\n", - HVA_PREFIX); - return -EINVAL; - } - - if (clk_set_rate(hva->clk, CLK_RATE)) { - dev_err(dev, "%s failed to set clock frequency\n", - HVA_PREFIX); - clk_disable_unprepare(hva->clk); - return -EINVAL; - } - - return 0; -} - -int hva_hw_execute_task(struct hva_ctx *ctx, enum hva_hw_cmd_type cmd, - struct hva_buffer *task) -{ - struct hva_dev *hva = ctx_to_hdev(ctx); - struct device *dev = hva_to_dev(hva); - u8 client_id = ctx->id; - int ret; - u32 reg = 0; - bool got_pm = false; - - mutex_lock(&hva->protect_mutex); - - /* enable irqs */ - enable_irq(hva->irq_its); - enable_irq(hva->irq_err); - - if (pm_runtime_resume_and_get(dev) < 0) { - dev_err(dev, "%s failed to get pm_runtime\n", ctx->name); - ctx->sys_errors++; - ret = -EFAULT; - goto out; - } - got_pm = true; - - reg = readl_relaxed(hva->regs + HVA_HIF_REG_CLK_GATING); - switch (cmd) { - case H264_ENC: - reg |= CLK_GATING_HVC; - break; - default: - dev_dbg(dev, "%s unknown command 0x%x\n", ctx->name, cmd); - ctx->encode_errors++; - ret = -EFAULT; - goto out; - } - writel_relaxed(reg, hva->regs + HVA_HIF_REG_CLK_GATING); - - dev_dbg(dev, "%s %s: write configuration registers\n", ctx->name, - __func__); - - /* byte swap config */ - writel_relaxed(BSM_CFG_VAL1, hva->regs + HVA_HIF_REG_BSM); - - /* define Max Opcode Size and Max Message Size for LMI and EMI */ - writel_relaxed(MIF_CFG_VAL3, hva->regs + HVA_HIF_REG_MIF_CFG); - writel_relaxed(HEC_MIF_CFG_VAL, hva->regs + HVA_HIF_REG_HEC_MIF_CFG); - - /* - * command FIFO: task_id[31:16] client_id[15:8] command_type[7:0] - * the context identifier is provided as client identifier to the - * hardware, and is retrieved in the interrupt functions from the - * status register - */ - dev_dbg(dev, "%s %s: send task (cmd: %d, task_desc: %pad)\n", - ctx->name, __func__, cmd + (client_id << 8), &task->paddr); - writel_relaxed(cmd + (client_id << 8), hva->regs + HVA_HIF_FIFO_CMD); - writel_relaxed(task->paddr, hva->regs + HVA_HIF_FIFO_CMD); - - if (!wait_for_completion_timeout(&hva->interrupt, - msecs_to_jiffies(2000))) { - dev_err(dev, "%s %s: time out on completion\n", ctx->name, - __func__); - ctx->encode_errors++; - ret = -EFAULT; - goto out; - } - - /* get encoding status */ - ret = ctx->hw_err ? -EFAULT : 0; - - ctx->encode_errors += ctx->hw_err ? 1 : 0; - -out: - disable_irq(hva->irq_its); - disable_irq(hva->irq_err); - - switch (cmd) { - case H264_ENC: - reg &= ~CLK_GATING_HVC; - writel_relaxed(reg, hva->regs + HVA_HIF_REG_CLK_GATING); - break; - default: - dev_dbg(dev, "%s unknown command 0x%x\n", ctx->name, cmd); - } - - if (got_pm) - pm_runtime_put_autosuspend(dev); - mutex_unlock(&hva->protect_mutex); - - return ret; -} - -#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS -#define DUMP(reg) seq_printf(s, "%-30s: 0x%08X\n",\ - #reg, readl_relaxed(hva->regs + reg)) - -void hva_hw_dump_regs(struct hva_dev *hva, struct seq_file *s) -{ - struct device *dev = hva_to_dev(hva); - - mutex_lock(&hva->protect_mutex); - - if (pm_runtime_resume_and_get(dev) < 0) { - seq_puts(s, "Cannot wake up IP\n"); - mutex_unlock(&hva->protect_mutex); - return; - } - - seq_printf(s, "Registers:\nReg @ = 0x%p\n", hva->regs); - - DUMP(HVA_HIF_REG_RST); - DUMP(HVA_HIF_REG_RST_ACK); - DUMP(HVA_HIF_REG_MIF_CFG); - DUMP(HVA_HIF_REG_HEC_MIF_CFG); - DUMP(HVA_HIF_REG_CFL); - DUMP(HVA_HIF_REG_SFL); - DUMP(HVA_HIF_REG_LMI_ERR); - DUMP(HVA_HIF_REG_EMI_ERR); - DUMP(HVA_HIF_REG_HEC_MIF_ERR); - DUMP(HVA_HIF_REG_HEC_STS); - DUMP(HVA_HIF_REG_HVC_STS); - DUMP(HVA_HIF_REG_HJE_STS); - DUMP(HVA_HIF_REG_CNT); - DUMP(HVA_HIF_REG_HEC_CHKSYN_DIS); - DUMP(HVA_HIF_REG_CLK_GATING); - DUMP(HVA_HIF_REG_VERSION); - - pm_runtime_put_autosuspend(dev); - mutex_unlock(&hva->protect_mutex); -} -#endif diff --git a/drivers/media/platform/sti/hva/hva-hw.h b/drivers/media/platform/sti/hva/hva-hw.h deleted file mode 100644 index b298990264d5..000000000000 --- a/drivers/media/platform/sti/hva/hva-hw.h +++ /dev/null @@ -1,45 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) STMicroelectronics SA 2015 - * Authors: Yannick Fertre <yannick.fertre@st.com> - * Hugues Fruchet <hugues.fruchet@st.com> - */ - -#ifndef HVA_HW_H -#define HVA_HW_H - -#include "hva-mem.h" - -/* HVA Versions */ -#define HVA_VERSION_UNKNOWN 0x000 -#define HVA_VERSION_V400 0x400 - -/* HVA command types */ -enum hva_hw_cmd_type { - /* RESERVED = 0x00 */ - /* RESERVED = 0x01 */ - H264_ENC = 0x02, - /* RESERVED = 0x03 */ - /* RESERVED = 0x04 */ - /* RESERVED = 0x05 */ - /* RESERVED = 0x06 */ - /* RESERVED = 0x07 */ - REMOVE_CLIENT = 0x08, - FREEZE_CLIENT = 0x09, - START_CLIENT = 0x0A, - FREEZE_ALL = 0x0B, - START_ALL = 0x0C, - REMOVE_ALL = 0x0D -}; - -int hva_hw_probe(struct platform_device *pdev, struct hva_dev *hva); -void hva_hw_remove(struct hva_dev *hva); -int hva_hw_runtime_suspend(struct device *dev); -int hva_hw_runtime_resume(struct device *dev); -int hva_hw_execute_task(struct hva_ctx *ctx, enum hva_hw_cmd_type cmd, - struct hva_buffer *task); -#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS -void hva_hw_dump_regs(struct hva_dev *hva, struct seq_file *s); -#endif - -#endif /* HVA_HW_H */ diff --git a/drivers/media/platform/sti/hva/hva-mem.c b/drivers/media/platform/sti/hva/hva-mem.c deleted file mode 100644 index 68047b60b66c..000000000000 --- a/drivers/media/platform/sti/hva/hva-mem.c +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) STMicroelectronics SA 2015 - * Authors: Yannick Fertre <yannick.fertre@st.com> - * Hugues Fruchet <hugues.fruchet@st.com> - */ - -#include "hva.h" -#include "hva-mem.h" - -int hva_mem_alloc(struct hva_ctx *ctx, u32 size, const char *name, - struct hva_buffer **buf) -{ - struct device *dev = ctx_to_dev(ctx); - struct hva_buffer *b; - dma_addr_t paddr; - void *base; - - b = devm_kzalloc(dev, sizeof(*b), GFP_KERNEL); - if (!b) { - ctx->sys_errors++; - return -ENOMEM; - } - - base = dma_alloc_attrs(dev, size, &paddr, GFP_KERNEL, - DMA_ATTR_WRITE_COMBINE); - if (!base) { - dev_err(dev, "%s %s : dma_alloc_attrs failed for %s (size=%d)\n", - ctx->name, __func__, name, size); - ctx->sys_errors++; - devm_kfree(dev, b); - return -ENOMEM; - } - - b->size = size; - b->paddr = paddr; - b->vaddr = base; - b->name = name; - - dev_dbg(dev, - "%s allocate %d bytes of HW memory @(virt=%p, phy=%pad): %s\n", - ctx->name, size, b->vaddr, &b->paddr, b->name); - - /* return hva buffer to user */ - *buf = b; - - return 0; -} - -void hva_mem_free(struct hva_ctx *ctx, struct hva_buffer *buf) -{ - struct device *dev = ctx_to_dev(ctx); - - dev_dbg(dev, - "%s free %d bytes of HW memory @(virt=%p, phy=%pad): %s\n", - ctx->name, buf->size, buf->vaddr, &buf->paddr, buf->name); - - dma_free_attrs(dev, buf->size, buf->vaddr, buf->paddr, - DMA_ATTR_WRITE_COMBINE); - - devm_kfree(dev, buf); -} diff --git a/drivers/media/platform/sti/hva/hva-mem.h b/drivers/media/platform/sti/hva/hva-mem.h deleted file mode 100644 index fec549dff2b3..000000000000 --- a/drivers/media/platform/sti/hva/hva-mem.h +++ /dev/null @@ -1,34 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) STMicroelectronics SA 2015 - * Authors: Yannick Fertre <yannick.fertre@st.com> - * Hugues Fruchet <hugues.fruchet@st.com> - */ - -#ifndef HVA_MEM_H -#define HVA_MEM_H - -/** - * struct hva_buffer - hva buffer - * - * @name: name of requester - * @paddr: physical address (for hardware) - * @vaddr: virtual address (kernel can read/write) - * @size: size of buffer - */ -struct hva_buffer { - const char *name; - dma_addr_t paddr; - void *vaddr; - u32 size; -}; - -int hva_mem_alloc(struct hva_ctx *ctx, - __u32 size, - const char *name, - struct hva_buffer **buf); - -void hva_mem_free(struct hva_ctx *ctx, - struct hva_buffer *buf); - -#endif /* HVA_MEM_H */ diff --git a/drivers/media/platform/sti/hva/hva-v4l2.c b/drivers/media/platform/sti/hva/hva-v4l2.c deleted file mode 100644 index bb34d6997d99..000000000000 --- a/drivers/media/platform/sti/hva/hva-v4l2.c +++ /dev/null @@ -1,1476 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) STMicroelectronics SA 2015 - * Authors: Yannick Fertre <yannick.fertre@st.com> - * Hugues Fruchet <hugues.fruchet@st.com> - */ - -#include <linux/module.h> -#include <linux/mod_devicetable.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <media/v4l2-event.h> -#include <media/v4l2-ioctl.h> -#include <media/videobuf2-dma-contig.h> - -#include "hva.h" -#include "hva-hw.h" - -#define MIN_FRAMES 1 -#define MIN_STREAMS 1 - -#define HVA_MIN_WIDTH 32 -#define HVA_MAX_WIDTH 1920 -#define HVA_MIN_HEIGHT 32 -#define HVA_MAX_HEIGHT 1920 - -/* HVA requires a 16x16 pixels alignment for frames */ -#define HVA_WIDTH_ALIGNMENT 16 -#define HVA_HEIGHT_ALIGNMENT 16 - -#define HVA_DEFAULT_WIDTH HVA_MIN_WIDTH -#define HVA_DEFAULT_HEIGHT HVA_MIN_HEIGHT -#define HVA_DEFAULT_FRAME_NUM 1 -#define HVA_DEFAULT_FRAME_DEN 30 - -#define to_type_str(type) (type == V4L2_BUF_TYPE_VIDEO_OUTPUT ? \ - "frame" : "stream") - -#define fh_to_ctx(f) (container_of(f, struct hva_ctx, fh)) - -/* registry of available encoders */ -static const struct hva_enc *hva_encoders[] = { - &nv12h264enc, - &nv21h264enc, -}; - -static inline int frame_size(u32 w, u32 h, u32 fmt) -{ - switch (fmt) { - case V4L2_PIX_FMT_NV12: - case V4L2_PIX_FMT_NV21: - return (w * h * 3) / 2; - default: - return 0; - } -} - -static inline int frame_stride(u32 w, u32 fmt) -{ - switch (fmt) { - case V4L2_PIX_FMT_NV12: - case V4L2_PIX_FMT_NV21: - return w; - default: - return 0; - } -} - -static inline int frame_alignment(u32 fmt) -{ - switch (fmt) { - case V4L2_PIX_FMT_NV12: - case V4L2_PIX_FMT_NV21: - /* multiple of 2 */ - return 2; - default: - return 1; - } -} - -static inline int estimated_stream_size(u32 w, u32 h) -{ - /* - * HVA only encodes in YUV420 format, whatever the frame format. - * A compression ratio of 2 is assumed: thus, the maximum size - * of a stream is estimated to ((width x height x 3 / 2) / 2) - */ - return (w * h * 3) / 4; -} - -static void set_default_params(struct hva_ctx *ctx) -{ - struct hva_frameinfo *frameinfo = &ctx->frameinfo; - struct hva_streaminfo *streaminfo = &ctx->streaminfo; - - frameinfo->pixelformat = V4L2_PIX_FMT_NV12; - frameinfo->width = HVA_DEFAULT_WIDTH; - frameinfo->height = HVA_DEFAULT_HEIGHT; - frameinfo->aligned_width = ALIGN(frameinfo->width, - HVA_WIDTH_ALIGNMENT); - frameinfo->aligned_height = ALIGN(frameinfo->height, - HVA_HEIGHT_ALIGNMENT); - frameinfo->size = frame_size(frameinfo->aligned_width, - frameinfo->aligned_height, - frameinfo->pixelformat); - - streaminfo->streamformat = V4L2_PIX_FMT_H264; - streaminfo->width = HVA_DEFAULT_WIDTH; - streaminfo->height = HVA_DEFAULT_HEIGHT; - - ctx->colorspace = V4L2_COLORSPACE_REC709; - ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT; - ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; - ctx->quantization = V4L2_QUANTIZATION_DEFAULT; - - ctx->max_stream_size = estimated_stream_size(streaminfo->width, - streaminfo->height); -} - -static const struct hva_enc *hva_find_encoder(struct hva_ctx *ctx, - u32 pixelformat, - u32 streamformat) -{ - struct hva_dev *hva = ctx_to_hdev(ctx); - const struct hva_enc *enc; - unsigned int i; - - for (i = 0; i < hva->nb_of_encoders; i++) { - enc = hva->encoders[i]; - if ((enc->pixelformat == pixelformat) && - (enc->streamformat == streamformat)) - return enc; - } - - return NULL; -} - -static void register_format(u32 format, u32 formats[], u32 *nb_of_formats) -{ - u32 i; - bool found = false; - - for (i = 0; i < *nb_of_formats; i++) { - if (format == formats[i]) { - found = true; - break; - } - } - - if (!found) - formats[(*nb_of_formats)++] = format; -} - -static void register_formats(struct hva_dev *hva) -{ - unsigned int i; - - for (i = 0; i < hva->nb_of_encoders; i++) { - register_format(hva->encoders[i]->pixelformat, - hva->pixelformats, - &hva->nb_of_pixelformats); - - register_format(hva->encoders[i]->streamformat, - hva->streamformats, - &hva->nb_of_streamformats); - } -} - -static void register_encoders(struct hva_dev *hva) -{ - struct device *dev = hva_to_dev(hva); - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(hva_encoders); i++) { - if (hva->nb_of_encoders >= HVA_MAX_ENCODERS) { - dev_dbg(dev, - "%s failed to register %s encoder (%d maximum reached)\n", - HVA_PREFIX, hva_encoders[i]->name, - HVA_MAX_ENCODERS); - return; - } - - hva->encoders[hva->nb_of_encoders++] = hva_encoders[i]; - dev_info(dev, "%s %s encoder registered\n", HVA_PREFIX, - hva_encoders[i]->name); - } -} - -static int hva_open_encoder(struct hva_ctx *ctx, u32 streamformat, - u32 pixelformat, struct hva_enc **penc) -{ - struct hva_dev *hva = ctx_to_hdev(ctx); - struct device *dev = ctx_to_dev(ctx); - struct hva_enc *enc; - int ret; - - /* find an encoder which can deal with these formats */ - enc = (struct hva_enc *)hva_find_encoder(ctx, pixelformat, - streamformat); - if (!enc) { - dev_err(dev, "%s no encoder found matching %4.4s => %4.4s\n", - ctx->name, (char *)&pixelformat, (char *)&streamformat); - return -EINVAL; - } - - dev_dbg(dev, "%s one encoder matching %4.4s => %4.4s\n", - ctx->name, (char *)&pixelformat, (char *)&streamformat); - - /* update instance name */ - snprintf(ctx->name, sizeof(ctx->name), "[%3d:%4.4s]", - hva->instance_id, (char *)&streamformat); - - /* open encoder instance */ - ret = enc->open(ctx); - if (ret) { - dev_err(dev, "%s failed to open encoder instance (%d)\n", - ctx->name, ret); - return ret; - } - - dev_dbg(dev, "%s %s encoder opened\n", ctx->name, enc->name); - - *penc = enc; - - return ret; -} - -static void hva_dbg_summary(struct hva_ctx *ctx) -{ - struct device *dev = ctx_to_dev(ctx); - struct hva_streaminfo *stream = &ctx->streaminfo; - struct hva_frameinfo *frame = &ctx->frameinfo; - - if (!(ctx->flags & HVA_FLAG_STREAMINFO)) - return; - - dev_dbg(dev, "%s %4.4s %dx%d > %4.4s %dx%d %s %s: %d frames encoded, %d system errors, %d encoding errors, %d frame errors\n", - ctx->name, - (char *)&frame->pixelformat, - frame->aligned_width, frame->aligned_height, - (char *)&stream->streamformat, - stream->width, stream->height, - stream->profile, stream->level, - ctx->encoded_frames, - ctx->sys_errors, - ctx->encode_errors, - ctx->frame_errors); -} - -/* - * V4L2 ioctl operations - */ - -static int hva_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct hva_ctx *ctx = fh_to_ctx(file->private_data); - struct hva_dev *hva = ctx_to_hdev(ctx); - - strscpy(cap->driver, HVA_NAME, sizeof(cap->driver)); - strscpy(cap->card, hva->vdev->name, sizeof(cap->card)); - snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", - hva->pdev->name); - - return 0; -} - -static int hva_enum_fmt_stream(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - struct hva_ctx *ctx = fh_to_ctx(file->private_data); - struct hva_dev *hva = ctx_to_hdev(ctx); - - if (unlikely(f->index >= hva->nb_of_streamformats)) - return -EINVAL; - - f->pixelformat = hva->streamformats[f->index]; - - return 0; -} - -static int hva_enum_fmt_frame(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - struct hva_ctx *ctx = fh_to_ctx(file->private_data); - struct hva_dev *hva = ctx_to_hdev(ctx); - - if (unlikely(f->index >= hva->nb_of_pixelformats)) - return -EINVAL; - - f->pixelformat = hva->pixelformats[f->index]; - - return 0; -} - -static int hva_g_fmt_stream(struct file *file, void *fh, struct v4l2_format *f) -{ - struct hva_ctx *ctx = fh_to_ctx(file->private_data); - struct hva_streaminfo *streaminfo = &ctx->streaminfo; - - f->fmt.pix.width = streaminfo->width; - f->fmt.pix.height = streaminfo->height; - f->fmt.pix.field = V4L2_FIELD_NONE; - f->fmt.pix.colorspace = ctx->colorspace; - f->fmt.pix.xfer_func = ctx->xfer_func; - f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; - f->fmt.pix.quantization = ctx->quantization; - f->fmt.pix.pixelformat = streaminfo->streamformat; - f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = ctx->max_stream_size; - - return 0; -} - -static int hva_g_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) -{ - struct hva_ctx *ctx = fh_to_ctx(file->private_data); - struct hva_frameinfo *frameinfo = &ctx->frameinfo; - - f->fmt.pix.width = frameinfo->width; - f->fmt.pix.height = frameinfo->height; - f->fmt.pix.field = V4L2_FIELD_NONE; - f->fmt.pix.colorspace = ctx->colorspace; - f->fmt.pix.xfer_func = ctx->xfer_func; - f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; - f->fmt.pix.quantization = ctx->quantization; - f->fmt.pix.pixelformat = frameinfo->pixelformat; - f->fmt.pix.bytesperline = frame_stride(frameinfo->aligned_width, - frameinfo->pixelformat); - f->fmt.pix.sizeimage = frameinfo->size; - - return 0; -} - -static int hva_try_fmt_stream(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct hva_ctx *ctx = fh_to_ctx(file->private_data); - struct device *dev = ctx_to_dev(ctx); - struct v4l2_pix_format *pix = &f->fmt.pix; - u32 streamformat = pix->pixelformat; - const struct hva_enc *enc; - u32 width, height; - u32 stream_size; - - enc = hva_find_encoder(ctx, ctx->frameinfo.pixelformat, streamformat); - if (!enc) { - dev_dbg(dev, - "%s V4L2 TRY_FMT (CAPTURE): unsupported format %.4s\n", - ctx->name, (char *)&pix->pixelformat); - return -EINVAL; - } - - width = pix->width; - height = pix->height; - if (ctx->flags & HVA_FLAG_FRAMEINFO) { - /* - * if the frame resolution is already fixed, only allow the - * same stream resolution - */ - pix->width = ctx->frameinfo.width; - pix->height = ctx->frameinfo.height; - if ((pix->width != width) || (pix->height != height)) - dev_dbg(dev, - "%s V4L2 TRY_FMT (CAPTURE): resolution updated %dx%d -> %dx%d to fit frame resolution\n", - ctx->name, width, height, - pix->width, pix->height); - } else { - /* adjust width & height */ - v4l_bound_align_image(&pix->width, - HVA_MIN_WIDTH, enc->max_width, - 0, - &pix->height, - HVA_MIN_HEIGHT, enc->max_height, - 0, - 0); - - if ((pix->width != width) || (pix->height != height)) - dev_dbg(dev, - "%s V4L2 TRY_FMT (CAPTURE): resolution updated %dx%d -> %dx%d to fit min/max/alignment\n", - ctx->name, width, height, - pix->width, pix->height); - } - - stream_size = estimated_stream_size(pix->width, pix->height); - if (pix->sizeimage < stream_size) - pix->sizeimage = stream_size; - - pix->bytesperline = 0; - pix->colorspace = ctx->colorspace; - pix->xfer_func = ctx->xfer_func; - pix->ycbcr_enc = ctx->ycbcr_enc; - pix->quantization = ctx->quantization; - pix->field = V4L2_FIELD_NONE; - - return 0; -} - -static int hva_try_fmt_frame(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct hva_ctx *ctx = fh_to_ctx(file->private_data); - struct device *dev = ctx_to_dev(ctx); - struct v4l2_pix_format *pix = &f->fmt.pix; - u32 pixelformat = pix->pixelformat; - const struct hva_enc *enc; - u32 width, height; - - enc = hva_find_encoder(ctx, pixelformat, ctx->streaminfo.streamformat); - if (!enc) { - dev_dbg(dev, - "%s V4L2 TRY_FMT (OUTPUT): unsupported format %.4s\n", - ctx->name, (char *)&pixelformat); - return -EINVAL; - } - - /* adjust width & height */ - width = pix->width; - height = pix->height; - v4l_bound_align_image(&pix->width, - HVA_MIN_WIDTH, HVA_MAX_WIDTH, - frame_alignment(pixelformat) - 1, - &pix->height, - HVA_MIN_HEIGHT, HVA_MAX_HEIGHT, - frame_alignment(pixelformat) - 1, - 0); - - if ((pix->width != width) || (pix->height != height)) - dev_dbg(dev, - "%s V4L2 TRY_FMT (OUTPUT): resolution updated %dx%d -> %dx%d to fit min/max/alignment\n", - ctx->name, width, height, pix->width, pix->height); - - width = ALIGN(pix->width, HVA_WIDTH_ALIGNMENT); - height = ALIGN(pix->height, HVA_HEIGHT_ALIGNMENT); - - if (!pix->colorspace) { - pix->colorspace = V4L2_COLORSPACE_REC709; - pix->xfer_func = V4L2_XFER_FUNC_DEFAULT; - pix->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; - pix->quantization = V4L2_QUANTIZATION_DEFAULT; - } - - pix->bytesperline = frame_stride(width, pixelformat); - pix->sizeimage = frame_size(width, height, pixelformat); - pix->field = V4L2_FIELD_NONE; - - return 0; -} - -static int hva_s_fmt_stream(struct file *file, void *fh, struct v4l2_format *f) -{ - struct hva_ctx *ctx = fh_to_ctx(file->private_data); - struct device *dev = ctx_to_dev(ctx); - struct vb2_queue *vq; - int ret; - - ret = hva_try_fmt_stream(file, fh, f); - if (ret) { - dev_dbg(dev, "%s V4L2 S_FMT (CAPTURE): unsupported format %.4s\n", - ctx->name, (char *)&f->fmt.pix.pixelformat); - return ret; - } - - vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); - if (vb2_is_streaming(vq)) { - dev_dbg(dev, "%s V4L2 S_FMT (CAPTURE): queue busy\n", - ctx->name); - return -EBUSY; - } - - ctx->max_stream_size = f->fmt.pix.sizeimage; - ctx->streaminfo.width = f->fmt.pix.width; - ctx->streaminfo.height = f->fmt.pix.height; - ctx->streaminfo.streamformat = f->fmt.pix.pixelformat; - ctx->flags |= HVA_FLAG_STREAMINFO; - - return 0; -} - -static int hva_s_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) -{ - struct hva_ctx *ctx = fh_to_ctx(file->private_data); - struct device *dev = ctx_to_dev(ctx); - struct v4l2_pix_format *pix = &f->fmt.pix; - struct vb2_queue *vq; - int ret; - - ret = hva_try_fmt_frame(file, fh, f); - if (ret) { - dev_dbg(dev, "%s V4L2 S_FMT (OUTPUT): unsupported format %.4s\n", - ctx->name, (char *)&pix->pixelformat); - return ret; - } - - vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); - if (vb2_is_streaming(vq)) { - dev_dbg(dev, "%s V4L2 S_FMT (OUTPUT): queue busy\n", ctx->name); - return -EBUSY; - } - - ctx->colorspace = pix->colorspace; - ctx->xfer_func = pix->xfer_func; - ctx->ycbcr_enc = pix->ycbcr_enc; - ctx->quantization = pix->quantization; - - ctx->frameinfo.aligned_width = ALIGN(pix->width, HVA_WIDTH_ALIGNMENT); - ctx->frameinfo.aligned_height = ALIGN(pix->height, - HVA_HEIGHT_ALIGNMENT); - ctx->frameinfo.size = pix->sizeimage; - ctx->frameinfo.pixelformat = pix->pixelformat; - ctx->frameinfo.width = pix->width; - ctx->frameinfo.height = pix->height; - ctx->flags |= HVA_FLAG_FRAMEINFO; - - return 0; -} - -static int hva_g_parm(struct file *file, void *fh, struct v4l2_streamparm *sp) -{ - struct hva_ctx *ctx = fh_to_ctx(file->private_data); - struct v4l2_fract *time_per_frame = &ctx->ctrls.time_per_frame; - - if (sp->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) - return -EINVAL; - - sp->parm.output.capability = V4L2_CAP_TIMEPERFRAME; - sp->parm.output.timeperframe.numerator = time_per_frame->numerator; - sp->parm.output.timeperframe.denominator = - time_per_frame->denominator; - - return 0; -} - -static int hva_s_parm(struct file *file, void *fh, struct v4l2_streamparm *sp) -{ - struct hva_ctx *ctx = fh_to_ctx(file->private_data); - struct v4l2_fract *time_per_frame = &ctx->ctrls.time_per_frame; - - if (sp->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) - return -EINVAL; - - if (!sp->parm.output.timeperframe.numerator || - !sp->parm.output.timeperframe.denominator) - return hva_g_parm(file, fh, sp); - - sp->parm.output.capability = V4L2_CAP_TIMEPERFRAME; - time_per_frame->numerator = sp->parm.output.timeperframe.numerator; - time_per_frame->denominator = - sp->parm.output.timeperframe.denominator; - - return 0; -} - -static int hva_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -{ - struct hva_ctx *ctx = fh_to_ctx(file->private_data); - struct device *dev = ctx_to_dev(ctx); - - if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - /* - * depending on the targeted compressed video format, the - * capture buffer might contain headers (e.g. H.264 SPS/PPS) - * filled in by the driver client; the size of these data is - * copied from the bytesused field of the V4L2 buffer in the - * payload field of the hva stream buffer - */ - struct vb2_queue *vq; - struct hva_stream *stream; - struct vb2_buffer *vb2_buf; - - vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, buf->type); - - if (buf->index >= vq->num_buffers) { - dev_dbg(dev, "%s buffer index %d out of range (%d)\n", - ctx->name, buf->index, vq->num_buffers); - return -EINVAL; - } - - vb2_buf = vb2_get_buffer(vq, buf->index); - stream = to_hva_stream(to_vb2_v4l2_buffer(vb2_buf)); - stream->bytesused = buf->bytesused; - } - - return v4l2_m2m_qbuf(file, ctx->fh.m2m_ctx, buf); -} - -/* V4L2 ioctl ops */ -static const struct v4l2_ioctl_ops hva_ioctl_ops = { - .vidioc_querycap = hva_querycap, - .vidioc_enum_fmt_vid_cap = hva_enum_fmt_stream, - .vidioc_enum_fmt_vid_out = hva_enum_fmt_frame, - .vidioc_g_fmt_vid_cap = hva_g_fmt_stream, - .vidioc_g_fmt_vid_out = hva_g_fmt_frame, - .vidioc_try_fmt_vid_cap = hva_try_fmt_stream, - .vidioc_try_fmt_vid_out = hva_try_fmt_frame, - .vidioc_s_fmt_vid_cap = hva_s_fmt_stream, - .vidioc_s_fmt_vid_out = hva_s_fmt_frame, - .vidioc_g_parm = hva_g_parm, - .vidioc_s_parm = hva_s_parm, - .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, - .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, - .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, - .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, - .vidioc_qbuf = hva_qbuf, - .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, - .vidioc_streamon = v4l2_m2m_ioctl_streamon, - .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -/* - * V4L2 control operations - */ - -static int hva_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct hva_ctx *ctx = container_of(ctrl->handler, struct hva_ctx, - ctrl_handler); - struct device *dev = ctx_to_dev(ctx); - - dev_dbg(dev, "%s S_CTRL: id = %d, val = %d\n", ctx->name, - ctrl->id, ctrl->val); - - switch (ctrl->id) { - case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - ctx->ctrls.bitrate_mode = ctrl->val; - break; - case V4L2_CID_MPEG_VIDEO_GOP_SIZE: - ctx->ctrls.gop_size = ctrl->val; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE: - ctx->ctrls.bitrate = ctrl->val; - break; - case V4L2_CID_MPEG_VIDEO_ASPECT: - ctx->ctrls.aspect = ctrl->val; - break; - case V4L2_CID_MPEG_VIDEO_H264_PROFILE: - ctx->ctrls.profile = ctrl->val; - snprintf(ctx->streaminfo.profile, - sizeof(ctx->streaminfo.profile), - "%s profile", - v4l2_ctrl_get_menu(ctrl->id)[ctrl->val]); - break; - case V4L2_CID_MPEG_VIDEO_H264_LEVEL: - ctx->ctrls.level = ctrl->val; - snprintf(ctx->streaminfo.level, - sizeof(ctx->streaminfo.level), - "level %s", - v4l2_ctrl_get_menu(ctrl->id)[ctrl->val]); - break; - case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: - ctx->ctrls.entropy_mode = ctrl->val; - break; - case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE: - ctx->ctrls.cpb_size = ctrl->val; - break; - case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM: - ctx->ctrls.dct8x8 = ctrl->val; - break; - case V4L2_CID_MPEG_VIDEO_H264_MIN_QP: - ctx->ctrls.qpmin = ctrl->val; - break; - case V4L2_CID_MPEG_VIDEO_H264_MAX_QP: - ctx->ctrls.qpmax = ctrl->val; - break; - case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE: - ctx->ctrls.vui_sar = ctrl->val; - break; - case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: - ctx->ctrls.vui_sar_idc = ctrl->val; - break; - case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING: - ctx->ctrls.sei_fp = ctrl->val; - break; - case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE: - ctx->ctrls.sei_fp_type = ctrl->val; - break; - default: - dev_dbg(dev, "%s S_CTRL: invalid control (id = %d)\n", - ctx->name, ctrl->id); - return -EINVAL; - } - - return 0; -} - -/* V4L2 control ops */ -static const struct v4l2_ctrl_ops hva_ctrl_ops = { - .s_ctrl = hva_s_ctrl, -}; - -static int hva_ctrls_setup(struct hva_ctx *ctx) -{ - struct device *dev = ctx_to_dev(ctx); - u64 mask; - enum v4l2_mpeg_video_h264_sei_fp_arrangement_type sei_fp_type = - V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TOP_BOTTOM; - - v4l2_ctrl_handler_init(&ctx->ctrl_handler, 15); - - v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &hva_ctrl_ops, - V4L2_CID_MPEG_VIDEO_BITRATE_MODE, - V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, - 0, - V4L2_MPEG_VIDEO_BITRATE_MODE_CBR); - - v4l2_ctrl_new_std(&ctx->ctrl_handler, &hva_ctrl_ops, - V4L2_CID_MPEG_VIDEO_GOP_SIZE, - 1, 60, 1, 16); - - v4l2_ctrl_new_std(&ctx->ctrl_handler, &hva_ctrl_ops, - V4L2_CID_MPEG_VIDEO_BITRATE, - 1000, 60000000, 1000, 20000000); - - mask = ~(1 << V4L2_MPEG_VIDEO_ASPECT_1x1); - v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &hva_ctrl_ops, - V4L2_CID_MPEG_VIDEO_ASPECT, - V4L2_MPEG_VIDEO_ASPECT_1x1, - mask, - V4L2_MPEG_VIDEO_ASPECT_1x1); - - mask = ~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | - (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | - (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) | - (1 << V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH)); - v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &hva_ctrl_ops, - V4L2_CID_MPEG_VIDEO_H264_PROFILE, - V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH, - mask, - V4L2_MPEG_VIDEO_H264_PROFILE_HIGH); - - v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &hva_ctrl_ops, - V4L2_CID_MPEG_VIDEO_H264_LEVEL, - V4L2_MPEG_VIDEO_H264_LEVEL_4_2, - 0, - V4L2_MPEG_VIDEO_H264_LEVEL_4_0); - - v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &hva_ctrl_ops, - V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE, - V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, - 0, - V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC); - - v4l2_ctrl_new_std(&ctx->ctrl_handler, &hva_ctrl_ops, - V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE, - 1, 10000, 1, 3000); - - v4l2_ctrl_new_std(&ctx->ctrl_handler, &hva_ctrl_ops, - V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM, - 0, 1, 1, 0); - - v4l2_ctrl_new_std(&ctx->ctrl_handler, &hva_ctrl_ops, - V4L2_CID_MPEG_VIDEO_H264_MIN_QP, - 0, 51, 1, 5); - - v4l2_ctrl_new_std(&ctx->ctrl_handler, &hva_ctrl_ops, - V4L2_CID_MPEG_VIDEO_H264_MAX_QP, - 0, 51, 1, 51); - - v4l2_ctrl_new_std(&ctx->ctrl_handler, &hva_ctrl_ops, - V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE, - 0, 1, 1, 1); - - mask = ~(1 << V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1); - v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &hva_ctrl_ops, - V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC, - V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1, - mask, - V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1); - - v4l2_ctrl_new_std(&ctx->ctrl_handler, &hva_ctrl_ops, - V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING, - 0, 1, 1, 0); - - mask = ~(1 << sei_fp_type); - v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &hva_ctrl_ops, - V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE, - sei_fp_type, - mask, - sei_fp_type); - - if (ctx->ctrl_handler.error) { - int err = ctx->ctrl_handler.error; - - dev_dbg(dev, "%s controls setup failed (%d)\n", - ctx->name, err); - v4l2_ctrl_handler_free(&ctx->ctrl_handler); - return err; - } - - v4l2_ctrl_handler_setup(&ctx->ctrl_handler); - - /* set default time per frame */ - ctx->ctrls.time_per_frame.numerator = HVA_DEFAULT_FRAME_NUM; - ctx->ctrls.time_per_frame.denominator = HVA_DEFAULT_FRAME_DEN; - - return 0; -} - -/* - * mem-to-mem operations - */ - -static void hva_run_work(struct work_struct *work) -{ - struct hva_ctx *ctx = container_of(work, struct hva_ctx, run_work); - struct vb2_v4l2_buffer *src_buf, *dst_buf; - const struct hva_enc *enc = ctx->enc; - struct hva_frame *frame; - struct hva_stream *stream; - int ret; - - /* protect instance against reentrancy */ - mutex_lock(&ctx->lock); - -#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS - hva_dbg_perf_begin(ctx); -#endif - - src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); - dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); - - frame = to_hva_frame(src_buf); - stream = to_hva_stream(dst_buf); - frame->vbuf.sequence = ctx->frame_num++; - - ret = enc->encode(ctx, frame, stream); - - vb2_set_plane_payload(&dst_buf->vb2_buf, 0, stream->bytesused); - if (ret) { - v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); - v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR); - } else { - /* propagate frame timestamp */ - dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp; - dst_buf->field = V4L2_FIELD_NONE; - dst_buf->sequence = ctx->stream_num - 1; - - ctx->encoded_frames++; - -#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS - hva_dbg_perf_end(ctx, stream); -#endif - - v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); - v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); - } - - mutex_unlock(&ctx->lock); - - v4l2_m2m_job_finish(ctx->hva_dev->m2m_dev, ctx->fh.m2m_ctx); -} - -static void hva_device_run(void *priv) -{ - struct hva_ctx *ctx = priv; - struct hva_dev *hva = ctx_to_hdev(ctx); - - queue_work(hva->work_queue, &ctx->run_work); -} - -static void hva_job_abort(void *priv) -{ - struct hva_ctx *ctx = priv; - struct device *dev = ctx_to_dev(ctx); - - dev_dbg(dev, "%s aborting job\n", ctx->name); - - ctx->aborting = true; -} - -static int hva_job_ready(void *priv) -{ - struct hva_ctx *ctx = priv; - struct device *dev = ctx_to_dev(ctx); - - if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx)) { - dev_dbg(dev, "%s job not ready: no frame buffers\n", - ctx->name); - return 0; - } - - if (!v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx)) { - dev_dbg(dev, "%s job not ready: no stream buffers\n", - ctx->name); - return 0; - } - - if (ctx->aborting) { - dev_dbg(dev, "%s job not ready: aborting\n", ctx->name); - return 0; - } - - return 1; -} - -/* mem-to-mem ops */ -static const struct v4l2_m2m_ops hva_m2m_ops = { - .device_run = hva_device_run, - .job_abort = hva_job_abort, - .job_ready = hva_job_ready, -}; - -/* - * VB2 queue operations - */ - -static int hva_queue_setup(struct vb2_queue *vq, - unsigned int *num_buffers, unsigned int *num_planes, - unsigned int sizes[], struct device *alloc_devs[]) -{ - struct hva_ctx *ctx = vb2_get_drv_priv(vq); - struct device *dev = ctx_to_dev(ctx); - unsigned int size; - - dev_dbg(dev, "%s %s queue setup: num_buffers %d\n", ctx->name, - to_type_str(vq->type), *num_buffers); - - size = vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT ? - ctx->frameinfo.size : ctx->max_stream_size; - - if (*num_planes) - return sizes[0] < size ? -EINVAL : 0; - - /* only one plane supported */ - *num_planes = 1; - sizes[0] = size; - - return 0; -} - -static int hva_buf_prepare(struct vb2_buffer *vb) -{ - struct hva_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - struct device *dev = ctx_to_dev(ctx); - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - - if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { - struct hva_frame *frame = to_hva_frame(vbuf); - - if (vbuf->field == V4L2_FIELD_ANY) - vbuf->field = V4L2_FIELD_NONE; - if (vbuf->field != V4L2_FIELD_NONE) { - dev_dbg(dev, - "%s frame[%d] prepare: %d field not supported\n", - ctx->name, vb->index, vbuf->field); - return -EINVAL; - } - - if (!frame->prepared) { - /* get memory addresses */ - frame->vaddr = vb2_plane_vaddr(&vbuf->vb2_buf, 0); - frame->paddr = vb2_dma_contig_plane_dma_addr( - &vbuf->vb2_buf, 0); - frame->info = ctx->frameinfo; - frame->prepared = true; - - dev_dbg(dev, - "%s frame[%d] prepared; virt=%p, phy=%pad\n", - ctx->name, vb->index, - frame->vaddr, &frame->paddr); - } - } else { - struct hva_stream *stream = to_hva_stream(vbuf); - - if (!stream->prepared) { - /* get memory addresses */ - stream->vaddr = vb2_plane_vaddr(&vbuf->vb2_buf, 0); - stream->paddr = vb2_dma_contig_plane_dma_addr( - &vbuf->vb2_buf, 0); - stream->size = vb2_plane_size(&vbuf->vb2_buf, 0); - stream->prepared = true; - - dev_dbg(dev, - "%s stream[%d] prepared; virt=%p, phy=%pad\n", - ctx->name, vb->index, - stream->vaddr, &stream->paddr); - } - } - - return 0; -} - -static void hva_buf_queue(struct vb2_buffer *vb) -{ - struct hva_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - - if (ctx->fh.m2m_ctx) - v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); -} - -static int hva_start_streaming(struct vb2_queue *vq, unsigned int count) -{ - struct hva_ctx *ctx = vb2_get_drv_priv(vq); - struct hva_dev *hva = ctx_to_hdev(ctx); - struct device *dev = ctx_to_dev(ctx); - struct vb2_v4l2_buffer *vbuf; - int ret; - unsigned int i; - bool found = false; - - dev_dbg(dev, "%s %s start streaming\n", ctx->name, - to_type_str(vq->type)); - - /* open encoder when both start_streaming have been called */ - if (V4L2_TYPE_IS_OUTPUT(vq->type)) { - if (!vb2_start_streaming_called(&ctx->fh.m2m_ctx->cap_q_ctx.q)) - return 0; - } else { - if (!vb2_start_streaming_called(&ctx->fh.m2m_ctx->out_q_ctx.q)) - return 0; - } - - /* store the instance context in the instances array */ - for (i = 0; i < HVA_MAX_INSTANCES; i++) { - if (!hva->instances[i]) { - hva->instances[i] = ctx; - /* save the context identifier in the context */ - ctx->id = i; - found = true; - break; - } - } - - if (!found) { - dev_err(dev, "%s maximum instances reached\n", ctx->name); - ret = -ENOMEM; - goto err; - } - - hva->nb_of_instances++; - - if (!ctx->enc) { - ret = hva_open_encoder(ctx, - ctx->streaminfo.streamformat, - ctx->frameinfo.pixelformat, - &ctx->enc); - if (ret < 0) - goto err_ctx; - } - - return 0; - -err_ctx: - hva->instances[ctx->id] = NULL; - hva->nb_of_instances--; -err: - if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { - /* return of all pending buffers to vb2 (in queued state) */ - while ((vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx))) - v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_QUEUED); - } else { - /* return of all pending buffers to vb2 (in queued state) */ - while ((vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx))) - v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_QUEUED); - } - - ctx->sys_errors++; - - return ret; -} - -static void hva_stop_streaming(struct vb2_queue *vq) -{ - struct hva_ctx *ctx = vb2_get_drv_priv(vq); - struct hva_dev *hva = ctx_to_hdev(ctx); - struct device *dev = ctx_to_dev(ctx); - const struct hva_enc *enc = ctx->enc; - struct vb2_v4l2_buffer *vbuf; - - dev_dbg(dev, "%s %s stop streaming\n", ctx->name, - to_type_str(vq->type)); - - if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { - /* return of all pending buffers to vb2 (in error state) */ - ctx->frame_num = 0; - while ((vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx))) - v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); - } else { - /* return of all pending buffers to vb2 (in error state) */ - ctx->stream_num = 0; - while ((vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx))) - v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); - } - - if ((V4L2_TYPE_IS_OUTPUT(vq->type) && - vb2_is_streaming(&ctx->fh.m2m_ctx->cap_q_ctx.q)) || - (V4L2_TYPE_IS_CAPTURE(vq->type) && - vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q))) { - dev_dbg(dev, "%s %s out=%d cap=%d\n", - ctx->name, to_type_str(vq->type), - vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q), - vb2_is_streaming(&ctx->fh.m2m_ctx->cap_q_ctx.q)); - return; - } - - /* close encoder when both stop_streaming have been called */ - if (enc) { - dev_dbg(dev, "%s %s encoder closed\n", ctx->name, enc->name); - enc->close(ctx); - ctx->enc = NULL; - - /* clear instance context in instances array */ - hva->instances[ctx->id] = NULL; - hva->nb_of_instances--; - } - - ctx->aborting = false; -} - -/* VB2 queue ops */ -static const struct vb2_ops hva_qops = { - .queue_setup = hva_queue_setup, - .buf_prepare = hva_buf_prepare, - .buf_queue = hva_buf_queue, - .start_streaming = hva_start_streaming, - .stop_streaming = hva_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, -}; - -/* - * V4L2 file operations - */ - -static int queue_init(struct hva_ctx *ctx, struct vb2_queue *vq) -{ - vq->io_modes = VB2_MMAP | VB2_DMABUF; - vq->drv_priv = ctx; - vq->ops = &hva_qops; - vq->mem_ops = &vb2_dma_contig_memops; - vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; - vq->lock = &ctx->hva_dev->lock; - - return vb2_queue_init(vq); -} - -static int hva_queue_init(void *priv, struct vb2_queue *src_vq, - struct vb2_queue *dst_vq) -{ - struct hva_ctx *ctx = priv; - int ret; - - src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - src_vq->buf_struct_size = sizeof(struct hva_frame); - src_vq->min_buffers_needed = MIN_FRAMES; - src_vq->dev = ctx->hva_dev->dev; - - ret = queue_init(ctx, src_vq); - if (ret) - return ret; - - dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - dst_vq->buf_struct_size = sizeof(struct hva_stream); - dst_vq->min_buffers_needed = MIN_STREAMS; - dst_vq->dev = ctx->hva_dev->dev; - - return queue_init(ctx, dst_vq); -} - -static int hva_open(struct file *file) -{ - struct hva_dev *hva = video_drvdata(file); - struct device *dev = hva_to_dev(hva); - struct hva_ctx *ctx; - int ret; - - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (!ctx) { - ret = -ENOMEM; - goto out; - } - ctx->hva_dev = hva; - - INIT_WORK(&ctx->run_work, hva_run_work); - v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); - - ret = hva_ctrls_setup(ctx); - if (ret) { - dev_err(dev, "%s [x:x] failed to setup controls\n", - HVA_PREFIX); - ctx->sys_errors++; - goto err_fh; - } - ctx->fh.ctrl_handler = &ctx->ctrl_handler; - - mutex_init(&ctx->lock); - - ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(hva->m2m_dev, ctx, - &hva_queue_init); - if (IS_ERR(ctx->fh.m2m_ctx)) { - ret = PTR_ERR(ctx->fh.m2m_ctx); - dev_err(dev, "%s failed to initialize m2m context (%d)\n", - HVA_PREFIX, ret); - ctx->sys_errors++; - goto err_ctrls; - } - - /* set the instance name */ - mutex_lock(&hva->lock); - hva->instance_id++; - snprintf(ctx->name, sizeof(ctx->name), "[%3d:----]", - hva->instance_id); - mutex_unlock(&hva->lock); - - /* default parameters for frame and stream */ - set_default_params(ctx); - -#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS - hva_dbg_ctx_create(ctx); -#endif - - dev_info(dev, "%s encoder instance created\n", ctx->name); - - return 0; - -err_ctrls: - v4l2_ctrl_handler_free(&ctx->ctrl_handler); -err_fh: - v4l2_fh_del(&ctx->fh); - v4l2_fh_exit(&ctx->fh); - kfree(ctx); -out: - return ret; -} - -static int hva_release(struct file *file) -{ - struct hva_ctx *ctx = fh_to_ctx(file->private_data); - struct hva_dev *hva = ctx_to_hdev(ctx); - struct device *dev = ctx_to_dev(ctx); - const struct hva_enc *enc = ctx->enc; - - if (enc) { - dev_dbg(dev, "%s %s encoder closed\n", ctx->name, enc->name); - enc->close(ctx); - ctx->enc = NULL; - - /* clear instance context in instances array */ - hva->instances[ctx->id] = NULL; - hva->nb_of_instances--; - } - - /* trace a summary of instance before closing (debug purpose) */ - hva_dbg_summary(ctx); - - v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); - - v4l2_ctrl_handler_free(&ctx->ctrl_handler); - - v4l2_fh_del(&ctx->fh); - v4l2_fh_exit(&ctx->fh); - -#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS - hva_dbg_ctx_remove(ctx); -#endif - - dev_info(dev, "%s encoder instance released\n", ctx->name); - - kfree(ctx); - - return 0; -} - -/* V4L2 file ops */ -static const struct v4l2_file_operations hva_fops = { - .owner = THIS_MODULE, - .open = hva_open, - .release = hva_release, - .unlocked_ioctl = video_ioctl2, - .mmap = v4l2_m2m_fop_mmap, - .poll = v4l2_m2m_fop_poll, -}; - -/* - * Platform device operations - */ - -static int hva_register_device(struct hva_dev *hva) -{ - int ret; - struct video_device *vdev; - struct device *dev; - - if (!hva) - return -ENODEV; - dev = hva_to_dev(hva); - - hva->m2m_dev = v4l2_m2m_init(&hva_m2m_ops); - if (IS_ERR(hva->m2m_dev)) { - dev_err(dev, "%s failed to initialize v4l2-m2m device\n", - HVA_PREFIX); - ret = PTR_ERR(hva->m2m_dev); - goto err; - } - - vdev = video_device_alloc(); - if (!vdev) { - dev_err(dev, "%s failed to allocate video device\n", - HVA_PREFIX); - ret = -ENOMEM; - goto err_m2m_release; - } - - vdev->fops = &hva_fops; - vdev->ioctl_ops = &hva_ioctl_ops; - vdev->release = video_device_release; - vdev->lock = &hva->lock; - vdev->vfl_dir = VFL_DIR_M2M; - vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M; - vdev->v4l2_dev = &hva->v4l2_dev; - snprintf(vdev->name, sizeof(vdev->name), "%s%lx", HVA_NAME, - hva->ip_version); - - ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); - if (ret) { - dev_err(dev, "%s failed to register video device\n", - HVA_PREFIX); - goto err_vdev_release; - } - - hva->vdev = vdev; - video_set_drvdata(vdev, hva); - return 0; - -err_vdev_release: - video_device_release(vdev); -err_m2m_release: - v4l2_m2m_release(hva->m2m_dev); -err: - return ret; -} - -static void hva_unregister_device(struct hva_dev *hva) -{ - if (!hva) - return; - - if (hva->m2m_dev) - v4l2_m2m_release(hva->m2m_dev); - - video_unregister_device(hva->vdev); -} - -static int hva_probe(struct platform_device *pdev) -{ - struct hva_dev *hva; - struct device *dev = &pdev->dev; - int ret; - - hva = devm_kzalloc(dev, sizeof(*hva), GFP_KERNEL); - if (!hva) { - ret = -ENOMEM; - goto err; - } - - ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); - if (ret) - return ret; - - hva->dev = dev; - hva->pdev = pdev; - platform_set_drvdata(pdev, hva); - - mutex_init(&hva->lock); - - /* probe hardware */ - ret = hva_hw_probe(pdev, hva); - if (ret) - goto err; - - /* register all available encoders */ - register_encoders(hva); - - /* register all supported formats */ - register_formats(hva); - - /* register on V4L2 */ - ret = v4l2_device_register(dev, &hva->v4l2_dev); - if (ret) { - dev_err(dev, "%s %s failed to register V4L2 device\n", - HVA_PREFIX, HVA_NAME); - goto err_hw; - } - -#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS - hva_debugfs_create(hva); -#endif - - hva->work_queue = create_workqueue(HVA_NAME); - if (!hva->work_queue) { - dev_err(dev, "%s %s failed to allocate work queue\n", - HVA_PREFIX, HVA_NAME); - ret = -ENOMEM; - goto err_v4l2; - } - - /* register device */ - ret = hva_register_device(hva); - if (ret) - goto err_work_queue; - - dev_info(dev, "%s %s registered as /dev/video%d\n", HVA_PREFIX, - HVA_NAME, hva->vdev->num); - - return 0; - -err_work_queue: - destroy_workqueue(hva->work_queue); -err_v4l2: -#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS - hva_debugfs_remove(hva); -#endif - v4l2_device_unregister(&hva->v4l2_dev); -err_hw: - hva_hw_remove(hva); -err: - return ret; -} - -static int hva_remove(struct platform_device *pdev) -{ - struct hva_dev *hva = platform_get_drvdata(pdev); - struct device *dev = hva_to_dev(hva); - - hva_unregister_device(hva); - - destroy_workqueue(hva->work_queue); - - hva_hw_remove(hva); - -#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS - hva_debugfs_remove(hva); -#endif - - v4l2_device_unregister(&hva->v4l2_dev); - - dev_info(dev, "%s %s removed\n", HVA_PREFIX, pdev->name); - - return 0; -} - -/* PM ops */ -static const struct dev_pm_ops hva_pm_ops = { - .runtime_suspend = hva_hw_runtime_suspend, - .runtime_resume = hva_hw_runtime_resume, -}; - -static const struct of_device_id hva_match_types[] = { - { - .compatible = "st,st-hva", - }, - { /* end node */ } -}; - -MODULE_DEVICE_TABLE(of, hva_match_types); - -static struct platform_driver hva_driver = { - .probe = hva_probe, - .remove = hva_remove, - .driver = { - .name = HVA_NAME, - .of_match_table = hva_match_types, - .pm = &hva_pm_ops, - }, -}; - -module_platform_driver(hva_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>"); -MODULE_DESCRIPTION("STMicroelectronics HVA video encoder V4L2 driver"); diff --git a/drivers/media/platform/sti/hva/hva.h b/drivers/media/platform/sti/hva/hva.h deleted file mode 100644 index ba6b893416ec..000000000000 --- a/drivers/media/platform/sti/hva/hva.h +++ /dev/null @@ -1,409 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) STMicroelectronics SA 2015 - * Authors: Yannick Fertre <yannick.fertre@st.com> - * Hugues Fruchet <hugues.fruchet@st.com> - */ - -#ifndef HVA_H -#define HVA_H - -#include <media/v4l2-ctrls.h> -#include <media/v4l2-device.h> -#include <media/videobuf2-v4l2.h> -#include <media/v4l2-mem2mem.h> - -#define fh_to_ctx(f) (container_of(f, struct hva_ctx, fh)) - -#define hva_to_dev(h) (h->dev) - -#define ctx_to_dev(c) (c->hva_dev->dev) - -#define ctx_to_hdev(c) (c->hva_dev) - -#define HVA_NAME "st-hva" -#define HVA_PREFIX "[---:----]" - -extern const struct hva_enc nv12h264enc; -extern const struct hva_enc nv21h264enc; - -/** - * struct hva_frameinfo - information about hva frame - * - * @pixelformat: fourcc code for uncompressed video format - * @width: width of frame - * @height: height of frame - * @aligned_width: width of frame (with encoder alignment constraint) - * @aligned_height: height of frame (with encoder alignment constraint) - * @size: maximum size in bytes required for data -*/ -struct hva_frameinfo { - u32 pixelformat; - u32 width; - u32 height; - u32 aligned_width; - u32 aligned_height; - u32 size; -}; - -/** - * struct hva_streaminfo - information about hva stream - * - * @streamformat: fourcc code of compressed video format (H.264...) - * @width: width of stream - * @height: height of stream - * @profile: profile string - * @level: level string - */ -struct hva_streaminfo { - u32 streamformat; - u32 width; - u32 height; - u8 profile[32]; - u8 level[32]; -}; - -/** - * struct hva_controls - hva controls set - * - * @time_per_frame: time per frame in seconds - * @bitrate_mode: bitrate mode (constant bitrate or variable bitrate) - * @gop_size: groupe of picture size - * @bitrate: bitrate (in bps) - * @aspect: video aspect - * @profile: H.264 profile - * @level: H.264 level - * @entropy_mode: H.264 entropy mode (CABAC or CVLC) - * @cpb_size: coded picture buffer size (in kB) - * @dct8x8: transform mode 8x8 enable - * @qpmin: minimum quantizer - * @qpmax: maximum quantizer - * @vui_sar: pixel aspect ratio enable - * @vui_sar_idc: pixel aspect ratio identifier - * @sei_fp: sei frame packing arrangement enable - * @sei_fp_type: sei frame packing arrangement type - */ -struct hva_controls { - struct v4l2_fract time_per_frame; - enum v4l2_mpeg_video_bitrate_mode bitrate_mode; - u32 gop_size; - u32 bitrate; - enum v4l2_mpeg_video_aspect aspect; - enum v4l2_mpeg_video_h264_profile profile; - enum v4l2_mpeg_video_h264_level level; - enum v4l2_mpeg_video_h264_entropy_mode entropy_mode; - u32 cpb_size; - bool dct8x8; - u32 qpmin; - u32 qpmax; - bool vui_sar; - enum v4l2_mpeg_video_h264_vui_sar_idc vui_sar_idc; - bool sei_fp; - enum v4l2_mpeg_video_h264_sei_fp_arrangement_type sei_fp_type; -}; - -/** - * struct hva_frame - hva frame buffer (output) - * - * @vbuf: video buffer information for V4L2 - * @list: V4L2 m2m list that the frame belongs to - * @info: frame information (width, height, format, alignment...) - * @paddr: physical address (for hardware) - * @vaddr: virtual address (kernel can read/write) - * @prepared: true if vaddr/paddr are resolved - */ -struct hva_frame { - struct vb2_v4l2_buffer vbuf; - struct list_head list; - struct hva_frameinfo info; - dma_addr_t paddr; - void *vaddr; - bool prepared; -}; - -/* - * to_hva_frame() - cast struct vb2_v4l2_buffer * to struct hva_frame * - */ -#define to_hva_frame(vb) \ - container_of(vb, struct hva_frame, vbuf) - -/** - * struct hva_stream - hva stream buffer (capture) - * - * @vbuf: video buffer information for V4L2 - * @list: V4L2 m2m list that the frame belongs to - * @paddr: physical address (for hardware) - * @vaddr: virtual address (kernel can read/write) - * @prepared: true if vaddr/paddr are resolved - * @size: size of the buffer in bytes - * @bytesused: number of bytes occupied by data in the buffer - */ -struct hva_stream { - struct vb2_v4l2_buffer vbuf; - struct list_head list; - dma_addr_t paddr; - void *vaddr; - bool prepared; - unsigned int size; - unsigned int bytesused; -}; - -/* - * to_hva_stream() - cast struct vb2_v4l2_buffer * to struct hva_stream * - */ -#define to_hva_stream(vb) \ - container_of(vb, struct hva_stream, vbuf) - -#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS -/** - * struct hva_ctx_dbg - instance context debug info - * - * @debugfs_entry: debugfs entry - * @is_valid_period: true if the sequence is valid for performance - * @begin: start time of last HW task - * @total_duration: total HW processing durations in 0.1ms - * @cnt_duration: number of HW processings - * @min_duration: minimum HW processing duration in 0.1ms - * @max_duration: maximum HW processing duration in 0.1ms - * @avg_duration: average HW processing duration in 0.1ms - * @max_fps: maximum frames encoded per second (in 0.1Hz) - * @total_period: total encoding periods in 0.1ms - * @cnt_period: number of periods - * @min_period: minimum encoding period in 0.1ms - * @max_period: maximum encoding period in 0.1ms - * @avg_period: average encoding period in 0.1ms - * @total_stream_size: total number of encoded bytes - * @avg_fps: average frames encoded per second (in 0.1Hz) - * @window_duration: duration of the sampling window in 0.1ms - * @cnt_window: number of samples in the window - * @window_stream_size: number of encoded bytes upon the sampling window - * @last_bitrate: bitrate upon the last sampling window - * @min_bitrate: minimum bitrate in kbps - * @max_bitrate: maximum bitrate in kbps - * @avg_bitrate: average bitrate in kbps - */ -struct hva_ctx_dbg { - struct dentry *debugfs_entry; - bool is_valid_period; - ktime_t begin; - u32 total_duration; - u32 cnt_duration; - u32 min_duration; - u32 max_duration; - u32 avg_duration; - u32 max_fps; - u32 total_period; - u32 cnt_period; - u32 min_period; - u32 max_period; - u32 avg_period; - u32 total_stream_size; - u32 avg_fps; - u32 window_duration; - u32 cnt_window; - u32 window_stream_size; - u32 last_bitrate; - u32 min_bitrate; - u32 max_bitrate; - u32 avg_bitrate; -}; -#endif - -struct hva_dev; -struct hva_enc; - -/** - * struct hva_ctx - context of hva instance - * - * @hva_dev: the device that this instance is associated with - * @fh: V4L2 file handle - * @ctrl_handler: V4L2 controls handler - * @ctrls: hva controls set - * @id: instance identifier - * @aborting: true if current job aborted - * @name: instance name (debug purpose) - * @run_work: encode work - * @lock: mutex used to lock access of this context - * @flags: validity of streaminfo and frameinfo fields - * @frame_num: frame number - * @stream_num: stream number - * @max_stream_size: maximum size in bytes required for stream data - * @colorspace: colorspace identifier - * @xfer_func: transfer function identifier - * @ycbcr_enc: Y'CbCr encoding identifier - * @quantization: quantization identifier - * @streaminfo: stream properties - * @frameinfo: frame properties - * @enc: current encoder - * @priv: private codec data for this instance, allocated - * by encoder @open time - * @hw_err: true if hardware error detected - * @encoded_frames: number of encoded frames - * @sys_errors: number of system errors (memory, resource, pm...) - * @encode_errors: number of encoding errors (hw/driver errors) - * @frame_errors: number of frame errors (format, size, header...) - * @dbg: context debug info - */ -struct hva_ctx { - struct hva_dev *hva_dev; - struct v4l2_fh fh; - struct v4l2_ctrl_handler ctrl_handler; - struct hva_controls ctrls; - u8 id; - bool aborting; - char name[100]; - struct work_struct run_work; - /* mutex protecting this data structure */ - struct mutex lock; - u32 flags; - u32 frame_num; - u32 stream_num; - u32 max_stream_size; - enum v4l2_colorspace colorspace; - enum v4l2_xfer_func xfer_func; - enum v4l2_ycbcr_encoding ycbcr_enc; - enum v4l2_quantization quantization; - struct hva_streaminfo streaminfo; - struct hva_frameinfo frameinfo; - struct hva_enc *enc; - void *priv; - bool hw_err; - u32 encoded_frames; - u32 sys_errors; - u32 encode_errors; - u32 frame_errors; -#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS - struct hva_ctx_dbg dbg; -#endif -}; - -#define HVA_FLAG_STREAMINFO 0x0001 -#define HVA_FLAG_FRAMEINFO 0x0002 - -#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS -/** - * struct hva_dev_dbg - device debug info - * - * @debugfs_entry: debugfs entry - * @last_ctx: debug information about last running instance context - */ -struct hva_dev_dbg { - struct dentry *debugfs_entry; - struct hva_ctx last_ctx; -}; -#endif - -#define HVA_MAX_INSTANCES 16 -#define HVA_MAX_ENCODERS 10 -#define HVA_MAX_FORMATS HVA_MAX_ENCODERS - -/** - * struct hva_dev - abstraction for hva entity - * - * @v4l2_dev: V4L2 device - * @vdev: video device - * @pdev: platform device - * @dev: device - * @lock: mutex used for critical sections & V4L2 ops - * serialization - * @m2m_dev: memory-to-memory V4L2 device information - * @instances: opened instances - * @nb_of_instances: number of opened instances - * @instance_id: rolling counter identifying an instance (debug purpose) - * @regs: register io memory access - * @esram_addr: esram address - * @esram_size: esram size - * @clk: hva clock - * @irq_its: status interruption - * @irq_err: error interruption - * @work_queue: work queue to handle the encode jobs - * @protect_mutex: mutex used to lock access of hardware - * @interrupt: completion interrupt - * @ip_version: IP hardware version - * @encoders: registered encoders - * @nb_of_encoders: number of registered encoders - * @pixelformats: supported uncompressed video formats - * @nb_of_pixelformats: number of supported umcompressed video formats - * @streamformats: supported compressed video formats - * @nb_of_streamformats: number of supported compressed video formats - * @sfl_reg: status fifo level register value - * @sts_reg: status register value - * @lmi_err_reg: local memory interface error register value - * @emi_err_reg: external memory interface error register value - * @hec_mif_err_reg: HEC memory interface error register value - * @dbg: device debug info - */ -struct hva_dev { - struct v4l2_device v4l2_dev; - struct video_device *vdev; - struct platform_device *pdev; - struct device *dev; - /* mutex protecting vb2_queue structure */ - struct mutex lock; - struct v4l2_m2m_dev *m2m_dev; - struct hva_ctx *instances[HVA_MAX_INSTANCES]; - unsigned int nb_of_instances; - unsigned int instance_id; - void __iomem *regs; - u32 esram_addr; - u32 esram_size; - struct clk *clk; - int irq_its; - int irq_err; - struct workqueue_struct *work_queue; - /* mutex protecting hardware access */ - struct mutex protect_mutex; - struct completion interrupt; - unsigned long int ip_version; - const struct hva_enc *encoders[HVA_MAX_ENCODERS]; - u32 nb_of_encoders; - u32 pixelformats[HVA_MAX_FORMATS]; - u32 nb_of_pixelformats; - u32 streamformats[HVA_MAX_FORMATS]; - u32 nb_of_streamformats; - u32 sfl_reg; - u32 sts_reg; - u32 lmi_err_reg; - u32 emi_err_reg; - u32 hec_mif_err_reg; -#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS - struct hva_dev_dbg dbg; -#endif -}; - -/** - * struct hva_enc - hva encoder - * - * @name: encoder name - * @streamformat: fourcc code for compressed video format (H.264...) - * @pixelformat: fourcc code for uncompressed video format - * @max_width: maximum width of frame for this encoder - * @max_height: maximum height of frame for this encoder - * @open: open encoder - * @close: close encoder - * @encode: encode a frame (struct hva_frame) in a stream - * (struct hva_stream) - */ - -struct hva_enc { - const char *name; - u32 streamformat; - u32 pixelformat; - u32 max_width; - u32 max_height; - int (*open)(struct hva_ctx *ctx); - int (*close)(struct hva_ctx *ctx); - int (*encode)(struct hva_ctx *ctx, struct hva_frame *frame, - struct hva_stream *stream); -}; - -#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS -void hva_debugfs_create(struct hva_dev *hva); -void hva_debugfs_remove(struct hva_dev *hva); -void hva_dbg_ctx_create(struct hva_ctx *ctx); -void hva_dbg_ctx_remove(struct hva_ctx *ctx); -void hva_dbg_perf_begin(struct hva_ctx *ctx); -void hva_dbg_perf_end(struct hva_ctx *ctx, struct hva_stream *stream); -#endif - -#endif /* HVA_H */ |